/* 配色的權威來源是平台的 music-hub/public/mh-theme.css（Lyrical Parchment），
   這裡只做「遊戲的語彙 → 平台 token」的對照。每一條都帶 fallback：
   平台沒載入時退回 v1.27 以前的原色，遊戲不會裸奔。
   **不要在這裡寫死新色**——寫死就等於又多出一份色票，正是這次要收掉的東西。
   （原本的 --srg-bg/--srg-accent/--srg-blue 三個別名全域零引用，已刪。） */
.srg-root{
  --srg-paper:var(--mh-paper,#f7f1e3);
  --srg-cream:var(--mh-surface,#f4ead2);
  /* ochre 是「金色系的字」：關卡標籤、分數數字。honey(#fed65b) 太亮，不能當字色。 */
  --srg-ochre:var(--mh-gold-ink,#c9a86a);
  --srg-honey:var(--mh-honey,#fed65b);
  --srg-slate:var(--mh-muted,#6b7c94);
  /* navy 現在是主色橄欖綠：標題、強調、active pill 的底色都吃它。 */
  --srg-navy:var(--mh-primary,#2b3a4a);
  --srg-ink:var(--mh-ink,#2b3a4a);
  --srg-success:var(--mh-success,#4fa46a);
  --srg-border:var(--mh-border,rgba(var(--mh-gold-rgb,201,168,106),.35));
  /* 內文用 ink（近黑）而不是主色——整頁橄欖綠讀起來會糊。 */
  position:relative;background:var(--srg-paper);color:var(--srg-ink);
  border-radius:20px;overflow:hidden;
  /* clip 與 hidden 裁的東西一樣，差別是 **clip 不會讓 .srg-root 變成捲動容器**。
     hidden 會 —— 那時關卡列表上方那條 position:sticky 的地區列（v2.60.0）
     黏的是一個從不捲動的盒子，等於沒黏。不支援 clip 的瀏覽器退回上一行。 */
  overflow:clip;
  /* 換畫面時 scrollToRoot() 會把這裡捲到視窗頂端，留一點餘裕別貼死上緣。
     固定式頁首的主題若有設 html{scroll-padding-top}，scrollIntoView 會自動加上去。 */
  scroll-margin-top:16px;
  font-family:var(--mh-sans,"Nunito","PingFang TC","Noto Sans TC",-apple-system,sans-serif);
  /* 內距跟著容器寬度縮放，不用斷點。主題本身就會先吃掉左右各 30–50px
     （Twenty Twenty-Five 的 root padding 是 clamp(30px,5vw,50px)），
     再加一層固定內距，窄畫面上能用的寬度就所剩無幾了。
     % 是相對於容器寬度，所以不同瀏覽器的視窗寬度差異會自動被吸收。 */
  padding:clamp(8px,2.4%,18px);box-shadow:0 10px 32px -14px rgba(var(--mh-ink-rgb,43,58,74),.25)}
.srg-root *{box-sizing:border-box}
/* 嵌入寬度模式（後台設定頁 / 短代碼 width 屬性） */
.srg-root.srg-w-box{box-sizing:border-box;max-width:var(--srg-maxw,760px);margin-left:auto;margin-right:auto}
/* full：區塊主題靠 alignfull class 撐滿整個內容區（正確處理全域邊距，無多餘捲軸）。
   滿版時遊戲已經貼著螢幕邊緣，自己的左右內距再收一段，把寬度全留給樂譜與鍵盤。 */
.srg-root.srg-w-full{box-sizing:border-box;border-radius:0;
  padding-left:clamp(6px,1.6%,14px);padding-right:clamp(6px,1.6%,14px);
}
/* 古典主題若未替 alignfull 定義樣式，退化為隨內容寬度（不做 100vw 破格，避免因捲軸寬度產生水平捲動）。 */
/* content 模式維持預設（隨容器寬度，不額外限制） */
.srg-root h1,.srg-root h2,.srg-root h3,.srg-root h4{font-family:var(--mh-serif,"Fraunces","Noto Serif TC",Georgia,serif);letter-spacing:-.02em;margin:0}
.srg-loading{padding:60px;text-align:center;font-size:20px;color:var(--srg-slate)}
/* 載入失敗：原始錯誤訊息小一級且不搶戲，重試鈕要摸得到（44px 是觸控下限）。 */
.srg-load-fail .srg-sub{font-size:13px;opacity:.75;margin:8px 0 16px;word-break:break-word}
.srg-load-fail .srg-btn{min-height:44px}

/* ================= 鍵盤焦點 =================
 *
 * **整份 game.css 原本一條 `:focus` 都沒有。** 很多佈景（含區塊主題的重設）
 * 會寫 `:focus{outline:none}`，那一條會一路吃到遊戲裡，於是用鍵盤操作的人
 * 全程看不到自己站在哪一顆按鈕上 —— 而鋼琴面板正是靠鍵盤才能作答的
 * （見 game.js buildPiano 的 keyActivate）。
 *
 * 用 `:focus-visible` 而不是 `:focus`：滑鼠點下去不該冒出外框，
 * 那會被誤讀成「選取中」。`outline-offset` 是負的，因為琴鍵是彼此貼齊的，
 * 往外畫的外框會被後畫的相鄰琴鍵蓋掉（同 .srg-lit 光暈那個坑）。
 */
.srg-root :is(button,a,select,input,[role="button"],[tabindex]):focus-visible{
  outline:3px solid var(--srg-honey);
  outline-offset:2px;
  border-radius:6px;
}
.srg-root .srg-white:focus-visible,.srg-root .srg-black:focus-visible{
  outline-offset:-3px;
  z-index:3;
}

/* ================= 流程閘門的說明卡 =================
   （SRG_Shortcode::notice_card()：教師／未開放訪客／流程還沒走完） */
.srg-gate .srg-gate-card{text-align:center;max-width:520px;margin:24px auto;padding:28px 24px}
.srg-gate-icon{font-size:44px;line-height:1;margin-bottom:10px}
.srg-gate .srg-gate-card h2{font-size:24px;color:var(--srg-navy);margin-bottom:8px}
.srg-gate .srg-gate-card .srg-sub{line-height:1.7}
.srg-gate-actions{margin:18px 0 0}
.srg-gate-actions .srg-btn{display:inline-block;text-decoration:none;
  min-height:44px;padding:11px 22px;font-size:16px}
.srg-bg-layer{position:absolute;inset:0;background-size:cover;background-position:center;opacity:.35;z-index:0;pointer-events:none;transition:filter .3s,opacity .3s}
/* 內容欄置中並限寬：滿版是為了手機（把主題左右各 30–50px 的內距要回來），
   桌機上真的鋪滿 1920px 的話，選單會排成七欄、樂譜會被放大到荒謬的尺寸。
   **上限放在 .srg-content 而不是 .srg-root**：主題的 .alignfull 用 !important
   蓋掉左右 margin，root 上的 margin:auto 根本置中不了（實測 1280px 下整塊
   靠左）。放在內層還有個好處——羊皮紙底色仍然滿版，只有內容被收攏。 */
/* width:100% 不能省：遊戲畫面時 .srg-content 是 flex 項目，而**auto margin 會
   取消 flex 的 stretch**，只剩內容寬度（實測整塊縮成 260px）。 */
.srg-content{position:relative;z-index:1;width:100%;max-width:960px;margin-left:auto;margin-right:auto}
.srg-card{background:rgba(var(--mh-surface-rgb,244,234,210),.88);border:1px solid var(--srg-border);border-radius:20px;padding:16px 20px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 8px 24px -12px rgba(var(--mh-ink-rgb,43,58,74),.35),0 2px 4px -2px rgba(var(--mh-ink-rgb,43,58,74),.15);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.srg-hero{display:flex;align-items:center;gap:16px;margin-bottom:14px}
.srg-hero .srg-mascot{width:88px;height:88px;object-fit:contain;filter:drop-shadow(0 4px 8px rgba(var(--mh-ink-rgb,43,58,74),.25));flex-shrink:0}
.srg-hero h1{font-size:32px;color:var(--srg-navy);margin:0 0 4px;line-height:1.1}
.srg-hero p{margin:0;color:var(--srg-slate);font-size:13px}
/*
 * 窄螢幕（2026-10-06，使用者回報「Firefox 上配置不正確」）：
 * 實測 Firefox 與 Chromium 數字完全相同，真因是寬度 —— Android「顯示大小」調大後
 * 版面只有 288px，一列塞「吉祥物 88＋標題＋喇叭＋全螢幕」，標題欄只剩 52px，
 * 「穆茲卡傳奇」直排成一字一行（360px 也會折成兩行）。
 * 改成兩列格線：兩顆按鈕在右上，標題與箴言在下一列吃滿吉祥物右邊的寬度。
 */
@media (max-width:480px){
  .srg-hero{display:grid;grid-template-columns:auto 1fr auto auto;column-gap:8px;row-gap:2px;align-items:start}
  .srg-hero .srg-mascot{grid-column:1;grid-row:1 / span 2;align-self:center;width:64px;height:64px}
  .srg-hero > div{grid-column:2 / -1;grid-row:2;min-width:0}
  .srg-hero .srg-menu-bgm-btn{grid-column:3;grid-row:1}
  .srg-hero .srg-menu-fs-btn{grid-column:4;grid-row:1}
}
.srg-title{font-size:22px;font-weight:700;margin:0 0 4px;color:var(--srg-navy)}
.srg-sub{color:var(--srg-slate);font-size:13px;margin:0}
.srg-section-block{margin-top:18px}

/* ================= 三層分類標題（關卡列表）=================
 *
 * 大分類（領域）→ 中分類（課程路線）→ 小分類。三層共用 `.srg-cat-head`，
 * 差別只有 `.srg-cat-l1/l2/l3` 那一層的字級、紋章大小與上方的分隔。
 *
 * ## 為什麼改掉「靠縮排不靠字級」
 *
 * 原本三層刻意同字級、只用左側直線與縮排分層。實際畫面上的結果是**分類與
 * 分類之間看不出斷點** —— 一整頁的關卡卡片之間夾著幾行同樣大小的字，
 * 玩家要從卡片的排列去反推哪幾張是同一組（使用者 2026-09-26 回報）。
 * 現在分層靠三件事一起講：字級、紋章牌、以及大分類上方的那條裝飾分隔帶。
 *
 * ## 名牌的底圖
 *
 * `--srg-cat-motif` 由 game.js 逐個分類寫進來（圖檔網址只有執行期知道）。
 * 底下疊三層：紋章（左端，aspect 固定）→ 織紋（repeat，極低對比）→
 * 羊皮紙漸層。**織紋不能再深**：標題字就壓在它上面。
 */
.srg-cat-head{display:flex;align-items:center;justify-content:space-between;
  gap:10px;flex-wrap:wrap}
.srg-cat-head .srg-cat-main{min-width:0;flex:1 1 auto}
.srg-cat-plate{display:inline-flex;align-items:center;border-radius:12px;
  border:1px solid rgba(var(--mh-gold-rgb,201,168,106),.5);
  /* 織紋與分隔帶走**相對路徑**：它們是固定檔名，而相對網址是相對於這份
     樣式表解析的，所以外掛裝在哪個目錄都對。紋章不能這樣寫（檔名隨分類而變），
     那一層由 game.js 寫 --srg-cat-motif 進來。 */
  background-image:var(--srg-cat-motif),url(assets/cat/weave.svg),
    linear-gradient(100deg,rgba(var(--mh-surface-hi-rgb,255,251,240),.95),
      rgba(var(--mh-surface-rgb,244,234,210),.75));
  background-repeat:no-repeat,repeat,no-repeat;
  background-position:left .55em center,left top,center;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7),
    0 2px 6px -4px rgba(var(--mh-ink-rgb,43,58,74),.5)}
.srg-cat-plate .srg-cat-name{margin:0;color:var(--srg-navy);
  /* 名牌的織紋在字底下，襯線字的細筆畫要靠這一點點亮邊才不會被吃掉。 */
  text-shadow:0 1px 0 rgba(255,255,255,.65);overflow-wrap:anywhere}
.srg-cat-head .srg-cat-desc{font-size:12px;color:var(--srg-slate);margin-top:4px}
.srg-cat-head .srg-count{font-size:13px;color:var(--srg-slate);white-space:nowrap}
.srg-cat-head .srg-count b{color:var(--srg-navy)}

/* ---- 第一層：領域 ---- */
.srg-cat-l1{margin:34px 0 10px;padding-top:16px;
  /* 分隔帶：上一塊領域到這裡結束。只靠間距講不夠——中間隔著一整片卡片格線，
     那點空白讀起來只是「下一排卡片」。 */
  background:url(assets/cat/divider.svg) left top repeat-x}
/* 第一塊不必先畫一條線（上面就是玩家資訊卡，本來就斷得很清楚）。
   **靠 JS 加 class 而不是 :first-of-type**：這些標題是 .srg-content 的
   第 n 個 div，前面還有英雄區／玩家卡／成就卡，:first-of-type 永遠選不中。 */
.srg-cat-l1.srg-cat-first{margin-top:18px;padding-top:0;background-image:none}
.srg-cat-l1 .srg-cat-plate{padding:8px 18px 8px 52px;background-size:34px auto,28px 28px,auto}
.srg-cat-l1 .srg-cat-name{font-size:clamp(22px,3.6vw,28px);line-height:1.25}
.srg-cat-l1 .srg-cat-desc{font-size:13px}
.srg-cat-head .srg-region-type{font-size:12px;padding:2px 12px;border-radius:10px;
  background:var(--mh-honey,#fed65b);color:var(--srg-navy);white-space:nowrap;
  align-self:center}

/* ---- 第二層：課程路線 ---- */
.srg-cat-l2{margin:22px 0 4px;padding-left:12px;
  border-left:3px solid var(--mh-honey,#fed65b)}
.srg-cat-l2 .srg-cat-plate{padding:5px 14px 5px 40px;background-size:26px auto,28px 28px,auto}
.srg-cat-l2 .srg-cat-name{font-size:clamp(18px,2.6vw,21px);line-height:1.3}

/* ---- 第三層：小分類 ---- */
.srg-cat-l3{margin-bottom:10px}
.srg-cat-l3 .srg-cat-plate{padding:4px 12px 4px 34px;background-size:22px auto,24px 24px,auto}
.srg-cat-l3 .srg-cat-name{font-size:clamp(16px,2.2vw,18px);line-height:1.3}
/* 路線底下的小分類：縮排並讓名牌收一階，才不會與路線標題搶視線。 */
.srg-section-block.srg-in-track{margin-top:14px;padding-left:12px;
  border-left:1px solid rgba(var(--mh-ink-rgb,43,58,74),.12)}
.srg-section-block.srg-in-track .srg-cat-l3 .srg-cat-name{font-size:16px}
/* 還沒選角色的引導卡。 */
.srg-pick-avatar{margin-top:14px;display:flex;flex-direction:column;align-items:flex-start;gap:8px}
.srg-pick-avatar h3{font-size:18px;margin:0;color:var(--srg-navy)}
/*
 * **`minmax(240px,…)` 的 240 是硬地板：容器比它窄的時候格線不會跟著縮，
 * 而 `.srg-root` 是 overflow:hidden —— 超出的部分是被裁掉，不是可以捲。**
 * 摺疊機（280px）與加了較寬內距的佈景就會踩到，症狀是右邊那一欄缺一角。
 *
 * `min(240px, 100%)` 是這個問題的標準解：想要 240px，但容器更窄時
 * 就收到容器寬。**刻意不改成更小的固定值**（例如 150px）—— 那會讓
 * 360px 的手機從「一欄 306px」變成「兩欄各 148px」，卡片反而更難讀，
 * 而那台手機本來就沒有裁切問題。
 */
.srg-menu-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(240px,100%),1fr));gap:12px}
.srg-level-btn{cursor:pointer;text-align:left;padding:14px 16px;border:1px solid var(--srg-border);
  background:rgba(var(--mh-surface-hi-rgb,255,251,240),.9);border-radius:16px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 4px 12px -8px rgba(var(--mh-ink-rgb,43,58,74),.25);
  transition:transform .15s,box-shadow .15s;font-family:inherit;color:inherit}
.srg-level-btn:hover:not(:disabled){transform:translateY(-2px);box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 8px 20px -8px rgba(var(--mh-ink-rgb,43,58,74),.35)}
.srg-level-btn:disabled{opacity:.5;cursor:not-allowed}
.srg-level-btn .srg-tag{font-size:10px;letter-spacing:.15em;text-transform:uppercase;color:var(--srg-ochre);font-weight:700}
/* **長標題要斷得掉。** 中文自然會斷行，但關卡標題可能是一長串沒有空白的
   拉丁字（匯入題的檔名、測試關卡），那種字串預設不斷 —— 它會撐破格線的
   欄寬，然後被 .srg-root 的 overflow:hidden 裁掉，畫面上只是「標題右邊沒了」。
   實測 360px 下 173px 的標題塞在 135px 的欄裡。
   `anywhere` 而不是 `break-word`：後者對「一個超長的單字」仍然可能不斷。 */
.srg-level-btn h4{margin:4px 0 2px;font-size:18px;color:var(--srg-navy);overflow-wrap:anywhere}
/* 區域／路線／徽章的標題同理（都是使用者自己命名的字串）。 */
.srg-region-head h2,.srg-track-head h3,.srg-section-head h3,.srg-ach-name{overflow-wrap:anywhere}
.srg-level-btn .srg-lvsub{color:var(--srg-slate);font-size:13px;margin-top:4px}
/* ---- 卡片上的「範圍」 ----
 * 一列一件事（拍號／音符／節奏型／音域）。標籤欄固定寬度靠 grid，
 * 四列的值才會對齊成一欄 —— 串成一行的話 240px 的卡片會折行，
 * 而折行之後看不出哪個詞屬於哪一類。 */
.srg-level-btn .srg-lvscope{display:grid;grid-template-columns:auto 1fr;
  gap:1px 7px;margin-top:5px;font-size:12.5px;line-height:1.45}
.srg-level-btn .srg-lvkey{color:var(--srg-ochre);font-weight:700;font-size:11px;
  letter-spacing:.04em;white-space:nowrap;padding-top:1px}
.srg-level-btn .srg-lvval{color:var(--srg-slate);overflow-wrap:anywhere}
.srg-level-btn small{display:block;margin-top:6px;color:#8a94a3;font-size:11px}
/* 魔王關的標記。**紫色，和另外四個旗標都不同色** —— 那四個講的是「你能不能玩」
   （綠＝玩過了、紅褐＝要先打上一關、琥珀＝還沒做好、藍紫＝要升級方案），
   這一個講的是「這一關是什麼」，永遠不會因為玩家做了什麼而消失。
   做成藥丸而不是一行字：它排在最上面，跟下面的狀態旗標要一眼分得開。 */
.srg-level-btn .srg-boss-flag{margin-top:6px;display:inline-block;font-size:11px;font-weight:700;
  color:#6b2f7a;background:rgba(160,90,180,.16);border:1px solid rgba(160,90,180,.42);
  border-radius:999px;padding:1px 9px;overflow-wrap:anywhere}
/* 卡片輪廓：**只加左邊那道邊**，不要整張換底色 —— 選單的卡片底色同時扛著
   「已完成／鎖住」的 filter，換底色會讓灰階化之後的魔王關看起來像壞掉。 */
.srg-level-btn.srg-boss-lv{border-color:rgba(160,90,180,.55);
  box-shadow:inset 3px 0 0 rgba(160,90,180,.6),inset 0 1px 0 rgba(255,255,255,.6),
    0 4px 12px -8px rgba(var(--mh-ink-rgb,43,58,74),.25)}
.srg-level-btn.srg-boss-lv:hover:not(:disabled){box-shadow:inset 3px 0 0 rgba(160,90,180,.6),
  inset 0 1px 0 rgba(255,255,255,.6),0 8px 20px -8px rgba(var(--mh-ink-rgb,43,58,74),.35)}
.srg-level-btn .srg-done-flag{margin-top:6px;font-size:11px;font-weight:700;color:var(--srg-success)}
.srg-level-btn .srg-lock-flag{margin-top:6px;font-size:11px;font-weight:700;color:#b06a6a}
.srg-level-btn.srg-locked{filter:grayscale(.4)}
/* 玩法還沒實作的關卡。用**琥珀色**而不是鎖頭的紅褐色：兩者的意思不一樣——
   鎖頭是「你還沒資格」（打完上一關就開），這個是「我們還沒做好」（等更新）。
   同色的話玩家會一直去打前一關，想解一個解不開的鎖。 */
.srg-level-btn .srg-soon-flag{margin-top:6px;font-size:11px;font-weight:700;color:#8a6100}
.srg-level-btn.srg-soon{filter:grayscale(.55);opacity:.85}
/* 方案鎖：**第三種顏色**，理由同上一段。
   這一個既不會因為打完上一關而開，也不會因為等更新而開——只有升級方案才會，
   所以要和另外兩種一眼分得出來，否則玩家會一直去打前一關想解一個解不開的鎖。 */
.srg-level-btn .srg-plan-flag{margin-top:6px;font-size:11px;font-weight:700;color:#5a5aa0}
.srg-level-btn.srg-outplan{filter:grayscale(.5);opacity:.9}
/* （v2.36.0 移除 `.srg-order-hint` —— 計分列與樂譜之間那一列作答提示。
   它講的「作答方式：…」進關卡片已經講過而且是玩家親手選的，
   「由左至右依序」所有關卡都一樣，「螢幕較小」在關卡卡片上有 📱 徽章。
   省下來的一整列還給樂譜。） */
.srg-mode-row{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0 4px}
.srg-mode-row button{padding:8px 14px;border-radius:12px;border:1px solid var(--srg-border);
  background:rgba(var(--mh-surface-hi-rgb,255,251,240),.9);cursor:pointer;font-family:inherit;color:var(--srg-navy);font-weight:600;font-size:13px;transition:all .15s}
.srg-mode-row button:hover{background:#fff}
.srg-mode-row button.active{background:var(--srg-navy);color:var(--srg-cream);border-color:var(--srg-navy)}
/* 遊戲畫面的頁首：兩列（名稱＋按鈕／數據），不再讓元素各自換行。
   手機直立時垂直空間非常吃緊，每多一列就少一列給樂譜。 */
.srg-header{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.srg-topbar{display:flex;align-items:center;gap:10px;padding:8px 14px}
.srg-topbar .srg-title{flex:1;min-width:0;font-size:16px;margin:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 題目類型，接在關卡名稱後面（「山度的進攻　節奏練習」）。
   **一定要比關卡名稱弱**：這一列的主詞是關卡名，型別只是註記；同樣粗細
   同樣大小的話，兩段中文會讀成一個很長的關卡名。
   ellipsis 由 .srg-title 統一處理，所以這裡不再自己截斷 —— 兩層各截一次
   會在窄畫面上先把型別截成半個字，比整段不見更難讀。 */
.srg-topbar .srg-mode-tag{margin-left:10px;font-size:12px;font-weight:600;
  color:var(--srg-slate);letter-spacing:.02em}
.srg-topbar-btns{display:flex;gap:6px;flex-shrink:0}
.srg-hud{padding:8px 14px}
/* **一定要排成一行**：換行時 flex 會讓每個 span 內部自己斷成「題 / 1/10」兩截，
   看起來像標題列和數值列各一行（實機截圖就是這樣）。 */
.srg-stats{display:flex;align-items:center;gap:12px;font-size:14px;flex-wrap:nowrap}
.srg-stats span{white-space:nowrap}
.srg-stats span b{color:var(--srg-ochre);font-size:16px}
/* 計時列吃掉剩下的寬度：它是唯一可以伸縮的元素，其餘都是不能斷的數字。 */
.srg-stat-time{display:flex;align-items:center;flex:1 1 auto;min-width:0}
.srg-stat-time .srg-timer{flex:1 1 auto;min-width:28px;width:auto}
/* 多音題的「已答 2/3」（v2.36.0 從被刪掉的提示列搬進計分列）。
   做成小藥丸把它與前面那幾格分開：這一列全是中文＋數字、字距又密，
   只靠 gap 會讀成「…12分已答 2/3」。`margin-left:auto` 讓它靠右靠齊 ——
   它是這一題的進度，與左邊那幾個整關累計的數字不是同一類。
   單音題整格 `display:none`（見 updateAnswerProgress）：計分列是 nowrap，
   多一格就少一格寬度，而「已答 0/1」什麼也沒告訴玩家。 */
.srg-stat-prog{color:var(--srg-slate);font-size:12px;white-space:nowrap;margin-left:auto;
  background:rgba(255,255,255,.75);border-radius:999px;padding:2px 9px}
.srg-stat-prog b{color:var(--srg-ochre);font-size:15px}
/* ================= 遊戲畫面撐滿一個螢幕 =================
 * 目標是沉浸感：樂譜與鍵盤要**長大**去佔滿螢幕，而不是全部擠在上方、
 * 下面留一大片空白。只有遊戲中（.srg-playing，由 renderGame 掛上）才套；
 * 選單與結算是隨內容長高的一般頁面。
 *
 * svh（small viewport height）是行動瀏覽器網址列展開時的高度——用 vh 的話
 * 網址列一收起畫面就會比視窗高，多出一段捲動。舊瀏覽器退回 vh。
 */
/* min + max 一起給（等同 height，但意圖更清楚）：**只有 min-height 的話 flex
   永遠不會把子項壓縮**——內容比一個螢幕高時 root 就跟著長高，樂譜的
   max-height:100% 也就永遠不會生效（實測 1280×800 的筆電被撐到 831px）。 */
.srg-root.srg-playing{min-height:calc(100vh - 24px);min-height:calc(100svh - 24px);
  max-height:calc(100vh - 24px);max-height:calc(100svh - 24px);
  display:flex;flex-direction:column}
/* 扣 24px：scrollToRoot 會把遊戲捲到離視窗頂端 scroll-margin-top(16px) 的位置，
   不扣的話最下面那截鍵盤會剛好被推出畫面。 */
.srg-root.srg-playing .srg-content{flex:1 1 auto;display:flex;flex-direction:column;min-height:0}
/* 樂譜吃掉所有剩下的高度，並在其中置中；作答面板維持自己的高度。 */
.srg-root.srg-playing .srg-staff-wrap{flex:1 1 auto;min-height:0;justify-content:center}
.srg-root.srg-playing .srg-answer-pad{flex:0 0 auto}
/* 沒有五線譜的玩法（聽音、常識）用 .srg-mode-body 佔住樂譜的位置：同樣吃掉
   剩下的高度、同樣垂直置中。少了這一條，題目文字會貼在計分列下方，
   底下留一整片空白——那正是 .srg-playing 想消掉的東西。
   overflow-y:auto 是保險：選項很長的常識題不該把作答面板擠出畫面。 */
.srg-root.srg-playing .srg-mode-body{flex:1 1 auto;min-height:0;overflow-y:auto;
  display:flex;flex-direction:column;justify-content:center}
/* 畫布也要是 flex 項目且 min-height:0，高度才是**確定值**——不然底下的
   `max-height:100%` 會因為父層高度是 auto 而算成 none，樂譜就長不封頂
   （實測 1280×800 的筆電上整個遊戲被撐到 831px，比視窗還高）。 */
.srg-root.srg-playing .srg-staff-canvas{flex:1 1 auto;min-height:0;position:relative}
/* 樂譜容器用絕對定位貼滿畫布，**不是** height:100%：flex 算出來的高度拿去給
   百分比高度解析並不可靠（實測畫布 289px、容器卻仍是內容高的 343px，樂譜
   直接溢出卡片壓到鍵盤上）。inset:0 的高度一定是確定值，svg 的 max-height
   才有東西可依。 */
.srg-root.srg-playing .srg-staff-svg{position:absolute;inset:0;
  display:flex;align-items:center;justify-content:center}
/* 樂譜撐滿卡片寬度（該放大就放大）；高度受限時 preserveAspectRatio 會維持比例，
   特效層靠 svgFit() 把縮放與置中留白一起換算回來。 */
/* width:100% 撐滿、height:auto 保持比例、max-height 太高時把整張譜等比縮回來
   （替換元素撞到 max-height 時，寬度會依內在比例一起縮，所以不會變形）。 */
.srg-root.srg-playing .srg-staff-svg svg{width:100%;height:auto;max-height:100%;max-width:100%}

/* ---- 大螢幕：不能只會「撐滿」 ----
 * 平板／桌機上單純撐滿會失控：1920px 的螢幕實測整張譜被放大到 **8.5 倍**
 * （1857×1138px 的五線譜），而且樂譜卡把畫面撐到 1685px、比視窗還高。
 * 兩道上限：①遊戲區本身置中並限寬；②樂譜再單獨限寬，維持可讀的音符大小。
 */
/* 節奏題的旋律本來就需要整條寬度（版面是照容器寬度算的），不套樂譜上限。 */
.srg-root.srg-playing:not(.srg-rhythm) .srg-staff-svg{max-width:min(100%,560px);margin-left:auto;margin-right:auto}

/* 樂譜區。卡片高度＝樂譜本身的高度（畫布已依關卡音域裁到剛好，見 staffBoxFor）。 */
/* position:relative 是給 .srg-fx-banner-in 的定位錨點用的（長樂譜時鼓勵詞
   會掛在這一層，見該規則）。裡面沒有其他 absolute 子層以它為錨。 */
.srg-staff-wrap{background:#fffdf5;border-radius:12px;padding:8px 10px;text-align:center;
  position:relative;display:flex;flex-direction:column;align-items:stretch}
/* **不要 overflow:auto**：SVG 已經有 max-width:100% 保證不會比容器寬，而畫布
   一旦裁到貼齊樂譜，overflow 就會把音符特效與加分浮字（它們刻意畫在音符上方）
   切掉。overflow-x:auto 還會連帶把 overflow-y 也變成 auto。 */
.srg-staff-canvas{min-width:0;position:relative}
/* 判讀區：樂譜卡片**裡面**、譜的正下方。成績那一行（「命中 6/7，準確 5，
   多敲 6」）與顏色圖例都住在這裡（v2.36.0）。
   在卡片裡是為了那層不透明的紙色底 —— 這兩樣以前在 `#srg-pad`，而 pad 的底
   就是關卡的背景圖，一排 10px 的小色塊印在畫上就分不出綠橘，
   而分辨顏色正是圖例唯一的用途。
   `flex:0 0 auto` 讓它不參與伸縮：要讓步的是樂譜畫布，不是判讀說明
   （畫布另有 min-height 地板擋著）。
   空的時候整塊不佔高度 —— 還沒演奏的關卡樂譜仍然拿得到整張卡片。 */
.srg-staff-report{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;
  gap:4px;margin-top:6px;text-align:center}
/* `:empty` 不夠用：paintStaffReport 一律會建一個（可能是空的）`.srg-rh-msg`
   節點給 updateRhythmMsg 用，所以容器永遠有子元素。由 JS 掛 class。 */
.srg-staff-report:empty,.srg-staff-report.is-empty{display:none;margin-top:0}
.srg-staff-report .srg-rh-msg{flex:0 0 auto;font-size:13px;line-height:1.45;color:var(--srg-navy)}
.srg-staff-report .srg-rh-msg:empty{display:none}
/* （v2.47.0：`.srg-rh-legend` 那兩條沒有了 —— 顏色圖例整排拿掉，判定改成
   直接寫在音符下面，見下方 `.srg-verdict-mark`。） */
/* 窄畫面把整張譜等比縮小以免橫向捲動——五線譜捲起來就沒辦法一眼看完整題。
   noteBoxes 存的是未縮放的座標，所以特效疊層要乘上 svgScaleK()（見 game.js）。 */
.srg-staff-svg svg{max-width:100%;height:auto}

/* 聽音模仿／節奏模仿：判定之前音符與休止符全部透明（見 game.js 的 scoreHidden）。
 *
 * **只藏音符，不藏譜。** 五線、譜號、拍號、調號、小節線都留著——那是玩家判斷
 * 「現在走到第幾拍」的框架，游標在上面移動才有意義。
 *
 * 用 opacity 不用 display:none：位置照樣佔著，顯現的那一刻譜不會整個跳動；
 * 而且 VexFlow 的幾何（noteBoxes、游標座標表）本來就是照畫出來的東西算的。
 *
 * **這是白名單不是黑名單，而且必須是。** VexFlow 把每一種東西都畫成 <svg> 的
 * 直接子元素（見 SVGContext.openGroup）：符頭在 `.vf-stavenote` 裡，但
 * **連桿組的符桿是獨立的 `.vf-stem`、連桿是 `.vf-beam`**，兩者都在音符群組外面。
 * 實測只藏 `.vf-stavenote` 的話，12 根符桿有 6 根還亮著、外加三條連桿
 * ——節奏就這樣整個洩漏出去了（而且看起來只是「譜有點怪」）。
 * 連音符號、圓滑線、表情記號日後加進來也是同樣的情形，一個一個補一定會漏。
 *
 * 單線節奏譜（modes/rhythm.js）的小節線是自己 `ctx.fillRect` 畫的，
 * 也就是沒有 class 的直接子 <rect>，所以要一併放行。 */
.srg-staff-svg.srg-notes-hidden svg > *{opacity:0}
.srg-staff-svg.srg-notes-hidden svg > rect,
.srg-staff-svg.srg-notes-hidden svg > .vf-stave,
.srg-staff-svg.srg-notes-hidden svg > .vf-stavebarline,
.srg-staff-svg.srg-notes-hidden svg > .vf-clef,
.srg-staff-svg.srg-notes-hidden svg > .vf-timesignature,
.srg-staff-svg.srg-notes-hidden svg > .vf-keysignature,
.srg-staff-svg.srg-notes-hidden svg > .srg-cursor{opacity:1}

.srg-answer-pad{margin-top:12px}
.srg-letters{display:grid;grid-template-columns:repeat(7,1fr);gap:8px}

/* ================= 魔法光影的顏色 =================
 * 鍵盤與作答鈕的光暈只讀這三個變數，動畫本身不認得屬性叫什麼名字。
 * 現在放的是**預設值**（羊皮紙金 / 夜紫）。角色系統上線後，只要把
 * .srg-el-{屬性} 也加到 .srg-root 上（applyElementClass 目前只加在特效層
 * #srg-fx），整組鍵盤與按鈕就會跟著角色的魔法屬性換色，不必動任何動畫。
 */
.srg-root{--srg-glow:#ffe088;--srg-glow-soft:#fff6d8;--srg-glow-dark:#8a6cb0}
.srg-root.srg-el-wind {--srg-glow:#8fd3d8;--srg-glow-soft:#e2f7f5;--srg-glow-dark:#4d8f96}
.srg-root.srg-el-wood {--srg-glow:#9ed37a;--srg-glow-soft:#e8f6d9;--srg-glow-dark:#4a7a3a}
.srg-root.srg-el-light{--srg-glow:#ffe088;--srg-glow-soft:#fff6d8;--srg-glow-dark:#a98a2e}
.srg-root.srg-el-earth{--srg-glow:#d9a86a;--srg-glow-soft:#f3e2c9;--srg-glow-dark:#7d5a34}
.srg-root.srg-el-metal{--srg-glow:#c3ced9;--srg-glow-soft:#eef3f8;--srg-glow-dark:#5f7183}
.srg-root.srg-el-water{--srg-glow:#7fc4ea;--srg-glow-soft:#dceffa;--srg-glow-dark:#3a7ba3}
.srg-root.srg-el-fire {--srg-glow:#ffa96b;--srg-glow-soft:#ffe0c6;--srg-glow-dark:#a34a22}

/* 音名／唱名按鈕：與琴鍵同一套立體感與光暈。 */
.srg-note-btn{position:relative;padding:14px 0;font-size:20px;font-weight:700;color:var(--srg-navy);
  border:1px solid var(--srg-ochre);border-radius:12px;cursor:pointer;
  background:linear-gradient(180deg,#fffdf6 0%,#fdf6e6 55%,#f4ead2 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),0 3px 0 rgba(var(--mh-gold-rgb,201,168,106),.45),
    0 6px 12px -6px rgba(var(--mh-ink-rgb,43,58,74),.35);
  transition:transform .1s ease-out,box-shadow .1s ease-out,filter .12s}
.srg-note-btn:hover{filter:brightness(1.03);transform:translateY(-1px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),0 4px 0 rgba(var(--mh-gold-rgb,201,168,106),.45),
    0 9px 16px -7px rgba(var(--mh-ink-rgb,43,58,74),.4)}
.srg-note-btn:active{transform:translateY(2px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7),0 1px 0 rgba(var(--mh-gold-rgb,201,168,106),.45),
    0 3px 6px -4px rgba(var(--mh-ink-rgb,43,58,74),.35)}
.srg-note-btn.correct{background:linear-gradient(180deg,#a9dcaa 0%,#8bc78e 100%);color:#fff;border-color:#6ea872}
.srg-note-btn.wrong{background:linear-gradient(180deg,#eda3a3 0%,#e28787 100%);color:#fff;border-color:#c06d6d}

/* ================= 鋼琴鍵盤 =================
 * 預設一個八度 C–C（8 白鍵）；音域跨過中央 C 而裝不進任何一個 C–C 八度時
 * （中音譜／大譜表的 f3–g4）改成「以 C 為正中心」的 9 鍵。哪一種由
 * game.js 的 pianoWindow() 決定，並把白鍵數寫進 --srg-keys。
 * 鍵面不放任何文字，只留鍵形。
 *
 * 寬度用 --srg-keys 換算而不是 100%：8 鍵鋪滿整個作答區的話一個白鍵會有
 * 100px 寬，看起來像玩具。上限 58px/鍵、下限 34px/鍵（再窄就按不準，
 * 改成橫向捲動，drawPad 會先捲到正中間）。
 */
/* padding 是給光暈留的：overflow-x:auto 會連帶把 overflow-y 變成 auto，
   最外側琴鍵的光暈沒有這圈餘裕就會被切掉。 */
.srg-piano-wrap{overflow-x:auto;padding:14px 10px 20px}
/* min() 的用意：**寧可把琴鍵縮窄，也不要橫向捲動**。
   鍵盤捲起來就看不到全部的鍵，而且「差幾 px 就溢出」的情形非常容易發生——
   實機上 Firefox 的版面寬度是 360（Chrome 是 393），可用寬度只剩 260px，
   跟 8×32=256 只差 4px，稍有出入整排鍵就開始捲動並被切掉。 */
/* 鍵盤高度跟著螢幕長：手機直立時琴鍵長一點才好按，也把畫面填滿。
   **vh 那一行不能省。** 不支援 svh 的瀏覽器（Safari<15.4／Chrome<108）會把
   整條 clamp() 判成無效值而整條丟掉，而 .srg-white/.srg-black 是
   position:absolute + top:0/bottom:0 —— 高度沒了就是整排琴鍵消失，
   不是「稍微矮一點」。同一個理由適用下面兩處。 */
.srg-piano{position:relative;height:clamp(160px,30vh,300px);height:clamp(160px,30svh,300px);user-select:none;touch-action:manipulation;margin:0 auto;
  min-width:min(100%, calc(var(--srg-keys,8) * 34px));
  /* 上限 76px/鍵：實體白鍵約 23mm，桌機螢幕上 76px 差不多就是那個尺寸。
     原本 58px 在 1280 以上的螢幕會顯得像玩具。 */
  max-width:calc(var(--srg-keys,8) * 76px)}
.srg-white{position:absolute;top:0;bottom:0;cursor:pointer;
  /* 米白：越往下越沉，鍵尾收在羊皮紙的奶油色裡 */
  background:linear-gradient(180deg,#fffdf6 0%,#faf4e4 58%,#f0e6cd 100%);
  border:1px solid #dbceac;border-top:none;border-radius:3px 3px 10px 10px;
  box-shadow:
    inset 1px 0 0 rgba(255,255,255,.95),          /* 左緣受光 */
    inset -2px 0 3px -2px rgba(var(--mh-ink-rgb,43,58,74),.3),      /* 右緣轉角的暗面 */
    inset 0 -12px 14px -12px rgba(var(--mh-ink-rgb,43,58,74),.35),  /* 鍵尾的內陰影 */
    0 4px 0 #ded0ad,                              /* 鍵身厚度 */
    0 8px 12px -6px rgba(var(--mh-ink-rgb,43,58,74),.38);
  transition:transform .08s ease-out,box-shadow .08s ease-out,filter .12s}
.srg-black{position:absolute;top:0;height:62%;cursor:pointer;z-index:2;
  background:linear-gradient(180deg,#4c5c70 0%,#2b3a4a 45%,#1a2632 100%);
  border-radius:2px 2px 8px 8px;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.3),
    inset -2px 0 3px -2px rgba(0,0,0,.5),
    0 4px 0 #121b24,
    0 8px 12px -5px rgba(19,28,37,.6);
  transition:transform .08s ease-out,box-shadow .08s ease-out,filter .12s}
/* 按下：鍵身壓下去，厚度跟著變薄。 */
.srg-white:active{transform:translateY(3px);filter:brightness(1.04);
  box-shadow:inset 1px 0 0 rgba(255,255,255,.95),inset -2px 0 3px -2px rgba(var(--mh-ink-rgb,43,58,74),.3),
    inset 0 -12px 14px -12px rgba(var(--mh-ink-rgb,43,58,74),.35),0 1px 0 #ded0ad,0 3px 6px -4px rgba(var(--mh-ink-rgb,43,58,74),.35)}
.srg-black:active{transform:translateY(2px);filter:brightness(1.15);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3),inset -2px 0 3px -2px rgba(0,0,0,.5),
    0 2px 0 #121b24,0 4px 7px -4px rgba(19,28,37,.6)}
/* 答對／答錯：保留立體感，只換鍵面顏色。 */
.srg-white.correct{background:linear-gradient(180deg,#c2e8c0 0%,#8bc78e 100%);border-color:#77ab7a}
.srg-white.wrong{background:linear-gradient(180deg,#f0b9b9 0%,#e28787 100%);border-color:#c68686}
.srg-black.correct{background:linear-gradient(180deg,#5aa862 0%,#2f7a38 100%)}
.srg-black.wrong{background:linear-gradient(180deg,#bf5a5a 0%,#8f2626 100%)}

/* ---- 魔法光暈 ----
 * 光暈畫在 ::after 上而不是琴鍵本身的 box-shadow 上：琴鍵的 box-shadow 已經
 * 扛著立體感（厚度、內陰影），拿去做動畫會把立體感一起動掉。
 * .srg-lit 由 game.js 的 bindKeyFlash 在 pointerdown 時掛上、480ms 後拿掉——
 * 只靠 :active 的話，觸控上手指一離開光暈就沒了，根本來不及看見。
 */
.srg-white::after,.srg-black::after,.srg-note-btn::after{content:'';position:absolute;inset:0;
  border-radius:inherit;opacity:0;pointer-events:none}
/* 琴鍵是**貼在一起**的，所以光暈的主體必須畫在鍵面裡：純外光暈的左右兩側
   會被相鄰的琴鍵蓋掉（後畫的兄弟節點蓋前面的），只有上下緣露得出來。
   所以做成「從指尖（鍵尾）往上漫開」的漸層，外光暈只負責上下兩端。 */
.srg-white.srg-lit::after{
  background:radial-gradient(120% 78% at 50% 100%,
    var(--srg-glow) 0%,var(--srg-glow-soft) 38%,transparent 74%);
  animation:srgKeyGlow .48s ease-out}
.srg-black.srg-lit::after{
  background:radial-gradient(130% 72% at 50% 100%,
    var(--srg-glow) 0%,var(--srg-glow-dark) 42%,transparent 78%);
  animation:srgKeyGlowDark .48s ease-out}
.srg-note-btn.srg-lit::after{
  background:radial-gradient(120% 90% at 50% 100%,var(--srg-glow-soft) 0%,transparent 72%);
  animation:srgKeyGlow .48s ease-out}
.srg-white.srg-lit,.srg-note-btn.srg-lit{filter:brightness(1.06)}
.srg-black.srg-lit{filter:brightness(1.25)}
@keyframes srgKeyGlow{
  0%{opacity:.35;box-shadow:0 0 6px 1px var(--srg-glow)}
  35%{opacity:.92;box-shadow:0 6px 18px 4px var(--srg-glow),0 -4px 14px 2px var(--srg-glow-soft)}
  100%{opacity:0;box-shadow:0 0 8px 1px var(--srg-glow)}
}
@keyframes srgKeyGlowDark{
  0%{opacity:.4;box-shadow:0 0 6px 1px var(--srg-glow-dark)}
  35%{opacity:.95;box-shadow:0 6px 18px 4px var(--srg-glow-dark),0 -4px 14px 2px var(--srg-glow)}
  100%{opacity:0;box-shadow:0 0 8px 1px var(--srg-glow-dark)}
}
/* 答對的鍵持續亮著（固定成功色，不跟屬性換色——答對/答錯必須一眼分得出來，
   和 .srg-fx-ice 是同一個理由）。 */
.srg-white.correct::after,.srg-black.correct::after,.srg-note-btn.correct::after{
  opacity:1;box-shadow:0 0 12px 2px rgba(79,164,106,.75),0 0 22px 8px rgba(79,164,106,.35)}
/* 麥克風作答面板 */
.srg-mic{background:rgba(var(--mh-surface-hi-rgb,255,251,240),.92);border:1px solid var(--srg-border);border-radius:16px;padding:14px 18px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 4px 14px -10px rgba(var(--mh-ink-rgb,43,58,74),.35)}
.srg-mic-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;flex-wrap:wrap}
.srg-mic-title{font-weight:700;color:var(--srg-navy);font-size:15px}
.srg-mic-state{font-size:12px;color:var(--srg-slate)}
.srg-mic-state.err{color:#b34747;font-weight:600}
/* 收音閘關著（音效播放中）。整個面板降到半透明，玩家一眼就知道現在講話沒有用。 */
.srg-mic.gated{opacity:.55}
.srg-mic.gated .srg-mic-gauge,.srg-mic.gated .srg-mic-vol{filter:grayscale(1)}
.srg-mic-read{display:flex;align-items:baseline;justify-content:center;gap:12px;margin:6px 0 2px;min-height:44px}
.srg-mic-note{font-size:38px;font-weight:700;line-height:1;color:var(--srg-navy);font-family:"Fraunces","Noto Serif TC",Georgia,serif}
.srg-mic-cents{font-size:15px;color:var(--srg-slate);font-variant-numeric:tabular-nums;min-width:56px}
.srg-mic-gauge{position:relative;height:16px;border-radius:8px;background:rgba(var(--mh-ink-rgb,43,58,74),.1);overflow:hidden}
.srg-mic-zone{position:absolute;top:0;bottom:0;background:rgba(79,164,106,.28)}
/* 音不準的外圈。比綠帶淡且顏色不同，兩層疊起來就是一個靶心。 */
.srg-mic-zone.off{background:rgba(229,149,0,.22)}
.srg-mic-center{position:absolute;top:0;bottom:0;left:50%;width:2px;margin-left:-1px;background:rgba(var(--mh-ink-rgb,43,58,74),.45)}
.srg-mic-needle{position:absolute;top:-2px;bottom:-2px;left:50%;width:4px;margin-left:-2px;border-radius:2px;
  background:var(--srg-ochre);transition:left .06s linear}
.srg-mic-needle.ok{background:var(--srg-success)}
.srg-mic-needle.off{background:#e59500}
.srg-mic-vol{height:5px;border-radius:3px;background:rgba(var(--mh-ink-rgb,43,58,74),.1);margin-top:8px;overflow:hidden}
.srg-mic-vol i{display:block;height:100%;width:0;background:var(--srg-slate);transition:width .08s linear}
.srg-mic-rule{margin-top:8px;font-size:12px;color:var(--srg-slate);text-align:center}
.srg-mic-ans{margin-top:10px;padding:8px 12px;border-radius:10px;font-size:14px;font-weight:600;
  display:flex;gap:14px;flex-wrap:wrap;justify-content:center}
.srg-mic-ans.correct{background:rgba(79,164,106,.18);color:#2f6b45}
.srg-mic-ans.wrong{background:rgba(226,135,135,.22);color:#8a2f2f}
/* 音不準的那一行自己換底色：整塊仍是「答對」的綠底，這一句是綠底上的提醒，
   不能跟著綠——否則看起來像在誇獎。flex-basis 100% 讓它獨占一行。 */
.srg-mic-ans-off{flex:1 0 100%;text-align:center;font-weight:600;
  padding:6px 10px;border-radius:8px;background:rgba(229,149,0,.18);color:#8a5a00}
.srg-mic-btns{margin-top:12px;display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
.srg-mic-warn{margin-top:8px;padding:8px 12px;border-radius:10px;background:rgba(226,135,135,.18);
  border:1px solid rgba(179,71,71,.35);color:#8a2f2f;font-size:12px;line-height:1.6;text-align:left}
.srg-feedback{display:flex;align-items:center;justify-content:center;pointer-events:none}
.srg-feedback img{width:140px;height:140px;object-fit:contain}
.srg-btn{padding:8px 16px;border:1px solid var(--srg-ochre);border-radius:10px;cursor:pointer;font-weight:600;
  background:linear-gradient(180deg,#fffdf6 0%,#fffbf0 55%,#f6edd8 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),0 2px 0 rgba(var(--mh-gold-rgb,201,168,106),.4),
    0 5px 10px -6px rgba(var(--mh-ink-rgb,43,58,74),.35);
  transition:transform .1s ease-out,box-shadow .12s ease-out,filter .12s}
.srg-btn:hover{filter:brightness(1.03)}
.srg-btn:active{transform:translateY(2px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7),0 0 12px 2px var(--srg-glow),
    0 2px 5px -3px rgba(var(--mh-ink-rgb,43,58,74),.35)}
.srg-btn.primary{background:linear-gradient(180deg,#d8bc85 0%,#c9a86a 100%);color:#fff;border-color:#b7955a}
/* 背景音樂開關（遊戲畫面右上） */
.srg-bgm-btn{padding:8px 12px;font-size:18px;line-height:1}
.srg-bgm-btn.off{opacity:.55}
.srg-bgm-btn:disabled{cursor:not-allowed}

/* 節拍器的視覺脈動。**麥克風作答時節拍器不出聲** —— 它的每一聲都正好落在
   玩家該演奏的那一刻，收音閘會連玩家自己的起音一起吃掉（見 game.js metroOn
   的說明）。所以這顆鈕的閃爍是麥克風模式下唯一的拍子提示，強拍要看得出來。
   動畫由 JS 移除／再加 class 觸發，時間要短才跟得上快板。 */
@keyframes srg-tick{from{transform:scale(1.28);background:var(--srg-glow-soft,#f3e3bb)}to{transform:scale(1)}}
@keyframes srg-tick-a{from{transform:scale(1.45);background:var(--srg-glow,#e0b76a)}to{transform:scale(1)}}
#srg-metro-btn.srg-tick{animation:srg-tick .16s ease-out}
#srg-metro-btn.srg-tick-a{animation:srg-tick-a .2s ease-out}
/* 減少動態時**不能整個關掉**（那會讓麥克風模式完全沒有拍子提示），
   只把縮放拿掉、留下顏色閃爍。同 v1.14.0 倒數脈動的處理。 */
@media (prefers-reduced-motion:reduce){
  @keyframes srg-tick{from{background:var(--srg-glow-soft,#f3e3bb)}to{background:transparent}}
  @keyframes srg-tick-a{from{background:var(--srg-glow,#e0b76a)}to{background:transparent}}
}
/* 選單（關卡選擇頁）的那一顆：靠右對齊、與標題同一列。
   margin-left:auto 而不是絕對定位——hero 是 flex，絕對定位在窄畫面會壓到標題上。 */
.srg-menu-bgm-btn{margin-left:auto;align-self:flex-start;flex-shrink:0}
/* 全螢幕開關。尺寸與喇叭鈕對齊（它們是同一列的一組）。
   **只有第一顆吃 margin-left:auto**：兩顆都吃的話中間會被撐開成一大段空白，
   所以 .srg-menu-fs-btn 只在**沒有**喇叭鈕（關卡沒設背景音樂）時才靠右。 */
.srg-fs-btn{padding:8px 12px;font-size:18px;line-height:1}
.srg-menu-fs-btn{align-self:flex-start;flex-shrink:0}
.srg-menu-fs-btn:first-of-type{margin-left:auto}
/* 已在全螢幕：按下去是「離開」。用實心底表達 aria-pressed=true，
   不換圖示（見 game.js updateFsBtn 的說明）。 */
.srg-fs-btn.on{background:var(--mh-honey,#fed65b);border-color:#b7955a}
/* ===== 關卡開始提示畫面：一卷展開的羊皮紙 =====
   卡片的底是一段卷軸展開的影片（ui/intro-scroll.js），說明文字排在紙面上。

   **9:16 是硬約束，不是版面偏好。** 上下兩根軸就貼在影片的最上與最下緣，
   `object-fit:cover` 只要裁掉 8% 就把它們吃光，卷軸的辨識度歸零。所以盒子
   恆為 720:1280，寬度不夠時整張縮小，絕不裁切。
   max() 的 320px 是地板：視窗太矮時寧可讓頁面捲動，也不要把卡片縮成一條。 */
.srg-intro{
  width:min(520px,100%,max(320px,calc((100svh - 40px) * 720 / 1280)));
  aspect-ratio:720 / 1280;
  margin:20px auto;position:relative;overflow:hidden;border-radius:18px;
  /* 卡片原本的半透明米色底與 backdrop-filter 會把影片糊掉，整組退掉。
     底色取影片自己的暗褐外框，寬度被地板夾住而留白時看不出接縫。 */
  background:#2a2018;border:0;padding:0;backdrop-filter:none;
  box-shadow:0 18px 44px -20px rgba(0,0,0,.55)}
.srg-intro-scroll{position:absolute;inset:0;z-index:0;pointer-events:none}
.srg-intro-vid,.srg-intro-still{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* 羊皮紙的可寫字區。
   **上緣是用對比度定的，不是用亮度門檻。** 上軸底下有一條陰影，往下量
   （影片最後一幀／poster 兩份都量過，兩者每一列相差不到 0.2）：
     20.0% → 3.1:1   21.0% → 4.5:1   22.5% → 6.2:1   23.8% → 7.0:1
   取 21%：第一件東西是 24px 粗體的關卡名稱，那是 WCAG 的「大型文字」
   （門檻 3:1），而規格列從 24% 起才開始，落在 7:1 以上。
   舊值 25% 是先前用亮度門檻粗抓的，白白空掉了一行標題的高度。
   左右 9%／下 13% 是暗邊與下軸之外。 */
.srg-intro-body{position:absolute;inset:21% 9% 13%;z-index:1;
  display:flex;flex-direction:column;text-align:center;
  /* 攤平之前 pointer-events 一定要關掉：**透明的元素照樣收得到點擊**，
     不擋的話玩家會在完全看不見按鈕的情況下按到「開始遊戲」。 */
  opacity:0;pointer-events:none;transition:opacity .45s ease}
.srg-intro.is-open .srg-intro-body{opacity:1;pointer-events:auto}
/* **只有說明會捲，按鈕釘在紙腳。** 整塊一起捲的話，老師填了長提示詞
   （欄位上限 500 字）「開始遊戲」就會被推到捲動範圍外 —— 實測 360×640 下
   說明高 668px 而紙面只有 372px，按鈕落在視窗外 225px 處。
   min-height:0 不能省：flex 項目的預設 min-height 是 auto，不歸零的話
   它會被內容撐開而永遠不出現捲軸（按鈕照樣被推出去）。 */
.srg-intro-pane{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain}
/* 說明比紙面高的時候才掛漸層遮罩（class 由 game.js 量完才加）。
   常態就掛的話第一行與最後一行永遠是半透明的，那看起來像字沒印好。 */
.srg-intro-pane.is-scroll{
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 12px,#000 calc(100% - 12px),transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 12px,#000 calc(100% - 12px),transparent 100%)}
/* 既沒有影片也沒有底圖（老師換了自訂影片而那支載不出來）：退回原本那張
   不透明的米色卡片。深褐色底上印深藍字等於一張讀不到的說明。 */
.srg-intro.is-bare{width:min(520px,100%);aspect-ratio:auto;height:auto;
  background:rgba(var(--mh-surface-rgb,244,234,210),.94);
  border:1px solid var(--srg-border);padding:16px 20px}
.srg-intro.is-bare .srg-intro-body{position:static;display:block;opacity:1;pointer-events:auto}
.srg-intro.is-bare .srg-intro-pane{overflow:visible;-webkit-mask-image:none;mask-image:none}
.srg-intro .srg-title{font-size:24px;margin-bottom:2px}
.srg-intro-rules{list-style:none;margin:6px 0 0;padding:0;text-align:left;display:inline-block}
.srg-intro-rules li{display:flex;align-items:flex-start;gap:8px;margin:8px 0;font-size:15px;color:var(--srg-navy);font-weight:600}
.srg-intro-ic{flex-shrink:0;font-size:18px;line-height:1.4}
.srg-intro-text{margin:10px 0 0;padding:9px 12px;border-radius:12px;background:rgba(var(--mh-gold-rgb,201,168,106),.22);
  border:1px solid var(--srg-border);color:var(--srg-navy);font-size:14px;line-height:1.6;white-space:pre-wrap;text-align:left}
.srg-intro-text-tag{display:block;font-weight:700;font-size:12px;color:#8a6316;margin-bottom:4px;white-space:normal}
.srg-intro-btns{margin-top:12px;display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.srg-intro-btns .srg-btn{padding:10px 20px;font-size:16px}
/* 進關卡片的規格列（題目類型／音域／作答方式／過關條件）。
   **標籤欄固定寬、內容欄靠左**：四列的內容長短差很多（音域是一小段、過關條件
   可能三行），不對齊的話讀起來像四張不相干的小卡。整塊 text-align:left 是刻意的
   —— .srg-intro 是置中的，規格是拿來讀的表格不是標語。 */
.srg-brief{margin:10px 0 0;text-align:left;border-top:1px solid rgba(var(--mh-ink-rgb,43,58,74),.22)}
.srg-brief-row{display:flex;gap:10px;align-items:flex-start;padding:7px 2px;
  border-bottom:1px solid rgba(var(--mh-ink-rgb,43,58,74),.16)}
/* 標籤欄的顏色不是 --srg-slate 了：那個淺灰是給米色卡片用的，
   印在羊皮紙上對比只剩三比一左右，四個標籤讀起來像沒印好。
   寬度 84→60px：標籤前面的 emoji 已經拿掉（見 game.js 的 briefRow），
   最長的「題目類型」四個字在 13px 下約 52px。省下的寬度還給內容欄。 */
.srg-brief-label{flex:0 0 60px;display:flex;align-items:center;font-size:13px;font-weight:700;
  color:var(--srg-navy);line-height:1.5}
.srg-brief-body{flex:1 1 auto;min-width:0;font-size:15px;font-weight:600;color:var(--srg-navy);line-height:1.55}
/* 關卡或玩法已經決定了作答面板時的那一句話。 */
.srg-brief-fixed{font-weight:700}
/* 補充說明（為什麼不能選、麥克風的容許偏差）。比內容小一級，看得出是註腳。 */
.srg-brief-note{margin-top:2px;font-size:12px;font-weight:600;color:#5d6b78;line-height:1.5}
/* 卡片裡的答題方式按鈕：這一列已經在表格的內容欄裡，不必再留上下外距。 */
.srg-brief-body .srg-mode-row{margin:0}
@media (max-width:600px){
  /* **這裡以前是 `flex-direction:column`**（讓內容欄拿回整個寬度）。
     卡片變成固定高的羊皮紙之後那一招反過來害事：上下堆疊讓每一列從約
     40px 長到 62px，四列就多吃掉 88px，而可寫字區只有 397px 高。
     改成把標籤欄縮窄、字級各降半級 —— 省的是同一段寬度，不必多要高度。 */
  .srg-brief-row{padding:6px 2px;gap:8px}
  .srg-brief-label{flex:0 0 52px;font-size:12px}
  .srg-brief-body{font-size:14px}
  .srg-intro .srg-title{font-size:20px}
  .srg-intro-rules li{font-size:14px;margin:6px 0}
  /* 作答方式那四顆改成**固定兩欄的格線**。
     flex-wrap 是照剩餘寬度斷的，於是每一種手機寬度斷在不同的地方：
     393px 實測是「音名／唱名／鋼琴鍵盤」＋孤零零一顆「麥克風」，288px 才剛好
     是 2+2。兩欄格線在每一種寬度上長得一樣，四顆也一樣大（比較好按）。
     行數沒有變多——這一列在 393px 以下本來就是兩排。 */
  .srg-brief-body .srg-mode-row{display:grid;grid-template-columns:1fr 1fr;gap:6px}
  .srg-brief-body .srg-mode-row button{padding:7px 6px;font-size:12px;text-align:center}
  /* 「開始遊戲」與「返回選單」要並排。
     **288px 不是假想的窄**：Android 把「顯示大小」調大之後，手機版 Firefox 的
     版面寬度就是 288 CSS px（實機回報）。那個寬度下兩顆鈕原本會折成兩排，
     把釘在紙腳的按鈕區從 43px 撐到 97px ——而紙面只有 320px，等於三成拿去
     放兩顆按鈕，說明被擠掉。
     用 `calc(50% - 5px)` 當基準寬（gap 是 10px）而不是 `nowrap`：正常情形穩穩
     並排，真的塞不下時（玩家把系統字級調得更大）仍然折得下去，不會滿出紙面。 */
  .srg-intro-btns .srg-btn{flex:1 1 calc(50% - 5px);min-width:0;padding:10px 8px;font-size:15px}
}
/* ===== 徽章 / 成就 / 稱號 ===== */
.srg-ach-sum-head{display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap}
.srg-ach-sum-head h3{font-size:20px;color:var(--srg-navy)}
.srg-ach-sum{display:flex;gap:14px;flex-wrap:wrap;margin:8px 0 4px;font-size:13px;color:var(--srg-slate);font-weight:600}
.srg-title-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:8px}
.srg-title-select{padding:6px 10px;border:1px solid var(--srg-border);border-radius:10px;
  background:rgba(var(--mh-surface-hi-rgb,255,251,240),.9);font-family:inherit;color:var(--srg-navy);max-width:100%;
  /* **16px 是 iOS 的下限，不是美感選擇**：小於它時 Safari 會在聚焦的瞬間
     把整頁放大，而且不會自己縮回來。體積用 padding 收，不要用字級收。 */
  font-size:16px;padding:5px 10px}
.srg-title-select:disabled{opacity:.6}
.srg-ach-near{margin-top:12px;padding-top:10px;border-top:1px dashed var(--srg-border)}
/* 同 .srg-menu-grid，而且 250 的地板更容易撞到。 */
.srg-ach-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(250px,100%),1fr));gap:10px}
.srg-ach-card{--srg-tier:#8a94a3;display:flex;gap:10px;align-items:flex-start;padding:10px 12px;
  border:1px solid var(--srg-border);border-left:4px solid var(--srg-tier);border-radius:14px;
  background:rgba(var(--mh-surface-hi-rgb,255,251,240),.72);opacity:.72}
.srg-ach-card.on{opacity:1;background:rgba(var(--mh-surface-hi-rgb,255,251,240),.96);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 4px 14px -10px rgba(var(--mh-ink-rgb,43,58,74),.4)}
/* 36 而不是 34：26px 的 emoji 字面實際佔 36px，34 會把左右各裁掉 1px。 */
.srg-ach-ic{font-size:26px;line-height:1.1;flex-shrink:0;width:36px;text-align:center}
.srg-ach-card:not(.on) .srg-ach-ic{filter:grayscale(1);opacity:.55}
.srg-ach-body{min-width:0;flex:1}
.srg-ach-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.srg-ach-name{font-weight:700;color:var(--srg-navy);font-size:15px}
.srg-ach-tier{font-size:10px;font-weight:700;letter-spacing:.06em;color:#fff;background:var(--srg-tier);
  border-radius:999px;padding:2px 8px;white-space:nowrap}
.srg-ach-desc{font-size:12px;color:var(--srg-slate);margin-top:2px;line-height:1.5}
.srg-ach-bar{height:6px;border-radius:3px;background:rgba(var(--mh-ink-rgb,43,58,74),.12);margin-top:6px;overflow:hidden}
.srg-ach-bar i{display:block;height:100%;background:var(--srg-tier);border-radius:3px}
.srg-ach-prog{font-size:11px;color:var(--srg-slate);margin-top:3px;font-variant-numeric:tabular-nums}
.srg-ach-new h3{font-size:19px;color:var(--srg-navy);margin-bottom:8px}
.srg-lb-title{display:inline-block;margin-left:6px;padding:1px 7px;border-radius:999px;font-size:11px;
  font-weight:700;color:#fff;background:var(--srg-tier,#8a94a3);vertical-align:middle;white-space:nowrap}
/* `.srg-lb-title`（上面那一條）是**稱號藥丸**，不是排行榜的版面 —— 它現在
   由 lbLedger() 接到平台的名冊列上，所以留著。
   本關榜自己的那一套（.srg-lb-wrap / .srg-lb-table / .srg-lb-me / .srg-lb-you）
   在 v2.58.0 隨著那張手拼的 <table> 一起刪掉：列的長相統一交給
   music-hub 的 .mh-lb-row，站上只有一種排行榜長相。 */
/* 成績送不出去時的警語（結算畫面的 #srg-next-box）。紅字是刻意的：
   它跟旁邊「下一關」那顆按鈕在同一塊，長得一樣就會被當成一般說明滑過去。 */
.srg-save-fail{color:#8a2f2a;font-weight:600;margin-bottom:8px}
/* 本關榜的標題。與選單那張卡同一種排法（圖示 ＋ 字）。 */
.srg-lb2-head{display:flex;align-items:center;gap:8px}
/* ===== 選單頂端的玩家資訊區 =====
   左立繪、右暱稱／稱號／等級／我的資訊。（.srg-name-input 隨玩家名稱輸入框
   一起移除，暱稱現在是帳號資料。）
   立繪那一格是 flex:0 0 auto 的固定寬：讓它跟著內容伸縮的話，換一張比例不同
   的立繪整張卡的左右分割就會變。 */
.srg-player-card{display:flex;align-items:center;gap:clamp(12px,3%,20px)}
.srg-pc-art{flex:0 0 auto;width:clamp(72px,20%,110px);aspect-ratio:3/4;object-fit:cover;object-position:top center;
  border-radius:14px;border:1px solid var(--srg-border);background:rgba(var(--mh-surface-hi-rgb,255,251,240),.7);
  box-shadow:0 6px 18px -12px rgba(var(--mh-ink-rgb,43,58,74),.55)}
/* 還沒選角：同一個格子改放一個去選角的入口，右欄才不會在選角前後左右跳。 */
.srg-pc-art-empty{display:flex;align-items:center;justify-content:center;font-size:34px;
  border-style:dashed;text-decoration:none;opacity:.75}
.srg-pc-info{min-width:0;flex:1;display:flex;flex-direction:column;align-items:flex-start;gap:6px}
.srg-pc-nick{font-family:var(--mh-serif,"Fraunces","Noto Serif TC",Georgia,serif);
  font-size:clamp(20px,5vw,26px);font-weight:700;color:var(--srg-navy);line-height:1.15;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srg-pc-title{display:inline-block;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:700;
  color:#fff;background:var(--srg-tier,#8a94a3);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srg-pc-title-none{background:transparent;color:var(--srg-slate);font-weight:400;padding-left:0}
/* 「選擇稱號」是一顆按鈕（送去徽章牆挑），所以要看得出來點得下去——
   已解鎖卻還沒挑是暫時狀態，長得跟「尚未取得稱號」一樣的話玩家不會去點。
   button 預設會帶自己的 font/background，這裡逐項收掉。 */
.srg-pc-title-pick{font:inherit;font-size:12px;font-weight:700;cursor:pointer;
  color:var(--srg-navy);background:transparent;border:1px dashed rgba(var(--mh-ink-rgb,43,58,74),.35)}
.srg-pc-title-pick:hover,.srg-pc-title-pick:focus-visible{
  background:rgba(var(--mh-ink-rgb,43,58,74),.07);border-style:solid}
.srg-pc-lv{display:flex;align-items:center;gap:8px;flex-wrap:wrap;width:100%}
.srg-pc-lv-num{font-size:14px;font-weight:700;color:var(--srg-navy);white-space:nowrap}
.srg-pc-bar{flex:1 1 80px;min-width:60px;max-width:220px;height:7px;border-radius:999px;
  background:rgba(var(--mh-ink-rgb,43,58,74),.14);overflow:hidden}
.srg-pc-bar i{display:block;height:100%;border-radius:999px;background:var(--mh-honey,#fed65b)}
.srg-pc-xp{font-size:11px;color:var(--srg-slate);white-space:nowrap}
.srg-pc-more{margin-top:2px;text-decoration:none}
@media (max-width:420px){
  /* 立繪縮到最小值就好，**不改成上下堆疊**：那會讓玩家資訊區高過選單上的
     任何一塊，而它只是一張名片。 */
  .srg-pc-art{width:72px}
  .srg-pc-xp{display:none}
}

/* 手機：畫面寬度不夠再切一欄給吉祥物（會把五線譜擠到要橫向捲動），
   改成放在樂譜下方靠右；位置一樣保留著，動畫出現時版面不會跳動。 */
/* 手機直立：整個遊戲畫面（頁首＋樂譜＋鍵盤）要塞進一個螢幕，所以每一處
   內距與間距都往回收。實測 393×720 的視窗，收完之後剛好不用捲動。 */
@media (max-width:600px){
  /* 內距已改由 clamp(10px,3.2%,22px) 隨容器縮放，這裡不再另外指定。 */
  .srg-menu-grid{gap:10px}
  .srg-header{gap:6px;margin-bottom:8px}
  .srg-topbar{padding:8px 12px;gap:8px}
  .srg-topbar .srg-title{font-size:15px}
  .srg-topbar-btns .srg-btn{padding:6px 10px;font-size:13px}
  .srg-hud{padding:6px 12px}
  .srg-stats{gap:8px;font-size:13px}
  .srg-stats span b{font-size:15px}
  .srg-staff-wrap{padding:8px}
  .srg-staff-canvas{width:100%}
  .srg-topbar .srg-mode-tag{margin-left:8px;font-size:11px}
  .srg-answer-pad{margin-top:8px}
  .srg-feedback img{width:74px;height:74px}
  /* 白鍵目標 32px；容器不夠寬時 min() 會讓它繼續縮，而不是切掉右邊幾個鍵。 */
  .srg-piano{min-width:min(100%, calc(var(--srg-keys,8) * 32px))}
  .srg-piano-wrap{padding:10px 4px 14px}
  .srg-letters{gap:6px}
  .srg-note-btn{padding:11px 0;font-size:18px}
}

/* ================= 短視窗（手機橫放） =================
 * 上面那組壓縮版面的條件是 **max-width:600px**，而手機橫放的寬度是 740–930——
 * 一條都套不到，橫放時吃到的反而是最寬鬆的桌機版內距。可是高度只剩 300–400px，
 * 直立版的垂直預算（頁首 101 ＋ 作答提示 32 ＋ 鍵盤 194 ＝ 327px）根本放不下。
 *
 * `.srg-staff-wrap` 是 .srg-playing 裡唯一 flex:1 的項目，於是它把整個赤字
 * **自己一個人吃下去**：實測 740×360 的變化音關卡，.srg-staff-canvas 高度是 0
 * ——樂譜整塊消失（使用者回報的症狀）。`.srg-root` 是 overflow:hidden，
 * 溢出的部分不會變成可捲動，所以只能真的把預算壓進一個螢幕，不能讓它超出。
 *
 * 因此這一組**以高度為條件**（橫放、以及矮的桌機視窗都該套），
 * 而且是唯一會改變頁首列數的地方。
 */
@media (max-height:560px){
  /* 頁首兩列併成一列，省下約 50px——正好是樂譜活下來所需要的高度。
     標題本來就 ellipsis、數據列本來就 nowrap，並排不會互相擠壞。 */
  .srg-root.srg-playing .srg-header{flex-direction:row;align-items:stretch;gap:6px;margin-bottom:6px}
  .srg-root.srg-playing .srg-topbar{flex:1 1 auto;min-width:0;padding:5px 10px;gap:8px}
  .srg-root.srg-playing .srg-topbar .srg-title{font-size:14px}
  .srg-root.srg-playing .srg-topbar-btns .srg-btn{padding:5px 9px;font-size:12px}
  /* 數據列只吃自己需要的寬度（裡面全是不能斷的數字），剩下的寬度留給標題。 */
  .srg-root.srg-playing .srg-hud{flex:0 1 auto;display:flex;align-items:center;padding:5px 10px}
  .srg-root.srg-playing .srg-stats{gap:10px;font-size:12px}
  .srg-root.srg-playing .srg-stats span b{font-size:14px}
  /* 計時列在直立版是「吃掉剩餘寬度」的那一個；併排之後它會把數據列撐到
     整條頁首，標題就沒得站了，所以改成固定寬度。 */
  .srg-root.srg-playing .srg-stat-time{flex:0 1 86px}
  /* 併排之後標題列本來就窄，型別註記再小一級並收緊間距。 */
  .srg-root.srg-playing .srg-topbar .srg-mode-tag{margin-left:6px;font-size:11px}
  /* 樂譜的高度地板，用 svh 表示：再矮下去五線譜就讀不出音高了。
     不寫死 px 是因為 .srg-root overflow:hidden——地板一旦超過剩餘預算，
     被裁掉的會是最下面那截鍵盤。 */
  .srg-root.srg-playing .srg-staff-wrap{min-height:min(96px,26vh);min-height:min(96px,26svh);padding:4px 8px}
  /* 萬一還是不夠，讓**鍵盤**先讓步而不是樂譜（樂譜是這個遊戲的主體，
     琴鍵矮一點仍然按得到，樂譜矮到 0 就等於畫面壞了）。 */
  .srg-root.srg-playing .srg-answer-pad{flex:0 1 auto;min-height:0}
  /* 鍵盤高度跟著視窗縮：原本 clamp 的下限 160px 在橫放時就是壓垮樂譜的那一項
     （30svh 在 360px 高的視窗只有 108px，卻被下限拉回 160px）。 */
  .srg-piano{height:clamp(84px,26vh,150px);height:clamp(84px,26svh,150px)}
  .srg-piano-wrap{padding:8px 6px 10px}
  .srg-answer-pad{margin-top:6px}
  .srg-note-btn{padding:8px 0;font-size:16px}
  .srg-mode-row{margin:6px 0 2px}
  .srg-mode-row button{padding:5px 10px;font-size:12px}
}

/* ================= 音符特效 ================= */
/*
 * 特效層住在 .srg-staff-canvas 裡（而不是外層 wrap），這樣樂譜橫向捲動時
 * 特效會跟著音符一起移動。代價是 drawStaff() 不能再用 innerHTML=''，
 * 必須只換掉樂譜那一個 div——見 game.js 的 drawStaff()。
 */
.srg-fx{position:absolute;inset:0;pointer-events:none;z-index:2;overflow:visible}
.srg-fx-node{position:absolute;width:0;height:0}

/* 屬性主題。動畫只讀這三個變數，不認得屬性叫什麼名字——
   要加雷/冰/暗之類的新屬性，加一組變數 + sanitize 白名單即可，JS 不用改。 */
.srg-el-wind  {--fx-a:#8fd3d8;--fx-b:#d9f2f0}
.srg-el-wood  {--fx-a:#7bb661;--fx-b:#dff0cf}
.srg-el-light {--fx-a:#e8c14a;--fx-b:#fff4cf}
.srg-el-earth {--fx-a:#b08050;--fx-b:#ead6bd}
.srg-el-metal {--fx-a:#9aa5b1;--fx-b:#e3e8ee}
.srg-el-water {--fx-a:#4fa3d1;--fx-b:#cfe8f5}
.srg-el-fire  {--fx-a:#e8703a;--fx-b:#ffd9b8}

/* 光暈：所有屬性共用，只有顏色不同。 */
.srg-fx-halo{position:absolute;left:-26px;top:-26px;width:52px;height:52px;border-radius:50%;
  background:radial-gradient(circle,var(--fx-b) 0%,var(--fx-a) 45%,transparent 70%);
  opacity:0;animation:srgHalo .55s ease-out forwards}
@keyframes srgHalo{0%{opacity:0;transform:scale(.3)}35%{opacity:.85;transform:scale(1)}100%{opacity:0;transform:scale(1.45)}}

/* 粒子。方向由 .srg-fx-p{1..5} 各自的 --tx/--ty 決定，動畫本身共用一支。 */
.srg-fx-p{position:absolute;left:-4px;top:-4px;width:8px;height:8px;border-radius:50%;
  background:var(--fx-a);box-shadow:0 0 6px var(--fx-b);opacity:0;
  animation:srgPart .6s ease-out forwards}
@keyframes srgPart{
  0%{opacity:0;transform:translate(0,0) scale(.4)}
  20%{opacity:1}
  100%{opacity:0;transform:translate(var(--tx),var(--ty)) scale(var(--ps,.5))}
}

/* 答對時音符本身輕彈一下（作用在特效層的節點上，不碰 SVG）。 */
.srg-fx-pop{position:absolute;left:-16px;top:-16px;width:32px;height:32px;border-radius:50%;
  border:2px solid var(--fx-a);opacity:0;animation:srgPop .45s ease-out forwards}
@keyframes srgPop{0%{opacity:.9;transform:scale(.4)}100%{opacity:0;transform:scale(1.8)}}

/*
 * 答錯：七種屬性完全一樣的固定冷灰藍，不套 --fx-a。
 * 水與金屬的成功色本身就是冷色，失敗再跟著屬性變色的話，
 * 玩家會分不出剛才到底對還是錯。
 */
.srg-fx-ice{position:absolute;left:-22px;top:-22px;width:44px;height:44px;
  opacity:0;animation:srgIce .8s ease-out forwards}
.srg-fx-ice::before,.srg-fx-ice::after{content:'';position:absolute;inset:0;
  border:2px solid #7d8a99;opacity:.85}
.srg-fx-ice::before{clip-path:polygon(50% 0,62% 38%,100% 50%,62% 62%,50% 100%,38% 62%,0 50%,38% 38%)}
.srg-fx-ice::after{transform:rotate(45deg) scale(.72)}
@keyframes srgIce{
  0%{opacity:0;transform:scale(.35) rotate(-12deg)}
  30%{opacity:1;transform:scale(1) rotate(0)}
  70%{opacity:1;transform:scale(1.02)}
  100%{opacity:0;transform:scale(1.12)}
}
.srg-fx-shake{position:absolute;left:-24px;top:-24px;width:48px;height:48px;border-radius:50%;
  /* 中心必須是透明的：實心的霧會蓋在符頭上，而答錯那一刻正是學生最需要
     看清楚正確答案的時候。做成環狀就只圍不蓋。 */
  background:radial-gradient(circle,transparent 0%,transparent 42%,
    rgba(125,138,153,.38) 56%,transparent 78%);
  animation:srgShake .34s ease-in-out}
@keyframes srgShake{0%,100%{transform:translateX(0)}20%{transform:translateX(-5px)}
  45%{transform:translateX(5px)}70%{transform:translateX(-3px)}}

/* ================= 加分浮字與鼓勵詞 =================
 * 都住在特效層裡，所以座標系與音符一致（見 game.js fxNodeAt）。
 * 一律往**上**飄：音符下方是琴鍵與作答鈕，往下飄會蓋住玩家正要按的東西。
 * pointer-events:none 是必要的——飄過琴鍵上方時不能吃掉點擊。
 */
/* 兩層都**完全在音符上方**（gain 近、praise 遠）：符頭與五線譜一格都不能被蓋住，
   加分的那一刻玩家還在確認自己剛剛讀的是哪個音。 */
.srg-fx-gain{position:absolute;left:0;top:-30px;transform:translateX(-50%);
  font-weight:800;font-size:22px;line-height:1;white-space:nowrap;pointer-events:none;
  color:var(--srg-success);text-shadow:0 1px 0 rgba(255,255,255,.95),0 0 10px var(--fx-b,rgba(255,255,255,.8));
  animation:srgGainFloat 1.1s cubic-bezier(.2,.7,.3,1) forwards}
.srg-fx-gain.srg-sm{font-size:16px;top:-26px}
@keyframes srgGainFloat{
  0%{opacity:0;transform:translate(-50%,14px) scale(.6)}
  22%{opacity:1;transform:translate(-50%,0) scale(1.15)}
  38%{transform:translate(-50%,-4px) scale(1)}
  100%{opacity:0;transform:translate(-50%,-34px) scale(.95)}
}
/* 鼓勵詞與「與音符無關的加分」（音準、節奏連擊里程碑）：浮在樂譜正上方置中。
   用 bottom:100% 貼在樂譜畫布的**上緣之外**，不是畫布內的 top:6px——畫布現在
   依關卡音域裁到剛好，五線上方只剩十幾 px，擺在裡面就直接蓋住音符了。
   （keyframes 裡的 translate 只是小幅位移，錨點換了照樣成立。） */
.srg-fx-banner{position:absolute;left:50%;bottom:100%;margin-bottom:6px;transform:translateX(-50%);
  padding:6px 16px;border-radius:999px;pointer-events:none;z-index:3;
  font-weight:800;font-size:15px;white-space:nowrap;color:var(--srg-navy);
  background:linear-gradient(180deg,#fffdf6,var(--fx-b,#f4ead2));
  border:1px solid var(--fx-a,var(--srg-ochre));
  box-shadow:0 4px 14px -6px rgba(var(--mh-ink-rgb,43,58,74),.5),0 0 16px var(--fx-b,transparent);
  animation:srgBanner 1.6s ease-out forwards}
/* 長樂譜版：掛在 .srg-staff-wrap（捲動容器外面一層）而不是 #srg-fx。
   `bottom:100%` 在那裡會跑到整張樂譜卡之外，改成貼齊卡片內側頂端；
   位置看起來仍然是「樂譜正上方」，但不會被 overflow 裁掉、也不跟著譜捲走。
   .srg-staff-wrap 本身是 position:relative（見上方 .srg-staff-wrap 那條）。 */
.srg-fx-banner.srg-fx-banner-in{bottom:auto;top:2px;margin-bottom:0;z-index:4}
/* 沒有樂譜的玩法（聽音、常識）：特效層直接疊在題目區之上（見 ui/shell.js）。
   這裡沒有「樂譜畫布的上緣」可以貼，`bottom:100%` 會把橫幅推到整個題目區
   之外看不見的地方，所以改成從題目區頂端往下一點 —— 蓋在題目文字上方，
   而不是蓋住玩家正要點的答案卡。 */
.srg-fx-free{z-index:3}
.srg-fx-free .srg-fx-banner{bottom:auto;top:12px;margin-bottom:0}
/* 答錯的原因（「忘記調號」）：紅底，和鼓勵詞的金色明確分開 ——
   兩者都是橫幅、都在同一個位置，顏色是唯一能一眼分出好消息壞消息的線索。 */
.srg-fx-banner.srg-why{color:#8a2f2a;
  background:linear-gradient(180deg,#fff6f5,#f6e0dd);
  border-color:#c0463f}
/* 鼓勵詞：字大一點、彈進來時帶一點傾斜，和「音準 +30」那種資訊型橫幅區分開。 */
.srg-fx-banner.srg-praise{font-size:19px;padding:7px 20px;
  font-family:"Fraunces","Noto Serif TC",Georgia,serif;
  animation:srgPraiseBanner 1.5s cubic-bezier(.2,.8,.3,1) forwards}
@keyframes srgBanner{
  0%{opacity:0;transform:translate(-50%,-14px) scale(.8)}
  15%{opacity:1;transform:translate(-50%,0) scale(1.06)}
  25%{transform:translate(-50%,0) scale(1)}
  80%{opacity:1}
  100%{opacity:0;transform:translate(-50%,-10px)}
}
@keyframes srgPraiseBanner{
  0%{opacity:0;transform:translate(-50%,-18px) scale(.5) rotate(-7deg)}
  18%{opacity:1;transform:translate(-50%,0) scale(1.14) rotate(3deg)}
  32%{transform:translate(-50%,0) scale(1) rotate(0)}
  72%{opacity:1;transform:translate(-50%,0) scale(1)}
  100%{opacity:0;transform:translate(-50%,-14px) scale(.97)}
}

/* ================= 計時列 ================= */
.srg-timer{display:inline-block;width:74px;height:7px;border-radius:4px;background:rgba(var(--mh-ink-rgb,43,58,74),.14);
  overflow:hidden;vertical-align:middle;margin-right:5px}
.srg-timer i{display:block;height:100%;width:100%;border-radius:4px;background:var(--srg-success);
  transform-origin:left center;transform:scaleX(1);transition:transform 1s linear}
.srg-timer.is-low i{background:#d9534f;animation:srgPulse .9s ease-in-out infinite}
@keyframes srgPulse{0%,100%{opacity:1}50%{opacity:.45}}
/* 麥克風作答時，每秒的倒數提示改用這個脈動代替聲音（見 game.js 的 tick）。
   收音中不能播倒數音效，所以這裡要夠明顯才擔得起原本那一聲的功能。 */
.srg-timer.srg-pulse{animation:srgTimerBeat .5s ease-out}
@keyframes srgTimerBeat{
  0%{transform:scale(1);box-shadow:0 0 0 0 rgba(217,83,79,.65)}
  30%{transform:scale(1.35);box-shadow:0 0 0 5px rgba(217,83,79,0)}
  100%{transform:scale(1);box-shadow:0 0 0 0 rgba(217,83,79,0)}
}

/* ================= 分數 ================= */
.srg-score-wrap{position:relative;display:inline-block}
/* HUD 的分數數字本身彈一下。玩家的視線在樂譜上，只有數字默默變大會被完全錯過。
   **兩個 id 都要列**：`#srg-s` 是視譜／旋律題的計分列（game.js 手刻的），
   `#srg-mode-score` 是外掛式玩法的（ui/shell.js 的 `opts.score` 產的）。
   只寫前者的話節奏／聽音／常識／找碴關的分數會滾但不會彈 —— 而那個差別
   沒有人會回報，只會覺得「那幾關的回饋比較弱」。 */
#srg-s,#srg-mode-score{display:inline-block}
#srg-s.srg-bump,#srg-mode-score.srg-bump{animation:srgScoreBump .45s cubic-bezier(.2,.8,.3,1)}
@keyframes srgScoreBump{
  0%{transform:scale(1)}
  30%{transform:scale(1.45);color:var(--srg-success)}
  100%{transform:scale(1)}
}

/* ---- 結算畫面 ---- */
.srg-result-score{margin:10px 0 2px;line-height:1;display:flex;align-items:baseline;gap:6px}
.srg-result-score b{font-family:"Fraunces","Noto Serif TC",Georgia,serif;font-size:52px;
  font-variant-numeric:tabular-nums;color:var(--srg-navy);
  text-shadow:0 2px 0 rgba(255,255,255,.8),0 0 18px var(--srg-glow-soft)}
.srg-result-score-u{font-size:16px;font-weight:700;color:var(--srg-slate)}
.srg-result-line{margin:2px 0 0;color:var(--srg-slate);font-size:14px}
/* 鼓勵評語：每一關都換一句（詞庫在 public/praise.js）。 */
/* 解鎖區的評語下面就是徽章卡，而卡片浮出時會往上頂 4px，留點空間別讓它壓到字。 */
.srg-ach-new .srg-result-praise{margin-bottom:12px}
.srg-result-praise{margin:10px 0 0;font-size:17px;font-weight:700;color:var(--srg-navy);
  font-family:"Fraunces","Noto Serif TC",Georgia,serif;
  animation:srgPraiseIn .7s .25s cubic-bezier(.2,.8,.3,1) both}
@keyframes srgPraiseIn{
  0%{opacity:0;transform:translateY(8px)}
  100%{opacity:1;transform:translateY(0)}
}

/* 新解鎖的徽章：浮出 → 閃一下 → 歸位。閃光用 ::after 疊一層，
   卡片本身的位移交給 transform，兩者互不干擾。 */
/* 只有結算畫面的新解鎖卡要 relative/overflow，徽章牆那幾十張不必跟著改。 */
.srg-ach-card.srg-pop-in{position:relative;overflow:hidden;
  animation:srgAchPop .75s cubic-bezier(.2,.8,.25,1) both}
.srg-ach-card.srg-pop-in::after{content:'';position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;opacity:0;
  background:linear-gradient(120deg,transparent 30%,var(--srg-glow-soft) 50%,transparent 70%);
  animation:srgAchFlash .75s cubic-bezier(.2,.8,.25,1) both;
  /* 卡片的 delay 是 JS 逐張設的 inline style；inherit 讓閃光跟著同一個節拍。 */
  animation-delay:inherit}
@keyframes srgAchPop{
  0%{opacity:0;transform:scale(.72) translateY(14px)}
  45%{opacity:1;transform:scale(1.08) translateY(-4px)}
  70%{transform:scale(.98) translateY(0)}
  100%{opacity:1;transform:scale(1) translateY(0)}
}
@keyframes srgAchFlash{
  0%{opacity:0;transform:translateX(-60%)}
  45%{opacity:.9}
  100%{opacity:0;transform:translateX(60%)}
}
.srg-score-pop{position:absolute;left:50%;bottom:100%;transform:translateX(-50%);
  white-space:nowrap;font-weight:800;font-size:13px;color:var(--srg-success);
  text-shadow:0 1px 2px rgba(255,255,255,.9);pointer-events:none;
  animation:srgScorePop .9s ease-out forwards}
@keyframes srgScorePop{
  0%{opacity:0;transform:translate(-50%,4px) scale(.8)}
  25%{opacity:1;transform:translate(-50%,-4px) scale(1.1)}
  100%{opacity:0;transform:translate(-50%,-22px) scale(1)}
}

/* ================= 逐題成績卡 =================
 * 第一排「答對了沒」＋「🎯 神準音符 3 個」+ 這一題的得分。
 *
 * **疊在樂譜上**（v2.53.0，使用者 2026-09-17 指定：「popup 直接遮蓋樂譜，
 * 樂譜不縮小」）。以前它掛在樂譜正下方的判讀區，而判讀區與樂譜畫布是同一張
 * 卡片裡的兩個 flex 項目 —— 卡片一出現就把高度從畫布那邊借走（畫布是
 * `flex:1`、SVG 是 `max-height:100%`），**不遮譜不代表不佔位**，譜跟著縮小。
 * 現在改成絕對定位疊在 `.srg-staff-canvas` 上：版面一格都不動。
 *
 * 蓋住的那幾秒不損失什麼：譜上的判定小字（準／快／慢／漏）現在一直都畫著，
 * 而卡片 5 秒後（或玩家點別的地方）就自己收掉。
 *
 * 右上角那顆 ✕ 留著（v2.38.0）：那是「我看完了」的即時出口。右邊的 34px
 * 內距是留給它的，少了它長一點的鼓勵詞會鑽到鈕底下。
 */
.srg-qcard{position:absolute;left:50%;top:50%;z-index:5;
  padding:10px 34px 10px 16px;
  width:max-content;max-width:min(92%,420px);border-radius:12px;
  text-align:left;
  /* 蓋在譜上，所以底要夠不透明——半透明的底配上五線譜，兩層文字會互相吃掉。 */
  background:rgba(var(--mh-surface-hi-rgb,255,251,240),.985);
  border:1px solid var(--srg-border);
  box-shadow:0 10px 30px -8px rgba(var(--mh-ink-rgb,43,58,74),.55);
  transform:translate(-50%,-50%)}
/* **跳出來**（縮放彈入）而不是淡入：那是「答完了，來看成績」的訊號，
   淡入會被讀成畫面自己在重排。中段的 1.04 是那一下「彈」。
   ⚠ 置中用的 translate(-50%,-50%) 必須寫進每一個 keyframe —— transform 是
   同一個屬性，動畫期間會整個蓋掉上面那一行，少寫的話卡片會飛到右下角。 */
.srg-qcard-in{animation:srgQPop .5s cubic-bezier(.2,.8,.25,1) both}
@keyframes srgQPop{
  0%{opacity:0;transform:translate(-50%,-50%) scale(.82) translateY(10px)}
  55%{opacity:1;transform:translate(-50%,-50%) scale(1.04) translateY(-2px)}
  100%{opacity:1;transform:translate(-50%,-50%) scale(1) translateY(0)}
}
/* 第一排：這一題答對了沒（v2.53.0）。結論用顏色與圖示說，
   「為什麼」壓小接在後面——它是註腳，不該跟結論搶同一個字級。 */
.srg-qcard .srg-qverdict{font-size:15px;line-height:1.45;margin-bottom:2px}
.srg-qcard .srg-qverdict b{font-weight:800}
.srg-qcard .srg-qverdict.ok b{color:var(--srg-success,#2e7d4f)}
.srg-qcard .srg-qverdict.bad b{color:#b0524a}
.srg-qcard .srg-qwhy{display:block;font-size:12.5px;font-weight:400;
  color:var(--srg-slate,#6b7280);line-height:1.4}
.srg-qcard .srg-qbig{font-size:16px;font-weight:800;color:var(--srg-navy);
  line-height:1.5}
.srg-qcard .srg-qbig b{color:var(--srg-ochre);font-size:22px;margin:0 5px}
.srg-qcard .srg-qfoot{display:flex;align-items:baseline;justify-content:space-between;
  gap:10px;margin-top:6px}
.srg-qcard .srg-qpraise{font-weight:700;color:var(--srg-navy);font-size:14px}
/* tabular-nums：滾動時每一幀的字寬一樣，數字才不會左右抖。 */
.srg-qcard .srg-qgain{font-weight:800;color:var(--srg-success);font-size:15px;
  white-space:nowrap;font-variant-numeric:tabular-nums}
/* 關閉鈕。**觸控目標要 32px 以上**（手機上這張卡就在拇指區），所以鈕比 ✕
   本身大一圈；顏色壓得比內文淡 —— 它是出口不是重點。 */
.srg-qcard .srg-qclose{position:absolute;top:4px;right:4px;
  width:32px;height:32px;line-height:1;padding:0;
  display:flex;align-items:center;justify-content:center;
  background:none;border:0;border-radius:8px;cursor:pointer;
  font-size:15px;color:var(--srg-slate);opacity:.7}
.srg-qcard .srg-qclose:hover,.srg-qcard .srg-qclose:focus-visible{
  opacity:1;background:rgba(var(--mh-ink-rgb,43,58,74),.08)}

/* 尊重系統的減少動態偏好：關掉位移與閃爍，只留顏色變化。 */
@media (prefers-reduced-motion: reduce){
  .srg-fx-p,.srg-fx-pop,.srg-fx-shake{display:none}
  /* 琴鍵的光暈不閃、不縮放，只留一層靜態的光——它同時是「這一鍵有收到」的回饋。 */
  .srg-white.srg-lit::after,.srg-note-btn.srg-lit::after{animation:none;opacity:.9;
    box-shadow:0 0 12px 3px var(--srg-glow)}
  .srg-black.srg-lit::after{animation:none;opacity:.9;box-shadow:0 0 12px 3px var(--srg-glow-dark)}
  .srg-white,.srg-black,.srg-note-btn,.srg-btn{transition:none}
  .srg-fx-halo,.srg-fx-ice{animation-duration:.01ms;opacity:.6}
  .srg-timer i{transition:none}
  .srg-timer.is-low i{animation:none}
  /* 倒數脈動不能整個關掉——麥克風模式下它是唯一的倒數提示。
     只把位移拿掉，改用顏色環傳達。 */
  .srg-timer.srg-pulse{animation-duration:.4s}
  @keyframes srgTimerBeat{
    0%{box-shadow:0 0 0 0 rgba(217,83,79,.65)}
    100%{box-shadow:0 0 0 5px rgba(217,83,79,0)}
  }
  .srg-score-pop{animation-duration:.01ms;opacity:1}
  /* 加分浮字與鼓勵詞不飛不轉，但**不能不顯示**——那是「為什麼加分」的唯一說明。
     改成原地淡入淡出，資訊全留著。 */
  .srg-fx-gain,.srg-fx-banner{animation:srgFadeHold 1.1s ease-out forwards}
  @keyframes srgFadeHold{0%{opacity:0}12%{opacity:1}80%{opacity:1}100%{opacity:0}}
  #srg-s.srg-bump,#srg-mode-score.srg-bump{animation:none}
  /* 逐題成績卡不彈，但**絕對不能不顯示**——「神準 3 個」與「休止符全對」
     那兩個數字就是這一題的成績本身。改成原地淡入，而且要**留在畫面上**
     （不可以套 srgFadeHold，那是「淡入→停→淡出」，卡片會自己消失）。 */
  .srg-qcard-in{animation:srgFadeIn .3s ease-out both}
  @keyframes srgFadeIn{0%{opacity:0}100%{opacity:1}}
  .srg-ach-card.srg-pop-in{animation:none}
  .srg-ach-card.srg-pop-in::after{display:none}
  .srg-result-praise{animation:none}
  /* 預備拍倒數：弱化但不移除——不縮放、原地淡入淡出，數字仍要讓玩家看到。 */
  .srg-rh-countdown{animation:srgFadeHold .9s ease-out forwards;
    transform:translate(-50%,-50%)}
}

/* ================= 節奏題 ================= */
/* 控制列：狀態訊息 + 開始鈕 + 樂器類型。放在作答面板最上方。 */
/*
 * 內距與下緣間距刻意小（2026-09-15 使用者回報「按鈕列和鼓的空隙太大」）：
 * 大部分時候這一列上只有一顆「▶ 開始」，而它底下就是鼓面板。
 * 6px 的下緣 + `.srg-drums` 的 4px 上內距 = 看得見的 10px，
 * 舊版是 10 + 10 = 20，在 800px 高的視窗上那是整整一行譜的高度。
 */
.srg-rh-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:6px 10px;margin-bottom:6px;border-radius:12px;
  background:rgba(var(--mh-surface-hi-rgb,255,251,240),.92);border:1px solid var(--srg-border)}
/*
 * 控制列上的按鈕比一般按鈕小一號。它們在畫面最下緣、只有一兩顆，
 * 用一般尺寸時整列比鼓面板還搶眼（同一次回報：「開始按鈕太大」）。
 */
.srg-rh-bar .srg-btn{padding:5px 12px}
.srg-rh-msg{flex:1 1 220px;font-size:14px;color:var(--srg-navy)}
.srg-rh-instwrap{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--srg-slate)}
/* 同 .srg-title-select：<select> 的字級不能低於 16px（iOS 聚焦會放大且不縮回）。 */
.srg-rh-inst{font-size:16px;padding:2px 6px;border-radius:6px;border:1px solid var(--srg-border)}
.srg-rh-note{font-size:11px;color:var(--srg-slate)}

/* 判定當下在音符上冒出來的小點。noteBoxes 在節奏題是以 noteIndex 為鍵。 */
.srg-rh-pop{position:absolute;width:14px;height:14px;margin:-7px 0 0 -7px;border-radius:50%;
  pointer-events:none;animation:srgRhPop .7s ease-out forwards}
.srg-rh-perfect{background:#2f8f4e}
.srg-rh-good{background:#6a9a3a}
.srg-rh-early,.srg-rh-late{background:#c08a2c}
.srg-rh-miss{background:#c0463f}
.srg-rh-wrongpitch{background:#8a4fa0}
/* 音不準：音名對、音準沒到。與「彈錯音」分開的第三種判定（見 isOffPitch）。 */
.srg-rh-offpitch{background:#e59500}
.srg-rh-extra{background:#8a8a8a}
@keyframes srgRhPop{
  0%{opacity:.9;transform:scale(.4)}
  40%{opacity:.85;transform:scale(1.6)}
  100%{opacity:0;transform:scale(2.2)}
}

/* 節奏題預備拍倒數：每一拍在遊戲正中央放一個會放大淡出的數字。
   掛在 .srg-root 上而不是 #srg-fx——後者疊在樂譜畫布上緣，倒數要的是整個遊戲區
   的中央。.srg-root 在 .srg-playing 時是 flex 滿版，這裡用 absolute 置中就是
   視窗中央；不用 fixed，否則頁面一捲動就跑出遊戲區外。
   z-index 90000 壓過遊戲內所有元素（含 .srg-fx z-index:2、.srg-fx-banner
   z-index:3、.srg-content z-index:1），但低於 modal 的 100000、骨架 160000、
   圖示選擇器面板 170000——玩家按下停止時 modal 蓋下來，倒數不擋路。
   pointer-events:none 蓋在作答面板上方不擋點擊。 */
.srg-rh-countdown{
  position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%) scale(.6);
  font-family:var(--mh-serif,"Fraunces","Noto Serif TC",Georgia,serif);
  font-weight:800;
  /* vmin 縮放：手機小螢幕不會頂出遊戲區、桌機大螢幕也不會小到看不清。 */
  font-size:clamp(96px,28vmin,220px);
  line-height:1;color:var(--srg-navy);
  text-shadow:0 2px 0 rgba(255,255,255,.9),0 0 24px var(--mh-surface,#f4ead2);
  pointer-events:none;z-index:90000;user-select:none;
  opacity:0;
  animation:srgRhCountdown .75s cubic-bezier(.2,.7,.3,1) forwards;
}
.srg-rh-countdown-label{
  display:block;
  font-size:clamp(14px,3.4vmin,26px);
  font-weight:700;letter-spacing:.14em;
  margin-top:.12em;opacity:.78;
}
/* 讀譜時間的數字：與預備拍區分開（那一顆是深藍，這一顆是墨綠系的主色）。 */
.srg-rh-countdown-read{color:var(--mh-primary,#455529)}

@keyframes srgRhCountdown{
  0%  {opacity:0;transform:translate(-50%,-50%) scale(.55)}
  18% {opacity:1;transform:translate(-50%,-50%) scale(1.08)}
  35% {opacity:1;transform:translate(-50%,-50%) scale(1)}
  100%{opacity:0;transform:translate(-50%,-50%) scale(1.55)}
}

/* 結算：兩條獨立的達標軸。u 是門檻刻度線。 */
.srg-rh-res{margin:10px 0}
.srg-rh-res-top{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:4px}
.srg-rh-res-l{font-weight:700;color:var(--srg-navy)}
.srg-rh-res-v{font-size:20px;font-weight:800;font-variant-numeric:tabular-nums;color:#c0463f}
.srg-rh-res.pass .srg-rh-res-v{color:var(--srg-success)}
.srg-rh-res-n{font-size:12px;color:var(--srg-slate);margin-left:auto}
.srg-rh-res-bar{position:relative;height:10px;border-radius:5px;overflow:hidden;
  background:rgba(var(--mh-ink-rgb,43,58,74),.12)}
.srg-rh-res-bar i{display:block;height:100%;border-radius:5px;background:#c0463f;
  transition:width .5s ease-out}
.srg-rh-res.pass .srg-rh-res-bar i{background:var(--srg-success)}
/* 門檻線要畫在填色之上才看得見，所以不放進 overflow:hidden 的填色層裡疊色。 */
.srg-rh-res-bar u{position:absolute;top:-2px;bottom:-2px;width:2px;margin-left:-1px;
  background:var(--srg-navy);opacity:.75}

/* 速度感的三句話（起步／穩不穩／趕拍）。上面那一排是計數，這一列是**講評** ——
   給它一條左邊界與底色，才不會被讀成又一排統計數字。 */
.srg-rh-tempo{margin:6px 0 0;padding:6px 10px;border-left:3px solid var(--srg-navy);
  background:rgba(0,0,0,.04);border-radius:0 6px 6px 0;font-size:13px;line-height:1.7}

@media (prefers-reduced-motion: reduce){
  .srg-rh-pop{animation-duration:.01ms;opacity:.7}
  .srg-rh-res-bar i{transition:none}
}

/* 播放游標。由播放時鐘在音符座標之間**內插**驅動（見 game.js updateCursor）——
   每個音跳一格看得出來是離散的、跟不上拍，內插才像真的在走拍子。

   **這是畫在 <svg> 裡的 SVG 元素，不是 HTML 疊層。** VexFlow 的 scale() 是改
   viewBox，所以游標和音符自動共用同一個座標系，不需要任何位置校準。
   不加 transition：位置本來就每幀更新，補間反而會落後於實際拍點。 */
.srg-cursor{pointer-events:none}
.srg-cursor .srg-cursor-bar{fill:rgba(47,107,214,.75)}
.srg-cursor .srg-cursor-tip{fill:rgba(47,107,214,.95)}
/* 預備拍：停在第一個音上脈動，表示「還沒輪到你」。 */
.srg-cursor.countin .srg-cursor-bar{fill:rgba(var(--mh-gold-rgb,201,168,106),.7)}
.srg-cursor.countin .srg-cursor-tip{fill:rgba(var(--mh-gold-rgb,201,168,106),.95)}
.srg-cursor.countin{animation:srgCursorWait .5s ease-in-out infinite}
@keyframes srgCursorWait{0%,100%{opacity:1}50%{opacity:.35}}
/* 譜面靠左：特效疊層的 x 以畫布左緣為原點，置中會讓兩者對不上。 */
.srg-staff-svg{text-align:left}
@media (prefers-reduced-motion: reduce){
  .srg-cursor.countin{animation:none}
}

/* 測試帳號提示（選單）。測試模式繞過了解鎖鏈，是很容易忘記的狀態——
   忘了就會把「關卡沒鎖」誤判成 bug，所以一定要在畫面上講出來。 */
.srg-testmode{margin:10px 0 4px;padding:8px 14px;border-radius:12px;font-size:13px;font-weight:600;
  color:#7a5b12;background:rgba(254,214,91,.35);border:1px dashed rgba(var(--mh-gold-rgb,201,168,106),.7)}

/* ================= 進版頁（外觀設定 → 進版頁） =================
 * 設計對象是**手機與平板直立**。整塊撐滿一個螢幕高，內部分三段：
 * 標題（上）／按鈕（中，吃掉所有剩餘高度）／地區說明＋圓點（下）。
 * 高度差全被中間那段吸收，所以沒有任何斷點——4 吋手機到 13 吋平板都成立。
 *
 * svh 是行動瀏覽器網址列展開時的高度；用 vh 的話網址列一收起，封面就會比視窗
 * 高出一截並產生捲軸（.srg-playing 已經踩過同一個坑）。
 */
.srg-root.srg-splash-on{
  padding:0;                       /* 圖片要滿出到圓角邊緣，內距會露出羊皮紙底 */
  min-height:calc(100vh - 24px);min-height:calc(100svh - 24px);
  max-height:calc(100vh - 24px);max-height:calc(100svh - 24px);
  display:flex;flex-direction:column;
  /* 圖片載入前的底色，用近黑的 ink 而不是純黑，和整體色調一致。 */
  background:var(--mh-ink,#1c1c17)}
.srg-splash{position:relative;flex:1 1 auto;min-height:0;overflow:hidden;border-radius:inherit;
  isolation:isolate;
  /* 自己也是 flex 容器：內容層改用 flex:1 撐滿，不用 height:100%。
     被 flex 拉長的項目，其高度在 Chrome 眼裡不算「確定值」，子元素的
     height:100% 會退回內容高度——實測 527px 的封面裡內容只佔 319px，
     標題、按鈕、說明全擠在上半部。 */
  display:flex;flex-direction:column}
/* ---- 圖層 ---- */
.srg-splash-stage{position:absolute;inset:0;z-index:0}
.srg-splash-img{position:absolute;inset:0;background-size:cover;background-position:center;
  opacity:0;transition:opacity 1.2s ease-in-out;transform-origin:center center;
  will-change:opacity,transform}
.srg-splash-img.on{opacity:1}
/* 深色漸層讓白字在任何一張圖上都讀得到（水彩圖的亮度分佈完全不可預期）。
   上下各壓一段、中間留亮，正好對應「標題在上、說明在下、圖在中間」。 */
.srg-splash-scrim{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(to bottom,rgba(20,20,14,.55) 0%,rgba(20,20,14,.12) 22%,
      rgba(20,20,14,.10) 52%,rgba(20,20,14,.62) 82%,rgba(20,20,14,.80) 100%)}
/* ---- 內容 ---- */
.srg-splash-ui{position:relative;z-index:2;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;
  padding:clamp(16px,4.5%,32px);text-align:center;color:#fff}
.srg-splash-head{flex:0 0 auto}
.srg-splash-head h1{font-size:clamp(28px,7.5vw,48px);line-height:1.15;color:#fff;
  letter-spacing:.06em;text-shadow:0 2px 10px rgba(0,0,0,.55),0 0 30px rgba(0,0,0,.3)}
.srg-splash-head p{margin:6px 0 0;font-size:clamp(11px,2.8vw,14px);letter-spacing:.28em;
  text-transform:uppercase;opacity:.85;text-shadow:0 1px 6px rgba(0,0,0,.6)}
/* 中段吃掉所有剩餘高度並置中——「開始冒險」永遠在畫面正中央。 */
.srg-splash-mid{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:14px}
.srg-splash-tag{margin:0;font-size:clamp(10px,2.6vw,12px);font-weight:600;letter-spacing:.24em;
  text-transform:uppercase;opacity:.8;text-shadow:0 1px 6px rgba(0,0,0,.6)}
/* 蠟封印章：設計稿的 primary CTA。手指要按得到，所以有最小高度與寬鬆內距。 */
.srg-splash-cta{display:inline-flex;align-items:center;gap:12px;cursor:pointer;
  min-height:60px;padding:0 clamp(28px,8vw,52px);border-radius:var(--mh-radius-pill,999px);
  font-family:var(--mh-serif,"Fraunces","Noto Serif TC",Georgia,serif);
  font-size:clamp(20px,5.6vw,30px);font-weight:700;letter-spacing:.12em;color:#fff;
  background:radial-gradient(circle at 30% 28%,var(--mh-seal-a,#c62828),var(--mh-seal-b,#93000a));
  border:2px solid var(--mh-seal-edge,#7a0006);
  box-shadow:0 10px 26px -8px rgba(0,0,0,.65),inset 0 0 18px rgba(0,0,0,.25),
    inset 0 2px 0 rgba(255,255,255,.18);
  text-shadow:0 2px 6px rgba(0,0,0,.45);
  transition:transform .15s ease,box-shadow .15s ease}
.srg-splash-cta:hover{transform:scale(1.04)}
.srg-splash-cta:active{transform:scale(.97)}
.srg-splash-cta-arrow{font-size:.8em;transition:transform .15s ease}
.srg-splash-cta:hover .srg-splash-cta-arrow{transform:translateX(4px)}
/* ---- 下緣：地區說明與圓點 ---- */
.srg-splash-foot{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:12px}
.srg-splash-cap{min-height:2.6em}   /* 佔位：切換到沒有說明的圖時版面不該跳動 */
.srg-splash-cap h2{font-size:clamp(20px,5.4vw,30px);color:#fff;line-height:1.2;
  text-shadow:0 2px 10px rgba(0,0,0,.6)}
.srg-splash-cap p{margin:4px 0 0;font-size:clamp(13px,3.4vw,16px);opacity:.9;
  text-shadow:0 1px 8px rgba(0,0,0,.7)}
.srg-splash-dots{display:flex;gap:9px;align-items:center}
.srg-splash-dot{width:9px;height:9px;padding:0;border:none;border-radius:999px;cursor:pointer;
  background:rgba(255,255,255,.45);transition:width .3s ease,background .3s ease}
.srg-splash-dot.on{width:26px;background:var(--srg-honey)}
/* 觸控目標要夠大（9px 的點按不到），用透明外框補足而不撐開視覺尺寸。 */
.srg-splash-dot::before{content:'';position:absolute;inset:-12px}
.srg-splash-dots .srg-splash-dot{position:relative}
/* 系統開啟「減少動態效果」時，推近由 JS 停用，這裡連淡入也一併關掉。 */
@media (prefers-reduced-motion:reduce){
  .srg-splash-img{transition:none}
  .srg-splash-cta{transition:none}
}

/* 拍子偏差的小字。畫在 <svg> 內，與音符共用座標系（見 drawBeatLabels），
   所以這裡只管字型與粗細——位置是 SVG 屬性給的。
   fill 由 JS 依後台色票設定，不寫在 CSS 裡。 */
.srg-beat-label{
  font-family:"Noto Sans TC","Microsoft JhengHei",system-ui,sans-serif;
  font-weight:600;
  pointer-events:none;
}

/* 結算卡的綜合成績列。刪掉了計算公式，所以這一列要自己站得住。 */
.srg-rh-final{display:flex;align-items:baseline;gap:10px;margin:14px 0 4px;
  padding-top:12px;border-top:1px solid var(--srg-line,#e2dcc9)}
.srg-rh-final b{font-size:22px;font-variant-numeric:tabular-nums}
.srg-rh-verdict{margin-left:auto;font-weight:700}
.srg-rh-verdict.pass{color:#2f8f4e}
.srg-rh-verdict.fail{color:#c0463f}

/* ─────────────────────────────────────────────────────────────────────────
   判定標示（v2.47.0 取代顏色圖例；v2.53.0 起一律顯示）

   以前這裡是 `.srg-rh-legend` / `.srg-rh-legrow` / `.srg-rh-key`：演奏完在
   樂譜下方掛一排色塊解釋「綠色是什麼意思」。整排拿掉了（使用者 2026-09-15
   指定），因為它①在手機上吃掉樂譜的高度，②要求玩家在色塊與符頭之間來回
   對照。改成把答案（準／快／慢／漏／誤）直接寫在音符下面。

   v2.53.0 **連那顆 ℹ 開關也拿掉了**（使用者 2026-09-17 指定：「直接渲染、
   刪除 info 按鈕」）—— 那些字是答案本身，不是附加資訊，沒有理由要按一下
   才看得到，而預設是關的等於絕大多數玩家從來沒看過它們。
   （`.srg-mark-toggle` 那一組規則隨之刪除。）
   ───────────────────────────────────────────────────────────────────────── */

/* 符頭下面那個判定的字。畫在 <svg> 內（與音符共用座標系，見
   rhythm-staff.js 的 drawMarks 與 melody-staff.js 的 drawBeatLabels），
   所以這裡只管字型——位置與 fill 都是 SVG 屬性給的。 */
.srg-verdict-mark{
  font-family:"Noto Sans TC","Microsoft JhengHei",system-ui,sans-serif;
  pointer-events:none;
}

/* HUD 的數量詞（個音／題／分）。中文的單位在數字後面。
   壓小壓淡是為了讓數字本身仍是視線落點——單位是給語意的，不是給掃視的。
   .srg-stats 是 nowrap，所以單位不能自己斷行。 */
.srg-stats .srg-u{
  font-style:normal;
  font-weight:400;
  font-size:.85em;
  opacity:.72;
  margin-left:2px;
  white-space:nowrap;
}

/* ─────────────────────────────────────────────────────────────────────────
   聽音範例 panel（v1.52.0）

   在遊戲區塊內另開一塊 demo，視覺上跟主關卡同一系統（�色／間距取自 var(--srg-*)）。
   預設音符透明、按下播放才出聲、播放完跑一小節預備拍，鍵盤作答即時塗色。

   為什麼這個 panel 獨立於現有關卡渲染：
   - 它不需要關卡資料／題庫／成績上報，純前端互動
   - 它的譜面是 8 個高音譜號音符（八度音階），比關卡畫面簡單得多
   - 它直接覆寫現有 .srg-cursor 那條樣式（重複宣告、後寫的贏）以沿用游標視覺
   ───────────────────────────────────────────────────────────────────────── */
.srg-demo{
  margin:18px auto 0;
  max-width:760px;
  padding:18px 22px 22px;
  background:var(--mh-card, #fffaf0);
  border:1.5px solid var(--mh-ink, #2b3a4a);
  border-radius:14px;
  color:var(--mh-ink, #2b3a4a);
  font-family:inherit;
  box-sizing:border-box;
  box-shadow:0 4px 18px rgba(43,58,74,.08);
}
.srg-demo-title{
  margin:0 0 6px;
  font:700 18px/1.3 "Nunito","PingFang TC","Noto Sans TC",sans-serif;
  letter-spacing:.02em;
}
.srg-demo-hint{
  margin:0 0 14px;
  font:400 13.5px/1.6 "PingFang TC","Noto Sans TC",sans-serif;
  opacity:.78;
}
/* 譜容器：固定高度避免每次重繪抖動。寬度跟著 panel 走。 */
.srg-demo-staff-wrap{
  position:relative;
  width:100%;
  min-height:140px;
  background:linear-gradient(180deg,#fbf6e7 0%,#f4ecd3 100%);
  border-radius:8px;
  border:1px solid rgba(43,58,74,.18);
  padding:8px 0 14px;
  overflow:hidden;
}
.srg-demo-staff{ position:relative; width:100%; }
/* VexFlow 自己產生的 svg 撐滿容器。 */
.srg-demo-staff svg{ display:block; width:100%; height:auto; }
/* 預設音符透明：所有 notehead 透明，stem 與 ledger 也跟著藏。
   只有「作答過」或「被判定為漏」的才塗色（見 .srg-demo-notehead--*）。 */
.srg-demo-staff svg .vf-notehead{
  fill:transparent !important;
  stroke:transparent !important;
}
/* stem / ledger / accidental 一律隱藏：譜面上只有譜線與游標。
   stem 沒顏色也藏掉，避免「透明的頭 + 一條黑桿」露餡。 */
.srg-demo-staff svg .vf-stem{ display:none !important; }
.srg-demo-staff svg .vf-ledger{ display:none !important; }
.srg-demo-staff svg text{ fill:transparent !important; }
/* 作答後的三態顏色。顏色由 JS 從 SRG_CONFIG.feedbackColors 注入，這裡只負責
   三種「狀態 class」與 CSS 變數的�定，之後改色不用碰這檔。 */
.srg-demo-notehead--ok{ fill:var(--srg-demo-ok,#00bd89) !important; }
.srg-demo-notehead--bad{ fill:var(--srg-demo-bad,#df2085) !important; }
.srg-demo-notehead--miss{ fill:var(--srg-demo-miss,#9aa4ad) !important; }

/* indicator bar：覆寫 .srg-cursor 的預設色 + 動畫。
   在譜容器內絕對定位，水平位置由 JS 的 left% 帶入。
   預備拍時用「脈動」動畫，答題時平滑跟著節拍走。 */
.srg-demo-cursor{
  position:absolute;
  top:0; bottom:0;
  width:6px;
  border-radius:3px;
  background:var(--srg-demo-cursor,#2f6bd6);
  box-shadow:0 0 8px rgba(47,107,214,.45);
  transition:left .05s linear;
  pointer-events:none;
  z-index:3;
}
.srg-demo-cursor[data-state="countin"]{
  animation:srg-demo-pulse 1s ease-in-out infinite;
}
@keyframes srg-demo-pulse{
  0%,100%{ opacity:.35; transform:scaleX(.55); }
  50%{    opacity:1;   transform:scaleX(1);  }
}

/* 控制列：左按鈕、右狀態。間距跟 panel 的 grid 對齊。 */
.srg-demo-bar{
  display:flex;
  align-items:center;
  gap:14px;
  margin-top:14px;
  flex-wrap:wrap;
}
.srg-demo-play{
  font:700 14px/1 "Nunito","PingFang TC","Noto Sans TC",sans-serif;
  padding:10px 20px;
  border-radius:999px;
  background:var(--mh-accent, #2b3a4a);
  color:#fffaf0;
  border:0;
  cursor:pointer;
  letter-spacing:.03em;
  transition:transform .12s, background .12s;
}
.srg-demo-play:hover{ background:var(--mh-accent-hover, #3a4f63); }
.srg-demo-play:active{ transform:scale(.97); }
.srg-demo-play[disabled]{
  opacity:.5;
  cursor:not-allowed;
  background:var(--mh-ink, #2b3a4a);
}
.srg-demo-status{
  font:500 13.5px/1.4 "PingFang TC","Noto Sans TC",sans-serif;
  opacity:.75;
  min-height:1.4em;
}
.srg-demo-status[data-tone="ok"]  { color:var(--srg-demo-ok,#00bd89);   opacity:1; }
.srg-demo-status[data-tone="bad"] { color:var(--srg-demo-bad,#df2085);  opacity:1; }
.srg-demo-status[data-tone="miss"]{ color:var(--srg-demo-miss,#9aa4ad); opacity:1; }


/* ==================== 卡片作答（大賢者之塔 / 聽音選擇）====================
   卡片是真的 <button>：Tab 走得到、Enter 按得下、螢幕閱讀器唸得出來。
   排序題另外給上下移按鈕 —— 只能拖曳的介面對鍵盤使用者等於不能玩。

   ⚠ **這一段的字級一律拆成四個屬性寫，不可以收回 `font:` 簡寫。**
   `font:600 16px/1.35 inherit` 是**無效的宣告**（`inherit` 只有在整條簡寫
   只有它一個值時才合法，當成字族名是不合規的），瀏覽器會把整條丟掉 ——
   於是這些卡片一直是用 `<button>` 的預設值在畫：13.33px、粗細 400、Arial，
   而不是這裡寫的 16px／600／跟著主題的字。畫面上看起來「就是小了一點」，
   沒有任何錯誤訊息，所以從上線到 2026-09-16 都沒有人發現
   （`CSS.supports('font','600 16px/1.35 inherit')` 回 false，實測）。 */
.srg-tv-prompt{font-size:19px;font-weight:700;text-align:center;margin:14px 0 4px;color:var(--srg-ink,#2b3a4a)}
/* 卡片區住在 `#srg-pad` 裡（見 modes/trivia.js），高度由自己的內容決定 ——
   吃掉剩餘高度的是上面那塊 .srg-mode-body，這裡再 flex:1 就會跟它搶。 */
.srg-tv-pad{display:flex;flex-direction:column;justify-content:center}
/*
 * 卡片題的作答面板（`modes/trivia.js` 掛上 `.srg-pad-cards`）。
 *
 * 鍵盤與鼓的高度是**算出來的**（clamp/svh），卡片不是 —— 翻牌的牌照欄寬
 * 等比長高、排序題的列數隨題目變。橫放的手機上那些內容會被推出遊戲區，
 * 而 `.srg-root` 是 `overflow:hidden` → **推出去就按不到，而且看不出來**
 * （實測 640×360：翻牌最下面一排與排序題的「確定順序」都在畫面外）。
 * 所以這一塊要能縮、縮不下就自己捲。
 */
.srg-root.srg-playing .srg-pad-cards{flex:0 1 auto;min-height:0;overflow-y:auto}
/* 聽力題的播放列。按鈕要夠大（小朋友會重複按它），說明文字自己占一行。 */
.srg-tv-playbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:center;margin:6px 0}
.srg-tv-play{padding:6px 16px;font-size:15px}
.srg-tv-play:disabled{opacity:.55;cursor:default}
.srg-tv-playnote{flex:1 1 240px;text-align:center;font-size:13px;color:var(--srg-ink-soft,#6b6250)}
.srg-tv-playnote.bad{color:#b0524a}
.srg-tv-note{min-height:24px;text-align:center;font-size:14px;font-weight:600;margin:8px 0}
.srg-tv-note.ok{color:var(--srg-success,#2e7d4f)}
.srg-tv-note.bad{color:#b0524a}

.srg-cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;padding:8px}
.srg-card-btn{
  display:flex;flex-direction:column;gap:3px;align-items:center;justify-content:center;
  min-height:76px;padding:12px 14px;cursor:pointer;
  border:2px solid var(--srg-line,#c9bda0);border-radius:12px;
  background:var(--srg-paper,#fcf9f0);
  font-family:inherit;font-weight:600;font-size:16px;line-height:1.35;color:var(--srg-ink,#2b3a4a);
  transition:transform .1s,border-color .12s,background .12s;
}
.srg-card-btn:hover:not(:disabled){transform:translateY(-2px);border-color:var(--srg-glow,#c9a227)}
.srg-card-btn:disabled{cursor:default}
.srg-card-sub{font-size:12px;font-weight:400;opacity:.7}
/* 對錯用**顏色＋符號**兩個線索：只靠顏色的話色覺不同的玩家看不出來。 */
.srg-card-ok{border-color:var(--srg-success,#2e7d4f);background:#eaf5ee}
.srg-card-ok::after{content:'✓';color:var(--srg-success,#2e7d4f);font-size:20px;font-weight:800}
.srg-card-bad{border-color:#b0524a;background:#fbeeec}
.srg-card-bad::after{content:'✕';color:#b0524a;font-size:20px;font-weight:800}

/* 配對：左右兩欄。配好的留在畫面上標成已配，不消失——消失的話玩家沒辦法
   回頭檢查自己配了什麼，而且卡片一少版面就跳。 */
.srg-match{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:8px}
.srg-match-col{display:flex;flex-direction:column;gap:8px}
.srg-match-btn{
  padding:11px 12px;cursor:pointer;text-align:left;
  border:2px solid var(--srg-line,#c9bda0);border-radius:10px;
  background:var(--srg-paper,#fcf9f0);font-family:inherit;font-weight:600;font-size:15px;line-height:1.3;color:var(--srg-ink,#2b3a4a);
  transition:border-color .12s,background .12s,opacity .12s;
}
.srg-match-btn:hover:not(:disabled){border-color:var(--srg-glow,#c9a227)}
.srg-match-active{border-color:var(--srg-glow,#c9a227);background:#fff7e0;box-shadow:0 0 0 2px rgba(201,162,39,.3)}
/* 已配好：淡出，但**左卡仍可點**（那是解開這一對的唯一入口），所以不設 cursor:default。 */
.srg-match-done{opacity:.62}
.srg-match-btn[disabled]{cursor:default}
/* flex-wrap 是給揭曉時的「正解：…」用的（它 flex:0 0 100% 自成一行）。 */
.srg-match-btn{display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px}
.srg-match-text{flex:1;min-width:0}
/* 配對號碼：兩張卡掛同一個號碼，玩家才看得出自己把誰配給了誰。
   還沒配的時候是空的，但**位置要留著** —— 不留的話配上去那一刻整欄的字會橫移。 */
.srg-match-num{
  flex:0 0 auto;width:22px;height:22px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  font-family:inherit;font-weight:700;font-size:12px;line-height:1;color:var(--srg-ink,#2b3a4a);
  border:1px solid var(--srg-line,#c9bda0);background:#fff;
}
.srg-match-done .srg-match-num{border-color:var(--srg-glow,#c9a227);background:#fff7e0}
/* 揭曉時補在配錯的左卡上的正解。換行顯示，不要跟術語擠成一行。 */
.srg-match-fix{flex:0 0 100%;font-size:12px;font-weight:600;color:#b0524a;opacity:.95}
/* 揭曉之後號碼與正解要看得清楚，不能繼續套 .srg-match-done 的淡出。 */
.srg-match-btn.srg-card-ok,.srg-match-btn.srg-card-bad{opacity:1}
/* .srg-card-ok/.srg-card-bad 的 ::after 打勾打叉在配對卡上會擠在文字後面，
   改成靠右自成一格（flex 讓它排在最後）。 */
.srg-match-btn.srg-card-ok::after,.srg-match-btn.srg-card-bad::after{order:2;font-size:16px}
.srg-match-submit{display:block;margin:12px auto 0}

/* ---------- 記憶翻牌（大賢者之塔 trivia_task = memory）----------
   一組配對拆成兩張牌打散。整副牌**必須同時看得到**：要捲動才看得完的話，
   玩家記的就是捲軸位置而不是牌的位置，而那不是這個題型在練的東西。
   所以欄數由 JS 依張數指定（--srg-mem-cols），不用 auto-fit。 */
.srg-mem{
  display:grid;grid-template-columns:repeat(var(--srg-mem-cols,4),minmax(0,1fr));
  gap:8px;padding:8px;
  /* 牌桌要**置中並限寬**：整條 960px 的內容欄鋪滿的話，一張牌會有 300px 寬
     —— 那看起來不像牌，而且眼睛要掃過整個螢幕才看得完一列。
     560px 與樂譜的上限同一個數字（.srg-staff-svg），兩個地區的版面寬度一致。 */
  width:100%;max-width:min(100%,560px);margin:0 auto;
  /* 翻牌用真的 3D：背面與正面是同一張牌的兩面，淡入淡出看起來像換了一張卡。 */
  perspective:900px;
}
.srg-mem-card{
  position:relative;padding:0;cursor:pointer;
  /* 牌是直式的。比例寫在這裡而不是給固定高度：欄寬會隨畫面變，
     固定高度在窄畫面上會變成一排扁扁的長條（那不像牌）。 */
  aspect-ratio:3/4;min-height:64px;
  border:0;background:none;
  transform-style:preserve-3d;transition:transform .34s cubic-bezier(.2,.7,.3,1);
  /* 觸控上「hover 會變外觀」的元素要點兩下才送得出 click（見 AGENTS/CLAUDE.md
     找碴模式那一節），所以 hover 的樣式一律關在 @media (hover:hover) 裡。 */
  /*
   * ⚠ **`touch-action:none` 不是可有可無的**（2026-09-17 實機回報「點了不翻」）。
   *
   * `manipulation` 允許從這張牌開始捲動頁面，於是手指按下去只要滑了十幾個
   * 像素，瀏覽器就把這一下**判給捲動**：送出 `pointercancel`、
   * 不送 `pointerup`、**也不送 `click`**。實測（CDP 真觸控、Pixel 5）位移 16px
   * 時頁面只捲了 1px —— 玩家看不到畫面在動，只覺得「點了沒反應」。
   * 牌桌不需要當捲動面（遊戲畫面本來就設計成一個螢幕裝得下），
   * 空隙、題目區與頁首照樣捲得動。
   */
  touch-action:none;
}
.srg-mem-back,.srg-mem-face{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  /* **命中目標一律是那顆 <button> 本身。** 這兩層是 3D 旋轉過的
     （`backface-visibility:hidden`），而 3D 圖層的命中測試在不同引擎、
     不同 GPU 上結果不一樣 —— 實測 WebKit 手機上點到的是背面朝外的
     `.srg-mem-face`。讓它們不吃指標事件，誰在上面都無所謂。 */
  pointer-events:none;
  padding:8px;border-radius:12px;border:2px solid var(--srg-line,#c9bda0);
  backface-visibility:hidden;-webkit-backface-visibility:hidden;
  /* 牌面的字要跟著牌縮：一張牌上可能是 `Fortississimo`，也可能是
     「德國增六和弦」。字級寫死的話，窄畫面上長字會被裁掉一半。 */
  font-family:inherit;font-weight:600;font-size:clamp(11px,2.6vw,15px);line-height:1.25;color:var(--srg-ink,#2b3a4a);
  text-align:center;word-break:break-word;overflow:hidden;
}
.srg-mem-back{
  background:
    repeating-linear-gradient(45deg,rgba(255,255,255,.10) 0 6px,transparent 6px 12px),
    var(--srg-glow-dark,#6b5a2a);
  color:#fff;font-size:26px;
}
/* 牌面底圖（外觀設定頁的「記憶翻牌的牌面」）。**沒有內建那一張**：
   沒設定時就是上面那塊紙色底，那是字最好讀的底。
   `cover` 與牌背同一個理由 —— 整副牌要長得一樣。 */
.srg-mem-hasface .srg-mem-face{
  background:var(--srg-mem-face-img) center/cover no-repeat,var(--srg-paper,#fcf9f0);
}
/* 牌面的字。沒有底圖時完全透明（看起來跟以前一樣）；一旦有底圖就變成一塊
   半透明的紙把字墊起來 —— 深色照片上的深色字是真的讀不到，而那種失敗
   老師在後台的縮圖上看不出來（縮圖裡沒有字）。 */
.srg-mem-label{display:inline-block;max-width:100%;border-radius:8px}
.srg-mem-hasface .srg-mem-label{
  padding:3px 7px;
  background:rgba(var(--mh-surface-hi-rgb,255,251,240),.86);
  box-shadow:0 1px 6px -2px rgba(var(--mh-ink-rgb,43,58,74),.5);
}
/* 牌背圖（外觀設定頁的「記憶翻牌的牌背」，例如魔法水晶板）。
   `cover` 是刻意的：一整副牌要長得一模一樣，`contain` 會在牌的比例與圖不同時
   露出底色的邊，而那個邊在深色圖上看起來像「這幾張牌不一樣」。
   變數掛在牌桌上（一整副共用一張圖），沒設定時整條規則不存在＝退回上面的花紋。 */
.srg-mem-hasback .srg-mem-back{
  background:var(--srg-mem-back) center/cover no-repeat,var(--srg-glow-dark,#6b5a2a);
}
.srg-mem-face{
  background:var(--srg-paper,#fcf9f0);
  transform:rotateY(180deg);
}
.srg-mem-up{transform:rotateY(180deg)}
@media (hover:hover){
  .srg-mem-card:not(:disabled):hover .srg-mem-back{border-color:var(--srg-glow,#c9a227)}
}
/* 配對成功：留在正面、不再能點。顏色＋符號兩個線索（同 .srg-card-ok）。 */
.srg-mem-done{cursor:default}
.srg-mem-done .srg-mem-face{border-color:var(--srg-success,#2e7d4f);background:#eaf5ee}
/* 翻錯的那一瞬間：抖一下再翻回去。只靠顏色的話色覺不同的玩家看不出來，
   而這兩張牌 0.9 秒之後就不見了，來不及去對照圖例。 */
.srg-mem-miss .srg-mem-face{border-color:#b0524a;background:#fbeeec;animation:srg-mem-shake .3s}
/* 時間到才被揭曉的牌＝玩家沒找到的，淡一點並標成未完成。 */
.srg-mem-left .srg-mem-face{border-style:dashed;opacity:.72}
@keyframes srg-mem-shake{
  0%,100%{transform:rotateY(180deg) translateX(0)}
  25%{transform:rotateY(180deg) translateX(-4px)}
  75%{transform:rotateY(180deg) translateX(4px)}
}
/*
 * 洗牌 → 發牌。**每一題出題時都會跑一次**（使用者指定）。
 *
 * 位移量（--dx/--dy）是 JS 量出來的：每張牌的中心到整副牌中心的距離。
 * 寫死數字的話手機上牌會從畫面外飛進來 —— 欄數與牌的大小是隨寬度變的。
 * 期間整塊牌桌不可點（cards.js 的 locked），計時也還沒開始。
 */
/*
 * ⚠⚠ **`animation-fill-mode` 一定要是 `backwards`，不可以是 `both`。**
 *
 * 這是「牌點了不翻」找了三輪的真兇（2026-09-17 實機回報，最後是靠使用者說
 * 「觸控的瞬間牌面有藍色光芒」才抓到 —— 那是 tap highlight，證明點擊有到，
 * 只是畫面沒動）。
 *
 * `both` 會**保留最後一格**（`transform:none`），而動畫的值在層疊裡**贏過
 * 一般宣告** —— 於是 `.srg-mem-up{transform:rotateY(180deg)}` 永遠套不上去，
 * 牌的 computed transform 一直是 `matrix(1,0,0,1,0,0)`。
 * 狀態、class、判定、計分全部照跑（測試也全綠），只有**畫面**從來沒翻過。
 *
 * `backwards` 只在 delay 期間套 0%（那正是「還疊在中央」要的），
 * 動畫跑完就交還給一般樣式。連帶：初始的 `opacity:0` 也只能在
 * **還沒開始發牌**時套，否則動畫結束到 ready() 之間那幾十毫秒牌會閃掉。
 */
.srg-mem-dealing:not(.srg-mem-deal-go) .srg-mem-card{opacity:0}
.srg-mem-deal-go .srg-mem-card{
  animation:srg-mem-deal .34s ease-out backwards;
}
@keyframes srg-mem-deal{
  /* 0%～那一段都疊在中央（發牌之前的「一疊牌」），由 animation-delay 錯開。 */
  0%   {opacity:1;transform:translate(var(--dx,0),var(--dy,0)) rotate(var(--dr,0)) scale(.86)}
  100% {opacity:1;transform:none}
}
/* 疊在中央那一疊要先左右抖動（洗牌）。牌桌自己動，牌不必各動各的。 */
.srg-mem-dealing.srg-mem-deal-go{animation:srg-mem-shuffle var(--shuffle-ms,620ms) ease-in-out}
@keyframes srg-mem-shuffle{
  0%,100%{transform:translateX(0)}
  20%{transform:translateX(-7px) rotate(-1deg)}
  45%{transform:translateX(7px) rotate(1deg)}
  70%{transform:translateX(-4px)}
}
/* 系統設定關掉動畫時**整段不演**（cards.js 也會把發牌時間設成 0，兩邊要一致）：
   這裡只負責讓牌不要卡在 opacity:0。 */
@media (max-width:600px){
  /* 窄畫面夾到 4 欄（5 欄時一張牌只剩 60px，中文會被擠成一行一個字）。 */
  .srg-mem{grid-template-columns:repeat(var(--srg-mem-cols-narrow,4),minmax(0,1fr));gap:6px;padding:4px}
}
@media (prefers-reduced-motion:reduce){
  .srg-mem-dealing:not(.srg-mem-deal-go) .srg-mem-card{opacity:1}
  .srg-mem-deal-go .srg-mem-card{animation:none}
  .srg-mem-dealing.srg-mem-deal-go{animation:none}
  .srg-mem-card{transition:none}
}

/* 排序：一列一項，左邊是拖曳握把、右邊是上下移。 */
.srg-rank-list{display:flex;flex-direction:column;gap:8px;padding:8px}
.srg-rank-row{
  display:flex;align-items:center;gap:10px;padding:10px 12px;
  border:2px solid var(--srg-line,#c9bda0);border-radius:10px;
  background:var(--srg-paper,#fcf9f0);font-family:inherit;font-weight:600;font-size:15px;line-height:1.3;color:var(--srg-ink,#2b3a4a);
}
.srg-rank-grip{cursor:grab;opacity:.5;font-size:18px;touch-action:none}
.srg-rank-text{flex:1;min-width:0}
/* 中文意思：跟著術語同一列的第二行。**不是另一欄** —— 兩欄會讓長短不一的
   中文把術語擠成不同寬度，而玩家是照著術語在排順序的。 */
.srg-rank-sub{display:block;font-size:12px;font-weight:400;opacity:.7}
.srg-rank-move{
  border:1px solid var(--srg-line,#c9bda0);border-radius:6px;background:#fff;
  width:30px;height:28px;cursor:pointer;font-size:11px;color:var(--srg-ink,#2b3a4a);
}
.srg-rank-move:hover{background:#f4efe2}
.srg-rank-submit{display:block;margin:14px auto 0}
.sortable-ghost{opacity:.35}

@media (max-width:600px){
  .srg-cards-grid{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}
  .srg-card-btn{min-height:64px;font-size:15px;padding:10px}
  .srg-match{gap:6px}
  .srg-match-btn{font-size:14px;padding:9px 10px}
}

/* ==================== 節奏（貝絲之國／遺忘的洞窟）==================== */
/* 純節奏題的訊息與旋律題共用 `.srg-rh-bar`（見上面「節奏題」那一段），
   所以這裡只補「對／錯」兩個顏色，不再重設字級與置中 ——
   重設會讓同一列裡的文字比旁邊的按鈕還大，整列高度跳一階。 */
.srg-rh-msg.ok{color:var(--srg-success,#2e7d4f);font-weight:700}
.srg-rh-msg.bad{color:#b0524a;font-weight:700}
/*
 * v1.69.0：純節奏題的譜面改用**與旋律題同一套容器**
 * （`.srg-staff-wrap` > `.srg-staff-canvas` > `.srg-staff-svg`），
 * 游標也改成畫在 `<svg>` 裡的 `.srg-cursor`。
 * 舊的 `.srg-rh-staves` / `.srg-rh-row` / `.srg-rh-cursor` 已經沒有人用，
 * 連同它們的樣式一起刪掉 —— 留著只會讓下一個人以為節奏題有第二套版面。
 */
/* （v2.47.0：`.srg-rh-mic` 沒有了 —— 那顆「🎤 用樂器回答」的切換鈕搬到
   進關卡片上變成「畫面上的鼓／用樂器」二選一，見 modes/rhythm.js 的
   `answerChoices`。控制列上只剩「開始」，288px 的手機上那一格寬度是搶來的。） */
/* align-items:stretch 讓同一列的按鈕一樣高 —— 字級與內距不同時，置中對齊
   會讓它們上緣差幾個 px，看起來像沒對齊（而且「同一列」就變得難以斷言）。 */
.srg-rh-btns{display:flex;align-items:stretch;gap:8px;flex:0 0 auto;flex-wrap:nowrap}
/* 答完一題之後的三顆鈕（重打／聽答案／下一題）。窄畫面上它們可以換行 ——
   三顆一起 nowrap 會把「下一題」擠出畫面，那是唯一往前走的出口。 */
.srg-rh-done{flex-wrap:wrap}
.srg-rh-done:empty{display:none}
/* （v2.36.0：`#srg-pad > .srg-rh-legend` 那組規則沒有了 —— 成績那一行與
   顏色圖例都搬進樂譜卡片內的 `.srg-staff-report`。位置一樣是「樂譜正下方」，
   差別在**底**：pad 的底是關卡背景圖，色塊印在畫上就分辨不出顏色。） */
.srg-rh-micnote{flex:1 1 240px;text-align:center;font-size:13px;line-height:1.4;
  color:var(--srg-ink-soft,#6b6250)}
/* 沒話要說的時候不要佔一列：空字串仍然是個 flex 項目，
   在窄畫面會把自己撐成一整行的空白。 */
.srg-rh-micnote:empty{display:none}
.srg-rh-micnote.bad{color:#b0524a}

/* 兩顆鼓。**用 pointerdown 不用 click**（見 ui/pads/drum.js），
   所以這裡也要 touch-action:manipulation 把瀏覽器的雙擊縮放判定關掉。
   面板本身住在 `#srg-pad` 裡（與鍵盤同一格），所以這裡不再自己搶垂直空間。 */
.srg-rh-pad{width:100%}
/* 上內距只有 4px：鼓的上面就是控制列，兩邊各留 10px 會疊成一道 20px 的空白帶。 */
.srg-drums{display:flex;gap:16px;justify-content:center;align-items:stretch;padding:4px 6px}
/* 說明在鼓的**外側**（左鼓在左、右鼓在右），不是壓在鼓下面：
   ①往下疊會吃掉樂譜的高度，而節奏譜常常排到三行；
   ②玩家的視線在「上排／下排」與「哪一顆鼓」之間來回，貼外側正好落在兩端。 */
.srg-drum{
  flex:1;max-width:240px;min-height:96px;
  display:flex;flex-direction:row;align-items:center;justify-content:center;gap:10px;
  border:2px solid var(--srg-line,#c9bda0);border-radius:16px;
  background:radial-gradient(circle at 50% 35%, #fff8e6, var(--srg-paper,#f2e8cf));
  cursor:pointer;touch-action:manipulation;user-select:none;
  box-shadow:0 3px 0 rgba(0,0,0,.12), inset 0 -3px 6px rgba(0,0,0,.06);
  transition:transform .07s, box-shadow .07s;
}
.srg-drum:active,.srg-drum-lit{
  transform:translateY(2px);
  box-shadow:0 1px 0 rgba(0,0,0,.12), inset 0 0 18px rgba(201,162,39,.55);
}
/* 鼓面。內建向量鼓與老師自訂的圖佔一模一樣的框，換圖不會讓版面跳動。
   emoji 只是第三層退路（連 SVG 都建不起來時），font-size 為它留著。 */
.srg-drum-face{font-size:38px;line-height:1;width:64px;height:64px;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center}
.srg-drum-svg,.srg-drum-img{width:100%;height:100%;display:block;
  object-fit:contain;pointer-events:none}
/* 自訂圖不一定有陰影，補一道投影讓它跟內建鼓一樣立體。 */
.srg-drum-img{filter:drop-shadow(0 2px 2px rgba(0,0,0,.18))}
/* 主標（排數）與副標（要演奏的音）上下疊在鼓的外側。 */
.srg-drum-label{display:flex;flex-direction:column;align-items:center;gap:2px;
  font-size:13px;font-weight:700;line-height:1.2;color:var(--srg-slate,#5a6b7d)}
.srg-drum-label b{font-weight:700}
.srg-drum-pitch{font-style:normal;font-size:12px;font-weight:700;
  padding:1px 7px;border-radius:8px;white-space:nowrap;
  background:rgba(0,0,0,.06);color:var(--srg-navy,#2b3a4a)}
.srg-drum-hint{width:100%;text-align:center;font-size:12px;color:var(--srg-slate,#5a6b7d)}
/* 左鼓的說明翻到左邊、右鼓的留在右邊 —— 兩段文字因此落在整組面板的最外側。 */
.srg-drum-l{flex-direction:row-reverse}
/* 單排時兩顆一樣（敲哪邊都算），兩排時左右顏色分開才對得上上下兩行譜。 */
.srg-drums-two .srg-drum-r{border-color:#7fa8c9}
.srg-drums-two .srg-drum-l{border-color:#c99a7f}

@media (max-width:600px){
  .srg-drums{gap:8px;padding:4px}
  .srg-drum{min-height:76px;gap:7px}
  .srg-drum-face{font-size:30px;width:48px;height:48px}
  .srg-drum-label{font-size:12px}
  .srg-drum-pitch{font-size:11px;padding:1px 5px}
}

/* ==================== 聽音（風靈高原）==================== */
.srg-ear-prompt{text-align:center;font-size:19px;font-weight:700;margin:14px 0 6px;color:var(--srg-ink,#2b3a4a)}
/* 一個音一個圓點，播到哪一個亮哪一個 —— 玩家才知道「還有幾個音要聽」。 */
.srg-ear-dots{display:flex;gap:8px;justify-content:center;margin:8px 0}
.srg-ear-dot{width:11px;height:11px;border-radius:50%;background:var(--srg-line,#c9bda0);
  transition:background .12s,transform .12s}
.srg-ear-dot.on{background:var(--srg-glow,#c9a227);transform:scale(1.25)}
.srg-ear-replay{display:block;margin:10px auto}
.srg-ear-note{min-height:24px;text-align:center;font-size:14px;font-weight:600;margin:6px 0}
.srg-ear-note.ok{color:var(--srg-success,#2e7d4f)}
.srg-ear-note.bad{color:#b0524a}

/* ============ 出題動畫（「聽單音辨認」與「聽音選擇」）============
 *
 * 魔獸吹奏樂器、噴出一個音符；噴出那一刻題目發聲、作答面板才亮起來。
 * 兩個子題型的題目都是**一個音**，所以共用同一座舞台；差別只在面板是
 * 鍵盤（single）還是卡片（choice）。
 * 行為與時間點在 `public/ui/ear-stage.js`，這裡只管它長什麼樣。
 *
 * **內建影片是 480×608 的直式**，底色 #F7F3E9（逐格取樣量出來的）——與羊皮紙
 * 同一家族，所以舞台底色刻意配成它，`object-fit:contain` 留白時才不會出現
 * 一圈明顯的色差方框。有動畫時題幹降級成舞台底下的說明字（見 modes/ear.js）。 */
/*
 * ## 舞台的高度只能來自「確定值」，而 flex 算出來的高度不算
 *
 * 第一版寫成 `width:100%` ＋ `max-width:32svh`，高度交給 `aspect-ratio` 推導。
 * 那是錯的：host 是可收縮的 flex 項目，空間不夠時它會縮，**但舞台的高度是從
 * 自己的寬度算出來的，不會跟著縮** —— 於是舞台比 host 高，再被
 * `align-items:center` 上下各推出去一半。實測 393×740：host 只拿到 247px、
 * 舞台卻是 300px，底緣 461 壓在題幹頂端 448 上面，
 * **影片蓋住「這是哪一個音？」**（2026-09-06 使用者回報）。
 *
 * 第二版改成 `height:100%` ＋ `width:auto`，想讓高度跟著 host 走。
 * **那也是錯的，而且更糟**（舞台反而變成 252×319）：host 的高度是 flex 算出來的，
 * 拿它解析子元素的百分比高度並不可靠 —— 百分比退化成 auto，於是又掉回
 * 「由 max-width 決定寬度、由寬度決定高度」那條路。
 * v1.22.0 為了同一件事把樂譜容器改成 `position:absolute;inset:0`，這裡是同一個坑。
 *
 * 所以分成兩條各自確定的路：
 *   直排（手機）  host 只靠 flex-grow 拿高度（`flex:1 1 0`，不看內容），
 *                 舞台 `position:absolute;inset:0` —— 絕對定位的包含塊高度
 *                 一定是確定值，`height:100%` 於是真的解析得出來，永不溢出。
 *   分欄（桌機）  見下面的 media query：`.srg-mode-body` 是 grid 項目、高度依內容，
 *                 絕對定位會讓 host 失去內容高度、整列塌成 0，所以那邊**改回**
 *                 一般流排版、由寬度決定大小（實測 414×524，本來就沒有重疊）。
 */
.srg-ear-stage-host{
  position:relative;display:flex;align-items:center;justify-content:center;
  min-height:0;flex:1 1 0;
}
.srg-ear-stage{
  position:absolute;inset:0;margin:auto;
  /* 長寬比是**影片量出來的**（ui/ear-stage.js 在 loadedmetadata 寫 --srg-stage-ar）。
     這裡的 480/608 只是第一支影片的退回值：量不到時維持舊行為，量到了就跟著走
     —— 比例對不上的影片會被 object-fit:contain 留一道底色邊，而那道邊看起來
     像版面壞了。 */
  height:100%;width:auto;aspect-ratio:var(--srg-stage-ar, 480 / 608);
  max-width:100%;
  border-radius:16px;overflow:hidden;
  background:#f7f3e9;border:2px solid var(--srg-line,#c9bda0);
  box-shadow:0 6px 18px rgba(0,0,0,.10);
}
/*
 * 保險：題幹、重聽鈕與回饋字疊在舞台**之上**。
 *
 * 上面修好之後舞台不該再溢出，但這一條的成本是一行 CSS，而它擋掉的是
 * 「玩家看不到題目在問什麼」—— 這一題唯一的文字說明。
 * **不用 `overflow:hidden` 擋**：那會把 `.cued` 那道往外漫的金光一起裁掉。
 */
.srg-ear-prompt,.srg-ear-replay,.srg-ear-note{position:relative;z-index:1}
.srg-ear-stage-vid,.srg-ear-stage-still{display:block;width:100%;height:100%;object-fit:contain}
/* 音符噴出的那一刻閃一道金光。**這是唯一把「動畫」與「卡片可以按了」接起來的
   訊號** —— 玩家的視線這時候正要從舞台移到卡片上。 */
.srg-ear-stage.cued::after{
  content:'';position:absolute;inset:0;border-radius:14px;pointer-events:none;
  box-shadow:inset 0 0 0 3px var(--srg-glow,#c9a227),0 0 26px var(--srg-glow-soft,#e8c765);
  animation:srg-ear-cue .62s ease-out forwards;
}
@keyframes srg-ear-cue{from{opacity:1}to{opacity:0}}

/* 還不能按的面板（卡片與鍵盤各一個 class，因為兩者的按鈕不同）。
   **用 opacity + pointer-events 而不是 `disabled`**：
   `disabled` 會把按鈕移出 Tab 序列，鍵盤使用者在解鎖前後會看到焦點整個跳走；
   這裡的語意是「先別按」不是「這顆按鈕不存在」。真正擋住作答的是
   `grid.dataset.locked`（cards.js 判斷「已經答過了」的同一個旗標）與
   `onKey` 開頭的 `st.locked`，見 modes/ear.js 的 lockPad —— 樣式只負責
   讓玩家看得出來。 */
.srg-cards-wait,.srg-keys-wait{transition:opacity .18s}
.srg-cards-wait .srg-card-btn,
.srg-keys-wait .srg-ear-key,
/* 鋼琴面板（關卡指定「只能使用鍵盤」時的聽音題）。**白鍵黑鍵都要挑到**：
   只寫 .srg-white 的話黑鍵仍然亮著而且按得下去，等於鎖了一半。 */
.srg-keys-wait .srg-white,
.srg-keys-wait .srg-black{opacity:.42;pointer-events:none;transform:none}

/* ---- 桌機分欄：舞台在左、作答面板在右 ----
 *
 * 直式影片疊在面板上方會把畫面拉得很長（寬螢幕上要捲動才看得到卡片），
 * 而那時候左右兩側本來就空著。切換點 820px：再窄的話兩欄各自都不夠寬。
 *
 * **`.srg-content` 在遊戲中原本是 flex column**（見上面的 `.srg-playing`），
 * 這裡整個換成 grid。魔王舞台也是它的子元素、而且不一定存在，所以規則寫成
 * 「預設每個子元素都整列跨欄，只有題目區與作答面板指名欄位」——
 * 改用具名 grid-template-areas 的話，沒有魔王的關卡會多出一個空的列。 */
@media (min-width:821px){
  .srg-root.srg-playing.srg-ear-split .srg-content{
    display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    column-gap:20px;align-content:start;
  }
  .srg-root.srg-playing.srg-ear-split .srg-content > *{grid-column:1 / -1}
  .srg-root.srg-playing.srg-ear-split .srg-mode-body{
    grid-column:1;overflow:visible;justify-content:flex-start;
  }
  /* 指名第 2 欄 → 稀疏排列會找「游標之後第一個第 2 欄還空著的列」，
     也就是 .srg-mode-body 剛佔掉第 1 欄的那一列。 */
  .srg-root.srg-playing.srg-ear-split #srg-pad{grid-column:2;align-self:center;margin-top:0}
  /*
   * **分欄時給 host 一個定高，舞台在裡面等比縮到放得下。**
   *
   * 這裡換過兩版，第二版是 v2.65.0 量出來才發現的：
   *
   * 1. `position:absolute;inset:0` ＋ 讓 host 的高度依內容 —— 不行。
   *    絕對定位的舞台不貢獻內容高度，整個 grid 列會塌成 0。
   * 2. 改成一般流、`width:100%;max-width:min(100%,46svh)`、高度交給
   *    `aspect-ratio` —— **只對當時那一支影片成立**。長寬比變成設定（跟著
   *    影片走）之後，直一點的影片算出來的高度就超出 host：host 是可收縮的
   *    flex 項目（`flex:0 1 auto`）會縮，舞台不跟著縮，於是溢出去壓在題幹上。
   *    實測 416×640 的詠唱動畫在 1280×900：舞台底緣 659、題幹頂端 649，
   *    壓住 10px。**桌機才會，直排完全正常** —— 與 v2.25.1 的手機版剛好相反。
   * 3. 對的：**host 有定高**（58svh，挑這個數字是為了讓既有的 480/608 維持
   *    原本的 414×524），舞台回到「`inset:0` ＋ `margin:auto` ＋ `height:100%`
   *    ＋ `width:auto`」—— 那是「任何長寬比都剛好裝進一個已知的盒子」的
   *    標準寫法，與直排那一套同一招（v1.22.0 的樂譜容器也是這樣修的）。
   *    host 有定高就貢獻得出高度，第 1 版那個塌成 0 的問題不會回來。
   */
  .srg-root.srg-playing.srg-ear-split .srg-ear-stage-host{
    position:relative;flex:0 0 auto;height:58svh;
  }
  .srg-root.srg-playing.srg-ear-split .srg-ear-stage{
    position:absolute;inset:0;margin:auto;
    height:100%;width:auto;max-width:100%;
  }
  /* 欄寬減半之後四張卡擠成一排會太瘦，改成兩欄兩列。 */
  .srg-root.srg-playing.srg-ear-split .srg-cards-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* 鍵盤區住在 `#srg-pad` 裡（見 modes/ear.js），已經在畫面下緣，
   不必再用 margin-top:auto 把自己推下去。 */
.srg-ear-pad{margin-top:0}
.srg-ear-keys{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;padding:10px 6px}
.srg-ear-key{
  min-width:58px;min-height:52px;padding:8px 12px;cursor:pointer;
  border:2px solid var(--srg-line,#c9bda0);border-radius:10px;
  background:var(--srg-paper,#fcf9f0);font-family:inherit;font-weight:700;font-size:15px;line-height:1.2;color:var(--srg-ink,#2b3a4a);
  transition:transform .08s,border-color .12s,background .12s;
}
.srg-ear-key:hover:not(:disabled){transform:translateY(-2px);border-color:var(--srg-glow,#c9a227)}
.srg-ear-key-picked{background:#fff7e0;border-color:var(--srg-glow,#c9a227)}
/* 對錯用顏色＋符號兩個線索（同卡片面板）。 */
.srg-ear-key-ok{border-color:var(--srg-success,#2e7d4f);background:#eaf5ee}
.srg-ear-key-ok::after{content:' ✓'}
.srg-ear-key-bad{border-color:#b0524a;background:#fbeeec}
.srg-ear-key-bad::after{content:' ✕'}
@media (max-width:600px){
  .srg-ear-key{min-width:48px;min-height:46px;font-size:14px;padding:6px 8px}
}

/* ==================== 長樂譜（奧托之地的課後練習）====================
 *
 * 小節數上限自 v1.60.0 由 4 放寬到 32。**長譜不縮小，改成捲動跟隨**。
 *
 * 舊版靠 `.srg-staff-svg svg{max-height:100%}` 硬把整張譜塞進一個畫面，
 * 於是四小節在手機上被等比壓到原尺寸的 43–53%（線距只剩 5.6px，正常 13px）。
 * 那個作法的前提是「一定要一眼看完」，而課後練習用的長樂譜本來就不是那樣看的。
 *
 * `.srg-long-score` 由 game.js 在譜真的排到多行時掛上。
 */
.srg-root.srg-playing .srg-long-score .srg-staff-canvas{
  overflow-y:auto;
  /* 慣性捲動；同時讓瀏覽器知道這一塊是可以直向捲的（避免與頁面捲動打架）。 */
  -webkit-overflow-scrolling:touch;
  overscroll-behavior-y:contain;
  /*
   * **這個 overflow 會裁掉刻意畫在音符上方的東西**（見本檔「特效層」那段的
   * 警告）。`+N` 加分浮字是 top:-30px，最上面那一行的音符會被切掉；
   * 補一段上內距把它救回來（下方交給 ::after 的漸層，不另外加）。
   * 鼓勵詞橫幅完全在盒子外，padding 救不了，改由 game.js 的 spawnBanner()
   * 掛到 .srg-staff-wrap 上（見 .srg-fx-banner-in）。
   */
  padding-top:32px;
}
/* 解除高度上限 —— 這一行就是「不再壓小」的全部意思。 */
.srg-root.srg-playing .srg-long-score .srg-staff-svg svg{max-height:none}

/* 捲動時上下緣給一點漸層，暗示「還有東西在外面」。
   純視覺，不攔事件。 */
.srg-long-score .srg-staff-canvas::after{
  content:'';position:sticky;bottom:0;display:block;height:14px;
  background:linear-gradient(to top, rgba(var(--mh-surface-rgb,244,234,210),.9), transparent);
  pointer-events:none;
}

/* ── 找碴模式（聽演奏、點出跟譜不一樣的音）─────────────────────────
 *
 * 命中框與標記圈都畫在樂譜的 <svg> 裡（與音符共用座標系），所以這裡只管
 * 外觀與滑鼠行為，位置一律由 modes/spot.js 用 user units 設好。
 */
.srg-notehit {
  fill: transparent;
  /* 透明的 <rect> 預設仍然可以被點到，但明寫比較不會被別人「順手清掉」。 */
  pointer-events: all;
  cursor: pointer;
  /* 觸控時不要等 300ms 的雙擊判定，也不要把點擊當成手勢的開頭。 */
  touch-action: manipulation;
}

/*
 * ⚠ **hover 樣式只給真的有滑鼠的裝置。**
 *
 * 觸控螢幕上，瀏覽器對「hover 會改變外觀」的元素實作的是
 * **第一下套用 hover、第二下才送出 click**。於是玩家看到的是
 * 「第一次點只有框、要點第二次才出現圓圈」（2026-09-02 實機回報，
 * 這台機器是二合一觸控機）。用 `@media (hover: hover)` 關掉之後，
 * 觸控裝置沒有 hover 樣式可套，第一下就直接是 click。
 *
 * 這件事**在 Playwright 裡重現不出來**（合成滑鼠沒有觸控的那套規則），
 * 所以守門員是下面的 `.is-marked`：選取狀態不依賴 hover 就看得見。
 */
@media (hover: hover) and (pointer: fine) {
  .srg-notehit:hover { fill: rgba(47, 107, 214, .10); }
}

/*
 * 選取狀態畫在命中框本身（不只符頭上的圓圈）。
 * 使用者要的是「點一次就同時出現框和圓圈」—— 框自己有狀態之後，
 * 就算某個裝置的 hover 行為很怪，玩家仍然看得出這一個被選中了。
 */
.srg-notehit.is-marked {
  fill: rgba(229, 149, 0, .16);
  stroke: rgba(229, 149, 0, .9);
  stroke-width: 1.5;
}
.srg-notehit:focus-visible {
  outline: none;
  fill: rgba(47, 107, 214, .16);
  stroke: rgba(47, 107, 214, .75);
  stroke-width: 1.5;
}
/* 標記圈與游標都不吃點擊，否則會擋住底下的命中框。 */
.srg-spot-marks { pointer-events: none; }
.srg-spot-mark { pointer-events: none; }

.srg-spot-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: center;
  padding: 6px 0;
}
.srg-spot-note {
  flex: 1 1 100%;
  text-align: center;
  font-size: .92em;
  opacity: .85;
  min-height: 1.4em;
}

/* ===== 關卡卡片的狀態 =====
   **只加左邊那一道邊，不整張換底色**（只有「下一關」例外，它要被一眼看到）——
   卡片底色同時扛著「這是一張卡」與羊皮紙，換掉就少了一層。
   顏色**與亮度**都要不同：只靠色相區分對色弱使用者無效。
   實測相對亮度 plum .078 < success .293 < honey .699，兩兩間距 > .05。
   每個 var() 都帶 fallback：mh-theme.css 沒載到時三條會一起退回 currentColor，
   那時三種狀態長得一模一樣而且沒有任何東西會報錯。 */
.srg-level-btn{border-left:5px solid rgba(var(--mh-ink-rgb,28,28,23),.18)}
/* **選擇器要帶 `.srg-level-btn`。** 既有的 `.srg-level-btn.srg-boss-lv` 是
   兩個 class（特異度 0,2,0），單寫 `.srg-lv--boss`（0,1,0）**整條是死的** ——
   顏色仍然由那條舊規則決定，而測試會因為舊規則剛好也夠暗而全綠。
   排序 done → boss → next：一張卡可能同時是魔王關，這時要被看到的是
   「就是這一關」。 */
.srg-level-btn.srg-lv--done{border-left-color:var(--mh-success,#4fa46a)}
.srg-level-btn.srg-lv--boss{border-left-color:var(--mh-plum,#684362)}
.srg-level-btn.srg-lv--next{border-left-color:var(--mh-honey,#fed65b);
  background:rgba(254,214,91,.22)}
.srg-lv-next-flag{font-size:9.5px;font-weight:700;letter-spacing:.2em;
  color:var(--mh-gold-ink,#735c00)}
/* ★ 用實心／空心兩種字元而不是三顆圖示：它要能一眼數出來，
   而且 0 顆星時仍然佔同樣的寬度（版面不會跳）。 */
.srg-lv-stars{font-size:11px;letter-spacing:.04em;color:var(--mh-gold-ink,#735c00)}
/* 徽章與狀態旗標裡的圖示：跟著文字的基線走，不要自己撐高一行。 */
.srg-lvbadge{display:inline-flex;align-items:center;gap:4px;vertical-align:-.15em}
.srg-level-btn .srg-boss-flag,.srg-level-btn .srg-done-flag,
.srg-level-btn .srg-lock-flag,.srg-level-btn .srg-soon-flag,
.srg-level-btn .srg-plan-flag{display:flex;align-items:center;gap:5px}

/* ===== 小分類 accordion（使用者 2026-09-29 指定：以小分類為標籤） =====
   收合由 `aria-expanded` 驅動，**不另外加 class** —— 兩個真相來源遲早會不一致，
   而 aria-expanded 本來就必須是對的（螢幕閱讀器在讀它）。
   按鈕在 h3 裡面，所以 .srg-cat-body 不是它的兄弟，要從外層的 .srg-cat-head
   用 :has() 往下判斷。Chrome/Edge/Safari 都支援，測試也跑 chrome channel。 */
.srg-cat-head:has(.srg-cat-l3-btn[aria-expanded="false"]) + .srg-cat-body{display:none}
/* 折疊列要整列都好按（44px 是觸控下限），所以按鈕撐滿 h3，
   h3 退成中性容器、字級規則留在 .srg-cat-name 上（字級遞減的斷言靠它）。 */
.srg-cat-l3 .srg-cat-name{margin:0}
.srg-cat-fold-btn{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;
  padding:0;text-align:left;cursor:pointer;border:none;background:none;
  font:inherit;color:inherit}
.srg-cat-fold-btn .srg-ico{flex:0 0 auto;opacity:.75}
.srg-cat-fold-name{min-width:0;overflow-wrap:break-word}
/* 收起來的時候，進度就是這一段唯一看得到的資訊。 */
.srg-cat-prog{flex-shrink:0;font-size:14px;font-weight:700;color:var(--srg-navy);
  font-variant-numeric:tabular-nums}
.srg-cat-body{margin-top:6px}

/* 「接下來」卡。整頁最大的一塊。
   紋章織紋當浮水印壓在底下：**用 background-image 疊在底色上而不是換底色** ——
   卡片底色同時扛著「這是一張卡」與「羊皮紙」，換掉就少了一層。
   相對 url() 是相對這份樣式表解析的，所以固定檔名直接寫就好（見 v2.55.0）。 */
.srg-continue{position:relative;overflow:hidden;margin:12px 0 0;padding:15px 16px 16px;
  border:1px solid rgba(var(--mh-gold-rgb),.8);border-radius:var(--mh-radius-lg);
  background-color:var(--mh-paper);background-image:url(assets/cat/weave.svg);
  background-size:28px 28px;box-shadow:var(--mh-shadow-card)}
.srg-continue-eyebrow{margin:0;display:flex;align-items:center;gap:7px;
  font-size:10.5px;font-weight:700;letter-spacing:.22em;color:var(--mh-gold-ink)}
.srg-continue-title{margin:5px 0 0;font-family:var(--mh-serif);
  font-size:clamp(20px,6vw,25px);font-weight:700;line-height:1.2;color:var(--mh-ink);
  /* 關卡標題是老師自己命名的字串，可能是一長串沒有空白的拉丁字（匯入題的檔名
     就長那樣）。少了這一條，288px 上它會撐破卡片然後被 .srg-root 的
     overflow:hidden 裁掉 —— **頁面不會長出捲軸，字是直接不見**（實測溢出 370px，
     而 documentElement 的捲動量仍然是 0）。 */
  overflow-wrap:break-word}
.srg-continue-path{margin:4px 0 0;font-size:11.5px;color:var(--mh-muted);overflow-wrap:break-word}
.srg-continue-scope{display:flex;flex-wrap:wrap;gap:5px;margin-top:11px}
/* 蠟封印章。尺寸規範與 .srg-splash-cta／.srg-auth-cta 同一份 —— 玩家是按了
   那兩顆才走到這裡，差一點換頁時就看得出在跳。 */
.srg-continue-cta{display:flex;align-items:center;justify-content:center;gap:9px;
  width:100%;min-height:56px;margin-top:13px;cursor:pointer;
  border:2px solid var(--mh-seal-edge);border-radius:var(--mh-radius-pill);
  background:radial-gradient(circle at 30% 28%,var(--mh-seal-a),var(--mh-seal-b));
  color:var(--mh-on-primary);font-family:var(--mh-serif);
  font-size:clamp(17px,5vw,20px);font-weight:700;letter-spacing:.12em;
  box-shadow:0 10px 26px -9px rgba(0,0,0,.6),inset 0 2px 0 rgba(255,255,255,.18);
  text-shadow:0 2px 6px rgba(0,0,0,.45)}

/* 傳奇榜摘要那張卡。**位置在玩家卡與關卡列表之間**（見 game.js 的 lbCard），
   所以上下都要留白 —— 以前它在頁尾，只有 margin-top 就夠了。 */
.srg-lb-card{margin:14px 0 18px}
.srg-lb-card h3{display:flex;align-items:center;gap:8px;font-size:20px;color:var(--srg-navy);margin-bottom:6px}
/* 內嵌圖示不可以被壓扁。標題在 288px 底下會換行，沒有 flex:0 0 auto
   獎盃就會被擠成一條線。 */
.srg-ico{flex:0 0 auto}
/* 地圖上那三顆按鈕：另外兩顆仍然是 emoji，所以這顆的圖示要跟文字對齊，
   否則三顆並排時只有它的字往上飄。 */
.srg-btn .srg-ico{vertical-align:-.22em;margin-right:6px}

/* ================= 多榜排行榜（平台元件的羊皮紙皮） =================
 * DOM 與行為都在 music-hub/public/mh-leaderboard.{js,css}（三個入口共用一份）。
 * 這裡**只換配色**——版面留給平台那一份，兩邊各寫一份版面遲早會分岔。
 * 全部限定在 `.srg-root` 底下：玩家資料頁與獨立排行榜頁不該被遊戲的皮影響。
 */
.srg-root .mh-lb-tab{
  border-color:var(--srg-ochre);
  background:rgba(255,255,255,.55);
  color:var(--srg-navy);
  font-family:inherit;
}
.srg-root .mh-lb-tab:hover{border-color:var(--srg-navy)}
.srg-root .mh-lb-tab.is-on{
  background:var(--srg-navy);
  border-color:var(--srg-navy);
  color:var(--mh-surface,#f4ead2);
}
.srg-root .mh-lb-cat{font-family:inherit}
.srg-root .mh-lb-table th,
.srg-root .mh-lb-table td{
  border-bottom:1px dashed var(--srg-ochre);
  font-size:14px;
}
/* 名次與數字沿用選單卡片的深藍，不要用平台的中性灰。 */
.srg-root .mh-lb-table th{color:var(--srg-navy);opacity:.75}
.srg-root .mh-lb-me{background:rgba(var(--mh-gold-rgb,201,168,106),.22);font-weight:700}
.srg-root .mh-lb-you{
  background:var(--srg-ochre);color:#2b1d0e;
  font-size:11px;padding:0 6px;border-radius:8px;
}
.srg-root .mh-lb-face{background:rgba(var(--mh-ink-rgb,43,58,74),.10)}

/* ==================================================================
 * 關卡列表 v2.60.0（2026-10-05，設計稿 music_game_level_map_demo）
 *
 *   地區列（sticky：← 回地圖＋地名）→ 地區名牌＋進度條 → 全部展開／收起
 *   → 每個小分類是一張折疊卡（紋章格｜名稱＋說明｜n/m｜圓形箭頭）
 *   → 卡片裡的關卡是橫列（編號格｜標題＋說明｜狀態）。
 *
 * 規則都寫在這一段、排在檔尾，靠「同特異度後者勝」蓋過上面的格狀卡片規則；
 * 每一條都比照原規則的選擇器寫，**不要為了蓋過去而加特異度** ——
 * 那會讓下一個改版的人再加一層（v2.59.0 的 .srg-lv--boss 就是這樣死掉的）。
 * ================================================================== */

/* ---- 地區列：黏在上緣 ---- */
.srg-map-back.srg-region-bar{position:sticky;top:0;z-index:5;
  margin:0 0 14px;padding:10px 12px;border-radius:16px;flex-wrap:nowrap;
  background:rgba(var(--mh-surface-rgb,244,234,210),.92);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  border:1px solid var(--srg-border);
  box-shadow:0 6px 16px -12px rgba(var(--mh-ink-rgb,43,58,74),.45)}
.srg-region-bar .srg-map-back-btn{flex:0 0 auto;min-height:44px}
.srg-region-bar .srg-map-back-where{min-width:0;overflow-wrap:anywhere;font-family:var(--mh-serif,serif)}

/* ---- 地區名牌下的進度條 ---- */
.srg-cat-bar{display:flex;align-items:center;gap:12px;margin-top:12px;max-width:520px}
.srg-cat-bar-track{flex:1 1 auto;height:9px;border-radius:99px;overflow:hidden;
  background:rgba(var(--mh-ink-rgb,43,58,74),.1)}
.srg-cat-bar-track i{display:block;height:100%;border-radius:99px;
  background:linear-gradient(90deg,var(--mh-honey,#fed65b),var(--mh-success,#4fa46a))}
.srg-cat-bar-text{flex:0 0 auto;font-weight:800;font-size:14px;color:var(--srg-navy);
  font-variant-numeric:tabular-nums}

/* ---- 全部展開／收起 ---- */
.srg-fold-tools{display:flex;align-items:center;justify-content:space-between;gap:8px 12px;
  flex-wrap:wrap;margin:12px 2px 4px}
.srg-fold-acts{display:flex;gap:7px}
.srg-fold-all{min-height:40px;padding:6px 13px;border-radius:999px;cursor:pointer;
  border:1px solid var(--srg-border);background:rgba(var(--mh-surface-hi-rgb,255,251,240),.8);
  font:inherit;font-size:13px;color:var(--srg-navy)}
.srg-fold-all:hover{background:rgba(var(--mh-surface-hi-rgb,255,251,240),1)}

/* ---- 小分類＝折疊卡 ---- */
.srg-section-block.srg-fold-card{margin-top:14px;border-radius:22px;overflow:hidden;
  border:1px solid var(--srg-border);
  background:rgba(var(--mh-surface-hi-rgb,255,251,240),.66);
  box-shadow:0 5px 18px -10px rgba(var(--mh-ink-rgb,43,58,74),.35)}
/* 路線底下的小分類以前靠左側直線縮排；變成卡片之後卡片本身就是分組，
   縮排只留一點點，不然窄畫面上每張卡都少一截寬度。 */
.srg-section-block.srg-fold-card.srg-in-track{padding-left:0;margin-left:8px;border-left:1px solid var(--srg-border)}
.srg-fold-card .srg-cat-l3{position:relative;margin:0;padding:12px 14px;flex-wrap:nowrap;gap:10px}
.srg-fold-card:has(.srg-cat-l3-btn[aria-expanded="true"]) .srg-cat-l3{
  background:linear-gradient(90deg,rgba(254,214,91,.22),rgba(255,255,255,0))}
.srg-fold-card .srg-cat-l3 .srg-cat-main{display:flex;flex-direction:column;justify-content:center}
/* 名牌在卡片裡退成「紋章格＋名字」：紋章仍然畫在名牌的 background 上
   （srg-menu-card-scope-test 量的是 plate 的 background-image），
   只是外框、織紋都拿掉，換成一個圓角方格墊在紋章後面。 */
.srg-fold-card .srg-cat-l3 .srg-cat-plate{display:flex;min-height:44px;padding:0 0 0 54px;
  border:0;box-shadow:none;border-radius:0;
  background-image:var(--srg-cat-motif),url(assets/cat/tile.svg);
  background-repeat:no-repeat,no-repeat;
  background-size:26px auto,44px 44px;
  background-position:9px center,0 center}
.srg-fold-card .srg-cat-l3 .srg-cat-name{font-size:clamp(17px,2.4vw,20px)}
.srg-fold-card .srg-cat-l3 .srg-cat-desc{margin:2px 0 0 54px}
/* 整列都按得到：折疊鈕的 ::after 撐滿標題列（標題列是 position:relative）。
   原本的左側小箭頭藏起來，改由右端的 .srg-cat-chev 表示方向。 */
.srg-fold-card .srg-cat-fold-btn::after{content:"";position:absolute;inset:0}
.srg-fold-card .srg-cat-fold-btn:focus-visible{outline:none}
.srg-fold-card .srg-cat-fold-btn:focus-visible::after{outline:2px solid var(--srg-navy);outline-offset:-3px}
.srg-fold-card .srg-cat-fold-btn .srg-ico{display:none}
.srg-fold-card .srg-cat-prog{font-size:14px;font-weight:800;white-space:nowrap}
.srg-cat-chev{flex:0 0 auto;width:30px;height:30px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(var(--mh-ink-rgb,43,58,74),.07);color:var(--srg-navy);
  transition:background-color .3s ease;
  /* **一定要穿透**：它疊在折疊鈕的 ::after 上面時，點箭頭會點在它身上而不是按鈕上，
     等於沒按（v2.60.0 測試抓到的）。 */
  pointer-events:none}
/* **轉的是裡面的 svg，不是圓本身**（v2.61.0）。圓轉到一半時外接矩形會從 30px
   脹到 42px（45° 的對角線），版面量測在轉場中途讀到的就是那個寬度 —— 而且
   transform 會讓它自成繪製層（見上面 pointer-events 的理由）。轉 svg 兩件事都沒有。 */
.srg-cat-chev svg{transform:rotate(-90deg);transition:transform .3s ease}
.srg-cat-head:has(.srg-cat-l3-btn[aria-expanded="true"]) .srg-cat-chev{
  background:var(--mh-honey,#fed65b);color:var(--mh-gold-ink,#735c00)}
.srg-cat-head:has(.srg-cat-l3-btn[aria-expanded="true"]) .srg-cat-chev svg{transform:none}
@media (prefers-reduced-motion:reduce){.srg-cat-chev,.srg-cat-chev svg{transition:none}}
.srg-fold-card .srg-cat-body{margin:0;padding:2px 12px 12px}

/* ---- 關卡＝橫列 ---- */
.srg-menu-grid{display:flex;flex-direction:column;gap:8px}
.srg-level-btn{display:grid;grid-template-columns:42px minmax(0,1fr) auto;gap:12px;align-items:center;
  width:100%;padding:12px 14px;border-radius:18px}
.srg-level-btn:hover:not(:disabled){transform:translateY(-1px)}
.srg-lv-num{width:40px;height:40px;border-radius:14px;display:flex;align-items:center;justify-content:center;
  font-weight:800;font-size:14px;font-variant-numeric:tabular-nums;
  color:var(--srg-navy);background:rgba(var(--mh-ink-rgb,43,58,74),.07)}
.srg-level-btn.srg-lv--done .srg-lv-num{background:rgba(79,164,106,.18);color:#2f6d47}
.srg-level-btn.srg-lv--boss .srg-lv-num{background:rgba(104,67,98,.14);color:var(--mh-plum,#684362)}
.srg-level-btn.srg-lv--next .srg-lv-num{background:var(--mh-honey,#fed65b);color:var(--mh-gold-ink,#735c00)}
.srg-lv-body{min-width:0}
.srg-lv-titlerow{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px}
.srg-level-btn h4{margin:0;font-size:17px;line-height:1.3}
.srg-level-btn .srg-lv-next-flag{flex:0 0 auto;padding:2px 8px;border-radius:99px;letter-spacing:.08em;
  font-size:10.5px;background:var(--mh-honey,#fed65b)}
.srg-level-btn .srg-lvscope{margin-top:4px;font-size:12px}
.srg-level-btn .srg-lvsub{font-size:12px;margin-top:3px}
.srg-level-btn small{margin-top:3px}
.srg-level-btn .srg-boss-flag{margin-top:5px;display:inline-flex}
.srg-lock-why{margin-top:4px;font-size:11.5px;color:var(--srg-slate)}
/* 右端狀態欄。旗標的顏色沿用上面那四條（完成綠／鎖頭紅褐／琥珀／藍紫），
   這裡只管排版：一欄、置中、不換行。 */
.srg-lv-status{min-width:58px;display:flex;flex-direction:column;align-items:center;gap:3px;text-align:center}
.srg-level-btn .srg-lv-status > div{margin:0;white-space:nowrap;font-size:12px;font-weight:800}
.srg-level-btn .srg-lv-status .srg-lv-stars{font-size:12px;font-weight:400}
.srg-lv-go{display:flex;align-items:center;gap:3px;color:var(--mh-gold-ink,#735c00)}

@media (max-width:520px){
  .srg-fold-card .srg-cat-l3{padding:11px 10px}
  .srg-fold-card .srg-cat-l3 .srg-cat-plate{padding-left:48px;background-size:22px auto,40px 40px;background-position:9px center,0 center}
  .srg-fold-card .srg-cat-l3 .srg-cat-desc{margin-left:48px}
  .srg-fold-card .srg-cat-body{padding:2px 8px 10px}
  .srg-level-btn{grid-template-columns:36px minmax(0,1fr) auto;gap:9px;padding:11px 10px}
  .srg-lv-num{width:36px;height:36px;font-size:13px}
  .srg-level-btn h4{font-size:16px}
  .srg-lv-status{min-width:48px}
}

/* ==================================================================
 * 徽記／功績／名號 v3（2026-10-06）
 *
 * 圖騰是本機產的透明圖（assets/ach/<id>.webp），**外框不在圖裡**：
 * 圓形底座＋階級色的雙圈由這裡畫（--srg-tier 由 JS 依 TIERS 寫入），
 * 69 張的框因此必然一致，改階級也不必重產圖。
 * 圖載不到時退回名字的第一個字（.srg-ach-glyph），不退回 emoji。
 * ================================================================== */
.srg-ach-card{align-items:center}
.srg-ach-ic{position:relative;flex:0 0 auto;width:60px;height:60px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;font-size:inherit;line-height:1;
  background:radial-gradient(circle at 50% 38%,rgba(255,255,255,.95),rgba(var(--mh-surface-rgb,244,234,210),.95) 70%);
  box-shadow:0 0 0 2px var(--srg-tier),0 0 0 4px rgba(255,255,255,.85),0 0 0 5px var(--srg-tier),
    0 4px 10px -4px rgba(var(--mh-ink-rgb,43,58,74),.4)}
.srg-ach-img{position:absolute;inset:4px;width:calc(100% - 8px);height:calc(100% - 8px);object-fit:contain}
.srg-ach-glyph{font-family:var(--mh-serif,serif);font-size:24px;font-weight:700;color:var(--srg-tier)}
.srg-ach-has-img .srg-ach-glyph{visibility:hidden}
/* 未解鎖：灰階＋淡，形狀仍看得出來（知道有什麼可拿）。 */
.srg-ach-card:not(.on) .srg-ach-ic{filter:grayscale(1);opacity:.5}
.srg-ach-lore{margin-top:4px;font-family:var(--mh-serif,serif);font-style:italic;font-size:12.5px;
  line-height:1.6;color:var(--mh-gold-ink,#735c00)}
.srg-ach-secret .srg-ach-desc{font-family:var(--mh-serif,serif);font-style:italic}

/* ==================================================================
 * 傳奇榜卡片：攤開的捲軸（2026-10-06，使用者：「傳奇榜的欄位超級醜」）
 *
 * 底圖 assets/lb-scroll.webp 是本機 Z-Image-Turbo 產的（dev/gen-lb-scroll.py），
 * 左右兩捲紙軸＋上下木條。用 border-image 九宮格切：
 *   - 切線 80 170 82 190 是對**這一張圖**量的（中線亮度剖面），換圖要重量；
 *   - 紙軸只會縱向拉長（圓柱拉長還是圓柱），木條只會橫向拉長，紙面整片拉 ——
 *     所以卡片多高多寬都不會把銅頭拉變形。
 * border-image 不吃 border-radius、矩形 box-shadow 會在透明的角落露出方框，
 * 所以兩者都拿掉，陰影改用 drop-shadow（沿著 alpha 走）。backdrop-filter 也拿掉：
 * 它會把透明角落後面的頁面糊成一塊方形霧。
 * ================================================================== */
.srg-root .srg-lb-card{
  margin:16px 0 20px;
  padding:12px 16px 8px;
  background:none;border-radius:0;box-shadow:none;
  -webkit-backdrop-filter:none;backdrop-filter:none;
  border-style:solid;border-color:transparent;
  border-width:24px 51px 25px 57px;
  border-image:url('assets/lb-scroll.webp') 80 170 82 190 fill / 24px 51px 25px 57px stretch;
  filter:drop-shadow(0 6px 10px rgba(60,40,15,.28));
}
/* 標題：置中，兩側一條漸淡的金線，像卷首的題字。 */
.srg-root .srg-lb-card h3{
  justify-content:center;gap:10px;
  font-size:22px;letter-spacing:.18em;color:#5a3d1c;margin:2px 0 10px;
}
.srg-root .srg-lb-card h3::before,
.srg-root .srg-lb-card h3::after{
  content:'';flex:0 1 90px;height:1.5px;
  background:linear-gradient(90deg,transparent,rgba(138,111,61,.85));
}
.srg-root .srg-lb-card h3::after{background:linear-gradient(90deg,rgba(138,111,61,.85),transparent)}
.srg-root .srg-lb-card .mh-lb-mini-item{border-bottom-color:rgba(138,111,61,.45)}
.srg-root .srg-lb-card .mh-lb-name{color:#3b2a14}
.srg-root .srg-lb-card .mh-lb-metric{color:#5a3d1c;font-size:17px}
.srg-root .srg-lb-card .mh-lb-face-box{border-color:rgba(138,111,61,.6);background:rgba(255,250,235,.7)}
/* 「你」那一列：紙上的一道淡金底，不是另一張卡。 */
.srg-root .srg-lb-card .mh-lb-youbar{
  margin-top:6px;border-top:none;border-radius:10px;
  background:rgba(201,168,106,.22);
}
.srg-root .srg-lb-card .mh-lb-more{color:#5a3d1c;border-color:#8a6f3d}
@media (max-width:480px){
  .srg-root .srg-lb-card{
    padding:8px 6px 4px;
    border-width:18px 36px 18px 40px;
    border-image-width:18px 36px 18px 40px;
  }
  .srg-root .srg-lb-card h3::before,
  .srg-root .srg-lb-card h3::after{flex-basis:36px}
}
/* 標題的文字是匿名 flex 項目，會跟兩側金線一起被壓到 min-content ——
   288px 時「傳奇榜」折成「傳奇／榜」。不准折，讓金線先縮。 */
.srg-root .srg-lb-card h3{white-space:nowrap}
/* 288px 時名字欄只剩 35px，「小明同學」折成兩行。紙軸兩側、間距、頭像各讓一點。
   頭像的 40px 是 mh-leaderboard.js 寫在行內的，所以要 !important。 */
@media (max-width:360px){
  .srg-root .srg-lb-card{
    padding:8px 2px 4px;
    border-width:18px 26px 18px 28px;
    border-image-width:18px 26px 18px 28px;
  }
  .srg-root .srg-lb-card .mh-lb-mini-item{gap:8px;padding-left:2px;padding-right:2px}
  .srg-root .srg-lb-card .mh-lb-face-box{width:32px !important;height:32px !important}
}

/* ==================================================================
 * 關卡列表的層級：地區 vs 大分類（2026-10-06，使用者：「少了區隔感，
 * 看不清哪些是地區哪些是大分類」）
 *
 * 原本兩層都是同一種羊皮紙名牌，只差字級 —— 中間又夾著一排排同色的折疊卡，
 * 讀起來是三層幾乎一樣的東西。改成三種**不同的形狀**，而不是同一形狀的三種大小：
 *   地區   ＝ 滿版的深色橫幅（章節頁），名字反白、進度條在橫幅裡；
 *   大分類 ＝ 沒有底的標題＋往右延伸的金線，左邊一條金色導軌往下接到它的小分類卡；
 *   小分類 ＝ 原本的折疊卡（不動）。
 * 導軌是每張 .srg-in-track 卡的 ::before 往上伸過 margin-top 接起來的（卡片是
 * .srg-content 的平鋪兄弟，不在同一個容器裡，所以沒有父元素可以畫整條線）。
 *
 * 選擇器一律寫成 `.srg-cat-head.srg-cat-l1` 這種兩個 class：要蓋過的
 * `.srg-cat-l1.srg-cat-first{background-image:none;padding-top:0}` 是 (0,2,0)，
 * 同特異度排在後面才贏 —— 不再往上加。
 * ================================================================== */
.srg-cat-head.srg-cat-l1{
  margin:40px 0 14px;padding:10px 8px 8px;border-radius:0;
  /* 底圖：assets/region-banner.webp（dev/gen-ui-art.py --kind region，seed 7200）。
     切線 92 120 92 120 是對這張量的：四角的金色卷草紋往內伸到 ~115px／~90px。
     角落不拉伸、上下框只橫向拉、中間的綠色琺瑯整片拉。 */
  background:none;box-shadow:none;
  border-style:solid;border-color:transparent;border-width:32px 42px;
  border-image:url('assets/region-banner.webp') 92 120 92 120 fill / 32px 42px stretch;
  filter:drop-shadow(0 10px 14px rgba(20,28,20,.35));
}
.srg-cat-head.srg-cat-l1.srg-cat-first{margin-top:18px}
.srg-cat-head.srg-cat-l1 .srg-cat-plate{
  border:0;box-shadow:none;border-radius:0;padding:2px 0 2px 50px;
  background-image:var(--srg-cat-motif);background-repeat:no-repeat;
  background-size:38px auto;background-position:left center;
}
.srg-cat-head.srg-cat-l1 .srg-cat-name{
  color:#f8eed3;letter-spacing:.06em;text-shadow:0 2px 0 rgba(0,0,0,.25);
  font-size:clamp(24px,3.8vw,30px);
}
.srg-cat-head.srg-cat-l1 .srg-cat-desc{color:rgba(248,238,211,.82)}
.srg-cat-head.srg-cat-l1 .srg-count,
.srg-cat-head.srg-cat-l1 .srg-count b{color:#f8eed3}
.srg-cat-head.srg-cat-l1 .srg-cat-bar-track{background:rgba(255,255,255,.16)}
.srg-cat-head.srg-cat-l1 .srg-cat-bar-text{color:#fed65b}

/* 大分類：沒有底，名字＋往右延伸到邊的金線。 */
.srg-cat-head.srg-cat-l2{
  margin:26px 0 2px;padding:0 0 0 2px;border-left:0;
}
.srg-cat-head.srg-cat-l2 .srg-cat-main{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.srg-cat-head.srg-cat-l2 .srg-cat-main::after{
  content:'';order:1;flex:1 1 40px;height:2px;align-self:center;
  background:linear-gradient(90deg,rgba(201,168,106,.95),rgba(201,168,106,0));
}
.srg-cat-head.srg-cat-l2 .srg-cat-desc{order:2;flex-basis:100%;margin:0 0 0 30px}
.srg-cat-head.srg-cat-l2 .srg-cat-plate{
  /* 緞帶：assets/track-ribbon.webp（--kind ribbon，seed 7301）。左右燕尾 120／115px
     不拉伸，中段只橫向拉；上下切 0，所以兩端寬度要跟著高度等比（187px 高的圖 → 
     兩端寬 = 高 × 120/187，名牌高約 50px → 32px）。 */
  position:relative;box-shadow:none;border-radius:0;
  border-style:solid;border-color:transparent;border-width:0 31px 0 32px;
  border-image:url('assets/track-ribbon.webp') 0 115 0 120 fill / 0 31px 0 32px stretch;
  padding:9px 14px 13px 34px;
  background:none;
  filter:drop-shadow(0 3px 4px rgba(90,60,20,.25));
}
/* 紋章改畫在 ::before：border-image 的 fill 會蓋在元素自己的 background 上面。 */
.srg-cat-head.srg-cat-l2 .srg-cat-plate::before{
  content:'';position:absolute;left:4px;top:50%;width:24px;height:24px;margin-top:-14px;
  background:var(--srg-cat-motif) center/contain no-repeat;
}
.srg-cat-head.srg-cat-l2 .srg-cat-name{color:#5a3d1c;text-shadow:0 1px 0 rgba(255,255,255,.6);font-size:clamp(19px,2.8vw,22px);letter-spacing:.04em}

/* 導軌：大分類底下的小分類卡往右縮一格，左邊一條金線往上接到大分類標題。 */
.srg-section-block.srg-fold-card.srg-in-track{
  position:relative;overflow:visible;margin-left:22px;border-left:1px solid var(--srg-border);
}
.srg-section-block.srg-fold-card.srg-in-track::before{
  content:'';position:absolute;left:-15px;top:-15px;bottom:-1px;width:3px;border-radius:2px;
  /* 金 #c9a86a 在淡色背景圖上幾乎量不到（實測與底色只差 ~12 的亮度），要壓深一階。 */
  background:rgba(160,120,40,.8);
}
/* overflow:visible 是為了讓導軌畫得出去；卡片原本靠 overflow:hidden 把
   展開時的標題底色裁成圓角，改由標題自己帶圓角。 */
.srg-fold-card.srg-in-track .srg-cat-l3{border-radius:22px 22px 0 0}
.srg-fold-card.srg-in-track:has(.srg-cat-l3-btn[aria-expanded="false"]) .srg-cat-l3{border-radius:22px}
@media (max-width:520px){
  .srg-cat-head.srg-cat-l1{padding:6px 4px 4px;border-width:24px 30px;border-image-width:24px 30px}
  .srg-cat-head.srg-cat-l1 .srg-cat-plate{padding-left:42px;background-size:32px auto}
  .srg-section-block.srg-fold-card.srg-in-track{margin-left:14px}
  .srg-section-block.srg-fold-card.srg-in-track::before{left:-11px}
}

/* ---- 下一個挑戰：標籤要讀得到（2026-10-06 使用者：先看到關卡名、聯想不到這張卡的作用）----
   從 10.5px 的灰金小字改成一枚紅色印章標籤（跟下面「進入關卡」同一組蠟封色），
   讓視線先落在「下一個挑戰」再落到關卡名。 */
.srg-continue-eyebrow{display:inline-flex;width:fit-content;
  padding:5px 14px 5px 11px;border-radius:999px;
  font-size:13px;font-weight:800;letter-spacing:.2em;
  color:var(--mh-on-primary,#fff);
  background:radial-gradient(circle at 30% 28%,var(--mh-seal-a),var(--mh-seal-b));
  border:1.5px solid var(--mh-seal-edge);
  box-shadow:0 3px 8px -4px rgba(0,0,0,.5)}
.srg-continue-title{margin-top:10px}

/* ---- 桌機：大分類與小分類各再縮一階（2026-10-06）---- */
.srg-fold-tools{justify-content:flex-end}
@media (min-width:768px){
  .srg-continue-eyebrow{font-size:16px;padding:6px 18px 6px 14px}
  .srg-cat-head.srg-cat-l2{margin-left:28px}
  .srg-section-block.srg-fold-card.srg-in-track{margin-left:76px}
  .srg-section-block.srg-fold-card.srg-in-track::before{left:-30px}
}
/* 大分類的計數留在緞帶那一列：標題列預設 flex-wrap:wrap，手機上緞帶＋金線＋說明
   就把計數擠到下一行最左邊，看起來像屬於下面那張卡。 */
.srg-cat-head.srg-cat-l2{flex-wrap:nowrap;align-items:flex-start}
.srg-cat-head.srg-cat-l2 .srg-count{margin-top:14px}

/* ==================================================================
 * 關卡卡片的範圍列＋放不下就縮字（2026-10-06，使用者：「關卡卡片自動縮小溢排文字」）
 *
 * **範圍列從 v2.60.0 起其實是壞的**：.srg-lvscope 是 `auto 1fr` 兩欄的格線，
 * 本意是「標籤一欄、值一欄」，但它的子元素是一整列 .srg-lvrow（標籤＋值包在一起），
 * 於是格線把**整列**當一格 —— 「拍號 4/4 · 2 小節」佔左欄、「音符 …」被擠進右欄，
 * 值欄只剩 48–69px，「四分音符、四分休止符」直排成一字一行。三個瀏覽器、
 * 任何寬度都一樣（1280px 也是 62px）。display:contents 讓標籤與值直接成為格子。
 * ================================================================== */
.srg-level-btn .srg-lvrow{display:contents}
.srg-level-btn .srg-lvscope{column-gap:8px}

/* 縮字（game.js 的 fitTexts）要量得到「放不下」：元素本身的寬度必須被父層夾住，
   而不是跟著內容長。flex 子元素預設 min-width:auto＝內容寬，nowrap 時永遠「放得下」。 */
.srg-lv-titlerow h4{min-width:0;max-width:100%}
.srg-cat-plate{max-width:100%;min-width:0}
.srg-cat-plate .srg-cat-name{min-width:0}
/* 大分類緞帶：名字在緞帶裡不折行（縮字處理），緞帶自己可以縮到整列寬。 */
.srg-cat-head.srg-cat-l2 .srg-cat-plate{flex:0 1 auto}
/* 窄手機（≤400px）：標題欄在 328px 上只剩 156px，29 個標題得縮字、2 個縮到底還是兩行。
   從留白裡挪 ~25px 給它：導軌縮排 14→8、內距 8/10→5/8、編號格 36→32、狀態欄 48→42。 */
@media (max-width:400px){
  .srg-section-block.srg-fold-card.srg-in-track{margin-left:8px}
  .srg-section-block.srg-fold-card.srg-in-track::before{left:-7px}
  .srg-fold-card .srg-cat-body{padding:2px 5px 8px}
  .srg-level-btn{grid-template-columns:32px minmax(0,1fr) auto;gap:8px;padding:10px 8px}
  .srg-lv-num{width:32px;height:32px;border-radius:11px;font-size:12px}
  .srg-lv-status{min-width:42px}
}
.srg-cat-desc{text-wrap:pretty}

/* ==================== 選項卡的魔法底圖（SRG 2.64.0，2026-10-07） ====================
 * cards.js 的 mountChoice 給每張卡掛 .srg-face-1..3（隨機起點輪流發）。
 * 底圖：assets/card-face-1..3.webp（dev/gen-card-face.py；星辰水晶／精靈銀藤／魔導書頁），640×320。
 *
 * ## 為什麼是九宮格（border-image）而不是 background 100% 100%
 *
 * 圖上**自己畫了框與四角裝飾**，而卡片的長寬比會變：實測 288px 寬是 1.97、
 * 390px 是 2.76、1280px 是 3.01。用 background 撐滿的話，桌機上四角的晶簇、
 * 藤蔓會被橫向拉長 1.5 倍。九宮格讓四個角照原比例畫，只有邊與中央延展。
 * 切線（--srg-face-cut，原圖像素）是量各張圖邊緣的細節剖面定的；
 * 畫出來的寬（--srg-face-w）＝切線 × 0.22，四邊同一個比例，角落才不會變形。
 *
 * ## 狀態色為什麼畫在 ::before
 *
 * border-image 會蓋掉 border-color，原本靠換邊框色的滑過（金）／答對（綠）／
 * 答錯（紅）全部會消失。所以改由一層 ::before 疊在圖上畫色框（inset box-shadow）
 * 與半透明底色。按鈕自己 z-index:0 開一個疊層環境，::before 用 z-index:-1：
 * 畫在按鈕的 border-image **之上**、文字**之下**（CSS 2 附錄 E 的繪製順序），
 * 所以疊色不會染到字。✓／✕ 仍是原本的 ::after。
 * 疊色後文字區最差 1% 像素的對比仍有 5.1:1 以上（gen-card-face.py 的 contrast() 量法）。
 *
 * 選擇器帶 [class*="srg-face-"] 是為了特異性高過 .srg-card-ok／.srg-card-bad，不用 !important。
 */
.srg-face-1{--srg-face:url('assets/card-face-1.webp');--srg-face-cut:48 72;--srg-face-w:11px 16px}
.srg-face-2{--srg-face:url('assets/card-face-2.webp');--srg-face-cut:48 64;--srg-face-w:11px 14px}
.srg-face-3{--srg-face:url('assets/card-face-3.webp');--srg-face-cut:64 96;--srg-face-w:14px 21px}
.srg-card-btn[class*="srg-face-"]{
  position:relative;z-index:0;
  border-color:transparent;background:none;
  border-image:var(--srg-face) var(--srg-face-cut) fill / var(--srg-face-w) stretch;
}
.srg-card-btn[class*="srg-face-"]::before{
  content:'';position:absolute;inset:-2px;z-index:-1;pointer-events:none;
  border-radius:inherit;transition:box-shadow .12s,background-color .12s;
}
/* 已判定的卡不吃 hover：點完滑鼠還停在卡上，金框會蓋掉答對的綠框／答錯的紅框。 */
.srg-card-btn[class*="srg-face-"]:hover:not(:disabled):not(.srg-card-ok):not(.srg-card-bad)::before,
.srg-card-btn[class*="srg-face-"]:focus-visible::before{box-shadow:inset 0 0 0 2px var(--srg-glow,#c9a227)}
.srg-card-btn[class*="srg-face-"].srg-card-ok::before{
  background:rgba(46,125,79,.18);box-shadow:inset 0 0 0 2px var(--srg-success,#2e7d4f);
}
.srg-card-btn[class*="srg-face-"].srg-card-bad::before{
  background:rgba(176,82,74,.16);box-shadow:inset 0 0 0 2px #b0524a;
}
