  :root{
    --bg:#0a080e;
    --panel:#120f1a;
    --ink:#ece6d8;
    --gold:#d4a94a;
    --gold-dim:#8a6d2e;
    --blood:#8a1f1f;
    --holy:#6fb3d4;
    --grid:#1c1628;
    --grid-active:#2e2440;
    --danger:#c0392b;
    /* iPhone 瀏海/動態島：頂部保留真實墊高，把「底圖 + 結算 + 控制列」整體下移（非覆蓋）。
       墊高 = 安全區 + --notch-extra 呼吸餘裕。桌面（無瀏海）safe-area=0，--notch-extra 預設 0 → 完全不佔空間、無突兀帶子。
       作者要多留一點呼吸感可調大 --notch-extra。 */
    --notch-extra:0px;
    --notch-bar-h:calc(env(safe-area-inset-top, 0px) + var(--notch-extra));
    --notch-orn:var(--gold);
  }
  /* touch-action:manipulation＝取消「雙擊縮放」（快速連點盤面不再觸發放大；亦消 300ms 點擊延遲）。
     viewport 的 user-scalable=no 在 iOS Safari 被無障礙政策忽略，須靠此宣告。
     個別需要完整攔截的元素（#returnSwipe none／選單 pan-x·pan-y）具體度較高，不受影響。 */
  *{box-sizing:border-box;-webkit-tap-highlight-color:transparent;
    -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;
    touch-action:manipulation;}
  /* 全域禁圖片拖拉：桌機滑鼠在圖上按住拖動會觸發原生 drag、吃掉 pointermove，
     聖徒化左右滑/生命歸還上滑等手勢會斷（Firefox 另靠 main.js 的 dragstart 攔截） */
  img{-webkit-user-drag:none;user-drag:none;}
  /* overscroll-behavior:none＝斷開 overscroll 鏈結：部分瀏覽器/內嵌 WebView 以水平
     overscroll 觸發上下頁導航，本遊戲全域不捲動故一律關閉 */
  html,body{margin:0;padding:0;width:auto;height:auto;background:var(--bg);
    overflow:hidden;overscroll-behavior:none;position:fixed;top:0;left:0;right:0;bottom:0;
    font-family:"Iowan Old Style","Palatino Linotype",Georgia,"Songti TC",serif;color:var(--ink);}
  /* 多語字體適配：lang 由 i18n.applyToDom 依語言寫入 <html>。日文改優先日文明朝
     （假名/和製漢字字形與字寬正確，避免以中文宋體代打造成版面跑位） */
  html[lang="ja"], html[lang="ja"] body{
    font-family:"Iowan Old Style","Palatino Linotype",Georgia,"Hiragino Mincho ProN",
      "Yu Mincho","Noto Serif JP","Songti TC",serif;}
  /* 觸底不用 100%/100dvh：iOS「加入主畫面」(standalone) 的 dvh 會保留幽靈工具列高度，
     底部露出一截畫布死區 → 改 fixed + 四邊 inset:0 直接撐滿視窗，不經 vh/dvh 單位計算 */
  /* iOS 26 standalone 容器 bug：視窗高 = 螢幕高 − 頂部安全區、錯錨在螢幕頂，底部差值區
     為 webview 外完全不可視死區——100vh 撐高會讓內容伸進去被裁（戰鬥盤面遭蓋，已撤回）、
     狀態列改 black 亦遭忽略。定案：接受死區為底部邊框，html.vp-clipped（index.html 偵測）
     模式下拿回「白墊在死區裡的底部安全區」還給內容（首頁底排／結算鈕，見各處規則）。 */
  /* ===== 載入畫面（#assetLoader 由 main.js 動態建立）=====
     頂部細讀取條＋百分比；中下方監察官立繪＋對話框輪播教學 Hint；底部「點擊繼續」。 */
  #assetLoader{position:fixed;inset:0;z-index:99999;background:#0a0812;color:#d9c68a;
    font-family:inherit;transition:opacity .5s ease;overflow:hidden;}
  /* 金色光圈讀取：與首頁紋章外圓重合（位置/圈徑由 main.js placeRing 依 #homeEmblem 實測；
     量不到前用此處預設保底）。進度沿圈順時針推進；圈內上=百分比、下=Saint Installation。 */
  #assetLoader #alRing{position:absolute;left:50%;top:23%;width:200px;height:200px;
    transform:translate(-50%,-50%);border-radius:50%;
    animation:alRingGlow 2.4s ease-in-out infinite;}
  #assetLoader #alRing svg{position:absolute;inset:0;width:100%;height:100%;
    transform:rotate(-90deg);overflow:visible;}   /* -90°：進度自 12 點鐘起、順時針 */
  #assetLoader .al-rail{fill:none;stroke:rgba(217,198,138,.18);stroke-width:2.5;}
  #assetLoader .al-prog{fill:none;stroke:var(--gold);stroke-width:2.5;stroke-linecap:round;
    transition:stroke-dashoffset .25s ease;filter:drop-shadow(0 0 4px rgba(217,198,138,.7));}
  @keyframes alRingGlow{
    0%,100%{box-shadow:0 0 6px rgba(217,198,138,.18),inset 0 0 8px rgba(217,198,138,.1);}
    50%{box-shadow:0 0 22px rgba(217,198,138,.5),inset 0 0 14px rgba(217,198,138,.25);}}
  /* 圈內文字：上百分比、下 Saint Installation，呼吸發光 */
  #assetLoader #alRingTxt{position:absolute;inset:0;display:flex;flex-direction:column;
    align-items:center;justify-content:center;gap:7px;
    animation:alTextBreath 2.4s ease-in-out infinite;}
  #assetLoader #assetLoaderPct{font-size:24px;letter-spacing:2px;color:var(--gold);
    font-variant-numeric:tabular-nums;}
  #assetLoader #alRingCap{font-size:10.5px;letter-spacing:3px;color:var(--gold);opacity:.85;}
  @keyframes alTextBreath{
    0%,100%{text-shadow:0 0 4px rgba(217,198,138,.25);opacity:.8;}
    50%{text-shadow:0 0 14px rgba(217,198,138,.85);opacity:1;}}
  /* 讀取完成（.al-done）：整圈常亮發光、Complete 字樣 */
  #assetLoader.al-done #alRing{animation:alRingDone 1.8s ease-in-out infinite;}
  @keyframes alRingDone{
    0%,100%{box-shadow:0 0 18px rgba(232,217,168,.55),inset 0 0 14px rgba(232,217,168,.3);}
    50%{box-shadow:0 0 34px rgba(255,244,214,.85),inset 0 0 22px rgba(232,217,168,.45);}}
  #assetLoader.al-done .al-prog{stroke:#e8d9a8;filter:drop-shadow(0 0 8px rgba(255,244,214,.9));}
  #assetLoader.al-done #alRingCap{font-size:13px;letter-spacing:5px;opacity:1;}
  /* 點擊後聖光綻放：以光圈為中心「緩慢」擴張的暖金白光暈，邊緣多層羽化半透明、無光束。
     2.5s 綻放蓋滿 → 撤遮罩 → 1.2s 淡出揭開主選單，總長 ≈3.7s 與 SI_01(3.7s) 等長連動。
     --fl-scale 由 JS 依螢幕算（光暈實心 30% 需蓋滿全畫面）。 */
  #alFlash{position:fixed;z-index:100000;transform:translate(-50%,-50%) scale(.85);
    opacity:1;pointer-events:none;
    transition:transform 2.5s cubic-bezier(.3,.35,.25,1),opacity 1.2s ease;}
  #alFlash.grow{transform:translate(-50%,-50%) scale(var(--fl-scale,16));}
  #alFlash.fade{opacity:0;}
  /* 光暈：暖金白核心，往外多層羽化 */
  #alFlash .fl-glow{position:absolute;inset:0;border-radius:50%;
    background:radial-gradient(circle,
      #fff 0%, #fff 30%,
      rgba(255,247,226,.92) 46%,
      rgba(255,239,202,.55) 62%,
      rgba(255,233,184,.24) 80%,
      rgba(255,233,184,0)   100%);}
  /* 監察官立繪舞台：吃畫面下半，立繪 contain 貼底（同結算 inspectorStage 的語言） */
  #assetLoader #alStage{position:absolute;left:0;right:0;bottom:0;height:64%;
    display:flex;justify-content:center;align-items:flex-end;pointer-events:none;}
  #assetLoader #alPortrait{width:auto;max-width:88%;max-height:100%;object-fit:contain;object-position:bottom;
    filter:drop-shadow(0 6px 24px rgba(0,0,0,.7));opacity:0;transition:opacity .6s ease;
    -webkit-mask-image:linear-gradient(to bottom,#000 86%,transparent 100%);
    mask-image:linear-gradient(to bottom,#000 86%,transparent 100%);}
  #assetLoader #alPortrait.on{opacity:1;}
  /* 對話框：疊在立繪偏下（同結算 inspectorBubble 樣式） */
  #assetLoader #alBubble{position:absolute;left:50%;bottom:15%;transform:translateX(-50%);
    width:82%;max-width:300px;background:rgba(16,12,24,.72);
    border:1px solid var(--gold-dim);border-radius:8px;padding:10px 13px;text-align:left;
    box-shadow:0 4px 20px rgba(0,0,0,.55);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);}
  #assetLoader .al-name{font-size:11px;letter-spacing:2px;color:var(--gold);margin-bottom:5px;opacity:.9;}
  /* Hint：整句淡入停留淡出（不打字）；min-height 兩行防換句時框體跳動 */
  #assetLoader .al-hint{font-size:13px;letter-spacing:.5px;line-height:1.6;color:var(--ink);
    min-height:3.2em;opacity:0;transition:opacity .4s ease;}
  #assetLoader .al-hint.show{opacity:1;}
  /* 語言切換鈕（讀取畫面版）：與首頁 #langBtn 同款同位，讀取中即可切換語言 */
  #assetLoader #alLangBtn{position:absolute;top:calc(var(--notch-bar-h,0px) + 12px);right:12px;
    min-width:44px;height:36px;padding:0 14px;border-radius:18px;background:rgba(10,8,14,.6);
    border:1px solid var(--gold-dim);color:var(--gold);font-family:inherit;font-size:14px;
    letter-spacing:1px;}
  #assetLoader #alLangBtn:active{transform:scale(.92);}
  /* 底部訊息：載入中 → 點擊繼續（呼吸） */
  #assetLoader #alMsg{position:absolute;left:0;right:0;
    bottom:calc(env(safe-area-inset-bottom,0px) + 26px);
    text-align:center;font-size:14px;letter-spacing:4px;}
  html.vp-clipped #assetLoader #alMsg{bottom:26px;}   /* 視窗被裁：安全區在死區裡，白墊拿回 */
  @keyframes alPulse{0%,100%{opacity:.45}50%{opacity:1}}
  #assetLoader .al-pulse{animation:alPulse 1.5s ease-in-out infinite;}
  /* 退出確認：數字盤模糊到看不清 + 半暗遮罩 + 面板 */
  /* 暫停：直接隱藏整個數字盤（淡出），避免暫停時偷看盤面 */
  #grid.grid-blur{opacity:0;pointer-events:none;}
  #grid{transition:opacity .15s ease-out;}   /* 暫停隱藏/恢復顯示皆有淡入淡出 */
  /* ⚠ 不用 backdrop-filter:iOS 對 backdrop 快照含「動畫 filter / 大範圍光暈」圖層
     (敵亮攻框時的黃圈+alert 脈動)會把光暈爆染成整面變黃。改純半透明底加深補償。 */
  /* #tutSkipConfirm（跳過教學確認，tutorial.js 動態建立）共用同一套面板樣式 */
  #exitConfirm, #tutSkipConfirm{position:fixed;inset:0;z-index:9500;display:flex;align-items:center;justify-content:center;
    background:rgba(6,4,12,.72);}
  #exitConfirm .ec-panel, #tutSkipConfirm .ec-panel{width:min(82%,320px);text-align:center;padding:22px 20px;border-radius:12px;
    background:linear-gradient(180deg,rgba(30,24,42,.98),rgba(16,12,24,.98));
    border:1px solid var(--gold-dim);box-shadow:0 12px 44px rgba(0,0,0,.6);}
  #exitConfirm .ec-title, #tutSkipConfirm .ec-title{font-size:17px;letter-spacing:3px;color:var(--gold);margin-bottom:8px;}
  #exitConfirm .ec-sub, #tutSkipConfirm .ec-sub{font-size:11px;letter-spacing:1px;color:var(--gold-dim);margin-bottom:18px;}
  #exitConfirm .ec-btns, #tutSkipConfirm .ec-btns{display:flex;gap:12px;}
  #exitConfirm .ec-btns button, #tutSkipConfirm .ec-btns button{flex:1;padding:11px 0;border-radius:8px;font-family:inherit;font-size:13px;
    letter-spacing:2px;border:1px solid var(--gold-dim);background:transparent;color:var(--ink);}
  #exitConfirm .ec-btns .ec-yes, #tutSkipConfirm .ec-btns .ec-yes{border-color:var(--gold);color:var(--gold);}
  #exitConfirm .ec-btns button:active, #tutSkipConfirm .ec-btns button:active{transform:scale(.97);}
  #app{display:flex;flex-direction:column;height:100%;width:100%;
    max-width:520px;margin:0 auto;position:relative;
    /* 頂部保留安全區墊高：#top（底圖）與 #bottom 為 flex 子項，會被此 padding 整體下移到瀏海之下 */
    padding-top:var(--notch-bar-h);}
  /* 戰敗定格：HP 歸零瞬間全畫面黑白（快速壓入），維持約 1 秒後才切「驅逐失敗」過渡禎 */
  #app.death-freeze{filter:grayscale(1) contrast(1.06) brightness(.9);
    transition:filter .18s ease-out;}

  /* ===== 上半：敵人（固定 50%） ===== */
  /* touch-action:none＝本區觸控全由 JS 接管（聖徒化左右滑）：內嵌瀏覽器（巴哈 app 等
     WebView）的左右滑切頁/返回屬原生手勢，需本宣告＋touchmove preventDefault 才讓位。
     盤面與紅點的點擊不受影響（touch-action 只管平移/縮放預設行為）。 */
  #top{height:50%;flex:none;position:relative;overflow:hidden;
    border-bottom:2px solid var(--gold-dim);background:#000;touch-action:none;}
  #enemyImg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
    object-position:center top;transition:transform .06s;}
  #enemyImg.hit{transform:scale(1.015);}
  #enemyImg.shake{animation:camShake .3s;}
  @keyframes camShake{0%,100%{transform:translate(0,0)}
    20%{transform:translate(-6px,4px)}40%{transform:translate(5px,-3px)}
    60%{transform:translate(-4px,-4px)}80%{transform:translate(4px,3px)}}
  /* 連戰換敵：敵人區「前進遭遇」進場（僅敵人區、非 cut-in、盤面不動）。
     leave＝舊敵被掠過（放大＋淡出、變暗）；enter＝新敵自遠處逼近（縮入＋提亮淡入）。 */
  #enemyImg.enemy-leave{animation:enemyLeave .26s ease-in forwards;}
  @keyframes enemyLeave{to{transform:scale(1.18);opacity:0;filter:brightness(.35)}}
  #enemyImg.enemy-enter{animation:enemyEnter .56s cubic-bezier(.2,.7,.25,1);}
  @keyframes enemyEnter{0%{transform:scale(1.4);opacity:0;filter:brightness(1.7)}
    100%{transform:scale(1);opacity:1;filter:brightness(1)}}
  #topVignette{position:absolute;inset:0;pointer-events:none;
    background:radial-gradient(120% 80% at 50% 20%,transparent 40%,rgba(0,0,0,.7) 100%);}

  /* HUD：敵人名稱（頂部） */
  #hud{position:absolute;top:8px;left:0;right:0;padding:0 14px;pointer-events:none;z-index:6;}
  .enemy-name{font-size:11px;letter-spacing:3px;color:var(--gold);opacity:.9;
    text-shadow:0 0 8px #000,0 1px 2px #000;text-align:center;}

  /* ===== 敵我血條：橫置於敵人區下方，敵上我下 ===== */
  /* 破防值計量表以 C 字型扣在兩條血量的左側 */
  #barsBlock{position:absolute;left:0;right:0;bottom:6px;z-index:6;pointer-events:none;
    display:flex;align-items:stretch;gap:8px;padding:0 12px 2px;}
  /* C 字型破防計量表 */
  #energyClasp{flex:none;width:20px;position:relative;align-self:stretch;touch-action:manipulation;pointer-events:none;}
  #energyClasp.full{cursor:pointer;pointer-events:auto;}
  /* 滿值時擴大點擊熱區，讓細長計量表更好按 */
  #energyClasp.full::before{content:"";position:absolute;top:0;bottom:0;left:-10px;right:-6px;}
  /* 滿檔加強光暈：drop-shadow 加倍層 + ::after 呼吸光暈橢圓（::before 已作觸控擴區） */
  #energyClasp.full svg{filter:drop-shadow(0 0 10px var(--holy)) drop-shadow(0 0 22px rgba(111,179,212,.75)) drop-shadow(0 0 4px #000);}
  #energyClasp.full::after{content:"";position:absolute;left:50%;top:50%;width:46px;height:70px;
    transform:translate(-50%,-50%);border-radius:50%;pointer-events:none;
    background:radial-gradient(ellipse at center, rgba(150,215,245,.32), transparent 70%);
    animation:claspHalo 1.1s ease-in-out infinite alternate;}
  @keyframes claspHalo{from{opacity:.5;transform:translate(-50%,-50%) scale(.9);}
    to{opacity:1;transform:translate(-50%,-50%) scale(1.18);}}
  /* 破防值滿瞬間：以計量表為中心擴散的半透漸層光圈（JS 動態掛 .energy-burst 於 body） */
  .energy-burst{position:fixed;width:190px;height:190px;z-index:45;pointer-events:none;border-radius:50%;
    background:radial-gradient(circle, rgba(150,215,245,0) 52%, rgba(150,215,245,.4) 66%,
      rgba(205,240,255,.8) 75%, rgba(150,215,245,.3) 84%, transparent 93%);
    transform:translate(-50%,-50%) scale(.22);opacity:.95;
    animation:energyBurst .85s cubic-bezier(.2,.7,.3,1) forwards;}
  @keyframes energyBurst{70%{opacity:.55;}100%{transform:translate(-50%,-50%) scale(1);opacity:0;}}
  #energyClasp svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;
    filter:drop-shadow(0 0 4px #000);}
  #energyClasp .clasp-track{fill:none;stroke:rgba(0,0,0,.7);stroke-width:6;}
  #energyClasp .clasp-fill{fill:none;stroke:var(--gold);stroke-width:6;stroke-linecap:round;
    transition:stroke-dashoffset .25s;}
  #energyClasp.full .clasp-fill{stroke:#ffe08a;animation:pulse .6s infinite alternate;}
  /* 兩條橫向血條 */
  #barStack{flex:1 1 0;display:flex;flex-direction:column;gap:5px;min-width:0;}
  .hrow{position:relative;}
  .hpbar{height:14px;background:rgba(0,0,0,.75);border:1px solid var(--gold-dim);
    border-radius:3px;overflow:hidden;box-shadow:0 0 10px #000;}
  .hpbar.enemy-bar{border-color:var(--gold-dim);}
  .hpbar.player-bar{border-color:var(--holy);}
  .hpbar>i{display:block;height:100%;transition:width .25s;}
  .hpbar.enemy-bar>i{background:linear-gradient(90deg,var(--blood),#d14e4e);}
  .hpbar.player-bar>i{background:linear-gradient(90deg,#2b6d9a,var(--holy));}
  /* ── 聖徒化回血特效（saint.js 掛 .saint-heal 於 .player-bar）──
     血條轉金；亮紋自左向右流動「聚集」到末端；末端騎在填充前緣的呼吸強光點。
     overflow:visible 讓光點光暈溢出條外（填充改小圓角補償失去的裁切）。 */
  .hpbar.player-bar.saint-heal{border-color:var(--gold);overflow:visible;
    box-shadow:0 0 10px rgba(212,169,74,.55),0 0 10px #000;}
  .hpbar.player-bar.saint-heal>i{position:relative;border-radius:2px;
    background:linear-gradient(90deg,#8a6d2e,#ffd970 70%,#fff3c4);
    box-shadow:0 0 8px rgba(255,224,138,.7);}
  .hpbar.player-bar.saint-heal>i::before{content:"";position:absolute;inset:0;border-radius:2px;
    background:repeating-linear-gradient(90deg,transparent 0 16px,rgba(255,255,255,.38) 16px 19px);
    animation:healFlow .5s linear infinite;
    -webkit-mask-image:linear-gradient(90deg,transparent,#000 55%);
    mask-image:linear-gradient(90deg,transparent,#000 55%);}
  @keyframes healFlow{from{background-position:0 0;}to{background-position:19px 0;}}
  .hpbar.player-bar.saint-heal>i::after{content:"";position:absolute;right:-7px;top:50%;
    width:14px;height:14px;transform:translateY(-50%);border-radius:50%;
    background:radial-gradient(circle,#fff 0%,#ffe9a8 40%,rgba(255,224,138,.4) 65%,transparent 75%);
    box-shadow:0 0 12px 4px rgba(255,224,138,.85),0 0 26px 8px rgba(212,169,74,.5);
    animation:healOrb .7s ease-in-out infinite alternate;}
  @keyframes healOrb{from{transform:translateY(-50%) scale(.85);}to{transform:translateY(-50%) scale(1.2);}}
  .hp-num{position:absolute;right:5px;top:0;height:14px;line-height:14px;
    font-size:9px;letter-spacing:1px;opacity:.9;text-shadow:0 0 4px #000,0 0 3px #000;}

  /* 蓄力預警（倒數數字/招式名已取消，紅圈即提示；容器保留供 defense 開閉） */
  #chargeWarn{position:absolute;top:52px;left:0;right:0;text-align:center;display:none;z-index:7;pointer-events:none;}
  #chargeWarn.on{display:block;}
  @keyframes blink{from{opacity:.5}to{opacity:1}}

  /* 特效層（槍擊命中、彈殼、爪痕、飄字都畫在這） */
  #fxTop{position:absolute;inset:0;pointer-events:none;z-index:5;overflow:hidden;}
  .muzzle{position:absolute;width:54px;height:54px;margin:-27px;pointer-events:none;
    background:radial-gradient(circle,#fff 0%,#ffe08a 30%,rgba(212,169,74,.6) 55%,transparent 70%);
    animation:muzzle .18s ease-out forwards;}
  @keyframes muzzle{from{opacity:1;transform:scale(.5) rotate(0)}
    to{opacity:0;transform:scale(1.4) rotate(25deg)}}
  .spark{position:absolute;width:3px;height:14px;background:linear-gradient(#fff,#d4a94a);
    pointer-events:none;animation:spark .25s ease-out forwards;transform-origin:center;}
  @keyframes spark{from{opacity:1}to{opacity:0;transform:translateY(-18px) scaleY(.3)}}
  .dmgnum{position:absolute;font-size:18px;font-weight:bold;color:var(--gold);
    text-shadow:0 0 8px #000;pointer-events:none;animation:floatup .7s ease-out forwards;}
  .critnum{color:#fff;font-size:26px;text-shadow:0 0 12px var(--danger),0 0 4px #fff;}
  .snipernum{color:#ff3232;font-size:42px;text-shadow:0 0 18px var(--danger),0 0 6px #fff;}
  @keyframes floatup{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-40px)}}

  /* 爪痕（被攻擊） */
  #claw{position:absolute;inset:0;pointer-events:none;opacity:0;z-index:8;}
  #claw.on{animation:clawFlash .5s ease-out;}
  @keyframes clawFlash{0%{opacity:0}15%{opacity:1}100%{opacity:0}}
  #redFlash{position:absolute;inset:0;background:radial-gradient(circle at 50% 50%,transparent 30%,rgba(150,0,0,.55));
    opacity:0;pointer-events:none;z-index:7;}

  /* v17.2：受擊特效三件套（血痕／齒痕／彈痕）＋防禦統一閃光。皆畫在 #hitFxLayer(z-8)。 */
  #hitFxLayer{position:absolute;inset:0;pointer-events:none;z-index:8;overflow:hidden;}
  #hitFxLayer .fx{position:absolute;pointer-events:none;will-change:opacity,transform;}
  /* 血痕：一道斜向割裂，紅色漸層，隨機角度由 --deg 控制 */
  .fx-blood{left:50%;top:46%;width:260px;height:52px;margin:-26px 0 0 -130px;
    transform:translate(-50%,-50%) rotate(var(--deg,20deg)) scaleX(.2);
    background:linear-gradient(90deg,transparent,rgba(190,20,20,0) 8%,rgba(200,20,20,.92) 20%,rgba(120,0,0,.98) 50%,rgba(200,20,20,.92) 80%,rgba(190,20,20,0) 92%,transparent);
    border-radius:50%;filter:drop-shadow(0 0 6px rgba(120,0,0,.8));opacity:0;
    animation:bloodStreak .55s ease-out forwards;}
  @keyframes bloodStreak{0%{opacity:0;transform:translate(-50%,-50%) rotate(var(--deg,20deg)) scaleX(.05)}
    22%{opacity:1;transform:translate(-50%,-50%) rotate(var(--deg,20deg)) scaleX(1)}
    100%{opacity:0;transform:translate(-50%,-50%) rotate(var(--deg,20deg)) scaleX(1)}}
  /* 紅刀痕：一條鋒利亮紅刀割，快速劃過（按錯懲罰用，搭配血痕濺血） */
  .fx-slash{left:50%;top:46%;width:320px;height:12px;margin:-6px 0 0 -160px;
    transform:translate(-50%,-50%) rotate(var(--deg,-25deg)) scaleX(.05);
    background:linear-gradient(90deg,transparent,rgba(255,50,50,0) 5%,rgba(255,70,70,.98) 20%,rgba(200,0,10,1) 50%,rgba(255,70,70,.98) 80%,rgba(255,50,50,0) 95%,transparent);
    border-radius:50%;filter:drop-shadow(0 0 9px rgba(230,0,25,.95));opacity:0;
    animation:slashCut .42s ease-out forwards;}
  @keyframes slashCut{0%{opacity:0;transform:translate(-50%,-50%) rotate(var(--deg,-25deg)) scaleX(.05)}
    16%{opacity:1;transform:translate(-50%,-50%) rotate(var(--deg,-25deg)) scaleX(1)}
    100%{opacity:0;transform:translate(-50%,-50%) rotate(var(--deg,-25deg)) scaleX(1)}}
  /* 濺血小血滴：自中心沿 --dx/--dy 飛散、短促淡出（刀痕專用，與延時寬血痕區隔） */
  .fx-drop{border-radius:50%;opacity:0;
    background:radial-gradient(circle at 40% 35%,rgba(255,40,50,1),rgba(150,0,6,.96) 70%);
    box-shadow:0 0 5px rgba(180,0,12,.9);
    transform:translate(-50%,-50%);
    animation:bloodDrop .42s ease-out forwards;}
  @keyframes bloodDrop{0%{opacity:0;transform:translate(-50%,-50%) scale(.5)}
    18%{opacity:1;transform:translate(calc(-50% + var(--dx,0)*.4),calc(-50% + var(--dy,0)*.4)) scale(1)}
    100%{opacity:0;transform:translate(calc(-50% + var(--dx,0)),calc(-50% + var(--dy,0))) scale(.7)}}
  /* 齒痕：上下兩排咬痕（用 radial-gradient 點陣模擬），隨機水平位置 */
  .fx-bite{width:150px;height:96px;margin:-48px 0 0 -75px;opacity:0;
    animation:biteMark .5s ease-out forwards;
    background:
      radial-gradient(circle at 12% 22%, rgba(150,0,0,.95) 0 5px, transparent 6px),
      radial-gradient(circle at 30% 14%, rgba(150,0,0,.95) 0 6px, transparent 7px),
      radial-gradient(circle at 50% 12%, rgba(150,0,0,.95) 0 6px, transparent 7px),
      radial-gradient(circle at 70% 14%, rgba(150,0,0,.95) 0 6px, transparent 7px),
      radial-gradient(circle at 88% 22%, rgba(150,0,0,.95) 0 5px, transparent 6px),
      radial-gradient(circle at 12% 78%, rgba(150,0,0,.95) 0 5px, transparent 6px),
      radial-gradient(circle at 30% 86%, rgba(150,0,0,.95) 0 6px, transparent 7px),
      radial-gradient(circle at 50% 88%, rgba(150,0,0,.95) 0 6px, transparent 7px),
      radial-gradient(circle at 70% 86%, rgba(150,0,0,.95) 0 6px, transparent 7px),
      radial-gradient(circle at 88% 78%, rgba(150,0,0,.95) 0 5px, transparent 6px);
    filter:drop-shadow(0 0 3px rgba(80,0,0,.8));}
  @keyframes biteMark{0%{opacity:0;transform:scale(.7)}25%{opacity:1;transform:scale(1.05)}
    45%{transform:scale(1)}100%{opacity:0}}
  /* 彈痕：玻璃被擊碎（中心孔＋放射狀裂紋＋環裂），隨機位置。細節用內嵌 SVG 畫。 */
  .fx-bullet{width:120px;height:120px;margin:-60px 0 0 -60px;opacity:0;
    animation:bulletHole .5s ease-out forwards;}
  @keyframes bulletHole{0%{opacity:0;transform:scale(.5)}20%{opacity:1;transform:scale(1.08)}
    40%{transform:scale(1)}100%{opacity:.92}}

  /* 防禦統一閃光：整張敵圖微微一閃（不過亮）。白＝格擋；金＝完美防禦／反擊。 */
  #defFlash{position:absolute;inset:0;pointer-events:none;z-index:6;opacity:0;mix-blend-mode:screen;}
  #defFlash.block{background:radial-gradient(circle at 50% 45%,rgba(255,255,255,.55),rgba(255,255,255,.12) 55%,transparent 72%);
    animation:defFlashAnim .32s ease-out;}
  #defFlash.gold{background:radial-gradient(circle at 50% 45%,rgba(240,205,110,.55),rgba(220,175,70,.14) 55%,transparent 72%);
    animation:defFlashAnim .36s ease-out;}
  @keyframes defFlashAnim{0%{opacity:0}30%{opacity:.7}100%{opacity:0}}



  /* 角落按鈕 */
  .corner-btn{position:absolute;z-index:37;width:44px;height:44px;border-radius:50%;
    background:rgba(10,8,14,.7);border:1px solid var(--gold-dim);color:var(--gold);
    font-size:20px;line-height:1;display:flex;align-items:center;justify-content:center;
    font-family:inherit;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);}
  .corner-btn:active{transform:scale(.9);}
  /* 控制鈕維持原 top:10px：#top 已被 #app padding 整體下移到瀏海之下，鈕相對 #top 定位即已安全，不再額外偏移（免雙重下推）。 */
  #exitBtn{top:10px;left:auto;right:10px;font-size:18px;}
  /* 結算畫面（banner 開啟）時隱藏右上退出鈕：corner-btn z-37 高於 banner z-30，會浮在結算之上 */
  #app:has(#banner.on) #exitBtn{display:none;}
  /* v17：測試人員用「清盤」鈕（左上角）。z-index 同 corner-btn，聖徒化手勢層之上，確保可點。
   *  預設隱藏：首頁手勢解鎖（團徽畫圓→橫劃團名，見 main.js testUnlockGesture）後 body.testmode 才顯示。 */
  #testClearBtn{top:10px;left:10px;right:auto;font-size:12px;letter-spacing:1px;color:var(--holy);border-color:var(--holy);display:none;}
  body.testmode #testClearBtn{display:flex;}

  /* ===== 過渡禎：開始/結束淡入淡出全畫面轉場 ===== */
  /* 淡入淡出時長由 JS 依 config.transitions.fadeMs 寫入 --expel-fade，CSS 與 config 同步。 */
  #expelTransition{position:absolute;inset:0;z-index:200;display:none;
    flex-direction:column;align-items:center;justify-content:center;text-align:center;
    padding:calc(env(safe-area-inset-top,0px) + 26px) 26px 26px;
    background:radial-gradient(120% 90% at 50% 40%,#140f1f 0%,#05040a 82%);
    opacity:0;transition:opacity var(--expel-fade,.3s) ease;pointer-events:none;}
  #expelTransition.show{display:flex;pointer-events:auto;}   /* 轉場中吸收點擊，避免重複觸發 */
  #expelTransition.vis{opacity:1;}
  .expel-cn{font-size:clamp(34px,11vw,60px);font-weight:bold;color:var(--gold);
    letter-spacing:.28em;text-indent:.28em;                 /* indent 補償 letter-spacing 的置中偏移 */
    text-shadow:0 0 22px var(--gold-dim),0 0 48px rgba(120,40,160,.4);}
  .expel-en{margin-top:22px;color:var(--ink);opacity:.82;font-style:italic;
    font-size:clamp(12px,3.4vw,15px);line-height:1.9;letter-spacing:.06em;max-width:34em;}
  /* 輕觸提示：淡入完成（.ready）後才浮現並緩慢呼吸；淡入途中不接受輕觸、也不顯示提示 */
  .expel-hint{margin-top:34px;font-size:12px;letter-spacing:.22em;color:var(--gold-dim);
    opacity:0;transition:opacity .4s ease;}
  #expelTransition.ready{cursor:pointer;}
  #expelTransition.ready .expel-hint{animation:expelHintPulse 1.5s ease-in-out infinite;}
  @keyframes expelHintPulse{0%,100%{opacity:.35}50%{opacity:.9}}

  /* ===== 瀏海/動態島 飾條 ===== */
  /* 精準填滿 #app 頂部保留墊高（0..--notch-bar-h），正好落在下移後的 #top 之上，不覆蓋任何內容。
     背景與 app 同底色融為一體；底緣一道極淡金線作為「畫框上緣」。桌面 safe-area=0、--notch-extra=0 → 高度 0，完全隱形。 */
  #notchBar{position:absolute;top:0;left:0;right:0;height:var(--notch-bar-h);z-index:36;
    pointer-events:none;overflow:hidden;display:flex;align-items:flex-end;justify-content:center;
    background:var(--bg);box-shadow:inset 0 -1px 0 rgba(212,169,74,.22);}
  #notchOrn{display:block;width:100%;height:100%;color:var(--notch-orn);
    filter:drop-shadow(0 0 1.5px rgba(212,169,74,.4));}
  /* ===== 下半：純數字盤 ===== */
  #bottom{height:50%;flex:none;background:var(--panel);padding:10px 12px;
    display:flex;flex-direction:column;min-height:0;}
  #gridWrap{flex:1 1 0;min-height:0;display:flex;align-items:center;justify-content:center;position:relative;}
  #transition{position:absolute;inset:0;display:none;align-items:center;justify-content:center;
    background:rgba(10,8,14,.82);z-index:15;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);}
  #transition.on{display:flex;}
  #transText{font-size:24px;letter-spacing:4px;color:var(--gold);font-weight:bold;
    text-shadow:0 0 16px var(--gold-dim);animation:transPop .45s;}
  @keyframes transPop{0%{transform:scale(.7);opacity:0}55%{transform:scale(1.12);opacity:1}100%{transform:scale(1);opacity:1}}
  @keyframes pulse{from{filter:brightness(1)}to{filter:brightness(1.7)}}

  #grid{display:grid;gap:6px;touch-action:manipulation;}
  .cell{position:relative;background:var(--grid);border:1px solid #000;
    border-radius:8px;display:flex;align-items:center;justify-content:center;
    font-weight:bold;color:var(--ink);transition:transform .06s,background .1s;
    box-shadow:inset 0 0 12px #0007;overflow:hidden;min-width:0;min-height:0;}
  .cell:active{transform:scale(.93);}
  .cell.done{background:var(--grid-active);color:var(--gold-dim);box-shadow:inset 0 0 16px var(--gold-dim);}
  /* 被點掉的格子破碎消失 */
  .cell.shatter{animation:cellShatter .32s ease-out forwards;pointer-events:none;}
  @keyframes cellShatter{
    0%{opacity:1;transform:scale(1);clip-path:polygon(0 0,100% 0,100% 100%,0 100%);
       filter:brightness(1.6) drop-shadow(0 0 10px var(--gold));}
    35%{opacity:1;transform:scale(1.08) rotate(-2deg);
       clip-path:polygon(10% 0,80% 8%,100% 70%,60% 100%,0 85%,4% 30%);
       filter:brightness(2) drop-shadow(0 0 16px #fff);}
    100%{opacity:0;transform:scale(.2) rotate(12deg);
       clip-path:polygon(45% 40%,55% 42%,58% 55%,50% 60%,42% 55%,44% 45%);
       filter:brightness(.6);}
  }
  .cell.next{border-color:var(--gold);box-shadow:0 0 8px var(--gold-dim);}
  .cell.wrong{animation:shake .3s;background:var(--danger);}
  @keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
  /* 威脅格 / 雙槍暴擊點 */
  /* 敵方紅點防禦：漸縮半透明紅點，直接點掉解除 */
  #redDots{position:absolute;inset:0;z-index:9;pointer-events:none;}
  /* 聖徒化橫斬特效：依滑動方向的一道白金色斬擊光 */
  #slashFx{position:absolute;inset:0;z-index:30;pointer-events:none;overflow:hidden;}
  .slash-line{position:absolute;top:50%;left:-40%;width:180%;height:14px;
    transform:translateY(-50%) rotate(-18deg);
    background:linear-gradient(90deg,transparent,rgba(255,255,255,0) 15%,#fff 48%,#ffe9a8 52%,rgba(255,233,168,0) 85%,transparent);
    filter:drop-shadow(0 0 16px #fff) drop-shadow(0 0 28px var(--gold));
    opacity:0;}
  .slash-line.go-right{animation:slashRight .45s cubic-bezier(.2,.7,.2,1) forwards;}
  .slash-line.go-left{animation:slashLeft .45s cubic-bezier(.2,.7,.2,1) forwards;}
  @keyframes slashRight{0%{opacity:0;transform:translate(-60%,-50%) rotate(-18deg) scaleX(.4)}
    30%{opacity:1}100%{opacity:0;transform:translate(40%,-50%) rotate(-18deg) scaleX(1.1)}}
  @keyframes slashLeft{0%{opacity:0;transform:translate(60%,-50%) rotate(18deg) scaleX(.4)}
    30%{opacity:1}100%{opacity:0;transform:translate(-40%,-50%) rotate(18deg) scaleX(1.1)}}
  #slashFx.flash::after{content:"";position:absolute;inset:0;background:radial-gradient(circle,rgba(255,255,255,.5),transparent 60%);animation:slashFlash .45s ease-out forwards;}
  @keyframes slashFlash{0%{opacity:0}20%{opacity:1}100%{opacity:0}}
  .reddot{position:absolute;border-radius:50%;pointer-events:auto;cursor:pointer;
    background:radial-gradient(circle,rgba(255,70,70,.7),rgba(200,20,20,.3) 60%,transparent 72%);
    border:2px solid rgba(255,100,100,.9);box-shadow:0 0 22px rgba(255,40,40,.85),inset 0 0 12px rgba(255,80,80,.6);
    transform:translate(-50%,-50%);}
  /* 盤面警戒：紅點出現時數字盤變紅，提醒玩家抬頭看敵人 */
  #grid.alert .cell{border-color:var(--danger);color:#ff8a8a;}
  #grid.alert{animation:alertPulse .5s infinite alternate;}
  @keyframes alertPulse{from{filter:none}to{filter:drop-shadow(0 0 8px var(--danger))}}
  /* 暫停對話框開啟中：凍結底下的警戒/聖徒化脈動（動畫 filter 於 iOS 會被抬成獨立合成層，
     蓋過 z-order 較高的教學對話框＝「盤面壓過對話框」；alert 另有色偏假影問題）。 */
  body.dlg-pause #grid.alert, body.dlg-pause #grid.saint.alert,
  body.dlg-pause #grid.saint{animation:none;filter:none;}
  /* 雙槍模式盤面外框 */
  #grid.dualwield .cell{border-color:var(--holy);}
  #grid.dualwield{filter:drop-shadow(0 0 6px var(--holy));}
  /* Overkill 窗口（敵死後追加輸出）：數字發藍光 + 盤面冷藍脈動 */
  #grid.overkill .cell{border-color:var(--holy);color:#bfe6ff;
    text-shadow:0 0 10px #4fc3ff,0 0 22px rgba(79,195,255,.55);}
  #grid.overkill{animation:overkillPulse .6s infinite alternate;}
  @keyframes overkillPulse{from{filter:drop-shadow(0 0 8px var(--holy))}to{filter:drop-shadow(0 0 18px #7fd4ff)}}
  /* 攻擊加倍 buff 盤面金框 */
  #grid.buffed .cell{border-color:var(--gold);}
  #grid.buffed{filter:drop-shadow(0 0 8px var(--gold));}
  /* 聖徒化盤面（金色神聖） */
  #grid.saint .cell{border-color:var(--gold);background:#2a2418;color:#ffe9a8;}
  #grid.saint{filter:drop-shadow(0 0 14px var(--gold));animation:saintPulse .8s infinite alternate;}
  /* v16：聖徒化期間敵發動攻擊（有紅點）時，盤面一樣要變紅（覆蓋金色） */
  #grid.saint.alert .cell{border-color:var(--danger);color:#ff8a8a;background:#2a1414;}
  #grid.saint.alert{filter:drop-shadow(0 0 12px var(--danger));animation:alertPulse .5s infinite alternate;}
  /* 聖徒化中進 overkill：藍光覆蓋金色（敵已死，優先權高於 saint 金） */
  #grid.saint.overkill .cell{border-color:var(--holy);color:#bfe6ff;background:#18202e;
    text-shadow:0 0 10px #4fc3ff,0 0 22px rgba(79,195,255,.55);}
  #grid.saint.overkill{filter:none;animation:overkillPulse .6s infinite alternate;}
  @keyframes saintPulse{from{filter:drop-shadow(0 0 10px var(--gold))}to{filter:drop-shadow(0 0 20px #fff)}}

  /* 彈殼 */
  .shell{position:absolute;width:9px;height:20px;
    background:linear-gradient(120deg,#fff3c4 0%,#e8c56a 35%,#a8842e 70%,#6b5220 100%);
    border-radius:3px;pointer-events:none;z-index:10;
    box-shadow:0 0 6px rgba(232,197,106,.7);animation:shellEject .55s ease-in forwards;}
  @keyframes shellEject{0%{opacity:1;transform:translate(0,0) rotate(0)}
    100%{opacity:0;transform:translate(34px,40px) rotate(260deg)}}

  button.act{flex:1;padding:11px;background:transparent;border:1px solid var(--gold-dim);
    color:var(--gold);border-radius:8px;font-family:inherit;font-size:13px;letter-spacing:2px;}
  button.act:active{background:var(--grid-active);}
  button.act:disabled{opacity:.3;}
  button.act.ready{border-color:var(--holy);color:var(--holy);animation:pulse .8s infinite alternate;}

  /* cutinTextIn：聖徒化 cut-in 副標進場用（#saintCutinSub；舊版雙槍 cut-in 首版遺留的
     其餘規則已清除——本區塊下方的第二版定義才是現行雙槍 cut-in） */
  @keyframes cutinTextIn{0%{opacity:0;transform:translateY(20px)}25%{opacity:1;transform:translateY(0)}85%{opacity:1}100%{opacity:0}}

  /* 雙槍 cut-in 演出 */
  /* z-8100：cut-in 為最上層演出（蓋過教學對話框 8000）；仍低於黑幕(9000)/確認框(9500) */
  #cutin{position:absolute;inset:0;z-index:8100;display:none;overflow:hidden;
    background:radial-gradient(circle at 50% 50%,rgba(40,10,50,.6),rgba(5,4,10,.95));}
  #cutin.on{display:block;}
  #cutinFlash{position:absolute;inset:0;background:#fff;opacity:0;}
  #cutin.on #cutinFlash{animation:cutinFlash 1.5s ease-out;}
  @keyframes cutinFlash{0%{opacity:1}12%{opacity:0}100%{opacity:0}}
  #cutinImg{position:absolute;top:50%;left:50%;height:96%;max-width:none;
    filter:drop-shadow(0 0 30px #c0308a) drop-shadow(0 0 12px #6a30c0);
    transform:translate(-50%,-50%) scale(1.3);opacity:0;}
  #cutin.on #cutinImg{animation:cutinImg 1.5s cubic-bezier(.15,.7,.3,1);}
  @keyframes cutinImg{
    0%{transform:translate(-120%,-50%) scale(1.5) rotate(-8deg);opacity:0;}
    18%{transform:translate(-50%,-50%) scale(1.28) rotate(0deg);opacity:1;}
    82%{transform:translate(-50%,-50%) scale(1.22);opacity:1;}
    100%{transform:translate(30%,-50%) scale(1.2);opacity:0;}
  }
  /* i18n 斷行規則：keep-all＝CJK/假名連續串視為一個詞不得中斷（セイント／インストール
     只能在空白或 \n 換行，不會斷成「～インスト／ール」）；pre-line＝語言包可用 \n 指定斷點；
     vw 上限縮字防窄機溢出 */
  #cutinText{position:absolute;bottom:16%;left:0;right:0;text-align:center;
    font-size:min(40px,9vw);font-weight:900;letter-spacing:8px;color:#fff;line-height:1.2;
    white-space:pre-line;word-break:keep-all;overflow-wrap:normal;
    text-shadow:0 0 20px #c0308a,0 0 8px #fff,3px 3px 0 #6a30c0;
    font-family:Impact,"Arial Black",sans-serif;opacity:0;transform:skewX(-10deg);}
  #cutinText .cutin-en{display:block;font-size:16px;letter-spacing:4px;font-weight:700;
    margin-top:6px;opacity:.92;text-shadow:0 0 12px #c0308a,0 1px 3px #000;}
  #cutin.on #cutinText{animation:cutinText 1.5s ease-out;}
  @keyframes cutinText{0%{opacity:0;transform:skewX(-10deg) scale(2)}
    20%{opacity:1;transform:skewX(-10deg) scale(1)}
    80%{opacity:1}100%{opacity:0}}
  #cutinStreak{position:absolute;inset:0;pointer-events:none;
    background:repeating-linear-gradient(-24deg,transparent 0 18px,rgba(192,48,138,.18) 18px 20px);}
  #cutin.on #cutinStreak{animation:cutinStreak .5s linear infinite;}
  @keyframes cutinStreak{from{background-position:0 0}to{background-position:40px 0}}

  /* ===== 聖徒化結局全畫面 cut-in ===== */
  #saintCutin{position:absolute;inset:0;z-index:8200;display:none;overflow:hidden;}   /* 結局 cut-in：最上層 */
  /* 生命歸還手勢層：預設隱藏，聖徒化時 .on 開啟；只覆蓋上半敵畫面(高50%)，不擋下半盤面點擊 */
  #returnSwipe{position:absolute;left:0;right:0;top:0;height:50%;z-index:35;display:none;background:transparent;touch-action:none;}
  #returnSwipe.on{display:block;}
  /* 向心聚光特效：按住時定位到觸摸點，光線由四周向中心收束 */
  #returnAura{position:absolute;width:0;height:0;pointer-events:none;display:none;z-index:36;}
  #returnAura.on{display:block;}
  #returnAura .core{position:absolute;left:-9px;top:-9px;width:18px;height:18px;border-radius:50%;
    background:radial-gradient(circle,rgba(255,240,190,.95),rgba(255,180,90,.5) 55%,transparent 72%);
    box-shadow:0 0 18px 6px rgba(255,200,110,.6);animation:auraCore .9s ease-in-out infinite;}
  #returnAura .ray{position:absolute;left:0;top:0;width:3px;height:64px;transform-origin:50% 0;
    background:linear-gradient(to bottom,transparent,rgba(255,210,130,.85));
    filter:drop-shadow(0 0 3px rgba(255,190,90,.8));animation:auraRay 1s ease-in infinite;}
  @keyframes auraRay{
    0%{ transform:rotate(var(--a)) translateY(76px) scaleY(1); opacity:0; }
    30%{ opacity:.9; }
    100%{ transform:rotate(var(--a)) translateY(4px) scaleY(.5); opacity:0; }
  }
  @keyframes auraCore{ 0%,100%{transform:scale(.85);opacity:.75;} 50%{transform:scale(1.15);opacity:1;} }
  #saintCutin.on{display:block;}
  #saintCutin.burst{background:radial-gradient(circle at 50% 45%,rgba(60,45,10,.85),rgba(8,6,2,.97));}
  #saintCutin.obe{background:radial-gradient(circle at 50% 45%,rgba(60,8,40,.9),rgba(6,2,8,.98));}
  #saintCutin.execute{background:radial-gradient(circle at 50% 45%,rgba(80,60,10,.92),rgba(4,2,0,.99));}
  #saintCutin.return{background:radial-gradient(circle at 50% 45%,rgba(70,55,15,.9),rgba(6,4,1,.98));}
  #saintCutin.boss{background:radial-gradient(circle at 50% 45%,rgba(70,10,20,.9),rgba(8,2,4,.98));}
  .scimg{position:absolute;inset:0;width:100%;height:100%;
    object-fit:cover;object-position:50% 30%;opacity:0;z-index:0;display:none;}
  /* 依結局類型只顯示對應圖片 */
  #saintCutin.burst .scimg[data-kind="burst"],
  #saintCutin.obe .scimg[data-kind="obe"],
  #saintCutin.execute .scimg[data-kind="execute"],
  #saintCutin.return .scimg[data-kind="return"],
  #saintCutin.boss .scimg[data-kind="boss"]{display:block;}
  #saintCutin.on .scimg{animation:saintCutinImgIn 1.6s ease-out forwards;}
  @keyframes saintCutinImgIn{0%{opacity:0;transform:scale(1.15)}
    18%{opacity:1;transform:scale(1)}82%{opacity:1;transform:scale(1)}
    100%{opacity:.85;transform:scale(1.03)}}
  #saintCutin.execute.on .scimg[data-kind="execute"]{animation-duration:3s;}
  #saintCutinFlash{position:absolute;inset:0;opacity:0;z-index:1;}
  #saintCutinStreak,#saintCutinTitle,#saintCutinSub{z-index:2;}
  #saintCutin.burst #saintCutinFlash{background:#fff;}
  #saintCutin.obe #saintCutinFlash{background:#ff3b3b;}
  #saintCutin.execute #saintCutinFlash{background:#fff;}
  #saintCutin.return #saintCutinFlash{background:#fff;}
  #saintCutin.boss #saintCutinFlash{background:#ff3b3b;}
  #saintCutin.on #saintCutinFlash{animation:cutinFlash 1.6s ease-out forwards;}
  #saintCutinStreak{position:absolute;inset:0;pointer-events:none;}
  #saintCutin.burst #saintCutinStreak{
    background:repeating-linear-gradient(-24deg,transparent 0 16px,rgba(255,223,120,.16) 16px 19px);}
  #saintCutin.obe #saintCutinStreak{
    background:repeating-linear-gradient(-24deg,transparent 0 16px,rgba(255,60,90,.18) 16px 19px);}
  #saintCutin.execute #saintCutinStreak{
    background:repeating-linear-gradient(-24deg,transparent 0 14px,rgba(255,240,190,.22) 14px 17px);}
  #saintCutin.return #saintCutinStreak{
    background:repeating-linear-gradient(-24deg,transparent 0 16px,rgba(255,223,120,.16) 16px 19px);}
  #saintCutin.boss #saintCutinStreak{
    background:repeating-linear-gradient(-24deg,transparent 0 16px,rgba(255,60,90,.18) 16px 19px);}
  #saintCutin.on #saintCutinStreak{animation:cutinStreak .5s linear infinite;}
  #saintCutinTitle{position:absolute;top:42%;left:0;right:0;text-align:center;
    transform:translateY(-50%) skewX(-8deg);font-weight:900;
    font-family:Impact,"Arial Black",sans-serif;line-height:1.05;
    font-size:clamp(30px,9vw,64px);letter-spacing:4px;opacity:0;padding:0 4%;white-space:pre-line;
    word-break:keep-all;overflow-wrap:normal;}   /* i18n：不從單詞/假名串中間斷行 */
  #saintCutin.burst #saintCutinTitle{color:#fff;
    text-shadow:0 0 22px var(--holy),0 0 10px #ffe9a8,3px 3px 0 var(--gold);}
  #saintCutin.obe #saintCutinTitle{color:#fff;
    text-shadow:0 0 22px #ff3b6b,0 0 10px #ff8a8a,3px 3px 0 #6a1030;}
  #saintCutin.execute #saintCutinTitle{color:#fff;
    text-shadow:0 0 26px var(--gold),0 0 12px #fff,3px 3px 0 #7a5a10;}
  #saintCutin.return #saintCutinTitle{color:#fff;
    text-shadow:0 0 22px var(--holy),0 0 10px #ffe9a8,3px 3px 0 var(--gold);}
  #saintCutin.boss #saintCutinTitle{color:#fff;
    text-shadow:0 0 22px #ff3b6b,0 0 10px #ff8a8a,3px 3px 0 #6a1030;}
  #saintCutin.on #saintCutinTitle{animation:saintCutinTitle 1.6s ease-out forwards;}
  @keyframes saintCutinTitle{0%{opacity:0;transform:translateY(-50%) skewX(-8deg) scale(2.2)}
    18%{opacity:1;transform:translateY(-50%) skewX(-8deg) scale(1)}
    82%{opacity:1}100%{opacity:0;transform:translateY(-50%) skewX(-8deg) scale(1.05)}}
  #saintCutinSub{position:absolute;top:60%;left:0;right:0;text-align:center;
    font-size:clamp(13px,3.5vw,18px);letter-spacing:6px;font-weight:bold;opacity:0;}
  #saintCutin.burst #saintCutinSub{color:var(--gold);text-shadow:0 0 12px var(--holy);}
  #saintCutin.obe #saintCutinSub{color:#ff9db3;text-shadow:0 0 12px #ff3b6b;}
  #saintCutin.execute #saintCutinSub{color:#ffe9a8;text-shadow:0 0 14px var(--gold);}
  #saintCutin.return #saintCutinSub{color:var(--gold);text-shadow:0 0 12px var(--holy);}
  #saintCutin.boss #saintCutinSub{color:#ff9db3;text-shadow:0 0 12px #ff3b6b;}
  #saintCutin.on #saintCutinSub{animation:cutinTextIn 1.6s ease-out forwards;}
  /* EXSECUTIŌ 停留 3 秒：拉長各元素動畫 */
  #saintCutin.execute.on #saintCutinFlash{animation-duration:3s;}
  #saintCutin.execute.on #saintCutinTitle{animation:saintCutinTitleHold 3s ease-out forwards;}
  #saintCutin.execute.on #saintCutinSub{animation:cutinTextInHold 3s ease-out forwards;}
  @keyframes saintCutinTitleHold{0%{opacity:0;transform:translateY(-50%) skewX(-8deg) scale(2.2)}
    10%{opacity:1;transform:translateY(-50%) skewX(-8deg) scale(1)}
    90%{opacity:1}100%{opacity:0;transform:translateY(-50%) skewX(-8deg) scale(1.05)}}
  @keyframes cutinTextInHold{0%{opacity:0;transform:translateY(20px)}12%{opacity:1;transform:translateY(0)}90%{opacity:1}100%{opacity:0}}

  #banner{position:absolute;inset:0;display:none;flex-direction:column;
    align-items:center;justify-content:space-between;background:rgba(5,4,10,.94);z-index:30;text-align:center;
    /* 結算內容同樣避開瀏海（#banner 為絕對定位、吃不到 #app padding，需自帶墊高） */
    padding:var(--notch-bar-h) 0 0;overflow:hidden;}
  #banner.on{display:flex;}
  /* 結算內容區（大標→rows→立繪），retry 固定在最底。固定不可滑動：overflow hidden + 禁回彈。 */
  #bannerScroll{flex:1 1 auto;width:100%;display:flex;flex-direction:column;align-items:center;
    justify-content:flex-start;overflow:hidden;overscroll-behavior:none;padding:10px 0 6px;position:relative;
    min-height:0;touch-action:none;}
  #banner h1{font-size:26px;letter-spacing:4px;color:var(--gold);margin:0 0 4px;
    text-shadow:0 0 16px var(--gold-dim);}
  #banner p{font-size:13px;letter-spacing:2px;opacity:.8;margin:2px 0 8px;}
  #banner.lose h1{color:var(--danger);text-shadow:0 0 16px var(--blood);}
  /* 大標＋retry 同時進場：淡入＋輕微下沉 */
  @keyframes bannerHeadIn{ from{opacity:0;transform:translateY(-10px);} to{opacity:1;transform:none;} }
  #banner.seq h1, #banner.seq p{animation:bannerHeadIn .35s ease-out both;}
  #banner.seq #rematchBtn{animation:bannerHeadIn .35s ease-out both;}
  /* 結算數據列（緊湊：留出立繪全身空間） */
  #resultStats{margin:0 0 6px;font-size:12.5px;letter-spacing:1px;line-height:1.5;color:var(--ink);
    min-width:230px;flex:0 0 auto;}
  #resultStats .row{display:flex;justify-content:space-between;gap:24px;min-width:230px;}
  #resultStats .row b{color:var(--gold);font-weight:normal;}
  #resultStats .record{color:#ffe08a;font-size:12px;letter-spacing:3px;
    text-shadow:0 0 10px var(--gold);animation:blink .5s infinite alternate;margin-top:6px;}
  /* rows 逐行下刷：每行淡入下沉，1 秒內刷完（delay 由 JS 逐行設定） */
  @keyframes rowSweep{ from{opacity:0;transform:translateY(-8px);} to{opacity:1;transform:none;} }
  #resultStats .row, #resultStats .record, #resultStats .grade-wrap{opacity:0;}
  #resultStats.sweep .row, #resultStats.sweep .record, #resultStats.sweep .grade-wrap{animation:rowSweep .28s ease-out forwards;}
  /* 評價：大字等第橫向緊湊（顯眼但不佔行高），色彩沿用 rank-*，glow 用 currentColor */
  #resultStats .grade-wrap{display:flex;flex-direction:row;align-items:center;justify-content:center;
    gap:12px;margin:0 0 6px;}
  #resultStats .grade-badge{font-size:46px;font-weight:bold;line-height:1;letter-spacing:1px;
    filter:drop-shadow(0 0 14px currentColor);}
  #resultStats .grade-meta{display:flex;flex-direction:column;align-items:flex-start;line-height:1.25;}
  #resultStats .grade-cap{font-size:11px;letter-spacing:5px;opacity:.6;color:var(--ink);}
  #resultStats .grade-exp{font-size:13px;letter-spacing:2px;color:var(--gold);opacity:.95;}
  /* 無傷貼標：達標才出現，貼在「戰鬥用時」旁 */
  #resultStats .tag-flawless{display:inline-block;margin-left:8px;padding:1px 8px;border-radius:10px;
    font-size:10px;letter-spacing:2px;font-weight:bold;color:var(--bg);background:var(--gold);
    vertical-align:middle;box-shadow:0 0 10px var(--gold-dim);}
  /* 評價等第 */
  #resultStats .rank{font-weight:bold;letter-spacing:2px;}
  #resultStats .rank-S{color:#ffe08a;text-shadow:0 0 12px var(--gold);}
  #resultStats .rank-A{color:var(--gold);}
  #resultStats .rank-B{color:var(--holy);}
  #resultStats .rank-C{color:#b9c2cc;}
  #resultStats .rank-D{color:#8f97a0;}
  #resultStats .rank-E{color:#6d7178;}
  /* ===== 監察官立繪舞台 ===== */
  /* 舞台吃掉數據列以外的剩餘空間（flex:1），立繪以 contain 顯示「全身」並隨空間縮放 → 手機也放得下 */
  #inspectorStage{position:relative;width:100%;max-width:340px;margin-top:2px;
    display:flex;justify-content:center;align-items:flex-end;flex:1 1 auto;min-height:0;}
  #inspectorPortrait{width:auto;max-width:100%;max-height:100%;object-fit:contain;object-position:bottom;
    filter:drop-shadow(0 6px 24px rgba(0,0,0,.7));
    opacity:0;transform:translateY(14px) scale(.98);
    -webkit-mask-image:linear-gradient(to bottom,#000 86%,transparent 100%);
    mask-image:linear-gradient(to bottom,#000 86%,transparent 100%);}
  #banner.seq #inspectorPortrait{animation:portraitIn .5s cubic-bezier(.2,.7,.3,1) both;}
  @keyframes portraitIn{ from{opacity:0;transform:translateY(14px) scale(.98);}
    to{opacity:1;transform:none;} }
  /* 對話框：絕對定位，疊在立繪偏下方，半透明 */
  #inspectorBubble{position:absolute;left:50%;bottom:11%;transform:translateX(-50%) translateY(8px);
    width:82%;max-width:300px;background:rgba(16,12,24,.72);
    border:1px solid var(--gold-dim);border-radius:8px;padding:10px 13px;text-align:left;
    box-shadow:0 4px 20px rgba(0,0,0,.55);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
    opacity:0;pointer-events:none;}
  #inspectorBubble.show{animation:bubbleIn .3s ease-out forwards;}
  @keyframes bubbleIn{ from{opacity:0;transform:translateX(-50%) translateY(8px);}
    to{opacity:1;transform:translateX(-50%) translateY(0);} }
  #inspectorBubble .insp-name{font-size:11px;letter-spacing:2px;color:var(--gold);
    margin-bottom:5px;opacity:.9;}
  #inspectorBubble .insp-line{font-size:13px;letter-spacing:.5px;line-height:1.6;color:var(--ink);min-height:1.6em;white-space:pre-line;}
  /* retry 鈕：置底、與畫面同寬、降低高度 */
  /* 貼底大鈕：拉至畫面最底，底部內距吃掉 iOS 安全區(home indicator)→ 底下不留空 */
  #banner #rematchBtn{flex:0 0 auto;width:100%;max-width:none;margin:0;border-radius:0;
    padding:0;min-height:calc(54px + env(safe-area-inset-bottom,0px));
    border:none;border-top:1px solid var(--gold-dim);
    background:rgba(20,16,28,.6);color:var(--gold);letter-spacing:6px;font-size:19px;
    /* 字樣對整個框上下左右置中（含安全區）：不用不對稱 padding，改高度撐框 + flex 置中；
       text-indent 補償 letter-spacing 尾端空隙的水平偏移 */
    display:flex;align-items:center;justify-content:center;text-indent:6px;line-height:1;}
  #banner #rematchBtn:active{background:var(--grid-active);}
  /* 視窗被裁（iOS 26 standalone）：底部安全區墊高白墊在死區裡 → 拿回 28px 還給監察官立繪。
     底色改純黑與死區黑帶視覺融合：按鈕(可視 54px)+死區連成一條原生風底欄，
     字樣位置≒原生 App 底欄按鈕（home indicator 上方），黑帶讀作手勢區而非缺口。 */
  html.vp-clipped #banner #rematchBtn{min-height:54px;background:#000;}
  /* 迎擊鈕（S 解鎖後）：變色＋發光脈動 */
  #banner #rematchBtn.intercept{color:var(--danger);border-top-color:var(--blood);
    background:rgba(60,12,18,.55);text-shadow:0 0 12px var(--blood);
    box-shadow:0 -2px 20px rgba(200,40,40,.4),inset 0 0 18px rgba(200,40,40,.25);
    animation:interceptPulse .7s infinite alternate;}
  @keyframes interceptPulse{ from{box-shadow:0 -2px 14px rgba(200,40,40,.3),inset 0 0 12px rgba(200,40,40,.2);}
    to{box-shadow:0 -2px 26px rgba(220,60,60,.6),inset 0 0 22px rgba(220,60,60,.35);} }

  /* ===== 首頁 ===== */
  /* 版面策略（2026-08-16 定案）：由上而下定位、團徽為錨——不用 justify-center
     （內容高過視窗時 center 會把團徽推出畫面頂、按鈕擠進 footer）。
     垂直間距/團徽尺寸以 --appvh（main.js 實測視窗高寫入；iOS Safari 的 vh 恆取大視口不可信）
     收縮：矮視窗整欄等比變緊，內容保證不壓到貼底 footer。 */
  #home{position:absolute;inset:0;display:none;flex-direction:column;
    align-items:center;justify-content:flex-start;z-index:50;text-align:center;
    background:radial-gradient(120% 90% at 50% 30%,#1a1330,#07050c 90%);
    padding-top:calc(var(--appvh,1vh)*9);
    /* 底部保留貼底 footer（Credit/原作 + 版權）的高度 */
    padding-bottom:calc(72px + env(safe-area-inset-bottom));}
  #home.on{display:flex;}
  /* 主畫面徽記：金色透明 PNG（含 THE IV ORDER OF TESTAMENT 弧字），置中。
     微微發光呼吸：drop-shadow 光暈 + 亮度，節奏同「開始遊戲」按鈕（1.2s alternate）。
     尺寸固定比例（64vw 上限 300px）不隨視窗高縮——矮視窗靠間距收縮與教學鈕移入底排騰空間。 */
  #home #homeEmblem{width:min(64vw,300px);max-width:78%;height:auto;
    margin:0 0 14px;flex:none;
    user-select:none;-webkit-user-drag:none;pointer-events:none;
    animation:emblemGlow 1.2s ease-in-out infinite alternate;}
  @keyframes emblemGlow{
    from{filter:drop-shadow(0 0 8px rgba(212,169,74,.25)) brightness(1);}
    to{filter:drop-shadow(0 0 22px rgba(212,169,74,.6)) brightness(1.12);}}
  /* 中文主標：不自動換行（依畫面寬用 clamp 縮字，保證單行不溢出） */
  #home .title{font-size:clamp(24px,7.6vw,34px);letter-spacing:.16em;color:var(--gold);
    margin:0;white-space:nowrap;
    text-shadow:0 0 20px var(--gold-dim),0 0 40px rgba(120,40,160,.5);font-weight:bold;}
  /* 英文長標題：字距收窄（.16em 會逼縮字機制把字縮過小、且撐滿整寬貼邊，觀感差） */
  html[lang="en"] #home .title{letter-spacing:.08em;}
  /* 副標 SAINT INSTALL：中文標下方，金字加左右細線（下緣間距隨視窗高收縮；
     選單移出首頁後空間充裕 → 團徽/標題區與出陣鈕拉開呼吸距離） */
  #home .saint-install{display:flex;align-items:center;justify-content:center;gap:12px;
    margin:10px 0 clamp(26px, calc(var(--appvh,1vh)*6), 60px);}
  #home .saint-install .si-text{font-size:12px;letter-spacing:.42em;
    color:var(--holy);opacity:.92;text-indent:.42em;white-space:nowrap;
    text-shadow:0 0 12px rgba(111,179,212,.45);}
  #home .saint-install .si-rule{width:clamp(22px,9vw,44px);height:1px;
    background:linear-gradient(90deg,transparent,rgba(111,179,212,.65));}
  #home .saint-install .si-rule:last-child{background:linear-gradient(90deg,rgba(111,179,212,.65),transparent);}
  #startBtn{padding:16px 46px;background:transparent;border:1px solid var(--gold);
    color:var(--gold);border-radius:10px;font-family:inherit;font-size:17px;letter-spacing:5px;
    box-shadow:0 0 18px var(--gold-dim);animation:pulse 1.2s infinite alternate;}
  #startBtn:active{transform:scale(.94);}
  /* 副武器/搭檔選單已移出首頁 → 出擊整備頁（#prepSheet，見下方區塊） */
  /* 語言切換鈕（首頁右上）：鈕面＝下一個語言的自稱（En/日本語/中文），點按循環切換 */
  #langBtn{position:absolute;top:calc(var(--notch-bar-h, 0px) + 12px);right:12px;z-index:5;
    min-width:44px;height:36px;padding:0 14px;border-radius:18px;background:rgba(10,8,14,.6);
    border:1px solid var(--gold-dim);color:var(--gold);font-family:inherit;font-size:14px;
    letter-spacing:1px;}
  #langBtn:active{transform:scale(.92);}
  /* 教學鈕：縮為小圓角鈕、移入底部 Credit/原作 同排（見 #homeLinks 區的共同樣式） */
  /* 極矮視窗（SE1 級/瀏覽器工具列全開）：按鈕降高、間距收緊，保整欄不壓 footer */
  @media (max-height:620px){
    #home .saint-install{margin-bottom:18px;}
    #startBtn{padding:12px 40px;}
  }

  /* ── 出擊整備頁（#prepSheet）：出陣 → 本頁 → 執槍才進戰鬥 ──
     搭檔卡上（吃較多高）、武器卡下，點卡開各自的全螢幕選擇畫面（z-60 蓋本頁 z-55，
     關閉後回到本頁）。底部「執槍」規格同結算「再度執槍」貼底整寬大鈕。 */
  /* 轉場粒子：畫面下方飄起的金色光點（main.js goldSparkRise 動態建立，純程式無素材）。
     z-56＝蓋整備頁(55)、讓位選擇畫面(60)。位移/升幅/時長由行內 --dx/--rise 與 duration 隨機。 */
  .gold-rise{position:fixed;inset:0;z-index:56;pointer-events:none;overflow:hidden;}
  .gold-rise i{position:absolute;bottom:-8px;border-radius:50%;
    background:radial-gradient(circle,#ffe9a8,rgba(212,169,74,.85) 55%,transparent 75%);
    box-shadow:0 0 8px rgba(255,224,138,.9),0 0 16px rgba(212,169,74,.5);
    opacity:0;animation:goldRise 1.8s ease-out forwards;}
  @keyframes goldRise{
    0%{opacity:0;transform:translate(0,0) scale(.6);}
    12%{opacity:1;}
    100%{opacity:0;transform:translate(var(--dx,0px),calc(-1*var(--rise,55vh))) scale(1.05);}}
  /* 開閉皆淡入淡出：.on 掛載（display）、.vis 控透明度（main.js 先 on 後下一幀 vis） */
  #prepSheet{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;
    background:radial-gradient(120% 90% at 50% 30%,#1a1330,#07050c 90%);z-index:55;
    padding:calc(var(--notch-bar-h,0px) + 12px) 16px 0;gap:12px;
    opacity:0;transition:opacity .4s ease;}
  #prepSheet.on{display:flex;}
  #prepSheet.vis{opacity:1;}
  #prepSheet #prepBack{top:calc(var(--notch-bar-h,0px) + 10px);right:10px;font-size:18px;}
  #prepSheet .prep-card{position:relative;width:100%;max-width:380px;flex:1 1 0;min-height:0;
    border:1px solid var(--gold-dim);border-radius:12px;background:#0f0c16;overflow:hidden;
    padding:0;font-family:inherit;box-shadow:0 0 22px rgba(0,0,0,.55);}
  #prepSheet #prepPartnerCard{flex:1.4 1 0;}   /* 搭檔立繪吃較多高 */
  #prepSheet .prep-card:active{transform:scale(.985);}
  /* 搭檔卡取景：頭頂對齊卡框頂（不裁頭頂）、水平置中、下緣自然裁掉＝上身特寫。
     尺寸以蕾妮（zoom:1＝滿版寬）為基準，各搭檔按 config siFit.zoom（單眼寬度基準的
     相對倍率，同選人畫面）放大——馬季諾 1.85 倍取上身，眼睛與蕾妮等大。
     --prep-zoom/--prep-top 由 weapon.refreshLoadoutLabels 依 config 寫入。 */
  #prepSheet .prep-card img{position:absolute;left:50%;top:0;
    width:calc(100% * var(--prep-zoom,1));height:auto;max-width:none;
    transform:translateX(-50%) translateY(var(--prep-top,0%));-webkit-user-drag:none;}
  #prepSheet .prep-weapon img{left:0;top:0;transform:none;width:100%;height:100%;
    object-fit:contain;padding:10px 14px;background:#0a0810;}
  /* 底部資訊帶：標籤（同選人畫面 tag 樣式）＋名稱＋更換箭頭 */
  #prepSheet .prep-strip{position:absolute;left:0;right:0;bottom:0;display:flex;align-items:center;
    gap:10px;padding:16px 12px 9px;text-align:left;
    background:linear-gradient(180deg,transparent,rgba(5,4,10,.9) 55%);}
  #prepSheet .prep-label{flex:none;font-size:10px;letter-spacing:2px;color:var(--gold-dim);
    border:1px solid var(--gold-dim);border-radius:4px;padding:2px 7px;text-indent:2px;}
  #prepSheet .prep-strip b{font-size:14px;letter-spacing:2px;color:var(--gold);font-weight:normal;
    flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  #prepSheet .prep-arrow{flex:none;color:var(--gold-dim);font-size:18px;line-height:1;}
  /* 執槍：貼底整寬、含底部安全區（同 #banner #rematchBtn 規格） */
  #prepSheet #prepGo{flex:0 0 auto;width:calc(100% + 32px);margin:2px -16px 0;border-radius:0;
    padding:0;min-height:calc(54px + env(safe-area-inset-bottom,0px));
    border:none;border-top:1px solid var(--gold-dim);
    background:rgba(20,16,28,.6);color:var(--gold);letter-spacing:6px;font-size:19px;
    font-family:inherit;display:flex;align-items:center;justify-content:center;
    text-indent:6px;line-height:1;}
  #prepSheet #prepGo:active{background:var(--grid-active);}
  html.vp-clipped #prepSheet #prepGo{min-height:54px;background:#000;}
  /* ── Boss 戰 S 級獎勵：銭湯インストール ── */
  /* 毛筆字型：Yuji Boku（OFL）子集，只含「銭湯インストール」8 字（3.6KB，自託管離線可用） */
  @font-face{ font-family:'YujiBokuSentou';
    src:url('resources/misc/YujiBoku_sentou.woff2?v=3') format('woff2');
    font-display:block; }
  #sentouReward{position:absolute;inset:0;display:none;align-items:center;justify-content:center;
    background:#050308;z-index:80;}
  #sentouReward.on{display:flex;animation:sentouIn .8s ease;}
  @keyframes sentouIn{from{opacity:0;}to{opacity:1;}}
  /* 圖完整顯示（object-fit:contain 等效）：外框鎖 2/3 比例、置中，字樣以框定位（不隨視窗裁切跑位） */
  #sentouReward .sentou-frame{position:relative;aspect-ratio:2/3;max-width:100%;max-height:100%;}
  #sentouReward img{width:100%;height:100%;-webkit-user-drag:none;}
  /* 毛筆招牌額（扁額風）：畫面左上角、和紙底 + 雙線木框，「銭湯」大字＋「インストール」小字兩行置中。
     額本體先蓋印進場（sentouPlaque），字再逐一寫出。 */
  #sentouReward .sentou-sign{position:absolute;top:2.8%;left:3%;
    font-family:'YujiBokuSentou','Noto Serif TC',serif;
    color:#221a12;font-size:clamp(19px, 7.2vmin, 34px);line-height:1.12;letter-spacing:.1em;
    text-align:center;padding:.34em .6em .38em;transform:rotate(-1.2deg);pointer-events:none;
    background:linear-gradient(160deg, rgba(243,235,216,.95), rgba(228,216,190,.93));
    border:1.5px solid #33261a;border-radius:2px;
    box-shadow:inset 0 0 0 3px rgba(243,235,216,.95), inset 0 0 0 4.5px #4a3826,
      inset 0 0 22px rgba(120,90,50,.25), 3px 5px 14px rgba(0,0,0,.45);
    animation:sentouPlaque .5s cubic-bezier(.2,1.4,.4,1) .25s backwards;}
  @keyframes sentouPlaque{from{opacity:0;transform:rotate(-1.2deg) scale(1.12);}
    to{opacity:1;transform:rotate(-1.2deg) scale(1);}}
  #sentouReward .sentou-col{display:block;}
  /* 第二行（インストール）：字級加大＋間距收窄——13px 毛筆片假名必糊，提到 15px 上下才立得住 */
  #sentouReward .sentou-col:nth-child(2){font-size:.54em;letter-spacing:.14em;margin-top:.18em;}
  /* 逐字「寫」出：由左往右 clip 揭開 + 墨暈收乾（blur→清晰），動畫延遲由 JS 逐字排 */
  #sentouReward .sentou-sign i{display:inline-block;font-style:normal;opacity:0;
    animation:sentouChar .34s ease forwards;
    text-shadow:0 0 1px rgba(34,26,18,.55), .05em .05em .14em rgba(0,0,0,.22);}
  /* 小字行不吃暈染 shadow：1px 暈在小字級上只會糊成一團 */
  #sentouReward .sentou-col:nth-child(2) i{text-shadow:none;}
  @keyframes sentouChar{
    from{opacity:0;clip-path:inset(0 100% 0 0);transform:scale(1.14);filter:blur(2.2px);}
    60%{opacity:1;filter:blur(.5px);}
    to{opacity:1;clip-path:inset(0 -12% 0 0);transform:scale(1);filter:blur(0);}}
  /* 寫完（.done）後撤掉殘留的 filter/clip-path 合成層：帶旋轉的光柵化層會讓小字發糊，
     改回純文字渲染求最銳利（此刻所有字動畫皆已跑完，切換無視覺跳動） */
  #sentouReward.done .sentou-sign i{animation:none;opacity:1;clip-path:none;transform:none;filter:none;}
  #sentouReward .sentou-hint{position:absolute;left:0;right:0;
    bottom:calc(14px + env(safe-area-inset-bottom));text-align:center;
    font-size:11px;letter-spacing:4px;color:var(--gold-dim);
    opacity:0;transition:opacity .8s;pointer-events:none;}
  #sentouReward.done .sentou-hint{opacity:.85;}
  /* Boss S 級：按下「再度執槍」→ 原地變身 SAINT INSTALL...?（字呼吸發光為主、框光為輔） */
  #rematchBtn.saintinstall{border-color:var(--gold);color:var(--gold);
    animation:saintBreath 2.2s ease-in-out infinite;}
  @keyframes saintBreath{
    0%,100%{box-shadow:0 0 5px rgba(217,198,138,.3);
      text-shadow:0 0 2px rgba(217,198,138,.35);}
    50%{box-shadow:0 0 18px rgba(217,198,138,.7);
      text-shadow:0 0 8px rgba(217,198,138,.95), 0 0 20px rgba(217,198,138,.7), 0 0 34px rgba(217,198,138,.4);}}

  /* ── 副武器選擇畫面（全螢幕）：橫式武器卡上下滑動 + 卡疊 + 武器介紹 ── */
  #weaponSheet{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;
    background:rgba(6,4,12,.96);z-index:60;
    padding:calc(14px + env(safe-area-inset-top)) 14px calc(12px + env(safe-area-inset-bottom));}
  #weaponSheet.on{display:flex;}
  #weaponSheet .ws-stage{position:relative;flex:1 1 auto;min-height:0;width:100%;
    display:flex;align-items:center;justify-content:center;touch-action:pan-x;user-select:none;}
  /* 卡疊：武器卡為橫式（16/10），各一張 .ws-frame 絕對疊放；現選在前、其餘依距離往上下墊後 */
  #weaponSheet .ws-deck{position:relative;width:min(88%,340px);aspect-ratio:16/10;}
  #weaponSheet .ws-frame{position:absolute;inset:0;overflow:hidden;
    border:1px solid var(--gold-dim);border-radius:10px;background:#0a0810;
    box-shadow:0 0 26px rgba(0,0,0,.7);
    transition:transform .42s cubic-bezier(.25,1.25,.4,1),filter .42s ease;pointer-events:none;}   /* 輪轉：帶回彈的抽換過渡 */
  #weaponSheet .ws-frame.back{filter:brightness(.38) saturate(.7);}
  /* 輪轉動畫：抽換瞬間整疊往滑動方向小幅擺轉再回正（swing-a/swing-b 由 JS 依方向掛上） */
  #weaponSheet .ws-deck.swing-a{animation:deckSwingY-a .42s cubic-bezier(.3,.7,.3,1);}
  #weaponSheet .ws-deck.swing-b{animation:deckSwingY-b .42s cubic-bezier(.3,.7,.3,1);}
  @keyframes deckSwingY-a{35%{transform:rotate(2.4deg) translateY(-4px);}100%{transform:none;}}
  @keyframes deckSwingY-b{35%{transform:rotate(-2.4deg) translateY(4px);}100%{transform:none;}}
  #weaponSheet .ws-frame img{width:100%;height:100%;object-fit:contain;-webkit-user-drag:none;}
  #weaponSheet .ws-arrow{position:absolute;left:50%;transform:translateX(-50%);z-index:30;
    width:56px;height:34px;background:rgba(15,12,22,.55);border:1px solid var(--gold-dim);
    color:var(--gold);border-radius:8px;font-family:inherit;font-size:17px;line-height:1;}
  #weaponSheet .ws-arrow:active{transform:translateX(-50%) scale(.92);}
  #weaponSheet .ws-up{top:2px;}
  #weaponSheet .ws-down{bottom:2px;}
  /* 武器介紹卡（名稱／介紹／數據）。高度固定＋卡內捲動（同搭檔卡：防 ja/en 長文擠掉選擇鈕）；
     上方卡疊亦不隨切換跳動 */
  #weaponSheet .ws-card{flex:none;width:100%;max-width:340px;height:150px;background:#0f0c16;
    border:1px solid var(--gold-dim);border-radius:12px;padding:12px 14px;text-align:left;
    overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;}
  #weaponSheet .ws-name{font-size:16px;letter-spacing:4px;color:var(--gold);text-align:center;
    margin-bottom:8px;}
  #weaponSheet .ws-desc{font-size:11.5px;line-height:1.55;color:var(--gold-dim);letter-spacing:.5px;
    white-space:pre-line;}   /* 規格文案多行（config desc 以 \n 換行） */
  #weaponSheet .ws-stats{margin-top:8px;font-size:11px;letter-spacing:1px;color:var(--ink);
    text-align:center;}

  /* ── 搭檔選人畫面（全螢幕）：大立繪左右滑動 + 技能卡 + 發動說明 ── */
  #partnerSheet{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;
    background:rgba(6,4,12,.96);z-index:60;
    padding:calc(14px + env(safe-area-inset-top)) 14px calc(12px + env(safe-area-inset-bottom));}
  #partnerSheet.on{display:flex;}
  #partnerSheet .ps-title, #weaponSheet .ps-title, #prepSheet .ps-title{font-size:15px;letter-spacing:6px;color:var(--gold);text-indent:6px;
    margin-bottom:8px;flex:none;}
  /* 立繪舞台保底：搭檔立繪（卡疊高＝舞台高）至少佔整體畫面 1/3 高——
     多語（en/ja）技能描述與發動說明較長時，被擠壓的是下方文字區、不是立繪 */
  #partnerSheet .ps-stage{position:relative;flex:1 1 auto;min-height:34vh;min-height:34dvh;width:100%;
    display:flex;align-items:center;justify-content:center;touch-action:pan-y;user-select:none;}
  /* 取景框：固定 2/3 直式外框、overflow 裁切。立繪高度＝框高 × --ps-zoom（config siFit.zoom），
     水平置中、垂直以 --ps-top（頭頂偏移）對齊——各搭檔頭部大小以蕾妮（zoom:1）為基準統一。 */
  /* 卡疊容器：高度撐滿 stage、維持 2/3 直式比例；各搭檔一張 .ps-frame 絕對疊放，
     transform 由 JS 依相對位置寫入（現選在前，其餘依距離往側後方墊、變暗） */
  #partnerSheet .ps-deck{position:relative;height:100%;aspect-ratio:2/3;}
  #partnerSheet .ps-frame{position:absolute;inset:0;overflow:hidden;
    border:1px solid var(--gold-dim);border-radius:10px;background:#0a0810;
    box-shadow:0 0 26px rgba(0,0,0,.7);
    transition:transform .42s cubic-bezier(.25,1.25,.4,1),filter .42s ease;pointer-events:none;}   /* 輪轉：帶回彈的抽換過渡 */
  #partnerSheet .ps-frame.back{filter:brightness(.38) saturate(.7);}
  /* 輪轉動畫：抽換瞬間整疊往滑動方向小幅擺轉再回正（swing-a/swing-b 由 JS 依方向掛上） */
  #partnerSheet .ps-deck.swing-a{animation:deckSwingX-a .42s cubic-bezier(.3,.7,.3,1);}
  #partnerSheet .ps-deck.swing-b{animation:deckSwingX-b .42s cubic-bezier(.3,.7,.3,1);}
  @keyframes deckSwingX-a{35%{transform:rotate(-3deg) translateX(-6px);}100%{transform:none;}}
  @keyframes deckSwingX-b{35%{transform:rotate(3deg) translateX(6px);}100%{transform:none;}}
  #partnerSheet .ps-portrait{position:absolute;left:50%;top:0;height:calc(100% * var(--ps-zoom,1));
    width:auto;transform:translateX(-50%) translateY(var(--ps-top,0%));
    pointer-events:none;-webkit-user-drag:none;}
  #partnerSheet .ps-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;
    width:38px;height:56px;background:rgba(15,12,22,.55);border:1px solid var(--gold-dim);
    color:var(--gold);border-radius:8px;font-family:inherit;font-size:24px;line-height:1;}
  #partnerSheet .ps-arrow:active{transform:translateY(-50%) scale(.92);}
  #partnerSheet .ps-prev{left:2px;}
  #partnerSheet .ps-next{right:2px;}
  #partnerSheet .ps-dots, #weaponSheet .ps-dots{display:flex;gap:8px;margin:8px 0 6px;flex:none;}
  #partnerSheet .ps-dots i, #weaponSheet .ps-dots i{width:7px;height:7px;border-radius:50%;
    background:transparent;border:1px solid var(--gold-dim);}
  #partnerSheet .ps-dots i.cur, #weaponSheet .ps-dots i.cur{background:var(--gold);border-color:var(--gold);}
  #partnerSheet .ps-dots i.picked, #weaponSheet .ps-dots i.picked{box-shadow:0 0 8px var(--gold);}
  /* 卡片高度「固定」（非 min-height）：ja/en 描述較長會把選擇鈕擠出畫面 →
     內容改卡內上下捲動；上方取景框也不隨切換縮放，頭部大小才真正一致 */
  #partnerSheet .ps-card{flex:none;width:100%;max-width:340px;height:182px;background:#0f0c16;
    border:1px solid var(--gold-dim);border-radius:12px;padding:12px 14px;text-align:left;
    overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;}
  #partnerSheet .ps-name{font-size:16px;letter-spacing:4px;color:var(--gold);text-align:center;
    margin-bottom:8px;}
  #partnerSheet .ps-skill{margin-top:7px;}
  #partnerSheet .ps-k{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ink);
    letter-spacing:1px;}
  #partnerSheet .ps-k b{color:var(--gold);font-weight:600;}
  #partnerSheet .ps-tag{flex:none;font-size:10px;letter-spacing:2px;color:var(--gold-dim);
    border:1px solid var(--gold-dim);border-radius:4px;padding:1px 6px;text-indent:2px;}
  #partnerSheet .ps-d{font-size:11.5px;line-height:1.55;color:var(--gold-dim);margin:3px 0 0 2px;
    letter-spacing:.5px;}
  #partnerSheet .ps-howto{flex:none;width:100%;max-width:340px;margin-top:8px;
    padding:8px 12px;border-top:1px solid rgba(217,198,138,.22);
    font-size:10.5px;line-height:1.7;letter-spacing:.5px;color:var(--gold-dim);text-align:center;}
  /* 矮視窗（小手機/橫向）：立繪舞台保底 1/3 後空間不足 → 下方文字區讓位
     （卡片高度固定的「防切換跳動」在矮機讓位給「立繪不得過小」） */
  @media (max-height:730px){
    #partnerSheet .ps-card{min-height:0;padding:10px 12px;}
    #partnerSheet .ps-howto{line-height:1.5;margin-top:5px;padding:6px 10px;}
  }
  /* 極矮視窗（320×568 級）：再壓一級行距/留白，保住底部選擇鈕不被裁 */
  @media (max-height:600px){
    #partnerSheet .ps-title{margin-bottom:4px;}
    #partnerSheet .ps-dots{margin:4px 0 2px;}
    #partnerSheet .ps-howto{font-size:9.5px;line-height:1.45;padding:4px 8px;}
    #partnerSheet .ps-btns{margin-top:3px;}
    #partnerSheet #psSelect{padding:8px 26px;}
  }
  /* 視窗被裁（iOS 26 standalone）：底部安全區位於不可視死區，白墊拿回還給立繪舞台 */
  html.vp-clipped #partnerSheet, html.vp-clipped #weaponSheet{
    padding-bottom:12px;}
  #partnerSheet .ps-btns, #weaponSheet .ps-btns{flex:none;display:flex;gap:12px;margin-top:6px;}
  #partnerSheet #psSelect, #weaponSheet #wsSelect{padding:10px 30px;background:transparent;border:1px solid var(--gold);
    color:var(--gold);border-radius:8px;font-family:inherit;font-size:13px;letter-spacing:3px;
    box-shadow:0 0 12px var(--gold-dim);}
  #partnerSheet #psSelect.picked, #weaponSheet #wsSelect.picked{border-color:var(--gold-dim);color:var(--gold-dim);box-shadow:none;}
  #partnerSheet #psSelect:active, #weaponSheet #wsSelect:active{transform:scale(.95);}

  /* 首頁底部：Credit / 原作 小鈕一排，版權宣告獨立一行在其下，整組貼底置中（避開 home indicator 安全區）。
     版權不與按鈕同排——窄機/字體較寬時會互相擠壓。 */
  #home #homeLinks{position:absolute;left:0;right:0;
    bottom:calc(10px + env(safe-area-inset-bottom));
    display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:10px;padding:0 8px;}
  /* 視窗被裁（iOS 26 standalone）：home indicator 位於不可視死區，安全區墊高全屬白墊 → 拿回 */
  html.vp-clipped #home #homeLinks{bottom:10px;}
  #home #tutorialBtn, #home #creditBtn, #home #originalBtn, #home #statsBtn{padding:6px 18px;background:transparent;
    border:1px solid var(--gold-dim);border-radius:20px;color:var(--gold-dim);
    font-family:inherit;font-size:11px;letter-spacing:2px;flex:none;}
  #home #tutorialBtn:active, #home #creditBtn:active, #home #originalBtn:active, #home #statsBtn:active{transform:scale(.95);color:var(--gold);border-color:var(--gold);}
  /* 後臺統計鈕（管理員限定）：嚴格綁定清盤鈕——只認本場手勢解鎖（body.testmode），
     重整即隱藏。裝置永久簽名只作遙測排除，不單獨顯示此鈕。 */
  #home #statsBtn{display:none;}
  body.testmode #home #statsBtn{display:block;}
  /* 版權：強制換行獨占一行（flex-basis:100%），置中、單行 */
  #home .home-copyright{flex:0 0 100%;text-align:center;margin-top:2px;
    font-size:9.5px;letter-spacing:.5px;color:var(--gold-dim);
    opacity:.65;pointer-events:none;white-space:nowrap;}
  /* 版本號不上首頁：改顯示於「連點團徽 5 下」的診斷 HUD（main.js debugHud） */

  /* 原作選擇面板 */
  #originalSheet{position:absolute;inset:0;display:none;align-items:center;justify-content:center;
    background:rgba(4,3,8,.88);z-index:60;}
  #originalSheet.on{display:flex;}
  #originalSheet .os-panel{width:80%;max-width:320px;background:#0f0c16;border:1px solid var(--gold-dim);
    border-radius:12px;padding:18px 16px 16px;text-align:center;box-shadow:0 0 30px rgba(0,0,0,.7);}
  #originalSheet .os-title{font-size:16px;letter-spacing:6px;color:var(--gold);margin-bottom:12px;}
  #originalSheet .os-work{font-size:15px;letter-spacing:2px;color:var(--gold);margin-bottom:4px;}
  #originalSheet .os-note{font-size:11px;letter-spacing:.5px;color:var(--gold-dim);margin-bottom:14px;}
  #originalSheet .os-links{display:flex;gap:10px;margin-bottom:14px;}
  #originalSheet .os-link{flex:1;text-align:center;padding:12px 8px;background:rgba(30,24,42,.7);
    border:1px solid var(--gold-dim);border-radius:8px;color:var(--gold);text-decoration:none;
    font-size:14px;letter-spacing:2px;}
  #originalSheet .os-link:active{transform:scale(.97);border-color:var(--gold);box-shadow:0 0 12px var(--gold-dim);}
  #originalSheet .os-close{padding:9px 34px;background:transparent;border:1px solid var(--gold-dim);
    color:var(--ink);border-radius:8px;font-family:inherit;font-size:13px;letter-spacing:3px;}
  #originalSheet .os-close:active{transform:scale(.97);}

  /* Credit 面板 */
  #creditSheet{position:absolute;inset:0;display:none;align-items:center;justify-content:center;
    background:rgba(4,3,8,.88);z-index:60;}
  #creditSheet.on{display:flex;}
  #creditSheet .credit-panel{width:85%;max-width:360px;max-height:80%;background:#0f0c16;
    border:1px solid var(--gold-dim);border-radius:12px;padding:18px 16px 16px;text-align:center;
    display:flex;flex-direction:column;box-shadow:0 0 30px rgba(0,0,0,.7);}
  #creditSheet .credit-title{font-size:16px;letter-spacing:5px;color:var(--gold);margin-bottom:14px;flex:none;}
  #creditSheet .credit-scroll{overflow-y:auto;overscroll-behavior:contain;flex:1 1 auto;min-height:0;
    text-align:left;padding-right:2px;}
  #creditSheet .credit-sec{margin-bottom:16px;}
  #creditSheet .credit-h{font-size:12px;letter-spacing:3px;color:var(--holy);
    border-bottom:1px solid var(--gold-dim);padding-bottom:5px;margin-bottom:10px;}
  #creditSheet .credit-list{list-style:none;margin:0;padding:0;}
  #creditSheet .credit-list li{border-bottom:1px dashed rgba(138,109,46,.35);font-size:12.5px;}
  #creditSheet .credit-list li:last-child{border-bottom:none;}
  /* 整列＝外連（前往作曲者頁面）：flex 版面掛在 a 上，整列可點、按下金框回饋 */
  #creditSheet .cl-link{display:flex;align-items:baseline;gap:8px;padding:6px 0;
    color:inherit;text-decoration:none;-webkit-tap-highlight-color:transparent;}
  #creditSheet .cl-link:active .cl-name{color:var(--gold);}
  #creditSheet .cl-name{color:var(--ink);flex:1 1 auto;min-width:0;}
  #creditSheet .cl-by{color:var(--gold-dim);font-size:11px;letter-spacing:.5px;flex:none;}
  #creditSheet .cl-use{color:var(--holy);font-size:10.5px;letter-spacing:.5px;flex:none;
    opacity:.85;white-space:nowrap;}
  /* 說明列：載明點擊曲目會前往作曲者頁面 */
  #creditSheet .credit-tip{font-size:10.5px;letter-spacing:1px;color:var(--gold-dim);
    text-align:center;opacity:.85;margin-top:2px;}
  #creditSheet .credit-close{margin-top:14px;flex:none;align-self:center;padding:9px 34px;
    background:transparent;border:1px solid var(--gold-dim);color:var(--ink);
    border-radius:8px;font-family:inherit;font-size:13px;letter-spacing:3px;}
  #creditSheet .credit-close:active{transform:scale(.97);}

  /* ══ 教學關卡（tutorial）══════════════════════════════════════════
   *  立繪層 #tutCast 掛在 #top 內（overflow:hidden 天然裁切左右滑入），
   *  z-20：壓過紅點(9)/血條(6)，低於退出鈕(37)與跳過鈕(38)。
   *  對話框浮在立繪之上（同容器 DOM 序靠後即可），停在敵人框下緣血條之上。
   *  #tutTouch＝對話期間全畫面點擊層（z-36 < corner-btn 37 → 退出/跳過仍可點）。 */
  #tutCast{position:absolute;inset:0;z-index:20;display:none;pointer-events:none;}
  #tutCast.on{display:block;}
  .tut-portrait{position:absolute;bottom:0;height:88%;max-width:62%;object-fit:contain;
    object-position:bottom;filter:brightness(.38) saturate(.75);
    transition:transform .45s ease,filter .25s ease;}
  /* .in 逐立繪掛在 img 上：只有說到話的角色才在場（單人段落不出現另一位） */
  #tutCastL{left:-2%;transform:translateX(-108%);}
  #tutCastR{right:-2%;transform:translateX(108%);}
  #tutCast .tut-portrait.in{transform:translateX(0);}
  /* .center（step.center）：立繪移畫面正中——側邊讓位給引導箭頭（箭頭不壓立繪） */
  #tutCast .tut-portrait.center{left:50%;right:auto;transform:translateX(-150%);}
  #tutCast .tut-portrait.center.in{transform:translateX(-50%);}
  .tut-portrait.speaking{filter:brightness(1) saturate(1);}   /* 說話者原色；其餘維持調暗 */
  /* 對話框：緊貼數字盤面上方（間隔 2px）。#top overflow:hidden 裁不到盤面側
     → 改 fixed 脫離裁切，精確 bottom 由 tutorial.placeBubble 依 #grid 實測寫入
     （此處 bottom:52% 僅為 JS 未及執行時的保底位置）；框高增長時向上長、貼齊邊不動。 */
  /* 教學對話框：#app 直屬、z-8000＝第二層——高於一般演出層（整備頁 55／轉場光點 56／
     立繪 20 等），但低於 cut-in(8100)／結局 cut-in(8200)，演出播放時讓位；
     黑幕(9000)與確認框(9500)仍蓋住它。顯示由自帶的 .on 控制（原靠父層 #tutCast 的 display）。 */
  /* ⚠ pointer-events:none 必要：對話框自 #tutCast 移出後為 #app 直屬（非 #tutTouch 的子孫），
     z-8000 又高於全畫面點擊層 #tutTouch(z-36) → 點在對話框上會被它吃掉，事件沿 #app 冒泡
     而非經過 #tutTouch，推進台詞的 handler 收不到＝對話框整塊變死區（玩家最直覺點的位置）。
     框內只有文字（tut-name/tut-line/tut-next），無可互動元件，穿透不損任何功能。 */
  #tutBubble{display:none;z-index:8000;pointer-events:none;
    position:fixed;left:50%;bottom:52%;transform:translateX(-50%);
    width:min(92%,360px);background:rgba(8,6,12,.9);border:1px solid var(--gold-dim);
    border-radius:10px;padding:9px 14px 12px;box-shadow:0 4px 18px rgba(0,0,0,.55);}
  /* 雙槍引導段（dualReady，tutorial.js 掛 .clasp-clear）：縮窄並右移，
     讓出左側破防計量表——玩家要看著它點（引導箭頭也指著它） */
  #tutBubble.on{display:block;}
  #tutBubble.clasp-clear{width:min(70%,300px);transform:translateX(-38%);}
  /* 台詞關鍵字（聖徒化／Saint Install）：金色粗字（i18n.decorateLine 包 .kw-saint） */
  .kw-saint{color:var(--gold);font-weight:bold;}
  #tutBubble .tut-name{font-size:11px;letter-spacing:2px;color:var(--gold);margin-bottom:4px;}
  #tutBubble .tut-line{font-size:13px;letter-spacing:.5px;line-height:1.7;color:var(--ink);
    min-height:3.4em;}
  #tutBubble .tut-next{position:absolute;right:10px;bottom:5px;font-size:9px;
    color:var(--gold);opacity:0;}
  #tutBubble.done .tut-next{animation:tutNext .7s ease-in-out infinite alternate;}
  @keyframes tutNext{from{opacity:.25;transform:translateY(0);}to{opacity:.95;transform:translateY(2px);}}
  /* 教學對話期間（dlg-pause）：凍結中的大絕紅點提到立繪之上——threat 步驟正對著它講解 */
  body.dlg-pause #redDots{z-index:21;}
  #tutTouch{position:fixed;inset:0;z-index:36;display:none;background:transparent;touch-action:none;}
  #tutTouch.on{display:block;}
  /* 跳過鈕：小型膠囊、三語統一 SKIP（i18n battle.skipBtn） */
  #tutSkipBtn{position:absolute;top:12px;left:10px;z-index:38;display:none;padding:4px 10px;
    border-radius:12px;background:rgba(10,8,14,.72);border:1px solid var(--gold-dim);
    color:var(--gold);font-family:inherit;font-size:10px;letter-spacing:1.5px;}
  #tutSkipBtn.on{display:block;}
  #tutSkipBtn:active{transform:scale(.94);}

  /* ── 教學引導箭頭（雪鐵龍雙箭羽依次閃滅）──
   *  #tutGuide 疊在 tutTouch(36) 之上、跳過鈕(38) 之下，pointer-events:none（手勢仍落在 tutTouch）。
   *  方向由 g-down/g-right/g-up 決定：chevron 用 border 折角轉向、容器主軸沿指向排列，
   *  依次閃滅（animation-delay 級聯）引導視線。 */
  #tutGuide{position:fixed;z-index:37;display:none;pointer-events:none;
    transform:translate(-50%,-50%);text-align:center;
    filter:drop-shadow(0 0 6px rgba(212,169,74,.8));}
  #tutGuide.on{display:block;}
  #tutGuide .tg-chevrons{display:flex;gap:7px;align-items:center;justify-content:center;}
  #tutGuide .tg-chevrons i{width:16px;height:16px;flex:none;
    border-top:4px solid var(--gold);border-right:4px solid var(--gold);
    opacity:.15;animation:tgBlink .9s infinite;}
  #tutGuide .tg-chevrons i:nth-child(2){animation-delay:.3s;}
  #tutGuide .tg-chevrons i:nth-child(3){animation-delay:.6s;}
  @keyframes tgBlink{0%{opacity:.15;}30%{opacity:1;}70%{opacity:1;}100%{opacity:.15;}}
  #tutGuide.g-right .tg-chevrons{flex-direction:row;}
  #tutGuide.g-right .tg-chevrons i{transform:rotate(45deg);}
  #tutGuide.g-down  .tg-chevrons{flex-direction:column;}
  #tutGuide.g-down  .tg-chevrons i{transform:rotate(135deg);}
  #tutGuide.g-up    .tg-chevrons{flex-direction:column-reverse;}   /* 由下往上依次閃 */
  #tutGuide.g-up    .tg-chevrons i{transform:rotate(-45deg);}
  #tutGuide .tg-label{margin-top:8px;font-size:13px;letter-spacing:3px;color:var(--gold);
    text-shadow:0 0 8px rgba(212,169,74,.75);animation:tgLabel 1s ease-in-out infinite alternate;}
  /* 點擊閘（指向左緣破防計量表）：標示縮字，置中定位時左緣不出畫面（箭頭保持正對計量表） */
  #tutGuide.g-down .tg-label{font-size:10px;letter-spacing:1px;}
  @keyframes tgLabel{from{opacity:.55;}to{opacity:1;}}
