:root {
  --bg: #0f1115; --panel: #171a21; --panel-2: #1f232c; --border: #2a2f3a;
  --text: #e6e6e6; --muted: #8b93a3; --accent: #d9a441; --accent-2: #4f8cff; --danger: #e05656;
  --player: #2b3a55; --npc: #2a2d36; --narr: #1c2a24;
  --topbar: 60px; /* 頂列固定高度；前台與後台的主區塊用 100vh 減掉它，整頁才不會多出捲軸 */
}
* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--text); font: 15px/1.55 system-ui, -apple-system, "PingFang TC", "Noto Sans TC", sans-serif; }
a { color: var(--accent-2); }
button { background: var(--accent); color: #111; border: 0; border-radius: 6px; padding: 8px 14px; font: inherit; cursor: pointer; white-space: nowrap; }
button.secondary { background: var(--panel-2); color: var(--text); border: 1px solid var(--border); }
button.danger { background: var(--danger); color: #fff; }
button:disabled { opacity: .5; cursor: default; }
input, textarea, select { width: 100%; background: var(--panel-2); color: var(--text); border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; font: inherit; }
textarea { min-height: 80px; resize: vertical; }
label { display: block; font-size: 13px; color: var(--muted); margin: 10px 0 4px; }
.muted { color: var(--muted); font-size: 13px; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 14px; }
h1, h2, h3 { margin: 0 0 10px; font-weight: 600; }
h1 { font-size: 20px; } h2 { font-size: 17px; } h3 { font-size: 15px; }
.topbar { display: flex; justify-content: space-between; align-items: center; height: var(--topbar); padding: 0 16px; border-bottom: 1px solid var(--border); background: var(--panel); }
.topbar .brand { font-weight: 700; color: var(--accent); letter-spacing: .5px; }

/* ---------- play ---------- */
.play { display: grid; grid-template-columns: 1fr 300px; height: calc(100vh - var(--topbar)); }
/* min-height: 0 讓對話區在自己的框裡捲動；否則整頁會跟著對話變長，輸入框被推出畫面 */
.stage { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* 插圖上方：故事名、這場故事的標題、目前的章節 */
.story-head { flex: none; display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; padding: 8px 16px; border-bottom: 1px solid var(--border); background: var(--panel); }
.story-head .title { font-weight: 600; font-size: 16px; }
.story-head .chapter { margin-left: auto; color: var(--accent); font-size: 13px; letter-spacing: .5px; }
.scene { flex: none; position: relative; background: #000; aspect-ratio: 16/6; max-height: 38vh; overflow: hidden; border-bottom: 1px solid var(--border); }
.scene img { width: 100%; height: 100%; object-fit: cover; display: block; }
.scene .caption { position: absolute; left: 0; right: 0; bottom: 0; padding: 10px 16px; background: linear-gradient(transparent, rgba(0,0,0,.85)); font-size: 13px; color: #ddd; }
.scene .caption #scene-place { color: var(--accent); font-weight: 600; }
/* 場景圖在背景重畫：舊圖先留著、稍微壓暗，右上角掛個標記；新圖到了就換 */
.scene img.drawing { filter: brightness(.75); transition: filter .4s; }
.scene .drawing-badge { position: absolute; top: 10px; right: 12px; padding: 3px 10px; border-radius: 999px; background: rgba(0,0,0,.6); color: #eee; font-size: 12px; }
.scene .drawing-badge.hidden { display: none; }
/* 訊息旁的小相機：補拍那一回合 */
.msg .photo-btn { border: none; background: none; cursor: pointer; font-size: 12px; opacity: .45; padding: 0 2px; }
.msg .photo-btn:hover { opacity: 1; }
.msg .photo-btn:disabled { opacity: .2; cursor: default; }
/* 編輯器裡的空間照縮圖 */
.plate-box { margin: 4px 0 8px; }
.plate-box img.plate { max-width: 320px; width: 100%; border-radius: 6px; display: block; }
.log { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.msg { max-width: 78%; padding: 10px 14px; border-radius: 12px; white-space: pre-wrap; word-break: break-word; }
.msg .who { font-size: 12px; color: var(--accent); margin-bottom: 3px; }
/* 玩家與 NPC 的訊息是「頭像 + 泡泡」一列，底色在泡泡上；旁白與系統訊息沒有頭像。 */
.msg.player, .msg.npc { display: flex; align-items: flex-start; gap: 10px; padding: 0; border-radius: 0; }
.msg.player { align-self: flex-end; flex-direction: row-reverse; }
.msg.player .who, .msg.player .avatar { color: #9fbfff; }
.msg.npc { align-self: flex-start; }
.msg .bubble { min-width: 0; padding: 10px 14px; border-radius: 12px; }
.msg.player .bubble { background: var(--player); }
.msg.npc .bubble { background: var(--npc); }
.msg.narration { align-self: center; background: var(--narr); color: #b9d4c4; font-style: italic; font-size: 14px; max-width: 90%; }
.msg.system { align-self: center; background: transparent; color: var(--muted); font-size: 12px; padding: 2px 8px; }
/* 導演模式：指示本身、被監製擋下的說明、切到導演模式時的輸入框 */
.msg.direction { align-self: center; max-width: 90%; background: transparent; border: 1px dashed #7a5d20; color: var(--accent); font-size: 13px; }
/* 邊玩邊標記（DESIGN.md 4.21）：只有自己看得到的記號，不是劇情 */
.msg.mark { align-self: center; max-width: 90%; background: transparent; border: 1px dashed var(--border); color: var(--muted); font-size: 12px; }
.msg .mark-del { background: none; border: 0; color: var(--muted); padding: 0 0 0 8px; font-size: 11px; line-height: 1; opacity: .55; }
.msg .mark-del:hover { color: var(--danger); opacity: 1; }
.msg .mark-btn { background: none; border: 0; color: var(--muted); padding: 0 0 0 6px; font-size: 11px; line-height: 1; opacity: 0; }
.msg:hover .mark-btn { opacity: .55; }
.msg .mark-btn:hover { opacity: 1; }
.msg.system.rejected { max-width: 90%; color: var(--danger); font-size: 13px; }
.msg.system.warning { max-width: 90%; color: var(--accent); font-size: 13px; white-space: pre-wrap; }
.place .clock { margin-top: 4px; }
.composer #btn-director { padding: 8px 12px; }
.composer #btn-director.on { background: var(--accent); border-color: var(--accent); color: #111; }
.composer.director textarea { border-color: var(--accent); }
/* 章節劇本：換章的提示；推進故事的按鈕 */
.msg.system.chapter { color: var(--accent); font-size: 13px; letter-spacing: 1px; }
.composer #btn-advance { padding: 8px 12px; }
/* 地點標記：放在同一個空間那段對話的最上方（對話由新到舊排列） */
.loc-mark { display: flex; align-items: center; gap: 8px; color: var(--accent); font-size: 12px; white-space: nowrap; }
.loc-mark::before, .loc-mark::after { content: ""; flex: 1; border-top: 1px solid var(--border); }
.log .more { align-self: center; font-size: 12px; padding: 4px 14px; }
.msg.typing .body::after { content: "▍"; animation: blink 1s infinite; }
.msg .voice-btn { background: none; border: 0; color: var(--muted); padding: 0 0 0 8px; font-size: 11px; line-height: 1; }
.msg .voice-btn:hover, .msg.speaking .voice-btn { color: var(--accent); }
/* 退回時間點：平時淡淡的，滑過去才變紅，免得誤按 */
/* 對話上的回合數：開場、第 N 回合 */
.msg .turn-tag { color: var(--muted); font-size: 11px; opacity: .8; }
.msg .who .turn-tag { margin-left: 6px; }
.msg.narration .turn-tag, .msg.direction .turn-tag, .msg.illustration .turn-tag { margin-right: 6px; }
/* 全劇播放的起點（頂列）：直接填第幾回合 */
.topbar .turn-pick-box { display: flex; align-items: center; gap: 5px; }
.topbar select.pace { width: auto; padding: 6px 8px; font-size: 13px; }
.mode-pick { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.mode-pick .check { display: block; }
.topbar .turn-pick { width: 5em; padding: 6px 8px; font-size: 13px; text-align: right; }
.msg .rewind-btn { background: none; border: 0; color: var(--muted); padding: 0 0 0 8px; font-size: 11px; line-height: 1; opacity: .55; }
.msg .rewind-btn:hover { color: var(--danger); opacity: 1; }
.msg.speaking .bubble { box-shadow: 0 0 0 1px var(--accent); }
/* 全劇播放正在播的那一則（沒有語音的也框起來） */
.msg.replaying .bubble, .msg.narration.replaying { box-shadow: 0 0 0 1px var(--accent); }
/* 頭像：有圖時是半身肖像（也是場景圖的人物參考），小圓框放大顯示臉部；沒圖時顯示名字的第一個字 */
.avatar { flex: none; display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: var(--panel-2) no-repeat; border: 1px solid var(--border); vertical-align: middle; color: var(--accent); font-size: 17px; font-weight: 600; font-style: normal; line-height: 1; }
.avatar.photo { background-size: 220%; background-position: 50% 8%; }
.avatar.sm { width: 22px; height: 22px; font-size: 12px; margin-right: 2px; }
.avatar.lg { width: 88px; height: 88px; font-size: 34px; }
.avatar.lg.photo { width: 96px; height: 128px; border-radius: 10px; background-size: cover; background-position: center; } /* 後台預覽整張 3:4 肖像 */
@keyframes blink { 50% { opacity: 0; } }
.composer { display: flex; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--border); background: var(--panel); }
.composer textarea { min-height: 44px; max-height: 160px; }
.composer button { align-self: stretch; padding: 8px 18px; }
.composer #btn-mic { padding: 8px 12px; }
.composer select { width: auto; flex: 0 0 auto; max-width: 130px; align-self: stretch; padding: 8px 10px; font-size: 13px; }
.composer #btn-mic.listening { background: var(--danger); border-color: var(--danger); animation: blink 1.2s infinite; }
.side { border-left: 1px solid var(--border); background: var(--panel); overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 14px; }
.char { display: flex; gap: 10px; align-items: flex-start; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel-2); }
.char > div { min-width: 0; }
.char .name { font-weight: 600; }
.char.away { opacity: .45; }
.char .thought { font-size: 12px; color: var(--muted); }
.char .thought.changed { color: var(--accent); }
/* 讀心術（VIP 以上）：在場人物上的 🔮，以及讀到的內容 */
.char .mind-btn { margin-left: 6px; padding: 1px 6px; font-size: 11px; }
.mind .mind-block { margin-top: 10px; white-space: pre-wrap; }
.mind .mind-block label { margin: 0 0 2px; }
/* 讀心術的條列與編輯（4.14）：一條一行，SVIP 的 ✏️ 🗑 貼在那一條右邊 */
.mind .beliefs { margin: 0 0 6px; padding-left: 20px; }
.mind .beliefs li { margin: 2px 0; }
.mind .beliefs li input { width: 100%; margin: 2px 0; }
.mind .belief-tools { margin-left: 6px; white-space: nowrap; }
.mind .belief-tools button { padding: 1px 6px; font-size: 11px; margin-left: 2px; }
.mind .mind-hint { font-size: 12px; margin-top: 4px; }
.mind .beliefs .unsound { color: var(--accent); }   /* 查核判定這個世界裡不成立的一條（4.14）：標出來，但照樣留著 */
.mind textarea { width: 100%; margin: 4px 0; }
.place { border: 1px solid var(--border); border-radius: 8px; background: var(--panel-2); padding: 8px 10px; }
.place .name { font-weight: 600; color: var(--accent); }
.exits { display: flex; flex-direction: column; gap: 6px; }
.exits .exit { text-align: left; }
button.tiny { padding: 3px 8px; font-size: 12px; }
.status { font-size: 12px; color: var(--muted); padding: 4px 16px; }
.lobby { max-width: 960px; margin: 32px auto; padding: 0 16px; display: flex; flex-direction: column; gap: 28px; }
.lobby .world { cursor: pointer; }
.lobby .world:hover { border-color: var(--accent); }
.hidden { display: none !important; }

/* ---------- 登入 ---------- */
.login { max-width: 420px; margin: 60px auto; padding-inline: 16px; }
.login .providers { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.login .provider { display: block; text-align: center; padding: 11px 14px; border-radius: 8px; font-weight: 600; text-decoration: none; }
.login .provider.google { background: #fff; color: #1f1f1f; border: 1px solid #dadce0; }
.login .provider.facebook { background: #1877f2; color: #fff; }
.login-error { color: var(--danger); font-size: 14px; margin-top: 8px; }
.user-box { display: flex; align-items: center; gap: 8px; }
.user-box img { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; }
/* 帳號等級 */
.badge.level-vip { color: #e0b84f; border-color: #7a5d20; }
.badge.level-svip { color: #c792ff; border-color: #5b3d8a; }
.badge.level-admin { color: #ff8a8a; border-color: #8a3d3d; }
/* 後台的帳號管理 */
.acct-avatar { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; }
.acct-disabled td { opacity: .5; }
.acct-level { width: auto; padding: 4px 8px; }
.admin th { white-space: nowrap; }
@media (max-width: 800px) {
  .play { grid-template-columns: 1fr; height: auto; }
  .stage { height: 78vh; }
  .side { border-left: 0; border-top: 1px solid var(--border); }
}

/* ---------- admin ---------- */
.admin { display: grid; grid-template-columns: 260px 1fr; height: calc(100vh - var(--topbar)); }
.admin .nav { border-right: 1px solid var(--border); background: var(--panel); overflow-y: auto; padding: 12px; }
.admin .nav .item { padding: 8px 10px; border-radius: 6px; cursor: pointer; }
.admin .nav .item:hover, .admin .nav .item.active { background: var(--panel-2); }
.admin .main { overflow-y: auto; padding: 18px; display: flex; flex-direction: column; gap: 16px; }
.tabs { display: flex; gap: 6px; border-bottom: 1px solid var(--border); }
.tabs .tab { padding: 8px 14px; cursor: pointer; color: var(--muted); border-bottom: 2px solid transparent; }
.tabs .tab.active { color: var(--text); border-color: var(--accent); }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: left; padding: 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
.badge { display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 10px; background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); }
.badge.player { color: #9fbfff; border-color: #3b5a8f; }
.badge.start { color: var(--accent); border-color: #7a5d20; }
label.check { display: inline-flex; align-items: center; gap: 6px; margin: 0 14px 6px 0; color: var(--text); font-size: 14px; }
label.check input { width: auto; }
.avatar-edit { display: flex; gap: 14px; align-items: center; margin-top: 10px; }
.avatar-edit > div { flex: 1; min-width: 0; }
.avatar-edit label { margin-top: 0; }
.checks { display: flex; flex-wrap: wrap; padding: 6px 0; }
.voice-try { margin-top: 8px; }
.voice-try input { flex: 1; width: auto; min-width: 0; }
.scenes { display: flex; flex-wrap: wrap; gap: 12px; }
.scenes figure { margin: 0; width: 260px; }
.scenes img { width: 100%; border-radius: 6px; display: block; }
.scenes figcaption { font-size: 12px; color: var(--muted); margin-top: 4px; }
details { border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px; background: var(--panel-2); }
details summary { cursor: pointer; font-weight: 600; }
pre { white-space: pre-wrap; word-break: break-word; font: inherit; margin: 6px 0; }
.timeline { border-left: 2px solid var(--border); margin-left: 8px; padding-left: 14px; display: flex; flex-direction: column; gap: 10px; }
.timeline .entry { position: relative; }
.timeline .entry::before { content: ""; position: absolute; left: -20px; top: 7px; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
.cog { border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px; background: var(--panel); }
.cog .ver { color: var(--accent); font-size: 12px; }
.cog-pager .pager { flex-wrap: nowrap; margin-bottom: 8px; }
.cog-pager select { width: auto; flex: 1; min-width: 0; padding: 4px 8px; font-size: 13px; }
/* 章節劇本：完成條件一列一個，節點一張小卡 */
.goal-list, .beat-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 6px; }
.goal-list .row, .beat .row { flex-wrap: nowrap; }
.goal-list input, .beat .row input { flex: 1; width: auto; min-width: 0; }
.beat { display: flex; flex-direction: column; gap: 6px; padding: 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); }
.beat textarea { min-height: 56px; }
.plot-item { margin: 4px 0; }
.badge.dead { color: var(--danger); border-color: #7a2a2a; }
.badge.done { color: #8fd19e; border-color: #2f6b3f; }
.badge.invalid { text-decoration: line-through; }

/* ---------- admin：上帝視角的故事線（/admin/story/） ---------- */
/* 整頁固定高度，表格在自己的框裡捲動，表頭（NPC 欄）才能固定在上方 */
.story { height: calc(100vh - var(--topbar)); padding: 14px 16px; display: flex; flex-direction: column; gap: 12px; }
.story .filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin-bottom: 8px; }
.story .filters label:not(.check) { margin: 0; display: flex; flex-direction: column; gap: 4px; }
.story .filters select { width: auto; min-width: 180px; }
#cognition:empty { display: none; }
.matrix-wrap { flex: 1; min-height: 0; overflow: auto; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); }
.matrix th { position: sticky; top: 0; z-index: 1; background: var(--panel-2); white-space: nowrap; }
.matrix .c-loc { white-space: nowrap; color: var(--muted); font-size: 13px; }
.matrix .c-npc { text-align: center; width: 72px; font-size: 12px; font-weight: 500; }
.matrix .body { min-width: 280px; white-space: pre-wrap; word-break: break-word; }
.matrix tr.k-narration .body { color: #b9d4c4; font-style: italic; }
.matrix tr.k-direction .body { color: var(--accent); }
.matrix tr.k-player .body strong { color: #9fbfff; }
.matrix td.w { text-align: center; width: 72px; color: var(--accent); }
.matrix td.w.speaker { color: var(--text); }
.matrix td.w.legacy { color: var(--muted); }
.matrix .focus { background: rgba(217, 164, 65, .10); }
.matrix tr.turn-sep td { background: var(--bg); color: var(--accent); font-size: 12px; font-weight: 600; padding: 4px 8px; }
.matrix tr.inner td { font-size: 12px; color: var(--muted); background: rgba(255, 255, 255, .02); }
.matrix tr.inner .note { margin: 2px 0; }
.matrix tr.inner .note b { color: var(--text); font-weight: 600; }
.matrix .legacy-event { color: var(--text); opacity: .7; }
.matrix .cog-badge { color: var(--accent); border-color: #7a5d20; cursor: help; }

/* ---------- 大廳：我的世界、商店、模版 ---------- */
.lobby section { display: flex; flex-direction: column; gap: 10px; }
.lobby h1 .muted { font-weight: 400; margin-left: 6px; }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.card.world { display: flex; flex-direction: column; gap: 4px; }
.card.world h3 { margin: 0; }
.clamp { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.badge.new { color: var(--accent); border-color: #7a5d20; }
/* 世界與商店的對話框 */
dialog.sheet { width: min(640px, calc(100vw - 32px)); max-height: calc(100vh - 64px); overflow-y: auto; background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 12px; padding: 18px 20px; }
dialog.sheet::backdrop { background: rgba(0, 0, 0, .6); }
.sheet-close { float: right; margin: -6px -8px 0 8px; }
.session-list { display: flex; flex-direction: column; gap: 6px; }
.session-row { flex-wrap: nowrap; }
.session-row .open { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; }
.manage { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border); }
.cast { display: flex; flex-direction: column; gap: 8px; }
/* 右上角的 Token 與容量 */
.account-chip { font-size: 13px; color: var(--muted); border: 1px solid var(--border); border-radius: 14px; padding: 2px 10px; white-space: nowrap; }
.account-chip.warn { color: var(--danger); border-color: #7a2a2a; }

/* ---------- 修改設定（/edit/） ---------- */
.editor { max-width: 880px; margin: 24px auto; padding-inline: 16px; display: flex; flex-direction: column; gap: 14px; }
.stack { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.spoiler { border-color: #7a5d20; }

/* ---------- 後台：空間地圖 ---------- */
.map-editor { display: grid; grid-template-columns: 1fr 320px; gap: 12px; align-items: start; }
@media (max-width: 1100px) { .map-editor { grid-template-columns: 1fr; } }
.map-main { padding: 10px; }
.map-tools { flex-wrap: nowrap; overflow-x: auto; margin-bottom: 8px; }
.map-tools .spacer { flex: 1; }
.map-tools #btn-map-link.on { background: var(--accent); border-color: var(--accent); color: #111; }
.map-hint { margin-top: 6px; }
.map-svg { display: block; width: 100%; height: 520px; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; touch-action: none; cursor: grab; user-select: none; }
.map-svg .node { cursor: pointer; }
.map-svg .node .box { fill: var(--panel-2); stroke: var(--border); stroke-width: 1.5; }
.map-svg .node.start .box { stroke: var(--accent); }
.map-svg .node .box.free { stroke-dasharray: 5 4; }
.map-svg .node:hover .box { stroke: var(--accent-2); }
.map-svg .node.on .box { stroke: var(--accent-2); stroke-width: 2.5; fill: #232936; }
.map-svg .node.linking .box { stroke: var(--accent); stroke-width: 2.5; stroke-dasharray: 5 4; }
.map-svg .node .label { fill: var(--text); font-size: 15px; text-anchor: middle; }
.map-svg .node .tag { fill: var(--accent); font-size: 11px; }
.map-svg .node .tag.free { fill: var(--muted); }
.map-svg .edge { cursor: pointer; }
.map-svg .edge .hit { stroke: transparent; stroke-width: 16; }
.map-svg .edge .wire { stroke: var(--border); stroke-width: 2; }
.map-svg .edge:hover .wire, .map-svg .edge.on .wire { stroke: var(--accent-2); stroke-width: 2.5; }
.map-svg .edge .dist-bg { fill: var(--bg); stroke: var(--border); }
.map-svg .edge.on .dist-bg { stroke: var(--accent-2); }
.map-svg .edge .dist { fill: var(--text); font-size: 12px; text-anchor: middle; }
.map-svg .edge .dist.unset { fill: var(--muted); }
.map-svg .arrow { fill: var(--border); }
.map-svg .arrow.on { fill: var(--accent-2); }
.map-side .conn-list { display: flex; flex-direction: column; gap: 6px; }
.map-side .conn-row { display: flex; justify-content: space-between; gap: 10px; text-align: left; }
.map-side hr.sep { border: 0; border-top: 1px solid var(--border); margin: 14px 0 10px; }
.map-legend { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--muted); }
.map-legend .key { display: inline-block; width: 22px; height: 12px; margin-right: 8px; vertical-align: -1px; border-radius: 3px; border: 1.5px solid var(--border); }
.map-legend .key.start { border-color: var(--accent); }
.map-legend .key.free { border-style: dashed; }
.map-legend .key.wire { height: 0; border: 0; border-top: 2px solid var(--border); border-radius: 0; }

/* ---------- 故事模版的匯入 ---------- */
.issues { margin: 6px 0 0; padding-left: 20px; }
.issues li { margin: 4px 0; }
.issues code { color: var(--muted); font-size: 12px; margin-right: 6px; }
.issues.errors li { color: var(--danger); }

/* ---------- 因果樹（章節劇本的圖形編輯器，public/causal.js）：每一章一個垂直排列的 block ---------- */
.cg-stack { display: flex; flex-direction: column; gap: 14px; }
.cg-block { padding: 10px 12px 8px; }
.cg-block.current { border-color: var(--accent); }
.cg-block-head { flex-wrap: nowrap; overflow-x: auto; margin-bottom: 8px; }
.cg-block-head .cg-num { color: var(--accent); font-size: 12px; letter-spacing: 1px; white-space: nowrap; }
.cg-block-head .cg-title { font-weight: 600; font-size: 16px; white-space: nowrap; }
.cg-block-head .cg-meta { white-space: nowrap; }
.cg-block-head .spacer { flex: 1; }
.cg-block-head select.cg-ref { width: auto; max-width: 200px; padding: 3px 8px; font-size: 12px; }
.cg-body { display: grid; grid-template-columns: 1fr 340px; gap: 12px; align-items: start; }
@media (max-width: 1100px) { .cg-body { grid-template-columns: 1fr; } }
.cg-global { margin-top: 12px; }
.cg-global .spacer { flex: 1; }
.cg-issues-card { margin-top: 12px; }
.cg-hint { margin-top: 6px; }
/* 圖不縮放塞進版面：畫布照內容的實際大小，這一層給捲軸（因果由上往下，所以多半是垂直捲） */
.cg-scroll { max-height: 560px; overflow: auto; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; }
.cg-svg { display: block; margin: 0 auto; touch-action: none; cursor: grab; user-select: none; }
.cg-svg foreignObject { pointer-events: none; overflow: hidden; }
.cg-svg .cg-node { cursor: pointer; }
.cg-svg .cg-node .box { fill: var(--panel-2); stroke: var(--border); stroke-width: 1.5; }
.cg-svg .cg-node.fact .box { fill: #1e2530; }
.cg-svg .cg-node.fact.goal .box { stroke: var(--accent); }
.cg-svg .cg-node.fact.ghost .box { stroke-dasharray: 5 4; fill: var(--bg); }
.cg-svg .cg-node.beat .box { fill: var(--panel); }
.cg-svg .cg-node:hover .box { stroke: var(--accent-2); }
.cg-svg .cg-node.on .box { stroke: var(--accent-2); stroke-width: 2.5; }
.cg-svg .cg-node.met .box, .cg-svg .cg-node.done .box, .cg-svg .cg-node.bypassed .box { fill: #1d2f24; stroke: #2f6b3f; }
.cg-svg .cg-node.invalid .box { stroke: #7a2a2a; stroke-dasharray: 4 3; opacity: .6; }
.cg-svg .cg-node.ready .box { stroke: var(--accent); stroke-width: 2.5; filter: drop-shadow(0 0 6px rgba(217,164,65,.5)); }
.cg-svg .cg-node .port { fill: var(--panel-2); stroke: var(--border); stroke-width: 1.5; opacity: 0; cursor: crosshair; }
.cg-svg .cg-node:hover .port, .cg-svg .cg-node.on .port { opacity: 1; }
.cg-svg .cg-node .port.out:hover { fill: var(--accent-2); }
.cg-text { color: var(--text); font: 13px/1.35 system-ui, -apple-system, "PingFang TC", "Noto Sans TC", sans-serif; height: 100%; display: flex; flex-direction: column; justify-content: center; overflow: hidden; }
.cg-text.fact { text-align: center; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.cg-text.beat .t { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cg-text.beat .c { color: var(--muted); font-size: 12px; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.cg-text .tag { font-weight: 400; font-size: 11px; color: var(--accent); }
.cg-svg .cg-edge { cursor: pointer; }
.cg-svg .cg-edge .hit { fill: none; stroke: transparent; stroke-width: 14; }
.cg-svg .cg-edge .wire { fill: none; stroke: var(--border); stroke-width: 2; }
.cg-svg .cg-edge.produces .wire { stroke: #6b5a2a; }
.cg-svg .cg-edge.requires .wire { stroke: #3b5a8f; }
.cg-svg .cg-edge.met .wire { stroke: #2f6b3f; }
.cg-svg .cg-edge:hover .wire, .cg-svg .cg-edge.on .wire { stroke: var(--accent-2); stroke-width: 2.5; }
.cg-svg .arrow { fill: var(--border); }
.cg-svg .arrow.produces { fill: #6b5a2a; }
.cg-svg .arrow.requires { fill: #3b5a8f; }
.cg-svg .arrow.met { fill: #2f6b3f; }
.cg-svg .arrow.on { fill: var(--accent-2); }
.cg-svg .cg-temp { fill: none; stroke: var(--accent-2); stroke-width: 2; stroke-dasharray: 6 4; pointer-events: none; }
.cg-side { max-height: 560px; overflow-y: auto; padding: 4px 6px; }
.cg-side .cg-form-status { font-size: 13px; }
.cg-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.cg-chip { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; padding: 2px 8px; border-radius: 10px; background: var(--panel-2); border: 1px solid var(--border); color: var(--text); }
.cg-chip .x { background: none; border: 0; color: var(--muted); padding: 0; font-size: 11px; }
.cg-chip .x:hover { color: var(--danger); }
.cg-chip.link { cursor: pointer; }
.cg-state { font-size: 13px; padding: 8px 10px; border: 1px solid #2f6b3f; border-radius: 8px; margin-bottom: 8px; color: #8fd19e; }
.cg-state.ready { border-color: #7a5d20; color: var(--accent); }
.cg-legend { display: flex; flex-direction: column; gap: 6px; font-size: 12px; color: var(--muted); margin-top: 12px; }
.cg-legend .key { display: inline-block; width: 20px; height: 11px; margin: 0 6px 0 2px; vertical-align: -1px; border-radius: 3px; border: 1.5px solid var(--border); background: var(--panel-2); }
.cg-legend .key.fact { border-radius: 6px; background: #1e2530; }
.cg-legend .key.goal { border-radius: 6px; border-color: var(--accent); background: #1e2530; }
.cg-legend .key.ghost { border-radius: 6px; border-style: dashed; background: var(--bg); }
.cg-legend .key.met { background: #1d2f24; border-color: #2f6b3f; }
.cg-legend .key.ready { border-color: var(--accent); box-shadow: 0 0 6px rgba(217,164,65,.5); }
.cg-legend .key.produces, .cg-legend .key.requires { height: 0; border: 0; border-radius: 0; background: none; border-top: 2px solid #6b5a2a; }
.cg-legend .key.requires { border-top-color: #3b5a8f; }
.cg-issues { display: flex; flex-direction: column; gap: 6px; }
.cg-issues button { text-align: left; white-space: normal; font-size: 13px; }
.cg-issues button.error { border-color: #7a2a2a; color: var(--danger); }
.cg-issues button.warn { border-color: #7a5d20; color: var(--accent); }

/* ---------- 情境圖：劇情節點完成時畫的一幕 ---------- */
.msg.illustration { align-self: center; max-width: 90%; padding: 0; background: transparent; }
.msg.illustration figure { margin: 0; border: 1px solid #7a5d20; border-radius: 10px; overflow: hidden; background: #000; }
.msg.illustration img { display: block; width: 100%; max-height: 320px; object-fit: cover; }
.msg.illustration figcaption { padding: 6px 12px; font-size: 12px; color: var(--accent); letter-spacing: 1px; text-align: center; }
.matrix tr.k-illustration .body { color: var(--accent); }
.matrix .illus { display: block; max-width: 260px; border-radius: 6px; margin-top: 4px; }
/* 抽成劇本 */
.script-box { margin-top: 10px; padding: 10px; border: 1px dashed var(--border); border-radius: 8px; font-size: 13px; }
.script-box .chapters { margin: 6px 0 0; padding-left: 18px; }

/* 投稿與回放（DESIGN.md 4.18） */
.notice { display: block; margin-top: 10px; padding: 10px 12px; border: 1px dashed #7a5d20; border-radius: 8px; color: var(--muted); font-size: 13px; white-space: pre-wrap; }
.replay-bar { align-items: center; flex-wrap: wrap; }
.replay-bar button { align-self: auto; }
.replay-bar .spacer { flex: 1; }
.badge.rating { color: var(--text); }
.badge.rating-restricted, .badge.rating- { color: #ff8a8a; border-color: #8a3d3d; }
.badge.rating-pg15, .badge.rating-pg12 { color: #e0b84f; border-color: #7a5d20; }
.badge.status-pending { color: #e0b84f; border-color: #7a5d20; }
.badge.status-approved { color: #8fd19e; border-color: #2f6b3d; }
.badge.status-rejected, .badge.status-withdrawn, .badge.status-draft { color: var(--muted); }
.declaration { max-height: 180px; overflow-y: auto; white-space: pre-wrap; font-size: 13px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; }
.log .story-notice { align-self: stretch; max-width: none; }
.rec-transcript { max-height: 60vh; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; font-size: 14px; }
.rec-line { white-space: pre-wrap; }
.rec-line.on { background: var(--panel-2); border-radius: 4px; }
.rec-try { align-items: center; gap: 6px; flex-wrap: wrap; }
.rec-try .turn-pick { width: 5em; padding: 6px 8px; font-size: 13px; text-align: right; }
.replay-bar .turn-pick-box { display: flex; align-items: center; gap: 5px; white-space: nowrap; }
.replay-bar .turn-pick { width: 5em; padding: 6px 8px; font-size: 13px; text-align: right; }
/* 年齡認證（DESIGN.md 4.19） */
.age-video { width: 100%; max-width: 480px; aspect-ratio: 4/3; background: #000; border-radius: 10px; transform: scaleX(-1); display: block; margin: 0 auto; }
.age-say { margin-top: 10px; font-size: 16px; color: var(--accent); text-align: center; min-height: 1.5em; }
/* 個人資料頁（DESIGN.md 4.20） */
.account-page { max-width: 820px; }
.profile-head { display: flex; align-items: center; gap: 16px; margin: 8px 0 4px; }
.profile-avatar { width: 88px; height: 88px; border-radius: 50%; overflow: hidden; background: var(--panel-2); border: 1px solid var(--border); display: grid; place-items: center; font-size: 34px; flex: none; }
.profile-avatar img { width: 100%; height: 100%; object-fit: cover; }
label.button-like { display: inline-flex; align-items: center; margin: 0; padding: 8px 14px; border-radius: 6px; background: var(--panel-2); border: 1px solid var(--border); color: var(--text); font-size: 14px; cursor: pointer; }
.age-state { font-size: 15px; margin-bottom: 4px; }
.age-state.ok { color: #8fd19e; }
.age-methods { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 14px; }
.age-method { border: 1px solid var(--border); border-radius: 8px; padding: 12px; background: var(--panel-2); }
.age-cam { position: relative; margin-top: 10px; }
.age-cam .age-video { max-width: 100%; }
.age-live { position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%); background: rgba(0, 0, 0, .65); color: var(--accent); padding: 4px 12px; border-radius: 14px; font-size: 16px; font-weight: 600; }
.age-live:empty { display: none; }
.age-estimate { text-align: center; color: var(--accent); font-weight: 600; margin-top: 4px; }
.age-result { margin-top: 10px; padding: 10px 12px; border-radius: 8px; border: 1px solid var(--border); }
.age-result.ok { border-color: #2f6b3d; }
.age-result.bad { border-color: #8a3d3d; }
.age-big { font-size: 20px; font-weight: 700; color: var(--accent); }
.user-box a#user-name { text-decoration: none; }
.user-box a#user-name:hover { color: var(--accent); }
@media (max-width: 700px) { .age-methods { grid-template-columns: 1fr; } }
.gen-avatar { margin: 6px 0 4px; }
