/* ============ 主題變數 ============ */
:root{
  --bg:#131114; --surface:#1C191E; --surface2:#262229; --line:#332E37;
  --text:#EAE6E0; --muted:#BDB6BE; --faint:#AAA2AC;   /* 次要文字提高明度，維持小字辨識度 */
  --accent:#C8A46E; --accent-soft:rgba(200,164,110,.16); --accent-ink:#191309;
  /* 第二強調色:目前只有「上下文用量」彈跳視窗拿來跟 --accent 並列(基本/
     觸發兩類背景資訊各自一色),各主題選一個跟自己 --accent 明顯區隔、
     但氣質仍相襯的冷色系,不搶主色風采 */
  --accent2:#7C9CB8; --accent2-soft:rgba(124,156,184,.16);
  --danger:#D07070;
  --radius:18px;
  --serif:"Noto Serif TC","Songti TC","Noto Serif CJK TC",serif;
  --sans:"Noto Sans TC","PingFang TC","Microsoft JhengHei",sans-serif;
  /* ---- 字級系統:全站文字一律取用這組 token,不再逐處硬編碼 ----
     展示級尺寸(品牌 27 / 分頁標題 24 / 今日籤大日期 44 / 倒數數字 34 /
     書封 30 / 翻牌字 28)與「emoji / ✕ ✓ › 等圖示字元」的 font-size
     屬於圖形尺寸,不在此系統內,維持原值。 */
  --fs-caption:11px;    /* 時間戳/hint/徽章/導覽字(原 10~11.5px) */
  --fs-small:12.5px;    /* 次要說明/小標/標籤(原 12~13px) */
  --fs-body-s:13.5px;   /* 敘事/清單/卡片內文(原 13.5~14px) */
  --fs-body:15px;       /* 正文/對話氣泡(原 14.5~15.5px) */
  --fs-body-l:16.5px;   /* 輸入框/卡片名稱(原 16~17px;≥16px 避免 iOS 聚焦縮放) */
  --fs-title-s:19px;    /* 區塊標題/sheet 標題(原 18~20px) */
  --fs-title:22px;      /* 大標/hero 名字(原 21~22px) */
  --fs-display-s:24px;  /* 分頁標題 */
  --fs-display:27px;    /* 品牌標題 */
  /* ---- 圓角/間距 token(第一階段:精確值收斂,零視覺變化)----
     圓角僅涵蓋單一值的 12/14/16/20(--radius:18px 維持氣泡/卡片主圓角);
     間距僅涵蓋單一值的 gap 4/8/12/16。其餘畸零值(圓角 13/17/22、
     gap 7/9/10/11/13…)為未來設計吸附的候選,吸附與否是會動版面的
     設計決策,不在本階段機械替換範圍。主題差異原則:顏色/字級/圓角/
     間距一律走 token 層(各主題於自己的選擇器覆寫變數),逐元件覆寫
     只保留給英雄場景特效(topbar、聊天室頂部列、氣泡質感)。 */
  --r-sm:12px; --r-md:14px; --r-lg:16px; --r-xl:20px;
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px;
}
[data-theme="shiro"]{ color-scheme:light; --bg:#F5F4F1; --surface:#FDFCFA; --surface2:#EDEBE5; --line:#E1DED6;
  --text:#37342F; --muted:#6F695F; --faint:#766F63;   /* 亮色主題提高深淺對比，faint 仍達一般文字門檻 */
  --accent:#6E675C; --accent-soft:rgba(110,103,92,.10); --accent-ink:#FAF9F6;
  --accent2:#5D7A96; --accent2-soft:rgba(93,122,150,.12); }
[data-theme="neon"]{ color-scheme:dark; --radius:8px;
  --bg:#0B0A14; --surface:#141230; --surface2:#1D1A42; --line:rgba(79,227,255,.42);
  --text:#EDEBFF; --muted:#BDB8EE; --faint:#9E98D6;   /* 次要文字提高明度與辨識度 */
  --accent:#FF5CCB; --accent-soft:rgba(255,92,203,.16); --accent-ink:#1A0716;
  --accent2:#4FE3FF; --accent2-soft:rgba(79,227,255,.16);
  --sans:"DotGothic16","Noto Sans TC",monospace; --serif:"DotGothic16","Noto Serif TC",monospace;
  background-image:repeating-linear-gradient(0deg,rgba(79,227,255,.04) 0 1px,transparent 1px 3px);
}
[data-theme="hoshi"]{ color-scheme:dark;
  --bg:#1B1B19; --surface:#222220; --surface2:#292826; --line:#3A3935;
  --text:#ECEAE4; --muted:#C3C0B8; --faint:#AAA79F;   /* 次要文字提高明度與辨識度 */
  --accent:#CDC7B6; --accent-soft:rgba(205,199,182,.15); --accent-ink:#211F1B;
  --accent2:#9DB4E0; --accent2-soft:rgba(157,180,224,.15);
  background-image:
    radial-gradient(ellipse 70% 45% at 72% 10%, rgba(255,255,255,.05), transparent 65%),
    radial-gradient(ellipse 50% 35% at 18% 80%, rgba(255,255,255,.035), transparent 65%),
    radial-gradient(1px 1px at 12% 22%, rgba(255,255,255,.85), transparent 55%),
    radial-gradient(1px 1px at 78% 8%, rgba(255,255,255,.7), transparent 55%),
    radial-gradient(1.2px 1.2px at 55% 30%, rgba(255,255,255,.75), transparent 55%),
    radial-gradient(1px 1px at 32% 55%, rgba(255,255,255,.55), transparent 55%),
    radial-gradient(1px 1px at 88% 46%, rgba(255,255,255,.6), transparent 55%),
    radial-gradient(1.4px 1.4px at 8% 68%, rgba(255,255,255,.7), transparent 55%),
    radial-gradient(1px 1px at 64% 78%, rgba(255,255,255,.5), transparent 55%),
    radial-gradient(1px 1px at 42% 92%, rgba(255,255,255,.6), transparent 55%),
    radial-gradient(1.2px 1.2px at 92% 88%, rgba(255,255,255,.65), transparent 55%);
}

/* ============ 莓(ichigo):草莓鮮奶油蛋糕 + 極淡抹茶包裝紙 ============
   亮色系,不是莓果夜色。主背景極淡抹茶,奶油白/草莓粉/淡粉紅撐主要 UI,
   藍莓藍/奶油黃/薄荷綠只做小面積跳色,黑色只出現在手繪描線,不當背景。

   對比度說明(已用 WCAG 相對亮度實測,不是憑感覺選色):
   --accent 若照原案 #FF78A0 對淡抹茶底只有 2.36:1,但這個 token 在全站
   有 100+ 處直接當「小字說明文字/邊框」顏色用(標籤、日曆生日點、測驗
   對錯……多半 11~13.5px),照抄會讓一大片小字幾乎看不清楚。這裡把
   --accent 適度加深到 #FF4779(3.09:1,達 UI 元件/大字門檻並留一點安全邊際,
   跳色感保留;極少數 11px 說明文字仍略低於 4.5:1 完整文字門檻,屬於可
   接受的邊緣情況)。
   --accent-ink 同步加深到 #471523,確保送出鈕/選中 tab/日曆選取格這類
   「草莓粉底 + 深色字」的組合達 4.5:1。focus ring、今日日曆格邊框、分頁
   選中字這幾個「不能不清楚」的可用性關鍵點,額外導去 --accent-ink 而非
   直接用 --accent,拿到遠高於門檻的安全邊際(見下方對應規則)。
   --muted/--faint/--danger 同樣是原案數值不足 4.5:1,小幅加深到剛好達標,
   色相/彩度盡量維持原案精神,肉眼幾乎看不出差異。 */
[data-theme="ichigo"]{ color-scheme:light;
  --bg:#F7FAEF; --surface:#FFF8FA; --surface2:#FCEBF0; --line:#DDE5CF;
  --text:#4B5140; --muted:#6E7560; --faint:#6C7759;
  --accent:#FF4779; --accent-soft:rgba(255,71,121,.22); --accent-ink:#471523;
  --accent2:#79B8FF; --accent2-soft:rgba(121,184,255,.18);
  --danger:#E1154C;
  --wish-char:var(--accent);
}
/* 主背景:低飽和高亮度抹茶底 + 極淡的粉莓/藍莓/薄荷色團,四角維持乾淨底色,
   不成明顯格線。#app 本身有 background:var(--bg) 的簡寫屬性,ID 選擇器
   優先度比單純 [data-theme="ichigo"] 高,單獨疊 background-image 會被蓋掉、
   完全看不到——這裡刻意疊上 #app 一起提高優先度覆寫,不動 #app 原本的
   規則,也不影響其他主題。 */
#app[data-theme="ichigo"]{
  background-image:
    radial-gradient(56% 42% at 10% 6%, rgba(255,214,224,.55), transparent 62%),
    radial-gradient(50% 38% at 92% 8%, rgba(121,184,255,.10), transparent 62%),
    radial-gradient(55% 42% at 88% 94%, rgba(156,230,196,.16), transparent 64%);
}
/* 情緒環(日誌/交換日記,見「日誌與交換日記」區塊):預設值是替暗色系的
   墨金調的暖金/青/藍,淡抹茶底上幾乎看不見(1.9~2.9:1),這裡換成同一組
   跳色但加深到剛好可辨(≥3:1,非文字用途的環狀邊框) */
[data-theme="ichigo"]{ --mood-happy:#BF8600; --mood-ok:#29A46B; --mood-sad:#2F91FF; }

/* 莓:可用性關鍵點——focus ring / 今日日曆格 / 分頁選中字改用 --accent-ink
   而非 --accent 本身,拿到遠高於 3:1 的安全邊際(其餘上百處裝飾性小字
   維持 --accent 本身,見上方 token 註解) */
[data-theme="ichigo"] input:focus,[data-theme="ichigo"] textarea:focus,
[data-theme="ichigo"] select:focus{border-color:var(--accent-ink)}
[data-theme="ichigo"] :focus-visible{outline-color:var(--accent-ink)}
[data-theme="ichigo"] .cal-cell.today{border-color:var(--accent-ink)}
[data-theme="ichigo"] .pill.hot,[data-theme="ichigo"] .sendbtn{box-shadow:0 3px 10px rgba(255,71,121,.32)}

/* 莓:底部 tab bar 整條都走莓果色系(深莓果),未選中降低不透明度做深淺
   區分,不是換成另一組不相干的顏色;跟聊天室 icon(見下方)呼應。 */
[data-theme="ichigo"] #tabbar button{color:var(--accent-ink);opacity:.55}
[data-theme="ichigo"] #tabbar button.on{opacity:1}

/* 莓:聊天室頁面的圖示(返回/整理記憶旁的清除對話/引用取消/工具列/捲到底)
   一律採用送出鈕同一個亮紅莓色,跟主頁面的深莓果 tab bar 區隔出「聊天室
   內」與「全站導覽」兩層語意,同時彼此都是莓果色系、氣質一致。 */
[data-theme="ichigo"] #chatroom .iconbtn{color:var(--accent)}
[data-theme="ichigo"] #chatroom .chat-scroll-bottom{color:var(--accent)}
.confetti-ichigo{color:var(--accent)}

/* ============ 莓:top bar 粉白糖霜 ============
   奶油白→淡粉紅的糖霜底,角落一塊極慢、極克制的柔光呼吸(24s,只動
   opacity,肉眼幾乎察覺不到,不影響閱讀);底部一條彩色巧克力米緞帶,
   純 CSS background layers 疊出短條筆刷感,不是圖片。緞帶只佔 6px 高、
   貼在 topbar 最下緣,不會蓋到標題文字。 */
[data-theme="ichigo"] .topbar{
  background:linear-gradient(180deg, #FFFDFB 0%, #FCEBF0 100%);
}
[data-theme="ichigo"] .topbar::before{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(65% 130% at 22% -25%, rgba(255,255,255,.9), transparent 62%);
  animation:ichigo-cream-flow 24s ease-in-out infinite;
}
@keyframes ichigo-cream-flow{0%,100%{opacity:.5}50%{opacity:.85}}
[data-theme="ichigo"] .topbar::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:6px;pointer-events:none;
  background:
    repeating-linear-gradient(96deg, #FF78A0 0 3px, transparent 3px 15px),
    repeating-linear-gradient(58deg, #79B8FF 0 2px, transparent 2px 18px),
    repeating-linear-gradient(124deg, #FFD166 0 2px, transparent 2px 21px),
    repeating-linear-gradient(72deg, #9CE6C4 0 2px, transparent 2px 19px),
    repeating-linear-gradient(140deg, #7B4A3A 0 1.5px, transparent 1.5px 24px);
  opacity:.85;
}
[data-theme="ichigo"] .topbar .sub{color:var(--accent-ink)}

/* ============ 莓:「整理記憶」換成手繪風草莓蛋糕 ============
   #mem-btn 本身在 index.html 內嵌了 font-size:16px 的行內樣式(用來撐
   ✨ emoji 的大小),行內樣式優先度高於一般選擇器,這裡用 !important
   蓋掉字級讓 emoji 文字節點縮到看不見,再疊上內嵌 SVG 蛋糕圖示——DOM
   與原本的按鈕/事件完全沒動,只換視覺。手繪感靠不規則的貝茲曲線路徑
   本身做出來,刻意不用 feTurbulence/feDisplacementMap 這類 SVG 濾鏡
   ——這類濾鏡在行動版 Safari 上是已知的效能/記憶體地雷,聊天訊息旁的
   貼紙(下方)又是每次視窗化重繪都可能疊出好幾份的重複元素,曾經在真機
   上造成「聊天記錄很多的角色一點開就被系統記憶體回收、整頁重載彈回
   歡迎頁」——拿掉濾鏡後純粹是靜態向量圖層,沒有這個風險。hover/active
   給極輕微的傾斜與位移回饋。 */
[data-theme="ichigo"] #mem-btn{
  font-size:0 !important;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cg%3E%3Cellipse cx='16' cy='27' rx='11' ry='2.4' fill='%23DCEFE0' opacity='0.7'/%3E%3Cpath d='M6 24 C6 26 9 27 16 27 C23 27 26 26 26 24 L25 17 C25 15 23 14 16 14 C9 14 7 15 7 17 Z' fill='%23FFF8FA' stroke='%237B4A3A' stroke-width='1.1' stroke-linejoin='round'/%3E%3Cpath d='M6.5 19 C6.5 19 10 20.2 16 20.2 C22 20.2 25.5 19 25.5 19' fill='none' stroke='%237B4A3A' stroke-width='0.9' opacity='0.55'/%3E%3Cpath d='M6.6 16.5 C7.5 12 10.5 10.2 12.7 12.4 C14 9.6 17.3 9.6 18.4 12.3 C20.6 10 24 11.7 25 15.6 C25.3 16.6 25.2 17.2 24.6 17.6 C21 19.2 10.8 19.2 7.2 17.6 C6.6 17.3 6.4 17 6.6 16.5 Z' fill='%23FFEFF4' stroke='%237B4A3A' stroke-width='1.1' stroke-linejoin='round'/%3E%3Ccircle cx='11.6' cy='13.6' r='2.5' fill='%23FF4D81' stroke='%236A1F34' stroke-width='0.9'/%3E%3Cpath d='M10.6 12 C11.2 10.8 12.3 10.8 12.7 12' fill='none' stroke='%239CE6C4' stroke-width='1' stroke-linecap='round'/%3E%3Ccircle cx='10.8' cy='13.3' r='0.35' fill='%23FFF'/%3E%3Ccircle cx='12.5' cy='14.2' r='0.35' fill='%23FFF'/%3E%3Ccircle cx='20.2' cy='13.9' r='1.6' fill='%2379B8FF' stroke='%236A1F34' stroke-width='0.8'/%3E%3Ccircle cx='22.2' cy='14.6' r='1.3' fill='%2379B8FF' stroke='%236A1F34' stroke-width='0.8'/%3E%3Cpath d='M20.3 12.5 C20.7 11.7 21.4 11.7 21.7 12.4' fill='none' stroke='%239CE6C4' stroke-width='0.9' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
  background-size:26px 26px;background-position:center;background-repeat:no-repeat;
  transition:transform .18s ease;
}
[data-theme="ichigo"] #mem-btn:hover{transform:rotate(-1.5deg) translateY(-1px)}
[data-theme="ichigo"] #mem-btn:active{transform:rotate(1.5deg) scale(.94)}

/* ============ 莓:訊息旁的手繪貼紙(愛心/藍莓/草莓) ============
   js/ui/chat.js 的 wrapRow() 會用低機率(10%)幫訊息列加上
   .ichigo-deco-heart/blueberry/strawberry 其中一個 class;這裡只負責畫圖與
   定位,貼在頭貼外側一角,不會蓋到氣泡文字,也不吃點擊(pointer-events:none)。 */
[data-theme="ichigo"] .msg-row{position:relative}
[data-theme="ichigo"] .msg-row[class*="ichigo-deco-"]::before{
  content:'';position:absolute;top:-4px;width:15px;height:15px;pointer-events:none;
  background-size:contain;background-repeat:no-repeat;
}
[data-theme="ichigo"] .msg-row.ai[class*="ichigo-deco-"]::before{left:-3px;transform:rotate(-8deg)}
[data-theme="ichigo"] .msg-row.me[class*="ichigo-deco-"]::before{right:-3px;transform:rotate(8deg)}
[data-theme="ichigo"] .msg-row.ichigo-deco-heart::before{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 13.5 C3 10 1 7.4 1 5 C1 2.8 2.8 1.4 4.8 1.6 C6.2 1.7 7.4 2.6 8 3.8 C8.6 2.6 9.8 1.7 11.2 1.6 C13.2 1.4 15 2.8 15 5 C15 7.4 13 10 8 13.5 Z' fill='%23FF78A0' stroke='%236A1F34' stroke-width='1'/%3E%3C/svg%3E");
}
[data-theme="ichigo"] .msg-row.ichigo-deco-blueberry::before{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg%3E%3Ccircle cx='6' cy='9' r='3.4' fill='%2379B8FF' stroke='%236A1F34' stroke-width='1'/%3E%3Ccircle cx='11' cy='10.2' r='2.7' fill='%2379B8FF' stroke='%236A1F34' stroke-width='1'/%3E%3Ccircle cx='8.8' cy='6' r='2.4' fill='%23A7D0FF' stroke='%236A1F34' stroke-width='0.9'/%3E%3Cpath d='M8 3.4 C8.6 2 10 2 10.4 3.2' fill='none' stroke='%239CE6C4' stroke-width='1.1' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
}
[data-theme="ichigo"] .msg-row.ichigo-deco-strawberry::before{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg%3E%3Cpath d='M8 15 C4 15 2.2 11.4 2.6 8 C3 5 5.2 3.6 8 3.6 C10.8 3.6 13 5 13.4 8 C13.8 11.4 12 15 8 15 Z' fill='%23FF4D81' stroke='%236A1F34' stroke-width='1'/%3E%3Ccircle cx='6' cy='8.5' r='0.5' fill='%23FFF3F6'/%3E%3Ccircle cx='9.5' cy='7.6' r='0.5' fill='%23FFF3F6'/%3E%3Ccircle cx='7.5' cy='11.2' r='0.5' fill='%23FFF3F6'/%3E%3Ccircle cx='10.2' cy='10.8' r='0.5' fill='%23FFF3F6'/%3E%3Cpath d='M5 4 L8 1.6 L11 4 L9.6 3.4 L8 4.6 L6.4 3.4 Z' fill='%239CE6C4' stroke='%236A1F34' stroke-width='0.8' stroke-linejoin='round'/%3E%3C/g%3E%3C/svg%3E");
}

/* 霓虹:光暈與卡帶感 */
[data-theme="neon"] .topbar h1{color:var(--accent);text-shadow:0 0 10px rgba(255,92,203,.6),0 0 24px rgba(79,227,255,.35)}
[data-theme="neon"] .topbar .sub{color:#4FE3FF;text-shadow:0 0 8px rgba(79,227,255,.6)}
[data-theme="neon"] .pill.hot,[data-theme="neon"] .sendbtn{box-shadow:0 0 14px rgba(255,92,203,.45)}
[data-theme="neon"] .cal-cell.today{box-shadow:0 0 9px rgba(79,227,255,.55)}
[data-theme="neon"] #tabbar button.on{text-shadow:0 0 8px rgba(255,92,203,.7)}
[data-theme="neon"] .avatar,[data-theme="neon"] .set-card,
[data-theme="neon"] .omikuji,[data-theme="neon"] .pf-card,[data-theme="neon"] .journal-card,
[data-theme="neon"] .convo .avatar,[data-theme="neon"] input,[data-theme="neon"] textarea,[data-theme="neon"] select{border-radius:7px}
[data-theme="neon"] .cstate{color:#4FE3FF}

/* 星空:上浮星芒粒子(背景大顆在文字之下 / 前景小顆在文字之上) */
#app{isolation:isolate}
#starfield-back{position:absolute;inset:0;pointer-events:none;z-index:-1;overflow:hidden}
#starfield-front{position:absolute;inset:0;pointer-events:none;z-index:1;overflow:hidden}
#starfield-back .spark,#starfield-front .spark{
  position:absolute;bottom:-30px;color:#FFF;opacity:0;line-height:1;
  animation:rise linear infinite;
  text-shadow:0 0 4px rgba(255,255,255,.9),0 0 9px rgba(255,255,255,.5);
}
#starfield-back .spark{filter:blur(.4px);text-shadow:0 0 6px rgba(255,255,255,.6),0 0 14px rgba(255,255,255,.28)}
@keyframes rise{
  0%{transform:translate(0,0) rotate(0deg) scale(.6);opacity:0}
  8%{opacity:var(--peak,1)}
  55%{opacity:calc(var(--peak,1) * .85)}
  80%{opacity:calc(var(--peak,1) * .5)}
  100%{transform:translate(var(--dx,0), calc(-100dvh - 70px)) rotate(200deg) scale(1.05);opacity:0}
}

/* 星空:閃爍星光(低明度,不影響閱讀) */
[data-theme="hoshi"]::after{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:1;
  background:
    radial-gradient(1.6px 1.6px at 26% 36%, rgba(255,255,255,.5), transparent 60%),
    radial-gradient(1.3px 1.3px at 70% 18%, rgba(210,220,255,.45), transparent 60%),
    radial-gradient(1.5px 1.5px at 84% 66%, rgba(255,255,255,.45), transparent 60%),
    radial-gradient(1.2px 1.2px at 16% 84%, rgba(210,220,255,.4), transparent 60%),
    radial-gradient(1.4px 1.4px at 48% 62%, rgba(255,255,255,.4), transparent 60%);
  animation:twinkle 3.4s ease-in-out infinite alternate;
}
@keyframes twinkle{from{opacity:.1}to{opacity:.4}}
[data-theme="hoshi"] .pill.hot{box-shadow:0 0 12px rgba(205,199,182,.4)}   /* 星空:柔和光暈,呼應星芒質感 */

/* ============ 品牌標題 μεταξύ:四主題各自的性格 ============ */
/* 墨金:金箔漸層字,微光緩慢掃過——搶眼 */
[data-theme="sumi"] .topbar h1.brand{
  background:linear-gradient(105deg,#8A6B3F 0%,#E8C87E 30%,#FFF3D6 50%,#E8C87E 70%,#8A6B3F 100%);
  background-size:220% 100%;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 0 10px rgba(200,164,110,.3));
  animation:sumi-shine 7s ease-in-out infinite;
}
@keyframes sumi-shine{0%,100%{background-position:0% 0}50%{background-position:100% 0}}
/* 霜白:溫柔——細字重、暖霧灰、柔白暈光 */
[data-theme="shiro"] .topbar h1.brand{
  color:#9C9384;font-weight:400;letter-spacing:.14em;
  text-shadow:0 0 16px rgba(255,251,240,.95), 0 1px 2px rgba(180,170,150,.2);
}
/* 霓虹:8bit 點陣字 + 硬像素疊影 + 閃爍游標 */
[data-theme="neon"] .topbar h1.brand{
  font-family:"DotGothic16",var(--sans);font-size:var(--fs-display-s);letter-spacing:.1em;font-weight:400;
  color:var(--accent);
  text-shadow:2px 2px 0 rgba(79,227,255,.7), 4px 4px 0 rgba(10,8,18,.9), 0 0 12px rgba(255,92,203,.55);
}
[data-theme="neon"] .topbar h1.brand::after{
  content:'▌';margin-left:5px;font-size:.8em;color:#4FE3FF;
  text-shadow:0 0 8px rgba(79,227,255,.7);
  animation:neon-cursor 1.1s steps(2,start) infinite;
}
@keyframes neon-cursor{50%{opacity:0}}
/* 星空:閃爍——暈光呼吸 + 右上一顆小星芒同步眨眼 */
[data-theme="hoshi"] .topbar h1.brand{
  position:relative;color:#ECE8DC;
  animation:hoshi-title 3.4s ease-in-out infinite alternate;
}
[data-theme="hoshi"] .topbar h1.brand::after{
  content:'✦';position:absolute;top:-3px;right:-17px;font-size:11px;color:#FFF;
  text-shadow:0 0 5px rgba(255,255,255,.9);
  animation:hoshi-title-spark 2.4s ease-in-out infinite alternate;
}
@keyframes hoshi-title{
  from{text-shadow:0 0 5px rgba(255,255,255,.25), 0 0 14px rgba(174,191,242,.2)}
  to{text-shadow:0 0 9px rgba(255,255,255,.6), 0 0 26px rgba(174,191,242,.5)}
}
@keyframes hoshi-title-spark{
  from{opacity:.25;transform:scale(.8) rotate(-8deg)}
  to{opacity:1;transform:scale(1.15) rotate(10deg)}
}

/* ============ 分頁標題(聊天/日曆/角色/設定)小動畫:四主題各一種,同主題四頁一致 ============ */
/* 墨金:比照品牌標題的金光掃過,同一套語彙 */
[data-theme="sumi"] .topbar h1:not(.brand){
  background:linear-gradient(105deg,#8A6B3F 0%,#E8C87E 30%,#FFF3D6 50%,#E8C87E 70%,#8A6B3F 100%);
  background-size:220% 100%;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  animation:sumi-shine 7s ease-in-out infinite;
}
/* 霜白:雪中漂浮——極輕上下飄移 + 呼吸,要飄不要跳 */
[data-theme="shiro"] .topbar h1:not(.brand){
  display:inline-block;
  animation:shiro-title-float 4.6s ease-in-out infinite alternate;
}
@keyframes shiro-title-float{
  from{transform:translateY(-2px);opacity:.9}
  to{transform:translateY(2px);opacity:1}
}
/* 霓虹:打字機——切到分頁時逐字打出,比照品牌標題的 8bit 點陣質感;
   文字用內層 .ttxt 以 width+overflow 逐字顯現(不用 clip-path),避免固定寬度的 h1
   跟真實字型量出的字寬對不上而被迫換行、把游標擠到下一行,曾在裝置上炸開一整塊底色;
   游標是獨立的 ::after,永遠貼在文字後面,不受內層寬度動畫影響 */
[data-theme="neon"] .topbar h1:not(.brand){
  font-family:"DotGothic16",var(--sans);letter-spacing:.1em;font-weight:400;
  color:var(--accent);
  text-shadow:2px 2px 0 rgba(79,227,255,.7), 4px 4px 0 rgba(10,8,18,.9), 0 0 12px rgba(255,92,203,.55);
  display:inline-flex;align-items:baseline;
}
[data-theme="neon"] .topbar h1:not(.brand) .ttxt{
  display:inline-block;overflow:hidden;white-space:nowrap;width:0;
  animation:neon-title-type .6s steps(2,end) 1 forwards;
}
[data-theme="neon"] .topbar h1:not(.brand)::after{
  content:'▌';margin-left:3px;color:#4FE3FF;
  text-shadow:0 0 8px rgba(79,227,255,.7);
  animation:neon-cursor 1.1s steps(2,start) infinite;
}
@keyframes neon-title-type{
  from{width:0}
  to{width:2.2em}   /* 目前四個分頁標題(聊天/日曆/角色/設定)皆為 2 個全形字 */
}
/* 星空:星光閃爍——暈光強弱呼吸,時長與品牌標題錯開,安靜地明滅 */
[data-theme="hoshi"] .topbar h1:not(.brand){
  animation:hoshi-title-page 4.1s ease-in-out infinite alternate;
}
@keyframes hoshi-title-page{
  from{text-shadow:0 0 4px rgba(255,255,255,.2), 0 0 11px rgba(174,191,242,.15)}
  to{text-shadow:0 0 8px rgba(255,255,255,.55), 0 0 22px rgba(174,191,242,.45)}
}

/* ============ 墨金:專屬質感——夜色暈染 + 灑金箔,卡片壓金色髮絲線 ============ */
[data-theme="sumi"]{
  background-image:
    radial-gradient(ellipse 120% 70% at 50% -20%, rgba(200,164,110,.10), transparent 60%),
    radial-gradient(ellipse 90% 55% at 88% 112%, rgba(150,110,60,.09), transparent 65%),
    radial-gradient(1.3px 1.3px at 15% 22%, rgba(232,200,126,.5), transparent 55%),
    radial-gradient(1px 1px at 78% 12%, rgba(232,200,126,.35), transparent 55%),
    radial-gradient(1.2px 1.2px at 62% 38%, rgba(232,200,126,.3), transparent 55%),
    radial-gradient(1px 1px at 30% 58%, rgba(232,200,126,.28), transparent 55%),
    radial-gradient(1.4px 1.4px at 88% 72%, rgba(232,200,126,.4), transparent 55%),
    radial-gradient(1px 1px at 10% 86%, rgba(232,200,126,.3), transparent 55%),
    radial-gradient(1.2px 1.2px at 45% 94%, rgba(232,200,126,.35), transparent 55%);
}
[data-theme="sumi"] .topbar .sub{color:var(--accent);opacity:.8}
[data-theme="sumi"] .set-card,[data-theme="sumi"] .pf-card,
[data-theme="sumi"] .omikuji{
  border-color:rgba(200,164,110,.22);
  box-shadow:inset 0 1px 0 rgba(232,200,126,.13), 0 4px 16px rgba(0,0,0,.22);
}
[data-theme="sumi"] #tabbar button.on{text-shadow:0 0 10px rgba(200,164,110,.55)}
[data-theme="sumi"] .pill.hot,[data-theme="sumi"] .sendbtn{box-shadow:0 0 12px rgba(200,164,110,.3)}
[data-theme="sumi"] .cal-cell.today{box-shadow:0 0 9px rgba(200,164,110,.4)}


/* ============ 基礎 ============ */
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
body{
  background:#08070A; font-family:var(--sans); color:var(--text);
  display:flex; justify-content:center; overscroll-behavior:none;
}
#app{
  width:100%; max-width:430px; height:100dvh; background:var(--bg); color:var(--text); color-scheme:dark;
  position:relative; overflow:clip; display:flex; flex-direction:column;
  transition:background .35s;
}
/* 用 overflow:clip 而不是 hidden:滿版覆蓋層(聊天室/交換日記)關閉時用
   transform:translateX(100%) 移到畫面右側,這個位移在瀏覽器眼裡仍算「可捲動
   內容」,讓 #app 的 scrollWidth 變成兩倍寬(hidden 仍會建立一個看不見捲軸、
   但邏輯上可捲動的容器);之後只要有元素被 focus,瀏覽器就可能把這個容器
   捲去一個奇怪的偏移量,導致整個畫面看起來位移跑版。clip 從根本上不建立
   可捲動的語意,瀏覽器就不會有東西可捲。 */
@media(min-width:480px){ #app{height:min(920px,100dvh); align-self:center; border-radius:28px; box-shadow:0 30px 80px rgba(0,0,0,.6); border:1px solid #211D26} }

/* ============ 點擊回饋:主題化小碎紙(js/ui/confetti.js) ============
   四主題各自的形狀/顏色,一律取用既有變數,不新增色票;#app 已是
   position:relative + overflow:clip,粒子直接掛在它底下絕對定位即可 */
.confetti-bit{
  position:absolute; left:0; top:0; pointer-events:none; z-index:999;
  animation:confetti-pop .7s ease-out forwards;
}
.confetti-bit svg{width:100%;height:100%;display:block}
@keyframes confetti-pop{
  0%{ transform:translate(-50%,-50%) translate(0,0) rotate(0deg) scale(.4); opacity:0; }
  15%{ opacity:1; transform:translate(-50%,-50%) translate(calc(var(--dx) * .3),calc(var(--dy) * .3)) rotate(calc(var(--rot) * .3)) scale(1); }
  100%{ opacity:0; transform:translate(-50%,-50%) translate(var(--dx),calc(var(--dy) + 22px)) rotate(var(--rot)) scale(.8); }
}
.confetti-bit svg{fill:currentColor;stroke:none}
.confetti-sumi{color:var(--accent)}
.confetti-shiro{color:var(--accent)}
.confetti-shiro svg{fill:none;stroke:currentColor;stroke-width:1.2;stroke-linecap:round}
.confetti-neon{color:var(--accent);filter:drop-shadow(0 0 2px rgba(255,92,203,.7))}
.confetti-hoshi{color:var(--wish-char)}

button{font-family:inherit;color:inherit;background:none;border:none;cursor:pointer}
input,textarea,select{font-family:inherit;font-size:var(--fs-body-l);color:var(--text);background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-sm);padding:11px 13px;width:100%;outline:none;transition:border .2s}
input:focus,textarea:focus,select:focus{border-color:var(--accent)}
/* iOS Safari 對 <input type=date> 有自己的原生樣式(置中對齊、字型/高度與其他
   輸入框不一致),不能只靠上面的通用 input 樣式蓋過去,要逐項明確指定 */
/* <input type=time> 有跟 type=date 同一套原生樣式問題(iOS Safari 內部排版
   不吃通用 input 的 height/padding,格子邊框因此包不住內容、高度塌陷),
   套用完全相同的處理,兩者外觀才會一致 */
input[type=date],input[type=time]{
  -webkit-appearance:none;appearance:none;
  font-family:inherit;font-size:var(--fs-body-l);color:var(--text);
  height:42px;min-height:42px;line-height:18px;padding:11px 13px;
}
input[type=date]::-webkit-date-and-time-value,
input[type=time]::-webkit-date-and-time-value{ text-align:left; }

@keyframes breathe{0%,100%{border-color:var(--accent)}50%{border-color:transparent}}
[data-theme="sumi"] input:focus,[data-theme="sumi"] textarea:focus,
[data-theme="shiro"] input:focus,[data-theme="shiro"] textarea:focus,
[data-theme="hoshi"] input:focus,[data-theme="hoshi"] textarea:focus{animation:breathe 2.8s ease-in-out infinite}
textarea{resize:none;line-height:1.6}
::placeholder{color:var(--faint)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media(prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;transition-duration:.01ms!important}}
/* 頁面進背景(切 app/鎖屏)時暫停所有動畫,省電;回前景瞬間恢復,
   前景視覺完全不變(class 由 main.js 的 visibilitychange 切換)。
   transition 不暫停:回前景當下可能正有內容淡入,凍住會卡在半透明。 */
#app.bg-paused *,#app.bg-paused *::before,#app.bg-paused *::after{animation-play-state:paused!important}

/* ============ 省電模式(三段式節能) ============
   由 js/ui/settings.js 的 applyPowerSave() 在 #app 上設定 data-power=
   gentle / standard / max(關閉時移除屬性,恢復完整效果)。手機長時間使用
   發燙耗電的主因是「一直在跑」的無限迴圈環境動畫(標題流光/卡片呼吸/星塵/
   落雪/霓虹閃爍…每幀都在重繪)與 backdrop-filter 毛玻璃(GPU 持續即時合成)。
   三段是逐級包含的關係:gentle ⊂ standard ⊂ max。 */

/* ── 溫和:只關「星塵/落雪」這類環境粒子——星空主題的飄浮星塵層(#starfield-*)、
   閃爍層(#app::after),以及霜白主題聊天室頂欄的落雪(.chat-head::before/::after)。
   毛玻璃、標題流光、卡片呼吸等其餘動畫全部保留。
   註:墨金與霓虹主題沒有這類環境粒子(它們的星點/掃描線是靜態背景、不耗電),
   因此在這兩個主題選「溫和」不會有可見變化,要省電請選「標準」以上。 */
#app[data-power="gentle"] #starfield-back,
#app[data-power="gentle"] #starfield-front,
#app[data-power="standard"] #starfield-back,
#app[data-power="standard"] #starfield-front,
#app[data-power="max"] #starfield-back,
#app[data-power="max"] #starfield-front{ display:none !important; }
#app[data-power="gentle"]::after,
#app[data-power="standard"]::after,
#app[data-power="max"]::after{ animation:none !important; }
/* 霜白落雪(兩層雪點)——只有霜白主題才有,用 [data-theme="shiro"] 限定,
   避免誤傷墨金頂欄那條同樣掛在 .chat-head::after 的流動燙金底線。 */
#app[data-power="gentle"][data-theme="shiro"] .chat-head::before,
#app[data-power="gentle"][data-theme="shiro"] .chat-head::after,
#app[data-power="standard"][data-theme="shiro"] .chat-head::before,
#app[data-power="standard"][data-theme="shiro"] .chat-head::after,
#app[data-power="max"][data-theme="shiro"] .chat-head::before,
#app[data-power="max"][data-theme="shiro"] .chat-head::after{ display:none !important; }

/* ── 標準(＋最省電):凍結所有「一直在跑」的無限迴圈動畫。
   做法比照本檔既有的 prefers-reduced-motion:把 animation 壓成一次、瞬間跑完
   ——無限環境動畫因此立刻停住不再逐幀重繪;而依賴 animationend 事件的邏輯
   (例如進場動畫跑完才綁定的按鈕)仍會照常觸發,不會卡住(這是為什麼不用
   animation-play-state:paused 硬凍)。只動 animation-*,不碰 transition,所以
   點擊回饋、頁面切換、彈窗滑入等一次性互動手感完全不變。 */
#app[data-power="standard"] *, #app[data-power="standard"] *::before, #app[data-power="standard"] *::after,
#app[data-power="max"] *, #app[data-power="max"] *::before, #app[data-power="max"] *::after{
  animation-duration:.01ms !important;
  animation-iteration-count:1 !important;
}

/* ── 最省電:再關掉 backdrop-filter 毛玻璃(改吃各元件本身就有的半透明底色,
   不再即時模糊合成)與聊天背景圖的即時模糊層。這是手機 GPU 上最貴的一項。 */
#app[data-power="max"] *,
#app[data-power="max"] *::before,
#app[data-power="max"] *::after{
  backdrop-filter:none !important; -webkit-backdrop-filter:none !important;
}
#app[data-power="max"] #chatroom.has-bg::before{ filter:none !important; }

/* ============ 版面 ============ */
.view{flex:1;overflow-y:auto;display:none;flex-direction:column;padding-bottom:8px}
.view.on{display:flex}

/* 「設定 → 關於」:版權與聯絡方式集中於此(原本重複掛在五個分頁底部的
   .app-copy footer 已移除),完整條款見 repo 根目錄 LICENSE */
.about-card{gap:var(--sp-2)}
.about-brand{font-family:"GFS Didot",var(--serif);font-size:var(--fs-title-s);letter-spacing:.04em;color:var(--accent)}
.about-brand .about-sub{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.15em;margin-left:6px}
/* 內文段落裡提到 μεταξύ 本名時,比照上面的品牌標題套用同一款 GFS Didot,
   跟周圍的一般說明文字區隔開來(捐款邀請段落用) */
.about-mark{font-family:"GFS Didot",var(--serif)}
.topbar{
  padding:calc(14px + env(safe-area-inset-top)) 20px 12px; display:flex;align-items:baseline;justify-content:space-between;
  position:sticky;top:0;background:linear-gradient(var(--bg) 75%,transparent);z-index:5;
}
/* 角色頁併入設定後改為次層入口,topbar 多一顆返回鍵(比照 detail-back-btn
   語意,但沿用 topbar 一貫的 h1+sub 版型,不用整組 set-detail-head 殼);
   三個子元素改左靠齊+等距,不再用 space-between 把 sub 推到最右 */
#char-topbar{justify-content:flex-start;gap:10px}
/* 社群頁 topbar 多一顆右上角通知鈴鐺:h1+sub 維持左靠齊緊鄰(margin-right:auto
   吃掉多餘空間),鈴鐺被推到最右——跟 #char-topbar 同一招,只是方向相反 */
#comm-topbar{justify-content:flex-start;gap:8px}
#comm-topbar .sub{margin-right:auto}
#comm-notif-btn,#comm-filter-btn{position:relative;flex-shrink:0}
.comm-notif-dot{
  position:absolute;top:6px;right:6px;width:9px;height:9px;border-radius:50%;
  background:var(--accent);border:2px solid var(--bg);
}
.topbar h1{font-family:var(--serif);font-size:var(--fs-display-s);font-weight:600;letter-spacing:.08em}
.topbar h1.brand{font-family:"GFS Didot",var(--serif);font-size:var(--fs-display);letter-spacing:.04em;font-weight:500}
.topbar .sub{font-size:var(--fs-small);color:var(--faint);letter-spacing:.15em}

/* ============ 底部導覽 ============ */
#tabbar{
  display:flex; border-top:1px solid var(--line); background:var(--surface);
  padding:6px 8px calc(8px + env(safe-area-inset-bottom));
}
/* 保險:下面這些「整頁滑入」覆蓋層開著時,#tabbar 理論上已經被蓋滿
   (inset:0 + height:100dvh + z-index 較高),但手機鍵盤彈出、iOS 為了露出
   聚焦中的輸入框捲動 layout viewport 時(見 main.js pinViewport 開頭
   註解),偶爾會讓覆蓋層底部跟鍵盤頂端之間露出一截縫隙,底下的 #tabbar
   就會被看見(筆記本/收藏/社群的留言輸入框最容易踩到)。這裡多一道保險:
   任一覆蓋層開著就直接把 #tabbar 藏起來,不只靠疊層蓋住,兩者互不衝突。 */
body:has(#chatroom.open) #tabbar,
body:has(#diarybook.open) #tabbar,
body:has(#community-post.open) #tabbar,
body:has(#community-notif.open) #tabbar,
body:has(#bookclub-page.open) #tabbar,
body:has(#bookclub-room.open) #tabbar,
body:has(#game-room-page.open) #tabbar,
body:has(#game-room-session.open) #tabbar,
body:has(#char-study-page.open) #tabbar{
  visibility:hidden;
}
#tabbar button{
  flex:1; display:flex;flex-direction:column;align-items:center;gap:3px;
  padding:7px 0 5px; color:var(--faint); font-size:var(--fs-caption); letter-spacing:.1em;
  border-radius:var(--r-sm); transition:color .2s;
}
#tabbar button svg{
  width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;
  opacity:.4;transform-origin:50% 100%;transition:transform .3s ease,opacity .3s ease,color .3s ease,filter .3s ease;
}
#tabbar button.on{color:var(--accent)}
#tabbar button.on svg{opacity:1;transform:scale(1.4)}
/* 聚焦圖示的專屬質感,比照 home rail(.ri-icon)同一套「淡出/放大」邏輯,
   顏色與光暈一律取用各主題既有變數,不另外硬編碼新色票 */
[data-theme="sumi"] #tabbar button.on svg{filter:drop-shadow(0 0 4px rgba(200,164,110,.6))}
[data-theme="neon"] #tabbar button.on svg{stroke-width:1.4;filter:drop-shadow(0 0 5px rgba(255,92,203,.75))}
[data-theme="hoshi"] #tabbar button.on svg{color:var(--wish-char);filter:drop-shadow(0 0 4px rgba(174,191,242,.5))}

/* ============ 聊天列表 ============ */
.convo{
  display:flex;gap:13px;align-items:center;padding:13px 20px;transition:background .15s;width:100%;text-align:left;
}
.convo:active{background:var(--surface)}
.avatar{
  width:50px;height:50px;border-radius:17px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;font-size:25px;
  background:var(--surface2);border:1px solid var(--line);
}
.avatar svg{width:50%;height:50%}
.convo .meta{flex:1;min-width:0}
.convo .name{font-weight:500;font-size:var(--fs-body)}
.convo .last{font-size:var(--fs-small);color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:2px}
.convo .time{font-size:var(--fs-caption);color:var(--faint);align-self:flex-start;margin-top:4px}
.empty{
  text-align:center;color:var(--faint);font-size:var(--fs-body-s);line-height:2;margin:auto;padding:40px 30px;
}
.empty .big{font-family:var(--serif);font-size:var(--fs-body-l);color:var(--muted);letter-spacing:.1em}

/* ============ 聊天室 ============ */
/* 上一輪用 position:fixed 把 .chat-head 釘在視窗頂端,結果在真機 iOS Safari
   上還是會被鍵盤推走——這是已知的平台限制:鍵盤彈出時 iOS 是位移「視覺視口」
   (visual viewport),不是縮小版面,而 fixed 元素的定位基準在鍵盤動畫過程中
   會跟著視覺視口一起被推移,不是穩定釘在版面頂端(即使 --app-top 等變數量測
   得再準,量到的也只是鍵盤彈出「前」的位置)。改採真正可靠的作法:整個聊天室
   本身就是一個 100dvh 的 flex column 容器,top bar / 輸入列都是容器內的一般
   區塊(固定高度、不脫離文件流),只有中間的訊息捲動區設 flex:1;overflow-y:auto。
   dvh 縮小是瀏覽器原生就支援、且行為穩定的機制(尤其搭配 viewport meta 的
   interactive-widget=resizes-content),鍵盤彈出時整個容器變矮,多出來的壓縮量
   全部由 flex:1 的訊息區吸收,top bar 與輸入列的高度、位置完全不受影響,
   不需要額外用 JS 去追蹤/校正任何座標。 */
#chatroom{
  position:absolute;inset:0;height:100dvh;background:var(--bg);z-index:20;
  display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .32s cubic-bezier(.3,.9,.3,1);overflow:hidden;
}
#chatroom.open{transform:translateX(0)}
/* 聊天背景圖:獨立模糊圖層(不影響文字清晰度),疊一層依主題各自調整的遮罩,
   確保文字對比度足夠 */
#chatroom.has-bg::before{
  content:'';position:absolute;inset:-14px;z-index:0;pointer-events:none;
  background-image:var(--chatbg-img);background-size:cover;background-position:center;
  filter:blur(2px);   /* 只保留一點點柔化,人物輪廓需清晰可辨 */
}
/* 遮罩層:毛玻璃效果,靠 backdrop-filter 模糊,不用純色蓋住背景。
   底色維持極低透明度(0.03~0.05),讓背景圖幾乎完全透出;四主題各自設定,不共用同一組數值 */
#chatroom.has-bg::after{
  content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  background:rgba(90,60,30,.04);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);   /* 墨金:暖褐微透,照片偏暖 */
}
[data-theme="shiro"] #chatroom.has-bg::after{
  background:rgba(255,255,255,.05);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
}   /* 霜白:白色毛玻璃,務必保留模糊,不做成死白蓋板 */
[data-theme="neon"] #chatroom.has-bg::after{
  background:
    linear-gradient(rgba(30,10,40,.04),rgba(30,10,40,.04)),
    radial-gradient(circle at 12% 6%, rgba(79,227,255,.04), transparent 55%),
    radial-gradient(circle at 88% 96%, rgba(255,92,203,.04), transparent 55%);
  backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
}   /* 霓虹:深紫黑微透,保留一點螢光邊呼應主題 */
[data-theme="hoshi"] #chatroom.has-bg::after{
  background:rgba(20,26,46,.04);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
}   /* 星空:深藍灰微透,確保星芒與模糊背景交疊時仍可見 */

/* z-index 明確分層:topbar 最高、輸入列次之、訊息捲動區最低,
   確保捲動時訊息內容一律裁切在 topbar 下方,不會穿幫交疊。
   .reply-preview(引用預覽,長按訊息→回覆後跳出的那一條)原本沒有列進這組
   分層——它是 position:static 的一般文件流子元素,而 #chatroom.has-bg::before
   /::after(背景圖模糊層/毛玻璃遮罩)雖然只有 z-index:0,但兩者都是
   position:absolute(且 ::after 又是「視覺上排在最後一個子元素」的
   偽元素),static、沒有自己堆疊層級的元素永遠墊在任何有定位的元素底下,
   跟 z-index 數值大小無關——結果是引用預覽的 hidden 屬性正確拿掉、文字也
   確實有渲染,畫面上卻整條被背景圖蓋住看不到(不是「沒有引用」,是「引用
   有出現但被蓋住」)。補上 position:relative 讓它跟 .chat-input 一樣被拉進
   同一層堆疊順序,才能疊在背景圖層之上。 */
#chatroom.has-bg #msgs{position:relative;z-index:1}
#chatroom.has-bg .chat-input,#chatroom.has-bg .reply-preview{position:relative;z-index:2}
#chatroom.has-bg .chat-head{position:relative;z-index:3}
#chatroom.has-bg .chat-head,#chatroom.has-bg .chat-input,#chatroom.has-bg .reply-preview{
  background:color-mix(in srgb, var(--bg) 80%, transparent);backdrop-filter:blur(3px);
}
/* 分層:對話框與訊息氣泡加陰影浮起,陰影也依主題各自設定 */
#chatroom.has-bg .chat-head{box-shadow:0 2px 12px rgba(0,0,0,.22)}
#chatroom.has-bg .chat-input{box-shadow:0 -2px 12px rgba(0,0,0,.22)}
#chatroom.has-bg .msg .bubble,#chatroom.has-bg .lwrap .lbubble{
  box-shadow:0 4px 14px rgba(20,15,11,.45), 0 1px 3px rgba(200,164,110,.18);
}   /* 墨金:暖色深陰影帶一點金邊 */
[data-theme="shiro"] #chatroom.has-bg .msg .bubble,[data-theme="shiro"] #chatroom.has-bg .lwrap .lbubble{
  box-shadow:0 3px 10px rgba(110,103,92,.22);
}   /* 霜白:柔和淺灰陰影,避免死黑 */
[data-theme="neon"] #chatroom.has-bg .msg .bubble,[data-theme="neon"] #chatroom.has-bg .lwrap .lbubble{
  box-shadow:0 0 10px rgba(255,92,203,.3), 0 3px 10px rgba(0,0,0,.4);
}   /* 霓虹:螢光粉光暈 + 深色陰影 */
[data-theme="hoshi"] #chatroom.has-bg .msg .bubble,[data-theme="hoshi"] #chatroom.has-bg .lwrap .lbubble{
  box-shadow:0 4px 14px rgba(0,0,0,.42), 0 0 8px rgba(174,191,242,.12);
}   /* 星空:深色陰影帶一點冷色微光 */
/* 敘事文字:不加任何底色/邊框,純靠固定白字 + 描邊維持可讀性,四主題一致 */
#chatroom.has-bg .narr{
  color:rgba(255,255,255,.95);
  text-shadow:0 1px 3px rgba(0,0,0,.7), 0 0 3px rgba(0,0,0,.55);
}
.chat-head{
  display:flex;align-items:center;gap:10px;padding:calc(10px + env(safe-area-inset-top)) 12px 10px;
  border-bottom:1px solid var(--line);background:var(--bg);flex-shrink:0;
}
.chat-head .avatar{width:38px;height:38px;font-size:19px;border-radius:13px}
.chat-head .cname{font-family:var(--serif);font-size:var(--fs-body-l);font-weight:600;letter-spacing:.05em}
.chat-head .cstate{font-size:var(--fs-caption);color:var(--accent);letter-spacing:.08em}
.iconbtn{width:38px;height:38px;display:flex;align-items:center;justify-content:center;border-radius:var(--r-sm);color:var(--muted)}
.iconbtn:active{background:var(--surface2)}
.iconbtn svg{width:21px;height:21px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* #chatroom 是 flex column、top bar 與輸入列都是一般區塊(flex-shrink:0),這裡
   只要 flex:1 就會自動吃掉剩餘空間;鍵盤彈出時 #chatroom 的 100dvh 高度縮小,
   多出來的壓縮量全部由這裡吸收,top bar/輸入列完全不受影響,不需要額外補內距。
   .chat-msgs-wrap 包住 #msgs + 章節 rail + 捲到底按鈕:它自己吃 flex:1,
   #msgs 再吃滿它的高度,rail/按鈕用 position:absolute 疊在同一個範圍內,
   不必手動算 top bar/輸入列的實際高度就能精準對齊「只蓋住訊息區」。 */
.chat-msgs-wrap{position:relative;flex:1;min-height:0;display:flex}
#msgs{flex:1;overflow-y:auto;padding:18px 16px 10px;display:flex;flex-direction:column;gap:var(--sp-3)}
.msg-seg-anchor{height:0;pointer-events:none}

/* ============ 聊天室右側章節導覽(rail,js/ui/chat.js) ============
   參考主頁 rail 的呈現邏輯(捲動時淡入、閒置後淡出),但視覺改成點+線
   (不是 icon):每 5 回合對話一組,ai 濃縮成小標題,拖曳到該點時標題淡出。
   定位收在 #msgs 右內距(16px)以內的窄邊緣,避開使用者訊息列右側固定
   30px 寬的頭貼欄位,不會疊到頭貼上。 */
#chat-rail{
  position:absolute; top:6px; bottom:6px; right:1px; width:13px; z-index:6;
  display:flex; flex-direction:column; align-items:center;
  opacity:0; pointer-events:none; transition:opacity .2s ease; touch-action:none;
}
#chat-rail.show{opacity:1;pointer-events:auto}
#chat-rail[hidden]{display:none}
#chat-rail::before{
  content:''; position:absolute; top:2px; bottom:2px; left:50%; width:1.5px;
  background:var(--line); transform:translateX(-50%); z-index:-1;
}
/* flex:1(非固定 13px + flex-shrink:0)讓點位一定會平分掉整條 rail 的
   高度——聊天室的分段數會隨對話長度無上限增加(不像角色頁/設定頁的 rail
   節點數固定,永遠塞得下),點數一多沒有這行會直接撐出 top/bottom 邊界,
   最下面幾點跑到畫面外點不到 */
.cr-dot{position:relative;width:13px;flex:1 1 0;min-height:0;display:flex;align-items:center;justify-content:center}
.cr-dot-mark{width:6px;height:6px;border-radius:50%;background:var(--faint);opacity:.5;transition:background .25s ease,opacity .25s ease,transform .25s ease,box-shadow .25s ease}
.cr-dot.focus .cr-dot-mark{background:var(--accent);opacity:1;transform:scale(1.5)}
.cr-dot-label{
  position:absolute;right:100%;top:50%;transform:translate(6px,-50%);margin-right:8px;
  font-size:var(--fs-caption);color:var(--accent);white-space:nowrap;max-width:150px;overflow:hidden;text-overflow:ellipsis;
  background:color-mix(in srgb, var(--bg) 85%, transparent);
  padding:3px 9px;border-radius:9px;
  opacity:0;pointer-events:none;transition:opacity .2s ease,transform .2s ease;
}
.cr-dot.focus .cr-dot-label{opacity:1;transform:translate(0,-50%)}
[data-theme="sumi"] .cr-dot-mark{background:rgba(200,164,110,.5)}
[data-theme="sumi"] .cr-dot.focus .cr-dot-mark{box-shadow:0 0 5px rgba(200,164,110,.6)}
[data-theme="neon"] .cr-dot-mark{background:#8b84c9}
[data-theme="neon"] .cr-dot.focus .cr-dot-mark{box-shadow:0 0 6px rgba(255,92,203,.75)}
[data-theme="neon"] .cr-dot-label{border:1px solid var(--line);border-radius:2px;font-family:"DotGothic16",var(--sans);font-size:10px}
[data-theme="hoshi"] .cr-dot-mark{background:rgba(205,199,182,.5)}
[data-theme="hoshi"] .cr-dot.focus .cr-dot-mark{background:var(--wish-char);box-shadow:0 0 5px rgba(174,191,242,.5)}

/* ============ 捲到最下方按鈕 ============ */
.chat-scroll-bottom{
  position:absolute; right:14px; bottom:14px; z-index:7;
  width:38px;height:38px;border-radius:50%;
  background:var(--surface2);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;color:var(--muted);
  box-shadow:0 2px 10px rgba(0,0,0,.25);
  opacity:0;pointer-events:none;transform:translateY(6px);
  transition:opacity .2s ease,transform .2s ease;
}
.chat-scroll-bottom.show{opacity:1;pointer-events:auto;transform:translateY(0)}
.chat-scroll-bottom svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.chat-scroll-bottom:active{background:var(--surface)}
[data-theme="neon"] .chat-scroll-bottom{border-radius:8px}
[data-theme="neon"] .chat-scroll-bottom.show{box-shadow:0 2px 10px rgba(0,0,0,.25),0 0 8px rgba(255,92,203,.35)}

/* 訊息列:頭貼與內容並排的 flex 欄位(Threads 式),頭貼永遠在群組外側、絕不疊壓文字。
   同一人連續發言只在該組第一則的 .msg-avatar-slot 加 .on 顯示頭貼,其餘用等寬空白佔位維持對齊 */
/* width:100%(而非 max-width:88%)是刻意的:.msg/.lwrap 需要從這裡拿到「確定的」寬度,
   .bubble/.lbubble 上的 max-width 百分比才有穩定的解析基準,否則在 shrink-to-fit 的
   flex 容器裡形成循環依賴,部分瀏覽器(如 iOS Safari)會把短句氣泡壓縮到只容得下兩三字 */
.msg-row{display:flex;gap:var(--sp-2);width:100%;align-items:flex-start}
.msg-row.ai{align-self:flex-start}
.msg-row.me{align-self:flex-end;flex-direction:row-reverse}
.msg-row .msg,.msg-row .lwrap{flex:1;min-width:0}
.msg-avatar-slot{width:30px;height:30px;flex-shrink:0;border-radius:50%;overflow:hidden}
.msg-avatar-slot.on{
  background:var(--surface2);border:1.5px solid var(--bg);box-shadow:0 1px 5px rgba(0,0,0,.3);
  display:flex;align-items:center;justify-content:center;font-size:15px;
}
.msg-avatar-slot img{width:100%;height:100%;object-fit:cover;display:block}

.msg{display:flex;flex-direction:column;gap:var(--sp-1)}
.msg .bubble{
  position:relative;max-width:78%;padding:10px 14px;font-size:var(--fs-body);line-height:1.65;border-radius:var(--radius);
  white-space:pre-wrap;word-break:break-word;
}
.msg.me{align-items:flex-end}
.msg.ai{align-items:flex-start}
.msg.me .bubble{background:var(--accent);color:var(--accent-ink);border-bottom-right-radius:6px}
.msg.ai .bubble{background:var(--surface2);border:1px solid var(--line);border-bottom-left-radius:6px}
/* 長按訊息可加表情反應:氣泡本身不能被選取/跳出系統選字選單,才不會跟長按手勢打架 */
.msg .bubble,.lwrap .lbubble,.msg-img,.narr,.htmlblock{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}
/* 表情反應徽章:疊在氣泡外側一角的果凍玻璃膠囊——半透明毛玻璃 + 內緣高光,不傾斜。
   同一則訊息最多兩枚同時存在(見 chat.js attachReactionBadge):使用者的固定右下角
   (可點擊改/取消),角色的固定左下角(唯讀,角色自己決定);膠囊裡的迷你頭貼用來
   分辨是哪一方按的,不再只靠位置猜。 */
.msg-reaction{
  position:absolute;bottom:-11px;height:24px;padding:0 8px 0 2px;border-radius:999px;
  background:rgba(255,255,255,.16);
  -webkit-backdrop-filter:blur(7px) saturate(160%);backdrop-filter:blur(7px) saturate(160%);
  border:1px solid rgba(255,255,255,.32);
  box-shadow:0 3px 9px rgba(0,0,0,.35), inset 0 1px 1.5px rgba(255,255,255,.4), inset 0 -3px 5px rgba(0,0,0,.12);
  display:flex;align-items:center;gap:var(--sp-1);font-size:13px;line-height:1;
  z-index:2;
}
.msg-reaction.side-r{right:-6px;cursor:pointer}
/* 隱形熱區:可點擊的反應徽章本體僅 24px 高,±10px 撐大點擊範圍(不改外觀) */
.msg-reaction.side-r::after{content:'';position:absolute;inset:-10px}
.msg-reaction.side-l{left:-6px;cursor:default}
.mr-av{
  width:16px;height:16px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;font-size:10px;line-height:1;
  background:var(--surface2);border:1px solid rgba(255,255,255,.5);
}
.mr-av img{width:100%;height:100%;object-fit:cover;display:block}
.mr-emoji{font-size:13px;line-height:1}
/* 快速反應面板:長按氣泡跳出的膠囊選單,常用表符 + 加號(開系統表情鍵盤) */
.reaction-picker{
  position:absolute;z-index:10;display:flex;align-items:center;gap:2px;
  background:var(--surface);border:1px solid var(--line);border-radius:999px;
  padding:6px;box-shadow:0 10px 30px rgba(0,0,0,.4);
  opacity:0;transform:scale(.85);transition:opacity .15s,transform .15s;pointer-events:none;
}
.reaction-picker.on{opacity:1;transform:scale(1);pointer-events:auto}
.reaction-picker button{
  width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:21px;transition:transform .12s;flex-shrink:0;
}
.reaction-picker button:active{transform:scale(1.2)}
.reaction-picker button.rp-current{background:var(--accent-soft);outline:1.5px solid var(--accent)}
.reaction-picker button.add{color:var(--muted);font-size:19px;font-weight:600;background:var(--surface2)}
.reaction-picker button.quote-btn{color:var(--muted);background:var(--surface2)}
.reaction-picker button.quote-btn svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.msg .ts{font-size:var(--fs-caption);color:var(--muted);padding:0 4px}
.msg-img{position:relative;display:block;max-width:100%;border-radius:var(--radius);margin-bottom:4px;cursor:pointer}
.msg.me .msg-img{border-bottom-right-radius:6px}
.msg.ai .msg-img{border-bottom-left-radius:6px}
.lwrap .msg-img{max-width:85%;border-radius:var(--radius)}
.lwrap.lwrap-me .msg-img{align-self:flex-end;border-bottom-right-radius:6px}
/* 貼圖訊息(手機/桌機都能送出,見 js/stickers.js/js/ui/chat.js):跟一般照片
   共用 .msg-img,只是圖章尺寸,不是佔滿氣泡寬度的照片,兩邊圓角也不用比照
   訊息方向切左右尖角。 */
.msg-img.msg-sticker{width:128px;height:128px;max-width:128px;object-fit:contain;border-radius:12px;background:none;box-shadow:none}
/* 語音訊息(角色設定 > 回應風格 > 語音,見 js/ui/chat.js msgEl/applyMsgVoice):
   跟氣泡同款底色與圓角,裡面放原生 <audio controls>(不重做播放器,借瀏覽器
   內建的播放/拖曳/音量),逐字稿(角色真正說出口的文字)淡化顯示在下方。 */
.msg-voice{
  max-width:78%;padding:8px 10px;border-radius:var(--radius);margin-bottom:4px;
  background:var(--surface2);border:1px solid var(--line);
}
.msg.me .msg-voice{background:var(--accent);border-color:transparent;border-bottom-right-radius:6px}
.msg.ai .msg-voice{border-bottom-left-radius:6px}
.msg-voice audio{display:block;width:min(260px,100%);height:36px}
.msg-voice .voice-transcript{
  margin-top:6px;font-size:var(--fs-small);font-style:italic;color:var(--faint);
  line-height:1.5;white-space:pre-wrap;word-break:break-word;
}
.msg.me .msg-voice .voice-transcript{color:var(--accent-ink);opacity:.75}
.img-attach-btn{position:relative}
.img-attach-preview{position:absolute;inset:5px;border-radius:9px;overflow:hidden;display:block;pointer-events:none}
.img-attach-preview[hidden]{display:none}   /* display:block 會蓋掉 [hidden] 預設,明確補回,送出後縮圖才會換回相機圖示 */
.img-attach-preview img{width:100%;height:100%;object-fit:cover;border-radius:9px;display:block}

/* 圖片匯入確認畫面(sheet 內):置中預覽 + 加入/刪除 pill 按鈕 */
.img-confirm-preview{
  width:100%;max-height:52vh;border-radius:var(--r-lg);overflow:hidden;margin-bottom:16px;
  display:flex;align-items:center;justify-content:center;background:var(--surface2);
}
.img-confirm-preview img{width:100%;height:100%;object-fit:contain;display:block}
.day-divider{align-self:center;font-size:var(--fs-caption);color:var(--faint);letter-spacing:.15em;padding:6px 14px;background:var(--surface);border-radius:var(--r-xl);margin:4px 0}
/* 訊息串頂端的「載入更早的訊息」:聊天室只渲染最近一段訊息(見 js/ui/chat.js
   的 renderMsgs 視窗化註解),捲到頂端時這顆會自動補載,也可以直接點。
   外型沿用 .day-divider 的膠囊,改成可點擊的樣子(強調色文字 + 手指游標)。 */
.msgs-older{align-self:center;font-size:var(--fs-caption);color:var(--accent);letter-spacing:.05em;padding:7px 16px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xl);margin:6px 0;cursor:pointer}
.msgs-older:active{opacity:.6}
/* 角色用 [紀念日:...] 標籤主動記下日子時,聊天氣泡旁的小提示;沿用 .day-divider
   的膠囊外型,改用強調色跟一般日期分隔線區分開來。 */
.anni-hint,.iv-hint{color:var(--accent);border:1px solid var(--accent-soft);background:var(--accent-soft)}
/* 心聲小提示:同款膠囊,但可以點——點了原地展開成一張引言小卡,直接在對話
   流內呈現心聲本身(.iv-body,再點一次收合),跟純顯示用的 .anni-hint 區分
   開來。展開動畫用 max-height + opacity 過渡(內容最多 30 字,200px 綽綽
   有餘,不會出現過渡跳段)。 */
.iv-hint{cursor:pointer;max-width:min(420px,86%)}
.iv-hint:active{opacity:.85}
.iv-hint .iv-label{display:block}
.iv-hint .iv-label::after{
  content:'▾';display:inline-block;margin-left:5px;opacity:.55;font-size:.85em;
  transition:transform .25s ease;
}
.iv-hint.open .iv-label::after{transform:rotate(180deg)}
.iv-hint .iv-body{
  display:block;max-height:0;opacity:0;overflow:hidden;
  font-family:var(--serif);font-style:italic;font-size:var(--fs-body-s);
  letter-spacing:.02em;line-height:1.65;white-space:normal;text-align:center;
  transition:max-height .28s ease,opacity .28s ease,margin .28s ease;
}
.iv-hint.open .iv-body{max-height:200px;opacity:1;margin-top:6px}
.iv-hint .iv-body::before{content:'「'}
.iv-hint .iv-body::after{content:'」'}
/* 思考鏈:角色設定 > 回應風格 > 思考鏈開啟時,回覆前後可能各出現一段內心
   決策過程,貼在回覆氣泡的正上方(thinkBefore)或正下方(thinkAfter)——
   兩者是各自獨立的 .think-card,呼應「思考鏈穿插在動作之間」的需求(見
   js/ui/chat.js thinkCardNode/genAndRender)。
   踩過兩次雷才走到現在這版:先是半透明玻璃卡片,預設收合時只露一行細細的
   頭列被誤讀成「壓縮成一條線」,半透明底色疊在自訂聊天背景照片上淡字幾乎
   看不見;改成借心聲的膠囊配色後兩個問題都解決,但使用者更想要的其實是
   「完全不要有底色的純文字」。現在收合時無底色、無邊框,純文字的
   「[> 思考鏈]」靠左對齊,像一段可以點開的旁白提示,不是一個「元件」。
   展開後的文字調性比照長文模式敘事段落(.narr:muted 灰階、不特別加粗或
   斜體、行距寬鬆),但改成靠左對齊,左側加一條強調色引言線——沿用
   .omikuji-msg(籤詩)那套 border-left 引言線語彙,讀起來像「翻開來看」的
   旁白,不是聊天氣泡。 */
.think-card{cursor:pointer;align-self:flex-start;max-width:88%}
.think-card:active{opacity:.7}
.think-card .think-head-label{
  display:inline-block;color:var(--accent);font-size:var(--fs-caption);letter-spacing:.05em;
}
.think-card .think-head-label::after{
  content:'▾';display:inline-block;margin-left:5px;opacity:.55;font-size:.85em;
  transition:transform .25s ease;
}
.think-card.open .think-head-label::after{transform:rotate(180deg)}
.think-card .think-body{
  max-height:0;opacity:0;overflow:hidden;padding:0;
  border-left:2px solid var(--accent);
  color:var(--muted);font-size:var(--fs-body-s);line-height:1.9;
  transition:max-height .28s ease,opacity .28s ease,margin .28s ease,padding .28s ease;
}
.think-card.open .think-body{max-height:600px;opacity:1;margin-top:6px;padding:2px 0 2px 13px}
.think-card .think-line{margin:0 0 4px;font-style:normal;text-align:left;color:var(--muted)}
.think-card .think-line:last-child{margin-bottom:0}
.think-card .think-tool{
  margin:4px 0;color:var(--accent);font-style:normal;text-align:left;
  font-family:monospace;font-size:var(--fs-caption);letter-spacing:.02em;
}
.think-card .think-tool-ico{margin-right:5px;opacity:.85}
/* 展開後的敘事文字說是「比照 .narr」,但先前只抄了 .narr 的基礎樣式(muted
   灰階),漏掉 .narr 在 #chatroom.has-bg(自訂聊天背景照片)下改用固定白字
   + 描邊維持可讀性的那條覆寫規則(見上方「敘事文字」),導致背景照片底下
   var(--muted) 淡字看不清楚。收合列的「[> 思考鏈]」標籤同樣中招:上一輪
   只補了 text-shadow,顏色仍是 var(--accent)(隨主題變化的強調色),遇到
   色調跟強調色相近的照片(例如暖色調照片撞上墨金主題的金色強調色)一樣會
   糊掉。這裡兩處都改成跟 .narr 完全一致的「固定白字 + 深色描邊」,不再用
   會隨主題變化的顏色,才能保證任何照片底下都讀得出來。 */
#chatroom.has-bg .think-card .think-body,
#chatroom.has-bg .think-card .think-line,
#chatroom.has-bg .think-card .think-head-label,
#chatroom.has-bg .think-card .think-tool{
  color:rgba(255,255,255,.95);
  text-shadow:0 1px 3px rgba(0,0,0,.7), 0 0 3px rgba(0,0,0,.55);
}
/* segments 陣列直接鋪陳在對話串裡(見 js/ui/chat.js segmentFlowNodes)——
   narration 沿用上面 .narr(不用另外定義),這裡只補工具呼叫那一行:置中、
   等寬、強調色小字,"> " 前綴呼應「> 🔧 工具名」這種精簡的紀錄感,跟舊版
   .think-card .think-tool 觀感一致,但獨立存在、一開始就看得到,不用點開
   收合卡片才看得到。 */
.think-tool-flow{
  align-self:center;text-align:center;color:var(--accent);
  font-family:monospace;font-size:var(--fs-caption);letter-spacing:.02em;
  max-width:95%;
}
.think-tool-flow::before{content:'> ';opacity:.7}
.think-tool-flow .think-tool-ico{margin-right:4px;opacity:.85}
#chatroom.has-bg .think-tool-flow{
  color:rgba(255,255,255,.95);
  text-shadow:0 1px 3px rgba(0,0,0,.7), 0 0 3px rgba(0,0,0,.55);
}
/* 心聲/紀念日提示(.iv-hint/.anni-hint)是更早就存在的功能,長期以來都沒有
   針對背景照片做這層處理——同一種踩雷(強調色文字疊在色調相近的照片上
   糊掉),只是先前沒人回報。比照思考鏈剛修好的做法,一併補上。 */
#chatroom.has-bg .iv-hint .iv-label,
#chatroom.has-bg .iv-hint .iv-body,
#chatroom.has-bg .anni-hint{
  color:rgba(255,255,255,.95);
  text-shadow:0 1px 3px rgba(0,0,0,.7), 0 0 3px rgba(0,0,0,.55);
}
.typing-wrap{display:flex;gap:9px;align-items:flex-end;align-self:flex-start}
.typing-wrap .avatar{width:30px;height:30px;font-size:15px;border-radius:11px;flex-shrink:0}
.typing{display:inline-flex;gap:5px;padding:14px 16px;background:var(--surface2);border:1px solid var(--line);border-radius:var(--radius);border-bottom-left-radius:6px;align-self:flex-start}
.typing i{width:7px;height:7px;border-radius:50%;background:var(--muted);animation:blink 1.2s infinite}
.typing i:nth-child(2){animation-delay:.2s}
.typing i:nth-child(3){animation-delay:.4s}
@keyframes blink{0%,60%,100%{opacity:.25;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
.chat-input{
  position:relative;   /* 貼圇面板 position:absolute 錨定用,見下方 .sticker-picker */
  display:flex;gap:9px;align-items:flex-end;padding:10px 12px calc(12px + env(safe-area-inset-bottom));
  border-top:1px solid var(--line);background:var(--bg);flex-shrink:0;
}
.chat-input textarea{flex:1;max-height:110px;border-radius:var(--r-xl);padding:11px 15px}
.sticker-btn{flex-shrink:0}
/* 貼圇面板(手機/桌機共用):append 進 .chat-input,靠上面那行 position:relative
   錨定,不會被 #chatroom 的定位脈絡拉走(見 js/ui/chat.js openStickerPanel)。 */
.sticker-picker{
  position:absolute;bottom:calc(100% + 12px);right:0;z-index:5;
  width:min(320px,90vw);max-height:340px;overflow-y:auto;
  padding:12px;border-radius:16px;
  background:color-mix(in srgb,var(--surface) 92%,transparent);
  border:1px solid color-mix(in srgb,var(--accent) 20%,transparent);
  box-shadow:0 20px 50px rgba(0,0,0,.4);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  opacity:0;transform:translateY(8px) scale(.96);pointer-events:none;
  transition:opacity .15s ease,transform .15s ease;
}
.sticker-picker.on{opacity:1;transform:translateY(0) scale(1);pointer-events:auto}
.sticker-picker-tabs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.sticker-picker-tabs button{
  padding:5px 10px;border-radius:999px;font-size:var(--fs-caption);
  border:1px solid color-mix(in srgb,var(--line) 40%,transparent);color:var(--muted);
  background:transparent;
}
.sticker-picker-tabs button.on{
  color:var(--text);border-color:color-mix(in srgb,var(--accent) 55%,transparent);
  background:color-mix(in srgb,var(--accent) 12%,transparent);
}
.sticker-picker-body{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.sticker-pick{
  aspect-ratio:1;border-radius:10px;overflow:hidden;
  background:color-mix(in srgb,var(--surface2) 50%,transparent);
  transition:transform .12s ease,background .12s ease;
}
.sticker-pick:hover{transform:scale(1.06);background:color-mix(in srgb,var(--accent) 10%,transparent)}
.sticker-pick img{width:100%;height:100%;object-fit:contain}
.sticker-picker-empty{grid-column:1/-1;font-size:var(--fs-caption);color:var(--faint);text-align:center;padding:20px 6px}
.sendbtn{
  width:42px;height:42px;border-radius:50%;background:var(--accent);color:var(--accent-ink);
  display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:transform .15s,opacity .2s;
}
.sendbtn:disabled{opacity:.35}
.sendbtn:active{transform:scale(.9)}
.sendbtn svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

/* 引用/回覆訊息:輸入框上方的待送出引用預覽(長按訊息→選「回覆」後出現),
   送出或取消後收起。左側色條 + 引用片段文字 + 取消鈕,視覺上貼著輸入列,
   跟下面 .chat-input 共用同一塊背景,像是同一組控制項的延伸。 */
.reply-preview{
  display:flex;align-items:center;gap:9px;padding:8px 10px 8px 12px;
  border-top:1px solid var(--line);background:var(--bg);flex-shrink:0;
}
.reply-preview[hidden]{display:none}
.rp-bar{width:3px;align-self:stretch;border-radius:2px;background:var(--accent);flex-shrink:0}
.rp-text{
  flex:1;min-width:0;font-size:var(--fs-small);color:var(--faint);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.rp-cancel{width:30px;height:30px;flex-shrink:0}
.rp-cancel svg{width:16px;height:16px}

/* 快速輸入工具列(輸入列的鍵盤鈕展開):「」/換行/羈絆任務邀請。
   整條工具列本身不帶背景/邊線,只露出三顆按鈕自己的主題底色;
   position+z-index 比照 .chat-input(z:2),確保浮在聊天背景圖的
   半透明遮罩層(#chatroom.has-bg::after,z:0)之上,不會被蓋住 */
.kb-tools{
  display:flex;align-items:center;gap:8px;padding:7px 12px 2px;
  flex-shrink:0;position:relative;z-index:2;
}
.kb-tools[hidden]{display:none}
.kb-tools .kb-key{
  width:38px;height:34px;border-radius:var(--r-sm);
  background:var(--surface2);border:1px solid var(--line);
}
.kb-tools .kb-key svg{width:19px;height:19px}
#kb-quest img,#kb-post img{width:22px;height:22px;display:block;object-fit:contain}
#kb-tools-btn.on{color:var(--accent)}

/* 圖片庫(#kb-gallery 開啟,見 js/ui/chat.js openGallerySheet):
   縮圖三欄方格,點縮圖 openGalleryPreview 放大 */
.gallery-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;max-height:60vh;overflow-y:auto}
.gallery-item{aspect-ratio:1;border-radius:var(--r-sm);overflow:hidden;padding:0;border:1px solid var(--line)}
.gallery-item img{width:100%;height:100%;object-fit:cover;display:block}

/* 分日刪除聊天記錄:垃圾桶鈕彈窗裡的日期多選清單(見 js/ui/chat.js #chat-clear) */
.clear-day-list{
  max-height:38vh;overflow-y:auto;display:flex;flex-direction:column;gap:6px;margin-bottom:6px;
}
.clear-day-row{
  display:flex;align-items:center;gap:10px;padding:9px 12px;
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface2);
}
.clear-day-row input{width:18px;height:18px;accent-color:var(--accent);flex-shrink:0}
.clear-day-row .d{flex:1;font-size:var(--fs-body-s)}
.clear-day-row .n{font-size:var(--fs-caption);color:var(--faint)}

/* 已送出訊息裡的引用區塊:飽和度較低的灰階文字 + 底框,貼在該則訊息上方。
   巢狀在 .msg/.lwrap 裡時交給父層的 align-items 左右對齊;長文模式開場是
   敘事段落時(見 chat.js renderSegmentNodes)則直接是 #msgs 的頂層 flex 子項,
   沒有父層可以依賴,靠自己的 .me/.ai class 對應 align-self 定位。
   點擊可捲動回被引用的原訊息並短暫高亮(見 chat.js jumpToMsg)。 */
.msg-quote{
  max-width:78%;padding:6px 12px;margin-bottom:2px;border-radius:var(--radius);
  background:var(--surface2);border:1px solid var(--line);color:var(--faint);
  font-size:var(--fs-small);line-height:1.4;white-space:pre-wrap;word-break:break-word;
  filter:grayscale(1);cursor:pointer;
}
.msg-quote.me{align-self:flex-end}
.msg-quote.ai{align-self:flex-start}
/* 被引用的原訊息短暫高亮(點引用區塊跳轉回去時):0%/100% 刻意不宣告
   background,讓動畫從/回元素原本的底色(氣泡的 accent 或 surface2)自然
   接軌,只在中段疊上強調色,不會在動畫頭尾閃過一次透明色 */
@keyframes msg-flash{45%,55%{background:var(--accent-soft)}}
.msg-flash{animation:msg-flash 1.2s ease}

/* 霓虹:頂部/底部列改 8bit 像素 HUD——直角、階梯式像素邊框、掃描線紋理、按下有位移回饋 */
[data-theme="neon"] .chat-head,
[data-theme="neon"] .chat-input,
[data-theme="neon"] .reply-preview{
  border-radius:0;border:none;position:relative;
  background:
    repeating-linear-gradient(0deg, rgba(79,227,255,.07) 0 2px, transparent 2px 4px),
    var(--bg);
  background-color:var(--bg);
  background-clip:padding-box;
}
/* 霓虹燈管收邊:2px 實心青色線 + 三層光暈由亮到淡,約 3 秒呼吸;
   再疊一個較長週期的動畫,只動 border-bottom-color,模擬燈管偶爾閃爍失靈
   (CSS 週期性模擬,無法真的隨機,但落在題目要求的 8~12 秒區間內) */
[data-theme="neon"] .chat-head{
  border-bottom:2px solid #4FE3FF;
  animation:neon-tube-breathe 3s ease-in-out infinite, neon-tube-flicker 9s steps(2,jump-end) infinite;
}
@keyframes neon-tube-breathe{
  0%,100%{box-shadow:0 6px 10px rgba(0,0,0,.5), 0 0 6px rgba(79,227,255,.9), 0 0 14px rgba(79,227,255,.6), 0 0 24px rgba(79,227,255,.3);}
  50%{box-shadow:0 6px 10px rgba(0,0,0,.5), 0 0 9px rgba(79,227,255,1), 0 0 20px rgba(79,227,255,.8), 0 0 34px rgba(79,227,255,.45);}
}
@keyframes neon-tube-flicker{
  0%,86%,100%{border-bottom-color:#4FE3FF}
  88%,92%{border-bottom-color:rgba(79,227,255,.2)}
  90%,94%{border-bottom-color:#4FE3FF}
}
[data-theme="neon"] .chat-input{
  box-shadow:0 -2px 0 0 var(--accent), 0 -4px 0 0 rgba(79,227,255,.85), 0 -6px 10px rgba(0,0,0,.5);
}
/* 背景圖可能偏亮,topbar/底部列固定加深不透明底,螢光邊框與文字不隨照片明暗浮動 */
[data-theme="neon"] #chatroom.has-bg .chat-head,
[data-theme="neon"] #chatroom.has-bg .chat-input{
  background:
    repeating-linear-gradient(0deg, rgba(79,227,255,.07) 0 2px, transparent 2px 4px),
    color-mix(in srgb, var(--bg) 88%, transparent);
}
[data-theme="neon"] .chat-head .avatar,
[data-theme="neon"] .iconbtn{border-radius:2px}
[data-theme="neon"] .iconbtn{
  border:1px solid var(--line);box-shadow:2px 2px 0 0 rgba(79,227,255,.6);transition:none;
}
[data-theme="neon"] .iconbtn:active{
  background:var(--surface2);transform:translate(2px,2px);box-shadow:none;
}
[data-theme="neon"] .mode-seg{
  border-radius:0;border:1px solid var(--accent);box-shadow:2px 2px 0 0 rgba(79,227,255,.7);
  background:rgba(10,8,18,.85);
}
[data-theme="neon"] .mode-seg button{
  border-radius:0;font-family:var(--sans);transition:none;color:#B8B0FF;
}
[data-theme="neon"] .mode-seg button.on{
  background:var(--accent);color:var(--accent-ink);box-shadow:inset 0 0 0 2px rgba(10,8,18,.5);
}
[data-theme="neon"] .chat-input textarea{
  border-radius:2px;border:1px solid var(--line);background:var(--surface2);
  box-shadow:2px 2px 0 0 rgba(79,227,255,.55);
}
[data-theme="neon"] .sendbtn{
  border-radius:2px;box-shadow:2px 2px 0 0 rgba(10,8,18,.6), 0 0 14px rgba(255,92,203,.45);transition:none;
}
[data-theme="neon"] .sendbtn:active{
  transform:translate(2px,2px);box-shadow:0 0 14px rgba(255,92,203,.45);
}

/* 霓虹:訊息氣泡——使用者實心粉底加同色系光暈,AI 深藍紫底加青色霓虹描邊,
   圓角都改小(6px)貼近像素對話框,原本方向性的尾巴角同步變成一致的小直角 */
[data-theme="neon"] .msg.me .bubble,
[data-theme="neon"] .lwrap.lwrap-me .lbubble{
  border-radius:6px;
  box-shadow:0 0 8px rgba(255,92,203,.55), 0 0 18px rgba(255,92,203,.3);
}
[data-theme="neon"] .msg.ai .bubble,
[data-theme="neon"] .lwrap .lbubble{
  border-radius:6px;
  border:1px solid #4FE3FF;
  box-shadow:0 0 8px rgba(79,227,255,.4), 0 0 16px rgba(79,227,255,.2);
}
/* AI 氣泡入場動畫:模擬 CRT 開屏——scaleY(.6)+高亮瞬間出現,0.15 秒內彈回正常,
   途中疊一幀色偏(粉/青文字陰影各偏 1px)模擬色差,一閃即逝 */
@keyframes neon-crt-in{
  0%{opacity:0;transform:scaleY(.6);filter:brightness(2.2);text-shadow:1px 0 0 rgba(255,92,203,.8),-1px 0 0 rgba(79,227,255,.8)}
  40%{opacity:1;transform:scaleY(1.08);filter:brightness(1.3);text-shadow:1px 0 0 rgba(255,92,203,.5),-1px 0 0 rgba(79,227,255,.5)}
  70%{transform:scaleY(.98);filter:brightness(1.05)}
  100%{opacity:1;transform:scaleY(1);filter:brightness(1);text-shadow:none}
}
[data-theme="neon"] .msg-row.ai .fade-in{animation:neon-crt-in .15s ease-out}

/* 墨金:聊天室頂部列升級——深黑拉絲金屬質感(橫向髮絲紋 + 縱向底色漸層),
   底部香檳金細線收邊帶內縮光暈,金屬光帶沿 top bar 最下緣水平流動;
   #chatroom 本身也套用同一組底色,確保 safe-area-inset-top(狀態列下方)、
   safe-area-inset-bottom(.chat-input 下方)這些留白區一併是墨金的深色調,
   不會露出主題預設的 --bg 造成「沒被覆蓋到」的視覺落差。
   #app 本身有 overflow:hidden(其他主題共用,不能只為墨金拿掉),在手機等實際使用的
   窄螢幕下 #app 寬度本來就等於裝置螢幕寬度,topbar/輸入列本來就已貼齊左右邊緣,
   不需要、也無法安全地在不影響其他主題的前提下另外撐出 100vw 破版 */
[data-theme="sumi"] #chatroom{
  background-color:#0d0d0f;
  background-image:linear-gradient(180deg, #1a1a1c 0%, #0d0d0f 100%);
}
[data-theme="sumi"] .chat-head{
  border-bottom:1px solid #c9a86a;position:relative;
  background-color:#0d0d0f;
  background-image:
    repeating-linear-gradient(180deg, rgba(255,255,255,.035) 0 1px, rgba(0,0,0,.045) 1px 2px),
    linear-gradient(180deg, #1a1a1c 0%, #0d0d0f 100%);
  background-clip:padding-box;
  box-shadow:inset 0 -3px 5px -2px rgba(201,168,106,.6), inset 0 1px 0 rgba(255,255,255,.05);
}
[data-theme="sumi"] .chat-head::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:2px;pointer-events:none;
  background:linear-gradient(90deg, rgba(201,168,106,.15) 0%, rgba(255,243,214,.95) 15%, rgba(201,168,106,.15) 30%, rgba(201,168,106,.15) 100%);
  background-size:260% 100%;
  animation:sumi-head-flow 6s linear infinite;
}
@keyframes sumi-head-flow{
  0%{background-position:0% 0}
  100%{background-position:-160% 0}
}
[data-theme="sumi"] .chat-head .cname{
  background:linear-gradient(105deg,#8A6B3F 0%,#E8C87E 35%,#FFF3D6 55%,#E8C87E 75%,#8A6B3F 100%);
  background-size:220% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;
  animation:sumi-shine 7s ease-in-out infinite;
}
[data-theme="sumi"] .chat-head .avatar{
  border:1.5px solid rgba(232,200,126,.5);
  animation:sumi-head-avatar-glow 3.6s ease-in-out infinite alternate;
}
@keyframes sumi-head-avatar-glow{
  from{box-shadow:0 0 0 rgba(232,200,126,0)}
  to{box-shadow:0 0 7px rgba(232,200,126,.55)}
}
[data-theme="sumi"] #chatroom.has-bg .chat-head{
  background-image:
    repeating-linear-gradient(180deg, rgba(255,255,255,.035) 0 1px, rgba(0,0,0,.045) 1px 2px),
    linear-gradient(180deg, color-mix(in srgb, #1a1a1c 85%, transparent) 0%, color-mix(in srgb, #0d0d0f 85%, transparent) 100%);
}
/* 內嵌下凹風格:返回鍵、整理記憶、清除對話等頂部列圖示按鈕 */
[data-theme="sumi"] .chat-head .iconbtn{
  background:linear-gradient(180deg, rgba(0,0,0,.32), rgba(0,0,0,.12));
  box-shadow:inset 0 2px 3px rgba(0,0,0,.55), inset 0 -1px 1px rgba(232,200,126,.28);
}
[data-theme="sumi"] .chat-head .iconbtn:active{
  box-shadow:inset 0 3px 5px rgba(0,0,0,.75), inset 0 -1px 1px rgba(232,200,126,.18);
}
/* 長文/短句切換選中態:金屬浮凸感 */
[data-theme="sumi"] .mode-seg button.on{
  background:linear-gradient(180deg, #d4af6a, #a8843f);
  color:#1a1512;
  box-shadow:0 0 6px rgba(212,175,106,.5), inset 0 1px 0 rgba(255,255,255,.35), inset 0 -1px 2px rgba(0,0,0,.3);
}
/* 底部輸入列比照頂部列的拉絲金屬質感與金線收邊,讓 safe-area-inset-bottom
   露出的留白區同樣是墨金深色調,首尾呼應,不會露出未上色的黑底 */
[data-theme="sumi"] .chat-input{
  border-top:1px solid #c9a86a;position:relative;
  background-color:#1a1a1c;
  background-image:
    repeating-linear-gradient(180deg, rgba(255,255,255,.035) 0 1px, rgba(0,0,0,.045) 1px 2px),
    linear-gradient(180deg, #0d0d0f 0%, #1a1a1c 100%);
  background-clip:padding-box;
  box-shadow:inset 0 3px 5px -2px rgba(201,168,106,.6);
}
[data-theme="sumi"] #chatroom.has-bg .chat-input{
  background-image:
    repeating-linear-gradient(180deg, rgba(255,255,255,.035) 0 1px, rgba(0,0,0,.045) 1px 2px),
    linear-gradient(180deg, color-mix(in srgb, #0d0d0f 85%, transparent) 0%, color-mix(in srgb, #1a1a1c 85%, transparent) 100%);
}

/* 墨金:訊息氣泡——使用者側霧面金箔漸層,AI 側墨黑漆面燙金邊,
   兩者皆加浮起落影;方向性圓角維持原本規則不變 */
[data-theme="sumi"] .msg.me .bubble,
[data-theme="sumi"] .lwrap.lwrap-me .lbubble{
  background:linear-gradient(160deg, #d4b26a 0%, #b8945a 100%);
  color:#1a1512;
  box-shadow:0 2px 8px rgba(0,0,0,.4);
}
[data-theme="sumi"] .msg.ai .bubble,
[data-theme="sumi"] .lwrap .lbubble{
  background:linear-gradient(180deg, #18181c 0%, #141417 100%);
  border:1px solid rgba(201,168,106,.35);
  color:#ece6da;
  box-shadow:0 2px 8px rgba(0,0,0,.4);
}
/* .lwrap.lwrap-me .lbubble 類選擇器比 .lwrap .lbubble 更精確,兩條規則同時存在時
   使用者自己的長文對白氣泡仍會正確套用上面的金箔樣式,不會被這條 AI 樣式蓋掉 */
[data-theme="sumi"] .msg .ts,
[data-theme="sumi"] .lwrap .ts{color:rgba(201,168,106,.6)}
/* AI 氣泡入場動畫:淡入 + 輕微上移 4px,比全站預設的 fade-in(8px/0.35s)更輕巧俐落 */
@keyframes sumi-bubble-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
[data-theme="sumi"] .msg-row.ai .fade-in{animation:sumi-bubble-in .25s ease}

/* 霜白:聊天室頂部列升級——真的「落雪」,兩層雪點以不同速度向下飄形成遠近視差,
   底色維持磨砂玻璃白帶一點冰藍調;雪點層 pointer-events:none 不擋按鈕 */
[data-theme="shiro"] .chat-head{
  border-bottom:none;position:relative;z-index:2;overflow:hidden;
  border-radius:0 0 28px 28px;
  background-color:rgba(248,246,240,.72);
  background-clip:padding-box;
  backdrop-filter:blur(20px) saturate(1.2);-webkit-backdrop-filter:blur(20px) saturate(1.2);
  /* 底部弧線下方的暖白柔光落影(讓 bar 像浮起的果凍卡片),
     頂部內緣一條極細白色高光模擬果凍表面反光;z-index:2 確保陰影不會被
     捲動到頂端的訊息內容蓋過(#msgs 在一般模式下沒有設 z-index) */
  box-shadow:0 8px 24px rgba(200,190,170,.25), inset 0 1px 0 rgba(255,255,255,.8);
}
[data-theme="shiro"] .chat-head::before,
[data-theme="shiro"] .chat-head::after{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:0;
}
[data-theme="shiro"] .chat-head::before{
  background-image:
    radial-gradient(1.6px 1.6px at 12% 15%, rgba(255,255,255,.95), transparent 60%),
    radial-gradient(1.2px 1.2px at 32% 50%, rgba(225,238,252,.85), transparent 60%),
    radial-gradient(1.8px 1.8px at 58% 10%, rgba(255,255,255,.9), transparent 60%),
    radial-gradient(1.3px 1.3px at 78% 40%, rgba(225,238,252,.8), transparent 60%),
    radial-gradient(1.5px 1.5px at 92% 65%, rgba(255,255,255,.85), transparent 60%);
  background-size:150px 100px;background-repeat:repeat;
  animation:shiro-snow-far 12s linear infinite;
  opacity:.75;
}
[data-theme="shiro"] .chat-head::after{
  background-image:
    radial-gradient(1px 1px at 8% 35%, rgba(255,255,255,1), transparent 60%),
    radial-gradient(1.4px 1.4px at 26% 5%, rgba(235,244,255,.95), transparent 60%),
    radial-gradient(1px 1px at 46% 55%, rgba(255,255,255,.95), transparent 60%),
    radial-gradient(1.3px 1.3px at 68% 20%, rgba(225,238,252,.9), transparent 60%),
    radial-gradient(1px 1px at 88% 45%, rgba(255,255,255,.95), transparent 60%),
    radial-gradient(1.2px 1.2px at 96% 80%, rgba(235,244,255,.9), transparent 60%);
  background-size:120px 85px;background-repeat:repeat;
  animation:shiro-snow-near 6.5s linear infinite;
}
@keyframes shiro-snow-far{from{background-position:0 0}to{background-position:0 100px}}
@keyframes shiro-snow-near{from{background-position:0 0}to{background-position:0 85px}}
[data-theme="shiro"] .chat-head .cname{color:#6b6258;position:relative;z-index:1}
[data-theme="shiro"] .chat-head .avatar,
[data-theme="shiro"] .chat-head .cstate,
[data-theme="shiro"] .chat-head .mode-seg,
[data-theme="shiro"] .chat-head .iconbtn{position:relative;z-index:1}
[data-theme="shiro"] .chat-head .avatar{border:1px solid rgba(180,170,150,.3)}
[data-theme="shiro"] .chat-head .cstate{color:#6b6258}
[data-theme="shiro"] #chatroom.has-bg .chat-head{
  background-color:rgba(248,246,240,.6);
  backdrop-filter:blur(20px) saturate(1.2);-webkit-backdrop-filter:blur(20px) saturate(1.2);
  box-shadow:0 8px 24px rgba(200,190,170,.3), inset 0 1px 0 rgba(255,255,255,.7);
}
/* 果凍質感按鈕:奶白半透明圓角、細微內側高光,按下 Q 彈回彈(scale + 陰影變淺) */
[data-theme="shiro"] .chat-head .iconbtn{
  background:rgba(255,253,248,.55);
  border:1px solid rgba(255,255,255,.65);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.9), 0 2px 6px rgba(200,190,170,.25);
  transition:transform .35s cubic-bezier(.34,1.56,.64,1), box-shadow .35s cubic-bezier(.34,1.56,.64,1);
}
[data-theme="shiro"] .chat-head .iconbtn:active{
  transform:scale(.94);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.7), 0 1px 3px rgba(200,190,170,.18);
}
/* 長文/短句選中態:奶茶色柔和填色 + 微微上浮陰影 */
[data-theme="shiro"] .mode-seg button.on{
  background:#d8c8b0;color:#4a4238;
  box-shadow:0 2px 6px rgba(200,180,150,.35), inset 0 1px 0 rgba(255,255,255,.5);
}
/* 底部輸入列沿用基礎規則的 background:var(--bg)(本身已是不透明實色),
   這裡明確加 background-clip,跟其他三主題的補強做法一致 */
[data-theme="shiro"] .chat-input{background-color:#F5F4F1;background-clip:padding-box}

/* 霜白:訊息氣泡——使用者奶茶色果凍感,角色雲朵白蓬鬆感,
   兩者按下都有 Q 彈回彈,方向性圓角維持原本規則不變 */
[data-theme="shiro"] .msg.me .bubble,
[data-theme="shiro"] .lwrap.lwrap-me .lbubble{
  background:rgba(216,200,176,.9);
  color:#4a4238;
  box-shadow:0 4px 16px rgba(190,180,160,.2), inset 0 1px 0 rgba(255,255,255,.7);
  transition:transform .3s cubic-bezier(.34,1.56,.64,1);
}
[data-theme="shiro"] .msg.ai .bubble,
[data-theme="shiro"] .lwrap .lbubble{
  background:rgba(255,253,248,.92);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  border-radius:22px;
  box-shadow:0 4px 16px rgba(190,180,160,.2);
  transition:transform .3s cubic-bezier(.34,1.56,.64,1);
}
[data-theme="shiro"] .msg.me .bubble:active,
[data-theme="shiro"] .lwrap.lwrap-me .lbubble:active,
[data-theme="shiro"] .msg.ai .bubble:active,
[data-theme="shiro"] .lwrap .lbubble:active{
  transform:scale(.97);
}
[data-theme="shiro"] .msg .ts,
[data-theme="shiro"] .lwrap .ts{color:rgba(107,98,88,.55)}
/* AI 氣泡入場動畫:像棉花糖輕輕膨出——scale(.92)→1 + 淡入,彈性曲線,0.3 秒 */
@keyframes shiro-bubble-in{from{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}
[data-theme="shiro"] .msg-row.ai .fade-in{animation:shiro-bubble-in .3s cubic-bezier(.34,1.56,.64,1)}

/* 星空:聊天室頂部列升級——8~12 顆星分兩層各自明滅(不同步),
   其中各一顆亮星帶柔和光暈,底線維持冷藍白星塵漸層 */
[data-theme="hoshi"] .chat-head{
  border-bottom:none;position:relative;overflow:hidden;
  background:
    linear-gradient(90deg, transparent, rgba(174,191,242,.55), rgba(255,255,255,.5), rgba(174,191,242,.55), transparent) bottom / 100% 1px no-repeat,
    linear-gradient(180deg, #1E2233, #1B1B19);
  background-color:#1B1B19;
  background-clip:padding-box;
}
[data-theme="hoshi"] .chat-head::before,
[data-theme="hoshi"] .chat-head::after{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:0;
}
[data-theme="hoshi"] .chat-head::before{
  background-image:
    radial-gradient(1.2px 1.2px at 10% 30%, rgba(255,255,255,.8), transparent 60%),
    radial-gradient(1px 1px at 22% 65%, rgba(210,220,255,.7), transparent 60%),
    radial-gradient(1.3px 1.3px at 38% 20%, rgba(255,255,255,.75), transparent 60%),
    radial-gradient(1px 1px at 50% 75%, rgba(210,220,255,.6), transparent 60%),
    radial-gradient(1.1px 1.1px at 63% 45%, rgba(255,255,255,.7), transparent 60%),
    radial-gradient(2.4px 2.4px at 20% 42%, rgba(255,255,255,1), transparent 65%),
    radial-gradient(8px 8px at 20% 42%, rgba(255,255,255,.3), transparent 70%);
  animation:hoshi-head-twinkle-a 3.2s ease-in-out infinite;
}
[data-theme="hoshi"] .chat-head::after{
  background-image:
    radial-gradient(1.2px 1.2px at 75% 30%, rgba(255,255,255,.75), transparent 60%),
    radial-gradient(1px 1px at 85% 60%, rgba(210,220,255,.65), transparent 60%),
    radial-gradient(1.3px 1.3px at 92% 22%, rgba(255,255,255,.7), transparent 60%),
    radial-gradient(1px 1px at 96% 78%, rgba(210,220,255,.6), transparent 60%),
    radial-gradient(1.1px 1.1px at 68% 60%, rgba(255,255,255,.65), transparent 60%),
    radial-gradient(2.2px 2.2px at 88% 48%, rgba(255,255,255,1), transparent 65%),
    radial-gradient(7px 7px at 88% 48%, rgba(255,255,255,.28), transparent 70%);
  animation:hoshi-head-twinkle-b 4.6s ease-in-out infinite 1.1s;
}
@keyframes hoshi-head-twinkle-a{0%,100%{opacity:.5}45%{opacity:1}70%{opacity:.35}}
@keyframes hoshi-head-twinkle-b{0%,100%{opacity:.55}35%{opacity:.3}60%{opacity:1}}
[data-theme="hoshi"] .chat-head .cname{color:#ECEAE4;text-shadow:0 0 6px rgba(174,191,242,.45);position:relative;z-index:1}
[data-theme="hoshi"] .chat-head .avatar,
[data-theme="hoshi"] .chat-head .cstate,
[data-theme="hoshi"] .chat-head .mode-seg,
[data-theme="hoshi"] .chat-head .iconbtn{position:relative;z-index:1}
[data-theme="hoshi"] #chatroom.has-bg .chat-head{
  background:
    linear-gradient(90deg, transparent, rgba(174,191,242,.55), rgba(255,255,255,.5), rgba(174,191,242,.55), transparent) bottom / 100% 1px no-repeat,
    color-mix(in srgb, var(--bg) 82%, transparent);
}
[data-theme="hoshi"] .chat-input{background-color:#1B1B19;background-clip:padding-box}

/* ============ 莓:聊天室頂部列比照主 top bar 同一套糖霜漸層+巧克力米緞帶
   ============
   跟 .topbar 共用一模一樣的背景漸層、柔光呼吸動畫(ichigo-cream-flow,
   定義在前面的 token 區塊)與底部緞帶配方,只是換一個選擇器套用,視覺上
   讀起來像「同一張桌布延伸過來」而不是兩種不同的頂欄語言。.chat-head
   原本沒有 position,這裡補上才能讓兩個偽元素正確疊在它自己範圍內。 */
[data-theme="ichigo"] .chat-head{
  position:relative;
  background:linear-gradient(180deg, #FFFDFB 0%, #FCEBF0 100%);
}
[data-theme="ichigo"] .chat-head::before{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(65% 130% at 22% -25%, rgba(255,255,255,.9), transparent 62%);
  animation:ichigo-cream-flow 24s ease-in-out infinite;
}
[data-theme="ichigo"] .chat-head::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:6px;pointer-events:none;
  background:
    repeating-linear-gradient(96deg, #FF78A0 0 3px, transparent 3px 15px),
    repeating-linear-gradient(58deg, #79B8FF 0 2px, transparent 2px 18px),
    repeating-linear-gradient(124deg, #FFD166 0 2px, transparent 2px 21px),
    repeating-linear-gradient(72deg, #9CE6C4 0 2px, transparent 2px 19px),
    repeating-linear-gradient(140deg, #7B4A3A 0 1.5px, transparent 1.5px 24px);
  opacity:.85;
}
[data-theme="ichigo"] .chat-head .avatar,
[data-theme="ichigo"] .chat-head .cname,
[data-theme="ichigo"] .chat-head .cstate,
[data-theme="ichigo"] .chat-head .mode-seg,
[data-theme="ichigo"] .chat-head .iconbtn{position:relative;z-index:1}

/* 莓:使用者訊息泡泡改成極淡抹茶綠——明度/彩度刻意跟角色泡泡(--surface2
   淡粉卡)同一量級,只是換個色相,兩邊泡泡才像「同一組色卡」而不是各自
   獨立;跟 --bg(也是淡抹茶,但飽和度更低、色相偏黃)之間留了明確的
   對比落差,不會糊在背景裡。文字沿用 --text(跟角色泡泡同一顏色),
   讓兩種泡泡除了底色都共用同一套排版語言。 */
[data-theme="ichigo"] .msg.me .bubble{background:#D2EBC6;color:var(--text);border:1px solid var(--line)}
[data-theme="ichigo"] .lwrap.lwrap-me .lbubble{background:#D2EBC6;color:var(--text);border:1px solid var(--line)}
[data-theme="ichigo"] .msg.me .msg-voice{background:#D2EBC6;border-color:var(--line)}
[data-theme="ichigo"] .msg.me .msg-voice .voice-transcript{color:var(--text)}

/* ============ 日曆 ============ */
.cal-wrap{padding:2px 18px 10px;position:relative}   /* 第一層(月曆總覽)壓縮進一頁,不需捲動 */
.cal-nav{display:flex;align-items:center;justify-content:space-between;margin:2px 0 8px}
.cal-nav .month{font-family:var(--serif);font-size:var(--fs-title-s);font-weight:600;letter-spacing:.1em}
/* 「回月曆」按鈕:單日聚焦狀態才顯示,取代年月切換列的位置。
   min-height 刻意跟 .cal-nav 的實際高度(由 38px 的 .iconbtn 撐出)對齊——
   兩者互換時高度不一致會讓下方的星期列/格子跟著垂直位移幾 px,對「該週原地
   不動」的第一週路徑來說是唯一殘留的位移來源,必須讓兩者高度一致才會真的
   零位移 */
.cal-back-btn{
  display:flex;align-items:center;gap:2px;background:none;border:none;color:var(--accent);
  font-size:var(--fs-body);font-weight:500;letter-spacing:.05em;padding:6px 2px;margin:2px 0 8px;cursor:pointer;
  min-height:38px;
}
/* 星期列獨立成一行,月曆總覽與單日聚焦兩種狀態都看得到,當作視覺錨點 */
.cal-wd-row{display:grid;grid-template-columns:repeat(7,1fr);text-align:center}
.cal-wd-row .wd{font-size:var(--fs-caption);color:var(--faint);padding:3px 0;letter-spacing:.1em}
/* .cal-grid 只負責「週與週之間」的間距(縱向堆疊 6 個 .cal-week-row);
   每個 .cal-week-row 內部才是 7 欄的格子排版,拆成獨立區塊才能整週淡出/滑動 */
.cal-grid{display:flex;flex-direction:column;gap:9px}
.cal-week-row{
  display:grid;grid-template-columns:repeat(7,1fr);gap:var(--sp-1);text-align:center;
  transition:opacity .2s ease;
}
.cal-week-row.leaving{opacity:0;pointer-events:none}
.cal-week-row.hidden-week{display:none}
.cal-cell{
  aspect-ratio:1;border-radius:var(--r-sm);display:flex;flex-direction:column;align-items:center;justify-content:center;
  font-size:var(--fs-body-s);position:relative;color:var(--text);transition:background .15s;
}
.cal-cell:active{background:var(--surface2)}
.cal-cell.dim{color:var(--faint);opacity:.45}
.cal-cell.today{border:1px solid var(--accent)}
.cal-cell.sel{background:var(--accent);color:var(--accent-ink);font-weight:700}
.cal-cell .dots{display:flex;gap:3px;position:absolute;bottom:6px}
.cal-cell .dots i{width:4.5px;height:4.5px;border-radius:50%}
.dot-todo{background:var(--muted)}
.dot-period{background:var(--danger)}
.dot-period-pred{background:transparent;border:1px solid var(--danger);box-sizing:border-box}
.cal-cell.sel .dot-todo{background:var(--accent-ink)}
.cal-cell .dots svg.dot-bday{width:8px;height:8px;flex-shrink:0}
.cal-cell .dots-solo svg.dot-bday{width:10px;height:10px}
.dot-bday{color:var(--accent)}
.cal-cell.sel .dot-bday{color:var(--accent-ink)}
.period-mode .cal-cell{outline:1px dashed var(--line);outline-offset:-3px}
.cal-legend{display:flex;gap:var(--sp-4);justify-content:center;font-size:var(--fs-caption);color:var(--faint)}
.cal-legend i{width:6px;height:6px;border-radius:50%;display:inline-block;margin-right:5px;vertical-align:1px}
/* 狀態 A(月曆總覽)專屬區塊:圖例/經期紀錄模式/經期概況,彼此間距 24px+
   ——版面與資料邏輯不動 */
#cal-monthonly{display:flex;flex-direction:column;gap:12px;margin-top:12px}
#cal-monthonly .section-title{margin:0 2px}
.cal-period-row{display:flex;gap:var(--sp-2);justify-content:center}

/* ============ 狀態 B(單日聚焦):固定區吸頂 + 卡片滑動區 ============
   #cal-fixed-head 包住標題列以下、卡片以上的所有東西(回月曆/星期列/選中週)。
   只有 .cal-day-mode(JS 依 ui.calView==='day' 切在 #view-cal 上)才吸頂,
   狀態 A 不受影響——月曆總覽的 nav/星期列/格子維持原本的一般文件流。
   --cal-topbar-h / --cal-head-h 由 calendar.js 量測後設定在 #view-cal 上。 */
#cal-fixed-head{position:relative;z-index:6}
.cal-day-mode #cal-fixed-head{
  position:sticky;top:var(--cal-topbar-h,64px);
  background:var(--bg);
  padding-bottom:8px;
}
/* 單日聚焦模式:內容區往上捲時要乾淨地「沒入」固定區之下——
   1) 聚焦卡不再蓋過固定區(主頁沿用 z:7 的共用規則不動,這裡以更高
      特異度降回 2:仍高於其他非聚焦卡,但低於固定區 6 與 topbar 5;
      固定區改為不透明實色後,卡片標題貼齊吸附位置時不會再被半透明
      漸層壓暗,原本墊高 z 的理由已不存在)
   2) topbar(日曆標題列)在此模式也改不透明,漸層尾端的透明帶
      不再讓捲上來的卡片內容穿透疊在「日曆」字樣上(見 issue 截圖) */
#view-cal.cal-day-mode .snap-card.focus{z-index:2}
#view-cal.cal-day-mode .topbar{background:var(--bg)}
/* 捲動聚焦到該卡時,小標題(待辦事項/日誌・日期)亮起為主題強調色
   (比照今日籤的「今日箋」標籤;霓虹主題即螢光粉),失焦淡回 */
#cal-daydetail .section-title span{transition:color .35s ease}
#cal-daydetail .snap-card.focus .section-title span{color:var(--accent)}
[data-theme="neon"] #cal-daydetail .snap-card.focus .section-title span{text-shadow:0 0 8px rgba(255,92,203,.5)}
/* 卡片區的 scroll-snap-type 設在頁面捲動容器本身(#view-cal),只在單日聚焦時
   啟用,不影響狀態 A 的一般捲動;scroll-padding-top 讓卡片吸附在固定區下方,
   跟主頁的 #view-home 用同一套邏輯與數值語意 */
#view-cal.cal-day-mode{
  scroll-padding-top:calc(var(--cal-topbar-h,64px) + var(--cal-head-h,190px) + 14px);
}
/* 鍵盤彈出期間(日誌卡 textarea 取得焦點)暫停 snap,避免虛擬鍵盤引發的
   視窗尺寸變化跟 scroll-snap 互相打架、畫面亂跳 */
/* 鍵盤開啟期間暫停吸附:改由 JS 端把關(attachGentleSnap 的 isEnabled 檢查 .kb-open) */

/* 狀態 B 專屬區塊:今日籤/日誌/待辦,三張卡重用主頁的 .snap-card 框架
   (阻尼參數、去外框風格與主頁完全一致,定義見「共用:scroll-snap 卡片聚焦框架」)。
   .cal-card-inner 是內容淡出淡入層(切換同週日期時 0.15s 快速淡出淡入用),
   跟外層 .snap-card 的捲動聚焦縮放各自獨立,兩者才不會互相蓋掉 transform/opacity。 */
/* 底部留白讓「最後一張卡」也能捲到吸附位置:少了這段,日誌卡頂端到不了
   scroll-padding-top 的吸附線,mandatory snap 會把它彈回上一張、聚焦(標題
   亮起)永遠輪不到它(同主頁 #home-cards 的 52vh 留白邏輯) */
#cal-daydetail{display:flex;flex-direction:column;padding-top:4px;padding-bottom:42vh}
#cal-daydetail .section-title{margin:0 2px}
.cal-card-inner{opacity:0;transform:translateY(6px);transition:opacity .25s ease,transform .25s ease}
.cal-card-inner.show{opacity:1;transform:translateY(0)}
.cal-card-inner.quick-swap{transition:opacity .15s ease;transform:none}
/* 日誌卡:非聚焦時互動元件(輸入框/心情/照片按鈕)一律不可點,點卡片本身
   只會捲動至聚焦,避免手滑誤觸跳出鍵盤;聚焦後才解鎖真正可以輸入 */
#cal-group-journal:not(.focus) .journal-card,
#cal-group-journal:not(.focus) .journal-card *{pointer-events:none}
#cal-group-journal:not(.focus){cursor:pointer}
/* 上面幾個區塊都用 class/id 明訂了 display,會蓋掉瀏覽器對 [hidden] 屬性的預設 display:none,
   這裡個別補上 [hidden] 的優先權,確保 JS 用 .hidden=true/false 切換狀態時實際生效 */
.cal-nav[hidden],.cal-back-btn[hidden],#cal-monthonly[hidden],#cal-daydetail[hidden]{display:none}

/* 單日聚焦頁三張卡去外框(與主頁卡片風格一致):.omikuji/.journal-card/.todo-item
   只在這裡使用,直接改動不影響其他頁面 */
#omikuji-area .omikuji{background:none;border:none;border-radius:0;box-shadow:none;margin-top:0}
/* .journal-card 去外框改在原本的定義處直接改(見下方,唯一使用處),
   這裡不重複宣告——避免同名 class 兩處定義時,源碼順序在後的那條蓋掉這條 */
.todo-item{background:none;border:none;border-radius:0;margin-bottom:0;padding:10px 2px}
.todo-item+.todo-item{border-top:1px dashed var(--line)}

/* 今日籤 */
.omikuji{
  margin:18px 0 0;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xl);overflow:hidden;
}
.omikuji-head{
  display:flex;align-items:center;justify-content:space-between;padding:14px 18px 0;
}
.omikuji-head .label{font-size:var(--fs-caption);letter-spacing:.35em;color:var(--accent);font-weight:500}
.omikuji-date{font-family:var(--serif);font-size:44px;font-weight:700;line-height:1;padding:6px 18px 0}
.omikuji-date small{font-size:var(--fs-small);color:var(--muted);font-weight:500;margin-left:8px;letter-spacing:.1em}
.omikuji-body{padding:14px 18px 18px;display:flex;flex-direction:column;gap:var(--sp-3)}
.yiji{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.yiji>div{background:var(--surface2);border-radius:var(--r-md);padding:11px 13px;font-size:var(--fs-body-s);line-height:1.55}
.yiji b{font-family:var(--serif);font-size:var(--fs-body);display:block;margin-bottom:3px}
.yiji .yi b{color:var(--accent)}
.yiji .ji b{color:var(--danger)}
.lucky{display:flex;align-items:center;gap:10px;font-size:var(--fs-body-s);color:var(--muted)}
.lucky .swatch{width:22px;height:22px;border-radius:50%;border:2px solid var(--line);flex-shrink:0}
.omikuji-msg{
  font-family:var(--serif);font-size:var(--fs-body);line-height:1.9;color:var(--text);
  border-left:2px solid var(--accent);padding:2px 0 2px 13px;
}
.omikuji-sign{text-align:right;font-size:var(--fs-small);color:var(--faint);letter-spacing:.1em}
.pill{
  display:inline-flex;align-items:center;gap:6px;padding:9px 16px;border-radius:22px;font-size:var(--fs-body-s);
  background:var(--accent-soft);color:var(--accent);border:1px solid transparent;transition:opacity .2s;
}
.pill.ghost{background:transparent;border-color:var(--line);color:var(--muted)}
.pill.hot{background:var(--accent);color:var(--accent-ink)}
.pill:disabled{opacity:.4}
.section-title{
  font-size:var(--fs-small);letter-spacing:.3em;color:var(--faint);margin:22px 2px 10px;display:flex;align-items:center;justify-content:space-between;
}
.todo-item{
  display:flex;align-items:center;gap:11px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-md);padding:11px 13px;margin-bottom:8px;
}
.todo-check{
  width:21px;height:21px;border-radius:7px;border:1.5px solid var(--faint);flex-shrink:0;
  display:flex;align-items:center;justify-content:center;transition:all .15s;
  position:relative;
}
.todo-check::after{content:'';position:absolute;inset:-9px}   /* 隱形熱區 */
.todo-check.done{background:var(--accent);border-color:var(--accent)}
.todo-check svg{width:13px;height:13px;stroke:var(--accent-ink);stroke-width:3;fill:none;stroke-linecap:round;stroke-linejoin:round;opacity:0}
.todo-check.done svg{opacity:1}
.todo-item .txt{flex:1;font-size:var(--fs-body);min-width:0;word-break:break-word}
.todo-item .txt.done{color:var(--faint);text-decoration:line-through}
.todo-add{display:flex;gap:var(--sp-2);margin-top:4px}
.period-info{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:10px 14px;
  font-size:var(--fs-body-s);line-height:1.65;color:var(--muted);
}
.period-info b{color:var(--danger);font-weight:500}

/* ============ 角色 ============
   角色總覽/編輯已改版為卡片網格 + 全頁模式,reuse .pf-card-grid 等 class
   (見「人設:4:5 頭貼卡總覽」段落)與 .detail-page/.set-node 全頁殼,
   這裡不再需要獨立的 .char-card/.addbtn。 */

/* ============ 設定 ============ */
.set-group{margin:0 18px 22px}
.set-label{font-size:var(--fs-small);letter-spacing:.25em;color:var(--faint);margin-bottom:10px}
.set-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:15px;display:flex;flex-direction:column;gap:var(--sp-3)}
.field label{font-size:var(--fs-small);color:var(--muted);display:block;margin-bottom:6px}
.hint{font-size:var(--fs-caption);color:var(--faint);line-height:1.7}
.hint a{color:var(--accent);text-decoration:none}
.theme-row{display:grid;grid-template-columns:repeat(5,1fr);gap:7px}   /* 四主題 + 自動(跟隨系統) */
.theme-chip{
  aspect-ratio:1;border-radius:var(--r-md);border:2px solid transparent;position:relative;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;transition:border .2s;
}
.theme-chip.on{border-color:var(--accent)}
.theme-chip .c{width:16px;height:16px;border-radius:50%}
.theme-chip .n{font-family:var(--serif);font-size:var(--fs-caption);letter-spacing:.05em}


/* ============ 主頁 ============ */
.mng-row{display:flex;align-items:center;gap:9px;padding:9px 2px;border-bottom:1px dashed var(--line);font-size:var(--fs-body-s)}
.mng-row .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mng-row .sm{font-size:var(--fs-caption);color:var(--faint)}
.mng-row .mini{
  width:30px;height:30px;border-radius:9px;border:1px solid var(--line);color:var(--muted);
  display:flex;align-items:center;justify-content:center;font-size:14px;flex-shrink:0;
}
.mng-row .mini:disabled{opacity:.3}
.mng-row .mini.add{color:var(--accent);border-color:var(--accent)}


/* ============ 頭像圖片 / 長文模式 / 匯入 ============ */
.avatar{overflow:hidden}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}
/* 敘事(旁白)文字:獨立成置中、加寬的區塊,不掛頭貼,寬度比對白氣泡(.msg-row 88%)更寬,
   呼應「旁白視角」而非「說話」;預設(無背景圖)不加框,靠背景圖時才加線框樣式,見上方 has-bg 覆寫 */
.narr{position:relative;align-self:center;text-align:center;color:var(--muted);font-size:var(--fs-body-s);line-height:1.95;max-width:95%;white-space:pre-wrap;word-break:break-word}
.ts{font-size:var(--fs-caption);color:var(--muted);padding:0 4px}
.ts-center{align-self:center;text-align:center}
.msg-img-standalone{align-self:flex-start;max-width:85%}
.msg-img-standalone.me{align-self:flex-end}
.lwrap{display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.lwrap .lbubble{position:relative;max-width:85%;background:var(--surface2);border:1px solid var(--line);border-radius:var(--radius);border-bottom-left-radius:6px;padding:10px 14px;font-size:var(--fs-body);line-height:1.7;white-space:pre-wrap;word-break:break-word}
.lwrap.lwrap-me{align-items:flex-end}
.lwrap.lwrap-me .lbubble{background:var(--accent);color:var(--accent-ink);border:none;border-bottom-left-radius:var(--radius);border-bottom-right-radius:6px}

/* 霓虹:時間戳統一改為青色 8bit 字體(font-family 已由全站 --sans 繼承),帶極淡 glow */
[data-theme="neon"] .msg .ts,[data-theme="neon"] .lwrap .ts{color:#4FE3FF;text-shadow:0 0 4px rgba(79,227,255,.5)}
[data-theme="neon"] .msg.me .ts,[data-theme="neon"] .lwrap.lwrap-me .ts{color:#4FE3FF;text-shadow:0 0 4px rgba(79,227,255,.5)}
.htmlblock{width:100%;border-radius:var(--r-md);overflow:hidden;background:var(--surface)}
.st-note{font-size:var(--fs-caption);color:var(--accent);line-height:1.7;margin:-4px 0 12px;background:var(--accent-soft);border-radius:10px;padding:8px 11px}
.av-preview{display:flex;align-items:center;gap:10px}
.av-preview .avatar{width:44px;height:44px;font-size:22px;flex-shrink:0}


/* ============ 長文模式與匯入 ============ */
.avatar{overflow:hidden}
.avatar img{width:100%;height:100%;object-fit:cover;border-radius:inherit;display:block}
.narration{
  align-self:center;text-align:center;color:var(--faint);font-size:var(--fs-body-s);line-height:2;
  max-width:94%;white-space:pre-wrap;word-break:break-word;padding:2px 6px;
}
.rich{align-self:stretch;max-width:100%;overflow-x:hidden}
.rich img{max-width:100%}
.mode-seg{
  display:flex;border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;flex-shrink:0;
}
.mode-seg button{
  font-size:var(--fs-caption);letter-spacing:.08em;padding:6px 11px;color:var(--faint);transition:all .15s;
}
.mode-seg button.on{background:var(--accent);color:var(--accent-ink)}
.import-meta{font-size:var(--fs-caption);color:var(--faint);margin-top:5px;letter-spacing:.05em}


/* ============ 日誌與交換日記 ============ */
:root{ --mood-happy:#D4B36A; --mood-ok:#7FB0A5; --mood-sad:#7C93C2; }
[data-theme="shiro"]{ --mood-happy:#C99F3F; --mood-ok:#57A296; --mood-sad:#6B87B8; }
[data-theme="neon"]{ --mood-happy:#FFE14D; --mood-ok:#4FFFD7; --mood-sad:#4F9DFF; }
[data-theme="hoshi"]{ --mood-happy:#E3C77E; --mood-ok:#82CFC4; --mood-sad:#86A8EA; }
.cal-cell.mood-happy{box-shadow:inset 0 0 0 2px var(--mood-happy)}
.cal-cell.mood-ok{box-shadow:inset 0 0 0 2px var(--mood-ok)}
.cal-cell.mood-sad{box-shadow:inset 0 0 0 2px var(--mood-sad)}
.cal-cell.hasphoto{box-shadow:none}
.cal-cell .jphoto{width:30px;height:30px;border-radius:50%;object-fit:cover;display:block}
.cal-cell.mood-happy .jphoto{box-shadow:0 0 0 2.5px var(--mood-happy)}
.cal-cell.mood-ok .jphoto{box-shadow:0 0 0 2.5px var(--mood-ok)}
.cal-cell.mood-sad .jphoto{box-shadow:0 0 0 2.5px var(--mood-sad)}
.cal-cell.sel .jphoto{box-shadow:0 0 0 2px var(--accent-ink)}
/* 只用在日曆單日聚焦頁的日誌卡,依「卡片去外框」規格拿掉底色/邊框/陰影,
   內容直接浮在頁面背景上 */
.journal-card{background:none;border:none;box-shadow:none;border-radius:18px;padding:15px 0;display:flex;flex-direction:column;gap:var(--sp-3)}
.mood-row{display:flex;gap:var(--sp-2)}
.mood-btn{
  flex:1;padding:9px 0;border-radius:13px;border:1.5px solid var(--line);font-size:var(--fs-small);
  display:flex;align-items:center;justify-content:center;gap:6px;color:var(--muted);transition:all .15s;
}
.mood-btn .c{width:10px;height:10px;border-radius:50%}
.mood-btn[data-m=happy] .c{background:var(--mood-happy)}
.mood-btn[data-m=ok] .c{background:var(--mood-ok)}
.mood-btn[data-m=sad] .c{background:var(--mood-sad)}
.mood-btn.on[data-m=happy]{border-color:var(--mood-happy);color:var(--text)}
.mood-btn.on[data-m=ok]{border-color:var(--mood-ok);color:var(--text)}
.mood-btn.on[data-m=sad]{border-color:var(--mood-sad);color:var(--text)}
.jphoto-row{display:flex;align-items:center;gap:10px}
.jphoto-prev{width:52px;height:52px;border-radius:50%;object-fit:cover;border:1px solid var(--line);flex-shrink:0}
.jphoto-empty{width:52px;height:52px;display:flex;align-items:center;justify-content:center;color:var(--faint);flex-shrink:0}
.jphoto-empty svg{width:100%;height:100%}
.jr-persona-row{display:flex;align-items:center;gap:10px}
.jr-persona-row .hint{flex-shrink:0}
.jr-persona-select{flex:1}
.exchange-letter{
  background:var(--surface2);border-left:2px solid var(--accent);border-radius:6px 14px 14px 6px;
  padding:13px 15px;font-family:var(--serif);font-size:var(--fs-body-s);line-height:2;white-space:pre-wrap;word-break:break-word;
}
.exchange-letter .from{display:flex;align-items:center;gap:var(--sp-2);font-family:var(--sans);font-size:var(--fs-small);color:var(--muted);margin-bottom:8px}
.exchange-letter .from .avatar{width:26px;height:26px;font-size:14px;border-radius:9px}
.exchange-row{display:flex;gap:var(--sp-2)}
.exchange-row select{flex:1}


/* ============ 交換日記(週曆書本) ============ */
#diarybook{
  position:absolute;inset:0;background:var(--bg);z-index:24;display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .32s cubic-bezier(.3,.9,.3,1);
}
#diarybook.open{transform:translateX(0)}
#db-stage{flex:1;overflow:hidden;padding:16px 14px calc(14px + env(safe-area-inset-bottom));perspective:1800px}
.book{position:relative;height:100%;border-radius:8px 16px 16px 8px}
.book-inner{
  position:absolute;inset:0;background:var(--surface);border:1px solid var(--line);
  border-radius:8px 16px 16px 8px;overflow:hidden;
  box-shadow:inset 3px 0 8px rgba(0,0,0,.12);
}
#db-week{position:absolute;inset:0;overflow-y:auto;padding:20px 18px 28px}
.book-page{
  position:absolute;inset:0;z-index:2;background:var(--surface);border-radius:8px 16px 16px 8px;
  overflow-y:auto;padding:20px 18px 28px;transform-origin:right center;backface-visibility:hidden;
  transform:rotateY(150deg);transition:transform .6s cubic-bezier(.6,.05,.3,1);
  box-shadow:-6px 0 16px rgba(0,0,0,.3);
}
.book-page.open{transform:rotateY(0deg)}
.book-page:not(.open){pointer-events:none}
.book-cover{
  position:absolute;inset:0;z-index:3;border-radius:8px 16px 16px 8px;
  background:linear-gradient(135deg,var(--surface2),var(--surface) 55%,var(--surface2));
  border:1px solid var(--line);border-left:6px solid var(--accent);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
  transform-origin:left center;transition:transform 1s cubic-bezier(.6,.05,.3,1);
  backface-visibility:hidden;box-shadow:8px 10px 30px rgba(0,0,0,.28);cursor:pointer;
}
.book.open .book-cover{transform:rotateY(-155deg);pointer-events:none}
.cover-title{font-family:"GFS Didot",var(--serif);font-size:30px;letter-spacing:.04em;color:var(--accent)}
.cover-sub{font-family:var(--serif);font-size:var(--fs-body-s);letter-spacing:.5em;color:var(--muted);margin-left:.5em}
.cover-hint{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.2em;margin-top:16px}
.db-week-nav{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.db-week-label{font-family:var(--serif);font-size:var(--fs-body);font-weight:600;letter-spacing:.06em}
/* 每天一列、橫式呈現,今日籤直接顯示在這一層,不用點進去才看得到 */
.db-week-rows{display:flex;flex-direction:column;gap:10px}
.dbw-row{
  display:flex;align-items:stretch;gap:var(--sp-3);background:var(--surface2);border:1px solid var(--line);
  border-radius:var(--r-md);padding:11px 13px;text-align:left;min-height:64px;
}
.dbw-row.today{border-color:var(--accent)}
.dbw-row.future{opacity:.45}
.dbw-row-date{display:flex;flex-direction:column;align-items:center;justify-content:center;flex-shrink:0;width:38px}
.dbw-row-wd{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.05em}
.dbw-row-num{font-family:var(--serif);font-size:var(--fs-title-s);font-weight:600;line-height:1.3}
.dbw-row-body{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;gap:var(--sp-1)}
.dbw-row-fortune{font-size:var(--fs-small);color:var(--text);line-height:1.5}
.dbw-row-fortune b{color:var(--accent);font-weight:600}
.dbw-row-empty{font-size:var(--fs-small);color:var(--faint)}
.dbw-row-marks{display:flex;align-items:center;gap:6px}
.dbw-mood{width:7px;height:7px;border-radius:50%;display:inline-block}
.dbw-mood.mood-happy{background:var(--mood-happy)}
.dbw-mood.mood-ok{background:var(--mood-ok)}
.dbw-mood.mood-sad{background:var(--mood-sad)}
.dbw-diary-dot{width:5px;height:5px;border-radius:50%;background:var(--muted);display:inline-block}
.dbw-row-photo{width:44px;height:44px;object-fit:cover;border-radius:9px;flex-shrink:0;align-self:center}

/* 角色篩選書籤:貼著書本右側邊緣,像從書頁裡露出來的標籤;閉合(封面)時
   先隱藏,翻開封面後才淡入,選中的那個籤微微往右抽出、換成強調色 */
.db-filter-tabs{
  position:absolute;top:56px;right:-1px;z-index:4;
  display:flex;flex-direction:column;gap:7px;
  opacity:0;pointer-events:none;transition:opacity .3s ease .35s;
}
.book.open .db-filter-tabs{opacity:1;pointer-events:auto}
.db-filter-tab{
  width:34px;height:30px;border-radius:0 8px 8px 0;flex-shrink:0;
  background:var(--surface2);border:1px solid var(--line);border-left:none;
  color:var(--text);font-size:13.5px;
  display:flex;align-items:center;justify-content:center;
  transform:translateX(-9px);transition:transform .18s ease,background .18s ease,color .18s ease,border-color .18s ease;
  box-shadow:2px 2px 6px rgba(0,0,0,.18);
}
.db-filter-tab img{width:18px;height:18px;border-radius:50%;object-fit:cover}
.db-filter-tab.on{transform:translateX(0);background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
[data-theme="neon"] .db-filter-tab{border-radius:0 4px 4px 0}
/* 只鎖定 .db-paper 的「直接子層」照片(當天日誌本身的大圖),用 > 排除巢狀在
   .db-author .avatar 裡的小頭貼 img——先前用一般的後代選擇器誤選到頭貼,
   多出的 margin-bottom 把置中的頭貼往上擠,右下角露出一截底色,無法滿版 */
#db-day-content .db-paper>img{width:100%;border-radius:8px;margin-bottom:8px;display:block}
.db-compose{border:1.5px dashed var(--line);border-radius:var(--r-md);padding:13px;display:flex;flex-direction:column;gap:10px;margin-bottom:22px}
.db-compose .row{display:flex;gap:var(--sp-2)}
.db-compose .row select{flex:1}
.db-entry{margin-bottom:26px}
.db-date{
  font-family:var(--serif);font-size:var(--fs-small);color:var(--accent);letter-spacing:.2em;
  display:flex;align-items:center;gap:10px;margin-bottom:10px;
}
.db-date::after{content:'';flex:1;height:1px;background:var(--line)}
.db-paper{
  background:var(--surface2);border:1px solid var(--line);border-radius:4px 12px 12px 4px;
  padding:12px 14px;margin-bottom:10px;font-family:var(--serif);font-size:var(--fs-body-s);line-height:2;
  word-break:break-word;position:relative;
}
.db-paper.me{border-left:3px solid var(--faint)}
.db-paper.them{border-left:3px solid var(--accent)}
.db-author{display:flex;align-items:center;gap:var(--sp-2);font-family:var(--sans);font-size:var(--fs-caption);color:var(--muted);margin-bottom:7px}
.db-author .avatar{width:24px;height:24px;font-size:13px;border-radius:8px}
/* 自由文字獨立包一層,保留換行/word-break,不讓 template literal 排版用的換行縮排
   被 .db-paper 的 white-space 規則當成內容渲染,擠壓頭貼列版面 */
.db-text{white-space:pre-wrap;word-break:break-word}

/* ============ 個人資料 ============ */
.profile-row{
  display:flex;align-items:center;gap:13px;width:calc(100% - 36px);margin:0 18px 22px;
  background:var(--surface);border:1px solid var(--line);border-radius:18px;padding:14px 15px;text-align:left;
}
/* 設定頁詳細流裡的人設/API 列已由外層 .set-group 統一管間距,不再自帶左右外距 */
.set-group .profile-row{width:100%;margin:0}

/* ============ 設定頁:分類卡片輪播(狀態 A)+ 詳細流 rail(狀態 B) ============
   狀態 A 參考 Teacat 卡片視覺:大圓角直式卡橫向滑動,聚焦卡換強調色底
   (或使用者自訂背景圖,加底部漸層遮罩保字);狀態 B 為直向上滑卡片流,
   右側 #set-rail 重用聊天室 rail 的點/線/標題樣式(.cr-* 為全域 class)。 */
#set-carousel-wrap{padding:2px 0 6px}
#set-carousel{
  position:relative;display:flex;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:12px 18px 16px;scrollbar-width:none;-webkit-overflow-scrolling:touch;
}
#set-carousel::-webkit-scrollbar{display:none}
#set-carousel-hint{text-align:center;margin:0 18px}
.set-cat-card{
  position:relative;flex:0 0 min(66vw,270px);height:min(52vh,360px);
  scroll-snap-align:center;border-radius:28px;padding:22px 20px;overflow:hidden;
  display:flex;flex-direction:column;align-items:flex-start;text-align:left;
  background:var(--surface);border:1px solid var(--line);color:var(--text);
  transition:background .35s ease,color .35s ease,border-color .35s ease;
  /* 右上圓滑缺角(參考 Teacat 卡):用遮罩在右上角挖一個圓弧凹口 */
  -webkit-mask:radial-gradient(circle 34px at calc(100% - 4px) 4px, transparent 33px, #000 34px);
  mask:radial-gradient(circle 34px at calc(100% - 4px) 4px, transparent 33px, #000 34px);
}
.set-cat-card.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.set-cat-card .scc-bg{position:absolute;inset:0;background-size:cover;background-position:center;opacity:.55;transition:opacity .35s ease}
.set-cat-card .scc-bg::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.18),rgba(0,0,0,.58))}
.set-cat-card.on .scc-bg{opacity:1}
.set-cat-card.has-img{color:#fff}
.scc-sub{position:relative;font-size:var(--fs-caption);letter-spacing:.25em;opacity:.65;margin-bottom:7px}
.scc-title{position:relative;font-family:var(--serif);font-size:var(--fs-display-s);font-weight:700;line-height:1.25}
.scc-summary{position:relative;font-size:var(--fs-small);opacity:.78;margin-top:8px;line-height:1.5}
[data-theme="neon"] .set-cat-card{
  border-radius:10px;
  -webkit-mask:radial-gradient(circle 30px at 100% 0, transparent 29px, #000 30px);
  mask:radial-gradient(circle 30px at 100% 0, transparent 29px, #000 30px);
}

/* ---- 狀態 B:全頁模式(設定的單一分類詳細頁 / 角色的單一角色全頁共用) ----
   .detail-page/.detail-back-btn/.detail-full-title 是共用殼,#set-detail 與
   #char-detail 都掛這幾個 class;吸附/scrollIntoView 對齊到 sticky topbar
   下緣的偏移量各自量測寫入各自的 CSS 變數(--set-topbar-h / --char-topbar-h),
   因此 scroll-padding-top 仍要各自宣告一行。 */
#view-set{scroll-padding-top:calc(var(--set-topbar-h,64px) + 14px)}
#view-char{scroll-padding-top:calc(var(--char-topbar-h,64px) + 14px)}
.detail-page{animation:setFadeIn .32s ease both}
@keyframes setFadeIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.set-detail-head{padding:2px 18px 6px}
.detail-back-btn{align-self:flex-start;padding:7px 13px;font-size:var(--fs-small)}
.detail-full-title{font-family:var(--serif);font-size:var(--fs-display);font-weight:700;margin:14px 2px 18px;letter-spacing:.02em}
/* 設定頁專屬:分類詳細頁一次只顯示點選的那個分類 */
#set-detail .set-sec{display:none}
#set-detail .set-sec.active{display:block}
.sticker-set-row{margin-bottom:18px}
.sticker-set-head{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.sticker-set-head b{font-family:var(--serif);font-size:var(--fs-body-s)}
.sticker-set-head small{color:var(--faint);font-size:var(--fs-caption);flex:1}
.sticker-set-thumbs{display:grid;grid-template-columns:repeat(5,1fr);gap:8px}
.sticker-set-cell{display:flex;flex-direction:column;gap:4px}
.sticker-set-thumb{width:100%;aspect-ratio:1;object-fit:contain;border-radius:8px;background:var(--surface2)}
.sticker-set-label{width:100%;box-sizing:border-box;padding:4px 6px;font-size:var(--fs-caption);text-align:center;border-radius:6px}
/* 全頁模式:去掉卡片邊框與小標籤,內容直接落在頁面上 */
#set-detail .set-label{display:none}
#set-detail .set-card{background:transparent;border:0;border-radius:0;padding:0}
.set-node{margin-bottom:34px;scroll-margin-top:10px}
/* 角色狀態/角色選歌單(Spotify)與須彌文字大小只有桌機版才有作用(狀態
   顯示在桌機左側角色列表、Spotify 歌單靠桌機左下播放器、文字大小只放大
   桌機須彌工作台),手機版直接不出現這三張卡,見 styles/desktop.css 同一
   斷點內的對應覆寫規則 */
.set-node[data-node="status"],
.set-node[data-node="spotify"],
.set-node[data-node="theme-fontscale"]{display:none}
.set-node-title{font-family:var(--serif);font-size:var(--fs-title-s);font-weight:600;margin-bottom:10px}
/* 節點卡片化,聚焦縮放/翻頁手感與首頁同一套(scroll-cards.js + 共用
   .snap-card 樣式):設定頁各分類與角色全頁的欄位卡都吃這條規則。
   一律比照主頁乾淨無底色風格(不加卡皮),靠間距與聚焦縮放區分卡片 */
.set-node.snap-card{background:none;border:0;border-radius:0;padding:4px 2px 0}
/* 角色全頁:版面間距由 #char-detail-body 統一給左右內距。
   底部留 34vh 吸附空間(比照主頁 #home-cards 的 52vh):沒有這段的話,
   後面幾張卡的吸附目標會被捲動上限夾住,翻頁落點跟 rail 圓點對不上 */
#char-detail-body{padding:14px 18px 34vh}
/* 吸附線統一:全域 .set-node 的 scroll-margin-top:10px 會讓 rail 點按的
   scrollIntoView 落點比翻頁式吸附低 10px,放開手後又被吸回去跳一下 */
#char-detail .set-node{scroll-margin-top:0}
/* 返回鍵列跟 topbar 一起釘住(不隨內容捲走),讓吸附線在整段捲動過程中
   維持同一個常數,見 worldbook.js 的 charSnapOffset() 說明 */
#char-detail .set-detail-head{
  position:sticky;top:var(--char-topbar-h,64px);z-index:5;
  background:var(--bg);
}
/* 全頁卡片內的 .field 之間補回間距(原本只在 #sheet 彈層裡有,見下方
   #sheet .field 規則;卡片版沒有彈層可依附,這裡各自補一份) */
#set-detail .field,#char-detail .field{margin-bottom:14px}
#setbg-clear[hidden]{display:none}
#set-footer{margin:auto 18px 14px;padding-top:26px;text-align:center}
/* 關於區的超連結:原本是瀏覽器預設藍,跟四個主題都不搭——統一改用主題
   強調色;霜白的 accent(#6E675C)在淺底上偏淡,再壓深一階拉出可讀性 */
#set-footer a{color:var(--accent);text-decoration:underline;text-underline-offset:2px}
[data-theme="shiro"] #set-footer a{color:#4A443B}
#set-top-btn{
  display:none;position:absolute;right:14px;bottom:calc(78px + env(safe-area-inset-bottom, 0px));z-index:8;
  width:38px;height:38px;border-radius:50%;
  background:var(--surface2);border:1px solid var(--line);
  align-items:center;justify-content:center;color:var(--muted);
  box-shadow:0 2px 10px rgba(0,0,0,.25);
  opacity:0;pointer-events:none;transform:translateY(6px);
  transition:opacity .2s ease,transform .2s ease;
}
#view-set.on ~ #set-top-btn{display:flex}
#set-top-btn.show{opacity:1;pointer-events:auto;transform:translateY(0)}
#set-top-btn svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
#set-top-btn:active{background:var(--surface)}
[data-theme="neon"] #set-top-btn{border-radius:8px}

/* ---- 下拉換裝:置中選項 + 上下兩條光線(lsel,見 settings.js enhanceSelects) ----
   亮色系(墨金/霜白/星空)光線帶「閃爍光芒」掃過;霓虹主題改為霓虹燈管
   (實線+粉紫外暈,掃光換青色),與 pfx/時間戳等既有霓虹語彙一致 */
.lsel{margin:2px 0}
.lsel-line{
  display:block;height:1.5px;position:relative;overflow:hidden;border-radius:1px;
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--accent) 75%,transparent) 16%,color-mix(in srgb,var(--accent) 75%,transparent) 84%,transparent);
}
.lsel-line::after{
  content:'';position:absolute;top:0;bottom:0;left:0;width:30%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.85),transparent);
  transform:translateX(-160%);animation:lselSweep 3.4s ease-in-out infinite;
}
@keyframes lselSweep{0%{transform:translateX(-160%)}55%,100%{transform:translateX(430%)}}
[data-theme="neon"] .lsel-line{
  background:var(--accent);
  box-shadow:0 0 7px rgba(255,92,203,.6),0 0 15px rgba(255,92,203,.3);
}
[data-theme="neon"] .lsel-line::after{background:linear-gradient(90deg,transparent,rgba(79,227,255,.85),transparent)}
.lsel-cur{
  width:100%;height:42px;padding:0 8px;background:none;border:0;color:var(--text);
  font-size:var(--fs-body-s);font-weight:600;
  display:flex;align-items:center;justify-content:center;gap:7px;
}
.lsel-caret{color:var(--faint);font-size:12px}
/* 展開=滾輪:選項上下滑動,光線固定中央,滑到兩線之間即選取(settings.js
   enhanceSelects);上下緣淡出遮罩做出轉輪視覺,行高 42px 與 JS LSEL_ROW 同步 */
.lsel-wheelwrap{position:relative}
.lsel-wheel{
  height:210px;overflow-y:auto;scroll-snap-type:y mandatory;
  scrollbar-width:none;overscroll-behavior:contain;
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 22%,#000 78%,transparent);
  mask-image:linear-gradient(180deg,transparent,#000 22%,#000 78%,transparent);
}
.lsel-wheel::-webkit-scrollbar{display:none}
.lsel-pad{height:84px;flex-shrink:0}
.lsel-opt{
  display:flex;align-items:center;justify-content:center;
  width:100%;height:42px;background:none;border:0;
  color:var(--faint);font-size:var(--fs-body-s);scroll-snap-align:center;
  transition:color .15s ease;
}
.lsel-opt.on{color:var(--text);font-weight:600}
.lsel-wheelwrap .lsel-line{position:absolute;left:0;right:0;pointer-events:none}
.lsel-wheelwrap .lsel-line.lt{top:calc(50% - 21px)}
.lsel-wheelwrap .lsel-line.lb{top:calc(50% + 21px)}

/* ---- 滑動開關(checkbox 換皮) ---- */
input.switch{
  appearance:none;-webkit-appearance:none;width:46px;height:26px;border-radius:13px;
  background:var(--surface2);border:1px solid var(--line);position:relative;
  flex-shrink:0;margin:0;cursor:pointer;transition:background .2s ease,border-color .2s ease;
}
input.switch::after{
  content:'';position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;
  background:var(--muted);transition:transform .2s ease,background .2s ease;
}
input.switch:checked{background:var(--accent);border-color:var(--accent)}
input.switch:checked::after{transform:translateX(20px);background:var(--accent-ink)}

/* ---- 人設:4:5 頭貼卡總覽 + 在頁編輯 ---- */
.pf-card-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}
.pf-card{
  position:relative;aspect-ratio:4/5;border-radius:var(--r-lg);overflow:hidden;
  background:var(--surface);border:1px solid var(--line);
  display:flex;align-items:flex-end;justify-content:flex-start;padding:0;text-align:left;
}
.pf-card-img{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--faint)}
.pf-card-img img{width:100%;height:100%;object-fit:cover;display:block}
.pf-card-img svg{width:34%;height:auto}
.pf-card-name{
  position:relative;width:100%;padding:22px 12px 10px;font-family:var(--serif);font-weight:600;
  font-size:var(--fs-body);color:#fff;
  background:linear-gradient(180deg,transparent,rgba(0,0,0,.62));
  display:flex;align-items:baseline;gap:7px;
}
.pf-card:not(.has-img) .pf-card-name{color:var(--text);background:none}
.pf-card-name em{font-style:normal;font-size:var(--fs-caption);color:var(--accent);letter-spacing:.08em}
.pf-card.active{border-color:var(--accent)}
.pf-card-add{align-items:center;justify-content:center;border-style:dashed;color:var(--faint);font-size:var(--fs-small);line-height:1.7}
.pf-editor .set-node-title{display:flex;align-items:baseline;gap:8px}
.pf-editor .set-node-title .em{font-size:var(--fs-caption);color:var(--accent);font-family:var(--sans);letter-spacing:.08em}

/* ---- 角色:總覽網格(reuse .pf-card-grid)+ 長按拖曳排序分身 ---- */
#char-grid-wrap{padding:2px 18px 6px}
#char-grid-hint{text-align:center;margin:10px 0 0}
.pf-card-emoji{font-size:40px;line-height:1}

/* ---- 角色全頁:頭像/背景大圖 hero 卡(名字併入頭像卡,點擊即改) ----
   4:5 大圖無框無底色,名字改為緊貼圖片下方的大字可編輯欄位;頭貼/背景
   未設定時播放佔位動畫(assets/dino.mp4/webm,見 worldbook.js HERO_ANIM)。 */
.char-hero{
  position:relative;width:100%;aspect-ratio:4/5;border-radius:var(--r-xl);
  overflow:hidden;background:var(--surface2);
  display:flex;align-items:center;justify-content:center;
}
.char-hero img,.char-hero video{width:100%;height:100%;object-fit:cover;display:block}
.char-hero-name{
  width:100%;background:none;border:0;padding:14px 2px 2px;
  font-family:var(--serif);font-size:var(--fs-display-s);font-weight:700;color:var(--text);
}
.char-hero-name:focus{outline:none}
.char-hero-name::placeholder{color:var(--faint)}
.char-hero-actrow{display:flex;gap:9px;align-items:center;margin-top:8px;flex-wrap:wrap}
.char-hero-actrow .hero-rm{margin-left:auto}   /* 移除圖片/移除背景靠右 */
.char-emoji-input{width:78px;flex-shrink:0;text-align:center}
/* 背景圖片卡的主題插槽列(通用+四主題,reuse .tag 圓角小籤);
   ● 標記 = 目前主題的聊天室實際在用的那個插槽 */
.bg-slot-row{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:10px}
.bg-live-dot{width:5px;height:5px;border-radius:50%;background:var(--accent);display:inline-block;margin-left:5px;vertical-align:2px}
/* 長按觸發拖曳後,本尊從 DOM 移除、這顆 fixed 定位的複製品跟著手指走 */
.pf-card-ghost{
  z-index:60;pointer-events:none;transform:scale(1.06);
  box-shadow:0 10px 28px rgba(0,0,0,.38);opacity:.96;
}
/* 人設編輯卡的收合式細項:收合=方圓角框只放標題;展開=框轉為靠左引用線,
   欄位完整展開可編輯,下方細項留在原位被自然下推(grid-template-rows 動畫) */
.pfx{
  border:1px solid var(--line);border-radius:var(--r-md);margin-bottom:10px;
  transition:border-color .25s ease,border-radius .25s ease,border-left-width .25s ease,box-shadow .25s ease;
}
/* 細項標題框/商店橫條:邊框配合主題色,亮色系走光澤(頂緣高光+柔和外暈),
   霓虹主題走霓光(粉紫外暈+青色內暈) */
.pfx,.bond-bar{
  border-color:color-mix(in srgb, var(--accent) 42%, var(--line));
  background-image:linear-gradient(180deg, color-mix(in srgb, var(--accent) 9%, transparent), transparent 46%);
}
[data-theme="sumi"] .pfx,[data-theme="sumi"] .bond-bar{box-shadow:inset 0 1px 0 rgba(255,255,255,.07),0 0 7px rgba(200,164,110,.15)}
[data-theme="shiro"] .pfx,[data-theme="shiro"] .bond-bar{box-shadow:inset 0 1px 0 rgba(255,255,255,.85),0 1px 6px rgba(110,103,92,.14)}
[data-theme="neon"] .pfx,[data-theme="neon"] .bond-bar{
  border-color:rgba(255,92,203,.55);
  box-shadow:0 0 9px rgba(255,92,203,.32), inset 0 0 7px rgba(79,227,255,.12);
}
[data-theme="hoshi"] .pfx,[data-theme="hoshi"] .bond-bar{box-shadow:inset 0 1px 0 rgba(255,255,255,.09),0 0 7px rgba(205,199,182,.18)}

/* ============ 資料頁:樹狀兩區(匯出資料 / 危險區域)============
   舊的 .data-actions 等距排列保留(其他地方仍可能沿用);資料頁改為兩張
   .set-node snap-card,清除類操作集中到 .danger-zone。 */
.data-actions{display:flex;flex-direction:column;gap:14px}
.data-actions>*{margin:0}
.data-item{display:flex;flex-direction:column}

/* 匯出資料卡:兩顆等寬同款主按鍵並排(Log in with Google / Upload to Google
   Drive),flex:1 各佔一半、外框式 ghost、文字金色;align-items:stretch 讓兩顆
   即使文字長短不一也同高。 */
.data-cloud-row{display:flex;align-items:stretch;gap:10px}
.dc-btn{flex:1;min-width:0;justify-content:center;text-align:center;font-size:var(--fs-small);line-height:1.3;padding-left:10px;padding-right:10px}
.pill.ghost.dc-btn{color:var(--accent);border-color:color-mix(in srgb, var(--accent) 45%, var(--line))}
.dc-btn.on{background:var(--accent-soft)}
/* 說明文字裡的按鍵名以強調色標記,對應上面兩顆按鍵 */
.dc-key{color:var(--accent);font-weight:600}
/* Google Drive 手動面板:預設收合(grid 0fr),點 icon 方鈕展開;展開後比照 pfx
   靠左引用線樣式。收合時無框、零高度,不留空盒。 */
.gd-panel{overflow:hidden}
.gd-panel-body{display:grid;grid-template-rows:0fr;transition:grid-template-rows .28s ease}
.gd-panel.open .gd-panel-body{grid-template-rows:1fr}
.gd-panel-inner{overflow:hidden;min-height:0}
.gd-panel.open .gd-panel-inner{padding:12px 0 2px 14px;border-left:2.5px solid var(--accent)}
.gd-panel-inner textarea,.gd-panel-inner input{width:100%}

/* 危險區域(Danger Zone):清除類操作集中一區,以危險色細框圈起,與匯出資料
   視覺上明確分隔。 */
.danger-title{color:var(--danger);letter-spacing:.02em}
.danger-zone{
  display:flex;flex-direction:column;gap:14px;
  border:1px solid color-mix(in srgb, var(--danger) 38%, var(--line));
  border-radius:var(--r-lg);padding:14px;
  background:color-mix(in srgb, var(--danger) 5%, transparent);
}
.danger-zone>*{margin:0}

/* ============ 帳號與雲端同步卡(Google 登入)============ */
.sync-title{font-family:var(--serif);font-size:var(--fs-body-l);letter-spacing:.04em;color:var(--text)}
.sync-acct{display:flex;align-items:center;gap:12px}
.sync-photo{width:42px;height:42px;border-radius:50%;flex-shrink:0;border:1px solid var(--line);object-fit:cover}
.sync-acct-meta{min-width:0;flex:1}
.sync-acct-name{font-weight:600;font-size:var(--fs-body)}
.sync-acct-email{font-size:var(--fs-small);color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pfx-head{
  display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  padding:13px 14px;background:none;border:0;color:var(--text);
  font-size:var(--fs-body-s);font-weight:600;
}
.pfx-hint{font-size:var(--fs-caption);color:var(--faint);font-weight:400;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pfx-chev{margin-left:auto;color:var(--faint);flex-shrink:0;transition:transform .25s ease}
.pfx.open,[data-theme] .pfx.open{
  border-color:transparent;border-left-color:var(--accent);border-left-width:2.5px;border-radius:0;
  box-shadow:none;background-image:none;
}
.pfx.open{border-left-style:solid}
.pfx.open .pfx-chev{transform:rotate(90deg);color:var(--accent)}
.pfx-body{display:grid;grid-template-rows:0fr;transition:grid-template-rows .28s ease}
.pfx-inner{overflow:hidden;min-height:0;padding:0 14px}
.pfx.open .pfx-body{grid-template-rows:1fr}
.pfx.open .pfx-inner{padding-bottom:13px}
.pfx-inner textarea,.pfx-inner input,.pfx-inner select{width:100%}
/* 例外:收合區塊「裡面」的滑動開關要維持固定尺寸——上面那條 width:100% 較晚
   宣告會贏過 input.switch 的 46px,開關被拉滿整行、旁邊標題被擠成直行字
   (離線推播的分類列就踩到這個),用更高特異度蓋回來 */
.pfx-inner input.switch{width:46px}
/* 開關型細項(回應風格):標題按鈕與開關並排同一列,開關獨立於收合按鈕
   之外,可以直接點擊切換而不觸發展開/收合(按鈕不能巢狀互動元件) */
.pfx-head-row{display:flex;align-items:center;gap:10px;padding:13px 14px}
.pfx-head-txt{
  flex:1;min-width:0;display:flex;align-items:center;gap:8px;
  background:none;border:0;padding:0;color:var(--text);
  font-size:var(--fs-body-s);font-weight:600;text-align:left;
}
.pfx.pfx-toggle .pfx-inner{padding-top:2px}

/* ---- 心意商店:目錄 pfx 收合列(標題放大;展開後同一行標題直接可編輯,
   維持 19px;收合時唯讀、點名字=展開) ---- */
.bond-item .bond-item-head{gap:10px}
.bi-name-edit{
  flex:1;min-width:0;background:none;border:0;padding:0;
  font-family:var(--serif);font-size:var(--fs-title-s);font-weight:600;color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.bi-name-edit:focus{outline:none}
.bi-name-edit::placeholder{color:var(--faint)}
.bi-name-edit[readonly]{cursor:pointer}
.bi-toggle{
  display:flex;align-items:center;gap:8px;flex-shrink:0;
  background:none;border:0;padding:0;color:var(--text);
}
.bi-cost{font-size:var(--fs-caption);color:var(--accent);letter-spacing:.05em}
.bond-item .pfx-chev{margin-left:0}
.bond-item .acts{display:flex;gap:9px;justify-content:flex-end;margin-top:4px}
.bond-item .acts .danger{color:var(--danger)}
/* 目錄項目縮小:名稱字體、收合列內距與外框圓角一併縮一號,列表更精簡 */
.bond-item{border-radius:var(--r-sm);margin-bottom:7px}
.bond-item .bond-item-head{padding:9px 11px}
.bond-item .bi-name-edit{font-size:var(--fs-body)}
.bond-item .bi-cost{font-size:var(--fs-caption)}
/* 商店目錄卡:標題與「新增道具」按鍵同一行,按鍵靠右 */
.bond-cat-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px}
.bond-cat-head .set-node-title{margin:0}
#bond-cat-add{flex-shrink:0}

/* ---- 心意商店:目錄橫條 + 展開編輯 ---- */
.bond-bar{
  width:100%;display:flex;align-items:center;gap:10px;margin-bottom:8px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:13px 14px;text-align:left;
}
.bond-bar .nm{flex:1;min-width:0;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bond-bar .cost{flex-shrink:0;font-size:var(--fs-small);color:var(--accent)}
.bond-bar .chev{flex-shrink:0;color:var(--faint);transition:transform .2s ease}
.bond-bar.open{border-color:var(--accent)}
.bond-bar.open .chev{transform:rotate(90deg)}
.bond-bar-editor{
  background:var(--surface);border:1px solid var(--accent);border-radius:var(--r-lg);
  padding:15px;margin:-2px 0 10px;display:flex;flex-direction:column;gap:var(--sp-3);
}
.bond-bar-editor .acts{display:flex;gap:10px;justify-content:flex-end}
.bond-bar-editor .acts .danger{color:var(--danger)}

/* ---- 主題:迷你介面預覽卡 ---- */
#theme-row{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.theme-prev{padding:0;border:0;background:none;display:flex;flex-direction:column;align-items:center;gap:7px}
.tp-screen{
  width:100%;aspect-ratio:9/14;border-radius:12px;border:1.5px solid var(--line);
  padding:8px;display:flex;flex-direction:column;gap:5px;overflow:hidden;
  transition:border-color .2s ease,box-shadow .2s ease;
}
.theme-prev.on .tp-screen{border-color:var(--accent);box-shadow:0 0 0 2.5px var(--accent-soft),0 4px 14px rgba(0,0,0,.18)}
.tp-dot{width:9px;height:9px;border-radius:50%;margin-bottom:1px}
.tp-line{height:4px;border-radius:2px;width:72%;opacity:.55}
.tp-line.short{width:45%}
.tp-bubble{height:13px;border-radius:7px;width:62%;margin-top:auto}
.tp-bubble.me{align-self:flex-end;margin-top:5px}
.tp-name{font-family:var(--serif);font-size:var(--fs-caption);letter-spacing:.06em;color:var(--muted)}
.theme-prev.on .tp-name{color:var(--accent);font-weight:700}

/* ---- 主題:每張分類卡的背景管理格 ---- */
#setbg-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:9px}
.setbg-tile{
  position:relative;aspect-ratio:3/4;border-radius:var(--r-sm);overflow:hidden;
  background:var(--surface);border:1px dashed var(--line);padding:0;
  display:flex;align-items:center;justify-content:center;flex-direction:column;gap:4px;
  color:var(--faint);font-size:var(--fs-caption);
}
.setbg-tile img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.setbg-tile .t{position:relative;padding:1px 5px;border-radius:5px}
.setbg-tile.has .t{color:#fff;background:rgba(0,0,0,.45)}
.setbg-tile.has{border-style:solid}
.setbg-tile .x{
  position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;
  background:rgba(0,0,0,.55);color:#fff;font-size:12px;line-height:20px;text-align:center;
}

/* .detail-rail:圓點+線導覽,設定頁(#set-rail)與角色頁(#char-rail)共用
   同一套樣式;「哪個 view 顯示才出現」這件事仍要各自寫(CSS 沒辦法泛化
   相鄰選擇器要認哪個 view id),display:none 的預設值就是防呆這裡。 */
.detail-rail{
  display:none;position:absolute;top:50%;right:1px;width:13px;height:min(44vh,320px);
  transform:translateY(-50%);z-index:8;
  flex-direction:column;align-items:center;justify-content:space-evenly;
  opacity:0;pointer-events:none;transition:opacity .2s ease;touch-action:none;
}
#view-set.on + .detail-rail{display:flex}
#view-char.on + .detail-rail{display:flex}
#view-set.on + .detail-rail[hidden],
#view-char.on + .detail-rail[hidden]{display:none}
.detail-rail.show{opacity:1;pointer-events:auto}
.detail-rail::before{
  content:'';position:absolute;top:2px;bottom:2px;left:50%;width:1.5px;
  background:var(--line);transform:translateX(-50%);z-index:-1;
}
.profile-row .avatar{width:48px;height:48px;font-size:24px;border-radius:var(--r-lg);flex-shrink:0}
.profile-row .pname{font-family:var(--serif);font-size:var(--fs-body-l);font-weight:600}
.profile-row .psub{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.1em;margin-top:2px}
.profile-row .chev{margin-left:auto;color:var(--faint);font-size:20px}


/* ============ 角色編輯:標籤/紀念日 ============
   基本設定/回應風格/於你我之間/過往記憶已改版為獨立全頁卡片(.set-node),
   不再是同一頁裡的收合 <details>,原本的 .cs-sec 樣式退役。 */

/* 過往記憶:書背式直立書架——每則記憶是一本立起來的書,書背直書日期;
   超過 5 本自動改「交疊模式」(JS 動態算步距讓整排塞進書架寬度,見
   worldbook.js 的 renderMemBook),點一本抽出、下方展開內文編輯面板 */
.mem-book{margin:10px 0}
.mem-shelf{display:flex;align-items:flex-end;gap:9px;padding:12px 4px 2px;overflow-x:auto;scrollbar-width:none}
.mem-shelf::-webkit-scrollbar{display:none}
/* 超過 7 本:書架本身橫向捲動選書,右緣淡出遮罩提示還沒滑到的書背;
   scroll-snap 讓每次滑動自然停在某一本書背的邊界上,手感更像抽書 */
.mem-shelf.scroll{
  scroll-snap-type:x proximity;
  -webkit-mask-image:linear-gradient(90deg,#000 92%,transparent);
  mask-image:linear-gradient(90deg,#000 92%,transparent);
}
.mem-shelf.scroll .mem-spine{scroll-snap-align:start}
.mem-spine{
  position:relative;width:44px;height:148px;flex-shrink:0;border-radius:9px;
  writing-mode:vertical-rl;display:flex;align-items:center;padding:11px 0;
  font-family:var(--serif);font-size:var(--fs-caption);letter-spacing:.06em;color:var(--text);
  border:1px solid color-mix(in srgb, var(--accent) 42%, var(--line));
  background:var(--surface);
  background-image:linear-gradient(90deg, color-mix(in srgb, var(--accent) 10%, transparent), transparent 55%);
  transition:transform .22s ease,border-color .22s ease,box-shadow .22s ease;
}
.mem-spine.off{opacity:.45}
.mem-spine.sel{border-color:var(--accent);transform:translateY(-9px);z-index:5;box-shadow:0 6px 14px rgba(0,0,0,.28)}
/* 霓虹主題的書背:壓暗底色、粉紫框線+外暈、內側一線青光,日期/標題改
   8bit 點陣字(比照霓虹的時間戳與 rail 標籤),像一排霓虹燈牌小卡帶 */
[data-theme="neon"] .mem-spine{
  border-radius:4px;
  border-color:rgba(255,92,203,.5);
  background:#120d18;
  background-image:linear-gradient(90deg, rgba(79,227,255,.09), transparent 55%);
  box-shadow:0 0 9px rgba(255,92,203,.26), inset 0 0 7px rgba(79,227,255,.10);
  font-family:"DotGothic16",var(--sans);letter-spacing:.14em;
  color:#4FE3FF;text-shadow:0 0 5px rgba(79,227,255,.45);
}
[data-theme="neon"] .mem-spine.sel{
  border-color:var(--accent);color:var(--accent);
  text-shadow:0 0 6px rgba(255,92,203,.55);
  box-shadow:0 0 14px rgba(255,92,203,.5), inset 0 0 9px rgba(79,227,255,.16);
}
/* 抽出的那本:內文面板,沿用 pfx 展開的「靠左引用線」語彙 */
.mem-open{border-left:2.5px solid var(--accent);padding:2px 0 2px 13px;margin:12px 0 2px}
.mem-open-date{font-family:var(--serif);font-size:var(--fs-body-s);color:var(--accent);letter-spacing:.05em;margin-bottom:8px}
.mem-title-edit{width:100%;margin-bottom:8px;font-size:var(--fs-body-s)}
.mem-entry-actrow{display:flex;align-items:center;gap:9px;margin-top:8px}
.mem-entry-actrow-lbl{font-size:var(--fs-caption);color:var(--muted)}
.mem-entry-actrow .mem-del{margin-left:auto;padding:6px 13px;font-size:var(--fs-small)}
.mem-entry-actrow .mem-del:active{color:var(--danger)}
.mem-text-edit{width:100%;font-size:var(--fs-body-s);line-height:1.7}
.tag-wrap{display:flex;flex-wrap:wrap;gap:7px}
.tag{padding:7px 12px;border-radius:18px;border:1px solid var(--line);font-size:var(--fs-small);color:var(--muted);transition:all .15s}
.tag.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}
.tag-add{display:flex;gap:7px;margin-top:9px}
.tag-add input{flex:1;padding:8px 12px;font-size:var(--fs-small)}
.anni-list{display:flex;flex-direction:column;gap:var(--sp-2)}
.anni-row{display:flex;align-items:center;gap:11px;background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 12px}
.anni-row .d{font-family:var(--serif);font-size:var(--fs-small);color:var(--accent);letter-spacing:.04em;flex-shrink:0}
.anni-row .n{flex:1;font-size:var(--fs-body-s);min-width:0;word-break:break-word}
.anni-row .x{color:var(--faint);font-size:15px;flex-shrink:0}
/* 每列的「僅此一次」勾選:直列對齊在名稱與刪除鍵之間,勾選中的項目
   日期一過就不再出現在主頁倒數(anniversaryData 的 once 邏輯) */
/* 選擇器帶 .anni-row 提高特異度:上方 .field label{display:block;margin-bottom:6px}
   會蓋掉單類別的 .anni-once,造成勾選標籤失去 inline-flex 且被 6px 下邊距推高 */
.anni-row .anni-once{display:inline-flex;align-items:center;gap:4px;flex-shrink:0;margin:0;font-size:var(--fs-caption);color:var(--muted);white-space:nowrap;position:relative}
.anni-row .anni-once::after{content:'';position:absolute;inset:-9px -4px}   /* 隱形熱區(不用 padding hack,避免干擾列內垂直置中) */
.anni-row .anni-once input{width:15px;height:15px;accent-color:var(--accent);margin:0;flex-shrink:0}
.anni-add{display:flex;gap:7px;margin-top:9px}
.anni-add input[type=date]{flex:0 0 42%}

/* ============ 彈窗 ============ */
#sheet-bg{
  position:absolute;inset:0;background:rgba(0,0,0,.55);z-index:40;opacity:0;pointer-events:none;transition:opacity .25s;
}
#sheet-bg.on{opacity:1;pointer-events:auto}
#sheet{
  position:absolute;left:0;right:0;bottom:0;z-index:41;background:var(--surface);
  border-radius:24px 24px 0 0;padding:10px 20px calc(20px + env(safe-area-inset-bottom));
  transform:translateY(105%);transition:transform .3s cubic-bezier(.3,.9,.3,1);max-height:88%;
  overflow-y:auto;overflow-x:hidden;   /* 安全網:sheet 內容絕不允許橫向捲動 */
}
#sheet.on{transform:translateY(0)}
#sheet .grip{width:38px;height:4px;border-radius:2px;background:var(--line);margin:4px auto 14px}
#sheet h3{font-family:var(--serif);font-size:var(--fs-title-s);letter-spacing:.08em;margin-bottom:16px}
#sheet .field{margin-bottom:14px}
.sheet-acts{display:flex;gap:10px;margin-top:6px}
.sheet-acts .pill{flex:1;justify-content:center;padding:12px}

/* 上下文用量彈窗(js/ui/chat.js openContextUsageSheet):基本設定用 --accent、
   觸發式用 --accent2,兩色只在分組標籤與每列前的圓點上出現——列本身的
   底色/邊框只用「這行現在有沒有真的被包含」(.on)來區分,避免顏色資訊
   疊太多層反而看不出重點。展開/收合沿用 .pfx-body 同一套 grid 0fr→1fr
   手感,只是換一組獨立的 class,不跟角色編輯頁的收合欄位共用開合狀態。 */
.ctxu-group-label{display:flex;align-items:center;gap:8px;font-size:var(--fs-small);color:var(--muted);font-weight:600;margin:16px 0 8px}
.ctxu-group-label:first-of-type{margin-top:0}
.ctxu-list{display:flex;flex-direction:column;gap:7px}
.ctxu-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;opacity:.4}
.ctxu-dot.basic{background:var(--accent)}
.ctxu-dot.trig{background:var(--accent2)}
.ctxu-row{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface2);overflow:hidden}
.ctxu-row.on{border-color:var(--line);background:var(--surface2)}
.ctxu-row.on .ctxu-dot{opacity:1}
.ctxu-row-head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 12px;text-align:left}
.ctxu-row-head:disabled{opacity:.55}
.ctxu-row-title{flex:1;min-width:0;font-size:var(--fs-body-s);color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ctxu-row-state{font-size:var(--fs-caption);color:var(--faint);flex-shrink:0}
.ctxu-row.on .ctxu-row-state{color:var(--text);font-weight:600}
.ctxu-chev{color:var(--faint);flex-shrink:0;transition:transform .2s ease}
.ctxu-row.open .ctxu-chev{transform:rotate(90deg);color:var(--accent)}
.ctxu-row-body{display:grid;grid-template-rows:0fr;transition:grid-template-rows .25s ease}
.ctxu-row-inner{overflow:hidden;min-height:0;padding:0 12px}
.ctxu-row.open .ctxu-row-body{grid-template-rows:1fr}
.ctxu-row.open .ctxu-row-inner{padding:0 12px 12px}
.ctxu-detail-list{margin:0;padding-left:18px;font-size:var(--fs-body-s);color:var(--muted);display:flex;flex-direction:column;gap:4px}
.ctxu-detail-list li{line-height:1.5}

/* 人設總覽(sheet 內):多組人設卡片列表 */
.persona-row{
  display:flex;align-items:center;gap:var(--sp-3);width:100%;box-sizing:border-box;max-width:100%;cursor:pointer;
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-md);
  padding:10px 12px;margin-bottom:9px;transition:border .2s;
}
.persona-row.active{border-color:var(--accent)}
.persona-row .avatar{width:42px;height:42px;font-size:20px;border-radius:var(--r-md);flex-shrink:0}
.persona-row .pr-meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.persona-row .pr-name{font-size:var(--fs-body);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.persona-row .pr-sub{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.05em}
/* 人設備註:僅自己看的配對提示(角色不讀取)——比 pr-sub 再壓一階的存在感 */
.persona-row .pr-note{font-size:var(--fs-caption);color:var(--faint);opacity:.75;letter-spacing:.02em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.persona-note{font-size:var(--fs-caption);color:var(--faint);opacity:.75;margin-top:6px;letter-spacing:.02em}
.persona-row.active .pr-sub{color:var(--accent)}
.persona-row .pr-badge{color:var(--accent);font-size:16px;flex-shrink:0;padding:0 6px}
.persona-row .pr-use{flex-shrink:0;padding:7px 14px;font-size:var(--fs-small)}
.persona-add-btn{display:flex;box-sizing:border-box;width:100%;justify-content:center;margin-top:4px}
#toast{
  position:absolute;left:50%;bottom:110px;transform:translateX(-50%) translateY(20px);z-index:60;
  background:var(--surface2);border:1px solid var(--line);color:var(--text);font-size:var(--fs-body-s);
  padding:10px 20px;border-radius:22px;opacity:0;transition:all .3s;pointer-events:none;
  box-shadow:0 8px 30px rgba(0,0,0,.4);
  /* 訊息可換行:短句仍緊貼內容維持膠囊狀(width:max-content),長訊息(API
     連線、被攔截等系統提示)在寬度上限內自動折行,不再單行衝出畫面被切掉。
     max-width 用 vw 換算再扣邊距,桌機「手機外框」模式下也不會超出外框
     (外框寬 480px,88vw−… 仍在框內);break-word 保住超長無空白字串(網址、
     模型名)也能斷。 */
  width:max-content;max-width:min(88vw,440px);
  white-space:normal;overflow-wrap:break-word;word-break:break-word;
  text-align:center;line-height:1.55;
}
#toast.on{opacity:1;transform:translateX(-50%) translateY(0)}
.fade-in{animation:fadein .35s ease}
@keyframes fadein{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}

/* ============ 歡迎頁 ============ */
#welcome-screen{
  position:absolute;inset:0;z-index:70;background:var(--bg);
  display:flex;flex-direction:column;overflow:hidden;
  opacity:1;transition:opacity .4s ease-out;
}
#welcome-screen[hidden]{display:none}
#welcome-screen.leaving{opacity:0;pointer-events:none}
/* 主頁面外殼:歡迎頁蓋在上面時維持 opacity:0(內容其實已經渲染好了,只是
   視覺上不透明的歡迎頁擋住看不到),點箭頭後跟歡迎頁淡出交疊淡入,
   避免「兩層都透明、露出畫面外背景」的黑/白閃一下 */
#main-shell{
  flex:1;min-height:0;position:relative;display:flex;flex-direction:column;
  opacity:0;transition:opacity .4s ease-out;
}
#main-shell.show{opacity:1}
.wel-img{
  flex:0 0 57%;position:relative;background-size:cover;background-position:center;background-repeat:no-repeat;
}
.wel-img.no-img{background-image:linear-gradient(160deg,var(--accent-soft),var(--bg) 88%)}
/* 底圖下緣柔和漸層沒入深色資訊區,避免生硬分界線 */
.wel-img::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:38%;
  background:linear-gradient(to bottom,transparent,var(--bg));pointer-events:none;
}
.wel-info{
  flex:1;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;gap:14px;padding:22px 30px calc(26px + env(safe-area-inset-bottom));background:var(--bg);min-height:0;
}
.wel-hello{
  font-family:var(--serif);font-size:var(--fs-title-s);font-weight:600;letter-spacing:.14em;color:var(--accent);
}
.wel-quote{
  font-style:italic;font-weight:300;font-size:var(--fs-body);line-height:1.75;color:var(--muted);
  max-width:300px;display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden;
}
.wel-sign{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.05em}
.wel-arrow{
  margin-top:4px;width:50px;height:50px;border-radius:50%;flex-shrink:0;
  background:var(--accent);color:var(--accent-ink);
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 6px 20px rgba(0,0,0,.35);transition:transform .15s;
}
.wel-arrow svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.wel-arrow:active{transform:scale(.9)}
[data-theme="neon"] .wel-arrow{border-radius:6px;box-shadow:0 0 14px rgba(255,92,203,.45)}
[data-theme="neon"] .wel-hello{text-shadow:0 0 8px rgba(79,227,255,.4)}

/* 人設編輯頁:歡迎頁背景圖庫縮圖網格 */
.wel-gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-2)}
.wel-gallery-item{position:relative;aspect-ratio:1;border-radius:var(--r-sm);overflow:hidden;background:var(--surface2)}
.wel-gallery-item img{width:100%;height:100%;object-fit:cover;display:block}
.wel-gallery-del{
  position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;
  background:rgba(0,0,0,.55);color:#fff;font-size:13px;line-height:1;
  display:flex;align-items:center;justify-content:center;
}
.wel-gallery-add{
  aspect-ratio:1;border-radius:var(--r-sm);border:1px dashed var(--line);color:var(--faint);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  font-size:var(--fs-caption);line-height:1.6;text-align:center;gap:2px;
}

/* ============ 主頁 v2:角色輪播 + 收合頁首 + 資訊卡框架 ============
   舊版主頁(#home-legacy)已退役移除,樣式一併清除;本區塊為 v2 框架專用樣式。
   尺寸變數(--big-d / --stride / --mini-h / --topbar-h / --hero-avail-h /
   --hero-pad-top)由 js/ui/home-hero.js 依 #app 實際寬度/可視高度量測後
   設定在 #view-home 上。 */

/* 垂直捲動吸附:每張卡「一則一則推進」;scroll-padding 讓卡片吸附在
   收合頁首下方(可視區中央偏上) */
/* 吸附改由 JS 緩滑接管(scroll-cards.js attachGentleSnap):原生 snap 曲線
   不可自訂且落點偶有偏差;scroll-padding-top 保留給 scrollIntoView 對位用,
   留白 6→14px 讓卡片標題與吸頂列之間有呼吸空間、不再被吃掉 */
#view-home{scroll-padding-top:calc(var(--topbar-h,64px) + var(--mini-h,52px) + 14px)}
#home-top-snap{height:1px;flex-shrink:0;scroll-snap-align:start}

/* 收合頁首容器:吸頂(sticky)。min-height 撐到可視區高度,讓頭貼落在
   「中上方」且卡片起點落在初始視口之外(未捲動時看不到任何卡片邊緣);
   收合動畫全部用 transform + opacity 完成,不動 width/height/top */
#home-hero{
  position:sticky;top:var(--topbar-h,64px);z-index:6;flex-shrink:0;
  min-height:var(--hero-avail-h,480px);
  display:flex;flex-direction:column;align-items:center;
  padding:0 0 14px;pointer-events:none;   /* 頂部留白改由 #hero-carousel 自己的 padding-top 負責,見下方說明 */
}
/* 收合後左上角「小頭貼+名字」列的底色,讓卡片從下方捲過時不與頁首打架;
   透明度跟隨收合進度 --collapse(JS 每影格更新)。
   高度=整個 #home-hero 容器(不再猜一個「應該夠用」的固定像素高度):
   手指還按著、還沒放開吸附前,可以停在「上一張卡尾端」到「這張卡開頭」
   之間的任何中間位置——上一張卡的尾端(例:願望清單的「查看全部」外框)
   在這段過渡期間可能落在 hero 容器裡的任何高度,不是只有吸附後的固定
   落點,用哪個固定像素高度去猜都會有漏網之魚(issue 截圖紅圈)。蓋滿
   整個 hero 容器高度才是不看拖曳位置的解法:非聚焦卡片沒有明確
   z-index,都會被蓋住;聚焦卡有 z:7 蓋過這層,不受影響。 */
#home-hero::before{
  content:'';position:absolute;left:0;right:0;top:0;bottom:0;
  background:var(--bg);
  opacity:var(--collapse,0);pointer-events:none;
}

/* 角色輪播:水平 scroll-snap,只有頭貼;左右 padding 讓第一/最後一張也能置中。
   #home-hero 是 align-items:center 的 flex column(用來垂直置中頭貼區塊),
   這裡務必顯式 width:100%,否則輪播會被壓成 shrink-to-fit,置中 padding 的
   百分比基準就不再是螢幕寬度,整組頭貼會整批往左偏移。
   注意:overflow-x:auto 會讓瀏覽器把「未設的」overflow-y 也算成 auto(CSS
   overflow 的成對規則,無法只設 overflow-x 而讓 overflow-y 維持 visible)——
   舊版容器高度剛好等於頭貼直徑,結果呼吸光暈(比頭貼大)上下各 17px 都被這條
   隱性裁切線切掉一刀(=頭貼上下緣的暗帶),往下捲收合移到左上角時頭貼本體
   也會整個移出這個裁切框而消失。修法:把原本掛在 #home-hero 的 padding-top
   移進這裡當 padding-top(容器頂部延伸到 hero 頂端,收合終點的左上角小頭貼
   位置自然落在裁切框內),額外用 height 撐出光暈需要的下緣空間、margin-bottom
   負值把撐出的高度還給 flow(視覺佔位跟改之前完全一樣,不影響 hero-namewrap
   位置),頭貼格改回固定高度(不再 100% 撐滿),靠 flex 頂對齊落在正確位置。 */
#hero-carousel{
  position:relative;display:flex;align-items:flex-start;width:100%;
  height:calc(var(--hero-pad-top,60px) + var(--big-d,120px) + 17px);
  margin-bottom:-17px;
  overflow-x:auto;scroll-snap-type:x mandatory;
  padding:var(--hero-pad-top,60px) calc((100% - var(--stride,200px)) / 2) 0;
  scrollbar-width:none;pointer-events:auto;
  overscroll-behavior-x:contain;
}
#hero-carousel::-webkit-scrollbar{display:none}
#home-hero.locked #hero-carousel{pointer-events:none}   /* 收合後鎖定,避免誤觸切換 */
/* 每張輪播格用 grid 疊放光暈層與頭貼(同一格、置中對齊),兩者共用 JS 算好的
   同一組 transform,不需要額外的置中位移換算;高度固定等於頭貼直徑(不再
   100% 撐滿容器——容器現在比頭貼高,撐滿會把頭貼擠去置中而偏離原本位置) */
.hero-slide{
  width:var(--stride,200px);flex-shrink:0;height:var(--big-d,120px);
  display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);place-items:center;
  position:relative;z-index:1;
  scroll-snap-align:center;
}
/* minmax(0,1fr) 是關鍵:光暈層(.hero-glow)比頭貼大,若軌道用裸的 1fr,
   CSS Grid 對 fr 軌道的「自動最小尺寸」預設吃 min-content——比容器本身
   還大的固定寬度子項(光暈)會把軌道自動撐大到光暈的寬度(即使容器已明訂
   width),而撐大的軌道預設向左對齊,導致整組頭貼偏移、不再置中(俗稱
   grid blowout)。minmax(0,1fr) 把軌道最小值壓成 0,軌道就固定等於格子
   本身寬度,超出的光暈改用 overflow 溢出顯示,頭貼與光暈才會共享同一個
   置中點。 */
.hero-slide.active{z-index:2}
.hero-av{
  grid-area:1/1;
  width:var(--big-d,120px);height:var(--big-d,120px);border-radius:50%;overflow:hidden;
  flex-shrink:0;padding:0;
  background:var(--surface2);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;
  font-size:calc(var(--big-d,120px) * .45);line-height:1;
  will-change:transform,opacity;
}
.hero-av img{width:100%;height:100%;object-fit:cover;display:block}
.hero-av.add{border:2px dashed var(--faint);background:transparent;color:var(--faint);font-size:calc(var(--big-d,120px) * .34)}
[data-theme="sumi"] .hero-av:not(.add){border-color:rgba(232,200,126,.45);box-shadow:0 0 10px rgba(200,164,110,.22)}
[data-theme="neon"] .hero-av:not(.add){border-color:var(--line);box-shadow:0 0 10px rgba(255,92,203,.3)}
[data-theme="hoshi"] .hero-av:not(.add){box-shadow:0 0 10px rgba(174,191,242,.16)}

/* ---- 置中大頭貼呼吸光暈:獨立光暈層,只動 opacity 與 transform(scale/rotate),
   不對 box-shadow / filter 跑動畫(靜態光暈預先畫好,呼吸靠透明度)。
   只有置中(非收合)且非「+」新增格的頭貼會顯示;收合時整層隨 --collapse 連續淡出,
   由 JS 逐影格設定 opacity/transform(見 home-hero.js update())。 ---- */
.hero-glow{
  grid-area:1/1;position:relative;pointer-events:none;
  width:calc(var(--big-d,120px) + 34px);height:calc(var(--big-d,120px) + 34px);
  opacity:0;will-change:opacity,transform;
}
.hg-outer{position:absolute;inset:0;border-radius:50%;will-change:opacity,transform}
.hg-ring,.hg-ring2,.hg-sweep,.hg-spark{display:none}

/* 墨金:細金環(1px)+ 柔和金色外暈呼吸(.25↔.6)+ 高光沿環走過一小段 */
[data-theme="sumi"] .hg-outer{
  background:radial-gradient(circle, rgba(232,200,126,.55) 0%, rgba(200,164,110,.22) 45%, transparent 72%);
  animation:hg-breathe-sumi 4.6s ease-in-out infinite;
}
@keyframes hg-breathe-sumi{0%,100%{opacity:.25}50%{opacity:.6}}
[data-theme="sumi"] .hg-ring{
  display:block;position:absolute;left:50%;top:50%;
  width:var(--big-d,120px);height:var(--big-d,120px);
  margin-left:calc(var(--big-d,120px) / -2);margin-top:calc(var(--big-d,120px) / -2);
  border-radius:50%;border:1px solid #c9a86a;opacity:.85;
}
[data-theme="sumi"] .hg-sweep{
  display:block;position:absolute;left:50%;top:50%;
  width:var(--big-d,120px);height:var(--big-d,120px);
  margin-left:calc(var(--big-d,120px) / -2);margin-top:calc(var(--big-d,120px) / -2);
  border-radius:50%;animation:hg-sumi-sweep-rot 4.6s ease-in-out infinite;
}
[data-theme="sumi"] .hg-sweep::before{
  content:'';position:absolute;top:-2px;left:50%;width:5px;height:5px;margin-left:-2.5px;
  border-radius:50%;background:#fff3d6;box-shadow:0 0 5px 1px rgba(255,243,214,.8);
}
@keyframes hg-sumi-sweep-rot{
  0%,42%{opacity:0;transform:rotate(0deg)}
  50%{opacity:.95;transform:rotate(22deg)}
  62%,100%{opacity:0;transform:rotate(48deg)}
}

/* 霜白:非常輕的暖白霧光,半徑(scale 1↔1.06)與透明度(.3↔.55)同步呼吸,不留硬邊 */
[data-theme="shiro"] .hg-outer{
  background:radial-gradient(circle, rgba(255,250,238,.85) 0%, rgba(255,250,238,.28) 48%, transparent 74%);
  filter:blur(7px);   /* 靜態模糊,不參與動畫,只有 opacity/transform 在跑 */
  animation:hg-breathe-shiro 4.8s ease-in-out infinite;
}
@keyframes hg-breathe-shiro{0%,100%{opacity:.3;transform:scale(1)}50%{opacity:.55;transform:scale(1.06)}}

/* 霓虹:雙色霓虹光環(內粉外青),透明度交錯呼吸(相位差半週期)+
   每 9~10 秒一次快速閃爍失靈,沿用主題既有的 flicker 語彙 */
[data-theme="neon"] .hg-outer{
  background:radial-gradient(circle, rgba(255,92,203,.4) 0%, transparent 70%);
  animation:hg-breathe-neon-a 4.4s ease-in-out infinite, hg-neon-flicker 9.5s steps(1,jump-end) infinite;
}
@keyframes hg-breathe-neon-a{0%,100%{opacity:.6}50%{opacity:.15}}
[data-theme="neon"] .hg-ring{
  display:block;position:absolute;left:50%;top:50%;
  width:var(--big-d,120px);height:var(--big-d,120px);
  margin-left:calc(var(--big-d,120px) / -2);margin-top:calc(var(--big-d,120px) / -2);
  border-radius:50%;border:1.5px solid #FF5CCB;
  animation:hg-breathe-neon-a 4.4s ease-in-out infinite;
}
[data-theme="neon"] .hg-ring2{
  display:block;position:absolute;left:50%;top:50%;
  width:calc(var(--big-d,120px) + 12px);height:calc(var(--big-d,120px) + 12px);
  margin-left:calc((var(--big-d,120px) + 12px) / -2);margin-top:calc((var(--big-d,120px) + 12px) / -2);
  border-radius:50%;border:1.5px solid #4FE3FF;
  animation:hg-breathe-neon-b 4.4s ease-in-out infinite;
}
@keyframes hg-breathe-neon-b{0%,100%{opacity:.15}50%{opacity:.6}}
@keyframes hg-neon-flicker{0%,84%,100%{opacity:1}86%,90%{opacity:.15}88%{opacity:.7}}

/* 星空:5~7 顆微小星點各自錯開週期閃爍 + 極淡紫色星雲光暈同步呼吸(.2↔.45);
   isolation 已在 #app 設定,星點屬於頭貼自己的裝飾層,不與全域粒子系統打架 */
[data-theme="hoshi"] .hg-outer{
  background:radial-gradient(circle, rgba(174,191,242,.35) 0%, rgba(174,191,242,.14) 50%, transparent 75%);
  animation:hg-breathe-hoshi 5s ease-in-out infinite;
}
@keyframes hg-breathe-hoshi{0%,100%{opacity:.2}50%{opacity:.45}}
[data-theme="hoshi"] .hg-spark{
  display:block;position:absolute;width:2px;height:2px;border-radius:50%;
  background:#fff;box-shadow:0 0 4px 1px rgba(210,220,255,.7);
  animation:hg-twinkle 3.2s ease-in-out infinite;
}
[data-theme="hoshi"] .hg-spark.s1{left:6%;top:18%;background:#E7D9FF;animation-delay:0s}
[data-theme="hoshi"] .hg-spark.s2{left:88%;top:12%;animation-delay:.5s}
[data-theme="hoshi"] .hg-spark.s3{left:92%;top:60%;background:#E7D9FF;animation-delay:1s}
[data-theme="hoshi"] .hg-spark.s4{left:10%;top:78%;animation-delay:1.5s}
[data-theme="hoshi"] .hg-spark.s5{left:50%;top:2%;background:#E7D9FF;animation-delay:2s}
[data-theme="hoshi"] .hg-spark.s6{left:78%;top:88%;animation-delay:2.5s}
[data-theme="hoshi"] .hg-spark.s7{left:22%;top:6%;animation-delay:1.8s}
@keyframes hg-twinkle{0%,100%{opacity:.15;transform:scale(.7)}50%{opacity:1;transform:scale(1.3)}}

/* 名字:主題標題字體,置中;切換角色時淡出淡入(0.2s),
   收合位移的 transform 由 JS 逐影格驅動(不能加 transform transition) */
#hero-namewrap{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;margin-top:10px;pointer-events:none}
#hero-name{
  font-family:var(--serif);font-size:var(--fs-title);font-weight:600;letter-spacing:.06em;
  max-width:70%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  transition:opacity .2s ease;
  will-change:transform,opacity;
}
[data-theme="neon"] #hero-name{font-weight:400;text-shadow:0 0 8px rgba(255,92,203,.4)}

/* 心聲:頭貼名字下方一句隱藏內心獨白(js/innervoice.js 記錄、home-hero.js
   渲染),引言式弱化設計——襯線斜體 + 柔和次要色 + 「」引號裝飾,出現時
   緩慢淡入+輕微上浮(hero-voice-in,fill 用 backwards:只在起跑前壓住
   opacity,結束後放手還給 JS 的行內值,不然收合淡出會被動畫 forwards 卡住)。
   內容變更時由 home-hero.js renderVoice 重設 animation 重跑一次;在主頁第一次
   被看到 60 分鐘後自動消失(innervoice.js SEEN_TTL)。透明度由 JS 逐影格綁定
   收合進度 --collapse(見 home-hero.js update() 的 voiceEl.style.opacity),
   往下捲進入資訊卡頁面前就已完全淡出,不會跟著收合後的小頭貼列一起露出。 */
#hero-voice{
  margin-top:6px;font-family:var(--serif);font-style:italic;color:var(--muted);
  font-size:var(--fs-body-s);letter-spacing:.02em;max-width:78%;text-align:center;
  white-space:pre-line;line-height:1.7;   /* 遇「。」換行(home-hero.js 插入 \n),不截斷、不加引號 */
  will-change:opacity;
  animation:hero-voice-in .6s ease backwards;
}
#hero-voice[hidden]{display:none}
@keyframes hero-voice-in{from{opacity:0;transform:translateY(5px)}}

/* 收合後的點擊熱區:蓋在左上角小頭貼+名字上,點了回到頂部(展開) */
#hero-mini-hit{
  position:absolute;left:8px;top:0;width:min(240px,62%);height:var(--mini-h,52px);
  pointer-events:auto;background:none;border:none;border-radius:var(--r-sm);
}
#hero-mini-hit[hidden]{display:none}

/* ============ 共用:scroll-snap 卡片聚焦框架 ============
   主頁(#home-cards)與日曆單日聚焦頁(#cal-daydetail)共用同一套阻尼手感,
   JS 端由 js/ui/scroll-cards.js 的 watchSnapCards() 共用(見該檔案說明)。
   去邊框、內容直接浮在背景上,靠間距與焦點縮放區分卡片;聚焦卡 scale(1)/
   opacity 1,其餘 .92/.45,0.3s ease-out 過渡,兩處數值必須保持一致。
   注意:scroll-snap-type 本身設在「頁面捲動容器」上(#view-home、
   #view-cal.cal-day-mode),不是這裡——卡片只需要 scroll-snap-align。 */
.snap-card{
  position:relative;z-index:1;
  min-height:clamp(220px,36vh,330px);margin:0 0 34px;
  background:none;border:none;box-shadow:none;
  scroll-snap-align:start;
  transform:scale(.92);opacity:.45;
  transition:transform .3s ease-out,opacity .3s ease-out;
  will-change:transform,opacity;
}
/* 聚焦卡的 z-index 要蓋過吸頂固定區(#home-hero / #cal-fixed-head 都是
   z-index:6,含各自淡出用的漸層遮罩)——scroll-snap 對齊後,聚焦卡的標題
   會緊貼在固定區下緣,若固定區疊在上層,它「給非聚焦卡片退場用」的漸層
   遮罩會連帶把聚焦卡自己的標題/簽名一起壓暗。非聚焦卡維持在遮罩下方,
   讓它們捲過固定區時該淡出就淡出,只有聚焦卡永遠完整明亮。 */
.snap-card.focus{transform:scale(1);opacity:1;z-index:7}

/* 資訊卡片滑動區(主頁專屬容器樣式:右側要留 rail 的空間) */
#home-cards{flex-shrink:0;padding:4px 52px 52vh 16px}
.home-fcard{padding:4px 2px 0}
/* 舊版(無角色/新增角色)佔位卡沿用的簡單標題,五張正式資訊卡改用下方的標題系統 */
.home-fcard .fc-title{font-size:var(--fs-small);letter-spacing:.3em;color:var(--accent);margin-bottom:12px}
.home-fcard .fc-body{font-size:var(--fs-body-s);line-height:1.9;color:var(--muted);white-space:pre-wrap;word-break:break-word}
.fc-body p{opacity:0;transform:translateY(6px);transition:opacity .4s ease,transform .4s ease}
.fc-body p.on{opacity:1;transform:translateY(0)}

/* ============ 共用色塊:半透明玻璃 / 霓虹燈條 ============
   同一個「使用者更新願望清單/抽今日籤/選今日歌曲」動作,同時出現在兩個地方:
   主頁該張資訊卡頂端的短暫提示(.fc-update-badge)、聊天室裡自動同步的那份
   副本卡片(.auto-snap-card,見 chat.js autoSnapCardNode)——兩者共用這裡的
   .snap-glass 當底色,視覺上才讀得出「同一件事的兩份呈現」。
   四主題各自的質感(基底=墨金,依主題覆寫):
   - 墨金 sumi:深色霧面玻璃 + 金箔描邊,上緣一道金色漸層細線
   - 霜白 shiro:亮色磨砂玻璃 + 極淡描邊與柔和落影,細線改暖灰
   - 霓虹 neon:深紫玻璃 + 青色描邊,頂部換成會微微閃爍的霓虹燈條
   - 星空 hoshi:近黑玻璃上灑幾點星塵,細線改月白
   之後若要換成美術提供的 jpg/png 素材,建議尺寸(皆 @2x;背景一律
   cover 裁切,不需要每個裝置寬度各出一份):
   - 主頁卡片提示色塊:686×96px(顯示約 343×48px),透明背景 PNG
   - 聊天室副本卡片底圖:680×440px(顯示寬 340px、高依內容約 120~220px,
     以最高情況設計、上下可被裁)
   - 霓虹燈條:686×12px 的長條(顯示高約 3~6px),左右可裁切/可水平平鋪 */
.snap-glass{
  position:relative;overflow:hidden;
  background:rgba(255,255,255,.07);border:1px solid rgba(200,164,110,.30);
  -webkit-backdrop-filter:blur(14px) saturate(140%);backdrop-filter:blur(14px) saturate(140%);
}
/* 墨金(基底):上緣金箔漸層細線;其他主題覆寫顏色,霓虹整段換成燈條 */
.snap-glass::before{
  content:'';position:absolute;top:0;left:0;right:0;height:2px;pointer-events:none;
  background:linear-gradient(90deg,transparent 4%,rgba(200,164,110,.75),transparent 96%);
}
[data-theme="shiro"] .snap-glass{
  background:rgba(255,255,255,.60);border-color:rgba(30,28,24,.10);
  box-shadow:0 6px 18px rgba(30,28,24,.07);
}
[data-theme="shiro"] .snap-glass::before{background:linear-gradient(90deg,transparent 4%,rgba(110,103,92,.40),transparent 96%)}
[data-theme="hoshi"] .snap-glass{
  background-color:rgba(255,255,255,.05);
  background-image:
    radial-gradient(1px 1px at 16% 28%,rgba(255,255,255,.75),transparent 55%),
    radial-gradient(1px 1px at 68% 18%,rgba(255,255,255,.5),transparent 55%),
    radial-gradient(1.2px 1.2px at 44% 72%,rgba(255,255,255,.6),transparent 55%),
    radial-gradient(1px 1px at 87% 58%,rgba(255,255,255,.45),transparent 55%),
    radial-gradient(1px 1px at 8% 80%,rgba(255,255,255,.4),transparent 55%);
  border-color:rgba(236,234,228,.16);
  box-shadow:0 4px 16px rgba(0,0,0,.28);
}
[data-theme="hoshi"] .snap-glass::before{background:linear-gradient(90deg,transparent 4%,rgba(236,234,228,.45),transparent 96%)}
[data-theme="neon"] .snap-glass{
  background:rgba(20,18,45,.55);border:1px solid rgba(79,227,255,.35);
  box-shadow:0 0 0 1px rgba(255,92,203,.08) inset,0 0 20px rgba(79,227,255,.18);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
/* 霓虹燈條:頂部一道漸層發光細線,取代其他主題的漸層細線 */
[data-theme="neon"] .snap-glass::before{
  top:0;left:8%;right:8%;height:3px;border-radius:3px;
  background:linear-gradient(90deg,transparent,var(--accent),#4FE3FF,var(--accent),transparent);
  box-shadow:0 0 8px 1px var(--accent),0 0 14px 2px rgba(79,227,255,.6);
  animation:snap-neon-flicker 2.4s ease-in-out infinite;
}
@keyframes snap-neon-flicker{
  0%,46%,49%,74%,100%{opacity:1}
  47.5%{opacity:.4}
  75.5%{opacity:.55}
}

/* 主頁資訊卡頂端的「剛剛更新」短暫提示:抽籤/選曲/願望清單更新後 6 秒內顯示,
   淡入 → 停留 → 淡出全靠一個 CSS animation(見 .show),自然消失不留痕跡,
   不需要額外的 JS 計時器精準對齊移除時機 */
.fc-update-badge{
  display:flex;align-items:center;gap:6px;
  padding:8px 12px;margin-bottom:10px;border-radius:var(--r-md);
  font-size:var(--fs-caption);color:var(--accent);letter-spacing:.02em;
  opacity:0;
}
.fc-update-badge[hidden]{display:none}
.fc-update-badge.show{animation:fc-badge-life 6s ease forwards}
@keyframes fc-badge-life{
  0%{opacity:0;transform:translateY(-4px)}
  8%{opacity:1;transform:translateY(0)}
  82%{opacity:1}
  100%{opacity:0}
}

/* ============ 卡片標題系統(五張卡通用) ============
   中文小標(左) + 右下角錯位疊一行英文草寫簽名,聚焦時播放:
   簽名用遮罩由左至右掃出(clip-path reveal,約 1.2s);霓虹主題改 8bit 打字機。
   標題於聚焦後立即開始(.play class 由 JS 於 IntersectionObserver 判斷聚焦時加上),
   內文動畫在標題播放到約一半時接續開始(見 home-hero.js 的時間序安排)。 */
.fc-head{position:relative;display:flex;align-items:flex-start;justify-content:space-between;min-height:32px;margin-bottom:14px}
.fc-title-cn{font-size:var(--fs-caption);letter-spacing:.28em;color:var(--accent);opacity:.55;transform:translateY(-3px);transition:opacity .3s ease,transform .3s ease}
.fc-head.play .fc-title-cn{opacity:.85;transform:translateY(0)}
.fc-sig-wrap{position:relative;align-self:flex-end;margin-left:auto;transform:translate(4px,11px)}
.fc-sig{
  font-family:'Caveat',var(--serif);font-size:var(--fs-title-s);color:var(--accent);opacity:.55;
  display:inline-block;clip-path:inset(0 100% 0 -12%);
}
.fc-head.play .fc-sig{animation:fc-sig-reveal 1.2s cubic-bezier(.22,1,.36,1) forwards}
@keyframes fc-sig-reveal{to{clip-path:inset(0 -12% 0 -12%)}}
[data-theme="sumi"] .fc-sig{color:transparent;-webkit-text-stroke:.6px #d8b877}
[data-theme="shiro"] .fc-sig{color:transparent;-webkit-text-stroke:.5px #9c9384}
[data-theme="hoshi"] .fc-sig{color:#c9c2e8;text-shadow:0 0 6px rgba(174,191,242,.35)}

/* 霓虹:英文標題不用草寫,改 8bit 像素字體 + 打字機逐字(含游標閃爍後消失);
   中文標題同樣打字機處理。--tchars 由 JS 依文字長度設定,寬度用 ch 精準對應字數 */
.fc-sig-mono{display:none}
[data-theme="neon"] .fc-sig{display:none}
[data-theme="neon"] .fc-sig-mono{
  display:inline-flex;align-items:baseline;
  font-family:"DotGothic16",var(--sans);font-size:var(--fs-small);color:var(--accent);opacity:.75;
}
[data-theme="neon"] .fc-sig-mono .tw{display:inline-block;overflow:hidden;white-space:nowrap;width:0}
[data-theme="neon"] .fc-head.play .fc-sig-mono .tw{animation:fc-type-en calc(var(--tchars,6) * .07s) steps(var(--tchars,6),end) forwards}
@keyframes fc-type-en{from{width:0}to{width:calc(var(--tchars,6) * 1ch)}}
[data-theme="neon"] .fc-sig-mono::after{content:'▌';margin-left:2px;color:#4FE3FF;opacity:0}
[data-theme="neon"] .fc-head.play .fc-sig-mono::after{opacity:1;animation:neon-cursor 1.1s steps(2,start) 3}
[data-theme="neon"] .fc-title-cn{
  font-family:"DotGothic16",var(--sans);letter-spacing:.08em;--tw-ls:.08em;opacity:.85;transform:none;transition:none;
}
[data-theme="neon"] .fc-title-cn .tw{display:inline-block;overflow:hidden;white-space:nowrap;width:0}
[data-theme="neon"] .fc-head.play .fc-title-cn .tw{animation:fc-type-cn .5s steps(var(--tchars,4),end) forwards}
/* 中文全形字在這款點陣字型裡的字寬 ≈ 1em,不是 1ch(ch 量的是拉丁字元「0」的寬度,
   對全形字會嚴重低估,導致標題被截斷);英文簽名用 ch 沒問題,拉丁字元本來就窄。
   注意每個字後面還有 letter-spacing(含最後一字):寬度不把字距算進去的話,
   終點寬度會短少「字數 × 字距」,最後一個字被 overflow:hidden 切掉
   (例:紀念日 → 紀念E)。各處的字距用 --tw-ls 傳進來,預設 0。 */
@keyframes fc-type-cn{from{width:0}to{width:calc(var(--tchars,4) * (1em + var(--tw-ls,0em)))}}

/* ============ 紀念日卡:完整實作 ============
   構圖:五段式 flex ——[左線段(flex:1)][圓圈][紀念日名稱][圓圈][右線段(flex:1)],
   線段是獨立元素,只在兩端,文字與圓圈之間完全乾淨、不會被線貫穿;
   線 → 圈 → 名稱依序入場(class 由 JS 依序加上),之下為兩則依序出現的內文
   (認識天數 / 下個紀念日倒數),數字用 JS 跑動遞增。 */
.fc-anni-deco{margin:2px 0 16px}
.fc-anni-row{display:flex;align-items:center;justify-content:center;gap:10px}
.fc-anni-seg{
  flex:1 1 0;min-width:0;height:1px;background:var(--accent);
  transform:scaleX(0);transition:transform .6s cubic-bezier(.22,1,.36,1);
}
.fc-anni-seg.l{transform-origin:100% 50%}   /* 內側(靠圓圈)固定,往外長出 */
.fc-anni-seg.r{transform-origin:0% 50%}
.fc-anni-deco.line-on .fc-anni-seg{transform:scaleX(1)}
.fc-anni-circle{width:13px;height:13px;flex-shrink:0}
.fc-anni-circle circle{
  fill:none;stroke:var(--accent);stroke-width:1;
  stroke-dasharray:47;stroke-dashoffset:47;
  transition:stroke-dashoffset .5s cubic-bezier(.34,1.56,.64,1);
}
.fc-anni-deco.circ-on .fc-anni-circle circle{stroke-dashoffset:0}
.fc-anni-name{
  font-family:var(--serif);font-size:var(--fs-small);color:var(--accent);white-space:nowrap;
  opacity:0;transform:translateY(6px);transition:opacity .4s ease,transform .4s ease;
}
.fc-anni-deco.name-on .fc-anni-name{opacity:.9;transform:translateY(0)}
[data-theme="neon"] .fc-anni-deco.name-on .fc-anni-name{animation:neon-crt-in .15s ease-out;opacity:.9;transform:none;transition:none}

.fc-anni-body{display:flex;flex-direction:column;gap:var(--sp-4);align-items:center;text-align:center;margin-top:8px}
.fc-anni-item{opacity:0;transform:translateY(8px);transition:opacity .4s ease,transform .4s ease}
.fc-anni-item.on{opacity:1;transform:translateY(0)}
.fc-anni-item[hidden]{display:none}
[data-theme="neon"] .fc-anni-item{transition:none}
[data-theme="neon"] .fc-anni-item.on{animation:neon-crt-in .15s ease-out;opacity:1;transform:none}
/* 已過期的一次性紀念日:壓低透明度,跟仍在倒數的項目區分開來(放在整份清單最後) */
.fc-anni-item.past.on{opacity:.6}
.ai-line{display:flex;align-items:baseline;gap:7px;justify-content:center;flex-wrap:wrap}
.ai-lead,.ai-trail{font-size:var(--fs-small);color:var(--muted)}
.ai-digit{font-family:var(--serif);font-size:34px;font-weight:700;color:var(--accent);line-height:1}
.ai-next-name{color:var(--text);font-weight:600;margin:0 2px}
[data-theme="neon"] .ai-lead,[data-theme="neon"] .ai-trail{font-family:"DotGothic16",var(--sans)}
[data-theme="neon"] .ai-digit{font-family:"DotGothic16",var(--sans);text-shadow:0 0 8px rgba(255,92,203,.5)}
/* 「還有 N 個日子」收合展開鈕:比照 .hint 的低調字級,獨立淡入(見 home-hero.js) */
.fc-anni-more{
  background:none;border:none;color:var(--faint);font-size:var(--fs-small);
  text-decoration:underline;text-underline-offset:3px;cursor:pointer;padding:2px 6px;
  opacity:0;transition:opacity .4s ease;
}
.fc-anni-more.on{opacity:1}

/* ============ 今日籤卡(卡片 2) ============
   日期淡入 → 宜/忌翻牌(perspective+backface-visibility)→ 幸運色彈現+文字擦出 →
   引言直線擦出+文字浮現。霓虹主題:日期打字機+一幀色偏 glitch、引言打字機。 */
.ff-date{text-align:center;margin-bottom:18px;opacity:0;transform:translateY(4px);transition:opacity .3s ease,transform .3s ease}
.ff-date.on{opacity:1;transform:translateY(0)}
.ff-date-big{font-family:var(--serif);font-size:44px;font-weight:700;line-height:1}
.ff-date-sm{font-size:var(--fs-small);color:var(--muted);font-weight:500;margin-left:8px;letter-spacing:.1em}
[data-theme="neon"] .ff-date{transition:opacity .1s ease,transform .1s ease}
[data-theme="neon"] .ff-date-big,[data-theme="neon"] .ff-date-sm{font-family:"DotGothic16",var(--sans)}
[data-theme="neon"] .ff-date .tw{display:inline-block;overflow:hidden;white-space:nowrap;width:0;vertical-align:bottom}
[data-theme="neon"] .ff-date-sm .tw{--tw-ls:.1em}   /* 對齊 .ff-date-sm 的 letter-spacing,終點寬度才裝得下最後一字 */
[data-theme="neon"] .ff-date.on .tw{animation-name:fc-type-cn;animation-timing-function:steps(var(--tchars,4),end);animation-duration:calc(var(--tchars,4) * .09s);animation-fill-mode:forwards}
@keyframes ff-date-glitch{
  0%{text-shadow:none}
  35%{text-shadow:1px 0 0 rgba(255,92,203,.85),-1px 0 0 rgba(79,227,255,.85)}
  65%{text-shadow:-1px 0 0 rgba(255,92,203,.6),1px 0 0 rgba(79,227,255,.6)}
  100%{text-shadow:none}
}
[data-theme="neon"] .ff-date.on .ff-date-big{animation:ff-date-glitch .2s ease-out}

.ff-empty{padding:2px 2px 4px}
.ff-empty .hint{margin-bottom:12px}

.ff-flip-row{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3);margin-bottom:18px;perspective:900px}
.ff-flip{height:98px}
.ff-flip-inner{position:relative;width:100%;height:100%;transform-style:preserve-3d;transition:transform .5s cubic-bezier(.4,.1,.2,1)}
.ff-flip.flip .ff-flip-inner{transform:rotateY(180deg)}
.ff-face{
  position:absolute;inset:0;backface-visibility:hidden;-webkit-backface-visibility:hidden;
  border-radius:var(--r-lg);background:var(--surface2);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;padding:10px;text-align:center;
}
.ff-face.front{font-family:var(--serif);font-size:28px;font-weight:700;color:var(--accent)}
.ff-face.back{transform:rotateY(180deg)}
.ff-face.back b{font-family:var(--serif);font-size:var(--fs-body);color:var(--accent)}
.ff-flip.ji .ff-face.back b{color:var(--danger)}
.ff-face.back .ff-face-text{font-size:var(--fs-small);line-height:1.5;color:var(--text)}
[data-theme="neon"] .ff-face{border-radius:6px}

.ff-lucky{display:flex;align-items:center;gap:10px;font-size:var(--fs-body-s);color:var(--muted);margin-bottom:18px}
.ff-lucky-dot{
  width:22px;height:22px;border-radius:50%;border:2px solid var(--line);flex-shrink:0;background:var(--surface2);
  transform:scale(0);transition:transform .4s cubic-bezier(.34,1.56,.64,1);
}
.ff-lucky.on .ff-lucky-dot{transform:scale(1)}
.ff-lucky-text .tw{display:inline-block;clip-path:inset(0 100% 0 -4%);transition:clip-path .35s ease-out .15s}
.ff-lucky.on .ff-lucky-text .tw{clip-path:inset(0 -4% 0 -4%)}
.ff-lucky-name{color:var(--text);font-weight:600}

.ff-quote{display:flex;gap:var(--sp-3)}
.ff-quote-line{width:2px;background:var(--accent);transform:scaleY(0);transform-origin:top;transition:transform .4s ease-out;flex-shrink:0}
.ff-quote.on .ff-quote-line{transform:scaleY(1)}
.ff-quote-body{flex:1;min-width:0;opacity:0;transform:translateY(4px);transition:opacity .35s ease .2s,transform .35s ease .2s}
.ff-quote.on .ff-quote-body{opacity:1;transform:translateY(0)}
.ff-quote-text{font-family:var(--serif);font-size:var(--fs-body);line-height:1.9;color:var(--text);white-space:pre-wrap;word-break:break-word}
.ff-quote-sign{text-align:right;font-size:var(--fs-small);color:var(--faint);letter-spacing:.1em;margin-top:4px}
.ff-redraw-row{display:flex;justify-content:flex-end;align-items:center;gap:8px;margin-top:12px}
[data-theme="neon"] .ff-quote-body{transition:opacity .1s ease .2s,transform .1s ease .2s}
[data-theme="neon"] .ff-quote-text{font-family:"DotGothic16",var(--sans)}

/* ============ 今日夢境 / 夜間日記(卡片 3、4) ============
   單一段落文字,超過三行截斷;有資料時整卡可點,開交換日記書本。 */
.fd-body{opacity:0;transform:translateY(4px);transition:opacity .4s ease,transform .4s ease}
.fd-body.on{opacity:1;transform:translateY(0)}
.fd-text{
  font-size:var(--fs-body-s);line-height:1.9;color:var(--text);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.fd-empty .hint{line-height:1.8}
.home-fcard.fd-clickable{cursor:pointer}
[data-theme="neon"] .fd-body{transition:opacity .1s ease}
[data-theme="neon"] .fd-text{font-family:"DotGothic16",var(--sans);letter-spacing:.02em}

/* ============ 願望清單(卡片 5) ============
   使用者項用主文字色、角色許願項用 --wish-char 強調色區分,前面各自掛來源頭貼;
   逐行間隔 0.1s 入場(淡入+左移歸位),勾選劃線用 ::after 由左至右展開。 */
:root{--wish-char:var(--accent)}
[data-theme="shiro"]{--wish-char:#B08968}
[data-theme="neon"]{--wish-char:#B388FF}
[data-theme="hoshi"]{--wish-char:#AEBFF2}
/* 「分享到聊天室」共用小按鈕(今日籤/心願/今日選曲卡片都用得到),純
   currentColor,顏色自然跟著各主題的 --faint/--accent 走,不用另外覆寫 */
.share-btn{
  width:24px;height:24px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;color:var(--faint);
  transition:color .2s;
}
.share-btn svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.share-btn:active{color:var(--accent)}
.fw-list{display:flex;flex-direction:column;gap:2px}
.fw-row{
  display:flex;align-items:center;gap:10px;padding:9px 2px;
  opacity:0;transform:translateX(-8px);transition:opacity .3s ease,transform .3s ease;
}
.fw-row+.fw-row{border-top:1px dashed var(--line)}
.fw-row.on{opacity:1;transform:translateX(0)}
.fw-row.done{opacity:.55}
.fw-av{
  width:22px;height:22px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;font-size:12px;
  background:var(--surface2);border:1px solid var(--line);
}
.fw-av img{width:100%;height:100%;object-fit:cover;display:block}
.fw-check{
  width:21px;height:21px;border-radius:7px;border:1.5px solid var(--faint);flex-shrink:0;
  display:flex;align-items:center;justify-content:center;transition:all .15s;
  position:relative;
}
.fw-check::after{content:'';position:absolute;inset:-9px}   /* 隱形熱區 */
.fw-check svg{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;opacity:0;transition:opacity .15s}
.fw-row.done .fw-check{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.fw-row.done .fw-check svg{opacity:1}
.fw-text{position:relative;flex:1;min-width:0;font-size:var(--fs-body-s);color:var(--text);white-space:normal;overflow-wrap:break-word}
.fw-row.from-char .fw-text{color:var(--wish-char)}
.fw-text::after{
  content:'';position:absolute;left:0;top:50%;height:1px;width:0;background:currentColor;
  transition:width .3s ease;
}
.fw-row.done .fw-text::after{width:100%}
.fw-foot{display:flex;justify-content:center;margin-top:14px}
[data-theme="neon"] .fw-text{font-family:"DotGothic16",var(--sans)}
[data-theme="neon"] .fw-check{border-radius:2px}

/* 「查看全部」sheet 內的完整清單列,沿用共用的 .mng-row 結構加來源色;
   .mng-row .nm 預設單行省略號,心願內容需要完整顯示,故覆寫為換行 */
.wish-full-row .nm{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:break-word}
.wish-full-row.from-char .nm{color:var(--wish-char)}
.wish-full-row.done .nm{opacity:.55;text-decoration:line-through}
.fw-av.sm{width:20px;height:20px;font-size:11px;flex-shrink:0}

/* ============ 今日選曲(卡片 6) ============
   無框構圖,全靠層次與線條:音波(五根細線,錯相呼吸,像正在播放)→
   歌名(大襯線)→ 歌手(小字疏排)→ 推薦語(左緣細線、{{char}} 口吻)→
   Spotify 連結與再選一首。入場由 home-hero.js 的 after() 序列逐段加 .on。 */
.fsg-deco{display:flex;align-items:flex-end;gap:5px;height:26px;margin:2px 0 14px}
.fsg-note{
  width:2.5px;border-radius:2px;background:var(--accent);transform-origin:bottom;
  opacity:0;transition:opacity .35s ease;
  animation:fsg-eq 1.6s ease-in-out infinite alternate;
}
.fsg-note.n1{height:12px;animation-delay:-.2s}
.fsg-note.n2{height:22px;animation-delay:-.7s;transition-delay:.05s}
.fsg-note.n3{height:15px;animation-delay:-1.1s;transition-delay:.1s}
.fsg-note.n4{height:26px;animation-delay:-.45s;transition-delay:.15s}
.fsg-note.n5{height:9px;animation-delay:-.9s;transition-delay:.2s}
.fsg-deco.on .fsg-note{opacity:.85}
@keyframes fsg-eq{from{transform:scaleY(1)}to{transform:scaleY(.4)}}
.fsg-title{
  font-family:var(--serif);font-size:var(--fs-title);font-weight:600;line-height:1.4;
  word-break:break-word;
  opacity:0;transform:translateY(8px);transition:opacity .45s ease,transform .45s ease;
}
.fsg-title.on{opacity:1;transform:translateY(0)}
.fsg-artist{
  font-size:var(--fs-small);color:var(--muted);letter-spacing:.14em;margin-top:6px;
  opacity:0;transform:translateY(6px);transition:opacity .4s ease,transform .4s ease;
}
.fsg-artist.on{opacity:1;transform:translateY(0)}
.fsg-reason{
  margin-top:16px;font-family:var(--serif);font-size:var(--fs-body-s);line-height:1.95;color:var(--text);
  border-left:2px solid var(--accent);padding-left:13px;white-space:pre-wrap;word-break:break-word;
  opacity:0;transition:opacity .5s ease;
}
.fsg-reason.on{opacity:1}
.fsg-sign{
  text-align:right;font-size:var(--fs-small);color:var(--faint);letter-spacing:.1em;margin-top:6px;
  opacity:0;transition:opacity .5s ease .1s;
}
.fsg-sign.on{opacity:1}
.fsg-foot{
  display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:18px;
  opacity:0;transform:translateY(6px);transition:opacity .4s ease,transform .4s ease;
}
.fsg-foot.on{opacity:1;transform:translateY(0)}
.fsg-spotify{
  display:inline-flex;align-items:center;gap:7px;color:var(--accent);text-decoration:none;
  font-size:var(--fs-small);letter-spacing:.16em;padding:6px 0;
}
.fsg-spotify svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;flex-shrink:0}
.fsg-spotify .arr{transition:transform .2s}
.fsg-spotify:active .arr{transform:translateX(3px)}
.fsg-foot-r{display:flex;align-items:center;gap:4px;flex-shrink:0}
.fsg-again{
  background:none;border:none;color:var(--faint);font-size:var(--fs-caption);letter-spacing:.08em;
  text-decoration:underline;text-underline-offset:3px;padding:6px 2px;flex-shrink:0;
}
.fsg-again:disabled{opacity:.4}
.fsg-empty .hint{line-height:1.8;margin-bottom:12px}
[data-theme="neon"] .fsg-title,[data-theme="neon"] .fsg-reason{font-family:"DotGothic16",var(--sans)}
[data-theme="neon"] .fsg-note{background:#4FE3FF;box-shadow:0 0 6px rgba(79,227,255,.55)}
[data-theme="neon"] .fsg-title{text-shadow:0 0 10px rgba(255,92,203,.35)}
[data-theme="hoshi"] .fsg-note{box-shadow:0 0 5px rgba(174,191,242,.4)}

/* ============ 首頁「安排歌單」卡(手機版策展入口,js/ui/spotify-player.js
   的 playlistCardBodyHTML/playPlaylistCardBody) ============ */
.plc-login,.plc-noapi{padding:4px 0}
.plc-form .field{margin-bottom:10px}
.plc-generate{width:100%;justify-content:center;margin-top:4px}
.plc-status{min-height:1.4em;margin:8px 0 0}
.plc-result{margin-top:6px}
.plc-result-head{margin-bottom:10px}
.plc-result-title{font-family:var(--serif);font-size:var(--fs-title-s)}
.plc-result-reason{margin-top:4px}
.plc-tracks{list-style:none;margin:0;padding:0;max-height:44vh;overflow-y:auto;display:flex;flex-direction:column;gap:10px}
.plc-tracks li{padding:8px 0}
.plc-tracks li+li{border-top:1px dashed var(--line)}
.plc-tracks li b{display:block;font-size:var(--fs-body)}
.plc-tracks li small{display:block;color:var(--faint);margin-top:1px}
.plc-tracks li p{margin:5px 0 0;color:var(--muted);font-size:var(--fs-small);line-height:1.6}
.plc-result-actions{display:flex;gap:8px;margin-top:12px}
.plc-result-actions .plc-sync{flex:1;justify-content:center}
.plc-result-actions .plc-open-spotify{flex:1;justify-content:center;text-align:center;text-decoration:none}
.plc-sync-status{min-height:1.4em;margin:8px 0 0}
.plc-regenerate{width:100%;justify-content:center;margin-top:12px}
.plc-widget-config{margin-top:16px}
.plc-widget-config summary{cursor:pointer;font-weight:600}
.plc-widget-config .hint{margin:8px 0}
.plc-widget-config .field{margin-top:10px}
.plc-widget-actions{display:flex;gap:8px;margin-top:10px}

/* ============ 右側資訊項導覽條(rail) ============
   固定在畫面右緣、垂直置中,寬度 ≤44px;聚焦項 icon 放大 1.4 倍並向左浮出名稱,
   其餘 icon 小尺寸 + 透明度 .4;開始捲動 0.2s 淡入,10 秒無捲動後 1.5s 緩慢淡出
   (淡入/淡出時長由 JS 用 style.transitionDuration 切換)。定位相對 #app,
   不隨 #view-home 內部捲動移動,只在主頁分頁顯示。 */
#home-rail{
  display:none;position:absolute;top:50%;right:2px;transform:translateY(-50%);
  width:44px;flex-direction:column;align-items:center;gap:15px;
  padding:8px 0;z-index:8;
  opacity:0;pointer-events:none;transition:opacity .2s ease;
}
#view-home.on + #home-rail{display:flex}
#home-rail[hidden]{display:none}
#home-rail.show{opacity:1;pointer-events:auto}
.rail-item{position:relative;width:100%;display:flex;align-items:center;justify-content:center;padding:2px 0}
.ri-icon{
  width:17px;height:17px;display:flex;align-items:center;justify-content:center;
  color:var(--faint);opacity:.4;
  transition:transform .3s ease,opacity .3s ease,color .3s ease;
}
.ri-icon svg{width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.rail-item.focus .ri-icon{transform:scale(1.4);opacity:1;color:var(--accent)}
.ri-label{
  position:absolute;right:100%;top:50%;transform:translate(6px,-50%);margin-right:8px;
  font-size:var(--fs-caption);color:var(--accent);white-space:nowrap;
  background:color-mix(in srgb, var(--bg) 82%, transparent);
  padding:3px 9px;border-radius:9px;
  opacity:0;pointer-events:none;transition:opacity .25s ease,transform .25s ease;
}
.rail-item.focus .ri-label{opacity:1;transform:translate(0,-50%)}
[data-theme="sumi"] .ri-icon{color:rgba(200,164,110,.5)}
[data-theme="neon"] .ri-icon{color:#8b84c9}
[data-theme="neon"] .ri-icon svg{stroke-width:1.4}
[data-theme="neon"] .rail-item.focus .ri-icon{color:var(--accent)}
[data-theme="neon"] .ri-label{border:1px solid var(--line);border-radius:2px;font-family:"DotGothic16",var(--sans);font-size:10px}
[data-theme="hoshi"] .ri-icon{color:rgba(205,199,182,.5)}

/* 減少動態效果:呼吸/星點閃爍/掃光停止,保留靜態微光;
   卡片與 rail 的一般 transition 已由全域規則(見上方 @media 區塊)壓成瞬時 */
@media(prefers-reduced-motion:reduce){
  .hg-outer,.hg-ring,.hg-ring2,.hg-sweep,.hg-spark{animation:none!important;opacity:.35!important;transform:none!important}
  .hg-sweep::before{display:none}
}

/* ============ 羈絆任務系統:週任務卡(主頁第七張卡) ============ */
.fq-desc{display:flex;align-items:baseline;flex-wrap:wrap;gap:0 6px;font-size:var(--fs-body);color:var(--text);margin-bottom:16px;line-height:1.6}
.fq-check{color:var(--accent);font-weight:700;flex-shrink:0}
.fq-intro{font-size:var(--fs-small);color:var(--muted);letter-spacing:.02em}
.fq-prog-row{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.fq-prog-track{flex:1;height:8px;border-radius:5px;background:var(--surface2);overflow:hidden}
.fq-prog-fill{height:100%;width:0;border-radius:5px;background:var(--accent);transition:width .6s cubic-bezier(.22,1,.36,1)}
.fq-prog-num{font-size:var(--fs-small);color:var(--muted);flex-shrink:0;min-width:44px;text-align:right;font-variant-numeric:tabular-nums}
.fq-meta-row{display:flex;align-items:center;justify-content:space-between;font-size:var(--fs-small);color:var(--muted);margin-bottom:18px}
.fq-tickets{display:flex;align-items:center;gap:5px}
.fq-tickets-num{color:var(--text);font-weight:600}
.fq-shop-btn{width:100%}
.fq-shop-icon{width:16px;height:16px;object-fit:contain;flex-shrink:0}
[data-theme="neon"] .fq-prog-track{border-radius:2px}
[data-theme="neon"] .fq-prog-fill{border-radius:2px}

/* ============ 心意商店 / 背包(sheet) ============ */
.bond-bal{display:flex;align-items:center;gap:8px;font-size:var(--fs-body-s);color:var(--muted);margin:-4px 0 14px}
.bond-bal img{width:20px;height:20px;object-fit:contain;flex-shrink:0}
.bond-bal b{color:var(--accent);font-size:var(--fs-body-l);font-weight:600}
.bond-tabs{display:flex;gap:8px;margin-bottom:12px}
.bond-tab{flex:1;padding:9px 0;border-radius:var(--r-md);border:1px solid var(--line);color:var(--muted);
  font-size:var(--fs-body-s);display:flex;align-items:center;justify-content:center;gap:6px;transition:all .15s}
.bond-tab.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.bond-tab-icon{width:15px;height:15px;object-fit:contain}
#bond-shop-content{max-height:360px;overflow-y:auto}
.bond-item-row{display:flex;align-items:center;gap:10px;padding:11px 2px;border-bottom:1px dashed var(--line)}
.bond-item-row:last-child{border-bottom:none}
.bond-item-row.expired{opacity:.5}
.bir-meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.bir-meta .nm{font-size:var(--fs-body-s);color:var(--text)}
.bir-meta .ds{font-size:var(--fs-caption);color:var(--faint)}
.bond-countdown{font-size:var(--fs-body-s);color:var(--accent);font-variant-numeric:tabular-nums;flex-shrink:0;white-space:nowrap}
.bond-state-tag{font-size:var(--fs-caption);color:var(--faint);flex-shrink:0}

/* ============ 信物圖鑑(心意商店「信物」分頁) ============
   8 格固定網格;未獲得的格子用 filter 把 emoji 壓成純黑剪影(brightness(0))
   再降低不透明度,不需要另外準備一組「剪影版」圖片素材。 */
.ks-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:6px}
.ks-slot{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;
  aspect-ratio:1;border-radius:var(--r-md);background:var(--surface2);border:1px solid var(--line);padding:6px;
}
.ks-icon{font-size:26px;line-height:1}
.ks-slot.silhouette .ks-icon{filter:brightness(0);opacity:.3}
[data-theme="shiro"] .ks-slot.silhouette .ks-icon{filter:brightness(0) invert(.85);opacity:.35}
.ks-slot.got{border-color:var(--accent)}
.ks-name{font-size:var(--fs-caption);color:var(--muted);text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
.ks-slot.silhouette .ks-name{color:var(--faint)}
.ks-history-title{font-size:var(--fs-small);letter-spacing:.15em;color:var(--faint);margin:16px 0 8px}
.ks-history-list{display:flex;flex-direction:column}
.ks-history-row{display:flex;justify-content:space-between;gap:10px;padding:6px 2px;border-bottom:1px dashed var(--line);font-size:var(--fs-caption);color:var(--faint)}
.ks-history-row:last-child{border-bottom:none}
.ks-history-row .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ks-history-row .dt{flex-shrink:0}

/* ============ 信物獲得展示卡(小卡淡入 + 主題材質光效) ============
   光暈沿用主頁英雄頭貼呼吸光暈的既有 CSS 語彙(.hero-glow/.hg-*,見上方
   「置中大頭貼呼吸光暈」區塊),這裡只需要覆寫尺寸(不依賴 --big-d,固定給
   一個較小的卡片用尺寸)與定位,四主題(墨金掃光/霜白柔光/霓虹閃爍/星空
   星塵)完全繼承既有規則,不重寫任何 keyframes。動畫僅 transform/opacity。 */
#keepsake-reveal{
  position:absolute;inset:0;z-index:75;display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.5);opacity:0;pointer-events:none;transition:opacity .3s ease;
}
#keepsake-reveal.on{opacity:1;pointer-events:auto}
.kr-card{
  position:relative;width:200px;padding:28px 18px 22px;border-radius:var(--r-xl);
  background:var(--surface);border:1px solid var(--line);text-align:center;
  transform:scale(.85);opacity:0;transition:transform .4s cubic-bezier(.22,1,.36,1),opacity .4s ease;
}
#keepsake-reveal.on .kr-card{transform:scale(1);opacity:1}
.kr-glow{--big-d:120px;position:absolute;left:50%;top:38%;transform:translate(-50%,-50%);opacity:1}
.kr-icon{position:relative;font-size:40px;line-height:1;margin-bottom:10px}
.kr-label{position:relative;font-size:var(--fs-caption);letter-spacing:.3em;color:var(--accent);margin-bottom:6px}
.kr-name{position:relative;font-family:var(--serif);font-size:var(--fs-title-s);font-weight:600;margin-bottom:10px}
.kr-phrase{position:relative;font-size:var(--fs-small);color:var(--muted);line-height:1.7}

/* ============ 心意 +N 輕量提示(右上角,主題色,獨立於 #toast) ============ */
#bond-toast{
  position:absolute;top:calc(env(safe-area-inset-top) + 10px);right:14px;z-index:65;
  background:var(--surface2);border:1px solid var(--accent);color:var(--accent);
  font-size:var(--fs-small);font-weight:600;padding:7px 14px;border-radius:16px;
  opacity:0;transform:translateY(-6px);pointer-events:none;
  transition:opacity .8s ease,transform .8s ease;
}
#bond-toast.on{opacity:1;transform:translateY(0);transition:opacity .15s ease,transform .15s ease}

/* ============ 心聲通知(可點擊,連到該角色主頁;獨立於 #toast/#bond-toast,
   兩者都是 pointer-events:none 沒辦法點) ============ */
#voice-toast{
  position:absolute;left:50%;top:calc(env(safe-area-inset-top) + 10px);
  transform:translateX(-50%) translateY(-140%);
  z-index:65;width:max-content;max-width:min(86vw,380px);
  display:flex;align-items:center;gap:10px;
  background:var(--surface2);border:1px solid var(--accent);color:var(--text);
  padding:9px 16px 9px 9px;border-radius:20px;box-shadow:0 8px 24px rgba(0,0,0,.35);
  opacity:0;pointer-events:none;cursor:pointer;
  transition:opacity .3s ease,transform .3s ease;
}
#voice-toast.on{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
#voice-toast .vt-av{
  width:32px;height:32px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;background:var(--surface);font-size:16px;
}
#voice-toast .vt-av img{width:100%;height:100%;object-fit:cover;display:block}
#voice-toast .vt-body{font-size:var(--fs-body-s);line-height:1.4;text-align:left;overflow:hidden;min-width:0}
#voice-toast .vt-body b{color:var(--accent)}
#voice-toast .vt-body i{
  display:block;font-style:italic;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* ============ 角色書房去逛逛完成通知(可點擊,連到該角色書房;結構/樣式
   沿用上面的 #voice-toast,見 js/ui/char-study.js 的 showStudyToast)。
   刻意疊在 #voice-toast 更下面一點,兩則提醒同時觸發時不會完全重疊。 ============ */
#study-toast{
  position:absolute;left:50%;top:calc(env(safe-area-inset-top) + 64px);
  transform:translateX(-50%) translateY(-140%);
  z-index:65;width:max-content;max-width:min(86vw,380px);
  display:flex;align-items:center;gap:10px;
  background:var(--surface2);border:1px solid var(--accent);color:var(--text);
  padding:9px 16px 9px 9px;border-radius:20px;box-shadow:0 8px 24px rgba(0,0,0,.35);
  opacity:0;pointer-events:none;cursor:pointer;
  transition:opacity .3s ease,transform .3s ease;
}
#study-toast.on{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
#study-toast .vt-av{
  width:32px;height:32px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;background:var(--surface);font-size:16px;
}
#study-toast .vt-av img{width:100%;height:100%;object-fit:cover;display:block}
#study-toast .vt-body{font-size:var(--fs-body-s);line-height:1.4;text-align:left;overflow:hidden;min-width:0}
#study-toast .vt-body b{color:var(--accent)}
#study-toast .vt-body i{
  display:block;font-style:italic;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* rail 的點陣圖示(其餘卡沿用手繪 SVG 線稿) */
.ri-icon img{width:100%;height:100%;object-fit:contain}

/* ============ 羈絆任務系統:全域浮動任務面板(第三輪) ============
   浮動 icon:固定 52px 圓形,預設透明度 .85;三種狀態動畫僅 transform/opacity
   (規格第 14 點),拖曳中直接寫 style.top/left(見 quest-panel.js),放開後
   吸邊 + 記憶位置。 */
#quest-fab{
  position:absolute;z-index:30;width:52px;height:52px;border-radius:50%;
  background:var(--surface);border:1px solid var(--line);box-shadow:0 4px 16px rgba(0,0,0,.32);
  opacity:.85;padding:11px;touch-action:none;will-change:transform,opacity;
  display:flex;align-items:center;justify-content:center;
}
/* 沒有未完結任務時整顆隱藏(refreshFabState 寫入 hidden 屬性);
   display:flex 會蓋掉 [hidden] 的預設行為,必須明確補回 */
#quest-fab[hidden]{display:none}
#quest-fab img{width:100%;height:100%;object-fit:contain;display:block;pointer-events:none}
#quest-fab.breathe{animation:qfab-breathe 3s ease-in-out infinite}
@keyframes qfab-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.05)}}
#quest-fab.pulse{animation:qfab-pulse 1.1s ease-in-out infinite;opacity:1}
@keyframes qfab-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.12)}}
#quest-fab-dot{
  position:absolute;top:0;right:0;min-width:16px;height:16px;padding:0 3px;border-radius:8px;
  background:var(--danger);border:2px solid var(--bg);color:#fff;font-size:10px;font-weight:700;
  display:flex;align-items:center;justify-content:center;line-height:1;
}
@media(prefers-reduced-motion:reduce){
  #quest-fab.breathe,#quest-fab.pulse{animation:none!important;transform:none!important}
}

/* 浮動面板:比照 #sheet/#sheet-bg 的底部抽屜語彙(同一份「主題材質」),但是
   獨立的元素——關閉時真的把 innerHTML 清空(見 quest-panel.js 的
   closeQuestPanel),不像 #sheet 只是切 class 隱藏。 */
#quest-panel-bg{
  position:absolute;inset:0;background:rgba(0,0,0,.55);z-index:44;opacity:0;pointer-events:none;transition:opacity .25s;
}
#quest-panel-bg.on{opacity:1;pointer-events:auto}
#quest-panel{
  position:absolute;left:0;right:0;bottom:0;z-index:45;background:var(--surface);
  border-radius:24px 24px 0 0;padding:10px 20px calc(20px + env(safe-area-inset-bottom));
  transform:translateY(105%);transition:transform .3s cubic-bezier(.3,.9,.3,1);max-height:80%;
  overflow-y:auto;overflow-x:hidden;
}
#quest-panel.on{transform:translateY(0)}
#quest-panel .qp-grip{width:38px;height:4px;border-radius:2px;background:var(--line);margin:4px auto 14px}
#quest-panel h3{font-family:var(--serif);font-size:var(--fs-title-s);letter-spacing:.08em;margin-bottom:14px}
.qp-group{margin-bottom:16px}
.qp-group-head{display:flex;align-items:center;gap:8px;font-size:var(--fs-body-s);font-weight:600;color:var(--text);margin-bottom:8px}
.qp-group-head .avatar{width:26px;height:26px;font-size:14px;flex-shrink:0}
.qp-row{display:flex;align-items:center;gap:10px;padding:9px 2px;border-bottom:1px dashed var(--line)}
.qp-row:last-child{border-bottom:none}
.qp-type{font-size:18px;flex-shrink:0;line-height:1}
.qp-meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.qp-content{font-size:var(--fs-body-s);color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.qp-sub{font-size:var(--fs-caption);color:var(--faint)}
.qp-acts{display:flex;flex-direction:column;gap:6px;flex-shrink:0}
.qp-acts .pill{padding:7px 12px;font-size:var(--fs-caption);white-space:nowrap}

/* 聊天氣泡內的活動邀請卡(接受/下次吧) */
.quest-invite-card{
  align-self:center;width:88%;max-width:340px;margin:6px 0;padding:13px 15px;
  background:var(--surface2);border:1px solid var(--accent);border-radius:var(--r-lg);
}
.qi-head{font-size:var(--fs-small);letter-spacing:.1em;color:var(--accent);margin-bottom:6px}
.qi-content{font-size:var(--fs-body-s);color:var(--text);line-height:1.6;margin-bottom:10px}
.qi-acts{display:flex;gap:8px}
.qi-acts .pill{flex:1;justify-content:center;padding:8px}
.qi-resolved{font-size:var(--fs-caption);color:var(--faint)}

/* 聊天氣泡內的英文小考互動卡 */
.quiz-card{
  align-self:center;width:88%;max-width:340px;margin:6px 0;padding:14px 16px;
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-lg);
}
.qz-head{font-size:var(--fs-small);letter-spacing:.1em;color:var(--accent);margin-bottom:8px}
.qz-question{font-family:var(--serif);font-size:var(--fs-body);color:var(--text);line-height:1.6;margin-bottom:12px}
.qz-options{display:flex;flex-direction:column;gap:8px}
.qz-opt{
  padding:9px 12px;border-radius:var(--r-md);border:1px solid var(--line);background:var(--surface);
  color:var(--text);font-size:var(--fs-body-s);text-align:left;transition:all .15s;
}
.qz-opt:disabled{opacity:.6}
.qz-opt.qz-correct-pick{border-color:var(--accent);background:var(--accent-soft);color:var(--accent);opacity:1}
.qz-opt.qz-wrong-pick{border-color:var(--danger);color:var(--danger);opacity:1}
.qz-result{margin-top:12px;font-size:var(--fs-body-s);font-weight:600}
.qz-result.correct{color:var(--accent)}
.qz-result.wrong{color:var(--danger)}
.qz-answer{margin-top:4px;font-size:var(--fs-small);color:var(--text);font-weight:500}
.qz-explain{margin-top:4px;font-size:var(--fs-caption);color:var(--faint);font-weight:400;line-height:1.6}

/* 遊戲房場次對話裡的私密大富翁「開局設定」填選表單(見 monopoly.js
   monopolySetupFormNode,貼在開場白回覆後面,由 game-room.js 的場次訊息
   串渲染),沿用跟 .quest-invite-card/.quiz-card 同一種置中卡片語彙,表單
   控制項沿用既有的 .field/.tag/.tag-wrap,不另刻一套。 */
.mono-setup-card{
  align-self:center;width:92%;max-width:420px;margin:6px 0;padding:14px 16px;
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-lg);
}
.ms-head{font-size:var(--fs-small);letter-spacing:.1em;color:var(--accent);margin-bottom:10px}
.ms-players{display:flex;flex-direction:column;gap:10px;margin-bottom:4px}
.ms-player{border:1px dashed var(--line);border-radius:var(--r-md);padding:10px}
.ms-acts{margin-top:12px}
.ms-acts .pill{width:100%;justify-content:center;padding:9px}
.ms-resolved{font-size:var(--fs-body-s);color:var(--faint)}

.lnk{background:none;border:none;padding:0;color:var(--accent);cursor:pointer;font-size:inherit;text-decoration:underline}

/* 兩欄並排的 .field(單對單 & 多人開局表單共用) */
.mmf-row{display:flex;gap:8px}
.mmf-row>.field{flex:1;min-width:0}

/* ================= 多人開局表單(頁籤式,比照其他頁的 .field/.set-card 慣例) ================= */
.mono-multi-card{padding:14px 14px 16px}
.mono-multi-card .ms-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
/* 頁籤:一排頭像鈕 */
.mmf-tabs{display:flex;flex-wrap:wrap;gap:6px;margin:12px 0}
.mmf-tab{
  display:flex;flex-direction:column;align-items:center;gap:3px;
  width:58px;padding:6px 2px;cursor:pointer;line-height:1.1;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);color:var(--muted);
}
.mmf-tab.on{background:var(--accent-soft);border-color:var(--accent);color:var(--text)}
.mmf-tab.done{border-color:var(--accent)}
.mmf-tab-av{
  width:28px;height:28px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;font-size:14px;background:var(--surface2);color:var(--muted);
}
.mmf-tab-av img{width:100%;height:100%;object-fit:cover}
.mmf-tab-n{font-size:10px;max-width:54px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mmf-tab-me{font-size:9px;color:var(--accent);border:1px solid var(--accent);border-radius:5px;padding:0 3px;line-height:1.4}
.mmf-tab-add{width:40px;justify-content:center}
.mmf-tab-add span{font-size:17px}
/* 頁面內容:一張卡,裡面就是一疊 .field */
.mmf-body{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px}
.mmf-body>.mmf-seatpage,.mmf-body>.mmf-global{display:flex;flex-direction:column;gap:var(--sp-3)}
.mmf-page-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:2px}
.mmf-page-n{font-size:var(--fs-small);letter-spacing:.15em;color:var(--accent)}
.mmf-del{color:var(--danger);text-decoration:none;font-size:var(--fs-caption)}
.mmf-fields{display:flex;flex-direction:column;gap:var(--sp-3)}
.mmf-fields.is-hidden{filter:blur(4px);opacity:.55;pointer-events:none;user-select:none}
.mmf-fillrow{display:flex;flex-direction:column;align-items:flex-start;gap:8px}
.mmf-fillrow .pill{width:100%;justify-content:center;padding:9px}
/* 勾選列:element+class 選擇器提高特異度,壓過全域 .field label{display:block}
   (比照 label.bc-char-pick / label.bc-rel-row 的作法) —— 之前就是被那條蓋掉才跑版 */
.mmf-checklist{display:flex;flex-direction:column;gap:7px;margin-top:2px}
label.mmf-chk{
  display:flex;align-items:flex-start;gap:9px;margin:0;
  font-size:var(--fs-body-s);color:var(--muted);line-height:1.6;cursor:pointer;
}
.mmf-chk input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent);margin:1px 0 0}
.mmf-chk span{flex:1;min-width:0;word-break:break-word}
.mmf-byme-field label.mmf-chk{
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-md);padding:9px 11px;color:var(--text);
}

/* 私密大富翁回合膠囊(見 game-room.js monoRoundBadgeNode,貼在遊戲房場次
   每輪對話最上方):膠囊造型沿用 .day-divider/.msgs-older 同一套語彙,改用
   強調色邊框+文字。 */
.mono-round-badge{align-self:center;font-size:var(--fs-caption);font-weight:600;color:var(--accent);letter-spacing:.05em;padding:7px 16px;background:var(--surface);border:1px solid var(--accent);border-radius:var(--r-xl);margin:6px 0}

/* 私密大富翁棋盤卡(見 monopoly.js monopolyCardNode):置中卡片,底色/邊框/
   標題色全走主題 token,不寫死灰。棋盤那一行(以 ［ 開頭)不換行、可左右捲。 */
.mono-card{
  align-self:center;width:92%;max-width:min(560px,92%);margin:6px 0;
  padding:10px 12px;border-radius:var(--r-lg);
  background:var(--surface2);border:1px solid var(--line);
  font-size:var(--fs-body-s);line-height:1.55;
}
.mono-card-head{font-weight:600;margin-bottom:6px;color:var(--accent);letter-spacing:.05em}
.mono-board-row{white-space:pre;overflow-x:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:var(--fs-body-s);padding-bottom:2px;color:var(--text)}
.mono-text-row{white-space:pre-wrap;word-break:break-word;font-size:var(--fs-body-s);color:var(--text)}

/* 多人開局卡的座位名條(莉亞回饋:圖示要換成頭貼、排版要換行)——見
   monopoly.js rosterRowNode/rosterListNode。 */
.mono-roster-list{display:flex;flex-direction:column;gap:6px;margin:8px 0}
.mono-roster-row{display:flex;align-items:center;gap:8px;padding:3px 4px;border-radius:var(--r-md)}
.mono-roster-row.is-turn{background:var(--accent-soft)}
.mono-roster-av{
  width:30px;height:30px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;font-size:15px;background:var(--surface);color:var(--muted);
}
.mono-roster-av img{width:100%;height:100%;object-fit:cover}
.mono-roster-lines{display:flex;flex-direction:column;min-width:0;line-height:1.4}
.mono-roster-ln1{font-weight:600;color:var(--text);font-size:var(--fs-body-s)}
.mono-roster-ln2{color:var(--muted);font-size:var(--fs-caption);font-variant-numeric:tabular-nums}
.mono-roster-hint{opacity:.7}
/* 開局設定膠囊(莉亞指定:荷官/安全/強度收進「這局的設定」,安全跟強度
   底下各自也要能單獨收合)——用原生 <details>,點擊展開/收合不用另外接 JS。 */
.mono-summary{margin:2px 0 6px}
.mono-summary>summary,.mono-summary-sub>summary{
  cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:5px;
  padding:7px 14px;border-radius:18px;font-size:var(--fs-caption);
  background:var(--surface2);border:1px solid var(--line);color:var(--muted);
}
.mono-summary>summary::-webkit-details-marker,.mono-summary-sub>summary::-webkit-details-marker{display:none}
.mono-summary>summary::after,.mono-summary-sub>summary::after{content:'▾';transition:transform .15s}
.mono-summary[open]>summary::after,.mono-summary-sub[open]>summary::after{transform:rotate(180deg)}
.mono-summary-body{padding:9px 2px 2px;display:flex;flex-direction:column;gap:7px}
.mono-summary-sub{margin:2px 0}
.mono-summary-fields{padding:6px 4px 2px 10px;margin-top:5px;display:flex;flex-direction:column;gap:3px;border-left:2px solid var(--line)}
.mono-summary-field{font-size:var(--fs-body-s);color:var(--text);white-space:pre-wrap;word-break:break-word}

/* 視覺棋盤(階段 3:露比美化包的 7 顆金線圖示 + 六格見方外圈版面,重上
   Metaxy 主題色)。圖示吃 currentColor＝--accent;自帶 mx-live/mx-land 動態。
   只是位置指示,壓在一個窄長條裡就好——留版面給對話。 */
.mono-board-grid{
  display:grid;grid-template-columns:repeat(6,1fr);grid-template-rows:repeat(6,1fr);
  gap:4px;width:100%;max-width:300px;aspect-ratio:1;margin:2px auto 8px;
}
.mono-bcell{
  position:relative;display:flex;align-items:center;justify-content:center;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);
  min-width:0;min-height:0;padding:0;cursor:pointer;font:inherit;
}
.mono-bcell.is-own{box-shadow:inset 0 -2px 0 0 var(--own,var(--accent))}
.mono-bicon{display:block;width:58%;color:var(--accent);line-height:0;opacity:.92}
.mono-bicon svg{width:100%;height:auto;display:block}
.mono-bnum{position:absolute;top:1px;left:4px;font-size:8px;color:var(--faint);letter-spacing:.05em}
.mono-bpieces{position:absolute;right:2px;bottom:2px;display:flex;flex-wrap:wrap;gap:1px;max-width:76%;justify-content:flex-end}
.mono-bpiece{width:12px;height:12px;display:block;filter:drop-shadow(0 1px 1px rgba(0,0,0,.4))}
.mono-bpiece svg{width:100%;height:100%;display:block}
@media (prefers-reduced-motion:no-preference){ .mono-bpiece{animation:mono-tok-pop .45s cubic-bezier(.3,1.4,.5,1) both} }
@keyframes mono-tok-pop{from{transform:translateY(-6px) scale(.5);opacity:0}60%{transform:translateY(1px) scale(1.15);opacity:1}to{transform:none}}
.mono-bmid{
  position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  text-align:center;padding:2px;
}
.mono-bmedal{position:absolute;color:var(--accent);opacity:.28;font-size:min(56px,13vw);pointer-events:none}
@media (prefers-reduced-motion:no-preference){ .mono-bmedal{animation:mono-bmid-spin 16s linear infinite} }
@keyframes mono-bmid-spin{to{transform:rotate(360deg)}}
.mono-binfo{display:flex;flex-direction:column;align-items:center;gap:2px}
.mono-bround{font-size:10px;letter-spacing:.16em;color:var(--faint)}
.mono-bturn{font-size:12px;color:var(--muted)}
.mono-bturn b{color:var(--accent);font-weight:700}
.mono-btip{font-size:11px;line-height:1.6;color:var(--accent);max-width:92%}

/* 階段 3b:任務卡 hero + 擲骰儀式(比照露比美化包,重上 Metaxy 主題色) */
.mono-card{position:relative}
.mono-card.is-task{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent-soft) inset}
.mono-hero-row{
  white-space:pre-wrap;word-break:break-word;
  font-size:var(--fs-body);line-height:1.6;color:var(--text);
  background:var(--accent-soft);border-left:2px solid var(--accent);border-radius:var(--r-sm);
  padding:7px 10px 7px 9px;margin:5px 0;font-weight:600;
}
.mono-card.fade-in{animation:mono-deal .5s cubic-bezier(.2,.7,.3,1)}
@media (prefers-reduced-motion:reduce){ .mono-card.fade-in{animation:none} }
@keyframes mono-deal{from{opacity:0;transform:translateY(12px) scale(.97) rotate(-.6deg)}to{opacity:1;transform:none}}
/* 任務卡上的按鈕(比照露比 MonoView:跳過/換卡永遠露在卡上、不藏選單) */
.mono-card-acts{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.mono-cardbtn{
  padding:7px 14px;font-size:var(--fs-body-s);font-weight:600;cursor:pointer;
  background:var(--accent);color:var(--accent-ink);border:1px solid var(--accent);border-radius:var(--r-md);
}
.mono-cardbtn.ghost{background:var(--surface);color:var(--muted);border-color:var(--line);font-weight:400}
.mono-cardbtn[disabled]{opacity:.5;pointer-events:none}

.mono-dice-veil{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:var(--surface2);border-radius:var(--r-lg);z-index:2;pointer-events:none;
  animation:mono-veil 1.9s ease forwards;
}
@keyframes mono-veil{0%,58%{opacity:1}100%{opacity:0;visibility:hidden}}
.mono-die{
  width:52px;height:52px;padding:6px;display:grid;
  grid-template:repeat(3,1fr)/repeat(3,1fr);gap:3px;
  background:var(--surface);border:1px solid var(--accent);border-radius:var(--r-md);
  animation:mono-die-in .5s cubic-bezier(.2,1.5,.4,1);
}
.mono-die i{border-radius:50%;background:transparent}
.mono-die i:nth-child(5){background:var(--accent)}                 /* 中心點:1,3,5 */
.mono-die[data-v="1"] i:not(:nth-child(5)){background:transparent}
.mono-die[data-v="2"] i:nth-child(1),.mono-die[data-v="2"] i:nth-child(9),
.mono-die[data-v="3"] i:nth-child(1),.mono-die[data-v="3"] i:nth-child(9),
.mono-die[data-v="4"] i:nth-child(1),.mono-die[data-v="4"] i:nth-child(3),.mono-die[data-v="4"] i:nth-child(7),.mono-die[data-v="4"] i:nth-child(9),
.mono-die[data-v="5"] i:nth-child(1),.mono-die[data-v="5"] i:nth-child(3),.mono-die[data-v="5"] i:nth-child(7),.mono-die[data-v="5"] i:nth-child(9),
.mono-die[data-v="6"] i:nth-child(1),.mono-die[data-v="6"] i:nth-child(3),.mono-die[data-v="6"] i:nth-child(4),.mono-die[data-v="6"] i:nth-child(6),.mono-die[data-v="6"] i:nth-child(7),.mono-die[data-v="6"] i:nth-child(9)
  {background:var(--accent)}
.mono-die[data-v="2"] i:nth-child(5),.mono-die[data-v="4"] i:nth-child(5),.mono-die[data-v="6"] i:nth-child(5){background:transparent}
@media (prefers-reduced-motion:reduce){
  .mono-dice-veil{animation:none;opacity:0;visibility:hidden}
  .mono-die{animation:none}
}
@keyframes mono-die-in{from{transform:scale(.3) rotate(-40deg);opacity:0}to{transform:none;opacity:1}}

/* 私密大富翁遊戲房的動作按鍵條(見 monopoly.js monopolyActionBarNode /
   game-room.js renderMonoActions):貼在 #gr-msgs 與輸入框之間,依牌局狀態
   顯示 擲骰／繼續／結算。用既有的 .pill 語彙,不另刻一套。 */
#gr-mono-actions{
  flex-shrink:0;display:flex;gap:8px;padding:8px 12px;
  border-top:1px solid var(--line);background:var(--surface);
}
#gr-mono-actions .pill{flex:1;justify-content:center;padding:9px 6px;font-size:var(--fs-body-s)}
#gr-mono-actions .pill[disabled]{opacity:.5}

/* 主頁動作(抽籤/選曲/願望清單更新)自動同步到聊天室的副本卡片(見 chat.js
   pushAutoSnapMessage/autoSnapCardNode):不當一般對話氣泡顯示,置中、寬度
   比照 .quiz-card/.quest-invite-card,底色改用 .snap-glass 半透明玻璃
   (霓虹主題是霓虹燈條)——這是純狀態通知,不會呼叫角色回應,也不能被回覆/
   引用,所以不需要頭貼、時間戳、互動按鈕 */
/* flex-shrink:0 是必要的,不是保險:#msgs 是 flex column 捲動容器,而
   .snap-glass 的 overflow:hidden 會讓這張卡的 min-height:auto 失效(變 0),
   聊天紀錄超出畫面高度時 flex 收縮就會挑上這張「唯一能縮」的卡片把它壓扁,
   內容被裁到只剩上緣一小截(其他訊息氣泡沒有 overflow:hidden,天生不會被壓) */
.auto-snap-card{
  flex-shrink:0;
  align-self:center;width:88%;max-width:340px;margin:6px 0;padding:13px 15px;
  border-radius:var(--r-lg);box-shadow:0 4px 18px rgba(0,0,0,.10);
}
.asc-head{font-size:var(--fs-small);letter-spacing:.08em;color:var(--accent);margin-bottom:8px}
.asc-body{font-size:var(--fs-body-s);color:var(--text);line-height:1.7}
.asc-yiji{display:flex;gap:14px;margin-bottom:6px}
.asc-yiji b{color:var(--accent);margin-right:4px;font-weight:600}
.asc-lucky{display:flex;align-items:center;gap:6px;font-size:var(--fs-caption);color:var(--muted);margin-bottom:6px}
.asc-swatch{width:10px;height:10px;border-radius:50%;display:inline-block;flex-shrink:0}
.asc-quote{color:var(--muted);font-style:italic}
.asc-title{font-family:var(--serif);font-size:var(--fs-body);color:var(--text)}
.asc-artist{font-size:var(--fs-small);color:var(--muted);margin:2px 0 6px}
.asc-reason{font-size:var(--fs-caption);color:var(--faint);line-height:1.6}

/* ============ 羈絆任務系統:抽獎(第四輪) ============ */
/* 週任務卡的抽獎按鈕(取代原本純顯示的券數) */
.fq-lottery-btn{
  display:flex;align-items:center;gap:5px;padding:6px 12px;border-radius:14px;
  border:1px solid var(--accent);color:var(--accent);font-size:var(--fs-small);background:transparent;transition:opacity .15s;
}
.fq-lottery-btn:disabled{opacity:.4;border-color:var(--line);color:var(--faint)}
.fq-lottery-btn b{color:inherit}
/* 抽獎紀錄分頁的類別小標籤 */
.bond-cat-tag{margin-left:6px;font-size:var(--fs-caption);color:var(--faint);font-weight:400}

/* ---- 全螢幕開獎彈窗(比照 #chatroom/#diarybook 的全螢幕覆蓋語彙,不是
   #sheet 那種帶暗色背板的置底抽屜)----
   影片/佔位動畫滿版鋪滿整個彈窗(不再是置中的正方形卡片),讓開獎畫面
   邊到邊、含上下 safe-area 都被蓋滿;#lottery-modal 本身已經是
   position:absolute;inset:0 貼齊 #app(手機上等於整個視口、桌機的「手機
   外框」模式下等於整個外框),#lottery-stage/#lottery-video-slot 用
   width/height:100% 貼合它就好,不用另外寫死 100vw/100dvh——寫死視口
   單位在桌機置中外框(見 #app 的 min-width:480px 規則)會直接蓋出外框
   範圍。 */
#lottery-modal{
  position:absolute;inset:0;z-index:78;background:var(--bg);overflow:hidden;
  opacity:0;pointer-events:none;transition:opacity .25s ease;
}
#lottery-modal.on{opacity:1;pointer-events:auto}
#lottery-stage{position:absolute;inset:0;overflow:hidden;background:rgba(22,10,36,.92)}
#lottery-video-slot{position:absolute;inset:0}
/* object-position:center 是給特別寬/窄機型的裁切保險,直式手機(素材約
   9:19.5)在 cover 模式下本來就會自然貼合,不需要額外的裁切邏輯。 */
.lottery-video-el{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;display:block;
}
/* 開獎按鈕改成疊在影片上方的浮動列(彈窗改滿版後,#lottery-stage 不再
   讓出版面空間給它) */
.lottery-acts{
  position:absolute;left:0;right:0;bottom:0;z-index:6;
  display:flex;gap:10px;padding:0 20px calc(20px + env(safe-area-inset-bottom));
}
.lottery-acts .pill{flex:1;justify-content:center;padding:12px}

/* ---- 結果疊字:淡入+輕微放大回彈,四主題共用同一種半透明深色襯底
   (確保任何動畫背景下文字都可讀) ---- */
#lottery-result{
  position:absolute;inset:0;z-index:4;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:24px;opacity:0;transform:scale(.9);
  transition:opacity .4s cubic-bezier(.34,1.56,.64,1),transform .4s cubic-bezier(.34,1.56,.64,1);
}
#lottery-result.on{opacity:1;transform:scale(1)}
.lr-name{
  font-family:var(--serif);font-size:26px;font-weight:700;color:#fff;
  padding:8px 18px;background:rgba(0,0,0,.55);border-radius:var(--r-md);margin-bottom:10px;
  max-width:100%;overflow-wrap:break-word;
}
.lr-desc{
  font-size:var(--fs-body-s);color:rgba(255,255,255,.88);
  padding:7px 16px;background:rgba(0,0,0,.45);border-radius:var(--r-md);line-height:1.6;max-width:92%;
}
[data-theme="neon"] .lr-name{animation:lr-glitch .3s ease-out}
@keyframes lr-glitch{
  0%{text-shadow:2px 0 #FF5CCB,-2px 0 #4FE3FF}
  100%{text-shadow:none}
}

/* ============ 社群(角色版) ============ */
/* 篩選列(#comm-filter-btn 切換顯示):作者分類籤 + 日期,兩排都貼齊
   feed 的左右內距,不佔用永久版位,收合時完全不吃版面高度 */
.comm-filter-bar{padding:2px 16px 10px;display:flex;flex-direction:column;gap:8px}
.comm-filter-bar[hidden]{display:none}
.comm-filter-kinds{display:flex;gap:6px;flex-wrap:wrap}
.comm-filter-chip{
  padding:6px 13px;border-radius:999px;font-size:var(--fs-caption);
  background:var(--surface2);border:1px solid var(--line);color:var(--muted);
  transition:background .18s,color .18s,border-color .18s;
}
.comm-filter-chip.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
/* 選「角色」後才展開的第二排:依角色名字進一步篩到單一角色,縮小一號
   跟第一排(全部/我/角色/路人)拉出視覺層級差異 */
.comm-filter-chars{display:flex;gap:5px;flex-wrap:wrap;padding-left:4px}
.comm-filter-chars[hidden]{display:none}
.comm-filter-chip.sub{padding:5px 11px;font-size:12px;opacity:.9}
.comm-filter-date-row{display:flex;align-items:center;gap:8px}
.comm-filter-date-row input[type="date"]{
  flex:1;background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:7px 10px;color:var(--text);font-size:var(--fs-caption);
}
#comm-feed{padding:8px 16px 96px}
/* #view-community 本身要是定位祖先,不然 position:absolute 會往上找到
   #main-shell(整欄含 #tabbar 都算在內)當基準,bottom 就會落到分頁列
   後面、疊住分頁列擋掉點擊。.view 有 overflow-y:auto,但 absolute 子層
   是釘在容器可視框(padding box)上、不隨內容捲動,不用另外處理。 */
#view-community{position:relative;overflow:hidden}
/* 內層捲動區(#comm-scroll):外層 section 不再捲動,發文 + 鈕 absolute 釘在
   外層上就會固定懸浮於右下角,不隨內容捲走;topbar 留在外層頂端不動 */
#comm-scroll{flex:1;min-height:0;overflow-y:auto}
#comm-compose-btn{
  position:absolute;right:18px;bottom:18px;z-index:6;
  width:54px;height:54px;border-radius:50%;background:var(--accent);color:var(--accent-ink);
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 6px 16px rgba(0,0,0,.32),0 0 0 5px var(--accent-soft);
  transition:transform .16s ease;
}
#comm-compose-btn:active{transform:scale(.9)}
#comm-compose-btn svg{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}

/* 貼文詳情/通知面板:比照 #chatroom / #diarybook 的滑入覆蓋層(position:absolute
   inset:0 + transform:translateX 位移),z-index 落在兩者之間,不互相搶層 */
#community-post,#community-notif{
  position:absolute;inset:0;background:var(--bg);z-index:21;display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .32s cubic-bezier(.3,.9,.3,1);overflow:hidden;
}
#community-notif{z-index:25}
#community-post.open,#community-notif.open{transform:translateX(0)}
#cpost-persona-btn{width:34px;height:34px;border-radius:50%;overflow:hidden;background:var(--surface2,var(--surface))}
#cpost-persona-btn img{width:100%;height:100%;object-fit:cover}

.pill.sm{padding:6px 12px;font-size:var(--fs-caption)}

/* 貼文卡(feed)與貼文詳情共用的頭像/名字/內文樣式 */
.cc-av{width:34px;height:34px;border-radius:50%;overflow:hidden;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--surface2,var(--surface));font-size:16px}
.cc-av img{width:100%;height:100%;object-fit:cover}
.cc-av.sm{width:26px;height:26px;font-size:13px}
.cc-head{display:flex;align-items:center;gap:8px}
.cc-name{font-weight:600;font-size:var(--fs-body-s)}
.cc-badge{font-size:var(--fs-caption);color:var(--muted);background:var(--surface2);border-radius:999px;padding:2px 8px;line-height:1.5}
.cc-replyto{font-size:var(--fs-caption);color:var(--faint)}
/* 留言時間(現實時間):跟在名字/回覆標籤之後,淡色小字 */
.cc-c-time{font-size:var(--fs-caption);color:var(--faint);margin-left:6px}
.cc-time{margin-left:auto;font-size:var(--fs-caption);color:var(--faint)}
.cc-text{font-size:var(--fs-body-s);line-height:1.6;white-space:pre-wrap;overflow-wrap:break-word;margin-top:6px}
.cc-text.lg{font-size:var(--fs-body);margin-top:10px}
.cc-mention{color:var(--accent);font-weight:600}
/* 查證來源/收藏連結的網址常常是一長串沒有空白的字元(見角色書房 [收藏]
   項目、貼文查證來源),沒有斷行點的話手機窄螢幕下會直接撐破卡片、橫向
   溢出邊界,補上 overflow-wrap 讓過長網址能在任意字元處換行。 */
.cc-src{margin-top:8px;font-size:var(--fs-caption);color:var(--faint);line-height:1.6;overflow-wrap:anywhere}
.cc-src a{color:inherit;text-decoration:underline;overflow-wrap:anywhere;word-break:break-all}
/* 貼文詳情的查證來源改成一顆顆可點的圓角 chip(feed 卡維持單行文字摘要) */
.cc-src.chips{display:flex;flex-wrap:wrap;gap:6px;line-height:1.4}
.cc-src.chips a{
  display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  background:var(--surface2);border:1px solid var(--line);border-radius:999px;
  padding:4px 11px;text-decoration:none;color:var(--muted);
}
/* 聊天室訊息下方的來源標籤(c.webSearch 開啟、geminiGrounded 回應時,見
   chat.js 的 sourcesHintNode):#msgs 是 flex column,直接沿用 .cc-src.chips
   的 chip 樣式,這裡只補訊息流裡需要的貼左對齊與寬度上限。 */
.msg-src{align-self:flex-start;max-width:min(420px,86%);margin:2px 0 4px}
.cc-img{margin-top:10px;border-radius:var(--r-md);overflow:hidden;max-height:260px;border:1px solid var(--line)}
.cc-img img{width:100%;height:100%;max-height:260px;object-fit:cover;display:block}
.cc-img.lg{margin-top:10px;max-height:360px}
.cc-img.lg img{max-height:360px}
/* 他的書房收藏項目的第三方截圖預覽(見 char-study.js 的
   screenshotImgHTML,thum.io 免金鑰截圖服務)——沿用 .cc-img 的卡片語彙,
   載入失敗時整塊會被 onerror 直接拿掉,這裡不用另外處理破圖占位。 */
.cs-shot-img{margin-top:8px;border-radius:var(--r-md);overflow:hidden;max-height:220px;border:1px solid var(--line);background:var(--surface2)}
.cs-shot-img img{width:100%;height:100%;max-height:220px;object-fit:cover;display:block}

/* Feed 卡片:乾淨貼文牆,不露讚數/留言數(互動一律收進通知面板)。
   入場輕微上浮淡入、按下微縮回饋;data-kind 依作者類型調整視覺重量——
   角色/使用者的頭像帶一圈強調色光環,路人維持素色,呼應「路人是配角」 */
.comm-card{
  display:block;width:100%;text-align:left;padding:15px 16px 16px;margin-bottom:12px;
  position:relative;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  transition:transform .16s ease,border-color .2s,background .16s;
  /* 入場動畫不能用 both/forwards fill:填充中的動畫樣式(to 的 transform:none)
     優先權高於一般宣告,會把 :active 的按壓縮放永久蓋掉——動畫跑完就放手,
     transform 交還給 :active */
  animation:comm-card-in .32s ease;
}
.comm-card:active{transform:scale(.97);background:var(--surface2)}
/* 未讀貼文(還沒點開過):外框換強調色,微微閃光(box-shadow 呼吸)+
   打霧(頂部一層霧面光暈覆蓋);點開後 seenAt 寫入、返回 feed 重繪即消 */
.comm-card.unread{border-color:var(--accent);animation:comm-card-in .32s ease, cc-unread-glow 2.8s ease-in-out .32s infinite}
.comm-card.unread::after{
  content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(130% 90% at 50% -10%, var(--accent-soft), transparent 62%);
}
@keyframes cc-unread-glow{
  0%,100%{box-shadow:0 0 5px var(--accent-soft)}
  50%{box-shadow:0 0 16px var(--accent-soft),0 0 3px var(--accent)}
}
/* 有還沒看過的新留言:右下角彩色對話泡泡,卡片自動多留一排底部空間
   容納它,不壓到內文或附圖 */
.comm-card.has-newc{padding-bottom:42px}
.cc-newc{
  position:absolute;right:11px;bottom:9px;width:24px;height:24px;color:var(--accent);
  display:flex;align-items:center;justify-content:center;border-radius:50%;
  background:var(--surface);box-shadow:0 0 0 2px var(--surface),0 0 8px var(--accent-soft);
  animation:cc-newc-pop .3s ease;
}
.cc-newc svg{width:17px;height:17px;fill:currentColor;stroke:none}
@keyframes cc-newc-pop{from{transform:scale(.4);opacity:0}to{transform:scale(1);opacity:1}}
/* 未讀區域分隔線:主題色(accent)極細波浪線夾時間,低調不搶版面 */
.comm-unread-divider{margin:4px 2px 14px;animation:comm-card-in .32s ease}
.cud-line{display:flex;align-items:center;gap:10px;color:var(--accent);opacity:.8}
.cud-wave{flex:1;height:8px;min-width:0;display:block}
.cud-time{font-size:var(--fs-caption);letter-spacing:.06em;flex-shrink:0}
[data-theme="neon"] .cud-line{filter:drop-shadow(0 0 4px rgba(255,92,203,.5))}
@keyframes comm-card-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.comm-card .cc-av{box-shadow:0 0 0 1px var(--line)}
.comm-card[data-kind="char"] .cc-av,.comm-card[data-kind="user"] .cc-av{box-shadow:0 0 0 2px var(--accent-soft)}

/* 貼文詳情覆蓋層 */
/* .chat-msgs-wrap 本身只是 flex 版型(flex:1;display:flex),真正負責捲動的
   是裡面的內容元素(#chatroom 用的是 #msgs,見它的 overflow-y:auto)——這裡
   照同一個模式,#cpost-body/#cnotif-list 各自補上 flex:1+min-height:0+
   overflow-y:auto,不然内容超出可視高度就整個看不到、也滑不動。 */
#cpost-body,#cnotif-list{flex:1;min-height:0;overflow-y:auto;padding:16px 16px calc(24px + env(safe-area-inset-bottom))}
/* 原貼文區:頭像放大一號、內文行距放寬,跟底下留言串拉出主從層級 */
.cpost-op{padding-bottom:16px;border-bottom:1px solid var(--line);margin-bottom:8px}
.cpost-op .cc-av{width:42px;height:42px;font-size:19px;box-shadow:0 0 0 2px var(--accent-soft)}
.cc-text.lg{line-height:1.75}
.cpost-react-row{display:flex;align-items:center;gap:10px;margin-top:14px;flex-wrap:wrap}
.cpost-react-sum{font-size:var(--fs-caption);color:var(--faint)}
/* 表情反應:平常只看到一顆灰色鏤空愛心(.cpost-react-heart),點下去才在
   它正上方彈出快速鍵+「+」那排選單(.cpost-react-picker,絕對定位、預設
   hidden)——[hidden] 的 display:none 特異度跟下面 display:flex 打平,
   author 樣式又會贏過瀏覽器內建的 [hidden] UA 樣式,所以要額外明講
   [hidden]{display:none} 蓋掉,不然 hidden 屬性會被吃掉、選單變成常駐顯示。 */
.cpost-react-wrap{position:relative;margin-left:auto}
.cpost-react-heart{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--faint)}
.cpost-react-heart svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.cpost-react-picker{
  display:flex;gap:4px;position:absolute;bottom:100%;right:0;margin-bottom:8px;padding:6px;
  border-radius:999px;background:var(--surface);border:1px solid var(--line);
  box-shadow:0 6px 18px rgba(0,0,0,.28);z-index:2;
}
.cpost-react-picker[hidden]{display:none}
.cpost-react-btn{width:32px;height:32px;border-radius:50%;font-size:16px;display:flex;align-items:center;justify-content:center;transition:transform .15s}
.cpost-react-btn:active{transform:scale(1.2)}
.cpost-react-more{width:32px;height:32px;border-radius:50%;border:1px dashed var(--line);color:var(--faint);font-size:16px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
/* 留言串:一個 .comm-thread = 一則頂層留言 + 底下收合的回覆(見
   community.js 的 buildCommentThreads/commentThreadsHTML),分隔線畫在
   「整串」之間,不是每一則留言各自畫一條——巢狀的回覆改用左側縮排+
   細線暗示從屬關係,呼應截圖裡 Threads 的「顯示 N 則回覆」版型。 */
.comm-thread{padding:12px 0;border-bottom:1px solid var(--line)}
.comm-thread:last-child{border-bottom:none}
.comm-comment{display:flex;gap:10px}
.comm-comment.nested{margin-top:10px}
.cc-c-body{flex:1;min-width:0}
.cc-c-body .cc-text{margin-top:2px}
.comm-show-replies{
  margin:10px 0 0 36px;font-size:var(--fs-caption);color:var(--faint);
  display:flex;align-items:center;gap:8px;
}
.comm-show-replies::before{content:'';width:20px;height:1px;background:var(--line)}
.comm-replies{margin:4px 0 0 17px;padding-left:19px;border-left:2px solid var(--line)}
/* 留言底下的表情反應列+回覆鈕:共用一列,表情按鈕縮小一號呼應留言本身較
   小的字級(比照 .cc-av.sm 的縮小邏輯),跟貼文本身那組(較大)區分開來 */
.cc-react-row{display:flex;align-items:center;gap:8px;margin-top:6px;flex-wrap:wrap}
.cc-react-row .cpost-react-sum{font-size:var(--fs-caption)}
.cc-react-row .cpost-react-heart{width:24px;height:24px}
.cc-react-row .cpost-react-heart svg{width:15px;height:15px}
.cc-react-row .cpost-react-picker{gap:2px}
.cc-react-row .cpost-react-btn{width:24px;height:24px;font-size:13px}
.cc-react-row .cpost-react-more{width:24px;height:24px;font-size:13px}
.cc-reply-btn{font-size:var(--fs-caption);color:var(--faint);transition:color .15s}
.cc-reply-btn:active{color:var(--accent)}

/* 發文 sheet:身分列+文字框 */
.comm-compose-head{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.cc-av-btn{width:34px;height:34px;border-radius:50%;overflow:hidden;flex-shrink:0;background:var(--surface2,var(--surface))}
.cc-av-btn img{width:100%;height:100%;object-fit:cover}
.comm-picker-list{max-height:180px;overflow-y:auto;border:1px solid var(--line);border-radius:var(--r-sm);margin-bottom:12px}
.comm-compose textarea{
  width:100%;min-height:100px;padding:12px;border-radius:var(--r-sm);border:1px solid var(--line);
  background:var(--surface2,var(--surface));color:var(--text);font-size:var(--fs-body-s);resize:vertical;margin-bottom:12px;
}
.comm-compose-img-row{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.comm-compose-img-preview{position:relative;width:52px;height:52px;border-radius:var(--r-sm);overflow:hidden;flex-shrink:0}
.comm-compose-img-preview img{width:100%;height:100%;object-fit:cover;display:block}
.comm-compose-img-preview #ccompose-img-remove{
  position:absolute;top:2px;right:2px;width:20px;height:20px;border-radius:50%;
  background:rgba(0,0,0,.55);color:#fff;
}
.comm-compose-img-preview #ccompose-img-remove svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}

/* 身分/提及挑選器 sheet:一行一個選項 */
.comm-persona-item,.comm-mention-item{
  display:flex;align-items:center;gap:10px;width:100%;padding:11px 10px;text-align:left;
  border-bottom:1px solid var(--line);font-size:var(--fs-body-s);transition:background .15s;
}
.comm-persona-item:active,.comm-mention-item:active{background:var(--surface2)}
.comm-persona-item:last-child,.comm-mention-item:last-child{border-bottom:none}
.comm-persona-item img{width:30px;height:30px;border-radius:50%;object-fit:cover;flex-shrink:0}
.comm-persona-item svg{width:30px;height:30px;flex-shrink:0}

/* 通知面板 */
.comm-notif-item{
  display:flex;align-items:flex-start;gap:10px;width:100%;text-align:left;padding:12px 16px;
  border-bottom:1px solid var(--line);transition:background .15s;
}
.comm-notif-item:active{background:var(--surface2)}
.comm-notif-item .cc-av{box-shadow:0 0 0 1px var(--line)}
/* 這次打開面板才出現的新通知:左側強調色細條+微微底色,跟舊通知的交界
   由 renderNotifList 插入同一款螢光筆+波浪+時間分隔線 */
.comm-notif-item.unread{background:var(--accent-soft);box-shadow:inset 3px 0 0 var(--accent)}
#cnotif-list .comm-unread-divider{margin:10px 16px 6px}
.cni-body{font-size:var(--fs-body-s);line-height:1.6}
.cni-body b{font-weight:600}

/* 空狀態(feed/留言串/通知共用):置中 + 大圖示,取代乾巴巴的一行字 */
.comm-empty{text-align:center;padding:52px 20px;color:var(--faint)}
.comm-empty .ce-ico{display:block;font-size:30px;margin-bottom:12px;opacity:.85}
.comm-empty p{font-size:var(--fs-body-s);line-height:1.9}
.comm-empty.sm{padding:22px 8px}
.comm-empty.sm .ce-ico{font-size:22px;margin-bottom:8px}

/* 表情反應名單 sheet:每個表情符號一組,底下列出按過的人 */
.comm-reactor-group{margin-bottom:16px}
.comm-reactor-group:last-child{margin-bottom:0}
.comm-reactor-emoji{font-size:var(--fs-body);margin-bottom:8px}
.comm-reactor-item{display:flex;align-items:center;gap:8px;padding:6px 0;font-size:var(--fs-body-s)}

/* ---- 離線推播設定(#push-card):分類列版型 ----
   每列固定兩行:第一行「小標題(左)+ 滑動開關(右)」,第二行整行寬的
   自訂提示詞輸入框(待辦提醒沒有文案可自訂,只有第一行) */
.push-cat-row{padding:13px 0;border-bottom:1px solid var(--line)}
.push-cat-row:first-child{padding-top:6px}
.push-cat-row:last-child{border-bottom:none;padding-bottom:4px}
.push-cat-main{display:flex;align-items:center;justify-content:space-between;gap:12px}
.push-cat-main span{flex:1;min-width:0;font-size:var(--fs-body-s);font-weight:600;line-height:1.4}
.push-cat-main input.switch{width:46px;flex-shrink:0}
.push-cat-hint{display:block;width:100%;margin-top:9px;font-size:var(--fs-caption);padding:9px 11px}
/* 測試/重寫/檢視三顆長文字按鈕改上下堆疊,窄卡片裡不會互擠越界 */
#push-card .sheet-acts{flex-direction:column;align-items:stretch;gap:8px}
#push-card .sheet-acts .pill{flex:none;width:100%;justify-content:center}

/* 今日推播排程 sheet:時間+類型+狀態一列 */
.pstatus-row{display:flex;align-items:center;gap:12px;padding:9px 2px;border-bottom:1px solid var(--line);font-size:var(--fs-body-s)}
.pstatus-row:last-of-type{border-bottom:none}
.pstatus-row .ps-time{font-weight:600;flex-shrink:0;font-variant-numeric:tabular-nums}
.pstatus-row .ps-cat{flex:1;min-width:0}
.pstatus-row .ps-state{font-size:var(--fs-caption);color:var(--faint);flex-shrink:0}
.pstatus-row.fired{opacity:.55}
.pstatus-row.fired .ps-state{color:var(--accent)}

/* 文案檢視/編輯 sheet:角色籤 + 分類 textarea(一行一句) */
.phrase-editor .pe-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
.pe-chip{padding:6px 12px;border-radius:999px;background:var(--surface2);border:1px solid var(--line);color:var(--muted);font-size:var(--fs-caption)}
.pe-chip.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
/* 「＋ 新增角色」用虛線框跟角色籤區分;展開的候選清單縮排一格 */
.av-check-out{margin-top:10px;padding:10px 12px;border-radius:10px;background:var(--surface2);border:1px solid var(--line)}
.av-check-line{margin:0 0 6px;font-size:var(--fs-caption);line-height:1.7;color:var(--muted)}
.av-check-line:last-child{margin-bottom:0}
.av-check-line b{color:var(--ink)}
.pe-chip-add{border-style:dashed}
.pe-add-list{margin:-4px 0 12px;padding:10px;border-radius:10px;background:var(--surface2);border:1px solid var(--line)}
.pe-head-row{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.pe-curname{font-weight:600;font-size:var(--fs-body-s)}
.pe-head-row .pill{margin-left:auto}
.pe-cat{margin-bottom:12px}
.pe-cat label{display:block;font-size:var(--fs-caption);color:var(--faint);margin-bottom:5px}
.pe-ta{width:100%;font-size:var(--fs-body-s);line-height:1.7;resize:vertical}

/* 表情符號選擇 sheet:六個快速鍵 + 任意 emoji 輸入框 */
.comm-emoji-quick{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px}
.comm-emoji-quick-btn{width:44px;height:44px;border-radius:50%;background:var(--surface2,var(--surface));font-size:20px;display:flex;align-items:center;justify-content:center}
.comm-emoji-quick-btn:active{transform:scale(1.15)}

/* 未讀通知紅點:輕微呼吸光圈,不動位置只擴光暈,提醒但不吵 */
#comm-notif-dot{width:10px;height:10px;animation:comm-dot-pulse 2s ease-in-out infinite}
@keyframes comm-dot-pulse{
  0%,100%{box-shadow:0 0 0 0 var(--accent-soft)}
  50%{box-shadow:0 0 0 5px var(--accent-soft)}
}

/* @提及圖示:使用者提供的 PNG 當遮罩、底色用 currentColor——跟文字圖示
   一樣自動吃各主題/各狀態的顏色,不用為每個主題出一張圖 */
.mention-ico{
  display:inline-block;width:20px;height:20px;background:currentColor;vertical-align:-3px;
  -webkit-mask:url(../icons/community/mention.png) center/contain no-repeat;
  mask:url(../icons/community/mention.png) center/contain no-repeat;
}
.mention-ico.sm{width:15px;height:15px}
/* 發文表單的附加照片鈕:沿用圖片庫快速鍵同一顆線框相片圖示,取代 emoji
   (.pill 本身是 flex+gap,圖示不用自帶外距) */
.ccompose-img-ico{
  width:16px;height:16px;flex-shrink:0;
  fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;
}

/* ---- 社群:四主題各自的質感(比照 .set-card 的主題差異化手法) ---- */
[data-theme="sumi"] .comm-card{
  border-color:rgba(200,164,110,.22);
  box-shadow:inset 0 1px 0 rgba(232,200,126,.13), 0 4px 16px rgba(0,0,0,.22);
}
[data-theme="sumi"] #comm-compose-btn{box-shadow:0 4px 14px rgba(0,0,0,.35),0 0 12px rgba(200,164,110,.4)}
[data-theme="shiro"] .comm-card{box-shadow:0 2px 10px rgba(0,0,0,.05)}
[data-theme="neon"] .comm-card,[data-theme="neon"] .cc-img{border-radius:8px}
[data-theme="neon"] .comm-card{box-shadow:0 0 10px rgba(79,227,255,.10),inset 0 0 14px rgba(79,227,255,.05)}
[data-theme="neon"] #comm-compose-btn{border-radius:10px;box-shadow:0 0 16px rgba(255,92,203,.5)}
[data-theme="neon"] .cc-mention{color:#4FE3FF;text-shadow:0 0 6px rgba(79,227,255,.45)}
[data-theme="hoshi"] .comm-card{box-shadow:0 4px 14px rgba(0,0,0,.18)}
[data-theme="hoshi"] #comm-compose-btn{box-shadow:0 4px 14px rgba(0,0,0,.3),0 0 12px rgba(205,199,182,.35)}

/* ============ PWA(加入主畫面)獨立模式:滿版高度 ============
   放在檔案最後:同特異度下要蓋過前面 #app{height:100dvh} 與
   #chatroom{height:100dvh} 的基礎規則,順序即優先權。
   iOS 啟動瞬間常把視口高度(dvh)誤報偏矮,畫面底部露出一條 app 外的
   bar,以前要「下拉一下」觸發 iOS 重算視口才會滿版;曾試過
   body{position:fixed} 把文件凍住——重算永遠不會發生,app 反而永遠
   到不了滿版,已移除。現行做法:app 殼高度改用 100lvh(最大視口高度)
   ——standalone 模式沒有會收合的瀏覽器 UI,lvh 從啟動起就是整個螢幕高,
   不需要等 dvh 修正、也不用使用者拉;鍵盤收起後的殘留捲動偏移由
   main.js 的 pinViewport 歸零。#chatroom 改為跟隨 #app 高度(inset:0),
   不再自己讀一次可能過期的 dvh。限手機寬度,桌機安裝版維持原本的
   相框式版面(min-width:480px 規則)。 */
@media (display-mode: standalone) and (max-width:479px){
  #app{height:100lvh}
  #chatroom{height:auto}
}

/* ============ 桌機版:展開為滿版全螢幕(無黑邊) ============
   從電腦瀏覽器開啟時,整個 app 由手機寬(430px 相框)展開填滿整個桌機
   螢幕(例:1920×1080),兩側不再露出 body 的黑底。

   做法:
   1) #app 拿掉 max-width、改 width:100% + height:100dvh 鋪滿視口。各主題的
      背景(漸層 + 粒子/星芒)本就畫在 #app 上(見 [data-theme=…] 規則),殼
      鋪滿後整片主題氛圍隨之鋪滿全螢幕,取代原本兩側的純黑 body 底。
   2) 內容(所有分頁 + 底部導覽 + 聊天室/日記本/貼文詳情等覆蓋層,全部掛在
      #main-shell 內、並以它為 position 定位基準)收束成一個置中的寬欄,避免
      單欄內容在 1920 寬被拉到過寬而鬆散;欄兩側露出的是 #app 同一套主題
      背景,與內容連成一片、不是黑邊。只動 #main-shell 一個容器,app 內其餘
      版面/JS 量測(home-hero、quest-panel 等讀的是 #app 即時寬度)照常運作。

   生效條件刻意收窄成「真的是電腦」:
   - min-width:1024px:視窗要有桌機寬度;
   - hover:hover + pointer:fine:要有滑鼠(手機/平板觸控螢幕不吃這組,
     手機瀏覽器與加入主畫面的 PWA 完全不受影響,維持原樣);
   480px~1023px 的中間地帶(桌機小視窗/平板)維持原本的置中相框版面。
   放在檔案最末:同特異度下靠順序蓋過前面 430px/480px 的基礎規則。 */
@media (min-width:1024px) and (hover:hover) and (pointer:fine){
  #app{
    --desk-zoom:1.25;              /* 桌機整體放大倍率:調這一個值即可整組縮放(1=不放大) */
    max-width:none; width:100%; height:100dvh;   /* 鋪滿整個螢幕,主題背景延伸到兩側,無黑邊 */
    border-radius:0; border:0; box-shadow:none;
  }
  /* 內容置中寬欄 + 整體等比放大:
     - zoom 讓欄內所有元素(文字/間距/圓角/頭貼/圖示…)一起等比放大、形狀不變,
       且固定視口高度的版面(#main-shell 由 flex 撐高、聊天室等)會自動配合,不
       會像 transform:scale 那樣溢出或壓壞捲動。
     - width 除以 zoom:放大後的視覺寬度 = min(1440*zoom, 視口寬),永遠不橫向溢出
       (小視窗桌機會剛好填滿、大螢幕留主題背景邊)。
     - align-self:center 在直向 flex 容器裡做橫向置中(比 margin auto 在 zoom 下更穩),
       兩側露出的是 #app 同一套主題背景,不是黑底。
     - overflow:clip 不可少:聊天室/日記本/貼文詳情/通知等覆蓋層平時用
       transform:translateX(100%) 藏到右側,基礎規則靠 #app 的 overflow:clip 裁掉;
       欄收窄後這些覆蓋層會落在欄右緣外的主題背景區露餡,改由 #main-shell 自己
       在欄邊界裁切(內層各 .view 的垂直捲動不受影響)。 */
  #main-shell{
    zoom:var(--desk-zoom);
    width:min(1440px, calc(100vw / var(--desk-zoom)));
    align-self:center; overflow:clip;
  }
  /* 聊天室原本用 height:100dvh(視口高),在 zoom 下會超出被放大的容器;改吃
     容器高度(它本就 inset:0 貼滿 #main-shell,100% 與 inset 一致) */
  #chatroom,#bookclub-room,#bookclub-page{ height:100%; }
  /* 歡迎頁(絕對定位在 #app、不在 #main-shell 內)內容也收束置中,與主畫面
     同一個寬欄視覺一致,不整片橫拉滿 1920 */
  #welcome-screen{ align-items:center; }
  #welcome-screen>*{ width:100%; max-width:1440px; }
  /* 聊天/圖片訊息行寬上限,寬版下仍好讀 */
  .msg .bubble,.lwrap .lbubble{max-width:560px}
  .msg-img,.msg-img-standalone{max-width:420px}
  /* 桌機有實體捲軸+滑鼠,恢復可捲區的細條深色捲軸樣式 */
  .view::-webkit-scrollbar,#msgs::-webkit-scrollbar,#comm-scroll::-webkit-scrollbar{width:8px}
  .view::-webkit-scrollbar-thumb,#msgs::-webkit-scrollbar-thumb,#comm-scroll::-webkit-scrollbar-thumb{
    background:var(--line);border-radius:4px;
  }
}

/* ============ 圓桌讀書會(js/ui/bookclub.js) ============ */
/* 聊天分頁頂部入口:單一橫幅卡,以書脊色條+襯線標題與私聊列(.convo)做出
   視覺區隔;書房不再混進聊天列表,點卡開主頁面 */
.bc-banner{
  display:flex;align-items:center;gap:12px;width:calc(100% - 32px);margin:10px 16px 12px;
  padding:19px 16px;text-align:center;position:relative;overflow:visible;min-height:60px;
  background:none;   /* 無底色色塊,花邊本身即邊界 */
  border:0;border-radius:var(--r-lg);
}
.bc-banner:active{background:color-mix(in srgb, var(--accent) 8%, transparent)}
.bc-banner-meta{flex:1;min-width:0}
.bc-banner-title{
  /* 固定用襯線 TC 字體:霓虹主題的 --serif 是 DotGothic16(日文點陣字,缺「桌」),
     會讓「圓桌讀書會」的「桌」變缺字/異體;這裡強制與其他主題一致的襯線字 */
  font-family:"Noto Serif TC","Songti TC","Noto Serif CJK TC",serif;
  font-weight:600;letter-spacing:.08em;font-size:var(--fs-body);
}
.bc-banner-sub{font-size:var(--fs-caption);color:var(--muted);margin-top:3px}
.bc-banner-chev{position:absolute;right:12px;top:50%;transform:translateY(-50%);width:18px;height:18px;stroke:currentColor;fill:none;color:var(--faint);flex-shrink:0}
/* 讀書會主頁頂部標題「圓桌讀書會」同樣強制襯線 TC(避免霓虹主題缺「桌」) */
#bookclub-page>.chat-head .cname{font-family:"Noto Serif TC","Songti TC","Noto Serif CJK TC",serif}

/* ---- 圓桌讀書會花邊框(四角,主題強調色)----
   -webkit-mask/mask 讓單色 SVG 依主題 --accent 上色(比照社群 mention icon 既有作法);
   四個角各一個 mask 圖層,固定 px 尺寸→不隨容器高度變形。--bcf 控制角落大小。
   註:mask 需同源資源,App 以 http(s) 提供(PWA)時正常;若以 file:// 直接開啟,
   瀏覽器會擋掉外部 mask 資源,花邊靜默不顯示(其餘功能不受影響)。 */
.bc-frame{
  position:absolute;inset:0;pointer-events:none;background:var(--accent);
  --bcf:88px;
  -webkit-mask:
    url(../assets/bookclub/bc-corner-tl.svg) top left/var(--bcf) var(--bcf) no-repeat,
    url(../assets/bookclub/bc-corner-tr.svg) top right/var(--bcf) var(--bcf) no-repeat,
    url(../assets/bookclub/bc-corner-bl.svg) bottom left/var(--bcf) var(--bcf) no-repeat,
    url(../assets/bookclub/bc-corner-br.svg) bottom right/var(--bcf) var(--bcf) no-repeat;
  mask:
    url(../assets/bookclub/bc-corner-tl.svg) top left/var(--bcf) var(--bcf) no-repeat,
    url(../assets/bookclub/bc-corner-tr.svg) top right/var(--bcf) var(--bcf) no-repeat,
    url(../assets/bookclub/bc-corner-bl.svg) bottom left/var(--bcf) var(--bcf) no-repeat,
    url(../assets/bookclub/bc-corner-br.svg) bottom right/var(--bcf) var(--bcf) no-repeat;
}
/* 橫幅專用:只保留四角花邊(略放大以界定整個橫幅範圍,取代原底色色塊四邊),
   沿用 .bc-frame 的四角 mask,不加上下花飾。 */
.bc-banner .bc-frame{--bcf:50px}

/* 主頁面覆蓋層:右滑進場;內容區做成一塊圓角書頁面板(借用交換日記
   .book-inner 的內陰影書頁語彙,但不做 3D 翻頁) */
#bookclub-page{
  position:absolute;inset:0;height:100dvh;background:var(--bg);z-index:20;
  display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .32s cubic-bezier(.3,.9,.3,1);overflow:hidden;
}
#bookclub-page.open{transform:translateX(0)}
#bcp-stage{flex:1;overflow:hidden;padding:14px 14px calc(14px + env(safe-area-inset-bottom));position:relative}
/* 讀書會主頁的四角花邊框:掛在固定不捲動的 stage 上,內層 #bcp-body 照常捲動。
   只把底部 inset 補上 safe-area:原本 inset:0 會讓花框底部延伸進home indicator
   的安全區、比上/左/右多出一截而與內頁邊框不齊;補上 safe-area 後四邊與內頁
   邊框維持一致的間距(上下左右對齊)。 */
#bcp-stage>.bc-frame{--bcf:104px;z-index:2;inset:0 0 env(safe-area-inset-bottom) 0}
#bcp-body{
  height:100%;overflow-y:auto;background:var(--surface);border:1px solid var(--line);
  border-radius:8px 16px 16px 8px;box-shadow:inset 3px 0 8px rgba(0,0,0,.12);
  padding:18px 16px 26px;
}
.bcp-sec-head{display:flex;align-items:baseline;gap:8px;margin-bottom:10px}
.bcp-sec-title{font-family:var(--serif);font-size:var(--fs-body);font-weight:600;letter-spacing:.08em}
.bcp-sec-sub{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.14em;flex:1}
.bcp-hint{margin:2px 0 6px}
/* 讀書會範圍共用的小型按鈕(頁面與房間內):不依賴 .mng-row 前綴 */
#bookclub-page .mini,#bookclub-room .mini,#char-study-page .mini{
  height:28px;padding:0 10px;border-radius:9px;border:1px solid var(--line);color:var(--muted);
  display:inline-flex;align-items:center;justify-content:center;font-size:var(--fs-caption);flex-shrink:0;
}
#bookclub-page .mini.accent,#bookclub-room .mini.accent,#char-study-page .mini.accent{color:var(--accent);border-color:var(--accent)}
#char-study-page .mini[hidden]{display:none}
.bcp-sec-head .mini{align-self:center}

/* 手機版讀書會管理頁改收合式(書庫/讀書會/角色書房),概念參考桌機版
   .bcp-accordion(desktop.css),視覺改沿用手機既有的 .bcp-sec-head 語彙
   (serif 標題 + 淡出副標),桌機版本身另有自己的一份規則(desktop.css 的
   media query 內),互不影響;pageUI.booksOpen/roomsOpen/studyOpen 兩邊
   共用同一份開闔狀態,縮放視窗切斷點不會忽然全部收合或全部展開。 */
.bcp-accordion{border-top:1px solid var(--line)}
.bcp-accordion+.bcp-accordion{margin-top:2px}
.bcp-accordion>summary{
  list-style:none;display:flex;align-items:center;gap:8px;cursor:pointer;
  padding:13px 0;color:var(--text);
}
.bcp-accordion>summary::-webkit-details-marker{display:none}
.bcp-accordion>summary>span{display:flex;align-items:baseline;gap:8px;flex:1;min-width:0}
.bcp-accordion>summary b{font-family:var(--serif);font-size:var(--fs-body);font-weight:600;letter-spacing:.08em}
.bcp-accordion>summary small{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.14em}
.bcp-accordion>summary i{font-style:normal;color:var(--faint);flex-shrink:0;transition:transform .2s ease}
.bcp-accordion[open]>summary i{transform:rotate(180deg)}
.bcp-accordion-body{padding:0 0 16px}
.bcp-add-action{
  width:100%;padding:10px 12px;margin-bottom:10px;border:1px dashed var(--line);
  border-radius:var(--r-md);text-align:left;font-size:var(--fs-caption);letter-spacing:.03em;
  color:var(--muted);background:var(--surface2);
}
.bcp-add-action:active{opacity:.7}

/* 書庫:每本書一列,左側書脊色條(實體=強調色、電子=淡色)+ 形式膠囊 + 進度 */
.bcp-book{
  display:flex;align-items:center;gap:10px;background:var(--surface2);border:1px solid var(--line);
  border-radius:var(--r-md);padding:10px 12px 10px 0;margin-bottom:9px;overflow:hidden;
}
.bcp-book-spine{align-self:stretch;width:6px;flex-shrink:0;background:var(--accent);border-radius:0 3px 3px 0}
.bcp-book-spine.ebook{background:var(--faint)}
.bcp-book-meta{flex:1;min-width:0}
.bcp-book-title{font-family:var(--serif);font-weight:600;font-size:var(--fs-body-s);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bcp-book-sub{display:flex;align-items:center;gap:8px;margin-top:3px;min-width:0}
.bcp-chip{font-size:var(--fs-caption);color:var(--accent);border:1px solid var(--accent);border-radius:999px;padding:1px 8px;flex-shrink:0}
.bcp-progress{font-size:var(--fs-caption);color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bcp-progress.faint{color:var(--faint)}

/* 行內表單(書庫添書/編輯、開房/編輯房):虛線框比照交換日記撰寫區
   (.db-compose)語彙,直接嵌在頁面裡,打字不會誤觸背景收合 */
.bcp-book-form,.bcp-room-form{
  border:1.5px dashed var(--line);border-radius:var(--r-md);padding:13px;
  display:flex;flex-direction:column;gap:10px;margin-bottom:12px;
}
.bcp-room-form{gap:0}
.bcp-room-form .field{margin-bottom:12px}
.bcp-form-row{display:flex;gap:10px}
.bcp-form-row label{font-size:var(--fs-small);color:var(--muted);display:block;margin-bottom:6px}
.bcp-form-row input,.bcp-form-row select{width:100%}
.bcp-form-acts{display:flex;align-items:center;gap:8px;margin-top:2px}

/* 讀書會列表:書本封面縮圖 + 標題 + 出席書友頭貼列 */
.bcp-room{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-md);
  padding:11px 12px;margin-bottom:9px;
}
.bcp-room:active{background:var(--surface)}
.bcp-room-cover{
  width:44px;height:52px;border-radius:4px 8px 8px 4px;flex-shrink:0;
  background:var(--surface);border:1px solid var(--line);border-left:3px solid var(--accent);
  display:flex;align-items:center;justify-content:center;font-size:20px;
}
.bcp-room-meta{flex:1;min-width:0}
.bcp-room-title{font-family:var(--serif);font-weight:600;font-size:var(--fs-body-s);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bcp-room-sub{font-size:var(--fs-caption);color:var(--muted);margin-top:2px}
.bcp-room-avs{display:flex;gap:4px;margin-top:6px}
.bcp-room-avs .avatar{width:22px;height:22px;font-size:12px;border-radius:8px}

/* 遊戲大廳(第六輪):模式卡沿用上面的 .bcp-room 卡片語彙,不另刻一套;
   .gl-soon 是還沒開放的模式(鼓瑟吹笙・多人群玩),整張變淡、拿掉點擊游標。
   角色挑選 sheet 沿用 community.js 的 .comm-mention-item(見 bookclub.js
   openGameLobby1v1Picker),只是這裡多帶了頭像,頭像縮小到跟 .qp-group-head
   同一個尺寸,不然預設 50px 的 .avatar 在這種列表行裡太大。 */
.gl-soon{opacity:.55}
.gl-soon:active{background:var(--surface2)}
.gl-pick-item .avatar{width:28px;height:28px;font-size:14px;border-radius:10px}
.gl-pick-live{margin-left:auto;font-size:var(--fs-caption);color:var(--accent);flex-shrink:0}

/* 房間覆蓋層:結構比照 #chatroom(flex column、右滑進場);z-index 高於
   主頁面一階,房間永遠疊在主頁面之上 */
#bookclub-room{
  position:absolute;inset:0;height:100dvh;background:var(--bg);z-index:21;
  display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .32s cubic-bezier(.3,.9,.3,1);overflow:hidden;
}
#bookclub-room.open{transform:translateX(0)}
#bc-msgs{flex:1;overflow-y:auto;padding:18px 16px 10px;display:flex;flex-direction:column;gap:var(--sp-3)}
#bc-msgs[hidden]{display:none}
#bc-notes{flex:1;overflow-y:auto;padding:14px 16px calc(20px + env(safe-area-inset-bottom))}
#bc-notes[hidden]{display:none}
#bc-inputrow[hidden]{display:none}

/* 圓桌/重點 分頁切換 */
.bc-tabs{
  display:flex;gap:8px;padding:8px 16px 2px;flex-shrink:0;
}
.bc-tabs button{
  flex:1;padding:7px 0;border-radius:999px;font-size:var(--fs-body-s);color:var(--muted);
  background:var(--surface2);border:1px solid var(--line);transition:background .2s,color .2s;
}
.bc-tabs button.on{background:var(--accent);color:var(--accent-ink);border-color:transparent}
.bc-tabs[hidden]{display:none}

/* 討論串頂欄:返回重點列表 + 聚焦的重點標題 */
.bc-thread-head{
  display:flex;align-items:center;gap:6px;padding:6px 12px;flex-shrink:0;border-bottom:1px solid var(--line);
}
.bc-thread-head[hidden]{display:none}
.bc-thread-title{
  flex:1;min-width:0;font-size:var(--fs-body-s);color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* 群聊氣泡的發言者名字標籤(僅角色訊息;使用者靠右不需要) */
.bc-name{font-size:var(--fs-caption);color:var(--muted);margin:0 4px 3px}

/* 書中重點卡片 */
.bc-note-add{width:100%;justify-content:center;margin-bottom:12px}
.bc-note{
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:13px 14px;margin-bottom:12px;
}
.bc-note-head{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.bc-note-loc{flex:1;font-family:var(--serif);font-weight:600;font-size:var(--fs-body-s);letter-spacing:.05em}
.bc-note-excerpt{
  margin:0 0 8px;padding:6px 10px;border-left:3px solid var(--accent);
  font-size:var(--fs-body-s);color:var(--muted);line-height:1.7;white-space:pre-wrap;word-break:break-word;
}
.bc-note-gist{margin:0 0 8px;font-size:var(--fs-body-s);line-height:1.7;white-space:pre-wrap;word-break:break-word}
.bc-take{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:8px 10px;margin-bottom:7px;
}
.bc-take-who{display:block;font-size:var(--fs-caption);color:var(--accent);margin-bottom:3px;letter-spacing:.05em}
.bc-take p{margin:0;font-size:var(--fs-body-s);line-height:1.7;white-space:pre-wrap;word-break:break-word}
.bc-note-acts{display:flex;gap:8px;margin-top:9px}
.bc-note-acts .pill{flex:1;justify-content:center;padding:8px 0;font-size:var(--fs-caption)}
/* 重點的行內新增/編輯表單:沿用重點卡外框,改虛線(比照頁面上的行內表單語彙) */
.bc-note.bc-note-form{border-style:dashed;border-width:1.5px}
.bc-note-form .field{margin-bottom:10px}
.bc-note-form .bcp-form-row{margin-bottom:10px}
/* 章節欄位:輸入框 +「查章節」按鍵同一行,下方是已查章節的下拉挑選 */
.bcn-ch-row{display:flex;gap:6px;align-items:stretch}
.bcn-ch-row input{flex:1;min-width:0}
.bcn-ch-row #bcn-fetch-ch{flex-shrink:0;white-space:nowrap}
.bcn-ch-pick{margin-top:6px;width:100%;font-size:var(--fs-small)}

/* 開房 sheet:參加書友勾選列與帶入原關係開關。
   選擇器帶 label 提高特異度:上方全域 .field label{display:block;margin-bottom:6px}
   會蓋掉單類別選擇器,造成勾選列失去 flex 排版(比照 .anni-row .anni-once 的處理) */
.bc-char-picks{display:flex;flex-direction:column;gap:7px;max-height:34vh;overflow-y:auto}
label.bc-char-pick,button.bc-char-pick{
  display:flex;align-items:center;gap:10px;padding:7px 10px;width:100%;text-align:left;margin-bottom:0;
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-md);font-size:var(--fs-body-s);color:inherit;
}
.bc-char-pick input{width:16px;height:16px;accent-color:var(--accent);margin:0;flex-shrink:0}
.bc-char-pick .avatar{width:32px;height:32px;font-size:16px;border-radius:11px}
label.bc-rel-row{display:flex;align-items:center;gap:8px;margin-bottom:0;font-size:var(--fs-body-s);color:inherit}
.bc-rel-row input{width:16px;height:16px;accent-color:var(--accent);margin:0;flex-shrink:0}

/* 讀書會管理頁「角色書房」入口區塊:角色頭貼小卡的橫向排列 */
.cs-room-grid{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:4px}
.cs-room-card{
  display:flex;flex-direction:column;align-items:center;gap:6px;width:64px;
  padding:6px 2px;border-radius:var(--r-md);text-align:center;position:relative;
}
.cs-room-card:active{background:var(--surface2)}
.cs-room-card .avatar{width:46px;height:46px;font-size:20px;border-radius:14px}
/* 桌機版「書頁之間」欄位目前正內嵌顯示這位角色的書房(見 bookclub.js 的
   pageUI.studyCharId),手機版永遠不會有這個 class(手機版走整頁滑入)。 */
.cs-room-card.on{background:var(--surface2)}
.cs-room-card.on .avatar{box-shadow:0 0 0 2px var(--accent)}
.cs-room-card.on .cs-room-name{color:var(--accent)}
/* 去逛逛寫了新內容、還沒點開看過(見 char-study.js hasUnseenStudy)的紅點。
   掛在卡片本身而不是 .avatar 上——.avatar 另有 overflow:hidden(裁切頭貼成
   圓角用),掛在它的 ::after 會被連著裁掉,看不到點。 */
.cs-room-card.unseen::after{
  content:'';position:absolute;top:1px;right:4px;width:10px;height:10px;
  border-radius:50%;background:var(--danger,#e0526b);border:2px solid var(--bg);
}
.cs-room-name{font-size:var(--fs-caption);color:var(--muted);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ================= 他的書房覆蓋層(js/ui/char-study.js) =================
   結構比照 #bookclub-room(flex column、右滑進場),疊在 #bookclub-page 之上
   一階,z-index 高於 #bookclub-room(21)。收藏/社群卡片直接沿用讀書會的
   .bc-note/.bc-note-gist/.cc-src,只補本頁專屬的去逛逛列、篩選列、留言串
   與空狀態文字。筆記本(見下面「筆記本」區塊)不共用這套清單版型,是整個
   換掉 #cs-body 內容的獨立畫面。 */
#char-study-page{
  position:absolute;inset:0;height:100dvh;background:var(--bg);z-index:30;
  display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .32s cubic-bezier(.3,.9,.3,1);overflow:hidden;
}
#char-study-page.open{transform:translateX(0)}
#char-study-page .bc-tabs{padding-top:12px}
#cs-nb-write{font-size:17px;flex-shrink:0}
#cs-nb-write:disabled{opacity:.4}
#cs-roam-row{display:flex;flex-direction:column;gap:8px;padding:10px 16px 4px;flex-shrink:0}
.cs-roam-item{display:flex;align-items:center;gap:10px;background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-md);padding:8px 10px}
.cs-roam-item-label{flex:1;font-size:var(--fs-body-s);display:flex;flex-direction:column;gap:2px}
.cs-roam-item-label small{color:var(--faint);font-size:var(--fs-caption)}
#cs-roam-row .hint{margin:0}
#cs-web-search-link{align-self:flex-start;color:var(--accent);border-color:var(--accent)}
#cs-body{flex:1;overflow-y:auto;padding:14px 16px calc(20px + env(safe-area-inset-bottom))}
.cs-empty{text-align:center;color:var(--faint);padding:34px 10px}
.cs-card-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:8px;font-size:var(--fs-caption);color:var(--faint)}

/* 收藏/社群篩選列(主題/網站,見 filterBarHTML)。放在 #cs-body 最上方,
   跟卡片列表同一個捲動容器。 */
.cs-filter-row{display:flex;gap:8px;margin-bottom:12px}
.cs-filter-select{
  flex:1;min-width:0;padding:7px 9px;border-radius:var(--r-md);border:1px solid var(--line);
  background:var(--surface2);color:inherit;font-size:var(--fs-caption);
}
/* 收藏/社群卡片上的主題短標籤(見 topicBadgeHTML),掛在標題列右側 */
.cs-topic-badge{
  flex-shrink:0;padding:2px 8px;border-radius:99px;background:var(--surface2);
  border:1px solid var(--line);color:var(--muted);font-size:var(--fs-caption);
}

/* 留言串(收藏/社群/筆記本章節共用,見 commentBlockHTML)。 */
.cs-cm-list{display:flex;flex-direction:column;gap:6px;margin-top:10px}
.cs-cm{padding:7px 9px;border-radius:var(--r-md);background:var(--surface2);font-size:var(--fs-caption);line-height:1.6}
.cs-cm b{display:block;font-size:11px;color:var(--faint);margin-bottom:2px;font-weight:600}
.cs-cm p{margin:0}
.cs-cm.char{border-left:2px solid var(--accent)}
.cs-cm-form{display:flex;gap:6px;margin-top:8px}
.cs-cm-input{
  flex:1;min-width:0;padding:7px 9px;border-radius:var(--r-md);border:1px solid var(--line);
  background:var(--surface2);color:inherit;font-size:var(--fs-caption);
}

/* ================= 筆記本(js/ui/char-study.js 的 renderNotebookBody) =================
   不跟收藏/社群共用清單版型,點進「筆記本」是另外翻進一本獨立的書:目錄
   (toc)→章節扉頁(chapter)→內文(content)三層,#cs-body 整個換成這套畫面
   (加上 .cs-nb-stage class)。紙頁語彙借用交換日記 .book-inner 的內陰影
   書頁(見上面 1538 行的 .book-inner)、四角花邊借用圓桌讀書會 .bc-frame
   (見上面 3707 行),三層頁面內容一律橫式書寫(writing-mode 明講,不繼承
   書背 .mem-spine 那種直式排版)。 */
#cs-body.cs-nb-stage{
  overflow:hidden;position:relative;display:flex;
  padding:14px 14px calc(14px + env(safe-area-inset-bottom));
}
/* 底部 inset 補上 safe-area(比照 #bcp-stage>.bc-frame 的既有修法,見上面
   3707 行附近的 .bc-frame 註解):stage 的下 padding 比上/左/右多出一截
   home indicator 安全區,.bc-frame 預設 inset:0 會讓花框跟著多延伸那一截,
   底部花飾比上/左/右更遠離紙頁邊緣、看起來對不齊——這裡把 bc-frame 的
   下緣拉回只留 safe-area 那一截,四邊跟紙頁的間距才會一致。 */
#cs-body.cs-nb-stage>.bc-frame{--bcf:100px;z-index:2;inset:0 0 env(safe-area-inset-bottom) 0}
.cs-nb-page{
  flex:1;height:100%;overflow-y:auto;background:var(--surface);border:1px solid var(--line);
  border-radius:8px 16px 16px 8px;box-shadow:inset 3px 0 8px rgba(0,0,0,.12);
  padding:30px 22px 34px;position:relative;z-index:1;
  writing-mode:horizontal-tb;display:flex;flex-direction:column;
}
.cs-nb-back{align-self:flex-start;flex-shrink:0;margin-bottom:16px}
/* 目錄:角色自訂標題的章節清單,虛線分隔像手寫目錄的頁緣 */
.cs-nb-toc-title{
  font-family:var(--serif);font-size:var(--fs-title-s);font-weight:600;letter-spacing:.3em;
  text-align:center;color:var(--accent);margin-bottom:22px;flex-shrink:0;
}
.cs-nb-toc-list{display:flex;flex-direction:column}
.cs-nb-toc-entry{
  display:flex;align-items:center;gap:8px;padding:14px 4px;cursor:pointer;
  border-bottom:1px dashed var(--line);
}
.cs-nb-toc-entry:active{background:color-mix(in srgb, var(--accent) 8%, transparent)}
.cs-nb-toc-entry-title{
  flex:1;font-family:var(--serif);font-size:var(--fs-body-s);letter-spacing:.05em;
}
/* 這個章節底下累積了幾篇獨立內容(entries,見 runNotebookWrite),讓使用者
   進去前就知道不是只有一篇 */
.cs-nb-toc-entry-count{
  flex-shrink:0;min-width:20px;text-align:center;padding:1px 6px;border-radius:99px;
  background:var(--surface2);border:1px solid var(--line);color:var(--faint);font-size:var(--fs-caption);
}
.cs-nb-empty{margin:auto;text-align:center;color:var(--faint);padding:20px}
/* 章節扉頁:只有標題,輕觸翻開才進內文;上鎖章節在同一頁改顯示密碼表單 */
.cs-nb-chapter-divider{flex:1;display:flex;flex-direction:column;min-height:0}
.cs-nb-chapter-open,.cs-nb-chapter-locked{
  flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:16px;text-align:center;
}
.cs-nb-chapter-open{cursor:pointer}
.cs-nb-chapter-title{
  font-family:var(--serif);font-size:var(--fs-title-s);font-weight:600;letter-spacing:.15em;color:var(--text);
}
.cs-nb-chapter-hint{font-size:var(--fs-caption);color:var(--faint);letter-spacing:.2em}
.cs-nb-chapter-locked .cs-cm-form{width:100%;max-width:260px}
/* 內文:章節標題下方是一篇一篇獨立的內容(.cs-nb-entry,見 runNotebookWrite
   的新增邏輯與 notebookEntryHTML),不是一整篇連續長文——每篇各自有時間、
   各自一套留言串(.cs-cm-block,跟收藏/社群項目共用同一套樣式),彼此用
   虛線分隔,呼應目錄清單同一種「一條一條」的手寫筆記感。 */
.cs-nb-content{display:flex;flex-direction:column}
.cs-nb-content-title{
  font-family:var(--serif);font-size:var(--fs-body);font-weight:600;letter-spacing:.08em;
  margin-bottom:18px;text-align:center;flex-shrink:0;
}
.cs-nb-entry{padding:16px 0;border-bottom:1px dashed var(--line)}
.cs-nb-entry:last-child{border-bottom:none;padding-bottom:0}
.cs-nb-entry-text{
  font-family:var(--serif);font-size:var(--fs-body-s);line-height:2;white-space:pre-wrap;
  word-break:break-word;margin-bottom:8px;
}

/* ================= 遊戲大廳 · 遊戲房覆蓋層(js/ui/game-room.js) =================
   兩層,結構都比照 #bookclub-room/#char-study-page(flex column、右滑進場):
   #game-room-page 是這位角色的場次清單(疊在 #bookclub-page 之上,z-index
   比 #char-study-page 高一階,兩者不會同時開著);#game-room-session 疊在
   #game-room-page 之上,是單一場次的獨立對話串,版面沿用聊天室
   (.chat-head/.chat-input/.msg-row/.msg/.bubble/.ts/.msg-avatar-slot),
   不另刻一套訊息氣泡樣式。 */
#game-room-page{
  position:absolute;inset:0;height:100dvh;background:var(--bg);z-index:31;
  display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .32s cubic-bezier(.3,.9,.3,1);overflow:hidden;
}
#game-room-page.open{transform:translateX(0)}
#gr-list-body{flex:1;overflow-y:auto;padding:14px 16px calc(20px + env(safe-area-inset-bottom))}
.gr-list-head{margin-bottom:14px}
.gr-list-head .pill{width:100%;justify-content:center;padding:11px}
.gr-sessions{display:flex;flex-direction:column;gap:9px}
.gr-session-row{
  display:flex;align-items:stretch;gap:6px;width:100%;
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-md);
  overflow:hidden;
}
.gr-session-open{
  flex:1;min-width:0;display:flex;align-items:center;gap:10px;text-align:left;
  padding:11px 12px;background:transparent;
}
.gr-session-open:active{background:var(--surface)}
.gr-session-del{
  flex-shrink:0;width:38px;display:flex;align-items:center;justify-content:center;
  color:var(--faint);font-size:15px;border-left:1px solid var(--line);background:transparent;
}
.gr-session-del:active{background:var(--surface);color:var(--danger,#c0392b)}
.gr-session-meta{flex:1;min-width:0}
.gr-session-title{font-family:var(--serif);font-weight:600;font-size:var(--fs-body-s);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gr-session-sub{font-size:var(--fs-caption);color:var(--muted);margin-top:2px}
.gr-session-time{font-size:var(--fs-caption);color:var(--faint);flex-shrink:0}

#game-room-session{
  position:absolute;inset:0;height:100dvh;background:var(--bg);z-index:32;
  display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .32s cubic-bezier(.3,.9,.3,1);overflow:hidden;
}
#game-room-session.open{transform:translateX(0)}
#gr-msgs{flex:1;overflow-y:auto;padding:18px 12px 10px;display:flex;flex-direction:column;gap:var(--sp-3)}
/* 遊戲房是長文敘事場——角色/荷官的回應氣泡放寬(一般聊天室 78%) */
#gr-msgs .msg.ai .bubble{max-width:96%}
#gr-msgs .msg.me .bubble{max-width:88%}
#gr-msgs .msg-avatar-slot{width:26px;height:26px}

/* 階段 3c:常駐棋盤面板 ＋ 對峙列 ＋ 安全詞鈕(比照露比美化包「固定的固定住、
   只有對話是捲軸」的版面,重上 Metaxy 主題色)。 */
#gr-board-panel{
  flex-shrink:0;display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:0 12px 8px;border-bottom:1px solid var(--line);background:var(--surface);
}
#gr-board-panel.is-collapsed{padding-bottom:0;gap:0}
#gr-board-panel .mono-board-grid{max-width:min(190px,42vw);margin:0}
@media (max-height:680px){ #gr-board-panel .mono-board-grid{max-width:150px} }
/* 收合把手:貼在 top bar 下方,點一下把棋盤收起 / 展開 */
.gr-board-handle{
  width:100%;display:flex;align-items:center;justify-content:space-between;
  padding:5px 2px;font-size:var(--fs-caption);color:var(--muted);
  background:none;border:none;cursor:pointer;
}
.gr-board-chev{color:var(--faint)}
.gr-standoff{
  display:flex;flex-wrap:wrap;justify-content:center;gap:4px 8px;width:100%;
}
.gr-so-seat{
  display:flex;align-items:center;gap:5px;font-size:var(--fs-caption);cursor:pointer;
  color:var(--muted);padding:3px 8px;border-radius:var(--r-xl);border:1px solid var(--line);background:var(--surface2);
}
.gr-so-seat.is-turn{border-color:var(--accent);color:var(--text);background:var(--accent-soft)}
.gr-so-seat.is-open{border-color:var(--accent)}
.gr-so-dot{width:9px;height:9px;border-radius:50%;background:var(--pc,var(--accent));flex-shrink:0}
.gr-so-name{font-weight:600;color:var(--text)}
.gr-so-stat{font-variant-numeric:tabular-nums}
/* 點某席 → 詳細身分 + 狀況 */
.gr-so-detail{
  width:100%;padding:9px 11px;border:1px solid var(--accent);border-radius:var(--r-md);
  background:var(--surface2);font-size:var(--fs-caption);line-height:1.7;
}
.gr-so-detail-h{font-weight:700;color:var(--text);margin-bottom:3px}
.gr-so-detail-stat{color:var(--text);font-variant-numeric:tabular-nums;margin-bottom:4px}
.gr-so-detail-id{color:var(--accent);font-weight:600;margin-bottom:3px}
.gr-so-detail-ln{color:var(--muted);padding-left:2px}
/* 輸入列上方的快速鍵列(「」/換行/404)——比照聊天室 #kb-tools。整條不透明,
   把後方頁面(含 #tabbar)確實蓋住。 */
.gr-kbrow{
  flex-shrink:0;display:flex;align-items:center;gap:6px;padding:6px 12px;
  border-top:1px solid var(--line);background:var(--bg);
}
/* 「你現在扮演誰」頭像鈕 */
.gr-persona-btn{
  display:flex;align-items:center;gap:5px;padding:3px 9px 3px 3px;cursor:pointer;
  font-size:var(--fs-caption);color:var(--text);
  background:var(--accent-soft);border:1px solid var(--accent);border-radius:var(--r-xl);
}
.gr-persona-av{
  width:22px;height:22px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;font-size:12px;background:var(--surface2);
}
.gr-persona-av img{width:100%;height:100%;object-fit:cover}
.gr-persona-chev{color:var(--accent);font-size:11px}
.gr-kbkey{
  padding:5px 11px;font-size:var(--fs-caption);color:var(--muted);cursor:pointer;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xl);
}
.gr-kbkey:active{background:var(--surface2)}
.gr-kb-safeword{margin-left:auto;font-weight:700;letter-spacing:.04em;color:var(--danger);border-color:var(--danger)}
.gr-kb-safeword:active{background:var(--danger);color:#fff}

/* 階段 3d:遊戲房自訂桌布(見 game-room.js applyGameRoomBg)。桌布上壓一層
   濃暗紗(gradient 疊在圖上面),露比美化包:自訂圖亮度不定、暗紗要壓重才
   保證字看得清。暗紗顏色跟主題走(亮色主題用亮紗)。 */
:root{ --gr-scrim:rgba(17,15,19,.60); --gr-scrim2:rgba(17,15,19,.83); }
[data-theme="shiro"],[data-theme="ichigo"]{ --gr-scrim:rgba(250,249,247,.68); --gr-scrim2:rgba(250,249,247,.88); }
#game-room-page.gr-has-bg,#game-room-session.gr-has-bg{
  background-image:linear-gradient(var(--gr-scrim),var(--gr-scrim2)),var(--gr-bg-img);
  background-size:cover;background-position:center;background-repeat:no-repeat;
}
/* 桌布透出來的地方:對話捲軸區、場次清單區不要自帶不透明底 */
#game-room-session.gr-has-bg #gr-msgs,
#game-room-page.gr-has-bg #gr-list-body{background:transparent}
.gr-tablebg-row{display:flex;gap:6px;margin-top:8px}
.gr-tablebg-row .tag{font-size:var(--fs-caption)}
