:root {
    /* 這一頁自己就是深色的，不要讓瀏覽器再套一層自動深色。
       三星瀏覽器開「深色模式」時會把整頁重新上色，少了這行整個設計會被壓成一團黑。 */
    color-scheme: dark;

    --bg-color: #0a0a0a;
    --card-bg: #161616;
    --text-main: #e0e0e0;
    --text-sub: #888888;
    --accent: #ffffff;
    --accent-hover: #cccccc;
    --border: #262626;
    --success: #4caf50;
    --error: #f44336;
    --btn-primary: #3b82f6; 
    --btn-primary-hover: #2563eb;
    --btn-youglish: #e62117; 
    --font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --warning: #ff9800;
}

/* 明確宣告「這個網站自己處理深色」。
   ---------------------------------------------------------
   三星瀏覽器的深色模式跟 Chrome 的自動深色是兩套不同的實作：
   Chrome 看 color-scheme（上面 :root 已經宣告），
   三星則是看網站有沒有回應 prefers-color-scheme —— 沒有的話，
   它就認定這個網站「不支援深色」，然後自己把整頁重新上色。
   我們的主題是用 data-theme 切的，從來沒用過這個 media query，
   所以在三星眼裡就是一個不支援深色的網站。

   這個區塊把基礎色重新宣告一次。值跟 :root 完全一樣（所以不會改變
   任何外觀），作用是讓瀏覽器看得到「這個網站對深色偏好有反應」。 */
@media (prefers-color-scheme: dark) {
    :root {
        color-scheme: dark;
        --bg-color: #0a0a0a;
        --card-bg: #161616;
        --text-main: #e0e0e0;
        --text-sub: #888888;
        --border: #262626;
    }
}

html {
    overscroll-behavior-y: none;
    /* 只能捲動，不能兩指縮放、也不會連點兩下放大（字太小用設定裡的文字大小） */
    touch-action: pan-x pan-y;
}

/* ── 捲軸 ──────────────────────────────────────────────
   不用瀏覽器預設的灰色粗捲軸：細、圓角、沒有底槽，顏色跟著主題的文字色走，
   滑過去才亮一點、變粗一點。手機的捲軸是系統疊在畫面上的，這段只影響電腦。
   Chrome 在元素有寫 scrollbar-width／scrollbar-color 時會改用標準捲軸、忽略下面這組，
   所以標準寫法只給不認得 ::-webkit-scrollbar 的瀏覽器（火狐）。 */
:root {
    --sb-thumb: rgba(255, 255, 255, 0.16);
    --sb-thumb-hover: rgba(255, 255, 255, 0.32);
    --sb-thumb: color-mix(in srgb, var(--text-sub) 42%, transparent);
    --sb-thumb-hover: color-mix(in srgb, var(--text-main) 55%, transparent);
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
    background-color: var(--sb-thumb);
    background-clip: padding-box;
    border: 3px solid transparent;
    border-radius: 999px;
    min-height: 40px;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--sb-thumb-hover); border-width: 2px; }
::-webkit-scrollbar-thumb:active { background-color: var(--sb-thumb-hover); border-width: 2px; }
::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
@supports not selector(::-webkit-scrollbar) {
    * { scrollbar-width: thin; scrollbar-color: var(--sb-thumb) transparent; }
}

* {
    box-sizing: border-box;
}

/* 無障礙：滑鼠/觸控點擊不顯示外框，鍵盤 Tab 導覽時才顯示。
   （按鈕在觸控點擊時不會觸發 :focus-visible，因此手機使用者看不到外框） */
:focus:not(:focus-visible) {
    outline: none;
}
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* 文字輸入類元件排除在外：它們本身就以「邊框變色」表示聚焦（見下方
   input/textarea 的 :focus 規則），再套一圈外框會很突兀。
   checkbox / radio / range 不在此列——它們沒有邊框可變色，需保留焦點外框。 */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):focus,
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):focus-visible,
textarea:focus, textarea:focus-visible,
select:focus, select:focus-visible,
[contenteditable]:focus, [contenteditable]:focus-visible {
    outline: none;
}

/* 搜尋輸入框（單字庫頁）：抽出 class，避免 inline 樣式蓋掉聚焦效果 */
.search-input {
    width: 100%;
    box-sizing: border-box;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 12px 44px 12px 14px;
    margin: 0;
    font-family: inherit;
    font-size: 0.9rem;
    color: var(--text-main);
    transition: border-color 0.2s;
}

.search-input:focus {
    border-color: var(--text-sub);
}

.search-input::-webkit-search-cancel-button {
    display: none;
}

body {
    background-color: var(--bg-color);
    color: var(--text-main);
    font-family: var(--font-family);
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    overscroll-behavior-y: none;
}

.container {
    width: 100%;
    max-width: 600px;
    /* 加到主畫面之後，沒有頁首的畫面（練習、市集、後台…三十幾個）
       第一排的「返回」按鈕會被動態島壓到一半。安全區要加在這裡，
       一條規則管掉全部，不是去改三十幾個畫面。 */
    padding: calc(40px + var(--safe-top)) var(--container-pad);
    display: flex;
    flex-direction: column;
}

header {
    margin-bottom: 40px;
    text-align: center;
    letter-spacing: 2px;
    text-transform: uppercase;
}

#main-header {
    position: sticky;
    top: 0;
    z-index: 999;
    background: rgba(10, 10, 10, 0.95);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    /* 負 margin 抵消 container 的上內距，讓 header 貼齊頂端無空隙。
       容器的上內距現在含安全區，這裡要一起減掉，不然頁首會被推下去一截，
       然後自己的 padding-top 再推一次 —— 等於讓開兩倍。 */
    margin: calc(-40px - var(--safe-top)) -20px 24px;
    padding: 14px 20px;
    /* 把內容推到狀態列下方（需配合 viewport-fit=cover） */
    padding-top: calc(var(--safe-top) + 14px);
    text-align: initial;
    letter-spacing: initial;
    text-transform: initial;
}

h1 {
    font-size: 1.4rem;
    font-weight: 300;
    letter-spacing: 3px;
    margin: 0;
    color: var(--accent);
}

h2 {
    font-size: 1.1rem;
    font-weight: 400;
    margin-bottom: 20px;
    letter-spacing: 0.5px;
}

/* Navigation Bar */
.nav-bar {
    margin-bottom: 30px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    min-height: 40px;
}

.nav-bar-right {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    flex-shrink: 0;
    position: relative;
}

.btn-icon {
    background: none;
    border: none;
    color: var(--text-sub);
    cursor: pointer;
    font-size: 0.9rem;
    transition: color 0.2s;
    padding: 6px 12px;
    border: 1px solid var(--border);
    border-radius: 15px;
    letter-spacing: 0.5px;
}

@media (hover: hover) {
    .btn-icon:hover {
        color: var(--accent);
        border-color: var(--text-sub);
    }
}

.export-quiz-btn { 
    font-size: 0.8rem; 
    border: 1px solid var(--text-sub); 
    color: var(--text-sub); 
    padding: 5px 14px; 
    border-radius: 20px; 
    background: transparent; 
    cursor: pointer; 
    white-space: nowrap !important; 
    display: inline-block !important; 
    visibility: visible !important;
    opacity: 1 !important;
    transition: all 0.2s;
    z-index: 10;
    letter-spacing: 0.5px;
}

@media (hover: hover) {
    .export-quiz-btn:hover {
        border-color: var(--accent);
        color: var(--accent);
    }
}

.card {
    background-color: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 24px;
    margin-bottom: 16px;
    transition: transform 0.2s, border-color 0.2s;
}

.book-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    padding: 18px;
    margin-bottom: 12px;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: var(--card-bg);
}

@media (hover: hover) {
    .book-item:hover {
        border-color: var(--text-sub);
    }
}

.book-item.selected {
    border-color: var(--accent);
    background-color: #1c1c1c;
}

.word-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.95rem;
    padding: 14px 0;
    border-bottom: 1px solid #1f1f1f;
}

/* 批次補詞性（Pro／Ultra）：每個字一列，右邊是詞性小籤，點了亮起、可以多選。 */
.pos-fill { margin-top: 12px; padding: 16px; }
.pos-fill-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.pos-fill-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pos-fill-name { font-weight: 700; font-size: .98rem; letter-spacing: .5px; color: var(--text-main); }
.pos-fill-badge { font-size: .6rem; font-weight: 800; letter-spacing: 1px; padding: 3px 8px; border-radius: 999px; color: #1a1206;
    background: linear-gradient(110deg, #f0c040, #e7b4ff 70%, #b388ff); white-space: nowrap; }
.pos-fill-go { margin: 0; white-space: nowrap; }
/* 免費帳號：鎖著的樣子，徽章寫「專屬」，按鈕換成金紫漸層 */
.pos-fill.locked { border-color: rgba(240,192,64,.28); background: linear-gradient(135deg, rgba(240,192,64,.06), rgba(179,136,255,.06)), var(--card-bg); }
.pos-fill.locked .pos-fill-go { background: linear-gradient(110deg, #f0c040, #e7b4ff 70%, #b388ff); color: #1a1206; border-color: transparent; font-weight: 700; }
.pos-fill-sub { margin-top: 8px; font-size: .78rem; line-height: 1.55; color: var(--text-sub); }
.pos-fill-sub b { color: var(--text-main); font-weight: 700; }
.pos-fill-preview { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.pos-fill-summary { display: flex; flex-wrap: wrap; gap: 6px; }
.pos-pill { display: inline-flex; align-items: center; gap: 5px; font-size: .74rem; padding: 4px 10px; border-radius: 999px;
    border: 1px solid var(--border); color: var(--text-sub); background: rgba(255,255,255,.03); }
.pos-pill b { color: var(--text-main); font-variant-numeric: tabular-nums; }
.pos-pill.ok { border-color: rgba(129,199,132,.45); }
.pos-pill.ok b { color: #a5d6a7; }
.pos-pill.warn { border-color: rgba(255,183,77,.5); }
.pos-pill.warn b { color: #ffcc80; }
.pos-fill-note { margin-top: 8px; font-size: .74rem; color: var(--text-sub); line-height: 1.5; }
.pos-fill-note:empty { display: none; }
.pos-fill-list { margin-top: 10px; max-height: 46vh; overflow-y: auto; overscroll-behavior: contain; border-radius: 12px;
    border: 1px solid var(--border); background: rgba(0,0,0,.12); }
.pos-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 6px 10px; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.pos-row:last-child { border-bottom: 0; }
.pos-row-word { min-width: 0; }
.pos-row-word b { display: block; font-size: .95rem; color: var(--text-main); overflow-wrap: anywhere; }
.pos-row-word .pos-row-zh { display: block; margin-top: 2px; font-size: .76rem; color: var(--text-sub); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pos-row-tag { display: inline-block; margin-left: 6px; font-size: .62rem; padding: 1px 6px; border-radius: 999px; vertical-align: 2px;
    border: 1px solid var(--border); color: var(--text-sub); font-weight: 600; }
.pos-row-tag.warn { border-color: rgba(255,183,77,.5); color: #ffcc80; }
.pos-row-chips { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 5px; max-width: 190px; }
.pos-chip { min-width: 42px; height: 30px; padding: 0 9px; border-radius: 999px; border: 1px solid var(--border); background: transparent;
    color: var(--text-sub); font: inherit; font-size: .8rem; font-weight: 700; cursor: pointer; transition: background .15s, border-color .15s, color .15s, transform .1s; }
.pos-chip:active { transform: scale(.94); }
.pos-chip[aria-pressed="true"] { background: rgba(255,152,0,.16); border-color: #ff9800; color: #ffb74d; }
.pos-chip.more { min-width: 30px; padding: 0; font-size: .95rem; font-weight: 600; }
.pos-row.missing .pos-row-word b { color: var(--text-sub); }
.pos-row.on { background: rgba(255,152,0,.04); }
.pos-fill-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.pos-fill-foot .btn { margin: 0; }
.pos-fill-hint { flex: 1 0 100%; font-size: .72rem; color: var(--text-sub); }
@media (max-width: 380px) { .pos-row-chips { max-width: 150px; } .pos-chip { min-width: 38px; padding: 0 7px; } }

.word-item:last-child {
    border-bottom: none;
}

.word-en {
    font-weight: 500;
    color: var(--accent);
    letter-spacing: 0.5px;
}

.word-zh {
    color: var(--text-sub);
    font-size: 0.9rem;
    margin-top: 4px;
}
/* 單字助手加字時附上的原句 */
.word-example {
    margin-top: 6px;
    padding-left: 10px;
    border-left: 2px solid var(--border);
    color: var(--text-sub);
    font-size: 0.82rem;
    font-style: italic;
    line-height: 1.5;
}
.word-example small { display: block; font-style: normal; font-size: 0.7rem; opacity: 0.7; margin-top: 2px; }

input[type="text"], input[type="number"], textarea {
    width: 100%;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--border);
    color: var(--text-main);
    padding: 12px 0;
    font-size: 1rem;
    margin-bottom: 24px;
    transition: border-color 0.2s;
    font-family: var(--font-family);
}

input[type="text"]:focus, input[type="number"]:focus, textarea:focus {
    border-bottom-color: var(--accent);
}

textarea {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px;
    min-height: 120px;
    margin-top: 10px;
    font-size: 0.9rem;
    line-height: 1.6;
    resize: vertical;
}

/* =========================================================
   主要按鈕：磨砂玻璃
   ---------------------------------------------------------
   原本是實心純白（#fff 底 + 黑字），在深色底上亮度落差太大：
   看久了刺眼，而且輸入框旁邊一整塊白會搶走視線，打字很干擾。
   改成半透明磨砂＋微微發亮 —— 底色只留一點點，靠 backdrop-filter
   把後面的畫面糊掉，邊框與內側高光撐出立體感。

   換顏色只要改 --btn-tint（RGB 三個數字）跟 --btn-ink（文字色），
   底下的 .btn-tint-* 就是這樣做的。實心的紅／橘／金按鈕全部收斂到
   同一套語彙，不然一半磨砂一半實心會更亂。
   ========================================================= */
.btn {
    --btn-tint: 255, 255, 255;
    --btn-ink: var(--text-main);
    --btn-blur: blur(14px) saturate(170%);
    background:
        linear-gradient(180deg,
            rgba(var(--btn-tint), 0.26) 0%,
            rgba(var(--btn-tint), 0.13) 100%);
    color: var(--btn-ink);
    border: 1px solid rgba(var(--btn-tint), 0.38);
    backdrop-filter: var(--btn-blur);
    -webkit-backdrop-filter: var(--btn-blur);
    box-shadow:
        0 0 18px rgba(var(--btn-tint), 0.12),
        inset 0 1px 0 rgba(255, 255, 255, 0.18);
    padding: 14px 24px;
    border-radius: 30px;
    font-weight: 500;
    cursor: pointer;
    font-size: 0.9rem;
    width: 100%;
    margin-top: 10px;
    transition: background 0.2s, border-color 0.2s, box-shadow 0.2s;
    letter-spacing: 0.5px;
}

@media (hover: hover) {
    .btn:hover {
        background:
            linear-gradient(180deg,
                rgba(var(--btn-tint), 0.32) 0%,
                rgba(var(--btn-tint), 0.17) 100%);
        border-color: rgba(var(--btn-tint), 0.52);
    }
}

.btn:disabled {
    opacity: 0.4;
    cursor: default;
    box-shadow: none;
}

/* 有顏色的按鈕：底色與邊框跟著 tint 走，文字用同色系的淺色才看得清楚 */
.btn-tint-rose  { --btn-tint: 236,  64, 122; --btn-ink: #ffc6da; }
.btn-tint-red   { --btn-tint: 255,  82,  82; --btn-ink: #ffb8b8; }
.btn-tint-amber { --btn-tint: 255, 152,   0; --btn-ink: #ffd49a; }
.btn-tint-gold  { --btn-tint: 240, 192,  64; --btn-ink: #f6e2ab; }
.btn-tint-green { --btn-tint:  76, 175,  80; --btn-ink: #b8e5ba; }
.btn-tint-cyan  { --btn-tint:   0, 188, 212; --btn-ink: #a6e7f0; }
.btn-tint-violet{ --btn-tint: 179, 136, 255; --btn-ink: #ddc8ff; }

/* 舊機型的「降低特效」模式：模糊很吃 GPU，關掉之後底色要加深一點，
   不然半透明疊在深色背景上會淡到看不出是按鈕 */
html[data-fx="low"] .btn {
    --btn-blur: none;
    background:
        linear-gradient(180deg,
            rgba(var(--btn-tint), 0.30) 0%,
            rgba(var(--btn-tint), 0.18) 100%);
}

/* 拍照的快門鍵：圓的，一樣是磨砂白，不是一顆實心白球 */
.shutter-btn {
    width: 70px;
    height: 70px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.20);
    border: 3px solid rgba(255, 255, 255, 0.55);
    color: var(--text-main);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(12px) saturate(160%);
    -webkit-backdrop-filter: blur(12px) saturate(160%);
    box-shadow:
        0 0 20px rgba(255, 255, 255, 0.12),
        inset 0 1px 0 rgba(255, 255, 255, 0.28);
    transition: transform 0.1s, background 0.2s;
}
.shutter-btn:active { transform: scale(0.94); background: rgba(255, 255, 255, 0.30); }

.btn-outline {
    background: transparent;
    color: var(--text-main);
    border: 1px solid var(--border);
    box-shadow: none;
}

@media (hover: hover) {
    .btn-outline:hover {
        border-color: var(--accent);
        /* 一定要明確指定底色。外框按鈕沒設 background 的話，
           會吃到 .btn:hover 的漸層，整顆變成接近全白。 */
        background: var(--outline-hover-bg);
        box-shadow: none;
    }
}

.btn-small {
    padding: 6px 14px;
    font-size: 0.8rem;
    width: auto;
    margin: 0;
    border-radius: 15px;
}

.btn-delete {
    background: transparent;
    color: #666;
    border: 1px solid #333;
}

@media (hover: hover) {
    .btn-delete:hover {
        color: var(--error);
        border-color: var(--error);
        background: transparent;
    }
}

.btn-yg {
    border-color: #444;
    color: var(--text-main);
}

@media (hover: hover) {
    .btn-yg:hover {
        background-color: var(--btn-youglish);
        border-color: var(--btn-youglish);
        color: white;
    }
}

/* ===== 練習模式按鈕：統一視覺語言 =====
   原本這一區混用了白底、深色底、素色外框、橘色外框等多種樣式，
   視覺很雜。改為單一語言 + 兩個層級：
   .mode-btn         一般練習模式（全部長得一樣）
   .mode-btn-primary 主要模式（精通類，稍微突出） */
.mode-btn {
    background: var(--card-bg);
    color: var(--text-main);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 15px 16px;
    width: 100%;
    margin: 0;
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 500;
    letter-spacing: 0.5px;
    line-height: 1.35;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, transform 0.12s;
}

@media (hover: hover) {
    .mode-btn:hover {
        border-color: var(--text-sub);
        background: #1c1c1c;
    }
}

.mode-btn:active {
    transform: scale(0.985);
}

.mode-btn-primary {
    background: var(--surface-strong, #1e1e1e);
    border-color: var(--surface-strong-border, #3a3a3a);
    padding: 17px 16px;
}

@media (hover: hover) {
    .mode-btn-primary:hover {
        border-color: var(--text-main);
        background: #262626;
    }
}

/* 按鈕內的說明文字（例如「獲取牌位積分」） */
.mode-btn-sub {
    display: block;
    margin-top: 4px;
    font-size: 0.72rem;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--text-sub);
}

.practice-area {
    text-align: center;
    margin-top: 40px;
    position: relative;
}

.question-text {
    font-size: 1.8rem;
    margin-bottom: 35px;
    font-weight: 500;
    letter-spacing: 0.5px;
}

.hint-text {
    color: var(--text-sub);
    margin-bottom: 12px;
    font-style: italic;
    height: 20px;
    font-size: 0.9rem;
    letter-spacing: 1px;
}

.progress-text {
    color: var(--text-sub);
    margin-top: 25px;
    font-size: 0.8rem;
    letter-spacing: 0.5px;
}

#feedback-area, #mcq-feedback-area, #mastery-feedback-area {
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    animation: fadeIn 0.3s ease;
    width: 100%;
}

.big-icon {
    font-size: 3rem;
    margin-bottom: 15px;
    font-weight: 300;
}

.icon-correct { color: var(--success); }
.icon-wrong { color: var(--error); }

.result-status {
    font-size: 1.1rem;
    font-weight: 500;
    margin-bottom: 25px;
    letter-spacing: 0.5px;
}

.status-correct { color: var(--success); }
.status-wrong { color: var(--error); }

.result-msg {
    margin-top: 15px;
    font-size: 1rem;
    font-weight: 500;
    text-align: center;
    min-height: 30px;
    transition: color 0.2s;
    letter-spacing: 0.5px;
}
.result-correct { color: var(--success); }
.result-wrong { color: var(--error); }

.answer-reveal {
    font-size: 1.3rem;
    margin-bottom: 15px;
    color: var(--text-sub);
    display: flex;
    align-items: center;
    gap: 12px;
    justify-content: center;
}

/* 精通模式的答案揭曉：英文在上、中文在下，避免全部擠成一行難以閱讀 */
.answer-reveal-stacked {
    flex-direction: column;
    gap: 10px;
    margin-bottom: 22px;
}

.answer-reveal-label {
    font-size: 0.78rem;
    color: var(--text-sub);
    letter-spacing: 2px;
}

.answer-reveal-main {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    flex-wrap: wrap;
}

.answer-reveal-en {
    font-size: 1.9rem;
    font-weight: 600;
    color: var(--text-main);
    line-height: 1.25;
    overflow-wrap: break-word;
}

.answer-reveal-zh {
    font-size: 1rem;
    color: var(--text-sub);
    line-height: 1.6;
    max-width: 92%;
    margin: 0 auto;
}

.tts-btn-large {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-sub);
    cursor: pointer;
    font-size: 0.85rem;
    transition: all 0.2s;
}

@media (hover: hover) {
    .tts-btn-large:hover {
        color: var(--accent);
        border-color: var(--text-sub);
    }
}

/* 底色交給 .btn 的磨砂玻璃，這裡只管尺寸與圓角 */
.btn-next-big {
    font-size: 1.05rem;
    padding: 14px;
    margin-top: 30px;
    border-radius: 8px;
    width: 100%;
}

.mcq-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 15px;
    margin-bottom: 20px;
}

.btn-mcq {
    background: var(--card-bg);
    border: 1px solid var(--border);
    color: var(--text-main);
    padding: 18px;
    border-radius: 12px;
    font-size: 1rem;
    cursor: pointer;
    transition: all 0.2s;
    overflow-wrap: break-word;
    letter-spacing: 0.5px;
}

@media (hover: hover) {
    .btn-mcq:hover {
        border-color: var(--text-sub);
        transform: translateY(-1px);
    }
}

@media (max-width: 480px) {
    .mcq-grid { grid-template-columns: 1fr; }
}

/* ======= 雙向連接 (Match) Mode Styles ======= */
.match-container {
    display: flex;
    gap: 15px;
    justify-content: space-between;
    width: 100%;
    margin-top: 20px;
}

.match-col {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 48%;
}

.match-btn {
    background: var(--card-bg);
    border: 1px solid var(--border);
    color: var(--text-main);
    padding: 14px 10px;
    border-radius: 8px;
    font-size: 0.95rem;
    cursor: pointer;
    transition: all 0.2s;
    overflow-wrap: break-word;
}

@media (hover: hover) {
    .match-btn:hover { border-color: var(--text-sub); }
}
.match-btn.selected { border-color: var(--btn-primary); background: rgba(59, 130, 246, 0.1); }
.match-btn.matched { border-color: var(--success); background: rgba(76, 175, 80, 0.05); color: var(--success); opacity: 0.5; cursor: default; }
.match-btn.wrong { border-color: var(--error); background: rgba(244, 67, 54, 0.1); animation: shake 0.3s; }

@keyframes shake {
    0%, 100% {transform: translateX(0);}
    25% {transform: translateX(-4px);}
    75% {transform: translateX(4px);}
}

/* ======= AI 單字閃卡 Styles ======= */
.wm-card-wrap {
    max-width: 380px;
    margin: 0 auto;
}

.wm-flip-card {
    width: 100%;
    height: 460px;
    perspective: 1400px;
    cursor: pointer;
}

.wm-flip-inner {
    position: relative;
    width: 100%;
    height: 100%;
    transition: transform 0.6s cubic-bezier(0.4, 0.1, 0.2, 1);
    transform-style: preserve-3d;
}

.wm-flip-inner.flipped {
    transform: rotateY(180deg);
}

.wm-flip-front, .wm-flip-back {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
    border-radius: 18px;
    padding: 0;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    background: linear-gradient(160deg, #1a1a1a 0%, #111 100%);
    border: 1px solid #333;
    box-shadow: 0 6px 20px rgba(0,0,0,.6), 0 24px 60px rgba(0,0,0,.75);
    overflow: hidden;
}

.wm-flip-back {
    transform: rotateY(180deg);
}

/* Corner L-bracket marks */
.wm-corner {
    position: absolute;
    width: 14px;
    height: 14px;
    pointer-events: none;
    z-index: 2;
}
.wm-corner-tl { top: 14px; left: 14px; border-top: 1.5px solid #383838; border-left: 1.5px solid #383838; }
.wm-corner-tr { top: 14px; right: 14px; border-top: 1.5px solid #383838; border-right: 1.5px solid #383838; }
.wm-corner-bl { bottom: 14px; left: 14px; border-bottom: 1.5px solid #383838; border-left: 1.5px solid #383838; }
.wm-corner-br { bottom: 14px; right: 14px; border-bottom: 1.5px solid #383838; border-right: 1.5px solid #383838; }

/* Top accent stripe */
.wm-card-accent {
    height: 3px;
    background: linear-gradient(90deg, #00bcd4 0%, #0097a7 100%);
    flex-shrink: 0;
}

/* Header row (front) */
.wm-card-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 13px 18px 11px;
    border-bottom: 1px solid #232323;
    flex-shrink: 0;
}

.wm-card-label {
    font-size: 0.68rem;
    color: #3a3a3a;
    letter-spacing: 1.8px;
    text-transform: uppercase;
}

.wm-pos {
    font-size: 0.7rem;
    background: #1e1e1e;
    color: #c17b20;
    padding: 2px 8px;
    border-radius: 4px;
    border: 1px solid #2e2e2e;
}

/* Main area (front) */
.wm-card-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 20px 28px;
    text-align: center;
}

.wm-word {
    font-size: 2.4rem;
    font-weight: 700;
    color: var(--text-main);
    letter-spacing: 0.5px;
    word-break: break-word;
    line-height: 1.2;
}

.wm-card-divider {
    width: 48px;
    height: 1px;
    background: #2a2a2a;
    margin: 18px auto;
}

.wm-zh {
    font-size: 1.05rem;
    color: #999;
}

/* Footer row (both sides) */
.wm-card-footer-row {
    border-top: 1px solid #232323;
    padding: 11px 18px;
    text-align: center;
    flex-shrink: 0;
}

.wm-flip-hint {
    font-size: 0.7rem;
    color: #383838;
    letter-spacing: 0.5px;
}

/* Back header row */
.wm-back-header-row {
    padding: 13px 18px 11px;
    border-bottom: 1px solid #232323;
    flex-shrink: 0;
}

.wm-back-wordlabel {
    font-size: 1rem;
    font-weight: 600;
    color: #ddd;
    letter-spacing: 0.5px;
}

.wm-back-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 16px 18px 8px;
}

.wm-back-section {
    margin-bottom: 18px;
    padding-left: 12px;
    border-left: 2px solid #2a2a2a;
}

.wm-back-section:last-child {
    margin-bottom: 0;
}

.wm-back-title {
    font-size: 0.78rem;
    font-weight: 600;
    color: #00bcd4;
    margin-bottom: 6px;
    letter-spacing: 0.3px;
}

.wm-back-text {
    font-size: 0.88rem;
    line-height: 1.75;
    color: #b8b8b8;
}

.wm-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    gap: 14px;
    color: var(--text-sub);
    font-size: 0.9rem;
    text-align: center;
}

.wm-spinner {
    width: 34px;
    height: 34px;
    border: 3px solid rgba(0, 188, 212, 0.2);
    border-top-color: #00bcd4;
    border-radius: 50%;
    animation: wmSpin 0.8s linear infinite;
}

@keyframes wmSpin {
    to { transform: rotate(360deg); }
}

.wm-nav-row {
    display: flex;
    gap: 12px;
    max-width: 380px;
    margin: 24px auto 0;
}

.wm-nav-row .btn, .wm-nav-row .btn-outline {
    flex: 1;
    margin: 0;
}

.wm-nav-row .btn:disabled,
.wm-nav-row .btn-outline:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

/* 卡片飛出/飛入動畫 */
.wm-fly-left {
    animation: wmFlyOutLeft 0.35s ease forwards;
}

.wm-fly-right {
    animation: wmFlyOutRight 0.35s ease forwards;
}

.wm-fly-in-right {
    animation: wmFlyInRight 0.4s ease forwards;
}

.wm-fly-in-left {
    animation: wmFlyInLeft 0.4s ease forwards;
}

@keyframes wmFlyOutLeft {
    to { transform: translateX(-130%) rotate(-10deg); opacity: 0; }
}

@keyframes wmFlyOutRight {
    to { transform: translateX(130%) rotate(10deg); opacity: 0; }
}

@keyframes wmFlyInRight {
    from { transform: translateX(130%) rotate(10deg); opacity: 0; }
    to { transform: translateX(0) rotate(0); opacity: 1; }
}

@keyframes wmFlyInLeft {
    from { transform: translateX(-130%) rotate(-10deg); opacity: 0; }
    to { transform: translateX(0) rotate(0); opacity: 1; }
}

@keyframes pulse {
    0% { transform: scale(1); }
    50% { transform: scale(1.05); }
    100% { transform: scale(1); }
}

/* ======= Reading Mode Styles ======= */
.reading-body {
    font-size: 1rem;
    line-height: 2;
    color: var(--text-main);
}

.rd-para {
    margin-bottom: 1.4em;
}

.rd-word {
    cursor: pointer;
    border-radius: 3px;
    transition: background 0.15s;
}

@media (hover: hover) {
    .rd-word:hover {
        background: rgba(233, 30, 99, 0.15);
        color: #e91e63;
    }
}

.rd-word.saved {
    background: rgba(233, 30, 99, 0.12);
    color: #e91e63;
    font-weight: 600;
}

.rd-popup {
    position: absolute;
    z-index: 999;
    background: #1e1e1e;
    border: 1px solid rgba(233, 30, 99, 0.4);
    border-radius: 14px;
    padding: 14px 16px;
    width: 210px;
    box-shadow: 0 8px 30px rgba(0,0,0,0.5);
    animation: fadeIn 0.15s ease;
}

.reading-list-item {
    background: var(--card-bg);
    border: 1px solid #2a2a2a;
    border-radius: 14px;
    padding: 16px;
    margin-bottom: 12px;
    cursor: pointer;
    transition: border-color 0.2s, box-shadow 0.2s;
}

@media (hover: hover) {
    .reading-list-item:hover {
        border-color: #e91e63;
        box-shadow: 0 0 16px rgba(233, 30, 99, 0.15);
    }
}

.reading-list-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-main);
    margin-bottom: 4px;
    line-height: 1.4;
}

.reading-list-meta {
    font-size: 0.75rem;
    color: #e91e63;
    margin-bottom: 6px;
}

.reading-list-desc {
    font-size: 0.82rem;
    color: var(--text-sub);
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.reading-word-item {
    padding: 10px 14px;
    background: var(--card-bg);
    border-radius: 10px;
    margin-bottom: 8px;
    display: flex;
    align-items: center;
}

/* ======= Cloze Mode Styles ======= */
.cloze-sentence-box {
    background: var(--card-bg);
    border: 1px solid rgba(156, 33, 176, 0.3);
    border-radius: 16px;
    padding: 24px 20px;
    font-size: 1.15rem;
    line-height: 2;
    color: var(--text-main);
    text-align: center;
    min-height: 80px;
    box-shadow: 0 0 24px rgba(156, 33, 176, 0.08);
}

.cloze-blank {
    color: #9c27b0;
    font-weight: 700;
    letter-spacing: 3px;
    border-bottom: 2px solid #9c27b0;
    padding: 0 4px;
}

.cloze-input {
    flex: 1;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--text-main);
    font-size: 1rem;
    padding: 12px 14px;
    outline: none;
    transition: border-color 0.2s;
}

.cloze-input:focus {
    border-color: #9c27b0;
    box-shadow: 0 0 0 2px rgba(156, 33, 176, 0.15);
}

.cloze-input:disabled {
    opacity: 0.6;
}

/* ======= Puzzle Mode Styles ======= */
.puzzle-container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-top: 20px;
    min-height: 50px;
}

.letter-tile {
    width: 36px;
    height: 36px;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-weight: 500;
    font-size: 1.1rem;
    cursor: pointer;
    background: var(--card-bg);
    color: var(--text-main);
    user-select: none;
}

@media (hover: hover) {
    .letter-tile:hover { border-color: var(--text-sub); }
}
.letter-tile.empty { border: 1px dashed rgba(150, 150, 150, 0.45); background: transparent; color: transparent; cursor: default; }
/* 下一個字母會放進來的那一格 */
.letter-tile.empty.next { border-color: var(--text-main); background: rgba(255, 255, 255, 0.04); }
/* 用掉的字母留著位子，不讓後面的往前補（排版固定才好按） */
.letter-tile.used { visibility: hidden; pointer-events: none; }

/* 拼圖「答案列」：長單字先縮一點點，縮到還認得出來的下限就換行，
   不會一路縮到看不清楚（--tile-size / --tile-gap 由 fitPuzzleAnswerRow 寫入）。
   下方供玩家點擊的字母池不套用此規則，按鈕大小維持不變好按。 */
.puzzle-answer-row {
    flex-wrap: nowrap;
    gap: var(--tile-gap, 8px);
}

.puzzle-answer-row .letter-tile {
    flex: 0 0 auto;
    width: var(--tile-size, 36px);
    height: var(--tile-size, 36px);
    font-size: calc(var(--tile-size, 36px) * 0.5);
    border-radius: calc(var(--tile-size, 36px) * 0.17);
}

/* 片語：同一個英文字的磚塊包成一組，折行只會發生在組與組之間。
   字與字之間的距離也拉開，不然整串字母黏在一起看不出斷在哪。 */
.puzzle-answer-row.pz-grouped {
    column-gap: calc(var(--tile-gap, 8px) * 2.4);
    row-gap: calc(var(--tile-gap, 8px) * 1.4);
}
.pz-word {
    display: flex;
    flex: 0 0 auto;
    flex-wrap: nowrap;              /* 一個字預設不切開 */
    gap: var(--tile-gap, 8px);
    justify-content: center;
}

/* ======= Memory Mode Styles ======= */
.memory-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    margin-top: 20px;
}

.memory-card {
    background-color: transparent;
    height: 80px;
    perspective: 1000px;
    cursor: pointer;
}

.memory-inner {
    position: relative;
    width: 100%;
    height: 100%;
    text-align: center;
    transition: transform 0.5s;
    transform-style: preserve-3d;
    border-radius: 8px;
}

.memory-card.flipped .memory-inner { transform: rotateY(180deg); }
.memory-card.matched .memory-inner { transform: rotateY(180deg); opacity: 0.4; }

.memory-front, .memory-back {
    position: absolute;
    width: 100%;
    height: 100%;
    backface-visibility: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    padding: 6px;
    font-size: 0.85rem;
    border: 1px solid var(--border);
}

.memory-back {
    background-color: #1a1a1a;
    color: #444;
    font-size: 1.2rem;
}

.memory-front {
    background-color: var(--card-bg);
    color: var(--accent);
    transform: rotateY(180deg);
    overflow-wrap: break-word;
    line-height: 1.3;
}

/* ======= YouGlish Mode Styles ======= */
.yg-open-btn {
    display: block;
    width: 100%;
    padding: 18px;
    margin-bottom: 15px;
    background: #111;
    border: 1px solid #444;
    border-radius: 12px;
    color: white;
    font-size: 0.95rem;
    cursor: pointer;
    text-align: center;
    transition: all 0.2s;
    text-decoration: none;
    letter-spacing: 0.5px;
}

@media (hover: hover) {
    .yg-open-btn:hover { background: #1c1c1c; border-color: var(--text-sub); }
}
.yg-open-btn .yg-btn-label { font-size: 0.8rem; color: var(--text-sub); margin-top: 6px; }
.yg-tip { color: var(--text-sub); font-size: 0.85rem; margin-bottom: 24px; line-height: 1.6; letter-spacing: 0.5px; }
.yg-word-display { font-size: 2.2rem; color: var(--accent); margin-bottom: 6px; }
.yg-zh-display { font-size: 1.1rem; color: var(--text-sub); margin-bottom: 25px; }

/* ======= Export Menu Styles ======= */
.export-menu {
    position: absolute;
    right: 0;
    top: 100%;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px;
    z-index: 100;
    flex-direction: column;
    gap: 8px;
    min-width: 130px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.6);
    display: none;
}

.export-menu.active { display: flex; }

.group-title { font-size: 0.9rem; font-weight: 500; text-transform: uppercase; color: var(--text-sub); letter-spacing: 1px; margin: 25px 0 10px 0; padding-bottom: 6px; border-bottom: 1px solid #222; text-align: left; }
.hidden { display: none !important; }
.flex-row { display: flex; gap: 10px; }
.checkbox-wrapper { display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; }
input[type="checkbox"] { accent-color: #ffffff; transform: scale(1.1); }
.mode-badge { font-size: 0.7rem; background: #222; padding: 3px 8px; border-radius: 4px; color: var(--text-sub); letter-spacing: 0.5px; }
.mode-badge.active { background: var(--warning); color: #000; font-weight: bold; }
.import-section { margin-top: 15px; border: 1px dashed var(--border); padding: 15px; border-radius: 8px; }
/* 展開／收合時才掛上。只在動畫進行中裁切與過渡 ——
   常駐 overflow:hidden 的話，裡面的下拉或提示會被邊框切掉。 */
.import-section.import-animating {
    overflow: hidden;
    transition: max-height 0.26s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.2s ease;
}
.import-trigger {
    font-size: 0.8rem; color: var(--text-sub); text-decoration: underline; cursor: pointer;
    text-align: right; display: block; margin-bottom: 6px; letter-spacing: 0.5px;
    transition: color 0.18s;
}
.import-trigger:active { color: var(--text-main); }
/* 免費使用者看到的「Pro」小標，掛在「智能匯入」那顆按鈕上 */
.import-pro-tag {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    color: #f0c040;
    border: 1px solid rgba(240, 192, 64, 0.6);
    border-radius: 6px;
    padding: 1px 5px;
    margin-left: 5px;
    vertical-align: middle;
}

@media (prefers-reduced-motion: reduce) {
    .import-section.import-animating { transition: none; }
}

@keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

/* 精通模式的按鈕：原本是實心深紫／深綠，現在只換 .btn 的顏色變數，
   底色與發光交給同一套磨砂玻璃 */
.mastery-btn-comp { --btn-tint: 156,  39, 176; --btn-ink: #e4bcee; }
.mastery-btn-beta { --btn-tint: 239, 184, 45; --btn-ink: #ffe59a; }
.mastery-btn-conn { --btn-tint:   0, 150, 136; --btn-ink: #9fdcd4; }
.mastery-btn-fc   { --btn-tint:   0, 188, 212; --btn-ink: #a6e7f0; }

/* ======= Custom Modal Styles (全新彈窗引擎) ======= */
#silen-modal-overlay {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background: rgba(0, 0, 0, 0.75); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
    display: flex; justify-content: center; align-items: center;
    z-index: 9999; opacity: 0; transition: opacity 0.2s ease;
    pointer-events: none;
}
#silen-modal-overlay.show { opacity: 1; pointer-events: auto; }
.silen-modal-box {
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 12px; padding: 25px; width: 90%; max-width: 380px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.8);
    transform: translateY(20px) scale(0.95); transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
#silen-modal-overlay.show .silen-modal-box { transform: translateY(0) scale(1); }
.silen-modal-msg { font-size: 1.05rem; color: var(--text-main); margin-bottom: 20px; line-height: 1.6; white-space: pre-wrap; letter-spacing: 0.5px; font-weight: 400;}
.silen-modal-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 10px; }
#silen-modal-input, #silen-modal-textarea {
    width: 100%; background: #0a0a0a; border: 1px solid var(--border);
    color: var(--text-main); padding: 12px; border-radius: 8px; margin-bottom: 20px;
    font-family: var(--font-family); font-size: 0.95rem; letter-spacing: 0.5px;
}
#silen-modal-textarea { resize: vertical; min-height: 100px; }

/* ======= 🟢 即時綠點呼吸燈與設定面板 ======= */
.breathing-dot {
    width: 6px;
    height: 6px;
    background-color: var(--success);
    border-radius: 50%;
    box-shadow: 0 0 6px var(--success);
    animation: breath 2s infinite ease-in-out;
    /* flex 項目預設可以被壓縮。人數變成兩位數之後那一行變寬，
       這顆點就被擠成 5.4px 寬、6px 高 —— 配上 border-radius: 50%
       就是一顆橫向壓扁的橢圓，看起來像缺了一角。
       它是固定尺寸的裝飾，不該參與伸縮。 */
    flex: 0 0 6px;
}

@keyframes breath {
    0%, 100% { opacity: 0.3; transform: scale(0.8); }
    50% { opacity: 1; transform: scale(1.3); }
}

#silen-settings-overlay {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background: rgba(0, 0, 0, 0.75); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
    display: flex; justify-content: center; align-items: center;
    z-index: 9999; opacity: 0; transition: opacity 0.2s ease; pointer-events: none;
}
#silen-settings-overlay.show { opacity: 1; pointer-events: auto; }
#silen-settings-overlay.show .silen-modal-box { transform: translateY(0) scale(1); }

/* 雲端備份清單。z-index 要比設定高，不然會被壓在設定後面看不到 */
#cloud-backup-overlay {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background: rgba(0, 0, 0, 0.78); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
    display: flex; justify-content: center; align-items: center;
    z-index: 10000; opacity: 0; transition: opacity 0.2s ease; pointer-events: none;
}
#cloud-backup-overlay.show { opacity: 1; pointer-events: auto; }
#cloud-backup-overlay.show .silen-modal-box { transform: translateY(0) scale(1); }
.cb-row {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px;
    background: var(--card-bg);
}
.cb-row-main { flex: 1; min-width: 0; }
.cb-when { color: var(--text-main); font-size: 0.88rem; }
.cb-size { color: var(--text-sub); font-size: 0.78rem; margin-top: 2px; }
.cb-row.cb-bad { border-color: #e57373; }
.cb-row.cb-bad .cb-size { color: #e57373; }

/* 隱藏原生的醜醜 checkbox */
.checkbox-wrapper input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 22px;
    height: 22px;
    border: 2px solid var(--border);
    border-radius: 4px;
    cursor: pointer;
    position: relative;
    transition: all 0.2s ease;
    flex-shrink: 0; 
}


.checkbox-wrapper input[type="checkbox"]:checked {
    background-color: var(--accent);
    border-color: var(--accent);
}


.checkbox-wrapper input[type="checkbox"]:checked::after {
    content: '✔';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: #000; /* 勾勾顏色 */
    font-size: 14px;
    font-weight: bold;
}


@media (hover: hover) {
    .checkbox-wrapper:hover input[type="checkbox"] {
        border-color: var(--accent);
    }
}

/* ========================================================= */
/* 💎 頂級 UX 升級：Liquid Glass、微動效與畫面呼吸感 */
/* ========================================================= */

/* 1. Liquid Glass (毛玻璃) 卡片質感
   這裡原本把底色、邊框、陰影全部寫死（rgba(20,20,20,.45) + 濃重黑影）。
   那是為純黑背景設計的：黑底上看不到黑影。換成漸層主題之後，
   卡片變成一塊不吃主題色的灰板，底下還浮著一圈明顯的黑影，非常突兀。
   改成走變數，預設值維持原本的曜黑外觀，漸層主題則沿用該主題的卡片色。 */
.card, .store-card, .acc-card, .silen-modal-box {
    background: var(--glass-card-bg) !important;
    backdrop-filter: blur(16px) saturate(120%);
    -webkit-backdrop-filter: blur(16px) saturate(120%);
    border: 1px solid var(--glass-card-border) !important;
    box-shadow: var(--glass-card-shadow) !important;
    transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

/* 2. 卡片懸浮光暈 (Hover Glow) */
@media (hover: hover) {
    .store-card:hover, .acc-card:hover, .book-item:hover {
        transform: translateY(-3px);
        box-shadow: var(--glass-card-shadow-hover) !important;
        border-color: var(--glass-card-border-hover) !important;
    }
}

/* 3. 按鈕的 3D 觸覺回饋 (Micro-interactions) */
.btn {
    transition: all 0.2s cubic-bezier(0.25, 0.8, 0.25, 1) !important;
    position: relative;
    overflow: hidden;
}
@media (hover: hover) {
    /* 泛光跟著按鈕自己的顏色走，不要寫死白色 ——
       紅色按鈕發白光會看起來髒 */
    .btn:hover {
        box-shadow:
            0 0 22px rgba(var(--btn-tint, 255, 255, 255), 0.20),
            inset 0 1px 0 rgba(255, 255, 255, 0.22) !important;
    }
    .btn-outline:hover {
        box-shadow: none !important;
    }
}
.btn:active {
    transform: scale(0.96) translateY(2px) !important; /* 點擊時瞬間微縮+下沉 */
    box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.22) !important; /* 壓下去是凹的，不是浮的 */
    opacity: 0.85;
}

/* 4. 畫面切換的「呼吸感」(Fade In & Slide Up) */
/* 只要畫面移除 hidden 類別，就會自動觸發這個優雅的浮現動畫 */
div[id^="view-"]:not(.hidden) {
    animation: viewFadeIn 0.35s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

/* 收尾一定要是 transform: none，不能寫 translateY(0)。
   animation-fill-mode 是 forwards，最後一格會永遠留在元素上，而只要元素身上
   有 transform（哪怕位移是 0），它就變成裡面所有 position:fixed 的定位基準 ——
   生死戰的押注／偷時間鈕就是這樣掉到內容最下面，玩家得往下滑才點得到。 */
@keyframes viewFadeIn {
    from {
        opacity: 0;
        transform: translateY(15px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

/* 對戰畫面整場都有浮在上面的技能鈕，連動畫那 0.35 秒都不能讓它跳位，
   所以這一頁的進場只淡入、不位移。 */
#view-dm-game:not(.hidden) {
    animation: dmViewIn 0.35s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

/* ── 對戰畫面：固定一屏，不給滑 ────────────────────────────────
   玩家回報「要滑動才按得到選項，那幾秒就輸了」。
   原本是一路往下堆，內容多高就多高 —— 在 360x740 超出 93px、
   360x640 超出 193px，最後一個選項直接在畫面外。

   逐項砍像素沒有用，超出的量會隨螢幕大小變動。改成整頁鎖成一屏，
   選項區塊吃掉剩下的高度 —— 從結構上就不可能溢出，不管什麼螢幕。

   用 dvh 不用 vh：手機上 100vh 是「網址列收起來之後」的高度，
   用它算會永遠多一截，那一截正好就是被切掉的最後一個選項。
   ────────────────────────────────────────────────────────── */
body.dm-playing { overflow: hidden; }
/* 對戰時把全站頁首收起來。
   兩個理由，都成立：
   1. 它是 sticky 並且用 margin-top: calc(-40px - safe-top) 抵消容器原本的
      上內距。對戰把容器內距改小了，那個負值就把它拉過頭 —— 直接蓋掉
      「投降」跟「第 N 題」。玩家回報「上方的按鈕與字體都被導覽列吃掉」。
   2. 就算對齊了也不該留 —— 品牌名和「幾人正在學習」在一場五秒的對戰裡
      是純雜訊，而且吃掉大約 70px，正好是我們在搶的那段高度。 */
body.dm-playing #main-header { display: none !important; }
body.dm-playing .container {
    height: 100vh;
    height: 100dvh;
    min-height: 0;
    box-sizing: border-box;
    padding-top: calc(8px + var(--safe-top));
    padding-bottom: calc(8px + var(--safe-bottom, 0px));
    overflow: hidden;
}
body.dm-playing #view-dm-game:not(.hidden) {
    flex: 1;
    min-height: 0;
    /* switchView 是用 style.setProperty('display','block','important') 開畫面的，
       inline 的 !important 蓋得過一般規則 —— 這裡不加 !important 的話，
       這一層永遠是 block，底下的 flex:1 全部失效（看起來像「有做但沒用」）。 */
    display: flex !important;
    flex-direction: column;
}
body.dm-playing #view-dm-game .nav-bar { flex-shrink: 0; margin-bottom: 6px; }
body.dm-playing .dm-hud { flex-shrink: 0; margin: 0 0 10px; gap: 9px; }
/* 玩家卡是最大的一塊（原本 218px）。要壓，但第一版壓過頭了 ——
   壓到 70px 之後名字、定位、血條、資源四層全黏在一起，玩家回報
   「這都全部擠在一起了」。
   選項區其實還有餘裕（360x640 上有 276px，四個按鈕舒服地用只要 205px），
   所以把行距還回去。資訊一個都不能拿掉 —— 血量、定位、剩幾次護盾
   都是當下要拿來做決定的。 */
body.dm-playing .dm-side { padding: 10px 12px; border-radius: 12px; }
body.dm-playing .dm-side-top { gap: 10px; }
body.dm-playing .dm-side-name { font-size: 0.85rem; }
body.dm-playing .dm-side-role { margin-top: 3px; font-size: 0.68rem; }
body.dm-playing .dm-hp { font-size: 1.1rem; }
body.dm-playing .dm-bar { margin-top: 10px; height: 8px; }
body.dm-playing .dm-pips { margin-top: 8px; gap: 8px; }
/* 這個數字要跟 dm.js 的 AVA 一致。CSS 寫 32、程式畫 44 的時候，
   圖片直接溢出去壓在名字上（玩家回報「名字和角色都插進頭像裡了」）。
   而且不能寫死 img 的大小 —— 頭像框是疊在上面、故意比較大的那一張。 */
body.dm-playing .dm-ava { width: 36px; height: 36px; }

body.dm-playing .dm-stage {
    flex: 1; min-height: 0;
    padding-bottom: 0;          /* 那 78px 是留給浮動技能鈕的，現在不浮動了 */
    display: flex; flex-direction: column;
}
body.dm-playing .dm-phase:not(.hidden) {
    flex: 1; min-height: 0;
    display: flex; flex-direction: column;
}
/* The fourth answer must remain reachable on short browser viewports. Let the
   answer phase scroll instead of clipping minimum-sized choice buttons. */
body.dm-playing #dm-phase-answer:not(.hidden) {
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
    padding-bottom: 8px;
}
/* 結算區必須跟著可用高度縮小，避免 300px 的最小高度把技能鈕推到螢幕外。 */
body.dm-playing .dm-reveal {
    flex: 1;
    min-height: 0;
    padding: 16px 8px;
    box-sizing: border-box;
}
body.dm-playing .dm-clock { flex-shrink: 0; margin-bottom: 8px; }
body.dm-playing .dm-word {
    flex-shrink: 0;
    margin: 10px 0 12px;
    /* 螢幕越小字越小，但不會小到看不清楚 */
    font-size: clamp(1.4rem, 7vw, 2rem);
}
/* 選項區吃掉剩下的高度，四個按鈕平分。畫面矮就自己變扁，
   但有 42px 的下限 —— 再小就按不準了。 */
body.dm-playing .dm-options {
    flex: 1 0 auto; min-height: auto;
    gap: 7px;
}
body.dm-playing .dm-option {
    flex: 1 0 44px; min-height: 44px;
    display: flex; align-items: center;
    padding: 8px 14px;
    touch-action: pan-y;
}
/* 平板：選項會被撐得很高，字卻還是手機的大小，看起來空空的、不好讀（10/07 平板玩家回報）。
   手機不變；寬度 600 以上（平板）字跟著螢幕短邊放大（約 24～29px，上限 1.8rem），
   而且置中 —— 不然一大塊按鈕只有左邊一小段字。 */
@media (min-width: 600px) {
    body.dm-playing .dm-option {
        font-size: clamp(1.2rem, 3.6vmin, 1.8rem);
        justify-content: center; text-align: center; padding: 10px 24px;
    }
}
.dm-curser-skills {
    display: flex; gap: 8px; flex-shrink: 0;
    margin-top: 8px; width: 100%; box-sizing: border-box;
}
.dm-curse-btn {
    flex: 1; min-width: 0; min-height: 46px; padding: 6px 8px;
    border: 1px solid rgba(190, 145, 255, .48); border-radius: 14px;
    background: linear-gradient(145deg, rgba(100, 52, 133, .46), rgba(43, 31, 65, .68));
    color: #f6eaff; box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 7px 22px rgba(26, 8, 45, .2);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    font-family: inherit; font-size: .8rem; font-weight: 700; cursor: pointer;
}
.dm-curse-btn span { display: block; font-size: .67rem; font-weight: 400; opacity: .72; }
.dm-curse-btn:disabled { opacity: .52; cursor: default; }
.dm-curse-btn.dm-curse-armed { border-color: #dc9aff; box-shadow: 0 0 16px rgba(193, 103, 249, .36), inset 0 1px 0 rgba(255,255,255,.2); }
.dm-options.dm-options-cursed { gap: 12px; }
.dm-option.dm-option-cursed:nth-child(4n+1) {
    width: 82%; align-self: flex-start;
    --curse-x1: -4px; --curse-x2: 34px; --curse-y1: -3px; --curse-y2: 4px;
    --curse-a: .96; --curse-b: 1.06;
    animation-duration: 1.24s; animation-delay: -.22s;
}
.dm-option.dm-option-cursed:nth-child(4n+2) {
    width: 72%; align-self: flex-end;
    --curse-x1: -34px; --curse-x2: 4px; --curse-y1: 4px; --curse-y2: -3px;
    --curse-a: 1.05; --curse-b: .95;
    animation-duration: 1.08s; animation-delay: -.73s;
}
.dm-option.dm-option-cursed:nth-child(4n+3) {
    width: 76%; align-self: flex-start;
    --curse-x1: 34px; --curse-x2: -6px; --curse-y1: 3px; --curse-y2: -4px;
    --curse-a: .95; --curse-b: 1.07;
    animation-duration: 1.42s; animation-delay: -1.12s;
}
.dm-option.dm-option-cursed:nth-child(4n+4) {
    width: 76%; align-self: flex-end;
    --curse-x1: -32px; --curse-x2: 6px; --curse-y1: -4px; --curse-y2: 3px;
    --curse-a: 1.04; --curse-b: .96;
    animation-duration: 1.17s; animation-delay: -.39s;
}
.dm-option.dm-option-cursed {
    animation-name: dmCurseWobble;
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
    animation-direction: alternate;
    box-shadow: inset 0 0 0 1px rgba(213, 160, 255, .18);
}
@keyframes dmCurseWobble {
    from { transform: translate(var(--curse-x1), var(--curse-y1)) scaleX(var(--curse-a)); }
    to { transform: translate(var(--curse-x2), var(--curse-y2)) scaleX(var(--curse-b)); }
}
@media (prefers-reduced-motion: reduce) {
    .dm-option.dm-option-cursed { animation: none; transform: none; }
}
body.dm-playing .dm-note { flex-shrink: 0; margin-top: 6px; min-height: 0; }

/* 決策區的兩個行動並排，留下足夠高度給送出鈕。短螢幕可在區內捲動，
   不再用 flex:1/min-height:0 把三顆按鈕擠到一起。 */
body.dm-playing #dm-phase-decide:not(.hidden) {
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
}
body.dm-playing .dm-decide-head { flex-shrink: 0; margin: 5px 0 12px; }
body.dm-playing .dm-decide-count { margin-top: 7px; font-size: 1.75rem; }
body.dm-playing .dm-choices {
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}
body.dm-playing .dm-choices.hidden { display: none; }
body.dm-playing .dm-choices .dm-choice {
    min-width: 0;
    min-height: 92px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 12px;
}
body.dm-playing #dm-phase-decide.dm-clash .dm-choices .dm-choice { min-height: 72px; }
body.dm-playing #dm-act-row .dm-choice-burst:not(.hidden) { grid-column: 1 / -1; }
body.dm-playing #dm-phase-decide.dm-clash .dm-clash-guard { grid-template-columns: 1fr; margin-top: 8px; }
body.dm-playing #dm-phase-decide.dm-clash .dm-clash-guard.dm-clash-out { grid-template-columns: repeat(2, minmax(0, 1fr)); }
body.dm-playing #dm-phase-decide.dm-clash .dm-decide-head { margin-bottom: 7px; }
body.dm-playing .dm-choice-d { line-height: 1.35; }
body.dm-playing .dm-commit {
    flex-shrink: 0;
    min-height: 50px;
    margin-top: 12px;
    padding: 11px 16px;
    position: sticky;
    bottom: 0;
    z-index: 2;
    background: var(--card-bg);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}

/* ── 技能鈕不再浮在畫面上 ──────────────────────────────────────
   原本是 position: fixed 釘在右下角，結果直接蓋住第 3、4 個選項 ——
   在 360x640 甚至蓋到第 2 個。玩家要按的東西被自己的技能鈕擋住。
   改成排在選項下面，滿版一條。永遠擋不到，而且拇指一樣搆得到。
   ────────────────────────────────────────────────────────── */
body.dm-playing #dm-steal,
body.dm-playing #dm-seer,
body.dm-playing #dm-bet {
    position: static;
    flex-shrink: 0;
    width: 100%;
    /* 小螢幕上被壓到 40px 以下就按不準了，給一個地板 */
    min-height: 42px;
    box-sizing: border-box;
    align-items: center;
    margin-top: 8px;
    box-shadow: none;
    border-radius: 12px;
    padding: 9px 14px;
    justify-content: center;
    flex-direction: row;
    align-items: baseline;
    gap: 8px;
}
body.dm-playing .dm-seer-sub,
body.dm-playing .dm-bet-sub { opacity: 0.5; }
body.dm-playing #dm-charge {
    position: static; flex-shrink: 0;
    width: 100%; margin-top: 8px; justify-content: center;
}
/* 學習流的浮動球在對戰中也會壓在選項上（實測 [292,343] 54x54）。
   對戰只有五秒，畫面上不該有任何跟這一局無關的東西。 */
body.dm-playing #flow-ball { display: none !important; }
@keyframes dmViewIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* 彈窗、面板裡自己會捲的區塊：捲到頭就停住，不要把剩下的力道傳給後面那一頁。
   沒有這一行的話，清單滑到底之後整個頁面會跟著動，看起來就像卡住了。 */
.wm-back-scroll,
#ecm-sheet,
.fr-send-list,
.add-book-body,
#silen-modal-overlay .silen-modal-msg,
.settings-scroll,
.sh-link,
.ps-rules-body,
.flow-rows,
.checkin-body,
.wr-host {
    overscroll-behavior-y: contain;
}

/* 5. 側邊導覽列 (Sidebar) 極簡白化與收納匣樣式 */
.sidebar {
    background: rgba(15, 15, 15, 0.85) !important;
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    overflow-x: hidden;
}
.sidebar-item {
    border-left: 3px solid transparent !important; /* 移除所有預設顏色 */
    color: var(--text-sub) !important; /* 預設偏灰 */
}
@media (hover: hover) {
    .sidebar-item:hover {
        background: rgba(255, 255, 255, 0.05) !important;
        border-left: 3px solid #fff !important; /* 統一變成白色指示線 */
        color: #fff !important;
    }
}
/* 側邊欄的收納匣已經隨著底部四分頁一起退場，樣式跟著移除 */


/* ==========================================
   🔥 極速心流連擊系統 (Combo UI) 
   ========================================== */
#combo-container {
    position: absolute; 
    top: 65px; /* 稍微上移，避免擋住題目 */
    right: 20px; 
    z-index: 1000; 
    text-align: right; 
    pointer-events: none; /* 絕對不阻擋玩家點擊 */
}
#combo-text {
    font-size: 2.2rem; 
    font-weight: 900; 
    color: #ff9800; 
    font-style: italic; 
    text-shadow: 0 4px 10px rgba(255, 152, 0, 0.4); 
    margin-bottom: 5px; 
    transform-origin: right;
}
.combo-rampage { color: #ff5252 !important; text-shadow: 0 4px 10px rgba(255, 82, 82, 0.5) !important; }
.combo-godlike { color: #e040fb !important; text-shadow: 0 4px 10px rgba(224, 64, 251, 0.5) !important; }

/* 📱 手機版專屬修飾：自動縮小，絕對不擋視線 */
@media (max-width: 600px) {
    #combo-container {
        top: 55px;
        right: 15px;
    }
    #combo-text {
        font-size: 1.5rem;
    }
    #combo-container > div:last-child {
        width: 80px !important; /* 縮短火條 */
        height: 4px !important;
    }
}

@keyframes popScale {
    0% { transform: scale(0.8); opacity: 0.5; }
    50% { transform: scale(1.15); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}

/* ==========================================
   ✨ 題目滑順過場動畫 (Smooth Transition)
   ========================================== */
/* 題目過場：先縮小再放大回彈（pop-in） */
@keyframes questionPopIn {
    0%   { opacity: 0; transform: scale(0.85); }
    55%  { opacity: 1; transform: scale(1.045); }
    100% { opacity: 1; transform: scale(1); }
}

/* 題目進場。
   原本只是 scale(0.85) → 1 彈一下，沒有位移也沒有方向 —— 五十幾題下來
   每一題長得一模一樣，會變成「題目換掉了」而不是「下一題來了」。
   改成從右下方帶著一點角度滑進來，過衝一點再落定，位移給足（46px），
   讓它讀起來是「一張卡片飛進來」。 */
@keyframes mqEnter {
    0%   { opacity: 0; transform: translate3d(46px, 20px, 0) scale(0.90) rotate(2.4deg); }
    58%  { opacity: 1; transform: translate3d(-7px, -4px, 0) scale(1.025) rotate(-0.5deg); }
    100% { opacity: 1; transform: none; }
}
.question-animate {
    animation: mqEnter 0.42s cubic-bezier(0.22, 1, 0.3, 1) forwards;
}

/* 裡面的東西再各自差一點點進來。整塊一起動是「一張圖」，
   分開動才有層次 —— 這是「精細」跟「有動」的差別。 */
.question-animate > .mode-badge,
.question-animate > .question-text,
.question-animate > .hint-text,
.question-animate > .mcq-grid,
.question-animate > .puzzle-container,
.question-animate > .card {
    animation: mqInner 0.36s cubic-bezier(0.2, 0.9, 0.25, 1) both;
}
@keyframes mqInner {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: none; }
}
.question-animate > .mode-badge      { animation-delay: 0.04s; }
.question-animate > .hint-text       { animation-delay: 0.07s; }
.question-animate > .question-text   { animation-delay: 0.09s; }
.question-animate > .mcq-grid,
.question-animate > .puzzle-container,
.question-animate > .card            { animation-delay: 0.15s; }

/* 答對：先被按下去一點，再往左上飛走。
   「離開」比「消失」重要 —— 東西憑空不見，大腦不會覺得完成了一件事。 */
@keyframes mqExitOk {
    0%   { opacity: 1; transform: none; }
    26%  { opacity: 1; transform: translate3d(0, 8px, 0) scale(0.975); }
    100% { opacity: 0; transform: translate3d(-58px, -30px, 0) scale(0.88) rotate(-3.2deg); }
}
.mq-exit-ok { animation: mqExitOk 0.36s cubic-bezier(0.4, 0, 0.7, 0.2) forwards; }

/* 答錯：橫向甩兩下再沉下去。用身體感覺讓人知道錯了，不只是換一個紅色的字 */
@keyframes mqExitBad {
    0%   { transform: translateX(0); }
    14%  { transform: translateX(-13px) rotate(-1.2deg); }
    30%  { transform: translateX(11px) rotate(1deg); }
    46%  { transform: translateX(-8px) rotate(-0.6deg); }
    62%  { transform: translateX(5px); }
    78%  { transform: translateX(-2px); }
    100% { opacity: 0; transform: translateY(16px) scale(0.97); }
}
.mq-exit-bad { animation: mqExitBad 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97) forwards; }

/* 升級提示：答對之後從題目中央往上飄。
   這一條是把「動畫」接到「進度」上 —— 前五十幾題進度條不會動，
   但每答對一次這個字確實往前走了一格，要讓人看得到。 */
.mq-levelup {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9500;
    pointer-events: none;
    font-size: 0.92rem;
    font-weight: 700;
    letter-spacing: 1px;
    color: #7bc67e;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
    white-space: nowrap;
    animation: mqLevelUp 1s cubic-bezier(0.22, 1, 0.3, 1) forwards;
}
@keyframes mqLevelUp {
    0%   { opacity: 0; transform: translate(-50%, 12px) scale(0.8); }
    18%  { opacity: 1; transform: translate(-50%, -6px) scale(1.12); }
    34%  { opacity: 1; transform: translate(-50%, -14px) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -66px) scale(0.94); }
}
.mq-levelup-max { color: #f0c040; }

/* 尊重使用者的「減少動態效果」系統設定 */
@media (prefers-reduced-motion: reduce) {
    .question-animate,
    .question-animate > *,
    .mq-exit-ok, .mq-exit-bad, .mq-levelup { animation: none; }
    .mq-levelup { opacity: 0; }
}
html[data-fx="low"] .question-animate > * { animation: none; }


/* ==========================================
   🧠 連連看 2x2 結算面板 (滑順動畫 + 避開頂部)
   ========================================== */
#memory-summary-overlay {
    position: fixed; 
    top: 60px; /* 🌟 往下挪 60px 避開你的頂部導覽列 (如果還是會蓋到，可以改成 70px) */
    left: 0; right: 0; bottom: 0;
    background: rgba(18, 18, 18, 0.85); /* 稍微調低背景透明度，質感更好 */
    display: none; flex-direction: column; align-items: center; justify-content: center;
    z-index: 900; /* 🌟 降低圖層高度，確保它永遠在導覽列 (通常是1000) 的下層 */
    backdrop-filter: blur(5px);
    animation: fadeInBg 0.2s ease-out forwards; /* 背景淡入動畫 */
}

/* 面板本體的專屬設定 */
.ms-box {
    background: var(--bg-color);
    padding: 25px;
    border-radius: 15px;
    width: 90%;
    max-width: 400px;
    box-sizing: border-box;
    text-align: center;
    border: 1px solid var(--border);
    box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    /* 🌟 加入充滿彈性的果凍彈出動畫 */
    animation: popUpJelly 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; 
}

/* --- 動畫關鍵影格 --- */
@keyframes fadeInBg {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes popUpJelly {
    from { opacity: 0; transform: scale(0.8) translateY(20px); }
    to { opacity: 1; transform: scale(1) translateY(0); }
}

/* (下面保留原本的 ms-grid, ms-card 等設定) */
.ms-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ms-card { background: rgba(255, 255, 255, 0.05); border-radius: 10px; padding: 15px 5px; text-align: center; border: 2px solid transparent; transition: transform 0.2s; }
.ms-card.correct { border-color: rgba(76, 175, 80, 0.5); background: rgba(76, 175, 80, 0.1); }
.ms-card.wrong { border-color: rgba(255, 82, 82, 0.5); background: rgba(255, 82, 82, 0.1); }
.ms-en { font-size: 1.1rem; font-weight: bold; color: #fff; margin-bottom: 4px; }
.ms-zh { font-size: 0.85rem; color: #aaa; margin-bottom: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 5px;}
.ms-status { font-size: 0.8rem; font-weight: bold; padding: 4px 0; border-radius: 4px; display: block; width: 90%; margin: 0 auto;}
.ms-status.c { color: #4caf50; background: rgba(76,175,80,0.2); }
.ms-status.w { color: #ff5252; background: rgba(255,82,82,0.2); }

/* ==========================================
   ✨ Combo 退場動畫
   ========================================== */
@keyframes fadeOutDown {
    0% { opacity: 1; transform: translateY(0) scale(1); }
    100% { opacity: 0; transform: translateY(10px) scale(0.9); }
}

.combo-exit {
    /* 強制執行 0.3 秒的下沉淡出動畫 */
    animation: fadeOutDown 0.3s ease forwards !important; 
}

/* ==========================================
   🎬 全站過渡動畫補強
   ========================================== */

/* --- 通用面板滑入動畫 --- */
@keyframes panelSlideIn {
    from { opacity: 0.3; transform: translateX(14px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes panelSlideInLeft {
    from { opacity: 0.3; transform: translateX(-14px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes panelFadeUp {
    from { opacity: 0.3; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes panelFadeDown {
    from { opacity: 0.3; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.panel-slide-in      { animation: panelSlideIn 0.25s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.panel-slide-in-left { animation: panelSlideInLeft 0.25s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.panel-fade-up       { animation: panelFadeUp 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.panel-fade-down     { animation: panelFadeDown 0.2s ease both; }

/* --- 填空題回饋動畫 --- */
@keyframes feedbackPop {
    0%   { opacity: 0; transform: scale(0.85) translateY(4px); }
    60%  { transform: scale(1.04) translateY(0); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
.cloze-feedback-anim { animation: feedbackPop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }

/* --- 單字彈窗消失動畫 --- */
@keyframes popupFadeOut {
    from { opacity: 1; transform: scale(1) translateY(0); }
    to   { opacity: 0; transform: scale(0.93) translateY(4px); }
}
.rd-popup-hiding { animation: popupFadeOut 0.18s ease forwards; }

/* --- 單字簿收起/展開（高度滑動） --- */
.sortable-group {
    /* overflow: hidden 是分類收合動畫需要的（max-height 0 才不會露出內容），
       但它同時會裁掉單字簿的 hover（translateY(-3px)）與選取（scale(1.01)）——
       前者被切掉上緣 3px，後者左右各被切掉約 2px，圓角看起來像被啃掉一塊。
       這裡留一點內距給變形用，再用等量的負外距把位置補回來，版面不受影響。 */
    overflow: hidden;
    padding: 4px 4px 0;
    margin: -4px -4px 0;
    transition: max-height 0.32s cubic-bezier(0.4, 0, 0.2, 1),
                opacity 0.25s ease,
                padding 0.32s cubic-bezier(0.4, 0, 0.2, 1);
    /* 展開時不設上限（以前 2000px，單字簿多就被截掉）；動畫高度由 app.js 的 setGroupCollapsed 給 */
    max-height: none;
    opacity: 1;
}
.sortable-group.collapsed {
    max-height: 0 !important;
    /* 收合時內距要一起收掉，否則會留下 4px 的空隙 */
    padding-top: 0;
    opacity: 0;
}

/* --- MCQ 選項 stagger 進場 --- */
@keyframes mcqOptionIn {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}
.mcq-option-anim {
    opacity: 0;
    animation: mcqOptionIn 0.22s ease forwards;
}
.mcq-option-anim:nth-child(1) { animation-delay: 0.04s; }
.mcq-option-anim:nth-child(2) { animation-delay: 0.09s; }
.mcq-option-anim:nth-child(3) { animation-delay: 0.14s; }
.mcq-option-anim:nth-child(4) { animation-delay: 0.19s; }

/* --- 書本選取 scale feedback --- */
.book-item {
    transition: transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1),
                border-color 0.2s, background 0.2s !important;
}
.book-item:active { transform: none; }
.book-item.selected { transform: none; }

/* --- 精通模式 L0 卡片進場 --- */
@keyframes masteryCardIn {
    from { opacity: 0; transform: translateY(20px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.mastery-card-enter { animation: masteryCardIn 0.3s cubic-bezier(0.2, 0.8, 0.2, 1) forwards; }

/* --- 閱讀文章單字高亮選中狀態 --- */
.rd-word.active {
    background: rgba(233, 30, 99, 0.2);
    color: #e91e63;
    border-radius: 3px;
}

/* --- 螢光筆標記顏色 --- */
.rd-hl-yellow { background: rgba(255, 230, 0, 0.55) !important; border-radius: 2px; color: inherit !important; }
.rd-hl-green  { background: rgba(72, 199, 116, 0.55) !important; border-radius: 2px; color: inherit !important; }
.rd-hl-pink   { background: rgba(233, 30, 99, 0.4) !important; border-radius: 2px; color: inherit !important; }

/* --- 懸浮工具球（body 直接子元素，不受父容器 transform 影響） --- */
.rd-float-ball {
    position: fixed;
    bottom: 96px;
    right: 20px;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: #e91e63;
    color: #fff;
    font-size: 1.3rem;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 20px rgba(233,30,99,0.5);
    cursor: grab;
    z-index: 9000;
    transition: transform 0.18s, background 0.2s;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
    border: none;
    touch-action: none; /* 阻止瀏覽器處理觸控滾動，讓 JS 全權控制拖動 */
    will-change: left, top; /* GPU 合成，滑動更流暢 */
}
.rd-float-ball:active { transform: scale(0.92); cursor: grabbing; }

/* rd-float-toolbar 已移除，工具按鈕改由 JS 直接定位 */
.rd-tool-btn {
    position: fixed;           /* JS 計算 left/top，放射狀展開 */
    width: 44px;
    height: 44px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.9rem;
    font-weight: 700;
    box-shadow: 0 3px 14px rgba(0,0,0,0.35);
    -webkit-tap-highlight-color: transparent;
    user-select: none;
    z-index: 9000;
    transform-origin: center;
}
.rd-tool-btn.active-tool { outline: 3px solid rgba(255,255,255,0.9); outline-offset: 2px; }

/* --- 儲存文章列表 --- */
.reading-saved-item {
    padding: 14px;
    background: var(--card-bg);
    border-radius: 12px;
    margin-bottom: 10px;
    border: 1px solid var(--border);
    cursor: default;
}
.reading-saved-item-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-main);
    margin-bottom: 4px;
    line-height: 1.4;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.reading-saved-item-meta {
    font-size: 0.78rem;
    color: var(--text-sub);
}

/* --- 翻頁導航 --- */
#rd-page-nav {
    border-top: 1px solid var(--border);
    padding-top: 20px;
}
#rd-page-indicator {
    font-variant-numeric: tabular-nums;
}
#rd-next-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* --- 詞組查詢浮動按鈕 --- */
.rd-phrase-select-btn {
    position: fixed;
    background: #e91e63;
    color: #fff;
    border-radius: 20px;
    padding: 7px 16px;
    font-size: 0.82rem;
    font-weight: 600;
    z-index: 9100;
    box-shadow: 0 2px 14px rgba(233,30,99,0.45);
    cursor: pointer;
    white-space: nowrap;
    transform: translateX(-50%);
    display: none;
    pointer-events: auto;
}

/* --- 詞組查詢彈窗 --- */
.rd-phrase-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.35);
    z-index: 9200;
}
.rd-phrase-popup {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    /* 有些主題的 --card-bg 是半透明的（玻璃感）：底下墊一層不透明的背景色，後面的文章才不會透出來 */
    background: linear-gradient(var(--card-bg), var(--card-bg)), var(--bg-color, #121212);
    border: 1px solid var(--border);
    border-radius: 18px;
    box-shadow: 0 8px 40px rgba(0,0,0,0.45);
    padding: 22px 18px;
    z-index: 9300;
    max-width: 340px;
    width: calc(100vw - 40px);
}

/* --- 通用 shimmer loading skeleton --- */
@keyframes shimmer {
    0%   { background-position: -400px 0; }
    100% { background-position: 400px 0; }
}
.skeleton {
    background: linear-gradient(90deg, #1e1e1e 25%, #2a2a2a 50%, #1e1e1e 75%);
    background-size: 400px 100%;
    animation: shimmer 1.2s infinite;
    border-radius: 6px;
}

/* ======= Pro 會員方案樣式 ======= */
.pro-compare-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 9px 0;
    border-bottom: 1px solid #1e1e1e;
    font-size: 0.88rem;
    color: var(--text-main);
}
.pro-compare-row:last-child { border-bottom: none; }
.pro-free { color: var(--text-sub); font-size: 0.82rem; min-width: 70px; text-align: right; }
.pro-paid { color: #f0c040; font-size: 0.82rem; font-weight: 600; min-width: 70px; text-align: right; }

/* ── 三階方案的對照表 ──────────────────────────────────────────
   三欄在 390px 的手機上會很擠，所以功能名稱用 flex:1 自己吃剩下的空間，
   三個欄位固定寬度、靠右對齊，數字才排得整齊。 */
.tier-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 9px 0;
    border-bottom: 1px solid #1e1e1e;
    font-size: 0.85rem;
    color: var(--text-main);
}
.tier-row:last-child { border-bottom: none; }
.tier-row > span:first-child { flex: 1; min-width: 0; }
.tier-row .t-free,
.tier-row .t-pro,
.tier-row .t-ultra {
    /* 46px 剛好放得下最長的「20 / 日」。原本給 58px，三欄就吃掉 174px，
       390px 的手機上功能名稱只剩八十幾 px，「動態主題（極光／細雨／微塵）」
       被折成三行。數值欄只要放得下就好，多出來的寬度該給名稱。 */
    width: 46px;
    flex-shrink: 0;
    text-align: center;
    font-size: 0.78rem;
    white-space: nowrap;
}
.tier-row .t-free  { color: var(--text-sub); }
.tier-row .t-pro   { color: #f0c040; font-weight: 600; }
.tier-row .t-ultra { color: #b388ff; font-weight: 600; }

/* 表頭要黏在上面，捲動時才知道哪一欄是哪一階 */
.tier-head {
    position: sticky;
    top: 0;
    background: var(--card-bg);
    z-index: 1;
    font-size: 0.72rem;
    letter-spacing: 0.5px;
    padding-bottom: 8px;
    border-bottom: 1px solid #2a2a2a;
}
.tier-head .t-free,
.tier-head .t-pro,
.tier-head .t-ultra { font-size: 0.72rem; }

.tier-sec {
    font-size: 0.72rem;
    color: var(--text-sub);
    letter-spacing: 1px;
    padding: 14px 0 6px;
    border-bottom: 1px solid #1e1e1e;
}

/* Ultra 的卡片用紫色，跟 Pro 的金色分開 */
.pro-plan-card-ultra {
    border-color: #b388ff;
    box-shadow: 0 0 20px rgba(179, 136, 255, 0.15);
}
.pro-plan-card-ultra .pro-plan-price,
.pro-plan-card-ultra .pro-plan-label { color: #b388ff; }
.tier-badge-ultra {
    display: inline-block;
    background: linear-gradient(135deg, #b388ff, #7c4dff);
    color: #fff;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 1px;
    padding: 3px 8px;
    border-radius: 6px;
    vertical-align: middle;
}

@media (max-width: 360px) {
    /* 很窄的機型：欄位再收一點，不然功能名稱會被擠到只剩兩個字 */
    .tier-row { font-size: 0.8rem; gap: 4px; }
    .tier-row .t-free,
    .tier-row .t-pro,
    .tier-row .t-ultra { width: 42px; font-size: 0.7rem; }
}

.pro-plan-card {
    flex: 1;
    background: var(--card-bg);
    border: 1px solid #2a2a2a;
    border-radius: 16px;
    padding: 18px 14px;
    text-align: center;
    position: relative;
}
.pro-plan-card-featured {
    border-color: #f0c040;
    box-shadow: 0 0 20px rgba(240, 192, 64, 0.15);
}
.pro-plan-badge {
    position: absolute;
    top: -10px;
    left: 50%;
    transform: translateX(-50%);
    background: #f0c040;
    color: #000;
    font-size: 0.72rem;
    font-weight: 700;
    padding: 3px 12px;
    border-radius: 10px;
    white-space: nowrap;
}
.pro-plan-label {
    font-size: 0.82rem;
    color: var(--text-sub);
    margin-bottom: 6px;
}
.pro-plan-price {
    font-size: 1.6rem;
    font-weight: 700;
    color: #f0c040;
}
.pro-plan-sub {
    font-size: 0.75rem;
    color: var(--text-sub);
    margin-top: 4px;
}

/* 三張卡片排一列：390px 的手機上一張只剩約 110px，
   而「NT$1,290」用原本的 1.6rem 會直接撐破卡片。整排縮一階。 */
.pro-plan-row3 { display: flex; gap: 10px; }
.pro-plan-row3 .pro-plan-card { padding: 16px 6px; border-radius: 14px; min-width: 0; }
.pro-plan-row3 .pro-plan-label { font-size: 0.76rem; margin-bottom: 4px; }
.pro-plan-row3 .pro-plan-price { font-size: 1.12rem; letter-spacing: -0.5px; white-space: nowrap; }
.pro-plan-row3 .pro-plan-sub { font-size: 0.68rem; margin-top: 3px; }
@media (max-width: 360px) {
    .pro-plan-row3 { gap: 6px; }
    .pro-plan-row3 .pro-plan-card { padding: 14px 3px; }
    .pro-plan-row3 .pro-plan-price { font-size: 1rem; }
    .pro-plan-row3 .pro-plan-sub { font-size: 0.62rem; }
}

/* ======= AI 課本教學樣式 ======= */
.lesson-step {
    animation: lessonStepIn 0.4s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

@keyframes lessonStepIn {
    from { opacity: 0; transform: translateY(24px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes lessonStepOut {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-16px); }
}

.lesson-step-tag {
    font-size: 0.72rem;
    color: #f0c040;
    font-weight: 600;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    margin-bottom: 4px;
}

.lesson-card {
    background: var(--card-bg);
    border: 1px solid #2a2a2a;
    border-radius: 14px;
    padding: 16px;
    margin-bottom: 14px;
}

.lesson-section-label {
    font-size: 0.78rem;
    color: var(--text-sub);
    margin-bottom: 10px;
    font-weight: 600;
    letter-spacing: 0.5px;
}

.lesson-next-btn {
    --btn-tint: 240, 192, 64;
    --btn-ink: #f6e2ab;
    font-weight: 700;
    width: 100%;
    margin-top: 20px !important;
}

.lesson-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #333;
    transition: all 0.3s ease;
    display: inline-block;
}

.lesson-dot-active {
    background: #f0c040;
    width: 24px;
    border-radius: 4px;
}

.lesson-dot-done {
    background: #666;
}

#lesson-shutter-btn:active {
    transform: scale(0.85) !important;
}

/* 後台管理：自訂 chip 選擇器 */
.admin-chip-group {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 10px;
}
.admin-chip {
    background: #1a1a1a;
    border: 1px solid #333;
    color: var(--text-sub);
    padding: 7px 14px;
    border-radius: 20px;
    font-size: 0.82rem;
    cursor: pointer;
    transition: all 0.2s ease;
    white-space: nowrap;
    font-family: inherit;
    letter-spacing: 0.5px;
}
.admin-chip:active {
    transform: scale(0.95);
}
.admin-chip.active {
    background: rgba(240, 192, 64, 0.12);
    border-color: #f0c040;
    color: #f0c040;
    font-weight: 600;
}
/* Ultra 那排選起來是紫的，跟 Pro 的金色一眼分得出來 */
#admin-plan-chips-ultra .admin-chip.active {
    background: rgba(179, 136, 255, 0.14);
    border-color: #b388ff;
    color: #b388ff;
}
.admin-chip-label {
    font-size: 0.75rem;
    color: var(--text-sub);
    letter-spacing: 1px;
    margin-bottom: 6px;
    text-transform: uppercase;
}

/* ===== LOADING SCREEN ===== */
#sv-loader {
    position: fixed; inset: 0; z-index: 9900;
    background: #0a0a0a;
    display: flex; align-items: center; justify-content: center;
    transition: opacity .4s ease;
}
.sv-loader-inner { text-align: center; }
.sv-loader-brand {
    font-size: 1.1rem; font-weight: 200; letter-spacing: 8px;
    color: #fff; margin: 0 0 24px 0;
}
.sv-loader-dots { display: flex; gap: 8px; justify-content: center; }
.sv-loader-dots span {
    width: 7px; height: 7px; border-radius: 50%; background: #444;
    animation: sv-dot 1.2s ease-in-out infinite;
}
.sv-loader-dots span:nth-child(2) { animation-delay: .2s; }
.sv-loader-dots span:nth-child(3) { animation-delay: .4s; }
@keyframes sv-dot { 0%,80%,100% { background:#333; transform:scale(.8); } 40% { background:#f0c040; transform:scale(1.1); } }

/* ===== LANDING PAGE ===== */
.ld-wrap {
    min-height: 100dvh;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    padding: 80px 28px 64px;
    position: relative;
    gap: 48px;
    animation: fadeIn .6s ease;
}
#view-landing { overflow: hidden; }
.ld-bg-glow {
    position: absolute; top: -80px; left: 50%; transform: translateX(-50%);
    width: 560px; height: 480px;
    background: radial-gradient(ellipse at 50% 0%, rgba(240,192,64,.08) 0%, transparent 65%);
    pointer-events: none; z-index: 0;
}
.ld-top-bar {
    position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 56px; height: 2px;
    background: linear-gradient(90deg, transparent, #f0c040, transparent);
}
.ld-hero { text-align: center; position: relative; z-index: 1; }
.ld-eyebrow {
    font-size: .62rem; color: #f0c040; letter-spacing: 3px;
    text-transform: uppercase; margin: 0 0 22px; opacity: .85; font-weight: 400;
}
.ld-brand {
    font-size: clamp(2rem, 8vw, 3.2rem);
    font-weight: 200;
    letter-spacing: clamp(4px, 1.2vw, 8px);
    color: #fff; margin: 0 0 26px; line-height: 1;
}
.ld-tagline {
    font-size: 1.28rem; font-weight: 300; color: #888;
    line-height: 1.65; margin: 0; letter-spacing: 1.5px;
}
.ld-strip {
    display: flex; align-items: center; gap: 8px;
    flex-wrap: nowrap; justify-content: center;
    position: relative; z-index: 1;
}
.ld-strip span { font-size: .72rem; color: #666; letter-spacing: .5px; font-weight: 500; white-space: nowrap; }
.ld-sep { color: #3a3a3a !important; font-size: .55rem !important; }
.ld-cta { width: 100%; max-width: 340px; text-align: center; position: relative; z-index: 1; }
.ld-btn {
    width: 100%; display: flex; align-items: center; justify-content: center;
    background: rgba(255,255,255,.04); color: #ddd;
    border: 1px solid rgba(255,255,255,.18);
    border-radius: 14px; padding: 15px 24px;
    font-size: .9rem; font-weight: 500; letter-spacing: .5px;
    cursor: pointer; font-family: inherit;
    transition: background .25s, border-color .25s, color .25s, transform .15s;
    position: relative;
}
.ld-btn::before {
    content: ''; position: absolute; inset: 0; border-radius: 14px;
    background: linear-gradient(135deg, rgba(240,192,64,.05) 0%, transparent 60%);
    pointer-events: none;
}
@media (hover: hover) {
    .ld-btn:hover {
        background: rgba(240,192,64,.06);
        border-color: rgba(240,192,64,.35);
        color: #fff; transform: translateY(-1px);
    }
}
.ld-btn:active { transform: translateY(0); }
.ld-note { margin: 14px 0 0; font-size: .68rem; color: #555; letter-spacing: 1px; }
.ld-divider { display: flex; align-items: center; gap: 14px; width: 100%; margin: 6px 0 2px; }
.ld-divider::before, .ld-divider::after { content: ''; flex: 1; height: 1px; background: #1e1e1e; }
.ld-divider span { font-size: .6rem; color: #2c2c2c; letter-spacing: 2px; white-space: nowrap; }
.ld-ebtn2 { width: 100%; background: rgba(255,255,255,.03); border: 1px solid #1e1e1e; color: #555; font-size: .82rem; padding: 14px; border-radius: 12px; cursor: pointer; letter-spacing: 1px; transition: background .2s, color .2s; font-family: inherit; }
@media (hover: hover) {
    .ld-ebtn2:hover { background: rgba(255,255,255,.06); color: #777; }
}

/* Email login bottom-sheet modal */
#email-modal { display: none; position: fixed; inset: 0; z-index: 9600; }
#em-overlay { position: absolute; inset: 0; background: rgba(0,0,0,.82); }
#em-sheet { position: fixed; bottom: 0; left: 0; right: 0; width: 100%; max-width: 480px; margin: 0 auto; background: #111; border: 1px solid #1e1e1e; border-bottom: none; border-radius: 20px 20px 0 0; padding: 0 24px 48px; animation: emSheetIn .4s cubic-bezier(.22,1,.36,1) both; }
@keyframes emSheetIn { from { transform: translateY(100%); } to { transform: translateY(0); } }
.em-bar { width: 36px; height: 3px; background: #252525; border-radius: 2px; margin: 14px auto 22px; }
.em-tabs { display: flex; border-bottom: 1px solid #1a1a1a; margin-bottom: 22px; }
.em-tab { flex: 1; background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px; color: #3a3a3a; font-size: .85rem; padding: 10px; cursor: pointer; letter-spacing: 1px; transition: color .2s, border-color .2s; font-family: inherit; }
.em-tab.em-tab-active { color: #ccc; border-bottom-color: #444; }
.em-form { display: flex; flex-direction: column; gap: 10px; }
.em-input { display: block !important; width: 100% !important; background: #0d0d0d !important; background-color: #0d0d0d !important; border: 1px solid #222 !important; border-radius: 12px !important; padding: 14px 16px !important; font-size: .9rem !important; color: #c8c8c8 !important; -webkit-text-fill-color: #c8c8c8 !important; outline: none !important; box-sizing: border-box !important; -webkit-appearance: none !important; appearance: none !important; font-family: inherit !important; letter-spacing: .3px !important; transition: border-color .2s; }
.em-input::placeholder { color: #2c2c2c !important; }
.em-input:focus { border-color: #333 !important; }
.em-input:-webkit-autofill, .em-input:-webkit-autofill:hover, .em-input:-webkit-autofill:focus { -webkit-box-shadow: 0 0 0 60px #0d0d0d inset !important; -webkit-text-fill-color: #c8c8c8 !important; caret-color: #c8c8c8; }
.em-input.em-hidden { display: none !important; }
.em-sbtn { width: 100%; background: #1c1c1c; border: 1px solid #2a2a2a; color: #ccc; font-size: .88rem; padding: 14px; border-radius: 12px; cursor: pointer; letter-spacing: 1px; transition: background .2s; font-family: inherit; margin-top: 2px; }
@media (hover: hover) {
    .em-sbtn:hover { background: #222; }
}
.em-sbtn:disabled { opacity: .45; cursor: default; }
.em-foot { text-align: right; margin-top: 2px; }
.em-flink { background: none; border: none; color: #2e2e2e; font-size: .68rem; cursor: pointer; letter-spacing: .3px; padding: 0; font-family: inherit; }
@media (hover: hover) {
    .em-flink:hover { color: #555; }
}
.em-msg { font-size: .72rem; min-height: 16px; margin: 0; letter-spacing: .3px; text-align: center; }

/* 匯出閃卡 Modal */
#ecm-overlay { position: absolute; inset: 0; background: rgba(0,0,0,.88); backdrop-filter: blur(2px); }
#ecm-sheet {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    max-width: 480px;
    margin: 0 auto;
    background: #0f0f0f;
    border: 1px solid #1e1e1e;
    border-bottom: none;
    border-radius: 22px 22px 0 0;
    padding: 0 16px env(safe-area-inset-bottom, 32px);
    padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 36px);
    max-height: 88vh;
    overflow-y: auto;
    animation: emSheetIn .35s cubic-bezier(.22,1,.36,1) both;
}
.ecm-handle { width: 36px; height: 4px; background: #2a2a2a; border-radius: 2px; margin: 10px auto 0; }
.ecm-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 0 14px; border-bottom: 1px solid #181818; margin-bottom: 16px; }
.ecm-title { font-size: .92rem; color: #d8d8d8; letter-spacing: .3px; font-weight: 500; }
.ecm-close-btn { background: #1a1a1a; border: 1px solid #272727; color: #555; font-size: .75rem; cursor: pointer; padding: 6px 10px; border-radius: 8px; font-family: inherit; line-height: 1; transition: background .15s, color .15s; }
.ecm-close-btn:active { background: #222; color: #888; }
.ecm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ecm-card-wrap { display: flex; flex-direction: column; gap: 8px; }
.ecm-side-tag { font-size: .65rem; color: #505050; text-align: center; letter-spacing: 1.8px; text-transform: uppercase; font-weight: 600; padding-bottom: 2px; }
.ecm-preview { width: 100%; border-radius: 10px; border: 1px solid #1e1e1e; display: block; background: #080808; aspect-ratio: 600/820; object-fit: contain; }
.ecm-dl-btn {
    width: 100%;
    background: linear-gradient(150deg, #00acc1 0%, #007c8a 100%);
    border: none;
    color: #fff;
    font-size: .78rem;
    font-weight: 600;
    padding: 11px 6px;
    border-radius: 11px;
    cursor: pointer;
    font-family: inherit;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    letter-spacing: .2px;
    transition: opacity .15s, transform .1s;
    box-shadow: 0 2px 10px rgba(0,172,193,.18);
}
.ecm-dl-btn:active { opacity: .82; transform: scale(.97); }

.profile-sec-input { width: 100%; background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; font-size: .88rem; color: var(--text-main); outline: none; box-sizing: border-box; transition: border-color .2s; }
.profile-sec-input:focus { border-color: #555; }

/* IAB toast notification */
#ld-iab-toast {
    position: fixed; bottom: 0; left: 50%; z-index: 9500;
    transform: translateX(-50%) translateY(calc(100% + 20px));
    width: min(440px, 100vw);
    background: #111; border: 1px solid #252525; border-bottom: none;
    border-radius: 20px 20px 0 0;
    padding: 8px 28px 44px;
    text-align: center;
    box-shadow: 0 -12px 48px rgba(0,0,0,.7);
    transition: transform .48s cubic-bezier(.22,1,.36,1);
}
#ld-iab-toast.show { animation: iabToastIn .48s cubic-bezier(.22,1,.36,1) forwards; }
@keyframes iabToastIn { from { transform: translateX(-50%) translateY(calc(100% + 20px)); } to { transform: translateX(-50%) translateY(0); } }
.ld-toast-bar { width: 36px; height: 3px; background: #2a2a2a; border-radius: 2px; margin: 12px auto 24px; }
.ld-toast-title { font-size: .9rem; font-weight: 400; color: #ccc; letter-spacing: 1px; margin: 0 0 10px; }
.ld-toast-sub { font-size: .78rem; color: #555; line-height: 1.85; margin: 0 0 24px; letter-spacing: .2px; }
.ld-toast-sub strong { color: #888; font-weight: 500; }
.ld-toast-btn { background: rgba(240,192,64,.1); border: 1px solid rgba(240,192,64,.22); color: #f0c040; font-size: .8rem; padding: 12px 36px; border-radius: 12px; cursor: pointer; letter-spacing: 1px; transition: background .2s; width: 100%; }
@media (hover: hover) {
    .ld-toast-btn:hover { background: rgba(240,192,64,.18); }
}

@keyframes ob-in { from { opacity:0; transform:scale(.94); } to { opacity:1; transform:scale(1); } }

/* ===== Pattern Analysis (句型分析) ===== */
.pa-thumb-wrap { position:relative; width:120px; height:90px; flex-shrink:0; }
.pa-thumb { width:100%; height:100%; object-fit:cover; border-radius:10px; border:1px solid #2a2a2a; display:block; }
.pa-thumb-remove { position:absolute; top:4px; right:4px; width:22px; height:22px; border-radius:50%; background:rgba(0,0,0,.78); border:none; color:#fff; font-size:.7rem; cursor:pointer; display:flex; align-items:center; justify-content:center; padding:0; line-height:1; }
.pa-upload-btn { width:100%; padding:14px; border-radius:12px; border:1.5px dashed #333; background:transparent; color:var(--text-sub); font-size:.9rem; font-family:inherit; cursor:pointer; display:flex; align-items:center; justify-content:center; gap:8px; margin-bottom:12px; transition:border-color .2s, color .2s; }
@media (hover: hover) {
    .pa-upload-btn:hover { border-color:#555; color:var(--text-main); }
}
.pa-analyze-btn { width:100%; padding:14px; border-radius:12px; border:none; background:linear-gradient(150deg,#f0c040 0%,#e0a020 100%); color:#000; font-size:.95rem; font-weight:700; font-family:inherit; cursor:pointer; transition:opacity .2s; box-shadow:0 2px 12px rgba(240,192,64,.22); }
.pa-analyze-btn:disabled { opacity:.35; cursor:not-allowed; }
.pa-chip { width:100%; padding:18px 20px; border-radius:14px; border:1px solid rgba(240,192,64,.35); background:rgba(240,192,64,.06); color:var(--text-main); font-size:1rem; font-weight:600; font-family:inherit; cursor:pointer; text-align:left; display:flex; align-items:center; justify-content:space-between; transition:background .15s, border-color .15s; }
.pa-chip::after { content:'›'; color:#f0c040; font-size:1.5rem; font-weight:300; flex-shrink:0; margin-left:10px; }
@media (hover: hover) {
    .pa-chip:hover { background:rgba(240,192,64,.14); border-color:rgba(240,192,64,.65); }
}
.pa-chip:active { transform:scale(.98); }
.pa-section-label { font-size:.72rem; font-weight:700; color:#f0c040; text-transform:uppercase; letter-spacing:1.5px; margin:22px 0 8px; }
.pa-section-label:first-child { margin-top:0; }
.pa-section-text { font-size:.95rem; color:#fff; line-height:1.7; }
.pa-example { font-size:.92rem; color:#fff; line-height:1.7; padding:10px 14px; border-left:3px solid rgba(240,192,64,.5); margin-bottom:8px; }
.pa-example-zh { color:#bbb; }
.pa-notes-text { font-size:.92rem; color:#e0a050; line-height:1.7; background:rgba(224,160,80,.08); border-radius:10px; padding:14px 16px; }
.pa-hint-text { font-size:.92rem; color:#e0f7fa; line-height:1.7; background:rgba(0,188,212,.08); border-radius:10px; padding:14px 16px; border-left:3px solid rgba(0,188,212,.5); }
.pa-qa-wrap { border:1px solid rgba(255,255,255,.08); border-radius:12px; padding:14px 16px; margin-bottom:10px; background:rgba(255,255,255,.03); }
.pa-qa-q { font-size:.9rem; color:#ddd; line-height:1.6; margin-bottom:8px; }
.pa-qa-ans { font-size:.95rem; color:#f0c040; font-weight:700; margin-bottom:4px; }
.pa-qa-why { font-size:.85rem; color:#999; line-height:1.5; }
.pa-mcq-card { border:1px solid rgba(255,255,255,.07); border-radius:14px; padding:16px; margin-bottom:14px; background:rgba(255,255,255,.02); }
.pa-mcq-q { font-size:.93rem; color:#e0e0e0; line-height:1.65; margin-bottom:12px; }
.pa-mcq-num { color:#f0c040; font-weight:700; }
.pa-mcq-opts { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.pa-mcq-opt { padding:10px 8px; border-radius:10px; border:1px solid rgba(255,255,255,.12); background:rgba(255,255,255,.04); color:#ccc; font-size:.85rem; font-family:inherit; cursor:pointer; text-align:left; line-height:1.4; transition:background .15s, border-color .15s; }
@media (hover: hover) {
    .pa-mcq-opt:hover:not(:disabled) { background:rgba(255,255,255,.1); border-color:rgba(255,255,255,.28); }
}
.pa-mcq-correct { background:rgba(240,192,64,.15) !important; border-color:#f0c040 !important; color:#f0c040 !important; font-weight:700; }
.pa-mcq-wrong { background:rgba(244,67,54,.1) !important; border-color:rgba(244,67,54,.5) !important; color:#f44336 !important; }
.pa-mcq-opt:disabled { cursor:default; }
.pa-mcq-why { font-size:.83rem; color:#888; margin-top:10px; padding-top:8px; border-top:1px solid rgba(255,255,255,.06); line-height:1.5; }
.pa-mcq-ans-reveal { font-size:.95rem; color:#f0c040; font-weight:700; margin-top:6px; }
/* 考卷詳解（每題：整句中文、為什麼、容易選錯、值得記的字） */
.pa-summary { color:var(--text-sub); font-size:.83rem; margin-bottom:10px; line-height:1.5; }
.pa-disclaimer { font-size:.78rem; color:var(--text-sub); background:rgba(255,255,255,.03); border-radius:8px; padding:8px 12px; margin-bottom:14px; line-height:1.55; }
.pa-progress { font-size:.8rem; font-weight:700; color:#f0c040; margin-bottom:12px; min-height:1em; }
.pa-intro { color:var(--text-sub); font-size:.85rem; margin-bottom:16px; line-height:1.6; padding:12px 14px; background:rgba(255,255,255,.03); border-radius:10px; }
.pa-concept { background:rgba(240,192,64,.06); border:1px solid rgba(240,192,64,.22); border-radius:12px; padding:12px 14px; margin-bottom:10px; }
.pa-concept .pa-section-label { margin:0 0 6px; }
.pa-batch { animation:paBatchIn .35s ease both; }
@keyframes paBatchIn { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
.pa-qa-zh { font-size:.86rem; color:var(--text-main); opacity:.85; line-height:1.6; margin:2px 0 8px; }
.pa-qa-why, .pa-qa-wrong, .pa-qa-evidence { font-size:.85rem; color:var(--text-sub); line-height:1.65; margin-top:6px; }
.pa-qa-why b, .pa-qa-wrong b, .pa-qa-evidence b { display:inline-block; font-size:.7rem; font-weight:700; padding:1px 7px; border-radius:6px; margin-right:7px; vertical-align:1px; }
.pa-qa-why b { background:rgba(0,188,212,.14); color:#4dd0e1; }
.pa-qa-wrong b { background:rgba(244,67,54,.12); color:#ef7a70; }
.pa-qa-evidence b { background:rgba(240,192,64,.12); color:#f0c040; }
.pa-qa-evidence .pa-pickable { font-style:italic; }
.pa-words { display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:10px; padding-top:10px; border-top:1px dashed rgba(255,255,255,.08); }
.pa-words-label { font-size:.7rem; color:var(--text-sub); margin-right:2px; }
.pa-word { display:inline-flex; align-items:baseline; gap:6px; padding:5px 10px !important; border-radius:999px !important; border:1px solid rgba(240,192,64,.35); background:rgba(240,192,64,.07); font-size:.82rem; }
.pa-word b { color:#f0c040; font-weight:700; }
.pa-word-zh { color:var(--text-sub); font-size:.76rem; }
.pa-word.wp-picked { box-shadow:none; border-color:#ff9800; }
.pa-word.wp-picked b { color:#ffb74d; }
.pa-reveal { display:inline-block; margin-top:10px; padding:6px 14px; border-radius:999px; border:1px solid rgba(255,255,255,.16); background:transparent; color:var(--text-sub); font-size:.8rem; font-family:inherit; cursor:pointer; }
.pa-reveal:active { transform:scale(.97); }
.pa-more { display:flex; align-items:center; justify-content:center; gap:10px; flex-wrap:wrap; color:var(--text-sub); font-size:.85rem; padding:18px 0 8px; text-align:center; }
.pa-more-spin { width:18px !important; height:18px !important; border-width:2px !important; margin:0 !important; }
.pa-more-fail { color:#ef7a70; }
.pa-loading-first { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px; height:220px; color:var(--text-sub); font-size:.85rem; }
/* 句型精通：常見錯誤 */
.lesson-mistake { font-size:.84rem; color:var(--text-sub); line-height:1.65; margin:6px 0 8px; padding:8px 12px; border-radius:8px; background:rgba(244,67,54,.06); }
.lesson-mistake b { display:inline-block; font-size:.7rem; font-weight:700; padding:1px 7px; border-radius:6px; margin-right:7px; background:rgba(244,67,54,.12); color:#ef7a70; }
/* 照片導入文章：AI 提示、照片上標記的字 */
.rd-ocr-hint { font-size:.82rem; color:var(--text-sub); line-height:1.6; padding:10px 12px; border-radius:10px; background:rgba(0,188,212,.07); border-left:3px solid rgba(0,188,212,.5); margin-bottom:12px; }
.rd-marked { border:1px solid rgba(255,152,0,.3); background:rgba(255,152,0,.05); border-radius:12px; padding:12px; margin-bottom:16px; }
.rd-marked-head { display:flex; align-items:center; justify-content:space-between; gap:10px; font-size:.8rem; font-weight:700; color:#ffb74d; margin-bottom:10px; }
.rd-marked-all { flex-shrink:0; padding:5px 12px; border-radius:999px; border:1px solid #ff9800; background:rgba(255,152,0,.12); color:#ffb74d; font-size:.76rem; font-weight:700; font-family:inherit; cursor:pointer; }
.rd-marked-all:active { transform:scale(.96); }
.rd-marked-list { display:flex; flex-wrap:wrap; gap:6px; }
.rd-marked-word { padding:4px 10px !important; border-radius:999px !important; border:1px solid rgba(255,255,255,.14); font-size:.88rem; color:var(--text-main); }

/* =====================================================
   觀戰派對 (Live Spectate Party)
   ===================================================== */

/* 彈幕浮層：不攔截點擊，房主與觀眾共用 */
#danmaku-layer {
    position: fixed;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 9400;
}

.danmaku-item {
    position: absolute;
    left: 100%;
    white-space: nowrap;
    font-size: 0.9rem;
    color: #fff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
    padding: 4px 10px;
    animation: danmakuFly 9s linear forwards;
}

.danmaku-name {
    color: #f0c040;
    margin-right: 8px;
    font-size: 0.78rem;
}

@keyframes danmakuFly {
    from { transform: translateX(0); }
    to   { transform: translateX(calc(-100vw - 100%)); }
}

@media (prefers-reduced-motion: reduce) {
    .danmaku-item { animation-duration: 14s; }
}

/* 房間設定面板 */
#live-room-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.72);
    z-index: 9600;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 20px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

#live-room-overlay.show { opacity: 1; pointer-events: auto; }
#live-room-overlay.hidden { display: none !important; }

.live-room-box {
    background: #111;
    border: 1px solid var(--border);
    border-radius: 18px;
    padding: 24px 22px;
    width: 100%;
    max-width: 380px;
}

/* 觀戰畫面 */
.spectate-stage {
    text-align: center;
    padding: 30px 16px 120px;
    min-height: 50vh;
}

.spectate-idle {
    color: var(--text-sub);
    font-size: 0.9rem;
    padding: 40px 0;
    letter-spacing: 1px;
}

.spectate-q {
    font-size: 1.7rem;
    font-weight: 600;
    color: var(--text-main);
    line-height: 1.4;
    margin-bottom: 26px;
}

.spectate-word {
    font-size: 2.1rem;
    font-weight: 700;
    color: var(--text-main);
    line-height: 1.3;
    overflow-wrap: break-word;
}

.spectate-zh {
    font-size: 1rem;
    color: var(--text-sub);
    margin-top: 8px;
    line-height: 1.6;
}

.spectate-pos {
    font-size: 0.72rem;
    color: #ff9800;
    margin-left: 6px;
}

.spectate-opts {
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: 420px;
    margin: 0 auto;
}

.spectate-opt {
    border: 1px solid var(--border);
    background: var(--card-bg);
    border-radius: 12px;
    padding: 14px 16px;
    font-size: 0.95rem;
    color: var(--text-main);
    transition: border-color 0.2s, background 0.2s;
}

.spectate-opt.is-picked { border-color: #fff; }
.spectate-opt.is-correct { border-color: var(--success); color: var(--success); }
.spectate-opt.is-wrong { border-color: var(--error); color: var(--error); }

.spectate-tiles {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    margin: 14px 0;
    min-height: 34px;
}

.spectate-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    height: 30px;
    padding: 0 4px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--card-bg);
    color: var(--text-main);
    font-size: 0.95rem;
}

.spectate-tile.dim { opacity: 0.45; }

.spectate-divider {
    border-bottom: 1px solid var(--border);
    margin: 18px auto;
    max-width: 320px;
}

.spectate-typed {
    font-size: 1.6rem;
    font-weight: 600;
    color: var(--text-main);
    letter-spacing: 3px;
    min-height: 40px;
}

.spectate-match {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    max-width: 420px;
    margin: 0 auto;
}

.spectate-match > div {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.spectate-result {
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: 2px;
    margin-bottom: 14px;
}

.spectate-result.ok { color: var(--success); }
.spectate-result.no { color: var(--error); }

.spectate-msg {
    font-size: 0.88rem;
    color: var(--text-sub);
    margin-top: 12px;
}

.spectate-progress {
    margin-top: 30px;
    font-size: 0.8rem;
    color: var(--text-sub);
    letter-spacing: 1px;
}

/* 彈幕輸入列 */
.danmaku-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    gap: 8px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    background: rgba(10, 10, 10, 0.94);
    border-top: 1px solid var(--border);
    z-index: 9450;
}

/* 公開房間列表 */
.spectate-room-item {
    display: flex;
    align-items: center;
    gap: 12px;
    border: 1px solid var(--border);
    background: var(--card-bg);
    border-radius: 12px;
    padding: 14px 16px;
    margin-bottom: 10px;
}

/* 答題輸入框被攔截時的回饋（點了鍵盤候選字或貼上） */
.answer-input-blocked {
    animation: answerBlockShake 0.35s ease;
    border-color: #ff9800 !important;
}

@keyframes answerBlockShake {
    0%, 100% { transform: translateX(0); }
    25%      { transform: translateX(-5px); }
    75%      { transform: translateX(5px); }
}

@media (prefers-reduced-motion: reduce) {
    .answer-input-blocked { animation: none; }
}

/* =========================================================
   單字小遊戲 · 單字賓果
   ========================================================= */

/* 進場：整個畫面先縮再放，和其他模式的過渡語言一致 */
@keyframes wbViewIn {
    0%   { opacity: 0; transform: scale(0.94) translateY(8px); }
    60%  { opacity: 1; transform: scale(1.012) translateY(0); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
#view-word-bingo.wb-enter {
    animation: wbViewIn 0.44s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.wb-wrap {
    margin-top: 6px;
}

.wb-grid {
    position: relative;
    width: 100%;
    max-width: 460px;
    margin: 0 auto;
    padding: 8px;
    border-radius: 18px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    touch-action: none;          /* 滑動時不要跟著捲動頁面 */
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    overflow: hidden;
}

/* gap 必須為 0：連線層的 viewBox 以「格」為單位，有間距就會對不準 */
.wb-cells {
    display: grid;
    gap: 0;
    position: relative;
    z-index: 2;
}

/* 連線層：疊在字母底下，且不能吃掉觸控事件 */
.wb-lines {
    position: absolute;
    left: 8px;
    top: 8px;
    width: calc(100% - 16px);
    height: calc(100% - 16px);
    z-index: 1;
    pointer-events: none;
    overflow: visible;
}

.wb-line {
    stroke-width: 0.74;
    stroke-linecap: round;
    fill: none;
}

.wb-line-active {
    stroke: rgba(255, 255, 255, 0.28);
    opacity: 0;
    transition: opacity 0.12s;
}

.wb-line-found {
    opacity: 0.3;
    transition: stroke-dashoffset 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}

/* ===== 字母格 ===== */
@keyframes wbCellIn {
    0%   { opacity: 0; transform: scale(0.3) rotate(-12deg); }
    100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

.wb-cell {
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.03);
    color: var(--text-main);
    font-size: clamp(0.72rem, 3.6vw, 1.05rem);
    font-weight: 600;
    letter-spacing: 0;
    line-height: 1;
    transition: background 0.14s, color 0.14s, transform 0.14s;
}

/* 開場逐格浮現：只在 .wb-entering 期間套用。
   若寫在 .wb-cell 上，之後移除 .pop 會讓 animation-name 變回它而重播一次。 */
.wb-cells.wb-entering .wb-cell {
    animation: wbCellIn 0.34s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.wb-cell.sel {
    background: rgba(255, 255, 255, 0.9);
    color: #0a0a0a;
    transform: scale(1.06);
    position: relative;
    z-index: 3;
}

.wb-cell.found {
    background: color-mix(in srgb, var(--wb-c, #00bcd4) 22%, transparent);
    color: var(--wb-c, #00bcd4);
}

/* color-mix 不支援時的退路 */
@supports not (background: color-mix(in srgb, red 20%, transparent)) {
    .wb-cell.found {
        background: rgba(255, 255, 255, 0.1);
    }
}

@keyframes wbPop {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.32); }
    100% { transform: scale(1); }
}
.wb-cell.pop {
    animation: wbPop 0.36s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes wbShake {
    0%, 100% { transform: translateX(0); }
    25%      { transform: translateX(-3px); }
    75%      { transform: translateX(3px); }
}
.wb-cell.shake {
    animation: wbShake 0.22s ease-in-out 2;
    background: rgba(244, 67, 54, 0.22);
    color: #ff8a80;
}

/* ===== 飄分 ===== */
@keyframes wbFloat {
    0%   { opacity: 0; transform: translate(-50%, 4px) scale(0.7); }
    25%  { opacity: 1; transform: translate(-50%, -8px) scale(1.05); }
    100% { opacity: 0; transform: translate(-50%, -52px) scale(1); }
}
.wb-float {
    position: absolute;
    z-index: 5;
    pointer-events: none;
    font-size: 0.95rem;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.7);
    animation: wbFloat 1.05s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* ===== 單字清單 ===== */
.wb-words {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
    margin: 16px auto 0;
    max-width: 460px;
}

.wb-word {
    padding: 7px 12px;
    border-radius: 10px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    text-align: center;
    line-height: 1.25;
    transition: border-color 0.3s, background 0.3s, transform 0.3s, opacity 0.3s;
}

.wb-word-en {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.4px;
    color: var(--text-main);
    position: relative;
    transition: color 0.3s;
}

.wb-word-zh {
    display: block;
    margin-top: 2px;
    font-size: 0.68rem;
    color: var(--text-sub);
}

@keyframes wbWordFound {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.14); }
    100% { transform: scale(1); }
}

.wb-word.found {
    border-color: var(--wb-c, #00bcd4);
    background: rgba(255, 255, 255, 0.04);
    animation: wbWordFound 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.wb-word.found .wb-word-en {
    color: var(--wb-c, #00bcd4);
}

/* 刪除線由左往右畫過去 */
.wb-word .wb-word-en::after {
    content: '';
    position: absolute;
    left: 0;
    top: 52%;
    height: 1.5px;
    width: 0;
    background: currentColor;
    border-radius: 2px;
    transition: width 0.32s cubic-bezier(0.22, 1, 0.36, 1) 0.1s;
}
.wb-word.found .wb-word-en::after {
    width: 100%;
}

.wb-word.found .wb-word-zh {
    opacity: 0.55;
}

/* ===== 提示列 ===== */
.wb-hint {
    margin: 16px auto 0;
    text-align: center;
    font-size: 0.78rem;
    color: var(--text-sub);
    letter-spacing: 0.5px;
    transition: opacity 0.4s, transform 0.4s;
}
.wb-hint.gone {
    opacity: 0;
    transform: translateY(-6px);
    pointer-events: none;
}

/* ===== 結算 ===== */
#wb-complete-overlay {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(0, 0, 0, 0.82);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 0.3s;
}
#wb-complete-overlay.show {
    opacity: 1;
}
#wb-complete-overlay.hidden {
    display: none !important;
}

@keyframes wbBoxIn {
    0%   { opacity: 0; transform: scale(0.8) translateY(20px); }
    65%  { opacity: 1; transform: scale(1.03) translateY(0); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}

.wb-complete-box {
    width: 100%;
    max-width: 340px;
    padding: 32px 24px 24px;
    border-radius: 20px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    text-align: center;
}
#wb-complete-overlay.show .wb-complete-box {
    animation: wbBoxIn 0.46s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.wb-complete-title {
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: 2px;
    color: var(--text-main);
}
.wb-complete-sub {
    margin-top: 6px;
    font-size: 0.78rem;
    color: var(--text-sub);
    letter-spacing: 1px;
}
.wb-complete-points {
    margin-top: 22px;
    font-size: 3rem;
    font-weight: 800;
    line-height: 1;
    color: #fff;
    font-variant-numeric: tabular-nums;
}
.wb-complete-unit {
    margin-top: 6px;
    font-size: 0.75rem;
    letter-spacing: 3px;
    color: var(--text-sub);
}

@media (prefers-reduced-motion: reduce) {
    #view-word-bingo.wb-enter,
    .wb-cells.wb-entering .wb-cell,
    .wb-cell.pop,
    .wb-cell.shake,
    .wb-float,
    .wb-word.found,
    #wb-complete-overlay.show .wb-complete-box {
        animation: none;
    }
}

/* =========================================================
   每日單字卡
   ========================================================= */

/* 導覽列上的圖示按鈕 */
.nav-icon-btn {
    position: relative;
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--text-main);
    cursor: pointer;
    padding: 0;
    transition: border-color 0.2s, background 0.2s, transform 0.12s;
}
@media (hover: hover) {
    .nav-icon-btn:hover { border-color: var(--text-sub); background: rgba(255,255,255,0.04); }
}
.nav-icon-btn:active { transform: scale(0.94); }

.nav-dot {
    position: absolute;
    top: -3px;
    right: -3px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--warning);
    border: 2px solid var(--bg-color);
}

.dc-loading {
    text-align: center;
    color: var(--text-sub);
    font-size: 0.9rem;
    padding: 60px 0;
    letter-spacing: 1px;
}

/* 卡片會飛到畫面外，不擋的話文件寬度會被撐開、跑出橫向捲軸。

   這一定要下在視窗層級，不能下在 #view-daily-cards。
   .container 是 max-width:600px 且左右各有 20px 內距，畫面本身是它的
   子元素，在那裡裁等於裁在「容器邊緣」而不是「螢幕邊緣」——
   手機會在離邊 20px 處被切掉，桌機更誇張（離邊 400px 以上），
   看起來就是卡片在一個框裡面滑走，而不是滑出螢幕。

   html 和 body 兩個都要寫：只寫 body 的話它會被propagate 到視窗，
   結果 body 自己反而不裁，實測仍然可以往右捲（scrollX 跑到 475）。
   兩個都下才真的既不裁在容器上、也捲不動。

   用 clip 不用 hidden：規範裡 overflow-x:clip 不會把 overflow-y:visible
   逼成 auto，所以不會生出捲動容器，頁首的 sticky 不受影響
   （實測捲到 y=600 頁首仍吸在 top=0）。 */
html, body {
    overflow-x: clip;
}
/* 不認得 clip 的舊瀏覽器：至少讓視窗本身不能橫向撐開（只下在 html，
   它會轉給視窗；body 不動，頁首的 sticky 就不受影響）。 */
@supports not (overflow-x: clip) {
    html { overflow-x: hidden; }
}

/* ── 卡片 ── */
@keyframes dcIn {
    0%   { opacity: 0; transform: scale(0.9) translateY(16px); }
    60%  { opacity: 1; transform: scale(1.015) translateY(0); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
/* 抽走：真的要離開畫面。
   原本只位移 120px，卡片本身就有 420px 寬，等於還沒離開原位就淡掉了，
   看起來像「原地消失」而不是「被抽走」。
   距離用 calc(50vw + 60%)：卡片置中，左緣到畫面右邊剛好是 50vw + 半個身寬，
   所以 50vw + 50% 就「剛好完全出去」，多給 10% 當餘裕。
   不要再多給：距離拉太長，卡片早早就飛出畫面，剩下的時間都在畫面外空跑，
   使用者會感覺按完之後卡了一下下一張才進來。
   旋轉軸心放在卡片下方（見 .dc-card 的 transform-origin），
   轉起來像被手指往旁邊甩，而不是整塊在原地自轉。 */
@keyframes dcOutRight {
    0%   { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg) scale(1); }
    85%  { opacity: 1; }
    100% { opacity: 0; transform: translate3d(calc(50vw + 60%), 26px, 0) rotate(16deg) scale(0.94); }
}
@keyframes dcOutLeft {
    0%   { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg) scale(1); }
    85%  { opacity: 1; }
    100% { opacity: 0; transform: translate3d(calc(-50vw - 60%), 26px, 0) rotate(-16deg) scale(0.94); }
}

/* 牌桌：負責「整疊牌」的外觀與定位，飛走的卡片是它的子元素。
   overflow 不能設 hidden，卡片要能飛出去；改由 #view-daily-cards 擋橫向溢位。 */
.dc-stage {
    position: relative;
    max-width: 420px;
    margin: 18px auto 0;
}

.dc-card {
    position: relative;
    z-index: 3;                    /* 疊在牌堆兩層（::before / ::after）上面 */
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 48px 26px 36px;
    /* 固定高度，不是 min-height：底下那張是絕對定位、跟著牌桌的高度走，
       而牌桌的高度由最上面那張決定。高度一變，換牌的瞬間整張卡會突然
       長高或縮短，底下的按鈕也跟著跳。一副牌本來就該每張一樣大。
       278px 是量過最長的字（AI/artificial intelligence）在 320px 窄機上的需求後訂的。 */
    height: 278px;
    overflow: hidden;
    transform-origin: 50% 130%;    /* 軸心在卡片下方，甩出去才像抽牌不像自轉 */
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
}
/* 底下墊兩張「真的卡」，而不是只有邊框。
   之前用 box-shadow 畫一圈輪廓，最上面那張飛走的瞬間就只剩兩條空的邊，
   看起來是「空的卻有厚度」。牌堆底下本來就還有牌，就該看得到牌面。
   兩層都比上面一張窄一點、往下露一截，才有一疊牌的層次。 */
/* 牌堆分成兩件事處理，因為卡片是半透明的：任何壓在它底下的東西都會透出來。

   ::after ＝ 平常看到的「厚度」。用 box-shadow 畫，陰影只會出現在邊框外側，
   完全不會疊到卡片正面，所以不會透出來變成框中有框。
   ::before ＝ 下一張牌的牌面。平常 opacity:0（才不會透過玻璃看到），
   只有在最上面那張正在飛走時才淡入 —— 這樣抽走的瞬間底下是有牌的，
   不會出現「空的卻有厚度」。 */
.dc-stage::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: 20px;
    pointer-events: none;
    box-shadow:
        0  8px 0 -3px var(--card-bg),
        0  8px 0 -2px var(--border),
        0 17px 0 -7px var(--card-bg),
        0 17px 0 -6px var(--border);
}
/* 真的只剩最後一張時，後面就沒牌了，厚度也不該還在 */
.dc-stage.dc-last::after { display: none; }

/* 下一張牌：內容已經渲染好，就等著遞補。
   平常 opacity:0 —— 上面那張是半透明玻璃，不藏起來會直接看到兩個單字疊在一起。
   最上面那張開始飛走時才淡入，同時從「後面一點、小一點」推到正位，
   所以抽走的瞬間底下就是下一張牌，不是空的。 */
.dc-card-back {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    opacity: 0;
    transform: scale(0.94) translateY(9px);
    transition: opacity 0.14s ease, transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.dc-stage.dc-swiping .dc-card-back {
    opacity: 1;
    transform: none;
    transition-delay: 0.04s, 0s;
}

.dc-card.dc-in        { animation: dcIn 0.34s cubic-bezier(0.22, 1, 0.36, 1) both; }
/* ease-out（快出、後段減速）才像被甩出去；原本的 ease-in 是慢慢加速，
   配上短距離就變成「原地抖一下再不見」。時間也從 0.26s 拉長到 0.38s，
   距離變長了，太快會看不出是往哪邊走。 */
.dc-card.dc-out-right { animation: dcOutRight 0.34s cubic-bezier(0.25, 0.46, 0.45, 0.94) both; }
.dc-card.dc-out-left  { animation: dcOutLeft  0.34s cubic-bezier(0.25, 0.46, 0.45, 0.94) both; }

.dc-level {
    font-size: 0.7rem;
    letter-spacing: 2px;
    color: var(--text-sub);
    text-transform: uppercase;
}
.dc-en {
    font-size: clamp(1.9rem, 8vw, 2.6rem);
    font-weight: 600;
    letter-spacing: 0.5px;
    line-height: 1.25;
    color: var(--text-main);
    word-break: break-word;
}
/* 少數很長的條目（像 AI/artificial intelligence）用原尺寸會撐到三行，
   卡片高度固定後就會被裁掉，所以字級跟著縮。由 fillCard 依長度掛上。 */
.dc-en.dc-en-long {
    font-size: clamp(1.3rem, 5.4vw, 1.75rem);
    line-height: 1.3;
}
.dc-zh {
    font-size: 1rem;
    color: var(--text-sub);
    line-height: 1.7;
    max-width: 90%;
}
.dc-replay {
    margin-top: 14px;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-sub);
    border-radius: 18px;
    padding: 6px 16px;
    font-size: 0.76rem;
    font-family: inherit;
    letter-spacing: 0.5px;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s;
}
@media (hover: hover) {
    .dc-replay:hover { border-color: var(--text-sub); color: var(--text-main); }
}

.dc-empty {
    text-align: center;
    color: var(--text-sub);
    font-size: 0.92rem;
    padding: 70px 20px;
    line-height: 1.8;
}

/* ── 兩顆操作鍵 ── */
.dc-actions {
    display: flex;
    gap: 12px;
    max-width: 420px;
    margin: 34px auto 0;
}
.dc-btn {
    flex: 1;
    padding: 16px 12px;
    border-radius: 14px;
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 500;
    letter-spacing: 1px;
    cursor: pointer;
    transition: transform 0.12s, background 0.2s, border-color 0.2s;
}
.dc-btn:active { transform: scale(0.97); }
.dc-btn-skip {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-sub);
}
.dc-btn-like {
    background: rgba(255, 255, 255, 0.22);
    border: 1px solid rgba(255, 255, 255, 0.36);
    color: var(--text-main);
    font-weight: 600;
    backdrop-filter: blur(12px) saturate(160%);
    -webkit-backdrop-filter: blur(12px) saturate(160%);
    box-shadow:
        0 0 14px rgba(255, 255, 255, 0.10),
        inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
@media (hover: hover) {
    .dc-btn-skip:hover { border-color: var(--text-sub); color: var(--text-main); }
    .dc-btn-like:hover { background: rgba(255, 255, 255, 0.32); border-color: rgba(255, 255, 255, 0.5); }
}

.dc-hint {
    text-align: center;
    font-size: 0.78rem;
    color: var(--text-sub);
    opacity: 0.75;
    margin-top: 22px;
    line-height: 1.7;
}

/* ── 結算頁 ── */
.dc-field-label {
    display: block;
    font-size: 0.78rem;
    color: var(--text-sub);
    letter-spacing: 0.5px;
    margin-bottom: 6px;
}

.dc-summary-list {
    margin-top: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.dc-sum-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 11px 14px;
}
.dc-sum-text { min-width: 0; }
.dc-sum-en {
    display: block;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-main);
    letter-spacing: 0.3px;
}
.dc-sum-zh {
    display: block;
    font-size: 0.76rem;
    color: var(--text-sub);
    margin-top: 2px;
    line-height: 1.5;
}
.dc-sum-del {
    flex-shrink: 0;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-sub);
    border-radius: 8px;
    padding: 5px 12px;
    font-size: 0.74rem;
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s;
}
@media (hover: hover) {
    .dc-sum-del:hover { border-color: var(--error); color: var(--error); }
}
.dc-sum-empty {
    text-align: center;
    color: var(--text-sub);
    font-size: 0.85rem;
    padding: 30px 0;
}

@media (prefers-reduced-motion: reduce) {
    .dc-card.dc-in,
    .dc-card.dc-out-right,
    .dc-card.dc-out-left { animation: none; }
    /* 卡片不會飛走，底下就沒有空檔要補；照露的話只會透過玻璃多亮一層 */
    .dc-stage.dc-swiping::before { opacity: 0; }
}

/* =========================================================
   主題系統（深色系 · 漸層磨砂）
   ---------------------------------------------------------
   設計取捨：專案裡還有約 340 處寫死的灰階顏色（多半在 index.html 的
   inline style），全部變數化風險太大，所以這一輪的主題全部維持深色底，
   那些寫死的 #222 / #333 在任何深色漸層上都還是能看。
   換色主要靠三樣東西：
     1. --app-bg-grad  整頁的大面積漸層背景
     2. --card-bg      半透明卡片底色（讓漸層透出來）
     3. --glass-blur   磨砂模糊
   淺色主題要等灰階變數化完成才能做。
   ========================================================= */

:root {
    --container-pad: 20px;               /* 容器左右內距，頁首的負外距要跟著它走 */

    /* iPhone 的瀏海／動態島高度。加到主畫面之後（standalone），
       網頁會鋪到螢幕最上緣，這個值就是「不能放東西的那一段」。
       集中成變數是因為有好幾條規則都要用到，各寫各的遲早會有人漏掉 —— 
       上一版就是這樣：頁首寫了，結果被另一條 padding 簡寫整個洗掉。 */
    --safe-top: env(safe-area-inset-top, 0px);
    --app-bg-grad: none;                 /* 預設曜黑：不加漸層，維持原樣 */
    --surface-strong: #1e1e1e;           /* 比卡片再實一階的表面（主要模式按鈕）*/
    --surface-strong-border: #3a3a3a;
    --glass-blur: none;
    --glass-sat: 100%;
    --theme-glow: rgba(255, 255, 255, 0.05);
}

/* 整頁漸層層：固定不捲動，墊在所有內容後面 */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background: var(--app-bg-grad);
}

/* 漸層一律用「百分比」尺寸，不要用固定像素。
   手機螢幕可以高達 2000px 以上，radial-gradient(1000px 600px ...) 只會蓋住
   最上面三分之一，中間以下直接掉回純黑，看起來就像一條彩色橫幅貼在黑 App 上。
   百分比是相對於這個 fixed 圖層（＝整個視窗），所以不管螢幕多長都均勻。
   另外底部顏色刻意不收到純黑，讓整頁從頭到尾都帶著同一個色調。 */

/* ── 午夜藍 ── */
html[data-theme="midnight"] {
    --bg-color:   #0b1322;
    --card-bg:    rgba(154, 188, 240, 0.105);
    --border:     rgba(154, 188, 240, 0.20);
    --text-main:  #dfe7f5;
    --text-sub:   #8b9bb8;
    --app-bg-grad:
        radial-gradient(165% 115% at 50% -15%, rgba(70, 122, 214, 0.105), transparent 78%),
        linear-gradient(180deg, #1d2b46 0%, #1a2640 52%, #172135 100%);
    --surface-strong:        rgba(154, 188, 240, 0.17);
    --surface-strong-border: rgba(154, 188, 240, 0.28);
    --glass-blur: blur(18px);
    --glass-sat: 130%;
    --theme-glow: rgba(96, 150, 230, 0.10);
}

/* ── 森墨 ── */
html[data-theme="forest"] {
    --bg-color:   #0b1614;
    --card-bg:    rgba(162, 216, 192, 0.10);
    --border:     rgba(162, 216, 192, 0.19);
    --text-main:  #ddeae4;
    --text-sub:   #8aa79a;
    --app-bg-grad:
        radial-gradient(165% 115% at 50% -15%, rgba(44, 150, 112, 0.10), transparent 78%),
        linear-gradient(180deg, #163229 0%, #132b24 52%, #11251f 100%);
    --surface-strong:        rgba(162, 216, 192, 0.16);
    --surface-strong-border: rgba(162, 216, 192, 0.27);
    --glass-blur: blur(18px);
    --glass-sat: 125%;
    --theme-glow: rgba(90, 200, 150, 0.09);
}

/* ── 暗紫霓虹 ── */
html[data-theme="neon"] {
    --bg-color:   #150d24;
    --card-bg:    rgba(202, 168, 242, 0.105);
    --border:     rgba(202, 168, 242, 0.21);
    --text-main:  #e8dff5;
    --text-sub:   #a495bc;
    --app-bg-grad:
        radial-gradient(165% 115% at 50% -15%, rgba(148, 68, 214, 0.115), transparent 78%),
        linear-gradient(180deg, #281a44 0%, #23163b 52%, #1e1332 100%);
    --surface-strong:        rgba(202, 168, 242, 0.17);
    --surface-strong-border: rgba(202, 168, 242, 0.30);
    --glass-blur: blur(20px);
    --glass-sat: 140%;
    --theme-glow: rgba(180, 90, 230, 0.12);
}

/* ── 玫瑰灰 ── */
html[data-theme="rose"] {
    --bg-color:   #1b1013;
    --card-bg:    rgba(240, 192, 194, 0.10);
    --border:     rgba(240, 192, 194, 0.19);
    --text-main:  #efe2e2;
    --text-sub:   #ad9695;
    --app-bg-grad:
        radial-gradient(165% 115% at 50% -15%, rgba(186, 92, 102, 0.10), transparent 78%),
        linear-gradient(180deg, #2f1c20 0%, #2a181c 52%, #241518 100%);
    --surface-strong:        rgba(240, 192, 194, 0.16);
    --surface-strong-border: rgba(240, 192, 194, 0.27);
    --glass-blur: blur(18px);
    --glass-sat: 120%;
    --theme-glow: rgba(226, 140, 148, 0.10);
}

/* ── 石墨藍灰（低調款）── */
html[data-theme="graphite"] {
    --bg-color:   #10151a;
    --card-bg:    rgba(184, 204, 220, 0.095);
    --border:     rgba(184, 204, 220, 0.18);
    --text-main:  #e2e7eb;
    --text-sub:   #909aa4;
    --app-bg-grad:
        radial-gradient(165% 115% at 50% -15%, rgba(96, 136, 176, 0.10), transparent 78%),
        linear-gradient(180deg, #202b37 0%, #1c2631 52%, #19212b 100%);
    --surface-strong:        rgba(184, 204, 220, 0.15);
    --surface-strong-border: rgba(184, 204, 220, 0.26);
    --glass-blur: blur(16px);
    --glass-sat: 115%;
    --theme-glow: rgba(150, 180, 210, 0.08);
}

/* ── 銀河（Pro 專屬） ──
   唯一有動態背景的主題：星空與流星在 #theme-fx[data-fx="galaxy"]（由 app.js 的 applyGalaxyFx
   建立／移除），換回其他主題時整層會被拿掉，效果自然跟著消失。
   玻璃也比別的主題再冷一階：模糊更重、飽和更高，並帶一點藍紫底，
   讓卡片看起來像浮在星空上而不是貼著。 */
html[data-theme="galaxy"] {
    --bg-color:   #04060e;
    --card-bg:    rgba(158, 178, 255, 0.085);
    --border:     rgba(158, 178, 255, 0.17);
    --text-main:  #e2e7fa;
    --text-sub:   #8e9ac2;
    /* 這裡刻意比其他主題暗得多：太空的底就是接近全黑，
       星雲只是幾團很淡的顏色浮在上面。底色一亮就不像太空，
       而且星星會被蓋掉 —— 星星看不見的話這個主題就沒意義了。 */
    --app-bg-grad:
        radial-gradient(140% 95% at 14% -10%, rgba(58, 48, 140, 0.30), transparent 66%),
        radial-gradient(130% 90% at 88% 4%,   rgba(20, 84, 122, 0.22), transparent 68%),
        radial-gradient(120% 85% at 64% 106%, rgba(88, 40, 120, 0.20), transparent 66%),
        linear-gradient(180deg, #080b1c 0%, #060814 50%, #03040a 100%);
    --surface-strong:        rgba(158, 178, 255, 0.15);
    --surface-strong-border: rgba(158, 178, 255, 0.26);
    --glass-blur: blur(22px);
    --glass-sat: 150%;
    --theme-glow: rgba(132, 152, 255, 0.12);
}

/* 特效層本身。z-index -1 跟 body::before 同層，但 DOM 順序在後面，
   所以會疊在整頁漸層之上、內容之下。contain 讓動畫不觸發外層重排。 */
/* =========================================================
   三個免費的動態主題：極光 / 細雨 / 微塵
   ---------------------------------------------------------
   做法跟銀河同一套，品質也照同一個標準：
     · 只用 transform 與 opacity 做動畫 —— 那兩個由合成器處理，
       不會每一幀重新繪製。像 background-position 那種會觸發重繪，
       在低階手機上會明顯掉幀。
     · 不用 filter: blur()。卡片已經有 backdrop-filter: blur(22px)，
       再疊一層模糊等於「模糊一個模糊過的東西」，很吃 GPU。
       柔邊改用 gradient 本身的漸變來做，那是免費的。
     · 速度都放到很慢（20 秒以上一輪）。這是背單字的畫面，
       背景會動可以，但不能搶注意力。
   ========================================================= */

/* ── 極光 ────────────────────────────────────────────────
   深海藍綠的底，三道極光帶在上面非常緩慢地飄。
   底色壓得低，極光才浮得出來。 */
html[data-theme="aurora"] {
    --bg-color:   #040d11;
    --card-bg:    rgba(150, 226, 218, 0.075);
    --border:     rgba(150, 226, 218, 0.16);
    --text-main:  #dff2ef;
    --text-sub:   #86a8a6;
    --app-bg-grad:
        radial-gradient(130% 90% at 18% -8%,  rgba(22, 104, 106, 0.30), transparent 64%),
        radial-gradient(120% 85% at 86% 8%,   rgba(28, 72, 118, 0.26), transparent 66%),
        radial-gradient(130% 90% at 56% 108%, rgba(18, 88, 84, 0.20), transparent 64%),
        linear-gradient(180deg, #06141a 0%, #041016 52%, #020709 100%);
    --surface-strong:        rgba(150, 226, 218, 0.14);
    --surface-strong-border: rgba(150, 226, 218, 0.24);
    --glass-blur: blur(22px);
    --glass-sat: 150%;
    --theme-glow: rgba(120, 224, 208, 0.12);
}

/* 三道帶子。每道是一個比畫面還大的橢圓漸層，靠 translate + rotate
   慢慢飄。尺寸刻意超出畫面，邊緣才不會被切出一條直線。 */
#theme-fx[data-fx="aurora"] i {
    position: absolute;
    left: -30%;
    width: 160%;
    height: 58%;
    border-radius: 50%;
    will-change: transform, opacity;
}
#theme-fx[data-fx="aurora"] i:nth-child(1) {
    top: -18%;
    background: radial-gradient(ellipse 50% 50% at 50% 50%,
        rgba(var(--personal-fx-rgb, 64, 232, 188), 0.20), rgba(var(--personal-fx-rgb, 64, 232, 188), 0.07) 42%, transparent 70%);
    animation: aurora-drift-a 34s ease-in-out infinite;
}
#theme-fx[data-fx="aurora"] i:nth-child(2) {
    top: 8%;
    background: radial-gradient(ellipse 50% 50% at 50% 50%,
        rgba(var(--personal-fx-rgb, 96, 168, 255), 0.17), rgba(var(--personal-fx-rgb, 96, 168, 255), 0.06) 44%, transparent 72%);
    animation: aurora-drift-b 46s ease-in-out infinite;
    animation-delay: -12s;
}
#theme-fx[data-fx="aurora"] i:nth-child(3) {
    top: 30%;
    background: radial-gradient(ellipse 50% 50% at 50% 50%,
        rgba(var(--personal-fx-rgb, 158, 120, 255), 0.13), rgba(var(--personal-fx-rgb, 158, 120, 255), 0.05) 46%, transparent 74%);
    animation: aurora-drift-a 58s ease-in-out infinite;
    animation-delay: -28s;
}
/* 兩支不同的路徑，錯開之後三道帶子不會整齊劃一地一起動 */
@keyframes aurora-drift-a {
    0%   { transform: translate3d(-8%, 0, 0) rotate(-3deg) scaleY(1);    opacity: 0.55; }
    50%  { transform: translate3d(8%, 4%, 0) rotate(2deg)  scaleY(1.25); opacity: 0.95; }
    100% { transform: translate3d(-8%, 0, 0) rotate(-3deg) scaleY(1);    opacity: 0.55; }
}
@keyframes aurora-drift-b {
    0%   { transform: translate3d(6%, 2%, 0)  rotate(2deg)  scaleY(1.15); opacity: 0.85; }
    50%  { transform: translate3d(-6%, -3%, 0) rotate(-2deg) scaleY(0.9);  opacity: 0.45; }
    100% { transform: translate3d(6%, 2%, 0)  rotate(2deg)  scaleY(1.15); opacity: 0.85; }
}

/* ── 細雨 ────────────────────────────────────────────────
   冷灰藍的底，斜斜的雨絲，加上幾滴留在玻璃上慢慢滑下來的水珠。
   跟卡片的磨砂玻璃搭在一起，像隔著窗看外面下雨。 */
html[data-theme="rain"] {
    --bg-color:   #0b1117;
    --card-bg:    rgba(176, 202, 226, 0.075);
    --border:     rgba(176, 202, 226, 0.16);
    --text-main:  #e2eaf2;
    --text-sub:   #90a2b5;
    --app-bg-grad:
        radial-gradient(120% 85% at 24% -10%, rgba(52, 82, 116, 0.28), transparent 64%),
        radial-gradient(130% 90% at 82% 12%,  rgba(40, 62, 90, 0.24), transparent 66%),
        linear-gradient(180deg, #121a23 0%, #0d141b 54%, #070b0f 100%);
    --surface-strong:        rgba(176, 202, 226, 0.14);
    --surface-strong-border: rgba(176, 202, 226, 0.24);
    --glass-blur: blur(22px);
    --glass-sat: 140%;
    --theme-glow: rgba(150, 190, 230, 0.10);
}

/* 雨絲用 repeating-linear-gradient 平鋪。兩層不同的角度與速度，
   才有前後景的層次 —— 只有一層看起來像壁紙，不像在下雨。
   元素做成兩倍高、用 translateY 位移一整個高度再循環，
   這樣接縫剛好對上，看不出重複。 */
#theme-fx[data-fx="rain"]::before,
#theme-fx[data-fx="rain"]::after {
    content: "";
    position: absolute;
    left: -20%;
    width: 140%;
    height: 200%;
    top: -100%;
    will-change: transform;
}
/* 雨絲要「短」。只用 repeating-linear-gradient 的話畫出來是一條條
   貫穿整個畫面的直線 —— 看起來像刮痕，而且會直接壓過文字。
   所以再套一層遮罩，沿著線的方向把它切成一段一段。
   遮罩的角度要跟漸層差 90 度（102 - 90 = 12），那才是「沿著線」的方向；
   角度寫成一樣的話只會把線變細，不會變短。 */
#theme-fx[data-fx="rain"]::before {
    background-image: repeating-linear-gradient(
        102deg,
        transparent 0 9px,
        rgba(var(--personal-fx-rgb, 196, 220, 244), 0.085) 9px 10px,
        transparent 10px 30px
    );
    -webkit-mask-image: repeating-linear-gradient(12deg, #000 0 26px, transparent 26px 120px);
    mask-image: repeating-linear-gradient(12deg, #000 0 26px, transparent 26px 120px);
    animation: rain-fall-a 1.5s linear infinite;
}
#theme-fx[data-fx="rain"]::after {
    background-image: repeating-linear-gradient(
        98deg,
        transparent 0 17px,
        rgba(var(--personal-fx-rgb, 196, 220, 244), 0.05) 17px 18px,
        transparent 18px 54px
    );
    -webkit-mask-image: repeating-linear-gradient(8deg, #000 0 18px, transparent 18px 150px);
    mask-image: repeating-linear-gradient(8deg, #000 0 18px, transparent 18px 150px);
    animation: rain-fall-b 2.6s linear infinite;
}
@keyframes rain-fall-a { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-6%, 50%, 0); } }
@keyframes rain-fall-b { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-4%, 50%, 0); } }

/* 玻璃上的水珠。慢慢往下滑、邊滑邊變小，滑到底就消失。
   六顆用不同的起點與延遲錯開，看起來才像偶爾才有一顆。 */
#theme-fx[data-fx="rain"] i {
    position: absolute;
    width: 2px;
    height: 12px;
    border-radius: 0 0 2px 2px;
    background: linear-gradient(180deg,
        rgba(var(--personal-fx-rgb, 214, 234, 255), 0.05), rgba(var(--personal-fx-rgb, 214, 234, 255), 0.42));
    box-shadow: 0 0 6px rgba(var(--personal-fx-rgb, 190, 220, 250), 0.22);
    will-change: transform, opacity;
}
#theme-fx[data-fx="rain"] i:nth-child(1) { left: 12%; animation: rain-drop 9s  linear infinite; animation-delay: 0s; }
#theme-fx[data-fx="rain"] i:nth-child(2) { left: 31%; animation: rain-drop 13s linear infinite; animation-delay: 2.5s; }
#theme-fx[data-fx="rain"] i:nth-child(3) { left: 48%; animation: rain-drop 11s linear infinite; animation-delay: 5s; }
#theme-fx[data-fx="rain"] i:nth-child(4) { left: 66%; animation: rain-drop 15s linear infinite; animation-delay: 7.5s; }
#theme-fx[data-fx="rain"] i:nth-child(5) { left: 79%; animation: rain-drop 10s linear infinite; animation-delay: 10s; }
#theme-fx[data-fx="rain"] i:nth-child(6) { left: 92%; animation: rain-drop 14s linear infinite; animation-delay: 12.5s; }
@keyframes rain-drop {
    0%   { transform: translate3d(0, -8vh, 0) scaleY(1);   opacity: 0; }
    8%   { opacity: 0.9; }
    88%  { opacity: 0.55; }
    100% { transform: translate3d(0, 104vh, 0) scaleY(0.5); opacity: 0; }
}

/* ── 微塵 ────────────────────────────────────────────────
   溫暖的赭色底，一道從右上灑進來的光，塵埃在光裡慢慢上浮。
   這是三個裡面最安靜的，適合久坐。 */
html[data-theme="dust"] {
    --bg-color:   #100c08;
    --card-bg:    rgba(240, 214, 176, 0.075);
    --border:     rgba(240, 214, 176, 0.16);
    --text-main:  #f2e8dc;
    --text-sub:   #ab9b86;
    --app-bg-grad:
        radial-gradient(110% 80% at 88% -12%, rgba(168, 116, 52, 0.30), transparent 60%),
        radial-gradient(130% 95% at 14% 22%,  rgba(96, 62, 38, 0.24), transparent 66%),
        radial-gradient(120% 85% at 60% 110%, rgba(60, 40, 28, 0.22), transparent 64%),
        linear-gradient(180deg, #1a130c 0%, #120d08 54%, #080604 100%);
    --surface-strong:        rgba(240, 214, 176, 0.14);
    --surface-strong-border: rgba(240, 214, 176, 0.24);
    --glass-blur: blur(22px);
    --glass-sat: 145%;
    --theme-glow: rgba(232, 186, 122, 0.12);
}

/* 塵埃用平鋪的小圓點，跟銀河的星空同一招 —— 那招已經驗證過，
   幾百顆粒子只要兩個元素。差別是這裡會往上飄而不是只閃爍。
   一樣做成兩倍高、位移一整個高度再循環，接縫才對得上。 */
#theme-fx[data-fx="dust"]::before,
#theme-fx[data-fx="dust"]::after {
    content: "";
    position: absolute;
    left: 0;
    width: 100%;
    height: 200%;
    top: -100%;
    background-repeat: repeat;
    will-change: transform;
}
#theme-fx[data-fx="dust"]::before {
    background-image:
        radial-gradient(1.7px 1.7px at 28px 44px,   rgba(var(--personal-fx-rgb, 255, 226, 178), 0.55), transparent),
        radial-gradient(1.3px 1.3px at 118px 152px, rgba(var(--personal-fx-rgb, 255, 236, 202), 0.40), transparent),
        radial-gradient(2.0px 2.0px at 196px 82px,  rgba(var(--personal-fx-rgb, 255, 220, 166), 0.50), transparent),
        radial-gradient(1.2px 1.2px at 74px 214px,  rgba(var(--personal-fx-rgb, 255, 232, 194), 0.34), transparent);
    background-size: 260px 260px;
    animation: dust-rise-a 44s linear infinite;
}
#theme-fx[data-fx="dust"]::after {
    background-image:
        radial-gradient(1.1px 1.1px at 62px 96px,   rgba(var(--personal-fx-rgb, 255, 228, 184), 0.30), transparent),
        radial-gradient(1.4px 1.4px at 158px 38px,  rgba(var(--personal-fx-rgb, 255, 216, 160), 0.38), transparent),
        radial-gradient(1.0px 1.0px at 104px 186px, rgba(var(--personal-fx-rgb, 255, 238, 206), 0.26), transparent);
    background-size: 190px 190px;
    animation: dust-rise-b 72s linear infinite;
}
/* 往上飄的同時左右微微漂移，才不像被繩子吊著直直往上拉 */
@keyframes dust-rise-a {
    from { transform: translate3d(0, 50%, 0); }
    to   { transform: translate3d(2%, 0, 0); }
}
@keyframes dust-rise-b {
    from { transform: translate3d(0, 50%, 0); }
    to   { transform: translate3d(-2%, 0, 0); }
}

/* ── 省電模式：把會動的全部停掉 ──────────────────────────
   使用者選了省電就是不想讓手機一直在畫東西。留下靜態的樣子，
   不要整個變空 —— 空掉的話會以為主題壞了。 */
/* 極光這條一定要寫 :nth-child(n)。原規則是 i:nth-child(1) —— 多一個偽類，
   特異度就比只寫 i 高，而媒體查詢與 html[data-fx] 都不會幫忙補特異度，
   結果就是 animation: none 被原規則蓋掉、省電模式下極光照樣在飄。 */
html[data-fx="low"] #theme-fx[data-fx="aurora"] i:nth-child(n),
html[data-fx="low"] #theme-fx[data-fx="rain"]::before,
html[data-fx="low"] #theme-fx[data-fx="rain"]::after,
html[data-fx="low"] #theme-fx[data-fx="dust"]::before,
html[data-fx="low"] #theme-fx[data-fx="dust"]::after {
    animation: none;
}
html[data-fx="low"] #theme-fx[data-fx="rain"] i { display: none; }
html[data-fx="low"] #theme-fx[data-fx="aurora"] i:nth-child(n) { opacity: 0.7; }

/* 省電時卡片改成實色（跟其他主題一致，磨砂很吃效能） */
html[data-fx="low"][data-theme="aurora"] { --card-bg: #11282b; --surface-strong: #17363a; }
html[data-fx="low"][data-theme="rain"]   { --card-bg: #1a242e; --surface-strong: #24313d; }
html[data-fx="low"][data-theme="dust"]   { --card-bg: #241c13; --surface-strong: #32261a; }

/* ── 使用者要求減少動態效果 ──────────────────────────────
   這是系統層級的無障礙設定，優先權比好看高。 */
@media (prefers-reduced-motion: reduce) {
    #theme-fx[data-fx="aurora"] i:nth-child(n),
    #theme-fx[data-fx="rain"]::before,
    #theme-fx[data-fx="rain"]::after,
    #theme-fx[data-fx="dust"]::before,
    #theme-fx[data-fx="dust"]::after {
        animation: none;
    }
    #theme-fx[data-fx="rain"] i { display: none; }
}

/* ── 設定頁的色票 ────────────────────────────────────────
   縮圖要一眼看得出來是哪個主題，所以各自畫出代表性的樣子。 */
.sw-aurora {
    background:
        radial-gradient(ellipse 80% 40% at 30% 28%, rgba(64, 232, 188, 0.55), transparent 70%),
        radial-gradient(ellipse 75% 38% at 70% 48%, rgba(96, 168, 255, 0.45), transparent 72%),
        linear-gradient(165deg, #0d3038, #061a20 55%, #030b0e 100%);
}
.sw-rain {
    background:
        repeating-linear-gradient(102deg, transparent 0 5px, rgba(196, 220, 244, 0.30) 5px 6px, transparent 6px 16px),
        linear-gradient(165deg, #2b4055, #131d27 55%, #080d12 100%);
}
.sw-dust {
    background:
        radial-gradient(1.8px 1.8px at 26% 32%, rgba(255, 226, 178, 0.9), transparent),
        radial-gradient(1.4px 1.4px at 62% 22%, rgba(255, 236, 202, 0.7), transparent),
        radial-gradient(2.0px 2.0px at 44% 58%, rgba(255, 220, 166, 0.85), transparent),
        radial-gradient(1.2px 1.2px at 80% 48%, rgba(255, 232, 194, 0.6), transparent),
        radial-gradient(ellipse 70% 55% at 85% 8%, rgba(198, 140, 62, 0.5), transparent 70%),
        linear-gradient(165deg, #3a2716, #1a1209 55%, #0a0704 100%);
}

/* 所有動態主題共用同一個容器。z-index -1 跟 body::before 同層，
   但 DOM 順序在後面，所以會疊在整頁漸層之上、內容之下。
   contain: strict 讓裡面的動畫不會觸發外層重排。 */
#theme-fx {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    overflow: hidden;
    contain: strict;
}

/* 星空用 radial-gradient 平鋪，不是幾百個 DOM 節點。
   兩層用不同的 background-size 與閃爍速度，看起來才有遠近層次。 */
#theme-fx[data-fx="galaxy"]::before,
#theme-fx[data-fx="galaxy"]::after {
    content: "";
    position: absolute;
    inset: 0;                 /* 剛好一個視窗就夠：星空不位移，只改透明度 */
    background-repeat: repeat;
    will-change: opacity;
}

#theme-fx[data-fx="galaxy"]::before {
    background-image:
        radial-gradient(1.4px 1.4px at 18px 32px,  rgba(255,255,255,0.90), transparent),
        radial-gradient(1.2px 1.2px at 96px 128px, rgba(214,228,255,0.75), transparent),
        radial-gradient(1.6px 1.6px at 172px 64px, rgba(255,255,255,0.95), transparent),
        radial-gradient(1.1px 1.1px at 58px 196px, rgba(198,214,255,0.70), transparent),
        radial-gradient(1.3px 1.3px at 216px 172px,rgba(255,255,255,0.80), transparent);
    background-size: 240px 240px;
    animation: galaxy-twinkle-a 5.5s ease-in-out infinite;
}

#theme-fx[data-fx="galaxy"]::after {
    background-image:
        radial-gradient(1px 1px at 44px 88px,   rgba(255,255,255,0.65), transparent),
        radial-gradient(1px 1px at 148px 24px,  rgba(190,210,255,0.55), transparent),
        radial-gradient(1.2px 1.2px at 88px 264px, rgba(255,255,255,0.70), transparent),
        radial-gradient(1px 1px at 268px 148px, rgba(206,222,255,0.55), transparent);
    background-size: 340px 340px;
    animation: galaxy-twinkle-b 8.5s ease-in-out infinite;
}

/* 兩層的最低亮度刻意不一樣，避免同時變暗看起來像整片在閃 */
@keyframes galaxy-twinkle-a {
    0%, 100% { opacity: 0.55; }
    50%      { opacity: 1; }
}
@keyframes galaxy-twinkle-b {
    0%, 100% { opacity: 0.95; }
    50%      { opacity: 0.45; }
}

/* 流星：元素本身是一條「上淡下亮」的直線，頭在下緣。
   先 rotate 再 translate，位移就會沿著它自己的指向走，
   所以尾巴永遠拖在後面，不用另外算角度。 */
#theme-fx[data-fx="galaxy"] i {
    position: absolute;
    display: block;
    width: 2px;
    height: 110px;
    border-radius: 2px;
    background: linear-gradient(to bottom,
        rgba(255, 255, 255, 0) 0%,
        rgba(178, 202, 255, 0.55) 55%,
        rgba(255, 255, 255, 0.95) 100%);
    opacity: 0;
    will-change: transform, opacity;
}

/* 五顆各自有起點、角度與節奏。週期拉長、亮的時間只佔一小段（行程的
   1%~7%，之後就停在終點等下一輪），平均每幾秒才看到一顆，不會變成流星雨。
   全部朝左下，跟真的流星雨一樣同向；起點都放在畫面右側，因為位移是沿著
   自己的指向走，從右邊出發才會真的橫越畫面，從左邊出發會立刻飛出去。 */
#theme-fx[data-fx="galaxy"] i:nth-child(1) { top: -14%; left: 100%; animation: galaxy-meteor-a 11s linear infinite; animation-delay: 0s; }
#theme-fx[data-fx="galaxy"] i:nth-child(2) { top: -20%; left: 105%; animation: galaxy-meteor-b 14s linear infinite; animation-delay: 3.5s; }
#theme-fx[data-fx="galaxy"] i:nth-child(3) { top: -12%; left:  78%; animation: galaxy-meteor-a 17s linear infinite; animation-delay: 7s; }
#theme-fx[data-fx="galaxy"] i:nth-child(4) { top: -22%; left: 118%; animation: galaxy-meteor-b 13s linear infinite; animation-delay: 10.5s; }
#theme-fx[data-fx="galaxy"] i:nth-child(5) { top: -16%; left:  62%; animation: galaxy-meteor-a 19s linear infinite; animation-delay: 15s; }

@keyframes galaxy-meteor-a {
    0%          { transform: rotate(28deg) translate3d(0, 0, 0); opacity: 0; }
    1%          { opacity: 0.95; }
    7%          { opacity: 0; }
    8%, 100%    { transform: rotate(28deg) translate3d(0, 145vh, 0); opacity: 0; }
}
@keyframes galaxy-meteor-b {
    0%          { transform: rotate(34deg) translate3d(0, 0, 0); opacity: 0; }
    1%          { opacity: 0.9; }
    6%          { opacity: 0; }
    7%, 100%    { transform: rotate(34deg) translate3d(0, 145vh, 0); opacity: 0; }
}

/* ── 磨砂：只套在大面積表面，避免手機掉幀 ── */
.card,
.dc-card,
.mode-btn,
#main-header,
.sidebar,
.silen-modal-box,
.nav-icon-btn,
.dc-sum-row,
.wb-grid,
.wb-word {
    backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
}

/* 有漸層主題時，頁首做成吸頂玻璃條。
   這裡「不要」給它自己的底色 —— 一旦加了底色，頁首就變成一塊獨立色塊，
   下緣會出現一條明顯的硬邊界，正是整體看起來很違和的主因。
   保持透明讓整頁漸層直接穿過去，捲動時靠 backdrop-filter 把底下的內容糊掉，
   自然就有層次，不需要畫線。 */
html:not([data-theme="dark"]) #main-header {
    position: sticky;
    top: 0;
    z-index: 50;
    /* 這裡的負外距必須跟 .container 的內距一致，否則頁首會比視窗寬 */
    margin-left: calc(-1 * var(--container-pad));
    margin-right: calc(-1 * var(--container-pad));
    padding: 10px var(--container-pad);
    /* 上面那行是 padding 簡寫，會把基礎規則裡的安全區 padding-top 整個洗掉。
       洗掉的後果不是差幾個 px：iPhone 加到主畫面之後，整個頁首會跑到
       動態島底下，標題、三條槓、頭像全部被蓋住。
       而且這條規則的條件是「不是曜黑主題」—— 新使用者預設就是隨機一個
       動態主題，所以大部分人一加到主畫面就中。 */
    padding-top: calc(var(--safe-top) + 10px);
    background: transparent;
    border-bottom: 1px solid rgba(255, 255, 255, 0.045);
}

/* 「降低特效」：關掉模糊、卡片改成不透明，給舊機型用 */
html[data-fx="low"] {
    --glass-blur: none;
}
html[data-fx="low"][data-theme="midnight"]  { --card-bg: #1a2434; --surface-strong: #243047; }
html[data-fx="low"][data-theme="forest"]    { --card-bg: #172722; --surface-strong: #1f3630; }
html[data-fx="low"][data-theme="neon"]      { --card-bg: #251739; --surface-strong: #32204d; }
html[data-fx="low"][data-theme="rose"]      { --card-bg: #2c1b1e; --surface-strong: #3a2529; }
html[data-fx="low"][data-theme="graphite"]  { --card-bg: #1c242c; --surface-strong: #26303a; }
html[data-fx="low"][data-theme="galaxy"]    { --card-bg: #1b2150; --surface-strong: #262e66; }

/* 降低特效／系統要求減少動態時：流星整個收掉，星空留著但不閃。
   星空是靜態貼圖，成本等同一張背景圖，留著才不會讓銀河變成普通深藍主題。 */
html[data-fx="low"] #theme-fx[data-fx="galaxy"] i { display: none; }
html[data-fx="low"] #theme-fx[data-fx="galaxy"]::before,
html[data-fx="low"] #theme-fx[data-fx="galaxy"]::after { animation: none; opacity: 0.8; }

@media (prefers-reduced-motion: reduce) {
    #theme-fx[data-fx="galaxy"] i { display: none; }
    #theme-fx[data-fx="galaxy"]::before,
    #theme-fx[data-fx="galaxy"]::after { animation: none; opacity: 0.8; }
}

/* ── AI 模式清單的圖示 ──
   用 SVG 不用 emoji：emoji 在不同系統長得完全不一樣（同一個 📖 在
   Android／iOS／Windows 是三種畫風），而且顏色寫死，沒辦法跟著
   每張卡片的主色走，換主題也不會變。
   這裡 stroke 吃 currentColor，顏色交給外層的 color 決定。 */
.ai-icon {
    min-width: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ai-icon svg {
    width: 30px;
    height: 30px;
    display: block;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}
/* 標題旁的小火花，取代原本的 ✨ */
.ai-spark {
    width: 1.05em;
    height: 1.05em;
    display: inline-block;
    vertical-align: -0.14em;
    margin-right: 6px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* ── 設定面板裡的主題選擇 ── */
.theme-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin-bottom: 8px;
}
.theme-swatch {
    position: relative;
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 0;
    height: 62px;
    cursor: pointer;
    overflow: hidden;
    font-family: inherit;
    transition: border-color 0.2s, transform 0.12s;
}
.theme-swatch:active { transform: scale(0.96); }
.theme-swatch[aria-pressed="true"] {
    border-color: var(--text-main);
    box-shadow: 0 0 0 1px var(--text-main) inset;
}
.theme-swatch-name {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 4px 0 5px;
    font-size: 0.68rem;
    letter-spacing: 0.5px;
    color: #fff;
    background: rgba(0, 0, 0, 0.55);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.sw-dark      { background: linear-gradient(150deg, #1c1c1c, #0a0a0a); }
.sw-midnight  { background: linear-gradient(165deg, #2f5091, #141f38 55%, #0a1220 100%); }
.sw-forest    { background: linear-gradient(165deg, #1f7d5f, #11241e 55%, #091412 100%); }
.sw-neon      { background: linear-gradient(165deg, #8a3cc4, #1f1234 58%, #11091c 100%); }
.sw-rose      { background: linear-gradient(165deg, #b45c66, #291719 55%, #170d10 100%); }
.sw-graphite  { background: linear-gradient(165deg, #52748f, #19212a 55%, #0e1319 100%); }
/* 縮圖直接畫幾顆星，讓人一眼看出這個是星空主題 */
.sw-galaxy {
    background:
        radial-gradient(1.4px 1.4px at 22% 26%, #fff, transparent),
        radial-gradient(1.2px 1.2px at 68% 20%, rgba(224,234,255,0.85), transparent),
        radial-gradient(1.6px 1.6px at 44% 52%, #fff, transparent),
        radial-gradient(1.1px 1.1px at 84% 44%, rgba(210,224,255,0.75), transparent),
        radial-gradient(1.3px 1.3px at 14% 62%, rgba(255,255,255,0.85), transparent),
        linear-gradient(165deg, #5a4bc8, #171d4c 52%, #0b1029 100%);
}

/* Pro 專屬主題的角標。刻意用文字而不是鎖頭圖示，跟頁首的 Pro 標籤一致。 */
.theme-swatch-pro {
    position: absolute;
    top: 5px;
    right: 5px;
    padding: 1px 5px;
    border-radius: 5px;
    font-size: 0.56rem;
    font-weight: 700;
    letter-spacing: 0.6px;
    color: #2a2000;
    background: linear-gradient(135deg, #ffdc73, #f0c040);
}

@media (prefers-reduced-motion: reduce) {
    .theme-swatch { transition: none; }
}

/* =========================================================
   好友系統 + 信箱
   ========================================================= */

.nav-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: var(--error);
    color: #fff;
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1;
    border: 2px solid var(--bg-color);
}

.fr-field-label {
    font-size: 0.78rem;
    color: var(--text-sub);
    letter-spacing: 0.5px;
    margin-bottom: 8px;
}

.fr-code-row {
    display: flex;
    align-items: center;
    gap: 12px;
}
.fr-code {
    flex: 1;
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: 7px;
    color: var(--text-main);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.fr-section-title {
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--text-sub);
    letter-spacing: 1px;
    margin: 0 0 12px;
}

.fr-rows {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.fr-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 11px 14px;
}

.fr-id {
    display: flex;
    align-items: center;
    gap: 11px;
    min-width: 0;
}
/* 名字那一塊現在是按鈕（點進去看那個人的主頁）。
   外觀要跟改之前一模一樣 —— 玩家不該因為多了一個功能就覺得版面變了。 */
.fr-open {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
    border-radius: 10px;
}
.fr-open:hover .fr-name { text-decoration: underline; }
.fr-open:focus-visible { outline: 2px solid var(--accent, #f0c040); outline-offset: 2px; }
.fr-avatar {
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    border: 1px solid var(--border);
}
.fr-avatar-ph {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-strong, #2a2a2a);
    color: var(--text-main);
    font-weight: 700;
    font-size: 1rem;
}
.fr-meta { min-width: 0; }
.fr-name {
    display: block;
    font-size: 0.94rem;
    font-weight: 600;
    color: var(--text-main);
    letter-spacing: 0.3px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 38vw;
}
.fr-sub {
    display: block;
    font-size: 0.74rem;
    color: var(--text-sub);
    margin-top: 2px;
}

.fr-status {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.74rem;
    color: var(--text-sub);
    margin-top: 3px;
}
.fr-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}
.fr-status.fr-on  { color: var(--success); }
.fr-status.fr-off { color: var(--text-sub); }
/* 離線超過 3 天 */
.fr-status.fr-far { color: #7a6a4a; }

.fr-actions {
    display: flex;
    gap: 7px;
    flex-shrink: 0;
}
.fr-btn {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-sub);
    border-radius: 8px;
    padding: 6px 11px;
    font-size: 0.75rem;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: border-color 0.2s, color 0.2s, background 0.2s;
}
.fr-btn-ok {
    border-color: var(--text-sub);
    color: var(--text-main);
}
@media (hover: hover) {
    .fr-btn:hover    { border-color: var(--text-sub); color: var(--text-main); }
    .fr-btn-ok:hover { background: var(--surface-strong, #262626); border-color: var(--text-main); }
}

.fr-empty {
    text-align: center;
    color: var(--text-sub);
    font-size: 0.85rem;
    padding: 34px 16px;
    line-height: 1.8;
}

/* ── 信箱 ── */
.mb-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 13px 14px;
}
.mb-row.unread { border-color: var(--text-sub); }
.mb-main { min-width: 0; }
.mb-title {
    display: block;
    font-size: 0.94rem;
    font-weight: 600;
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 42vw;
}
.mb-row.unread .mb-title::before {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--error);
    margin-right: 7px;
    vertical-align: 2px;
}
.mb-sub {
    display: block;
    font-size: 0.74rem;
    color: var(--text-sub);
    margin-top: 3px;
}
/* 系統通知信：內文要整段看得到，按鈕放在下面 */
.mb-row.mb-notice { flex-direction: column; align-items: stretch; }
.mb-notice .mb-title { white-space: normal; max-width: none; }
.mb-body {
    margin: 9px 0 0;
    font-size: 0.86rem;
    line-height: 1.75;
    color: var(--text-main);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}
.mb-notice .fr-actions { justify-content: flex-end; }

/* ── 寄送單字簿彈窗 ── */
#fr-send-overlay,
#dm-book-overlay {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(0, 0, 0, 0.78);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 0.2s;
}
#fr-send-overlay.show, #dm-book-overlay.show { opacity: 1; }
#fr-send-overlay.hidden, #dm-book-overlay.hidden { display: none !important; }

@keyframes frBoxIn {
    0%   { opacity: 0; transform: scale(0.92) translateY(14px); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
.fr-send-box {
    width: 100%;
    max-width: 380px;
    max-height: 78vh;
    display: flex;
    flex-direction: column;
    padding: 22px;
    border-radius: 18px;
    background: var(--card-bg);
    border: 1px solid var(--border);
}
#fr-send-overlay.show .fr-send-box,
#dm-book-overlay.show .fr-send-box {
    animation: frBoxIn 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* 目前選中的那一項 */
.fr-book-on { border-color: #ff9800; background: rgba(255, 152, 0, 0.1); }

/* 自訂房的出題範圍 */
.aw-src { margin-bottom: 14px; text-align: left; }
.aw-src.hidden { display: none; }
.aw-src-label {
    display: block; margin-bottom: 6px;
    font-size: 0.75rem; color: var(--text-sub); letter-spacing: 1px;
}
.aw-src-btn {
    width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 12px 14px; border-radius: 10px;
    background: transparent; border: 1px solid var(--border);
    color: var(--text-main); font-family: inherit; font-size: 0.88rem;
    text-align: left; cursor: pointer;
}
.aw-src-btn > span:first-child {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aw-src-go { flex-shrink: 0; font-size: 0.75rem; color: #ff9800; letter-spacing: 1px; }
.fr-send-title {
    margin: 0 0 16px;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-main);
    letter-spacing: 0.5px;
}
.fr-send-list {
    flex: 1;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.fr-book-btn {
    text-align: left;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 12px 14px;
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, transform 0.12s;
}
.fr-book-btn:active { transform: scale(0.98); }
@media (hover: hover) {
    .fr-book-btn:hover { border-color: var(--text-sub); background: var(--surface-strong, #1c1c1c); }
}
.fr-book-name {
    display: block;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--text-main);
}
.fr-book-sub {
    display: block;
    font-size: 0.74rem;
    color: var(--text-sub);
    margin-top: 3px;
}

@media (prefers-reduced-motion: reduce) {
    #fr-send-overlay.show .fr-send-box { animation: none; }
}

/* =========================================================
   側邊欄：讓手機使用者看得出這些是可以點的
   ---------------------------------------------------------
   原本只有 @media (hover: hover) 的 hover 樣式，手機完全看不到，
   整排字看起來就只是文字不是按鈕。這裡不加外框（15 個框太吵），
   改用手機使用者本來就認得的「清單列」語彙：細分隔線 + 右側箭頭 +
   點擊當下的回饋。
   ========================================================= */

.sidebar-menu .sidebar-item {
    position: relative;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

/* 每一項右邊給一個箭頭，這是最省版面的可點暗示 */
.sidebar-menu .sidebar-item::after {
    content: "›";
    position: absolute;
    right: 20px;
    top: 50%;
    transform: translateY(-52%);
    font-size: 1.15rem;
    line-height: 1;
    color: var(--text-sub);
    opacity: 0.42;
    pointer-events: none;
}

/* 手機沒有 hover，點下去的當下一定要有反應，否則會覺得按了沒事 */
.sidebar-menu .sidebar-item:active {
    background: rgba(255, 255, 255, 0.09) !important;
    border-left: 3px solid var(--text-main) !important;
    color: #fff !important;
}

/* =========================================================
   新增單字簿／片語簿：彈窗
   ========================================================= */
#add-book-overlay {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: rgba(0, 0, 0, 0.78);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 0.2s;
}
#add-book-overlay.show { opacity: 1; }
#add-book-overlay.hidden { display: none !important; }

@keyframes addBookIn {
    0%   { transform: translateY(26px); opacity: 0; }
    100% { transform: translateY(0);    opacity: 1; }
}
.add-book-box {
    width: 100%;
    max-width: 560px;
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 20px 20px 0 0;
    backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
}
#add-book-overlay.show .add-book-box {
    animation: addBookIn 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* 桌機留一點邊距，不要整條貼底 */
@media (min-width: 700px) {
    #add-book-overlay { align-items: center; padding: 24px; }
    .add-book-box { border-radius: 20px; max-height: 82vh; }
}

.add-book-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 18px 20px 14px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.add-book-body {
    padding: 20px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
/* 搬進彈窗後，原本區塊最上面的 h3 就多餘了（標題已經在彈窗頂端） */
.add-book-body > div > h3:first-child { display: none; }
.add-book-body textarea { max-height: 34vh; }

@media (prefers-reduced-motion: reduce) {
    #add-book-overlay.show .add-book-box { animation: none; }
}

/* =========================================================
   新手引導
   ========================================================= */
@keyframes obBarIn {
    0%   { transform: translateY(100%); opacity: 0; }
    100% { transform: translateY(0);    opacity: 1; }
}

.ob-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 8500;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 18px calc(14px + env(safe-area-inset-bottom, 0px));
    background: var(--card-bg);
    border-top: 1px solid var(--border);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    animation: obBarIn 0.32s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.ob-bar.hidden { display: none !important; }

.ob-main {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 13px;
    min-width: 0;
}
.ob-step {
    flex-shrink: 0;
    font-size: 0.72rem;
    letter-spacing: 1px;
    color: var(--text-sub);
    font-variant-numeric: tabular-nums;
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 4px 10px;
}
.ob-text { min-width: 0; }
.ob-text > span {
    display: block;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--text-main);
    line-height: 1.4;
}
.ob-hint {
    font-size: 0.75rem !important;
    font-weight: 400 !important;
    color: var(--text-sub) !important;
    margin-top: 2px;
}
.ob-skip {
    flex-shrink: 0;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-sub);
    border-radius: 8px;
    padding: 7px 13px;
    font-size: 0.76rem;
    font-family: inherit;
    cursor: pointer;
}

/* 聚光燈：標出這一步該點哪裡 */
@keyframes obPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.32); }
    50%      { box-shadow: 0 0 0 7px rgba(255, 255, 255, 0); }
}
.ob-spotlight {
    position: relative;
    z-index: 2;
    border-color: var(--text-main) !important;
    animation: obPulse 1.9s ease-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .ob-bar { animation: none; }
    .ob-spotlight { animation: none; box-shadow: 0 0 0 2px var(--text-main); }
}

/* =========================================================
   載入狀態共用元件（見 loading.js）
   ========================================================= */

/* ── 骨架屏 ── */
@keyframes svShimmer {
    0%   { background-position: -420px 0; }
    100% { background-position:  420px 0; }
}

.sv-skel {
    background-color: rgba(255, 255, 255, 0.05);
    background-image: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0.00) 0%,
        rgba(255, 255, 255, 0.09) 45%,
        rgba(255, 255, 255, 0.00) 90%
    );
    background-repeat: no-repeat;
    background-size: 420px 100%;
    border-radius: 6px;
    animation: svShimmer 1.4s ease-in-out infinite;
    animation-delay: var(--sv-skel-delay, 0ms);
}

.sv-skel-wrap {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.sv-skel-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px 14px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--card-bg);
}
.sv-skel-avatar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    flex-shrink: 0;
}
.sv-skel-lines {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 7px;
    min-width: 0;
}
.sv-skel-pill {
    width: 62px;
    height: 27px;
    border-radius: 8px;
    flex-shrink: 0;
}

.sv-skel-card {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 18px 16px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--card-bg);
}

.sv-skel-line { height: 10px; }
.sv-skel-line.short { height: 8px; opacity: 0.7; }
.sv-skel-line.title { height: 14px; }
.sv-skel-line.w35 { width: 35%; }
.sv-skel-line.w45 { width: 45%; }
.sv-skel-line.w60 { width: 60%; }
.sv-skel-line.w70 { width: 70%; }
.sv-skel-line.w75 { width: 75%; }
.sv-skel-line.w85 { width: 85%; }
.sv-skel-line.w90 { width: 90%; }

/* ── 內容到位時依序淡入 ── */
@keyframes svReveal {
    from { opacity: 0; transform: translateY(7px); }
    to   { opacity: 1; transform: translateY(0); }
}
.sv-reveal > * {
    animation: svReveal 0.34s cubic-bezier(0.22, 1, 0.36, 1) both;
    animation-delay: var(--sv-reveal-delay, 0ms);
}

/* ── 轉圈 ── */
@keyframes svSpin { to { transform: rotate(360deg); } }

.sv-spin {
    display: inline-block;
    width: 13px;
    height: 13px;
    margin-right: 7px;
    vertical-align: -2px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    opacity: 0.75;
    animation: svSpin 0.7s linear infinite;
}
.sv-spin-lg {
    width: 26px;
    height: 26px;
    border-width: 2.5px;
    margin: 0 0 14px 0;
    vertical-align: 0;
}

.sv-btn-loading {
    opacity: 0.75;
    cursor: default;
    pointer-events: none;
}

/* ── 置中轉圈 ── */
.sv-load-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 52px 20px;
    color: var(--text-sub);
}
.sv-load-text {
    font-size: 0.84rem;
    letter-spacing: 1px;
}

@media (prefers-reduced-motion: reduce) {
    .sv-skel { animation: none; }
    .sv-reveal > * { animation: none; }
    .sv-spin { animation-duration: 1.6s; }
}

/* =========================================================
   PRO 標籤 + 徽章展示櫃
   ========================================================= */
.pro-chip {
    display: inline-flex;
    align-items: center;
    background: linear-gradient(135deg, #f0c040, #e8a020);
    color: #000;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    padding: 3px 8px;
    border-radius: 9px;
    line-height: 1.2;
    white-space: nowrap;
    flex-shrink: 0;
}
/* Ultra 的徽章換成紫色。用 class 而不是改 inline style，
   是為了讓公開主頁、側邊欄、頁首三個地方共用同一份定義。 */
.pro-chip.pro-chip-ultra {
    background: linear-gradient(135deg, #b388ff, #7c4dff);
    color: #fff;
}
/* Ultra 會員的名字：一道紫金色的光慢慢流過（會員權益） */
#public-profile-name.ultra-name {
    background: linear-gradient(100deg, #e9dcff 0%, #b388ff 30%, #ffe6a8 50%, #b388ff 70%, #e9dcff 100%);
    background-size: 220% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    filter: drop-shadow(0 0 10px rgba(179, 136, 255, 0.45));
    animation: ultra-name-flow 4s linear infinite;
}
@keyframes ultra-name-flow { from { background-position: 0% 0; } to { background-position: 220% 0; } }
@media (prefers-reduced-motion: reduce) { #public-profile-name.ultra-name { animation: none; } }
/* 公開主頁的字級比頁首大一點，標籤跟著放大才不會顯得零碎 */
#public-pro-badge {
    font-size: 0.68rem;
    padding: 4px 10px;
    border-radius: 10px;
}

/* ── 徽章管理彈窗 ── */
#badge-manager-overlay {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: rgba(0, 0, 0, 0.78);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 0.2s;
}
#badge-manager-overlay.show { opacity: 1; }
#badge-manager-overlay.hidden { display: none !important; }

.badge-manager-box {
    width: 100%;
    max-width: 460px;
    max-height: 86vh;
    display: flex;
    flex-direction: column;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 20px 20px 0 0;
    backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
}
#badge-manager-overlay.show .badge-manager-box {
    animation: addBookIn 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@media (min-width: 700px) {
    #badge-manager-overlay { align-items: center; padding: 24px; }
    .badge-manager-box { border-radius: 20px; max-height: 80vh; }
}

.badge-pick-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
    gap: 10px;
}
.badge-pick {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    padding: 13px 6px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 12px;
    font-family: inherit;
    cursor: pointer;
    opacity: 0.42;
    transition: opacity 0.2s, border-color 0.2s, background 0.2s, transform 0.12s;
}
.badge-pick:active { transform: scale(0.96); }
.badge-pick.picked {
    opacity: 1;
    border-color: #f0c040;
    background: rgba(240, 192, 64, 0.07);
}
.badge-pick-label {
    font-size: 0.7rem;
    color: var(--text-sub);
    letter-spacing: 0.5px;
}
.badge-pick.picked .badge-pick-label { color: var(--text-main); }

@media (prefers-reduced-motion: reduce) {
    #badge-manager-overlay.show .badge-manager-box { animation: none; }
}

/* =========================================================
   液態玻璃卡片與外框按鈕的主題變數
   預設（曜黑）維持原本的數值，視覺完全不變；
   漸層主題改用該主題自己的卡片色，陰影也大幅調淡。
   ========================================================= */
:root {
    --glass-card-bg:           rgba(20, 20, 20, 0.45);
    --glass-card-border:       rgba(255, 255, 255, 0.08);
    --glass-card-shadow:       0 8px 32px 0 rgba(0, 0, 0, 0.4);
    --glass-card-shadow-hover: 0 12px 40px 0 rgba(0, 0, 0, 0.6), 0 0 15px rgba(255, 255, 255, 0.05);
    --glass-card-border-hover: rgba(255, 255, 255, 0.2);
    --outline-hover-bg:        rgba(255, 255, 255, 0.06);
}

html[data-theme]:not([data-theme="dark"]) {
    --glass-card-bg:           var(--card-bg);
    --glass-card-border:       var(--border);
    /* 黑影在有顏色的漸層上會很明顯，調淡並收窄 */
    --glass-card-shadow:       0 2px 12px rgba(0, 0, 0, 0.14);
    --glass-card-shadow-hover: 0 6px 20px rgba(0, 0, 0, 0.2);
    --glass-card-border-hover: var(--text-sub);
}

/* =========================================================
   玩家市場：購買前預覽
   ========================================================= */
#market-preview-overlay {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: rgba(0, 0, 0, 0.78);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 0.2s;
}
#market-preview-overlay.show { opacity: 1; }
#market-preview-overlay.hidden { display: none !important; }

.market-preview-box {
    width: 100%;
    max-width: 420px;
    max-height: 82vh;
    display: flex;
    flex-direction: column;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 20px 20px 0 0;
    backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
}
#market-preview-overlay.show .market-preview-box {
    animation: addBookIn 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@media (min-width: 700px) {
    #market-preview-overlay { align-items: center; padding: 24px; }
    .market-preview-box { border-radius: 20px; max-height: 78vh; }
}

.mp-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.mp-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.02);
}
.mp-en {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-main);
    letter-spacing: 0.3px;
    flex-shrink: 0;
}
.mp-zh {
    font-size: 0.82rem;
    color: var(--text-sub);
    text-align: right;
    line-height: 1.5;
    min-width: 0;
}

@media (prefers-reduced-motion: reduce) {
    #market-preview-overlay.show .market-preview-box { animation: none; }
}

/* =========================================================
   頂部導覽列：小螢幕不能被擠爆
   ---------------------------------------------------------
   原本左右兩側都用 inline style 排版，沒有 min-width:0，
   flex 無法把左側縮小，右側的按鈕與頭像就被推出畫面，
   412px 以下開始溢出，320px 時整頁會多出 76px 的橫向捲動。
   ========================================================= */
#main-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.hdr-left {
    display: flex;
    align-items: center;
    gap: 12px;
    /* 這兩行是關鍵：允許左側被壓縮，右側才不會被擠出去 */
    min-width: 0;
    flex: 1 1 auto;
}

.hdr-menu {
    font-size: 1.5rem;
    padding: 0 4px;
    color: var(--text-main);
    flex-shrink: 0;
}

.hdr-brand {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
}

.hdr-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    max-width: 100%;
}

.hdr-title {
    margin: 0;
    cursor: pointer;
    letter-spacing: 1px;
    /* 依螢幕寬度縮放，真的放不下再切字 */
    font-size: clamp(0.95rem, 5vw, 1.4rem);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.hdr-presence {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 5px;
    min-width: 0;
}
.hdr-presence-text {
    font-size: 0.75rem;
    color: var(--text-sub);
    letter-spacing: 0.5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* 右側是圖示與頭像，尺寸固定，一律不准被壓縮 */
.hdr-right {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

@media (max-width: 400px) {
    #main-header { gap: 8px; }
    .hdr-left { gap: 9px; }
    .hdr-right { gap: 7px; }
    .hdr-menu { font-size: 1.35rem; padding: 0 2px; }
    .nav-icon-btn { width: 34px; height: 34px; }
    .pro-chip { font-size: 0.55rem; padding: 2px 6px; }
    .hdr-presence-text { font-size: 0.7rem; }
}

@media (max-width: 345px) {
    :root { --container-pad: 14px; }
    /* 真的很窄的機型（320px 級）：把周邊全部再收一點，
       讓「SilenVocab」這個品牌名不會被切成「Silen…」。
       量過只差 5.6px，容器左右內距從 20px 收到 14px 就夠了，
       順便讓其他畫面在小螢幕上也多一點可用寬度。 */
    #main-header { gap: 6px; }
    .hdr-left { gap: 7px; }
    .hdr-right { gap: 5px; }
    .hdr-menu { font-size: 1.25rem; padding: 0; }
    .nav-icon-btn { width: 31px; height: 31px; }
    .nav-icon-btn svg { width: 17px; height: 17px; }
    .pro-chip { font-size: 0.5rem; padding: 2px 5px; border-radius: 7px; }
    .hdr-right .avatar-wrapper,
    .hdr-right #auth-container img { width: 32px !important; height: 32px !important; }
}

/* =========================================================
   自製英文鍵盤（keyboard.js）
   配置照抄 QWERTY（肌肉記憶不能動），但外觀走自己的主題變數，
   不要做成 Android 原生灰 —— 那會跟整個 App 的磨砂玻璃格格不入。
   ========================================================= */
.kb {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    box-sizing: border-box;
    max-width: 100vw;
    z-index: 9600;
    /* 下緣不要貼死。Gboard 底下也留了一條 —— 拇指不用伸到螢幕最底，
       而且手勢導覽列（那條橫線）不會跟最下排按鍵打架。 */
    padding: 8px 3px 0;
    /* Opaque theme tint keeps animated backgrounds from repainting through
       a full-screen backdrop blur on every key press. */
    background: linear-gradient(var(--surface-strong), var(--surface-strong)), var(--bg-color);
    border-top: 1px solid var(--border);
    /* 位置和縮放跟著「可視視窗」走，不是版面視窗。
       玩家雙指放大之後，position: fixed 是貼著版面視窗排的，
       鍵盤右半邊會整個跑到螢幕外 —— 實測放大 1.3 倍就少 90px，
       而 PWA 沒有網址列，玩家看不出自己縮放了，也不知道怎麼還原。
       三個變數由 keyboard.js 的 fitViewport() 填。 */
    transform-origin: left bottom;
    transform: translate(var(--kb-x, 0px), var(--kb-y, 0px))
               translateY(100%) scale(var(--kb-s, 1));
    transition: transform 0.16s cubic-bezier(0.22, 1, 0.36, 1);
    /* 使用者按鍵時不要選到文字、也不要跳出系統的長按選單 */
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    touch-action: manipulation;
}
.kb.kb-show {
    transform: translate(var(--kb-x, 0px), var(--kb-y, 0px)) scale(var(--kb-s, 1));
}

/* 20 格網格：字母 2 格、功能鍵 3 格、空白 10 格、間隔空位 1 格。
   用 grid 不用 flex —— flex 平分沒辦法讓不同鍵數的排對齊，實測會差好幾 px。 */
.kb-row {
    display: grid;
    grid-template-columns: repeat(20, 1fr);
    gap: 3px;
    margin-bottom: 4px;
}
.kb-row:last-child { margin-bottom: 0; }

.kb-key {
    grid-column: span 2;
    min-width: 0;
    height: 50px;
    border: none;
    border-radius: 7px;
    background: var(--card-bg);
    color: var(--text-main);
    font-family: inherit;
    font-size: 1.15rem;
    font-weight: 500;
    line-height: 1;
    cursor: pointer;
    touch-action: none;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.35);
    transition: background 0.08s, transform 0.08s;
}
/* 按下去要有回饋，不然在手機上完全不知道有沒有打到 */
.kb-key-hit,
.kb-key:active {
    background: var(--surface-strong-border, #3a3a3a);
    transform: translateY(1px);
}

/* 功能鍵（shift / 刪除 / 符號 / 送出）用比較實的底色區隔 */
.kb-key-fn {
    background: var(--surface-strong-border, #333);
    grid-column: span 3;
    font-size: 0.8rem;
    letter-spacing: 0.5px;
}
.kb-key-wide { grid-column: span 3; }
.kb-key-space { grid-column: span 10; }
.kb-key svg { width: 22px; height: 22px; }

/* shift 的三種狀態要看得出差別：一次性大寫 vs 鎖定大寫。
   原本鎖定大寫與送出鍵是實心純白，打字時整片深色鍵盤裡跳出一塊白，
   眼睛一直被拉過去。改成磨砂高亮：亮度夠讓人找得到，但不刺眼。 */
.kb-key-shift.kb-shift-on { color: var(--text-main); background: var(--surface-strong); }
.kb-key-shift.kb-shift-lock,
.kb-key-enter {
    color: var(--text-main);
    background: rgba(255, 255, 255, 0.24);
    border: 1px solid rgba(255, 255, 255, 0.38);
    box-shadow:
        0 0 12px rgba(255, 255, 255, 0.12),
        inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

/* 鍵盤是 fixed，會蓋住畫面下緣。撐開底部留白，
   免得「送出」按鈕剛好被壓在鍵盤底下點不到。 */
body.kb-open .container { padding-bottom: calc(var(--kb-height, 250px) + 24px); }
/* 有浮起來的「送出」時，底下再多留它的高度，輸入框才捲得到它上面（keyboard.js reveal）。 */
body.kb-open .container:has(.kb-active-area) { padding-bottom: calc(var(--kb-height, 250px) + 96px); }
/* 打字時題目字縮小一點：中文題目兩行時，題目和輸入框才都放得進鍵盤上方。 */
.kb-active-area .question-text { font-size: 1.35rem; line-height: 1.45; margin-bottom: 18px; transition: font-size .2s ease, margin .2s ease; }
/* keyboard.js moves this button to <body> while typing. Its position is then
   independent of the mastery view's entrance animation and stacking context. */
body.kb-open #mastery-btn-typing.kb-submit-floating {
    position: fixed;
    z-index: 9601;
    left: var(--kb-visual-center, 50%);
    bottom: calc(var(--kb-height, 250px) + var(--kb-visual-bottom, 0px) + 10px);
    transform: translateX(-50%);
    width: min(calc(var(--kb-visual-width, 100vw) - 32px), 560px);
    min-height: 48px;
    margin: 0;
}
body.kb-open #mastery-btn-typing.kb-submit-floating:active {
    transform: translateX(-50%) scale(0.96) translateY(2px) !important;
}

@media (max-width: 360px) {
    .kb-key { height: 48px; font-size: 1.05rem; }
}
@media (prefers-reduced-motion: reduce) {
    .kb { transition: none; }
    .kb-key { transition: none; }
}
/* 第二排兩端的半格空位，讓字母鍵寬度跟第一排一致 */
.kb-spacer { grid-column: span 1; }

/* 鍵盤底部的留白條，右邊放收起鍵（對齊系統鍵盤的習慣位置） */
.kb-bar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    height: 42px;
    padding: 0 10px calc(env(safe-area-inset-bottom, 0px));
    box-sizing: content-box;
}
.kb-down {
    width: 46px;
    height: 34px;
    border: none;
    background: transparent;
    color: var(--text-sub);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    touch-action: none;
    border-radius: 8px;
}
.kb-down:active { background: var(--card-bg); color: var(--text-main); }
.kb-down svg { width: 24px; height: 24px; }

/* =========================================================
   設定面板與彈窗的高度處理
   ---------------------------------------------------------
   原本兩個都沒有高度上限也沒有 overflow：內容一長就整塊撐出螢幕，
   底部的「完成設定」「確認」按鈕被推到看不見的地方，而且捲不動，
   等於卡死在那裡。
   單位用 dvh 不用 vh —— 手機網址列縮起來時 vh 不會跟著變，
   會多算一段高度，按鈕還是會露在畫面外。
   ========================================================= */

/* 系統彈窗（alert/confirm/prompt）：訊息可捲，按鈕永遠留在下面 */
#silen-modal-overlay .silen-modal-box {
    display: flex;
    flex-direction: column;
    max-height: 86dvh;
}
#silen-modal-overlay .silen-modal-msg {
    overflow-y: auto;
    min-height: 0;                 /* flex 子元素要這個才縮得下去 */
    overscroll-behavior: contain;  /* 捲到底不要帶動後面的頁面 */
}
#silen-modal-overlay .silen-modal-actions { flex: 0 0 auto; }

/* 彈窗要蓋在設定面板上面。
   兩個 overlay 原本都是 z-index:9999，同層時由 DOM 順序決定，
   而設定面板寫在後面 —— 結果從設定裡叫出來的說明會被設定蓋住，
   得先關掉設定才看得到。 */
#silen-modal-overlay { z-index: 10001; }

/* 設定面板：標題與底部按鈕固定，中間捲動 */
.settings-box {
    display: flex;
    flex-direction: column;
    max-height: 86dvh;
    overflow: hidden;              /* 捲動交給 .settings-scroll，不要有兩層捲軸 */
    padding: 20px 0 16px;          /* 左右內距移到子元素，捲軸才會貼著邊 */
}
.settings-title {
    flex: 0 0 auto;
    margin: 0 20px 14px;
    color: var(--text-main);
}
.settings-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 0 20px;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}
.settings-footer {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 20px 0;
    border-top: 1px solid var(--border);
}

/* 分組。原本十來個項目平鋪成一長串，分了組才找得到東西 */
.settings-group { margin-bottom: 24px; }
.settings-group-title {
    font-size: 0.72rem;
    letter-spacing: 2px;
    color: var(--text-sub);
    margin-bottom: 12px;
    padding-bottom: 7px;
    border-bottom: 1px solid var(--border);
}
.settings-sub {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-bottom: 6px;
}
.settings-note {
    font-size: 0.78rem;
    color: var(--text-sub);
    line-height: 1.5;
    min-height: 0;
}
.settings-note:empty { display: none; }

.settings-danger-zone { margin-top: 30px; padding-top: 12px; border-top: 1px solid var(--border); }
.settings-delete-entry {
    width: 100%; display: flex; align-items: center; justify-content: space-between;
    padding: 13px 15px; border: 1px solid rgba(230, 101, 101, .5);
    border-radius: 12px; background: rgba(230, 101, 101, .07);
    color: #ffabab; font: inherit; font-size: .9rem; text-align: left; cursor: pointer;
}
.settings-delete-entry:disabled { opacity: .55; cursor: not-allowed; }
.settings-danger-zone .settings-note { margin: 8px 2px 0; }
#account-delete-overlay {
    position: fixed; inset: 0; z-index: 10020; display: flex;
    align-items: center; justify-content: center; padding: 16px;
    background: rgba(0, 0, 0, .82); backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
#account-delete-overlay .account-delete-box {
    box-sizing: border-box; width: min(100%, 430px); max-height: min(85vh, 700px);
    overflow-y: auto; padding: 24px; text-align: left;
    transform: none; border: 1px solid rgba(230, 101, 101, .45);
}
.account-delete-box h3 { margin: 0 0 12px; color: #ffabab; font-size: 1.2rem; }
.account-delete-box p { margin: 0 0 12px; color: var(--text-sub); font-size: .88rem; line-height: 1.65; }
.account-delete-box strong { color: var(--text-main); overflow-wrap: anywhere; }
.account-delete-box label { display: block; margin: 14px 0 6px; color: var(--text-main); font-size: .85rem; }
.account-delete-box input {
    box-sizing: border-box; width: 100%; min-height: 44px; padding: 10px 12px;
    border: 1px solid var(--border); border-radius: 10px;
    background: var(--card-bg); color: var(--text-main); font: inherit;
}
.account-delete-box input:focus-visible { outline: 2px solid #ffabab; outline-offset: 2px; }
.account-delete-box .account-delete-actions { display: flex; gap: 10px; margin-top: 20px; }
.account-delete-box .account-delete-actions button { flex: 1; margin: 0; }
#account-delete-confirm { background: #a93636; color: white; }
#account-delete-confirm:disabled { opacity: .45; cursor: not-allowed; }
#account-delete-error { min-height: 1.5em; margin: 10px 0 0; color: #ffabab; }

/* =========================================================
   題目內生字收集（wordpicker.js）
   ========================================================= */
/* 可點的單字。平常幾乎看不出來（不要干擾閱讀），點到才亮起來 */
.wp-word {
    cursor: pointer;
    border-radius: 3px;
    padding: 0 1px;
    transition: background 0.15s, color 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.wp-word:active { background: rgba(255, 255, 255, 0.12); }
.wp-word.wp-picked {
    background: rgba(255, 152, 0, 0.22);
    color: #ffb74d;
    box-shadow: 0 1px 0 #ff9800;
}

/* 點下去浮出來的字卡：實心底、高對比，不會跟底下的選項疊在一起看不清楚 */
.wp-tip {
    position: fixed;
    z-index: 10002;
    width: max-content;
    min-width: 200px;
    max-width: min(86vw, 340px);
    padding: 12px 14px 10px;
    border-radius: 14px;
    background: #1c1a22;
    color: #f2eef8;
    border: 1px solid rgba(255, 183, 77, 0.45);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(0, 0, 0, 0.4);
    opacity: 0;
    transform: translateY(-4px) scale(.98);
    transition: opacity 0.15s, transform 0.15s;
    pointer-events: none;
}
.wp-tip.show { opacity: 1; transform: none; pointer-events: auto; }
.wp-tip-head { display: flex; align-items: center; gap: 10px; }
.wp-tip-en { font-weight: 800; color: #ffc46b; font-size: 1.15rem; letter-spacing: .3px; font-family: Georgia, 'Times New Roman', serif; }
.wp-tip-say { margin-left: auto; flex: 0 0 auto; border: 1px solid rgba(255,255,255,.22); background: rgba(255,255,255,.06); color: #f2eef8; border-radius: 999px; padding: 3px 10px; font: inherit; font-size: .74rem; cursor: pointer; }
.wp-tip-form { margin-top: 3px; font-size: .74rem; color: #b8b0c6; }
.wp-tip-body { margin-top: 8px; display: flex; flex-direction: column; gap: 5px; }
.wp-tip-sense { display: flex; align-items: baseline; gap: 7px; font-size: .95rem; line-height: 1.4; color: #f2eef8; }
.wp-tip-pos { flex: 0 0 auto; padding: 0 6px; border-radius: 6px; background: rgba(255, 183, 77, .16); color: #ffc46b; font-size: .72rem; font-weight: 700; font-style: italic; }
.wp-tip-zh { word-break: break-word; }
.wp-tip-loading, .wp-tip-missing { font-size: .86rem; color: #b8b0c6; line-height: 1.5; }
.wp-tip-loading::after { content: ''; display: inline-block; width: 10px; height: 10px; margin-left: 6px; border: 2px solid #ffc46b; border-right-color: transparent; border-radius: 50%; animation: wp-spin .7s linear infinite; vertical-align: -1px; }
@keyframes wp-spin { to { transform: rotate(360deg); } }
.wp-tip-tags { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 8px; }
.wp-tip-tag { padding: 1px 7px; border-radius: 999px; border: 1px solid rgba(127, 212, 255, .45); color: #9fdcff; font-size: .68rem; font-weight: 700; }
.wp-tip-foot { display: flex; align-items: center; gap: 8px; margin-top: 10px; padding-top: 8px; border-top: 1px solid rgba(255,255,255,.1); }
.wp-tip-status { font-size: .74rem; color: #b8b0c6; }
.wp-tip-status.on { color: #7fe0a8; }
.wp-tip-btn { margin-left: auto; border: 1px solid rgba(255,255,255,.22); background: transparent; color: #f2eef8; border-radius: 8px; padding: 3px 10px; font: inherit; font-size: .74rem; cursor: pointer; }

/* 右下角計數泡泡。避開自製鍵盤，鍵盤升起時往上讓 */
.wp-chip {
    position: fixed;
    right: 16px;
    bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    z-index: 9400;
    padding: 10px 16px;
    border: 1px solid #ff9800;
    border-radius: 20px;
    background: rgba(255, 152, 0, 0.16);
    color: #ffb74d;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.5px;
    cursor: pointer;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
body.kb-open .wp-chip { bottom: calc(var(--kb-height, 250px) + 16px); }

/* 結算視窗。結構跟設定面板一樣：標題與底部按鈕固定，中間可捲 */
.wp-overlay {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.2s ease;
}
.wp-overlay.show { opacity: 1; }
.wp-box {
    display: flex;
    flex-direction: column;
    width: 90%;
    max-width: 420px;
    max-height: 86dvh;
    overflow: hidden;
    padding: 20px 0 16px;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.8);
}
.wp-title { flex: 0 0 auto; margin: 0 20px 14px; color: var(--text-main); font-size: 1.05rem; letter-spacing: 1px; }
.wp-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 20px; overscroll-behavior: contain; }
.wp-footer {
    flex: 0 0 auto;
    display: flex;
    gap: 10px;
    padding: 14px 20px 0;
    border-top: 1px solid var(--border);
}
.wp-label { display: block; font-size: 0.75rem; color: var(--text-sub); letter-spacing: 1px; margin-bottom: 6px; }
.wp-input { width: 100%; margin-bottom: 14px; }
.wp-note { font-size: 0.78rem; color: var(--text-sub); line-height: 1.5; margin-bottom: 8px; }
.wp-note:empty { display: none; }
.wp-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
}
.wp-row-main { flex: 1; min-width: 0; }
.wp-row-top { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.wp-row-en { font-weight: 700; color: var(--text-main); font-size: 1rem; }
.wp-row-seen { font-size: .7rem; color: var(--text-sub); }
.wp-row-tag { font-size: .66rem; padding: 0 6px; border-radius: 999px; border: 1px solid rgba(127, 212, 255, .4); color: #9fdcff; }
.wp-row-zh { font-size: 0.84rem; color: var(--text-main); opacity: .85; margin-top: 3px; word-break: break-word; line-height: 1.45; }
.wp-row-wait { color: var(--text-sub); opacity: 1; }
.wp-row-pos { display: inline-block; margin-right: 6px; padding: 0 5px; border-radius: 5px; background: rgba(255, 183, 77, .14); color: #ffc46b; font-size: .68rem; font-weight: 700; font-style: italic; }
.wp-say { margin-right: 6px; }
.wp-del {
    flex: 0 0 auto;
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text-sub);
    font-family: inherit;
    font-size: 0.75rem;
    padding: 5px 10px;
    border-radius: 8px;
    cursor: pointer;
}
.wp-del:active { background: var(--surface-strong); color: var(--text-main); }
.wp-empty { color: var(--text-sub); font-size: 0.85rem; padding: 20px 0; text-align: center; }

/* =========================================================
   學測模擬試題（gsat.js）
   ========================================================= */
.gs-part { font-size: 0.72rem; letter-spacing: 2px; color: var(--text-sub); margin: 16px 0 8px; }
.gs-part:first-child { margin-top: 0; }
.gs-pick {
    display: flex; align-items: center; gap: 12px;
    padding: 11px 12px; margin-bottom: 8px;
    border: 1px solid var(--border); border-radius: 10px;
    background: var(--card-bg); cursor: pointer;
}
.gs-pick-name { flex: 1; color: var(--text-main); font-size: 0.92rem; }
.gs-pick-pt { font-size: 0.78rem; color: var(--text-sub); }
.gs-total {
    margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border);
    text-align: center; color: var(--text-main); font-size: 0.9rem; letter-spacing: 1px;
}
.gs-total.gs-total-bad { color: #e57373; }

/* 今日還能出幾個大題 */
.gs-quota {
    font-size: 0.8rem; color: var(--text-sub); letter-spacing: 0.5px;
    margin-bottom: 12px;
}
.gs-quota:empty { display: none; }
.gs-quota.gs-quota-out { color: #e57373; }

/* 作答時的固定頂欄：計時與交卷永遠看得到 */
.gs-bar-top {
    position: sticky; top: 0; z-index: 60;
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 10px 0; margin-bottom: 10px;
    background: var(--bg-color);
    border-bottom: 1px solid var(--border);
}
html:not([data-theme="dark"]) .gs-bar-top { background: transparent; backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); }
.gs-timer {
    font-family: 'Courier New', Courier, monospace;
    font-size: 1.3rem; font-weight: 700; letter-spacing: 1px; color: var(--text-main);
}
.gs-timer.gs-timer-warn { color: #ff5252; }

.gs-part-title { font-size: 0.95rem; letter-spacing: 2px; color: var(--text-sub); margin: 26px 0 10px; }
.gs-sec { margin-bottom: 22px; }
.gs-sec-head {
    display: flex; justify-content: space-between; align-items: baseline;
    font-size: 0.95rem; font-weight: 600; color: var(--text-main);
    letter-spacing: 1px; padding-bottom: 8px; margin-bottom: 12px;
    border-bottom: 1px solid var(--border);
}
.gs-sec-head span { font-size: 0.78rem; color: var(--text-sub); font-weight: 400; }
.gs-passage {
    background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px;
    padding: 16px; margin-bottom: 14px;
    font-size: 0.95rem; line-height: 1.9; color: var(--text-main);
    white-space: pre-wrap;
}
.gs-bank {
    display: flex; flex-wrap: wrap; gap: 8px;
    padding: 12px; margin-bottom: 14px;
    border: 1px dashed var(--border); border-radius: 10px;
}
.gs-bank span { font-size: 0.85rem; color: var(--text-main); }
.gs-bank-long { flex-direction: column; gap: 10px; }
.gs-bank-long span { line-height: 1.6; }

.gs-q { margin-bottom: 18px; }
.gs-q-text { font-size: 0.95rem; line-height: 1.7; color: var(--text-main); margin-bottom: 8px; }
.gs-pt { font-size: 0.75rem; color: var(--text-sub); }
.gs-task { font-size: 0.85rem; color: var(--text-sub); line-height: 1.6; margin-bottom: 6px; }

.gs-opts { display: flex; flex-direction: column; gap: 7px; }
.gs-opt {
    display: flex; align-items: flex-start; gap: 10px; width: 100%;
    padding: 11px 13px; border: 1px solid var(--border); border-radius: 10px;
    background: var(--card-bg); color: var(--text-main);
    font-family: inherit; font-size: 0.9rem; line-height: 1.5; text-align: left; cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}
.gs-opt-l {
    flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
    border: 1px solid var(--border); display: flex; align-items: center; justify-content: center;
    font-size: 0.75rem; color: var(--text-sub);
}
.gs-opt.gs-opt-on { border-color: #fff; background: rgba(255, 255, 255, 0.1); }
.gs-opt.gs-opt-on .gs-opt-l { background: #fff; color: #000; border-color: #fff; }

.gs-short { width: 100%; }
.gs-textarea { width: 100%; resize: vertical; line-height: 1.7; }
.gs-wc { font-size: 0.78rem; color: var(--text-sub); text-align: right; margin-top: 6px; }

/* 匯出考卷 */
.gs-export {
    width: 100%; margin-top: 24px;
    background: transparent; color: var(--text-main);
    border: 1px solid var(--border);
}
.gs-export:disabled { opacity: 0.55; }

/* 成績單 */
.gs-score-card { text-align: center; }
.gs-score { font-size: 3rem; font-weight: 700; color: var(--text-main); line-height: 1.1; }
.gs-score span { font-size: 1.1rem; color: var(--text-sub); font-weight: 400; margin-left: 6px; }
.gs-score-pct { font-size: 0.85rem; color: var(--text-sub); margin-top: 6px; letter-spacing: 1px; }
.gs-h4 { margin: 0 0 14px 0; font-size: 1rem; letter-spacing: 1px; color: var(--text-main); }
.gs-advice { font-size: 0.9rem; line-height: 1.8; color: var(--text-main); white-space: pre-wrap; }

.gs-bar-row { margin-bottom: 12px; }
.gs-bar-label { display: flex; justify-content: space-between; font-size: 0.85rem; color: var(--text-main); margin-bottom: 5px; }
.gs-bar-label span { color: var(--text-sub); }
.gs-bar { height: 7px; border-radius: 4px; background: var(--surface-strong); overflow: hidden; }
.gs-bar-fill { height: 100%; background: #4caf50; border-radius: 4px; }

.gs-rubric { display: flex; flex-direction: column; gap: 14px; }
.gs-rb-h { display: flex; justify-content: space-between; font-size: 0.88rem; color: var(--text-main); margin-bottom: 5px; }
.gs-rb-h span { color: var(--text-sub); }
.gs-rb-c { font-size: 0.82rem; color: var(--text-sub); line-height: 1.6; margin-top: 6px; }
.gs-deduct { font-size: 0.82rem; color: #ff9800; margin-top: 12px; }
.gs-wc-note { font-size: 0.78rem; color: var(--text-sub); margin-top: 8px; }
.gs-fixes { margin-top: 16px; }
.gs-fixes-t { font-size: 0.85rem; color: var(--text-main); margin-bottom: 10px; letter-spacing: 1px; }
.gs-fix { border-left: 2px solid var(--border); padding-left: 12px; margin-bottom: 12px; }
.gs-fix-before { font-size: 0.85rem; color: var(--text-sub); text-decoration: line-through; line-height: 1.6; }
.gs-fix-after { font-size: 0.88rem; color: #4caf50; line-height: 1.6; margin-top: 3px; }
.gs-fix-why { font-size: 0.8rem; color: var(--text-sub); line-height: 1.6; margin-top: 4px; }

.gs-tr { padding: 12px 0; border-bottom: 1px solid var(--border); }
.gs-tr:last-child { border-bottom: none; }
.gs-tr-zh { font-size: 0.9rem; color: var(--text-main); margin-bottom: 6px; }
.gs-tr-user { font-size: 0.85rem; color: var(--text-sub); line-height: 1.6; }
.gs-tr-fix { font-size: 0.85rem; color: #4caf50; line-height: 1.6; margin-top: 4px; }
.gs-tr-err { font-size: 0.8rem; color: #ff9800; line-height: 1.6; margin-top: 4px; }

.gs-review-sec { font-size: 0.8rem; letter-spacing: 1.5px; color: var(--text-sub); margin: 16px 0 8px; }
.gs-review { padding: 10px 12px; border-radius: 8px; margin-bottom: 8px; border-left: 3px solid var(--border); }
.gs-review-good { border-left-color: #4caf50; background: rgba(76, 175, 80, 0.05); }
.gs-review-bad { border-left-color: #ff5252; background: rgba(255, 82, 82, 0.06); }
.gs-review-h { font-size: 0.85rem; color: var(--text-main); margin-bottom: 4px; }
.gs-review-b { font-size: 0.82rem; color: var(--text-sub); line-height: 1.6; }
.gs-review-x { font-size: 0.8rem; color: var(--text-sub); line-height: 1.7; margin-top: 5px; }

/* =========================================================
   單字知識王（quizking.js）
   配對 → 難度滾輪 → 搶答 → 結算
   ========================================================= */

/* ---- 說明頁 ---- */
.qk-intro { padding: 4px 0 24px; }
.qk-intro-title { font-size: 1.15rem; font-weight: 600; color: var(--text-main); letter-spacing: 1px; margin-bottom: 8px; }
.qk-intro-sub { font-size: 0.85rem; color: var(--text-sub); line-height: 1.7; margin-bottom: 20px; }
.qk-rule-list { border: 1px solid var(--border); border-radius: 14px; overflow: hidden; }
.qk-rule {
    display: flex; gap: 12px; align-items: flex-start;
    padding: 12px 14px; font-size: 0.84rem; color: var(--text-main); line-height: 1.6;
    border-bottom: 1px solid var(--border); background: var(--card-bg);
}
.qk-rule:last-child { border-bottom: none; }
.qk-rule-k { flex: 0 0 44px; color: var(--text-sub); font-size: 0.8rem; }
.qk-remain { text-align: center; font-size: 0.78rem; color: var(--text-sub); margin-top: 14px; }

/* ---- 置中的過場畫面（配對中／配對成功／滾輪）---- */
.qk-center {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-height: 62vh; gap: 20px; text-align: center; padding: 10px 0;
}

/* 找人中的雷達圈 */
.qk-radar { position: relative; width: 108px; height: 108px; }
.qk-radar span {
    position: absolute; inset: 0; border-radius: 50%;
    border: 1px solid var(--text-sub); opacity: 0;
    animation: qk-ping 2.1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}
.qk-radar span:nth-child(2) { animation-delay: 0.7s; }
.qk-radar span:nth-child(3) { animation-delay: 1.4s; }
@keyframes qk-ping {
    0%   { transform: scale(0.35); opacity: 0.75; }
    100% { transform: scale(1);    opacity: 0; }
}
.qk-matching-text { font-size: 1rem; color: var(--text-main); letter-spacing: 1px; min-height: 1.4em; }
.qk-matching-dots { display: inline-block; width: 1.6em; text-align: left; }
.qk-matching-hint { font-size: 0.8rem; color: var(--text-sub); line-height: 1.6; }

/* ---- 配對成功 ---- */
/* 對齊用 flex-start：對手多一行「電腦對手」，用 center 會讓兩顆頭像一高一低 */
.qk-vs { display: flex; align-items: flex-start; justify-content: center; gap: 18px; width: 100%; }
.qk-vs-side { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 8px; animation: qk-in 0.45s ease both; }
.qk-vs-side:last-child { animation-delay: 0.15s; }
@keyframes qk-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.qk-vs-name { font-size: 0.88rem; color: var(--text-main); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qk-vs-tag { font-size: 0.72rem; color: var(--text-sub); }
/* 頭像 72px，往下推到它的垂直中心 */
.qk-vs-mark { font-size: 1.1rem; font-weight: 600; color: var(--text-sub); letter-spacing: 2px; flex: 0 0 auto; margin-top: 26px; }

/* ---- 難度滾輪 ---- */
.qk-wheel-box {
    width: 100%; max-width: 320px; border: 1px solid var(--border); border-radius: 16px;
    background: var(--card-bg); padding: 0; overflow: hidden; position: relative;
    transition: border-color 0.3s;
}
.qk-wheel-box.qk-wheel-locked { border-color: var(--accent); }
.qk-wheel-window { height: 56px; overflow: hidden; position: relative; }
.qk-wheel-strip { will-change: transform; }
.qk-wheel-item {
    display: flex; align-items: center; justify-content: center;
    font-size: 0.95rem; color: var(--text-main); letter-spacing: 1px;
}
.qk-wheel-result { font-size: 1.05rem; color: var(--accent); letter-spacing: 1px; min-height: 1.5em; }

/* 競技場圖示（原本是 ⚔️ emoji，各平台長得都不一樣） */
.arena-icon { display: flex; justify-content: center; margin-bottom: 14px; color: var(--text-main); }
.arena-icon svg { width: 52px; height: 52px; display: block; }

/* ---- 遊戲中：左右玩家 + 中央倒數環 ---- */
.qk-level-tag { font-size: 0.78rem; color: var(--text-sub); }

.qk-arena-top {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 8px; padding: 6px 0 2px;
}
.qk-player {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; gap: 5px;
}
.qk-ava-frame {
    position: relative; width: 56px; height: 56px; flex: 0 0 auto;
    border-radius: 50%; transition: box-shadow 0.25s;
}
/* 只鎖頭像那一格的尺寸。這裡以前寫成 .qk-ava-frame > div，
   把旁邊的「已作答」標籤也一起撐成 56px 的白塊，整個頭像被蓋掉。 */
#qk-ava-me, #qk-ava-foe,
#qk-ava-me > img, #qk-ava-foe > img,
#qk-ava-me > div, #qk-ava-foe > div {
    width: 56px !important; height: 56px !important;
}
.qk-player.qk-answered .qk-ava-frame { box-shadow: 0 0 0 2px var(--accent); }
.qk-ans-check {
    position: absolute; left: 50%; bottom: -7px;
    transform: translateX(-50%) scale(0.75);
    font-size: 0.62rem; line-height: 1; padding: 3px 7px; border-radius: 9px;
    background: var(--accent); color: #000; white-space: nowrap;
    opacity: 0; transition: opacity 0.18s, transform 0.18s; pointer-events: none;
}
.qk-ans-check.on { opacity: 1; transform: translateX(-50%) scale(1); }
.qk-p-name {
    font-size: 0.78rem; color: var(--text-sub); max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 4px;
}
.qk-p-score {
    font-size: 1.25rem; font-weight: 600; color: var(--text-main);
    font-variant-numeric: tabular-nums; line-height: 1.1;
}

.qk-ring-wrap { position: relative; flex: 0 0 auto; width: 78px; height: 78px; margin-top: 2px; }
.qk-ring { width: 100%; height: 100%; display: block; transform: rotate(-90deg); }
.qk-ring-bg { fill: none; stroke: var(--border); stroke-width: 6; }
.qk-ring-fg {
    fill: none; stroke: var(--accent); stroke-width: 6; stroke-linecap: round;
    stroke-dasharray: 276.46; stroke-dashoffset: 0;
    transition: stroke-dashoffset 0.1s linear, stroke 0.3s;
}
.qk-ring-fg.qk-ring-hot { stroke: #ff5252; }
.qk-ring-num {
    position: absolute; left: 0; top: 0; right: 0; bottom: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.4rem; font-weight: 600; color: var(--text-main);
    font-variant-numeric: tabular-nums;
}

.qk-arena-mid { display: flex; align-items: stretch; gap: 10px; margin-top: 18px; }
.qk-sidebar { flex: 0 0 6px; }
.qk-sidebar-track {
    width: 6px; height: 100%; min-height: 220px; border-radius: 3px;
    background: var(--border); overflow: hidden; position: relative;
}
.qk-sidebar-fill {
    position: absolute; left: 0; bottom: 0; width: 100%; height: 0;
    border-radius: 3px; transition: height 0.35s ease;
}
.qk-fill-me { background: var(--accent); }
.qk-fill-foe { background: var(--text-sub); }
.qk-arena-center { flex: 1 1 auto; min-width: 0; }

.qk-word {
    font-size: 2rem; font-weight: 600; color: var(--text-main); text-align: center;
    letter-spacing: 1px; line-height: 1.3; word-break: break-word; margin-bottom: 6px;
}
.qk-gain {
    text-align: center; font-size: 0.9rem; min-height: 1.5em;
    transition: opacity 0.25s; margin-bottom: 10px;
}
.qk-gain-good { color: #4caf50; }
.qk-gain-bad { color: #ff5252; }

.qk-options { display: flex; flex-direction: column; gap: 10px; }
.qk-option {
    width: 100%; box-sizing: border-box; text-align: center;
    background: var(--card-bg); color: var(--text-main);
    border: 1px solid var(--border); border-radius: 12px;
    padding: 16px 14px; font-size: 0.95rem; font-family: inherit; line-height: 1.4;
    cursor: pointer; transition: border-color 0.15s, background 0.15s, transform 0.1s;
}
@media (hover: hover) { .qk-option:hover:not(:disabled) { border-color: var(--text-sub); background: #1c1c1c; } }
.qk-option:active:not(:disabled) { transform: scale(0.985); }
.qk-option:disabled { cursor: default; }
.qk-option-right { border-color: #4caf50; background: rgba(76, 175, 80, 0.12); color: #cdebcf; }
.qk-option-wrong { border-color: #ff5252; background: rgba(255, 82, 82, 0.12); color: #f3c9c9; }
/* 對手選了哪一個。只有在我自己答完之後才會掛上來 —— 在那之前
   看不到對手選什麼，也看不到他加了幾分。 */
.qk-option { position: relative; }
.qk-option-foe::after {
    content: "對手";
    position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    font-size: 0.62rem; line-height: 1; padding: 3px 7px; border-radius: 8px;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.26);
    color: var(--text-sub);
    animation: qkFoeIn 0.25s ease both;
}
@keyframes qkFoeIn { from { opacity: 0; transform: translateY(-50%) scale(0.8); } }
.qk-foe-status { text-align: center; font-size: 0.8rem; color: var(--text-sub); margin-top: 16px; min-height: 1.4em; }

/* 公平競技：遊戲中的題目與選項不給選取、不給長按叫出「搜尋這段文字 / 以圖搜尋」 */
#view-qk-game, #view-qk-game * {
    -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;
    -webkit-touch-callout: none;
}
#view-qk-game img { -webkit-user-drag: none; pointer-events: none; }
/* 切出畫面時把題目糊掉，回來才看得到 —— 圈圖搜尋會先把畫面截走 */
.qk-guard #qk-word, .qk-guard #qk-options {
    filter: blur(14px); opacity: 0.35; transition: filter 0.12s, opacity 0.12s;
}
.qk-guard-note {
    text-align: center; font-size: 0.8rem; color: #ff5252;
    margin-top: 10px; min-height: 1.4em; line-height: 1.6;
}

/* ---- 結算 ---- */
.qk-result-wrap { padding: 6px 0 28px; }
.qk-result-title { text-align: center; font-size: 1.6rem; font-weight: 600; letter-spacing: 3px; margin-bottom: 4px; }
.qk-r-win { color: #4caf50; }
.qk-r-lose { color: #ff5252; }
.qk-r-draw { color: var(--text-sub); }
.qk-result-level { text-align: center; font-size: 0.8rem; color: var(--text-sub); margin-bottom: 20px; }

.qk-score-cards { display: flex; gap: 10px; }
.qk-score-card {
    flex: 1 1 0; min-width: 0; text-align: center;
    background: var(--card-bg); border: 1px solid var(--border); border-radius: 14px; padding: 16px 10px;
}
.qk-score-name { font-size: 0.8rem; color: var(--text-sub); margin-bottom: 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qk-score-num { font-size: 1.8rem; font-weight: 600; color: var(--text-main); font-variant-numeric: tabular-nums; line-height: 1.1; }
.qk-score-sub { font-size: 0.76rem; color: var(--text-sub); margin-top: 6px; }

.qk-points { text-align: center; font-size: 0.95rem; color: var(--accent); margin: 18px 0 4px; letter-spacing: 1px; }

.qk-wrong-wrap { margin-top: 16px; }
.qk-wrong-title { font-size: 0.8rem; color: var(--text-sub); margin-bottom: 8px; }
.qk-wrong-row {
    display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
    padding: 11px 13px; border: 1px solid var(--border); border-radius: 10px;
    background: var(--card-bg); margin-bottom: 8px;
}
.qk-wrong-en { font-size: 0.92rem; color: var(--text-main); word-break: break-word; }
.qk-wrong-zh { font-size: 0.84rem; color: var(--text-sub); flex: 0 0 auto; }
.qk-wrong-empty { font-size: 0.82rem; color: var(--text-sub); text-align: center; padding: 14px 0; }

/* =========================================================
   擴充商城：分類篩選器與組合包定位標籤
   ========================================================= */
.store-filter {
    display: flex; gap: 8px; flex-wrap: wrap;
    margin-top: 16px;
}
.store-chip {
    flex: 0 0 auto;
    background: var(--card-bg); color: var(--text-sub);
    border: 1px solid var(--border); border-radius: 999px;
    padding: 7px 14px; font-size: 0.8rem; font-family: inherit;
    cursor: pointer; letter-spacing: 0.5px;
    transition: border-color 0.15s, background 0.15s, color 0.15s;
}
@media (hover: hover) {
    .store-chip:hover { border-color: var(--text-sub); color: var(--text-main); }
}
.store-chip-on {
    background: rgba(255, 255, 255, 0.22);
    border-color: rgba(255, 255, 255, 0.48);
    color: var(--text-main);
    font-weight: 600;
    backdrop-filter: blur(10px) saturate(150%);
    -webkit-backdrop-filter: blur(10px) saturate(150%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.store-header {
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.store-position {
    flex: 0 0 auto;
    font-size: 0.7rem; color: var(--text-sub);
    border: 1px solid var(--border); border-radius: 999px;
    padding: 3px 9px; line-height: 1.4;
}

/* =========================================================
   列表進場動畫
   ---------------------------------------------------------
   只在「剛進到那個畫面」時跑一次。單字簿列表每點一次選取就會整個
   重畫，如果無條件掛動畫，每點一下全部的卡片都會重新閃一次，很煩。
   所以由 JS 在進場那次才加上 -anim 類別。
   ========================================================= */
@keyframes listItemIn {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

.bl-anim, .store-anim, .sub-anim {
    opacity: 0;
    animation: listItemIn 0.26s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

/* 階梯式延遲。超過第 8 個就一起出來，不然排在後面的要等很久 */
.bl-anim:nth-child(1),   .store-anim:nth-child(1),   .sub-anim:nth-child(1)   { animation-delay: 0.03s; }
.bl-anim:nth-child(2),   .store-anim:nth-child(2),   .sub-anim:nth-child(2)   { animation-delay: 0.06s; }
.bl-anim:nth-child(3),   .store-anim:nth-child(3),   .sub-anim:nth-child(3)   { animation-delay: 0.09s; }
.bl-anim:nth-child(4),   .store-anim:nth-child(4),   .sub-anim:nth-child(4)   { animation-delay: 0.12s; }
.bl-anim:nth-child(5),   .store-anim:nth-child(5),   .sub-anim:nth-child(5)   { animation-delay: 0.15s; }
.bl-anim:nth-child(6),   .store-anim:nth-child(6),   .sub-anim:nth-child(6)   { animation-delay: 0.18s; }
.bl-anim:nth-child(7),   .store-anim:nth-child(7),   .sub-anim:nth-child(7)   { animation-delay: 0.21s; }
.bl-anim:nth-child(n+8), .store-anim:nth-child(n+8), .sub-anim:nth-child(n+8) { animation-delay: 0.24s; }

/* 分類標題也一起浮現，不然標題先出現、卡片才跟上，看起來會斷掉 */
.bl-head-anim {
    opacity: 0;
    animation: listItemIn 0.24s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

/* 單字知識王的選項也做 stagger，跟選擇題一致 */
.qk-option {
    opacity: 0;
    animation: listItemIn 0.22s ease forwards;
}
.qk-option:nth-child(1) { animation-delay: 0.04s; }
.qk-option:nth-child(2) { animation-delay: 0.09s; }
.qk-option:nth-child(3) { animation-delay: 0.14s; }
.qk-option:nth-child(4) { animation-delay: 0.19s; }

/* 會暈車、或系統設了「減少動態效果」的人，一律不要動 */
@media (prefers-reduced-motion: reduce) {
    .bl-anim, .store-anim, .sub-anim, .bl-head-anim, .qk-option {
        opacity: 1;
        animation: none;
    }
    div[id^="view-"]:not(.hidden) { animation: none; }
}

/* =========================================================
   分享面板（share.js）
   ---------------------------------------------------------
   QR 一定要深色圖案配淺色底才掃得到，所以這裡自己鋪一塊白板，
   不跟著主題走 —— 深色主題底下直接畫 QR 是掃不出來的。
   ========================================================= */
.sh-box {
    max-width: 360px;
    width: 90%;
    text-align: center;
    padding: 26px 22px 22px;
}
.sh-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--text-main);
    letter-spacing: 1px;
    margin-bottom: 4px;
}
.sh-sub {
    font-size: 0.85rem;
    color: var(--text-sub);
    margin-bottom: 16px;
    word-break: break-word;
}
.sh-qr-plate {
    display: inline-block;
    background: #ffffff;
    padding: 10px;
    border-radius: 14px;
    line-height: 0;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
}
.sh-qr { display: block; }
.sh-hint {
    font-size: 0.76rem;
    color: var(--text-sub);
    margin: 12px 0 14px;
}
.sh-link {
    font-size: 0.72rem;
    color: var(--text-sub);
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 9px 11px;
    word-break: break-all;
    line-height: 1.5;
    text-align: left;
    /* 網址本來就長，給它一個高度上限，不要把按鈕擠出畫面 */
    max-height: 4.6em;
    overflow-y: auto;
}
.sh-note {
    font-size: 0.76rem;
    color: var(--text-sub);
    line-height: 1.7;
    margin-top: 12px;
    text-align: left;
}
.sh-actions {
    display: flex;
    gap: 10px;
    margin: 16px 0 10px;
}
.sh-actions .btn { flex: 1; margin-top: 0; }

/* 好友頁：代號旁的說明 */
.fr-field-hint {
    font-size: 0.74rem;
    color: var(--text-sub);
    margin-top: 8px;
    line-height: 1.6;
}

/* 取代 emoji 的線條圖示：跟著文字顏色走，各平台長相一致 */
.ico { display: block; flex-shrink: 0; }
span > .ico, button > .ico { display: inline-block; }

/* =========================================================
   單字記憶學院（academy.js）
   ---------------------------------------------------------
   兩種題型共用同一塊版面：字尾題會多顯示一排字根，同族題不顯示。
   選項一律用 .btn-mcq，答完之後只加顏色、不改尺寸，避免整頁跳動。
   ========================================================= */
.ac-lead {
    font-size: 0.85rem; color: var(--text-sub);
    margin-bottom: 18px; line-height: 1.6;
}
.ac-mod { width: 100%; text-align: left; padding: 20px 18px; margin-bottom: 12px; }
.ac-soon {
    margin-top: 14px; font-size: 0.8rem; color: var(--text-sub);
    text-align: center; opacity: 0.7;
}

/* ── 選方向 ── */
.ps-dir-list { display: flex; flex-direction: column; gap: 12px; }
.ps-dir { width: 100%; text-align: left; padding: 18px; }
.ps-dir-title { display: block; }
.ps-loading {
    padding: 40px 0; text-align: center;
    color: var(--text-sub); font-size: 0.9rem;
}

/* ── 練習 ── */
.ps-score { color: var(--text-sub); font-size: 0.85rem; }
.ps-progress {
    color: var(--text-sub); font-size: 0.85rem;
    margin-left: 10px; letter-spacing: 0.5px;
}
.ps-play { padding-bottom: 30px; }
.ps-task {
    text-align: center; font-size: 0.9rem; color: var(--text-sub);
    letter-spacing: 0.5px; margin: 6px 0 16px;
}
.ps-card {
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 14px; padding: 22px 16px; text-align: center;
}
.ps-word {
    font-size: 2.1rem; font-weight: 600; color: var(--text-main);
    letter-spacing: 0.5px; overflow-wrap: anywhere;
}
.ps-word-zh { margin-top: 6px; font-size: 0.95rem; color: var(--text-sub); }
.ps-arrow {
    display: flex; justify-content: center;
    color: var(--text-sub); opacity: 0.55; margin: 10px 0 6px;
}
.ps-target { text-align: center; margin-bottom: 18px; }
.ps-target-label { font-size: 0.82rem; color: var(--text-sub); margin-right: 8px; }
.ps-target-zh {
    font-size: 1.15rem; font-weight: 600; color: var(--text-main);
    letter-spacing: 0.5px;
}
.ps-stem {
    text-align: center; margin-bottom: 16px;
    font-size: 1.5rem; font-weight: 600; color: var(--text-main);
    letter-spacing: 1px; overflow-wrap: anywhere;
}
.ps-stem-blank { color: var(--text-sub); margin-left: 8px; font-weight: 400; }
.ps-options { grid-template-columns: 1fr 1fr; }
.ps-opt { letter-spacing: 0.5px; }
.ps-opt:disabled { cursor: default; opacity: 0.55; }
.ps-opt-right {
    border-color: #4caf50 !important; color: #4caf50 !important;
    opacity: 1 !important;
}
.ps-opt-wrong {
    border-color: #e05260 !important; color: #e05260 !important;
    opacity: 1 !important;
}
.ps-hint {
    margin-top: 14px; text-align: center;
    font-size: 0.78rem; color: var(--text-sub); opacity: 0.75;
}

.ps-feedback { margin-top: 20px; text-align: center; }
.ps-fb-status { font-size: 1rem; font-weight: 700; letter-spacing: 2px; }
.ps-fb-status.ps-ok { color: #4caf50; }
.ps-fb-status.ps-no { color: #e05260; }
.ps-fb-answer {
    margin-top: 10px; font-size: 1.6rem; font-weight: 600;
    color: var(--text-main); overflow-wrap: anywhere;
}
.ps-fb-zh { margin-top: 4px; font-size: 0.9rem; color: var(--text-sub); }
.ps-next { width: 100%; max-width: 300px; margin-top: 20px; }

/* ── 結算 ── */
.ps-result { padding: 40px 0 30px; text-align: center; }
.ps-result-score {
    font-size: 3rem; font-weight: 700; color: var(--text-main);
    letter-spacing: 2px;
}
.ps-result-sub { margin-top: 6px; font-size: 0.9rem; color: var(--text-sub); }
.ps-result-review { margin: 26px 0 6px; text-align: left; }
.ps-review-title {
    font-size: 0.82rem; color: var(--text-sub);
    margin-bottom: 10px; letter-spacing: 0.5px;
}
.ps-review-row {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border);
}
.ps-review-en { color: var(--text-main); font-size: 0.95rem; overflow-wrap: anywhere; }
.ps-review-zh { color: var(--text-sub); font-size: 0.82rem; flex-shrink: 0; }
.ps-result-btn { width: 100%; margin-top: 14px; }
.ps-result-alt { --btn-tint: 150, 150, 150; }

/* ── 字尾規則卡 ── */
#ps-rules-overlay {
    position: fixed; inset: 0; z-index: 9998;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
    display: flex; justify-content: center; align-items: center;
    padding: 20px;
}
#ps-rules-overlay.hidden { display: none; }
.ps-rules-box {
    max-width: 420px; width: 100%;
    max-height: 82vh; display: flex; flex-direction: column;
    transform: none; padding: 22px 18px 18px;
}
.ps-rules-title {
    font-size: 1.05rem; font-weight: 700; color: var(--text-main);
    letter-spacing: 1px; margin-bottom: 14px;
}
.ps-rules-body { overflow-y: auto; -webkit-overflow-scrolling: touch; }
.ps-rule-group { margin-bottom: 20px; }
.ps-rule-pos {
    font-size: 0.8rem; color: var(--text-sub);
    letter-spacing: 1px; margin-bottom: 8px;
}
.ps-rule-card {
    border: 1px solid var(--border); border-radius: 10px;
    padding: 11px 13px; margin-bottom: 8px;
}
.ps-rule-suffix {
    font-size: 1rem; font-weight: 600; color: var(--text-main);
    letter-spacing: 0.5px;
}
.ps-rule-desc { margin-top: 3px; font-size: 0.8rem; color: var(--text-sub); }
.ps-rule-eg {
    margin-top: 6px; font-size: 0.82rem; color: var(--text-sub);
    opacity: 0.85; overflow-wrap: anywhere;
}
.ps-rules-close { width: 100%; margin-top: 8px; flex-shrink: 0; }
.ac-pro {
    font-size: 0.7rem; background: rgba(240, 192, 64, 0.2);
    border: 1px solid #f0c040; color: #f0c040;
    padding: 1px 7px; border-radius: 8px;
    margin-left: 8px; vertical-align: middle; font-weight: 600;
}

/* ── 不規則變化對照表（規則卡最後一段） ── */
.ps-rule-note {
    font-size: 0.8rem; color: var(--text-sub);
    line-height: 1.6; margin-bottom: 10px;
}
.ps-irr-list { border-top: 1px solid var(--border); }
.ps-irr-row {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 12px; padding: 9px 2px; border-bottom: 1px solid var(--border);
}
.ps-irr-en { color: var(--text-main); font-size: 0.92rem; overflow-wrap: anywhere; }
.ps-irr-arrow { color: var(--text-sub); margin: 0 2px; }
.ps-irr-zh { color: var(--text-sub); font-size: 0.78rem; flex-shrink: 0; }

/* ── 動畫 ──
   答題節奏要有手感：題目滑進來、選項依序浮現、答完之後答案才長出來。
   全部尊重系統的「減少動態效果」設定，檔案最後有統一關掉。 */
@keyframes ps-rise {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}
@keyframes ps-pop {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.045); }
    100% { transform: scale(1); }
}
@keyframes ps-shake {
    0%, 100% { transform: translateX(0); }
    22%      { transform: translateX(-5px); }
    55%      { transform: translateX(4px); }
    80%      { transform: translateX(-2px); }
}
.ps-enter .ps-task   { animation: ps-rise 0.26s ease both; }
.ps-enter .ps-card   { animation: ps-rise 0.3s ease both 0.04s; }
.ps-enter .ps-arrow,
.ps-enter .ps-target,
.ps-enter .ps-stem   { animation: ps-rise 0.3s ease both 0.1s; }
.ps-enter .ps-opt:nth-child(1) { animation: ps-rise 0.28s ease both 0.16s; }
.ps-enter .ps-opt:nth-child(2) { animation: ps-rise 0.28s ease both 0.21s; }
.ps-enter .ps-opt:nth-child(3) { animation: ps-rise 0.28s ease both 0.26s; }
.ps-enter .ps-opt:nth-child(4) { animation: ps-rise 0.28s ease both 0.31s; }
.ps-enter .ps-hint   { animation: ps-rise 0.3s ease both 0.36s; }

.ps-opt { transition: transform 0.12s ease, border-color 0.18s ease, color 0.18s ease, background 0.18s ease; }
.ps-opt:active:not(:disabled) { transform: scale(0.97); }
.ps-opt-right { animation: ps-pop 0.34s ease; }
.ps-opt-wrong { animation: ps-shake 0.32s ease; }

.ps-feedback:not(.hidden) { animation: ps-rise 0.26s ease both; }
.ps-feedback:not(.hidden) .ps-fb-answer { animation: ps-rise 0.3s ease both 0.06s; }
.ps-feedback:not(.hidden) .ps-next { animation: ps-rise 0.3s ease both 0.12s; }
.ps-result:not(.hidden) { animation: ps-rise 0.3s ease both; }
.ps-result:not(.hidden) .ps-result-score { animation: ps-pop 0.45s ease 0.1s; }

@media (prefers-reduced-motion: reduce) {
    .ps-enter .ps-task, .ps-enter .ps-card, .ps-enter .ps-arrow,
    .ps-enter .ps-target, .ps-enter .ps-stem, .ps-enter .ps-opt,
    .ps-enter .ps-hint, .ps-opt-right, .ps-opt-wrong,
    .ps-feedback:not(.hidden), .ps-feedback:not(.hidden) .ps-fb-answer,
    .ps-feedback:not(.hidden) .ps-next,
    .ps-result:not(.hidden), .ps-result:not(.hidden) .ps-result-score {
        animation: none;
        opacity: 1;
        transform: none;
    }
}
/* 加字首的題目要反過來念：「？ ＋ 字根」，所以把兩塊對調 */
.ps-stem.ps-stem-pre { display: flex; justify-content: center; align-items: baseline; }
.ps-stem.ps-stem-pre #ps-stem-text { order: 2; }
.ps-stem.ps-stem-pre .ps-stem-blank { order: 1; margin-left: 0; margin-right: 8px; }

/* =========================================================
   心流模式（flow.js）
   ---------------------------------------------------------
   CD 球的 z-index 要在內容之上、彈窗之下：彈窗最高到 10002，
   所以球放 9400、面板放 9450，跳出確認框時球不會壓在上面。
   ========================================================= */
.flow-ball {
    position: fixed;
    right: 16px;
    bottom: calc(22px + env(safe-area-inset-bottom, 0px));
    width: 54px; height: 54px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: linear-gradient(145deg, rgba(255,255,255,0.16), rgba(255,255,255,0.05));
    backdrop-filter: blur(12px) saturate(160%);
    -webkit-backdrop-filter: blur(12px) saturate(160%);
    color: var(--text-main);
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.45);
    cursor: grab;
    touch-action: none;            /* 不然拖曳會被瀏覽器當成捲動 */
    z-index: 9400;
    display: flex; align-items: center; justify-content: center;
    transition: box-shadow 0.25s ease, border-color 0.25s ease, transform 0.15s ease;
}
.flow-ball:active { cursor: grabbing; transform: scale(0.94); }
.flow-ball.flow-active {
    border-color: rgba(255, 255, 255, 0.45);
    box-shadow: 0 6px 26px rgba(0, 0, 0, 0.5), 0 0 18px rgba(255, 255, 255, 0.14);
}
.flow-cd { width: 38px; height: 38px; display: block; }
/* 轉動＝正在播放。這是 CD 造型最大的價值：不用文字就看得懂狀態 */
@keyframes flow-spin { to { transform: rotate(360deg); } }
.flow-ball.flow-spinning .flow-cd { animation: flow-spin 4.5s linear infinite; }
.flow-dot {
    position: absolute; top: 4px; right: 4px;
    width: 9px; height: 9px; border-radius: 50%;
    background: #4caf50;
    box-shadow: 0 0 8px rgba(76, 175, 80, 0.8);
}

/* ── 混音面板 ── */
.flow-panel { position: fixed; inset: 0; z-index: 9450; }
.flow-panel.hidden { display: none; }
.flow-backdrop {
    position: absolute; inset: 0;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
    opacity: 0; transition: opacity 0.25s ease;
}
.flow-panel.flow-shown .flow-backdrop { opacity: 1; }
.flow-sheet {
    position: absolute; left: 50%; bottom: 0;
    width: 100%; max-width: 480px;
    transform: translate(-50%, 100%);
    transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
    background: var(--card-bg);
    border: 1px solid var(--border); border-bottom: none;
    border-radius: 20px 20px 0 0;
    padding: 10px 18px calc(20px + env(safe-area-inset-bottom, 0px));
    max-height: 86vh; display: flex; flex-direction: column;
}
.flow-panel.flow-shown .flow-sheet { transform: translate(-50%, 0); }
.flow-grip {
    width: 40px; height: 4px; border-radius: 2px;
    background: var(--text-sub); opacity: 0.35;
    margin: 0 auto 10px;
}
.flow-head { margin-bottom: 10px; }
.flow-title { font-size: 1.1rem; font-weight: 700; color: var(--text-main); letter-spacing: 1px; }
.flow-lead { margin-top: 4px; font-size: 0.78rem; color: var(--text-sub); line-height: 1.55; }

.flow-rows { overflow-y: auto; -webkit-overflow-scrolling: touch; flex: 1; }
.flow-row { padding: 8px 0 9px; border-bottom: 1px solid var(--border); }
.flow-row-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.flow-chip {
    background: none; border: 1px solid var(--border);
    border-radius: 999px; padding: 4px 13px;
    color: var(--text-sub); font-size: 0.9rem; font-weight: 600;
    cursor: pointer; letter-spacing: 0.5px;
    transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.flow-row-on .flow-chip {
    color: var(--text-main);
    border-color: rgba(255, 255, 255, 0.4);
    background: rgba(255, 255, 255, 0.08);
}
.flow-pct { font-size: 0.78rem; color: var(--text-sub); min-width: 34px; text-align: right; }
.flow-sub { margin-top: 3px; font-size: 0.71rem; color: var(--text-sub); opacity: 0.65; line-height: 1.4; }
.flow-slider {
    width: 100%; margin: 7px 0 0;
    -webkit-appearance: none; appearance: none;
    height: 3px; border-radius: 2px;
    background: var(--border); outline: none;
}
.flow-slider::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 17px; height: 17px; border-radius: 50%;
    background: var(--text-main); cursor: pointer;
    box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
}
.flow-slider::-moz-range-thumb {
    width: 17px; height: 17px; border-radius: 50%; border: none;
    background: var(--text-main); cursor: pointer;
}
/* .btn 本身是 width:100%，不覆蓋掉的話兩顆按鈕會搶同一份寬度，
   結果是其中一顆被壓成直排的四個字 */
.flow-actions { display: flex; gap: 10px; margin-top: 14px; flex-shrink: 0; }
.flow-main { flex: 1 1 auto; width: auto; min-width: 0; white-space: nowrap; }
.flow-alt {
    flex: 0 0 auto; width: auto; white-space: nowrap;
    padding-left: 18px; padding-right: 18px;
    --btn-tint: 150, 150, 150;
}

/* ── 學習前清單 ── */
.flow-checklist {
    position: fixed; inset: 0; z-index: 9500;
    background: rgba(0, 0, 0, 0.88);
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
}
.flow-checklist.hidden { display: none; }
.flow-cl-inner { width: 100%; max-width: 340px; text-align: center; }
.flow-cl-step { font-size: 0.78rem; color: var(--text-sub); letter-spacing: 2px; }
.flow-cl-title {
    margin-top: 18px; font-size: 1.45rem; font-weight: 700;
    color: var(--text-main); line-height: 1.5; letter-spacing: 1px;
}
.flow-cl-sub { margin-top: 12px; font-size: 0.85rem; color: var(--text-sub); line-height: 1.7; }
.flow-cl-next { width: 100%; margin-top: 34px; }
.flow-cl-skip {
    display: block; width: 100%; margin-top: 14px;
    background: none; border: none; cursor: pointer;
    color: var(--text-sub); font-size: 0.8rem; letter-spacing: 0.5px;
}

/* ── 心流狀態：把裝飾沉下去，留下正在做的事 ── */
html[data-flow="on"] #theme-fx[data-fx="galaxy"] { opacity: 0.35; transition: opacity 0.8s ease; }
body::before { transition: filter 0.9s ease; }
html[data-flow="on"] body::before { filter: saturate(0.6) brightness(0.8); }
/* 進入心流時把「幾人正在學習」和 Pro 徽章收掉。
   只調 opacity 的話它們還是佔著位子，商標會孤零零地停在上半部、
   下面空一塊。要連高度／寬度一起收，整個頁首才會塌下來、商標往下
   填回原本的中間位置 —— 而且兩邊都要有過渡，不然是硬跳。 */
#online-presence-badge {
    /* overflow: hidden 是下面那個收合動畫要的 —— max-height 動到 0 的時候
       沒有它就收不起來。但它同時也會把裡面的東西裁掉：那顆呼吸的綠點
       貼在容器最左邊，動畫放大到 1.3 倍時會頂出左緣被切掉一角。
       人數變成兩位數時那一行更擠，就更明顯。
       左右各留 3px 再用負 margin 抵銷回去，裁切框變寬但版面完全不動。 */
    overflow: hidden;
    padding-left: 3px;
    padding-right: 3px;
    margin-left: -3px;
    margin-right: -3px;
    max-height: 26px;
    transition: opacity 0.45s ease, max-height 0.65s cubic-bezier(0.22, 1, 0.36, 1),
                margin-top 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}
html[data-flow="on"] #online-presence-badge {
    opacity: 0; max-height: 0; margin-top: 0; pointer-events: none;
}
#header-pro-badge {
    overflow: hidden;
    max-width: 90px;
    transition: opacity 0.45s ease, max-width 0.65s cubic-bezier(0.22, 1, 0.36, 1),
                margin-left 0.65s cubic-bezier(0.22, 1, 0.36, 1),
                padding 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}
html[data-flow="on"] #header-pro-badge {
    opacity: 0; max-width: 0; margin-left: 0;
    padding-left: 0; padding-right: 0; pointer-events: none;
}
/* 商標本身也跟著移動，這一段要一起有過渡才不會只有徽章在動 */
.hdr-brand, .hdr-title-row { transition: transform 0.65s cubic-bezier(0.22, 1, 0.36, 1); }
#main-header { transition: background 0.9s ease, border-color 0.9s ease; }
html[data-flow="on"] #main-header { background: transparent; border-bottom-color: transparent; }
/* 邊緣壓暗，視線自然往中間收。
   這一層一直都在，只是平常透明 —— 元素要先存在才有辦法做過渡，
   不然進出心流就是硬切一下。 */
body::after {
    content: ""; position: fixed; inset: 0; z-index: 0;
    pointer-events: none; opacity: 0;
    background: radial-gradient(ellipse at center, transparent 42%, rgba(0, 0, 0, 0.55) 100%);
    transition: opacity 0.9s ease;
}
html[data-flow="on"] body::after { opacity: 1; }
html[data-flow="on"] #theme-fx[data-fx="galaxy"] { transition: opacity 0.8s ease; }

@media (prefers-reduced-motion: reduce) {
    .flow-ball.flow-spinning .flow-cd { animation: none; }
    .flow-sheet, .flow-backdrop { transition: none; }
}
.flow-ball.flow-hidden { display: none; }

/* ── 心流的動畫：慢、平、淡 ──
   這個模式的整個賣點就是不要有突兀的東西，所以曲線都用 ease-out、
   時間比別的地方長，而且一律是淡入，不用彈跳或位移太大的效果。 */
@keyframes flow-fade-up {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}
@keyframes flow-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
/* 面板打開時，每一列依序浮現 */
.flow-panel.flow-shown .flow-row { animation: flow-fade-up 0.42s cubic-bezier(0.22, 1, 0.36, 1) both; }
.flow-panel.flow-shown .flow-row:nth-child(1) { animation-delay: 0.06s; }
.flow-panel.flow-shown .flow-row:nth-child(2) { animation-delay: 0.10s; }
.flow-panel.flow-shown .flow-row:nth-child(3) { animation-delay: 0.14s; }
.flow-panel.flow-shown .flow-row:nth-child(4) { animation-delay: 0.18s; }
.flow-panel.flow-shown .flow-row:nth-child(5) { animation-delay: 0.22s; }
.flow-panel.flow-shown .flow-row:nth-child(6) { animation-delay: 0.26s; }
.flow-panel.flow-shown .flow-row:nth-child(7) { animation-delay: 0.30s; }
.flow-panel.flow-shown .flow-row:nth-child(8) { animation-delay: 0.34s; }
.flow-panel.flow-shown .flow-head { animation: flow-fade-up 0.4s ease both; }
.flow-panel.flow-shown .flow-actions { animation: flow-fade 0.5s ease both 0.3s; }

/* 學習前清單：整頁淡入，換頁時內容重新浮現一次 */
.flow-checklist { animation: flow-fade 0.5s ease both; }
.flow-cl-anim .flow-cl-step { animation: flow-fade 0.4s ease both; }
.flow-cl-anim .flow-cl-title { animation: flow-fade-up 0.5s cubic-bezier(0.22, 1, 0.36, 1) both 0.05s; }
.flow-cl-anim .flow-cl-sub { animation: flow-fade-up 0.5s cubic-bezier(0.22, 1, 0.36, 1) both 0.12s; }
.flow-cl-anim .flow-cl-next { animation: flow-fade-up 0.5s cubic-bezier(0.22, 1, 0.36, 1) both 0.2s; }
.flow-cl-anim .flow-cl-skip { animation: flow-fade 0.5s ease both 0.3s; }

/* CD 球：進出心流的時候也要慢慢亮起來，不要閃一下 */
.flow-ball .flow-cd { transition: opacity 0.6s ease; }
.flow-dot { animation: flow-fade 0.6s ease both; }

@media (prefers-reduced-motion: reduce) {
    .flow-panel.flow-shown .flow-row,
    .flow-panel.flow-shown .flow-head,
    .flow-panel.flow-shown .flow-actions,
    .flow-checklist,
    .flow-cl-anim .flow-cl-step,
    .flow-cl-anim .flow-cl-title,
    .flow-cl-anim .flow-cl-sub,
    .flow-cl-anim .flow-cl-next,
    .flow-cl-anim .flow-cl-skip,
    .flow-dot {
        animation: none; opacity: 1; transform: none;
    }
    body::after, body::before, #main-header { transition: none; }
}
/* 清單的重看入口。一天只自己跳一次，錯過了要找得到路回去 */
.flow-listlink {
    display: block; width: 100%; margin-top: 10px; flex-shrink: 0;
    background: none; border: none; cursor: pointer;
    color: var(--text-sub); font-size: 0.78rem; letter-spacing: 0.5px;
    padding: 6px 0;
}
.flow-listlink:hover { color: var(--text-main); }
/* 面板上的開關列 */
.flow-opt {
    display: flex; align-items: center; justify-content: space-between;
    width: 100%; margin-top: 12px; flex-shrink: 0;
    padding: 10px 14px;
    background: none; border: 1px solid var(--border); border-radius: 12px;
    color: var(--text-sub); font-size: 0.82rem; letter-spacing: 0.5px;
    cursor: pointer;
    transition: color 0.2s ease, border-color 0.2s ease;
}
.flow-opt:hover { color: var(--text-main); }
.flow-opt-state { color: var(--text-main); font-weight: 600; }
.flow-opt.flow-opt-off .flow-opt-state { color: var(--text-sub); opacity: 0.7; }

/* 暖身階段的三顆按鈕。
   原本只有「跳過暖身」與「下一步」兩顆，加了「上一步」之後每顆都變窄，
   320px 的機型上「跳過暖身」會折成兩行 —— 所以字級與左右內距都收一階，
   而且明確禁止換行。 */
.mastery-l0-btns { gap: 8px; }
.mastery-l0-btns .btn {
    flex: 1;
    margin: 0;
    padding: 15px 6px;
    font-size: 0.86rem;
    white-space: nowrap;
    letter-spacing: 0;
}
.mastery-l0-btns #mastery-btn-l0 { flex: 1.6; }
@media (max-width: 340px) {
    .mastery-l0-btns { gap: 6px; }
    .mastery-l0-btns .btn { font-size: 0.8rem; padding: 14px 4px; }
}

/* =========================================================
   玩家市場：方格型錄
   ---------------------------------------------------------
   原本一張卡片一整列，名稱、創作者、描述、銷量、預覽、價格全部塞在
   同一張裡，捲很久也看不完幾個商品。改成方格：格子上只放名稱與單字量，
   其餘的等點進預覽再說 —— 買之前本來就該看內容，不是看描述。
   ========================================================= */
.mk-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 12px;
}
.mk-tile {
    position: relative;
    aspect-ratio: 1 / 1;
    display: flex;
    flex-direction: column;
    padding: 14px 12px;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--card-bg);
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    transition: border-color 0.18s, transform 0.18s, box-shadow 0.18s;
    overflow: hidden;
}
@media (hover: hover) {
    .mk-tile:hover {
        border-color: #ff9800;
        box-shadow: 0 0 18px rgba(255, 152, 0, 0.12);
    }
}
.mk-tile:active { transform: scale(0.97); }

/* 名字吃掉中間整塊並置中。靠上對齊的話，正方形的格子中間會空一大片。 */
.mk-tile-name {
    flex: 1;
    display: flex;
    align-items: center;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-main);
    line-height: 1.35;
    letter-spacing: 0.3px;
    overflow: hidden;
}
/* 名字太長就切三行，不要把格子撐破。
   -webkit-line-clamp 只對 -webkit-box 有效，所以夾行的是裡面這層。 */
.mk-tile-name > span {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
}
.mk-tile-foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 6px;
}
.mk-tile-count { font-size: 0.72rem; color: var(--text-sub); white-space: nowrap; }
.mk-tile-price { font-size: 0.86rem; font-weight: 700; color: #ff9800; white-space: nowrap; }
.mk-tile-owned { font-size: 0.78rem; font-weight: 600; color: var(--text-sub); }
/* 自己上架的東西要一眼認得出來，不然會想不起來哪個是自己的 */
.mk-tile-mine { border-color: rgba(255, 152, 0, 0.55); }
.mk-tile-flag {
    position: absolute;
    top: 0; right: 0;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    padding: 3px 8px;
    border-bottom-left-radius: 10px;
    background: rgba(255, 152, 0, 0.9);
    color: #000;
}
.mk-tile-flag-owned { background: rgba(255, 255, 255, 0.16); color: var(--text-main); }
/* 官方推薦：金色框＋左上角標籤（右上角留給「我的／已擁有」） */
.mk-tile-featured { border-color: rgba(241, 196, 15, 0.7); box-shadow: 0 0 14px rgba(241, 196, 15, 0.18); }
.mk-tile-pick {
    position: absolute;
    top: 0; left: 0;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    padding: 3px 8px;
    border-bottom-right-radius: 10px;
    background: linear-gradient(135deg, #f1c40f, #e0a100);
    color: #000;
}
.mk-chip-featured { border-color: rgba(241, 196, 15, 0.45); color: #f1c40f; }
.mk-chip-featured.active { background: rgba(241, 196, 15, 0.14); border-color: #f1c40f; color: #f1c40f; }
.mk-tile-featured .mk-tile-name { margin-top: 10px; }
.mp-foot .btn.mp-feature-btn { margin-top: 10px; border-color: rgba(241, 196, 15, 0.6); color: #f1c40f; }
.mp-feature-btn.on { border-color: var(--border); color: var(--text-sub); }

/* 篩選列 */
.mk-filter-bar { margin-top: 18px; }
.mk-filter-label {
    font-size: 0.72rem; color: var(--text-sub);
    letter-spacing: 1px; margin-bottom: 8px;
}
/* 換行而不是橫捲：五顆晶片在 390px 上剛好會被切掉最後一顆，
   看起來像畫面壞了，而不是「可以往右滑」。 */
.mk-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.mk-chip {
    flex: 0 0 auto;
    background: #1a1a1a;
    border: 1px solid #333;
    color: var(--text-sub);
    padding: 6px 13px;
    border-radius: 20px;
    font-size: 0.8rem;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.18s ease;
}
.mk-chip.active {
    background: rgba(255, 152, 0, 0.12);
    border-color: #ff9800;
    color: #ff9800;
    font-weight: 600;
}
.mk-chip:active { transform: scale(0.95); }
.mk-filter-note {
    font-size: 0.74rem;
    color: var(--text-sub);
    margin-top: 10px;
    min-height: 1em;
}

/* 預覽彈窗：多出來的資訊與釘在底下的購買列 */
.mp-meta {
    display: flex; flex-wrap: wrap; gap: 8px;
    margin-bottom: 12px;
}
.mp-meta span {
    font-size: 0.72rem; color: var(--text-sub);
    border: 1px solid var(--border); border-radius: 999px;
    padding: 4px 10px;
}
.mp-desc {
    font-size: 0.84rem; color: var(--text-sub);
    line-height: 1.6; margin-bottom: 14px;
    white-space: pre-wrap; word-break: break-word;
}
.mp-desc:empty { display: none; }
.mp-foot {
    flex-shrink: 0;
    padding: 14px 20px calc(14px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border);
}
.mp-foot .btn { width: 100%; margin: 0; }

/* =========================================================
   AI 閱讀：段落解釋
   ---------------------------------------------------------
   每一段下面掛一條「解釋這段」，點了才產。產出來之後點中文那一塊
   會朗讀整段英文，再點一下停 —— 所以整塊都要看起來可以按。
   ========================================================= */
.rd-para-tools { margin: -6px 0 18px; }

.rd-explain-btn {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-sub);
    font-family: inherit;
    font-size: 0.74rem;
    letter-spacing: 0.5px;
    padding: 4px 11px;
    border-radius: 999px;
    cursor: pointer;
    transition: color 0.18s, border-color 0.18s, background 0.18s;
}
.rd-explain-btn:active { transform: scale(0.96); }
.rd-explain-btn:disabled { opacity: 0.5; cursor: default; }
.rd-translate-btn { margin-right: 6px; border-color: rgba(255, 193, 7, 0.45); color: #e6c36a; }
.rd-translate-box { margin-top: 10px; padding: 12px 14px; border: 1px solid var(--border); border-left: 3px solid #ffc107;
    border-radius: 10px; background: rgba(255, 193, 7, 0.04); }
.rd-translate-box.hidden { display: none; }
.tr-inline-loading { color: var(--text-sub); font-size: 0.85rem; }
.tr-inline-zh { color: var(--text-main); font-size: 0.95rem; line-height: 1.7; }
.tr-inline-zh-ai { color: #e9d8ff; }
.tr-inline-tools { display: flex; align-items: center; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.tr-inline-ai { border: 1px solid rgba(179, 136, 255, 0.5); background: transparent; color: #cdb4ff; border-radius: 999px; padding: 3px 10px;
    font-size: 0.74rem; cursor: pointer; font-family: inherit; }
.tr-inline-ai:disabled { opacity: 0.6; cursor: default; }
.tr-inline-note { color: var(--text-sub); font-size: 0.7rem; }
.rd-translate-box .tr-chips { margin-top: 8px; }
/* 已經有人產過的：免費也看得到，標成綠的讓人知道點下去不用錢 */
.rd-explain-ready { border-color: rgba(76, 175, 80, 0.5); color: #7bc67e; }
/* 免費使用者點到沒人產過的段落會被擋，先標出來，不要讓人一直點一直被拒絕 */
.rd-explain-locked { border-color: rgba(240, 192, 64, 0.45); color: #d9b45c; }

.rd-explain-box {
    margin-top: 10px;
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-left: 3px solid #e91e63;
    border-radius: 10px;
    background: rgba(233, 30, 99, 0.04);
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
}
.rd-explain-box.hidden { display: none; }
@media (hover: hover) {
    .rd-explain-box:hover { background: rgba(233, 30, 99, 0.08); }
}
.rd-explain-text {
    font-size: 0.9rem;
    line-height: 1.85;
    color: var(--text-main);
    white-space: pre-wrap;
    word-break: break-word;
}
.rd-explain-hint {
    margin-top: 10px;
    font-size: 0.72rem;
    color: var(--text-sub);
    letter-spacing: 0.5px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.rd-explain-hint::before {
    content: '';
    width: 6px; height: 6px; border-radius: 50%;
    background: var(--text-sub);
    flex: 0 0 6px;
}
/* 朗讀中：左邊那條變色，提示點的圓點跳動 */
.rd-explain-speaking {
    border-left-color: #4caf50;
    background: rgba(76, 175, 80, 0.07);
}
.rd-explain-speaking .rd-explain-hint { color: #7bc67e; }
.rd-explain-speaking .rd-explain-hint::before {
    background: #4caf50;
    animation: rdSpeakPulse 1s ease-in-out infinite;
}
@keyframes rdSpeakPulse {
    0%, 100% { opacity: 1;   transform: scale(1); }
    50%      { opacity: 0.4; transform: scale(1.5); }
}
@media (prefers-reduced-motion: reduce) {
    .rd-explain-speaking .rd-explain-hint::before { animation: none; }
}
html[data-fx="low"] .rd-explain-speaking .rd-explain-hint::before { animation: none; }

/* =========================================================
   文章博物館
   ---------------------------------------------------------
   大家讀過的文章。卡片要一眼看得出來源 —— 精選新聞與玩家分享
   是兩種不同的東西，混在一起會讓人不知道自己在讀誰的內容。
   ========================================================= */
.mu-card {
    display: block;
    width: 100%;
    text-align: left;
    font-family: inherit;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 14px 16px;
    margin-bottom: 12px;
    cursor: pointer;
    transition: border-color 0.18s, transform 0.18s;
}
.mu-card:active { transform: scale(0.985); }
@media (hover: hover) {
    .mu-card:hover { border-color: #e91e63; }
}
.mu-card-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; margin-bottom: 8px;
}
.mu-tag {
    font-size: 0.66rem; font-weight: 600; letter-spacing: 0.5px;
    padding: 2px 8px; border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: var(--text-sub);
    flex: 0 0 auto;
}
.mu-tag-news { border-color: rgba(233, 30, 99, 0.5); color: #f06292; }
.mu-meta { font-size: 0.68rem; color: var(--text-sub); white-space: nowrap; }
.mu-title {
    font-size: 0.98rem; font-weight: 600; color: var(--text-main);
    line-height: 1.45; margin-bottom: 6px; word-break: break-word;
}
.mu-excerpt {
    font-size: 0.8rem; color: var(--text-sub); line-height: 1.6;
    display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2;
    -webkit-box-orient: vertical; overflow: hidden;
}
.mu-foot {
    margin-top: 8px; font-size: 0.7rem; color: var(--text-sub);
    letter-spacing: 0.3px; opacity: 0.8;
}

/* =========================================================
   每日簽到
   ---------------------------------------------------------
   七天一格。三種狀態要一眼分得出來：已領（打勾、暗）、
   今天可領（發亮、會呼吸）、還沒到（暗、鎖著）。
   ========================================================= */
#checkin-overlay {
    position: fixed;
    inset: 0;
    z-index: 9100;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: rgba(0, 0, 0, 0.8);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 0.2s;
}
#checkin-overlay.show { opacity: 1; }
#checkin-overlay.hidden { display: none !important; }

.checkin-box {
    width: 100%;
    max-width: 440px;
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 20px 20px 0 0;
    backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
}
#checkin-overlay.show .checkin-box {
    animation: addBookIn 0.3s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@media (min-width: 700px) {
    #checkin-overlay { align-items: center; padding: 24px; }
    .checkin-box { border-radius: 20px; }
}

.checkin-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 12px; padding: 18px 20px 14px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.checkin-title { font-size: 1.05rem; font-weight: 700; color: #f0c040; letter-spacing: 1px; }
.checkin-sub { font-size: 0.76rem; color: var(--text-sub); margin-top: 4px; }
.checkin-body { padding: 18px 20px; overflow-y: auto; }

.checkin-streak-card {
    position: relative;
    overflow: hidden;
    padding: 16px 18px 17px;
    margin-bottom: 16px;
    border: 1px solid rgba(240, 192, 64, 0.38);
    border-radius: 16px;
    background: linear-gradient(130deg, rgba(240, 192, 64, 0.16), rgba(240, 192, 64, 0.03) 72%);
}
.checkin-streak-card::before {
    content: '';
    position: absolute;
    width: 130px;
    height: 130px;
    right: -48px;
    top: -65px;
    border-radius: 50%;
    background: rgba(240, 192, 64, 0.12);
    filter: blur(20px);
    pointer-events: none;
}
.checkin-streak-main { display: flex; align-items: baseline; gap: 7px; color: #f0c040; }
.checkin-streak-flame { align-self: center; font-size: 1.2rem; }
#checkin-streak-value { font-size: 2.25rem; font-weight: 800; line-height: 1.15; font-variant-numeric: tabular-nums; }
.checkin-streak-unit { font-size: 0.83rem; font-weight: 700; }
.checkin-streak-meta { display: flex; justify-content: space-between; gap: 8px; margin: 8px 0; font-size: 0.72rem; color: var(--text-sub); }
.checkin-progress { height: 6px; border-radius: 99px; overflow: hidden; background: rgba(240, 192, 64, 0.14); }
#checkin-progress-fill { height: 100%; width: 0; border-radius: inherit; background: linear-gradient(90deg, #bb8230, #ffe08a); transition: width 0.7s cubic-bezier(0.2, 0.8, 0.2, 1); }
.checkin-streak-celebrate { animation: checkinStreakGlow 0.85s ease-out both; }
.checkin-streak-celebrate .checkin-streak-flame { animation: checkinStarJump 0.7s ease-out both; }
@keyframes checkinStreakGlow {
    0% { box-shadow: 0 0 0 rgba(240, 192, 64, 0); }
    40% { box-shadow: 0 0 28px rgba(240, 192, 64, 0.45); }
    100% { box-shadow: 0 0 0 rgba(240, 192, 64, 0); }
}
@keyframes checkinStarJump {
    0% { transform: translateY(0) rotate(0); }
    40% { transform: translateY(-8px) rotate(20deg) scale(1.4); }
    100% { transform: translateY(0) rotate(0); }
}

/* 四格一列。第七天橫跨兩格 —— 它是這一輪的大獎，
   跟前面六天長一樣大的話看不出有什麼好期待的。 */
.checkin-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
}
.checkin-day {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-height: 74px;
    padding: 10px 4px;
    border: 1px solid #2a2a2a;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.02);
    transition: transform 0.2s, border-color 0.2s, background 0.2s;
}
.checkin-day-7 { grid-column: span 2; }
.checkin-day-label { font-size: 0.68rem; color: var(--text-sub); letter-spacing: 0.5px; }
.checkin-day-value { font-size: 0.95rem; font-weight: 700; color: var(--text-main); }
.checkin-day-unit { font-size: 0.6rem; color: var(--text-sub); }

/* 已領：打勾，整格壓暗，不要跟今天搶注意力 */
.checkin-day-done {
    border-color: rgba(76, 175, 80, 0.4);
    background: rgba(76, 175, 80, 0.07);
    opacity: 0.75;
}
.checkin-day-done .checkin-day-value { color: #7bc67e; }
.checkin-day-done::after {
    content: '✓';
    position: absolute;
    top: 5px; right: 7px;
    font-size: 0.7rem;
    font-weight: 700;
    color: #7bc67e;
}

/* 今天可領：發亮 + 呼吸。整個畫面就是要人點這一格 */
.checkin-day-today {
    border-color: #f0c040;
    background: rgba(240, 192, 64, 0.1);
    cursor: pointer;
    animation: checkinPulse 1.8s ease-in-out infinite;
}
.checkin-day-today .checkin-day-value { color: #f0c040; font-size: 1.05rem; }
.checkin-day-today .checkin-day-label { color: #f0c040; }
@keyframes checkinPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(240, 192, 64, 0.35); }
    50%      { box-shadow: 0 0 16px 2px rgba(240, 192, 64, 0.28); }
}

/* 剛領到的那一格：跳一下再落定 */
.checkin-day-claimed { animation: checkinPop 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) both; }
@keyframes checkinPop {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.14); }
    100% { transform: scale(1); }
}

.checkin-note {
    margin-top: 14px;
    font-size: 0.76rem;
    color: var(--text-sub);
    line-height: 1.7;
    text-align: center;
}
.checkin-note-warn { color: #d9b45c; }

.checkin-foot {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 20px calc(14px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border);
}
.checkin-points { flex: 1; min-width: 0; }
.checkin-points-label { display: block; font-size: 0.68rem; color: var(--text-sub); letter-spacing: 0.5px; }
.checkin-points-value {
    font-size: 1.25rem; font-weight: 700; color: var(--text-main);
    font-family: 'Courier New', Courier, monospace;
}
.checkin-foot .btn { width: auto; margin: 0; flex: 0 0 auto; padding: 13px 22px; font-weight: 700; }

/* 側邊欄那顆「還沒領」的紅點 */
.checkin-dot {
    display: inline-block;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: #e91e63;
    margin-left: 8px;
    vertical-align: middle;
    animation: checkinDot 1.6s ease-in-out infinite;
}
@keyframes checkinDot {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
    .checkin-day-today, .checkin-day-claimed, .checkin-dot { animation: none; }
    #checkin-overlay.show .checkin-box { animation: none; }
    .checkin-streak-celebrate, .checkin-streak-celebrate .checkin-streak-flame { animation: none; }
    #checkin-progress-fill { transition: none; }
}
html[data-fx="low"] .checkin-day-today,
html[data-fx="low"] .checkin-dot,
html[data-fx="low"] .checkin-streak-celebrate,
html[data-fx="low"] .checkin-streak-celebrate .checkin-streak-flame { animation: none; }
html[data-fx="low"] #checkin-progress-fill { transition: none; }

@media (max-width: 360px) {
    .checkin-grid { gap: 6px; }
    .checkin-day { min-height: 66px; padding: 8px 2px; }
    .checkin-day-value { font-size: 0.86rem; }
    .checkin-foot .btn { padding: 12px 16px; font-size: 0.85rem; }
}

/* 漢堡按鈕上的未領取提示。
   側邊欄裡那顆要打開選單才看得到，關掉簽到彈窗的人不會知道還有東西沒領。 */
.hdr-menu { position: relative; }
.hdr-dot {
    position: absolute;
    top: 4px; right: 4px;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: #e91e63;
    box-shadow: 0 0 0 2px var(--bg, #121212);
    animation: checkinDot 1.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .hdr-dot { animation: none; } }
html[data-fx="low"] .hdr-dot { animation: none; }

/* 拼圖的字母池：跟答案列一樣會縮，只是下限高一階（這排是要用手指點的）。
   原本固定 36px，結果七、八個字母的字在窄一點的手機上一定排不下 ——
   換行之後第二行常常只有一兩塊，位置每題都在跳，反而更難點。 */
.puzzle-pool-row {
    gap: var(--tile-gap, 8px);
}
.puzzle-pool-row .letter-tile {
    flex: 0 0 auto;
    width: var(--tile-size, 36px);
    height: var(--tile-size, 36px);
    font-size: calc(var(--tile-size, 36px) * 0.5);
    border-radius: calc(var(--tile-size, 36px) * 0.17);
}

/* The new mastery flow gives the unplaced letters a comfortable touch target.
   The answer row keeps its fitted size, so a picked letter visibly shrinks. */
.mastery-beta-active #mastery-puzzle-pool .letter-tile {
    width: 48px;
    height: 48px;
    font-size: 1.3rem;
    border-radius: 10px;
}

/* =========================================================
   加入主畫面的引導
   ---------------------------------------------------------
   iOS 沒有任何 API 可以叫出安裝，只能一步一步帶著做，
   所以這裡是圖文步驟，不是一顆按鈕。
   ========================================================= */
#install-overlay {
    position: fixed;
    inset: 0;
    z-index: 9600;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: rgba(0, 0, 0, 0.82);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 0.22s;
}
#install-overlay.show { opacity: 1; }
#install-overlay.hidden { display: none !important; }

.install-box {
    width: 100%;
    max-width: 440px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 20px 20px 0 0;
    padding: 22px 20px calc(18px + env(safe-area-inset-bottom));
    backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
}
#install-overlay.show .install-box {
    animation: addBookIn 0.3s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@media (min-width: 700px) {
    #install-overlay { align-items: center; padding: 24px; }
    .install-box { border-radius: 20px; }
}

.install-head { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; }
.install-icon {
    width: 52px; height: 52px; border-radius: 12px; flex-shrink: 0;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}
.install-title { font-size: 1.02rem; font-weight: 700; color: var(--text-main); letter-spacing: 0.5px; }
.install-sub { font-size: 0.78rem; color: var(--text-sub); margin-top: 3px; line-height: 1.5; }

.install-step {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 11px 0;
    border-top: 1px solid var(--border);
}
.install-step:first-child { border-top: none; }
.install-step-no {
    flex: 0 0 22px;
    width: 22px; height: 22px;
    border-radius: 50%;
    background: rgba(240, 192, 64, 0.15);
    border: 1px solid rgba(240, 192, 64, 0.5);
    color: #f0c040;
    font-size: 0.72rem; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
    margin-top: 1px;
}
.install-step-body {
    font-size: 0.88rem; color: var(--text-main); line-height: 1.7;
    min-width: 0;
}
.install-step-body strong { color: #f0c040; font-weight: 600; }
/* iOS 的分享圖示畫出來，不然「分享按鈕」四個字在一堆圖示裡還是找不到 */
.install-share-ico {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px;
    border: 1px solid var(--border); border-radius: 7px;
    color: #4da3ff;
    vertical-align: middle; margin: 0 2px;
}
.install-share-ico svg { width: 16px; height: 16px; }

.install-note {
    margin-top: 12px; padding: 10px 12px;
    background: rgba(240, 192, 64, 0.08);
    border: 1px solid rgba(240, 192, 64, 0.3);
    border-radius: 10px;
    font-size: 0.78rem; color: #d9b45c; line-height: 1.6;
}
.install-note.hidden { display: none; }

.install-foot { display: flex; align-items: center; gap: 10px; margin-top: 20px; }
.install-later {
    flex: 0 0 auto;
    background: transparent; border: 1px solid var(--border);
    color: var(--text-sub); font-family: inherit;
    border-radius: 999px; padding: 11px 16px;
    font-size: 0.84rem; cursor: pointer;
}
.install-foot .btn { flex: 1; margin: 0; padding: 12px 18px; font-weight: 600; }
.install-foot .btn.hidden { display: none; }

/* 每一步旁邊畫出那個按鈕長什麼樣子 */
.install-ico {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px;
    border: 1px solid var(--border); border-radius: 7px;
    color: #4da3ff;
    vertical-align: middle; margin: 0 2px;
}
.install-ico svg { width: 16px; height: 16px; }
.install-hint { display: block; margin-top: 3px; font-size: 0.76rem; color: var(--text-sub); line-height: 1.6; }
.install-hint strong { color: var(--text-main); }
.install-ios-steps.hidden { display: none; }
/* 手機橫拿、或多了提醒的時候說明會比畫面高：框不超出畫面，裡面自己捲 */
.install-box { max-height: calc(100dvh - 16px); overflow-y: auto; overscroll-behavior: contain; }

.install-more { margin-top: 8px; font-size: 0.8rem; color: var(--text-sub); }
.install-more summary {
    cursor: pointer; padding: 8px 0; color: #4da3ff; list-style: none;
}
.install-more summary::-webkit-details-marker { display: none; }
.install-more summary::after { content: ' ▾'; }
.install-more[open] summary::after { content: ' ▴'; }
.install-more ul { margin: 0; padding-left: 18px; line-height: 1.9; }
.install-more strong { color: var(--text-main); font-weight: 600; }

/* 按鈕在畫面下方的時候，說明框改放上面，下面留給指向工具列的箭頭 */
#install-overlay.install-top { align-items: flex-start; }
#install-overlay.install-top .install-box {
    border-radius: 0 0 20px 20px;
    padding-top: calc(18px + env(safe-area-inset-top));
    padding-bottom: 18px;
    max-height: calc(100dvh - 120px); overflow-y: auto;
}

/* 指著 Safari 真正的按鈕（在網頁外面的工具列上） */
#install-pointer {
    position: fixed; z-index: 9601; pointer-events: none;
    width: 44px; height: 44px; color: #f0c040;
    filter: drop-shadow(0 2px 8px rgba(0,0,0,0.6));
}
#install-pointer.hidden { display: none; }
#install-pointer svg { width: 100%; height: 100%; }
#install-pointer.at-bottom { left: calc(50% - 22px); bottom: calc(10px + env(safe-area-inset-bottom)); animation: installPointDown 1.1s ease-in-out infinite; }
#install-pointer.at-bottom-right { right: 18px; bottom: calc(10px + env(safe-area-inset-bottom)); animation: installPointDown 1.1s ease-in-out infinite; }
#install-pointer.at-top-right { right: 70px; top: calc(10px + env(safe-area-inset-top)); transform: rotate(180deg); animation: installPointUp 1.1s ease-in-out infinite; }
@keyframes installPointDown { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(9px); } }
@keyframes installPointUp { 0%, 100% { transform: rotate(180deg) translateY(0); } 50% { transform: rotate(180deg) translateY(9px); } }

@media (prefers-reduced-motion: reduce) {
    #install-overlay.show .install-box { animation: none; }
    #install-pointer { animation: none !important; }
}

/* ========================================================================
   英語文法專區
   ======================================================================== */

/* ── 首頁入口 ── */
.gm-home-btn {
    width: 100%; display: flex; align-items: center; gap: 14px;
    padding: 15px 16px; border-radius: 12px;
    background: linear-gradient(135deg, rgba(76, 175, 80, 0.10) 0%, rgba(240, 192, 64, 0.10) 100%);
    border: 1px solid rgba(76, 175, 80, 0.35);
    color: var(--text-main); font-family: inherit;
    cursor: pointer; transition: background 0.2s ease, transform 0.12s ease;
    text-align: left;
}
.gm-home-btn:hover {
    background: linear-gradient(135deg, rgba(76, 175, 80, 0.20) 0%, rgba(240, 192, 64, 0.20) 100%);
}
.gm-home-btn:active { transform: scale(0.985); }
.gm-home-icon { width: 26px; height: 26px; flex: 0 0 auto; color: #7fc47f; }
.gm-home-txt { font-size: 1rem; letter-spacing: 2px; font-weight: 600; }
.gm-home-sub {
    display: block; margin-top: 3px;
    font-size: 0.78rem; letter-spacing: 0.3px;
    font-weight: 400; color: var(--text-sub);
}

/* ── 主題列表 ── */
.gm-lead-top {
    font-size: 0.85rem; color: var(--text-sub);
    line-height: 1.7; margin-bottom: 18px;
}
.gm-list { display: flex; flex-direction: column; gap: 12px; }
.gm-card {
    display: flex; align-items: center; gap: 14px;
    width: 100%; padding: 18px 16px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-left: 3px solid var(--gm-c, var(--border));
    border-radius: 14px;
    color: var(--text-main); font-family: inherit;
    cursor: pointer; text-align: left;
    transition: border-color 0.18s ease, background 0.18s ease, transform 0.12s ease;
}
.gm-card:hover { background: rgba(255, 255, 255, 0.03); }
.gm-card:active { transform: scale(0.99); }
.gm-card-icon { flex: 0 0 auto; width: 30px; height: 30px; }
.gm-icon-svg { width: 100%; height: 100%; display: block; }
.gm-card-body { flex: 1; min-width: 0; }
.gm-card-title {
    font-size: 1.05rem; font-weight: 600;
    letter-spacing: 0.5px; margin-bottom: 4px;
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.gm-card-mp {
    font-size: 0.7rem; font-weight: 500; letter-spacing: 0.5px;
    color: var(--gm-c, var(--text-sub));
    border: 1px solid var(--gm-c, var(--border));
    border-radius: 8px; padding: 1px 8px; opacity: 0.85;
}
.gm-card-sub { font-size: 0.82rem; color: var(--text-sub); line-height: 1.5; }
.gm-card-go { color: var(--gm-c, var(--text-sub)); font-size: 1.4rem; font-weight: 300; }
.gm-card-done {
    flex: 0 0 auto; font-size: 0.72rem; letter-spacing: 0.5px;
    color: var(--success); border: 1px solid rgba(76, 175, 80, 0.5);
    border-radius: 999px; padding: 2px 9px;
}
.gm-soon {
    margin-top: 6px; font-size: 0.8rem; color: var(--text-sub);
    text-align: center; opacity: 0.7;
}
.gm-loading {
    padding: 40px 0; text-align: center;
    color: var(--text-sub); font-size: 0.9rem;
}

/* ── 一課的版面 ── */
.gm-lesson-body { padding-bottom: 30px; }

.gm-lead {
    border-left: 3px solid var(--gm-c, var(--border));
    padding: 4px 0 4px 16px; margin-bottom: 30px;
}
.gm-lead-badge {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 0.78rem; letter-spacing: 1px; font-weight: 600;
    color: var(--gm-c, var(--text-sub));
    border: 1px solid var(--gm-c, var(--border));
    border-radius: 999px; padding: 4px 12px 4px 9px;
    margin-bottom: 14px;
}
.gm-lead-badge .gm-icon-svg { width: 16px; height: 16px; }

.gm-p {
    font-size: 0.92rem; line-height: 1.85;
    color: var(--text-main); margin-bottom: 12px;
}
.gm-p:last-child { margin-bottom: 0; }
.gm-b { color: var(--gm-c, var(--text-main)); font-weight: 700; }
.gm-en {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.88em; background: rgba(255, 255, 255, 0.05);
    border-radius: 5px; padding: 1px 5px;
    overflow-wrap: anywhere;
}
.gm-mark {
    background: rgba(255, 255, 255, 0.10);
    background: color-mix(in srgb, var(--gm-c, #888) 18%, transparent);
    border-bottom: 2px solid var(--gm-c, #888);
    border-radius: 3px 3px 0 0; padding: 1px 3px;
}

.gm-sec { margin-bottom: 34px; }
.gm-sec-title {
    font-size: 1.05rem; font-weight: 600; letter-spacing: 0.5px;
    color: var(--text-main); margin-bottom: 4px;
    padding-left: 11px; border-left: 3px solid var(--gm-c, var(--border));
    line-height: 1.5;
}
.gm-sec-hint {
    font-size: 0.8rem; color: var(--text-sub);
    margin: 0 0 14px 14px;
}
.gm-sec-title + .gm-p,
.gm-sec-title + .gm-stage,
.gm-sec-title + .gm-branch,
.gm-sec-title + .gm-lab,
.gm-sec-title + .gm-trap,
.gm-sec-title + .gm-quiz { margin-top: 14px; }

/* ── 舞台 ── */
.gm-stage {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 14px; padding: 18px 14px 14px;
}
.gm-stage-canvas {
    position: relative;
    min-height: 96px;
    display: flex; align-items: center; justify-content: center;
    padding: 26px 4px 14px;
}
/* 這裡刻意「不要」position: relative。框是用 offsetLeft 去對位的，而
   offsetLeft 是相對於最近的定位祖先算的 —— 只要這一排變成定位元素，
   字就改以這一排為基準、框卻還以外層畫布為基準，兩邊差一個置中的位移，
   框就會整個偏到左邊去。 */
.gm-row {
    display: flex; flex-wrap: wrap;
    align-items: center; justify-content: center;
    gap: 8px 9px;
    font-size: 1.18rem;
}
.gm-break { flex-basis: 100%; height: 0; }
.gm-tok {
    display: inline-block;
    font-size: inherit; font-weight: 500; letter-spacing: 0.3px;
    color: var(--text-main);
    padding: 4px 2px;
    transition: transform 0.42s cubic-bezier(0.2, 0.7, 0.2, 1),
                color 0.3s ease, opacity 0.3s ease;
    will-change: transform;
}
.gm-tok-hi { color: var(--gm-c, var(--text-main)); font-weight: 700; }
.gm-tok-tape {
    color: var(--gm-c, var(--text-main)); font-weight: 700;
    background: rgba(255, 255, 255, 0.09);
    background: color-mix(in srgb, var(--gm-c, #888) 16%, transparent);
    border-radius: 7px; padding: 4px 0.42em;
}
.gm-tok-dim { color: var(--text-sub); opacity: 0.6; }
.gm-tok-bad {
    color: var(--error); text-decoration: line-through;
    text-decoration-thickness: 2px; opacity: 0.85;
}
.gm-tok-in { animation: gm-pop 0.34s ease both; }
@keyframes gm-pop {
    from { opacity: 0; transform: translateY(8px) scale(0.9); }
    to   { opacity: 1; transform: none; }
}

.gm-box {
    position: absolute; left: 0; top: 0;
    border: 2px dashed var(--gm-c, #888);
    border-radius: 10px;
    pointer-events: none;
    transition: left 0.42s cubic-bezier(0.2, 0.7, 0.2, 1),
                top 0.42s cubic-bezier(0.2, 0.7, 0.2, 1),
                width 0.42s cubic-bezier(0.2, 0.7, 0.2, 1),
                height 0.42s cubic-bezier(0.2, 0.7, 0.2, 1),
                opacity 0.3s ease;
}
.gm-box-label {
    position: absolute; left: 50%; top: -5px;
    transform: translate(-50%, -100%);
    color: var(--gm-c, var(--text-sub));
    font-size: 0.66rem; letter-spacing: 0.5px; font-weight: 600;
    white-space: nowrap;
}

.gm-cap {
    font-size: 0.88rem; line-height: 1.8;
    color: var(--text-main);
    min-height: 3.6em;
    padding: 0 4px;
}
.gm-cap-in { animation: gm-cap-rise 0.3s ease both; }
@keyframes gm-cap-rise {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
.gm-note {
    margin-top: 10px; padding: 9px 11px;
    background: rgba(255, 255, 255, 0.035);
    border-radius: 9px;
    font-size: 0.8rem; line-height: 1.7; color: var(--text-sub);
}
.gm-note.hidden { display: none; }

.gm-ctrl {
    display: flex; align-items: center; gap: 10px;
    margin-top: 14px; padding-top: 12px;
    border-top: 1px solid var(--border);
}
.gm-step-btn {
    flex: 0 0 auto;
    background: transparent; border: 1px solid var(--border);
    color: var(--text-sub); font-family: inherit;
    border-radius: 999px; padding: 8px 15px;
    font-size: 0.82rem; cursor: pointer;
    transition: border-color 0.18s ease, color 0.18s ease, transform 0.12s ease;
}
.gm-step-btn:active:not(:disabled) { transform: scale(0.96); }
.gm-step-btn:disabled { opacity: 0.35; cursor: default; }
.gm-step-next:not(:disabled) {
    border-color: var(--gm-c, var(--border));
    color: var(--gm-c, var(--text-main));
    font-weight: 600;
}
.gm-dots { flex: 1; display: flex; align-items: center; justify-content: center; gap: 7px; }
.gm-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--border); cursor: pointer;
    transition: background 0.2s ease, transform 0.2s ease;
}
.gm-dot-past {
    background: rgba(255, 255, 255, 0.3);
    background: color-mix(in srgb, var(--gm-c, #888) 45%, transparent);
}
.gm-dot-on { background: var(--gm-c, #888); transform: scale(1.5); }

/* ── 分支卡片 ── */
.gm-branch { display: flex; flex-direction: column; gap: 12px; }
.gm-bc {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px; padding: 15px 15px 13px;
}
.gm-bc-head {
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
    margin-bottom: 10px; padding-bottom: 9px;
    border-bottom: 1px solid var(--border);
}
.gm-bc-label {
    font-size: 1.05rem; font-weight: 700; letter-spacing: 0.3px;
    color: var(--gm-c, var(--text-main));
}
.gm-bc-sub { font-size: 0.8rem; color: var(--text-sub); }
.gm-bc-p {
    font-size: 0.86rem; line-height: 1.8;
    color: var(--text-main); margin-bottom: 6px;
}
.gm-bc-p:last-child { margin-bottom: 0; }

/* ── 例句實驗室 ── */
.gm-lab {
    position: relative;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px; padding: 15px 52px 13px 15px;
    margin-bottom: 12px;
}
.gm-lab-en {
    font-size: 1.05rem; line-height: 1.7; font-weight: 500;
    color: var(--text-main); overflow-wrap: anywhere;
}
.gm-lab-zh {
    margin-top: 6px; font-size: 0.85rem; color: var(--text-sub);
}
.gm-lab-notes {
    margin: 11px 0 0; padding: 10px 0 0 18px;
    border-top: 1px solid var(--border);
    list-style: none;
}
.gm-lab-notes li {
    position: relative;
    font-size: 0.82rem; line-height: 1.75;
    color: var(--text-sub); margin-bottom: 4px;
}
.gm-lab-notes li:last-child { margin-bottom: 0; }
.gm-lab-notes li::before {
    content: ''; position: absolute; left: -13px; top: 0.72em;
    width: 5px; height: 5px; border-radius: 50%;
    background: var(--gm-c, var(--text-sub)); opacity: 0.7;
}
.gm-say {
    position: absolute; top: 12px; right: 12px;
    width: 30px; height: 30px; border-radius: 50%;
    background: transparent; border: 1px solid var(--border);
    color: var(--text-sub); font-family: inherit; font-size: 0.78rem;
    cursor: pointer; line-height: 1;
    transition: border-color 0.18s ease, color 0.18s ease, transform 0.12s ease;
}
.gm-say:hover { border-color: var(--gm-c, var(--border)); color: var(--gm-c, var(--text-main)); }
.gm-say:active { transform: scale(0.92); }

/* ── 陷阱區 ── */
.gm-trap {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px; padding: 14px 15px;
    margin-bottom: 12px;
}
.gm-trap-line { display: flex; align-items: flex-start; gap: 9px; margin-bottom: 6px; }
.gm-trap-mark {
    flex: 0 0 auto; width: 17px;
    display: flex; align-items: center; justify-content: center;
    height: 1.6em;
}
.gm-mark-svg { width: 13px; height: 13px; display: block; }
.gm-trap-bad .gm-trap-mark { color: var(--error); }
.gm-trap-good .gm-trap-mark { color: var(--success); }
.gm-trap-txt {
    font-size: 0.95rem; line-height: 1.6; overflow-wrap: anywhere;
}
.gm-trap-bad .gm-trap-txt { color: var(--text-sub); text-decoration: line-through; }
.gm-trap-good .gm-trap-txt { color: var(--text-main); font-weight: 500; }
.gm-trap-why {
    margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--border);
    font-size: 0.82rem; line-height: 1.75; color: var(--text-sub);
}

/* ── 小測驗 ── */
.gm-quiz {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px; padding: 15px;
    margin-bottom: 12px;
}
.gm-q {
    font-size: 0.95rem; line-height: 1.7;
    color: var(--text-main); margin-bottom: 12px;
    overflow-wrap: anywhere;
}
.gm-opts { display: flex; flex-direction: column; gap: 8px; }
.gm-opt {
    width: 100%; text-align: left;
    background: transparent; border: 1px solid var(--border);
    color: var(--text-main); font-family: inherit;
    border-radius: 10px; padding: 11px 13px;
    font-size: 0.9rem; line-height: 1.5; cursor: pointer;
    overflow-wrap: anywhere;
    transition: border-color 0.18s ease, background 0.18s ease, transform 0.12s ease;
}
.gm-opt:active:not(:disabled) { transform: scale(0.985); }
.gm-opt:disabled { cursor: default; }
.gm-opt-right {
    border-color: var(--success); color: var(--success);
    background: rgba(76, 175, 80, 0.10); font-weight: 600;
    animation: gm-right 0.34s ease;
}
.gm-opt-wrong {
    border-color: var(--error); color: var(--error);
    background: rgba(244, 67, 54, 0.08);
}
@keyframes gm-right {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.03); }
    100% { transform: scale(1); }
}
.gm-why {
    margin-top: 11px; padding: 10px 12px;
    background: rgba(255, 255, 255, 0.035);
    border-radius: 9px;
    font-size: 0.82rem; line-height: 1.8; color: var(--text-sub);
    animation: gm-cap-rise 0.28s ease both;
}
.gm-why.hidden { display: none; }

.gm-end { margin-top: 26px; text-align: center; }
.gm-end-btn { letter-spacing: 1px; }

@media (prefers-reduced-motion: reduce) {
    .gm-tok, .gm-box { transition: none; }
    .gm-tok-in, .gm-cap-in, .gm-opt-right, .gm-why { animation: none; }
}

/* ========================================================================
   單字簿語言（牌位積分只計算英文）
   ======================================================================== */
.lang-pick {
    display: flex; align-items: center; gap: 8px;
    margin: 12px 0 14px; flex-wrap: wrap;
}
.lang-pick-label {
    font-size: 0.82rem; color: var(--text-sub); letter-spacing: 0.5px;
}
.lang-opt {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-sub);
    font-family: inherit; font-size: 0.82rem;
    border-radius: 999px; padding: 6px 14px;
    cursor: pointer;
    transition: border-color 0.18s ease, color 0.18s ease,
                background 0.18s ease, transform 0.12s ease;
}
.lang-opt:active { transform: scale(0.96); }
.lang-opt.on {
    border-color: var(--text-main);
    color: var(--text-main);
    background: rgba(255, 255, 255, 0.06);
    font-weight: 600;
}
.lang-pick .help-icon { margin-left: 0; }

/* 單字簿列表上的標記。只有「其他語言」會出現 —— 英文是預設，
   每一本都掛一個「英文」反而變成一整排噪音。 */
.book-lang-chip {
    display: inline-block; margin-left: 8px;
    font-size: 0.68rem; letter-spacing: 0.5px;
    color: var(--warning);
    border: 1px solid rgba(255, 152, 0, 0.45);
    border-radius: 999px; padding: 1px 8px;
    vertical-align: middle; white-space: nowrap;
}

/* ========================================================================
   排位賽
   ======================================================================== */

/* ── 段位徽章 ── */
/*
 * 徽章一律是正方形（見 rankui.js 的 emblem）。放徽章的容器也都是
 * 正方形，寬高相同 —— 上一版讓長翅膀的徽章變寬 1.69 倍，首頁那張
 * 小卡的徽章就壓到旁邊的字上了。
 */
.rk-emblem { display: block; width: 100%; height: 100%; }

/* 粒子。只是很輕的呼吸，不是特效表演 —— 徽章會出現在排行榜那種
   一次十幾個的地方，抖動會讓整頁看起來很吵。 */
.rk-sparks circle { animation: rk-spark 2.8s ease-in-out infinite; transform-origin: center; }
@keyframes rk-spark {
    0%, 100% { opacity: 0.25; }
    50%      { opacity: 1; }
}

.rk-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-top: 3px solid var(--rk-c, var(--border));
    border-radius: 16px;
    padding: 24px 18px 20px;
    text-align: center;
}
.rk-badge-big {
    width: 116px; height: 116px; margin: 0 auto 12px;
    filter: drop-shadow(0 6px 18px color-mix(in srgb, var(--rk-c, #888) 35%, transparent));
}
.rk-tier-name {
    font-size: 1.5rem; font-weight: 700; letter-spacing: 3px;
    color: var(--rk-c, var(--text-main));
}
.rk-rating {
    margin-top: 4px; font-size: 0.95rem; color: var(--text-sub);
    font-family: 'Courier New', Courier, monospace; letter-spacing: 1px;
}
.rk-bar {
    margin: 16px auto 8px; max-width: 280px;
    height: 8px; border-radius: 999px;
    background: rgba(255, 255, 255, 0.07);
    overflow: hidden;
}
.rk-bar-fill {
    height: 100%; width: 0;
    background: var(--rk-c, #888);
    border-radius: 999px;
    transition: width 0.7s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.rk-next { font-size: 0.78rem; color: var(--text-sub); }
.rk-meta {
    margin-top: 16px; padding-top: 14px;
    border-top: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center; gap: 12px;
    font-size: 0.85rem; color: var(--text-sub); flex-wrap: wrap;
}
.rk-streak { font-size: 0.78rem; border-radius: 999px; padding: 2px 10px; }
.rk-streak:empty { display: none; }
.rk-streak-win { color: var(--success); border: 1px solid rgba(76, 175, 80, 0.5); }
.rk-streak-lose { color: var(--error); border: 1px solid rgba(244, 67, 54, 0.45); }
.rk-countdown { margin-top: 10px; font-size: 0.78rem; color: var(--text-sub); }

.rk-placement {
    margin-top: 14px; padding: 12px 14px;
    background: rgba(240, 192, 64, 0.08);
    border: 1px solid rgba(240, 192, 64, 0.3);
    border-radius: 10px;
    font-size: 0.8rem; line-height: 1.7; color: #d9b45c;
}
.rk-placement.hidden { display: none; }
.rk-tiers-open { display:block; width:100%; margin-top:16px; }
/* 「段位」與「獎勵」併一行。頁面上已經有兩顆全寬按鈕，再加第三顆
   就是玩家說的「太雜亂」—— 這兩顆都是「去看東西」，本來就同一類。 */
.rk-sub-row { display: flex; gap: 10px; margin-top: 16px; }
.rk-sub-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 11px 8px;
    line-height: 1.25;
}
.rk-sub-k { font-size: 0.92rem; font-weight: 700; letter-spacing: 1px; }
.rk-sub-v { font-size: 0.7rem; letter-spacing: 0.5px; color: var(--text-sub); }

/* 獎勵清單。一階一列：徽章、名稱、拿到沒有。 */
.rk-rewards { display: flex; flex-direction: column; gap: 10px; }
.rk-reward {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 14px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.03);
}
.rk-reward-art { flex: none; display: grid; place-items: center; width: 48px; height: 48px; }
.rk-reward-body { flex: 1; min-width: 0; }
.rk-reward-name { font-size: 0.95rem; font-weight: 700; letter-spacing: 1px; }
.rk-reward-sub { font-size: 0.74rem; letter-spacing: 0.3px; color: var(--text-sub); margin-top: 2px; }
.rk-reward-act { flex: none; }
/* 還沒拿到的：壓暗，但看得到長什麼樣 —— 看不到的目標不會讓人想爬。 */
.rk-reward.is-locked .rk-reward-art { opacity: 0.32; filter: grayscale(0.8); }
.rk-reward.is-locked .rk-reward-name { color: var(--text-sub); }
.rk-reward.is-owned { border-color: color-mix(in srgb, var(--rk-c, #888) 55%, transparent); }
.rk-reward-tag {
    font-size: 0.72rem;
    letter-spacing: 0.5px;
    padding: 4px 10px;
    border-radius: 999px;
    border: 1px solid currentColor;
    color: var(--text-sub);
    background: none;
}
.rk-reward.is-owned .rk-reward-tag { color: var(--rk-c, #f0c040); cursor: pointer; }
/* 還沒拿到的也能先看：按鈕照樣按得到，只是顏色淡一點 */
.rk-reward.is-locked .rk-reward-tag { cursor: pointer; }
.rk-reward.is-locked .rk-reward-tag:hover { color: var(--text-main); }
.rk-tiers-dialog {
    box-sizing:border-box; width:min(440px,calc(100vw - 28px)); max-height:min(780px,85vh);
    padding:20px; overflow-y:auto; border:1px solid var(--border); border-radius:20px;
    background:var(--bg-color,#111); color:var(--text-main); box-shadow:0 20px 60px #0009;
}
.rk-tiers-dialog::backdrop { background:#000b; }
.rk-tiers-head { display:flex; justify-content:space-between; align-items:center; gap:12px; margin-bottom:14px; }
.rk-tiers-head h2 { margin:0 0 3px; font-size:1.3rem; }
.rk-tiers-head p, .rk-tiers-note { margin:0; color:var(--text-sub); font-size:.79rem; line-height:1.5; }
.rk-tiers-close { flex:0 0 44px; width:44px; height:44px; border:1px solid var(--border); border-radius:12px; background:var(--card-bg); color:var(--text-main); font-size:1.6rem; cursor:pointer; }
.rk-tiers-list { display:grid; gap:8px; }
.rk-tiers-row { display:flex; align-items:center; gap:14px; min-height:66px; padding:7px 13px; border:1px solid var(--border); border-left:3px solid var(--rk-tier-c); border-radius:12px; background:var(--card-bg); }
.rk-tiers-row.rk-tiers-current { background:color-mix(in srgb,var(--rk-tier-c) 12%,var(--bg-color)); }
.rk-tiers-icon { width:56px; height:56px; flex:0 0 56px; }
.rk-tiers-words { min-width:0; }
.rk-tiers-name { color:var(--rk-tier-c); font-size:.98rem; font-weight:700; }
.rk-tiers-score { margin-top:4px; color:var(--text-sub); font-size:.8rem; }
.rk-tiers-note { margin-top:14px; }
.rk-play { width: 100%; margin-top: 18px; letter-spacing: 2px; }
.rk-topics { display: flex; align-items: center; gap: 8px; margin-top: 16px; flex-wrap: wrap; }
.rk-topics-k { font-size: 0.8rem; color: var(--text-sub); letter-spacing: 1px; margin-right: 2px; }
.rk-topic {
    flex: 1; min-width: 64px; padding: 8px 10px; border-radius: 999px; cursor: pointer;
    border: 1px solid rgba(255, 255, 255, 0.16); background: transparent; color: var(--text-sub);
    font-size: 0.85rem; letter-spacing: 1px; transition: background .15s, color .15s, border-color .15s;
}
.rk-topic[aria-pressed="true"] { border-color: var(--accent); background: rgba(255, 255, 255, 0.1); color: var(--text, #fff); font-weight: 700; }
.rk-daily { margin-top: 8px; text-align: center; font-size: 0.76rem; color: var(--text-sub); }
.rk-lb-btn { width: 100%; margin-top: 14px; }
.rk-error {
    margin-bottom: 14px; padding: 12px 14px;
    border: 1px solid rgba(244, 67, 54, 0.4); border-radius: 10px;
    color: var(--error); font-size: 0.82rem;
}
.rk-error.hidden { display: none; }

/* ── 結果畫面上的分數變化 ── */
.rk-delta {
    margin: 4px 0 14px; padding: 14px;
    background: rgba(255, 255, 255, 0.035);
    border: 1px solid var(--border);
    border-radius: 12px;
}
.rk-delta.hidden { display: none; }
.rk-delta-wait { font-size: 0.82rem; color: var(--text-sub); text-align: center; }
.rk-delta-head { display: flex; align-items: center; gap: 10px; }
.rk-delta-badge { width: 36px; height: 36px; flex: 0 0 auto; }
.rk-delta-tier {
    flex: 1; text-align: left;
    font-size: 0.95rem; font-weight: 600; letter-spacing: 1px;
    color: var(--rk-c, var(--text-main));
}
.rk-delta-num {
    font-size: 1.3rem; font-weight: 700;
    font-family: 'Courier New', Courier, monospace;
}
.rk-delta-num.rk-up { color: var(--success); }
.rk-delta-num.rk-down { color: var(--error); }
.rk-delta-num.rk-flat { color: var(--text-sub); }
.rk-delta-bar {
    margin: 12px 0 8px; height: 7px; border-radius: 999px;
    background: rgba(255, 255, 255, 0.07); overflow: hidden;
}
.rk-delta-fill {
    height: 100%; width: 0; border-radius: 999px;
    background: var(--rk-c, #888);
    transition: width 0.9s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.rk-delta-foot { font-size: 0.75rem; color: var(--text-sub); }
.rk-delta-note {
    margin-top: 8px; font-size: 0.75rem; line-height: 1.6;
    color: var(--warning);
}

/* ── 升降階：全螢幕 ── */
.rk-promo {
    position: fixed; inset: 0; z-index: 9000;
    display: flex; align-items: center; justify-content: center;
    /* 幾乎全遮：底下那張排位卡本身很亮，遮不夠的話升階畫面會跟它打架 */
    background: rgba(0, 0, 0, 0.95);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    opacity: 0; transition: opacity 0.26s ease;
    padding: 24px;
}
.rk-promo.hidden { display: none; }
.rk-promo.show { opacity: 1; }
.rk-promo-box { position: relative; text-align: center; max-width: 340px; }

/* 光芒只在升階時出現。降階已經夠難受了，不需要再被煙火慶祝一次。 */
.rk-rays {
    position: absolute; left: 50%; top: 66px;
    width: 340px; height: 340px; margin: -170px 0 0 -170px;
    background: conic-gradient(from 0deg,
        color-mix(in srgb, var(--rk-c, #888) 42%, transparent) 0deg 6deg, transparent 6deg 30deg);
    border-radius: 50%;
    -webkit-mask-image: radial-gradient(circle, #000 18%, transparent 62%);
    mask-image: radial-gradient(circle, #000 18%, transparent 62%);
    animation: rk-spin 9s linear infinite, rk-rays-in 0.7s ease both;
    pointer-events: none;
}
@keyframes rk-spin { to { transform: rotate(360deg); } }
@keyframes rk-rays-in { from { opacity: 0; transform: scale(0.5); } to { opacity: 1; transform: scale(1); } }

.rk-promo-badge { position: relative; width: 140px; height: 140px; margin: 0 auto 18px; }
.rk-promo-up .rk-promo-badge {
    animation: rk-badge-up 0.72s cubic-bezier(0.18, 1.3, 0.34, 1) both;
    filter: drop-shadow(0 0 26px color-mix(in srgb, var(--rk-c, #888) 55%, transparent));
}
.rk-promo-down .rk-promo-badge {
    animation: rk-badge-down 0.6s ease both;
    filter: grayscale(0.4);
}
@keyframes rk-badge-up {
    0%   { opacity: 0; transform: scale(0.3) translateY(40px); }
    60%  { opacity: 1; transform: scale(1.12) translateY(0); }
    100% { opacity: 1; transform: scale(1); }
}
@keyframes rk-badge-down {
    0%   { opacity: 0; transform: scale(1.1) translateY(-18px); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}

.rk-promo-kicker {
    font-size: 0.85rem; letter-spacing: 8px; font-weight: 600;
    color: var(--rk-c, #888);
    animation: rk-fade-up 0.5s ease 0.34s both;
}
.rk-promo-down .rk-promo-kicker { color: var(--text-sub); }
.rk-promo-tier {
    margin-top: 6px;
    font-size: 2rem; font-weight: 700; letter-spacing: 4px;
    color: var(--text-main);
    animation: rk-fade-up 0.5s ease 0.44s both;
}
.rk-promo-sub {
    margin-top: 8px; font-size: 0.85rem; color: var(--text-sub);
    font-family: 'Courier New', Courier, monospace;
    animation: rk-fade-up 0.5s ease 0.54s both;
}
@keyframes rk-fade-up {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
}
.rk-promo-ok {
    margin-top: 26px;
    background: transparent; border: 1px solid var(--rk-c, var(--border));
    color: var(--rk-c, var(--text-main));
    font-family: inherit; font-size: 0.9rem; letter-spacing: 2px;
    border-radius: 999px; padding: 11px 32px; cursor: pointer;
    animation: rk-fade-up 0.5s ease 0.68s both;
}
.rk-promo-down .rk-promo-ok { border-color: var(--border); color: var(--text-sub); }

/* ── 排位排行榜 ── */
.rk-lb-list { display: flex; flex-direction: column; gap: 8px; }
.rk-lb-loading { padding: 40px 0; text-align: center; color: var(--text-sub); font-size: 0.9rem; }
.rk-lb-row {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 14px;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 12px;
}
.rk-lb-me { border-color: var(--text-main); }
.rk-lb-rank {
    width: 26px; text-align: center; flex: 0 0 auto;
    font-size: 0.9rem; color: var(--text-sub);
    font-family: 'Courier New', Courier, monospace;
}
.rk-lb-badge { width: 28px; height: 28px; flex: 0 0 auto; }
.rk-lb-info { flex: 1; min-width: 0; }
.rk-lb-name {
    font-size: 0.95rem; color: var(--text-main);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rk-lb-tier { font-size: 0.72rem; color: var(--text-sub); margin-top: 2px; }
.rk-lb-rating {
    font-size: 1.05rem; font-weight: 700;
    font-family: 'Courier New', Courier, monospace;
    color: var(--text-main);
}

/* 紀錄對手的標籤：要跟「線上玩家」明顯不一樣，不能讓人以為在跟真人打 */
.qk-vs-ghost {
    color: var(--warning) !important;
    border-color: rgba(255, 152, 0, 0.5) !important;
}

@media (prefers-reduced-motion: reduce) {
    .rk-rays { animation: none; }
    .rk-promo-badge, .rk-promo-kicker, .rk-promo-tier, .rk-promo-sub, .rk-promo-ok { animation: none; }
    .rk-bar-fill, .rk-delta-fill { transition: none; }
    .rk-sparks circle { animation: none; opacity: 0.75; }
    .rk-aura { animation: none; }
}

/* 排位賽的段位徽章（個人頁的榮譽徽章格） */
.badge-ranked {
    width: 60px; height: 60px; border-radius: 50%;
    border: 2px solid var(--rk-c, #888);
    background: color-mix(in srgb, var(--rk-c, #888) 14%, transparent);
    box-shadow: 0 0 12px color-mix(in srgb, var(--rk-c, #888) 22%, transparent);
    display: flex; flex-direction: column;
    justify-content: center; align-items: center; gap: 1px;
}
.badge-ranked-emblem { width: 32px; height: 32px; }
.badge-ranked-season {
    font-size: 0.62rem; font-weight: 700; letter-spacing: 1px;
    color: var(--rk-c, #888);
}

/* 新賽季第一次打開：解釋分數為什麼跟上一季不一樣 */
.rk-carry {
    margin-top: 14px; padding: 12px 14px;
    background: rgba(255, 255, 255, 0.035);
    border: 1px solid var(--border);
    border-radius: 10px;
    font-size: 0.8rem; line-height: 1.75; color: var(--text-sub);
}
.rk-carry.hidden { display: none; }

.rk-retry {
    display: block; margin: 12px auto 0;
    background: transparent; border: 1px solid var(--border);
    color: var(--text-sub); font-family: inherit;
    border-radius: 999px; padding: 7px 20px;
    font-size: 0.82rem; cursor: pointer;
}
.rk-retry:active { transform: scale(0.96); }

/* ========================================================================
   每日複習
   ======================================================================== */

/* ── 首頁入口 ── */
.rv-entry {
    width: 100%; display: flex; align-items: center; gap: 12px;
    padding: 16px 18px; margin-bottom: 14px;
    border-radius: 14px;
    background: rgba(0, 188, 212, 0.08);
    border: 1px solid rgba(0, 188, 212, 0.32);
    color: var(--text-main); font-family: inherit;
    cursor: pointer; text-align: left;
    transition: background 0.2s ease, transform 0.12s ease;
}
.rv-entry:hover { background: rgba(0, 188, 212, 0.16); }
.rv-entry:active { transform: scale(0.985); }
.rv-entry.hidden { display: none; }
.rv-entry-dot {
    width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
    background: #00bcd4;
    box-shadow: 0 0 0 0 rgba(0, 188, 212, 0.55);
    animation: rv-pulse 2.4s ease-out infinite;
}
@keyframes rv-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(0, 188, 212, 0.5); }
    70%  { box-shadow: 0 0 0 9px rgba(0, 188, 212, 0); }
    100% { box-shadow: 0 0 0 0 rgba(0, 188, 212, 0); }
}
.rv-entry-txt { flex: 1; font-size: 0.98rem; letter-spacing: 1px; font-weight: 600; }
.rv-entry-sub {
    display: block; margin-top: 3px;
    font-size: 0.78rem; font-weight: 400; letter-spacing: 0.3px;
    color: var(--text-sub);
}
.rv-entry-go { color: #00bcd4; font-size: 1.3rem; font-weight: 300; }

/* ── 複習畫面（第三版：遊戲化）── */
.rv-view { --rv-a: #00bcd4; --rv-b: #9c6bff; --rv-c: #ff9800; --rv-d: #ffc107; --rv-m: #ffca28; position: relative; }
.rv-tier-a { --gem: var(--rv-a, #00bcd4); }
.rv-tier-b { --gem: var(--rv-b, #9c6bff); }
.rv-tier-c { --gem: var(--rv-c, #ff9800); }
.rv-tier-d { --gem: var(--rv-d, #ffc107); }
.rv-tier-m { --gem: var(--rv-m, #ffca28); }
.rv-nav-right { display: flex; align-items: center; gap: 10px; }
.rv-progress {
    color: var(--text-sub); font-size: 0.85rem;
    font-family: 'Courier New', Courier, monospace; letter-spacing: 1px;
}
.rv-points { color: #ffca28; font-weight: 700; font-size: 0.88rem; font-family: 'Courier New', Courier, monospace; min-width: 0; }
.rv-points:empty { display: none; }
.rv-points-pop { animation: rv-pop 0.35s ease; }
.rv-combo {
    font-size: 0.78rem; font-weight: 700; letter-spacing: 1px; color: #ff9800;
    padding: 2px 8px; border-radius: 999px; border: 1px solid transparent;
    opacity: 0; transition: opacity 0.3s ease;
}
.rv-combo-on { opacity: 1; border-color: rgba(255, 152, 0, 0.45); background: rgba(255, 152, 0, 0.1); }
.rv-combo-hot { color: #ff5722; border-color: rgba(255, 87, 34, 0.6); background: rgba(255, 87, 34, 0.14); box-shadow: 0 0 12px rgba(255, 87, 34, 0.35); }
.rv-combo-off { opacity: 0; }
.rv-combo-pop { animation: rv-pop 0.32s cubic-bezier(.3, 1.6, .5, 1); }
.rv-info-btn {
    width: 28px; height: 28px; border-radius: 50%; flex: 0 0 auto;
    border: 1px solid var(--border); background: rgba(255, 255, 255, 0.04);
    color: var(--text-sub); font: inherit; font-weight: 700; font-size: 0.9rem; cursor: pointer;
}
.rv-info-btn:hover { color: var(--text-main); border-color: #00bcd4; }

.rv-bar {
    height: 6px; border-radius: 999px;
    background: rgba(255, 255, 255, 0.07);
    overflow: hidden; margin-bottom: 22px; position: relative;
}
.rv-bar-fill {
    height: 100%; width: 0; border-radius: 999px;
    background: linear-gradient(90deg, #00bcd4, #7c4dff, #00bcd4);
    background-size: 200% 100%;
    animation: rv-flow 3s linear infinite;
    transition: width 0.45s cubic-bezier(0.2, 0.7, 0.2, 1);
}
@keyframes rv-flow { to { background-position: -200% 0; } }

/* 開場 */
.rv-intro { text-align: center; padding: 18px 4px 10px; animation: rv-rise-k 0.35s ease both; }
.rv-intro-kicker { font-size: 0.8rem; letter-spacing: 4px; color: #00bcd4; }
.rv-intro-big { margin-top: 10px; font-size: 3.6rem; font-weight: 800; line-height: 1; color: var(--text-main); font-family: 'Courier New', Courier, monospace; }
.rv-intro-big small { font-size: 1rem; font-weight: 500; margin-left: 6px; color: var(--text-sub); font-family: inherit; }
.rv-intro-time { margin-top: 8px; color: var(--text-sub); font-size: 0.9rem; }
.rv-intro-tiles { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 26px auto 14px; max-width: 420px; }
.rv-tile {
    width: 18px; height: 18px; border-radius: 5px;
    background: color-mix(in srgb, var(--gem) 70%, transparent);
    box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.25), 0 0 8px color-mix(in srgb, var(--gem) 35%, transparent);
    animation: rv-tile-in 0.35s cubic-bezier(.3, 1.5, .5, 1) both;
}
.rv-tile-boss { outline: 2px solid #ffca28; outline-offset: 1px; }
@keyframes rv-tile-in { from { opacity: 0; transform: translateY(14px) scale(0.4); } to { opacity: 1; transform: none; } }
.rv-tiles-fly .rv-tile { animation: rv-tile-fly 0.4s cubic-bezier(.5, 0, .8, .3) both; animation-delay: 0s !important; }
.rv-tiles-fly .rv-tile:nth-child(3n) { animation-delay: 40ms !important; }
.rv-tiles-fly .rv-tile:nth-child(3n+1) { animation-delay: 80ms !important; }
@keyframes rv-tile-fly { to { opacity: 0; transform: translateY(-160px) scale(0.3); } }
.rv-intro-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 14px; font-size: 0.8rem; color: var(--text-sub); }
.rv-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.rv-legend-dot { width: 10px; height: 10px; border-radius: 3px; background: var(--gem); }
.rv-intro-note { margin: 20px auto 0; max-width: 360px; font-size: 0.82rem; line-height: 1.7; color: var(--text-sub); }
.rv-intro-go { width: 100%; max-width: 420px; min-height: 54px; margin: 22px auto 0; display: block; }

/* 卡片：有厚度、會翻 */
.rv-scene { perspective: 1100px; margin-bottom: 14px; }
.rv-card {
    position: relative;
    background: linear-gradient(180deg, color-mix(in srgb, var(--card-bg) 88%, #fff 12%), var(--card-bg));
    border: 1px solid var(--border);
    border-radius: 18px;
    padding: 14px 16px 24px;
    text-align: center;
    box-shadow: 0 6px 0 color-mix(in srgb, var(--border) 80%, #000 20%), 0 16px 30px rgba(0, 0, 0, 0.28);
    transform-style: preserve-3d;
    backface-visibility: hidden;
}
.rv-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 18px; text-align: left; }
.rv-card-step { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rv-step { font-size: 0.82rem; font-weight: 700; color: var(--text-main); letter-spacing: 0.5px; }
.rv-step-name { font-size: 0.72rem; color: var(--text-sub); letter-spacing: 1px; }
.rv-tag {
    font-size: 0.7rem; font-weight: 700; color: #ff5252; letter-spacing: 1px;
    border: 1px solid rgba(255, 82, 82, 0.5); background: rgba(255, 82, 82, 0.1);
    padding: 2px 8px; border-radius: 999px; white-space: nowrap;
}
.rv-card-level { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.rv-gems { display: inline-flex; gap: 4px; }
.rv-gem {
    width: 12px; height: 12px; transform: rotate(45deg); border-radius: 3px;
    border: 1px solid color-mix(in srgb, var(--gem) 55%, transparent);
    background: transparent;
}
.rv-gem.on { background: var(--gem); box-shadow: 0 0 8px color-mix(in srgb, var(--gem) 60%, transparent); border-color: var(--gem); }
.rv-gem.now { animation: rv-breathe 1.6s ease-in-out infinite; }
.rv-gem-up { animation: rv-gem-up 0.6s cubic-bezier(.3, 1.8, .5, 1) both !important; }
.rv-gem-shake { animation: rv-gem-shake 0.45s ease both !important; }
@keyframes rv-breathe { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--gem) 0%, transparent); } 50% { box-shadow: 0 0 10px 1px color-mix(in srgb, var(--gem) 70%, transparent); } }
@keyframes rv-gem-up { 0% { transform: rotate(45deg) scale(0.3); } 60% { transform: rotate(225deg) scale(1.6); } 100% { transform: rotate(405deg) scale(1); } }
@keyframes rv-gem-shake { 0%, 100% { transform: rotate(45deg); } 25% { transform: rotate(45deg) translateX(-3px); } 75% { transform: rotate(45deg) translateX(3px); } }
.rv-level { font-size: 0.68rem; color: var(--text-sub); letter-spacing: 0.5px; }

.rv-phase { font-size: 0.8rem; letter-spacing: 2px; color: var(--text-sub); margin-bottom: 12px; min-height: 1.2em; }
.rv-word {
    font-size: 2.3rem; font-weight: 700; letter-spacing: 0.5px;
    color: var(--text-main); overflow-wrap: anywhere; min-height: 1.3em;
}
.rv-ch { display: inline-block; white-space: pre; animation: rv-ch-in 0.32s cubic-bezier(.3, 1.4, .5, 1) both; }
@keyframes rv-ch-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.rv-word-zh { font-size: 1.5rem; font-weight: 600; line-height: 1.45; animation: rv-rise-k 0.3s ease both; }
.rv-word-ear { display: flex; justify-content: center; }
.rv-ear {
    position: relative; width: 84px; height: 84px; border-radius: 50%;
    border: 2px solid #00bcd4; background: rgba(0, 188, 212, 0.1); cursor: pointer;
    display: grid; place-items: center;
}
.rv-ear-icon {
    width: 30px; height: 30px; background: #00bcd4;
    clip-path: polygon(0 32%, 30% 32%, 62% 4%, 62% 96%, 30% 68%, 0 68%);
    margin-left: -6px;
}
.rv-ear-icon::after { content: ''; }
.rv-ear-ring { position: absolute; inset: -2px; border-radius: 50%; border: 2px solid #00bcd4; animation: rv-ring 1.8s ease-out infinite; }
.rv-ear-play { animation: rv-pop 0.3s ease; }
@keyframes rv-ring { from { transform: scale(1); opacity: 0.7; } to { transform: scale(1.6); opacity: 0; } }
.rv-pos { margin-top: 10px; color: var(--warning); font-size: 0.82rem; }
.rv-hear {
    margin-top: 12px; border: 1px solid var(--border); border-radius: 999px; padding: 7px 14px;
    background: rgba(255, 255, 255, 0.04); color: var(--text-sub); font: inherit; font-size: 0.82rem; cursor: pointer;
}

/* 換卡：翻牌 */
.rv-deal-in { animation: rv-deal 0.42s cubic-bezier(.2, .9, .3, 1.1) both; }
.rv-flip-out { animation: rv-flip-out 0.18s ease-in both; }
.rv-flip-in { animation: rv-flip-in 0.34s cubic-bezier(.2, .9, .3, 1.15) both; }
@keyframes rv-deal { from { opacity: 0; transform: translateY(40px) rotateX(25deg) scale(0.92); } to { opacity: 1; transform: none; } }
@keyframes rv-flip-out { to { transform: rotateY(-90deg) scale(0.96); opacity: 0.6; } }
@keyframes rv-flip-in { from { transform: rotateY(90deg) scale(0.96); opacity: 0.6; } to { transform: none; opacity: 1; } }

/* 精熟檢驗：金卡、三面盾牌、倒數條 */
.rv-card-boss {
    border: 2px solid #ffca28;
    background: radial-gradient(120% 90% at 50% 0%, rgba(255, 202, 40, 0.16), transparent 60%), var(--card-bg);
    box-shadow: 0 6px 0 #b8860b, 0 0 0 1px rgba(255, 202, 40, 0.25), 0 18px 40px rgba(255, 179, 0, 0.22);
}
.rv-card-boss::after {
    content: ''; position: absolute; inset: -1px; border-radius: 18px; pointer-events: none;
    box-shadow: 0 0 0 0 rgba(255, 202, 40, 0.5), inset 0 0 18px rgba(255, 202, 40, 0.12);
    animation: rv-boss-glow 2.2s ease-in-out infinite;
}
@keyframes rv-boss-glow {
    0%, 100% { box-shadow: 0 0 6px 0 rgba(255, 202, 40, 0.25), inset 0 0 12px rgba(255, 202, 40, 0.08); }
    50% { box-shadow: 0 0 22px 3px rgba(255, 202, 40, 0.45), inset 0 0 22px rgba(255, 202, 40, 0.18); }
}
.rv-card-gold .rv-step { color: #ffca28; }
.rv-boss-in { animation: rv-boss-in 0.6s cubic-bezier(.2, .9, .3, 1.2) both; }
@keyframes rv-boss-in { 0% { transform: scale(0.85); filter: brightness(0.4); } 60% { transform: scale(1.03); filter: brightness(1.4); } 100% { transform: none; filter: none; } }
.rv-shields { display: flex; justify-content: center; gap: 14px; margin: -4px 0 14px; }
.rv-shield { display: flex; flex-direction: column; align-items: center; gap: 4px; opacity: 0.45; transition: opacity 0.2s ease; }
.rv-shield.now, .rv-shield.on, .rv-shield.cracked { opacity: 1; }
.rv-shield-icon {
    width: 30px; height: 34px; background: rgba(255, 255, 255, 0.12);
    clip-path: polygon(50% 0, 100% 14%, 92% 62%, 50% 100%, 8% 62%, 0 14%);
}
.rv-shield.now .rv-shield-icon { background: rgba(255, 202, 40, 0.35); animation: rv-pulse-k 1.2s ease-in-out infinite; }
.rv-shield.on .rv-shield-icon { background: linear-gradient(160deg, #fff59d, #ffca28 45%, #ff8f00); box-shadow: 0 0 12px #ffca28; }
.rv-shield.cracked .rv-shield-icon {
    background: linear-gradient(115deg, rgba(255, 82, 82, 0.5) 0 46%, transparent 46% 52%, rgba(255, 82, 82, 0.5) 52%);
}
.rv-shield-name { font-size: 0.66rem; color: var(--text-sub); letter-spacing: 0.5px; }
.rv-shield-lit .rv-shield-icon { animation: rv-shield-lit 0.5s cubic-bezier(.3, 1.8, .5, 1) both; }
.rv-shield-crack .rv-shield-icon { animation: rv-shield-crack 0.45s ease both; }
@keyframes rv-shield-lit { 0% { transform: scale(0.5); } 60% { transform: scale(1.35); filter: brightness(1.8); } 100% { transform: none; } }
@keyframes rv-shield-crack { 0%, 100% { transform: none; } 30% { transform: translateX(-4px) rotate(-6deg); } 60% { transform: translateX(3px) rotate(4deg); } }
@keyframes rv-pulse-k { 50% { filter: brightness(1.6); } }
.rv-timer { height: 6px; border-radius: 999px; background: rgba(255, 255, 255, 0.08); overflow: hidden; margin: 0 0 14px; }
.rv-timer-fill { height: 100%; width: 100%; background: #4caf50; border-radius: 999px; }
.rv-timer-run { animation-name: rv-timer-color; animation-timing-function: linear; animation-fill-mode: both; }
@keyframes rv-timer-color { 0% { background: #4caf50; } 55% { background: #ffc107; } 80%, 100% { background: #f44336; } }
.rv-timer-urgent { animation: rv-urgent 0.25s ease-in-out infinite; }
@keyframes rv-urgent { 0%, 100% { transform: none; } 50% { transform: translateX(2px); } }

/* 選擇題 */
.rv-options { display: flex; flex-direction: column; gap: 10px; }
.rv-options.hidden { display: none; }
.rv-opt {
    width: 100%; text-align: left; display: flex; align-items: center; gap: 12px;
    background: var(--card-bg); border: 1px solid var(--border);
    color: var(--text-main); font-family: inherit;
    border-radius: 14px; padding: 14px 14px;
    font-size: 0.98rem; line-height: 1.45; cursor: pointer;
    overflow-wrap: anywhere;
    box-shadow: 0 3px 0 color-mix(in srgb, var(--border) 85%, #000 15%);
    animation: rv-opt-in 0.32s cubic-bezier(.2, .9, .3, 1.15) both;
    transition: border-color 0.16s ease, background 0.16s ease, transform 0.1s ease, opacity 0.25s ease, box-shadow 0.1s ease;
}
@keyframes rv-opt-in { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
.rv-opt:hover:not(:disabled) { border-color: color-mix(in srgb, #00bcd4 60%, var(--border)); }
.rv-opt:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 var(--border); }
.rv-opt:disabled { cursor: default; }
.rv-opt-key {
    flex: 0 0 auto; width: 24px; height: 24px; border-radius: 7px; display: grid; place-items: center;
    font-size: 0.75rem; font-weight: 700; color: var(--text-sub); border: 1px solid var(--border);
    font-family: 'Courier New', Courier, monospace;
}
.rv-opt-text { flex: 1; }
.rv-options-en .rv-opt-text { font-size: 1.12rem; font-weight: 600; letter-spacing: 1px; font-family: 'Courier New', Courier, monospace; }
.rv-opt-right {
    border-color: var(--success); color: var(--success);
    background: rgba(76, 175, 80, 0.12); font-weight: 600;
    animation: rv-opt-right 0.4s cubic-bezier(.3, 1.6, .5, 1) both !important;
}
.rv-opt-right .rv-opt-key { border-color: var(--success); color: var(--success); }
@keyframes rv-opt-right { 50% { transform: scale(1.03); } 100% { transform: scale(1.015); } }
.rv-opt-wrong {
    border-color: var(--error); color: var(--error);
    background: rgba(244, 67, 54, 0.1);
    animation: rv-shake-k 0.4s ease both !important;
}
.rv-opt-fade { opacity: 0.35; }

/* 字母格子 */
.rv-type { display: flex; flex-direction: column; gap: 12px; }
.rv-type.hidden { display: none; }
.rv-type-hint { text-align: center; font-size: 0.85rem; color: #00bcd4; letter-spacing: 1px; }
.rv-type-hint:empty { display: none; }
.rv-boxes-wrap { position: relative; display: block; padding: 4px 0; }
.rv-boxes { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; min-height: 50px; }
.rv-box {
    width: 36px; height: 46px; border-radius: 9px; display: grid; place-items: center;
    border: 1.5px solid var(--border); background: var(--card-bg);
    font-family: 'Courier New', Courier, monospace; font-size: 1.4rem; font-weight: 700;
    color: var(--text-main); text-transform: none;
    box-shadow: 0 3px 0 color-mix(in srgb, var(--border) 85%, #000 15%);
    transition: border-color 0.12s ease, background 0.12s ease;
}
.rv-boxes-free .rv-box { width: 30px; }
.rv-box.on { border-color: color-mix(in srgb, #00bcd4 55%, var(--border)); }
.rv-box.ghost { color: color-mix(in srgb, var(--text-sub) 45%, transparent); }
.rv-box-gap { width: 14px; border: none; background: none; box-shadow: none; }
.rv-box-space { width: 14px; border-style: dashed; box-shadow: none; }
.rv-box.caret { border-color: #00bcd4; animation: rv-caret 1s ease-in-out infinite; }
@keyframes rv-caret { 50% { box-shadow: 0 3px 0 color-mix(in srgb, var(--border) 85%, #000 15%), 0 0 0 3px rgba(0, 188, 212, 0.25); } }
.rv-pop { animation: rv-pop 0.18s cubic-bezier(.3, 1.8, .5, 1); }
.rv-box-ok { animation: rv-box-ok 0.35s ease both; border-color: var(--success); color: var(--success); background: rgba(76, 175, 80, 0.12); }
.rv-box-bad { animation: rv-box-bad 0.35s ease both; border-color: var(--error); color: var(--error); }
@keyframes rv-box-ok { 0% { transform: none; } 50% { transform: translateY(-6px); } 100% { transform: none; } }
@keyframes rv-box-bad { 0% { background: var(--card-bg); } 100% { background: rgba(244, 67, 54, 0.1); } }
@keyframes rv-pop { 50% { transform: scale(1.18); } }
.rv-box.given { color: #00bcd4; }
.rv-type-btn { margin: 0; }

/* 看不見的輸入框：手機上網站自己的英文鍵盤打進這裡，複習程式再換算成格子裡的字。
   放在格子正下方（鍵盤滑上來時會把它捲到鍵盤上方，格子就跟著露出來），點不到、看不到 */
.rv-proxy { position: absolute; left: 50%; bottom: 0; width: 1px; height: 1px; padding: 0; border: 0; margin: 0;
    opacity: 0; pointer-events: none; font-size: 16px; background: transparent; color: transparent; caret-color: transparent; }
.rv-boxes-wrap { cursor: pointer; }
/* 拼字的時候收起右邊的浮動球，免得蓋住鍵盤右邊的按鍵 */
body:has(#view-review:not(.hidden) #rv-type:not(.hidden)) #flow-ball { visibility: hidden; pointer-events: none; }


.rv-shake { animation: rv-shake-k 0.3s ease; }
@keyframes rv-shake-k {
    0%, 100% { transform: translateX(0); }
    20% { transform: translateX(-6px); }
    45% { transform: translateX(5px); }
    70% { transform: translateX(-3px); }
}

/* 片語排順序 */
.rv-order { display: flex; flex-direction: column; gap: 16px; }
.rv-order.hidden { display: none; }
.rv-order-line { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; min-height: 46px; padding: 8px; border-radius: 12px; border: 1px dashed var(--border); }
.rv-order-slot { min-width: 54px; padding: 8px 12px; border-radius: 9px; border-bottom: 2px solid var(--border); color: var(--text-main); font-weight: 600; cursor: pointer; }
.rv-order-slot.on { background: rgba(0, 188, 212, 0.12); border-color: #00bcd4; animation: rv-pop 0.2s ease; }
.rv-order-ok { border-color: var(--success); background: rgba(76, 175, 80, 0.08); }
.rv-order-bad { border-color: var(--error); animation: rv-shake-k 0.35s ease; }
.rv-order-bank { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.rv-order-chip {
    padding: 10px 14px; border-radius: 10px; border: 1px solid var(--border); background: var(--card-bg);
    color: var(--text-main); font: inherit; font-weight: 600; cursor: pointer;
    box-shadow: 0 3px 0 color-mix(in srgb, var(--border) 85%, #000 15%);
}
.rv-order-chip.used { opacity: 0.25; }

/* 回饋條 */
.rv-feedback { display: none; }
.rv-feedback.on {
    display: flex; align-items: center; gap: 12px; margin: 0 0 14px;
    padding: 12px 14px; border-radius: 14px; border: 1px solid var(--border); background: var(--card-bg);
}
.rv-fb-icon { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; font-weight: 800; font-size: 1.1rem; }
.rv-fb-ok { border-color: color-mix(in srgb, var(--success) 50%, var(--border)); }
.rv-fb-ok .rv-fb-icon { background: var(--success); color: #fff; animation: rv-pop 0.4s cubic-bezier(.3, 1.8, .5, 1); }
.rv-fb-bad { border-color: color-mix(in srgb, #ff9800 50%, var(--border)); }
.rv-fb-bad .rv-fb-icon { background: rgba(255, 152, 0, 0.18); color: #ff9800; }
.rv-fb-text { flex: 1; min-width: 0; }
.rv-fb-title { font-weight: 700; color: var(--text-main); font-size: 0.95rem; }
.rv-fb-sub { color: var(--text-sub); font-size: 0.8rem; margin-top: 2px; }
.rv-fb-level { font-size: 0.75rem; color: var(--text-sub); white-space: nowrap; font-family: 'Courier New', Courier, monospace; }

/* 答錯：正確答案 */
.rv-answer {
    margin: 0 0 14px; padding: 14px 16px; border-radius: 14px;
    border: 1px solid color-mix(in srgb, var(--error) 40%, var(--border));
    background: color-mix(in srgb, var(--error) 6%, var(--card-bg));
}
.rv-answer-label { font-size: 0.72rem; letter-spacing: 2px; color: var(--text-sub); }
.rv-answer-main { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.rv-answer-en { font-size: 1.5rem; font-weight: 700; color: var(--text-main); letter-spacing: 1px; overflow-wrap: anywhere; }
.rv-answer-pos { color: var(--warning); font-size: 0.82rem; }
.rv-answer-replay { margin-left: auto; border: 1px solid var(--border); border-radius: 999px; padding: 5px 12px; background: transparent; color: var(--text-sub); font: inherit; font-size: 0.78rem; cursor: pointer; }
.rv-answer-zh { color: var(--text-sub); font-size: 0.92rem; margin-top: 4px; }
.rv-answer-choice { margin-top: 8px; color: var(--error); font-size: 0.85rem; overflow-wrap: anywhere; }
.rv-answer .spelling-diff { margin-top: 10px; }

.rv-next { width: 100%; min-height: 52px; margin: 16px 0 0; }
.rv-next-quiet { opacity: 0.85; }
.rv-rise { animation: rv-rise-k 0.28s ease both; }
@keyframes rv-rise-k { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* 特效層：光圈、火花、飄分 */
.rv-fx { position: fixed; inset: 0; pointer-events: none; z-index: 60; overflow: hidden; }
.rv-burst {
    position: absolute; width: 20px; height: 20px; margin: -10px 0 0 -10px; border-radius: 50%;
    border: 3px solid var(--success); animation: rv-burst 0.6s ease-out both;
}
.rv-burst-bad { border-color: var(--error); animation-duration: 0.45s; }
@keyframes rv-burst { from { transform: scale(0.4); opacity: 0.9; } to { transform: scale(7); opacity: 0; } }
.rv-spark {
    position: absolute; width: 6px; height: 6px; margin: -3px 0 0 -3px; border-radius: 50%;
    background: #ffd54f; box-shadow: 0 0 6px #ffca28;
    animation: rv-spark 0.65s cubic-bezier(.2, .8, .4, 1) both;
}
@keyframes rv-spark { to { transform: translate(var(--dx), var(--dy)) scale(0.2); opacity: 0; } }
.rv-float {
    position: absolute; transform: translate(-50%, -50%); font-weight: 800; font-size: 1.25rem; color: #ffca28;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); font-family: 'Courier New', Courier, monospace;
    animation: rv-float 0.9s cubic-bezier(.4, 0, .6, 1) both;
}
.rv-float-dim { color: #ffb74d; font-size: 1.05rem; }
@keyframes rv-float {
    0% { transform: translate(-50%, -20%) scale(0.6); opacity: 0; }
    25% { transform: translate(-50%, -110%) scale(1.15); opacity: 1; }
    100% { transform: translate(calc(-50% + var(--tx, 0px)), calc(-50% + var(--ty, -80px))) scale(0.5); opacity: 0.2; }
}

/* 精熟蓋章 */
.rv-stamp { position: fixed; inset: 0; z-index: 70; display: grid; place-items: center; background: rgba(0, 0, 0, 0.55); cursor: pointer; }
.rv-stamp.hidden { display: none; }
.rv-stamp-glow {
    position: absolute; width: 520px; height: 520px; max-width: 140vw; max-height: 140vw; border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 213, 79, 0.55), rgba(255, 179, 0, 0.12) 45%, transparent 70%);
    animation: rv-glow 1.8s ease-out both;
}
@keyframes rv-glow { 0% { transform: scale(0.2); opacity: 0; } 30% { opacity: 1; } 100% { transform: scale(1.3); opacity: 0.4; } }
.rv-stamp-card { position: relative; text-align: center; padding: 0 16px; }
.rv-stamp-seal {
    display: inline-block; padding: 14px 26px; border: 4px solid #ffca28; border-radius: 14px;
    color: #ffca28; font-size: 2.2rem; font-weight: 900; letter-spacing: 8px;
    transform: rotate(-8deg); text-shadow: 0 0 18px rgba(255, 202, 40, 0.6);
    box-shadow: inset 0 0 0 3px rgba(255, 202, 40, 0.35), 0 0 30px rgba(255, 202, 40, 0.35);
}
.rv-stamp-in .rv-stamp-seal { animation: rv-stamp-drop 0.5s cubic-bezier(.5, 0, .7, 1.4) both; }
@keyframes rv-stamp-drop { 0% { transform: rotate(-8deg) scale(3); opacity: 0; } 70% { transform: rotate(-8deg) scale(0.92); opacity: 1; } 100% { transform: rotate(-8deg) scale(1); } }
.rv-stamp-word { margin-top: 22px; font-size: 1.8rem; font-weight: 700; color: #fff; letter-spacing: 1px; }
.rv-stamp-sub { margin-top: 8px; font-size: 0.85rem; color: rgba(255, 255, 255, 0.75); }
.rv-stamp-in .rv-stamp-word, .rv-stamp-in .rv-stamp-sub { animation: rv-rise-k 0.4s ease 0.4s both; }

/* 「?」資訊卡 */
.rv-info { position: fixed; inset: 0; z-index: 65; background: rgba(0, 0, 0, 0.45); display: flex; justify-content: flex-end; align-items: flex-start; padding: 56px 12px 12px; }
.rv-info.hidden { display: none; }
.rv-info-card {
    width: min(380px, 100%); max-height: calc(100vh - 80px); overflow: auto;
    background: linear-gradient(var(--card-bg), var(--card-bg)), var(--bg-color, #111); border: 1px solid var(--border); border-radius: 16px; padding: 16px;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45); transform-origin: top right;
}
.rv-info-in .rv-info-card { animation: rv-info-in 0.28s cubic-bezier(.2, .9, .3, 1.15) both; }
@keyframes rv-info-in { from { transform: scale(0.3); opacity: 0; } to { transform: none; opacity: 1; } }
.rv-info-head { display: flex; justify-content: space-between; align-items: center; color: var(--text-main); font-size: 1.02rem; }
.rv-info-x { border: 0; background: none; color: var(--text-sub); font-size: 1rem; cursor: pointer; padding: 4px 6px; }
.rv-info-now { margin: 8px 0 12px; font-size: 0.85rem; color: #00bcd4; line-height: 1.6; }
.rv-info-steps { display: flex; flex-direction: column; gap: 6px; }
.rv-info-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; border: 1px solid transparent; }
.rv-info-row.now { border-color: #00bcd4; background: rgba(0, 188, 212, 0.08); }
.rv-info-row.boss .rv-info-name { color: #ffca28; }
.rv-info-n { flex: 0 0 auto; width: 24px; height: 24px; border-radius: 7px; display: grid; place-items: center; font-weight: 800; font-size: 0.78rem; color: #111; background: var(--gem); }
.rv-info-body { flex: 1; min-width: 0; }
.rv-info-name { font-size: 0.86rem; font-weight: 700; color: var(--text-main); }
.rv-info-note { font-size: 0.74rem; color: var(--text-sub); margin-top: 1px; }
.rv-info-gap { font-size: 0.7rem; color: var(--text-sub); white-space: nowrap; }
.rv-info-rules { margin: 12px 0 0; padding-left: 18px; font-size: 0.78rem; color: var(--text-sub); line-height: 1.7; }
.rv-info-ok { width: 100%; margin: 12px 0 0; }

@media (max-width: 380px) {
    .rv-box { width: 30px; height: 42px; font-size: 1.2rem; }
    .rv-boxes-free .rv-box { width: 26px; }
    .rv-word { font-size: 1.9rem; }
}

/* ── 結果 ── */
.rv-done-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-top: 3px solid #00bcd4;
    border-radius: 16px;
    padding: 28px 18px 20px;
    text-align: center;
    animation: rv-deal 0.45s cubic-bezier(.2, .9, .3, 1.1) both;
}
.rv-done-big {
    font-size: 3.4rem; font-weight: 800; color: #00bcd4;
    font-family: 'Courier New', Courier, monospace; line-height: 1;
}
.rv-done-unit { font-size: 0.82rem; color: var(--text-sub); margin-top: 4px; }
.rv-done-note { font-size: 0.85rem; color: var(--text-sub); margin-top: 12px; }
.rv-done-points { margin-top: 12px; font-size: 1rem; color: #ffca28; font-weight: 700; }
.rv-done-points:empty { display: none; }
.rv-done-rows {
    margin-top: 18px; padding-top: 16px;
    border-top: 1px solid var(--border);
    display: flex; flex-direction: column; gap: 12px; text-align: left;
}
.rv-done-row { animation: rv-rise-k 0.35s ease both; }
.rv-done-row-head { display: flex; align-items: center; justify-content: space-between; font-size: 0.88rem; }
.rv-done-label { color: var(--text-sub); }
.rv-done-num { font-family: 'Courier New', Courier, monospace; font-weight: 800; font-size: 1.05rem; }
.rv-row-ok .rv-done-num { color: var(--success); }
.rv-row-bad .rv-done-num { color: #ff9800; }
.rv-row-gold .rv-done-num, .rv-row-gold .rv-done-label { color: #ffca28; }
.rv-done-tiles { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.rv-done-tile {
    font-size: 0.72rem; padding: 3px 8px; border-radius: 6px;
    background: rgba(76, 175, 80, 0.12); color: var(--success); border: 1px solid rgba(76, 175, 80, 0.3);
    animation: rv-tile-land 0.4s cubic-bezier(.3, 1.5, .5, 1) both;
}
.rv-row-bad .rv-done-tile { background: rgba(255, 152, 0, 0.1); color: #ff9800; border-color: rgba(255, 152, 0, 0.3); }
.rv-row-gold .rv-done-tile { background: rgba(255, 202, 40, 0.14); color: #ffca28; border-color: rgba(255, 202, 40, 0.45); box-shadow: 0 0 8px rgba(255, 202, 40, 0.3); }
@keyframes rv-tile-land { from { opacity: 0; transform: translateY(-26px) scale(0.6) rotate(-8deg); } to { opacity: 1; transform: none; } }
.rv-done-more { font-size: 0.72rem; color: var(--text-sub); align-self: center; }
.rv-done-grad {
    margin-top: 14px; padding: 12px 14px;
    background: rgba(255, 202, 40, 0.08);
    border: 1px solid rgba(255, 202, 40, 0.35);
    border-radius: 10px;
    font-size: 0.82rem; line-height: 1.7; color: #ffca28;
}
.rv-done-grad.hidden { display: none; }
.rv-done-streak {
    margin-top: 14px; display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 8px;
    padding: 12px 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--card-bg);
    animation: rv-rise-k 0.35s ease 0.6s both;
}
.rv-done-streak.hidden { display: none; }
.rv-streak-n { font-size: 1.6rem; font-weight: 800; color: #ff9800; font-family: 'Courier New', Courier, monospace; }
.rv-streak-l { font-size: 0.85rem; color: var(--text-main); }
.rv-streak-tmr { margin-left: auto; font-size: 0.78rem; color: var(--text-sub); }
.rv-done-qtitle { margin-top: 18px; font-size: 0.85rem; color: var(--text-sub); letter-spacing: 1px; }
.rv-done-quests { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.rv-quest {
    display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 10px;
    border: 1px solid var(--border); background: var(--card-bg); font-size: 0.86rem; color: var(--text-sub);
    animation: rv-rise-k 0.35s ease both;
}
.rv-quest-check { width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--border); display: grid; place-items: center; font-size: 0.72rem; font-weight: 800; }
.rv-quest.done { color: var(--text-main); border-color: color-mix(in srgb, var(--success) 45%, var(--border)); }
.rv-quest.done .rv-quest-check { background: var(--success); border-color: var(--success); color: #fff; animation: rv-pop 0.4s cubic-bezier(.3, 1.8, .5, 1) 1.1s both; }
.rv-quest-name { flex: 1; }
.rv-quest-prog { font-size: 0.75rem; font-family: 'Courier New', Courier, monospace; }
.rv-done-list { margin-top: 18px; }
.rv-done-title {
    font-size: 0.85rem; color: var(--text-sub);
    margin-bottom: 10px; letter-spacing: 0.5px;
}
.rv-done-empty {
    text-align: center; padding: 20px 0;
    font-size: 0.85rem; color: var(--text-sub);
}
.rv-weak-row {
    display: flex; align-items: baseline; gap: 10px;
    padding: 11px 14px; margin-bottom: 8px;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 10px;
}
.rv-weak-en { font-size: 0.95rem; font-weight: 600; color: var(--text-main); }
.rv-weak-tag { font-size: 0.66rem; color: #ff5252; border: 1px solid rgba(255, 82, 82, 0.5); padding: 1px 6px; border-radius: 999px; }
.rv-weak-zh {
    flex: 1; text-align: right;
    font-size: 0.82rem; color: var(--text-sub); overflow-wrap: anywhere;
}

@media (prefers-reduced-motion: reduce) {
    .rv-entry-dot, .rv-view *, .rv-view *::before, #view-review-done * {
        animation-duration: 0.01ms !important; animation-delay: 0s !important; animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    .rv-bar-fill { animation: none; }
    .rv-fx { display: none; }
}

/* ==========================================================
   底部四分頁導覽
   ========================================================== */
.bnav {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 900;
    display: flex;
    background: var(--card-bg);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    /* 毛玻璃在舊機上很吃效能，跟其他地方一樣跟著「降低特效」走 */
    backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat));
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    transition: transform .32s cubic-bezier(.22,.7,.2,1), opacity .22s ease, visibility 0s;
}
/* Keep the bar rendered until its exit finishes; inert/aria-hidden are set in nav.js. */
.bnav.hidden {
    display: flex !important;
    transform: translateY(calc(100% + 8px));
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform .32s cubic-bezier(.22,.7,.2,1), opacity .22s ease, visibility 0s .32s;
}
.bnav-item {
    flex: 1;
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 9px 0 7px;
    background: transparent;
    border: none;
    color: var(--text-sub);
    font-family: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.18s ease;
}
.bnav-ico { display: block; width: 24px; height: 24px; }
.bnav-ico svg { width: 100%; height: 100%; display: block; }
.bnav-label { font-size: 0.68rem; letter-spacing: 1px; }
.bnav-item[data-tab="chat"] .bnav-label { font-size: 0.61rem; letter-spacing: 0; white-space: nowrap; }
.bnav-on { color: var(--text-main); }
.bnav-on .bnav-label { font-weight: 600; }
/* 亮起來的那一格上面畫一條，不只是變色 —— 深色底下純靠顏色差很難看出來 */
.bnav-on::before {
    content: '';
    position: absolute;
    top: 0; left: 50%;
    width: 26px; height: 2px;
    transform: translateX(-50%);
    background: #00bcd4;
    border-radius: 0 0 2px 2px;
}
.bnav-item:active { transform: scale(0.94); }

/* 每日聊天室：單一靜態玻璃層，訊息進場只動 transform/opacity。 */
.daily-chat-shell { box-sizing: border-box; display: flex; flex-direction: column; height: calc(100dvh - 220px); max-width: 760px; margin: 2px auto 0; padding: 0 5px 5px; }
.daily-chat-head {
    position: relative; flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 10px;
    min-height: 44px; box-sizing: border-box; padding: 6px 11px; margin: 0;
    border: 1px solid rgba(159,205,244,.32); border-radius: 18px;
    background: linear-gradient(140deg, rgba(80,141,178,.19), rgba(127,93,180,.13) 58%, var(--card-bg));
    box-shadow: inset 0 1px rgba(255,255,255,.12), 0 6px 18px rgba(0,0,0,.1);
}
.daily-chat-head h2 { color: var(--text-main); font-size: 1rem; font-weight: 650; margin: 0; white-space: nowrap; }
.daily-chat-head h2 span { color: #a8d9df; font-size: .76rem; vertical-align: 2px; }
.daily-chat-day { display: inline-flex; flex: 0 0 auto; padding: 3px 7px; border-radius: 20px; border: 1px solid rgba(158,220,231,.3); color: #bde6e9; background: rgba(88,150,164,.12); font-size: .65rem; }
.daily-chat-messages { flex: 1 1 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 10px 5px 5px; }
.daily-chat-empty { margin: 65px 12px; padding: 20px; color: var(--text-sub); text-align: center; border: 1px dashed var(--border); border-radius: 18px; }
.daily-chat-message { display: flex; gap: 10px; align-items: flex-start; margin: 0 0 15px; }
.daily-chat-mine { justify-content: flex-end; }
.daily-chat-mine .daily-chat-person { display: none; }
.daily-chat-mine .daily-chat-content { border-color: rgba(142,218,225,.35); border-radius: 17px 5px 17px 17px; background: linear-gradient(135deg, rgba(79,153,174,.27), rgba(111,105,174,.22)); }
.daily-chat-mine .daily-chat-message-top { justify-content: flex-end; }
.daily-chat-enter { animation: chat-arrive .28s cubic-bezier(.2,.8,.3,1) both; }
@keyframes chat-arrive { from { opacity: 0; transform: translateY(9px) scale(.985); } to { opacity: 1; transform: translateY(0) scale(1); } }
.daily-chat-person, .daily-chat-name { border: 0; background: none; cursor: pointer; color: inherit; padding: 0; font: inherit; }
.daily-chat-person { flex: 0 0 38px; }
.daily-chat-avatar { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%; border: 1px solid rgba(173,206,235,.38); background: linear-gradient(135deg, #448a9e, #735f9d); color: #fff; font-weight: 700; }
.daily-chat-avatar > img:not(.avatar-frame) { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.daily-chat-content { min-width: 0; max-width: min(85%, 570px); padding: 8px 12px 10px; border-radius: 5px 17px 17px 17px; border: 1px solid var(--border); background: var(--card-bg); box-shadow: 0 3px 14px rgba(0,0,0,.08); }
.daily-chat-message-top { display: flex; align-items: baseline; gap: 12px; margin-bottom: 3px; }
.daily-chat-name { color: #bde6e9; font-size: .82rem; font-weight: 650; text-align: left; }
.daily-chat-message-top time { color: var(--text-sub); font-size: .67rem; white-space: nowrap; }
.daily-chat-content p { color: var(--text-main); font-size: .9rem; line-height: 1.55; overflow-wrap: anywhere; white-space: pre-wrap; margin: 0; }
.daily-chat-invite-card { display: flex; flex-direction: column; align-items: flex-start; gap: 7px; margin-top: 9px; padding: 11px; border: 1px solid rgba(168,216,224,.35); border-radius: 13px; background: linear-gradient(135deg, rgba(77,150,173,.19), rgba(121,106,175,.16)); }
.daily-chat-invite-card strong { color: var(--text-main); font-size: .87rem; }
.daily-chat-invite-card span { color: var(--text-sub); font-size: .75rem; }
.daily-chat-invite-card button { padding: 7px 12px; border: 1px solid rgba(177,225,231,.5); border-radius: 12px; background: rgba(117,192,210,.16); color: var(--text-main); font: inherit; font-size: .78rem; cursor: pointer; }
.daily-chat-invite-card button:disabled { opacity: .64; cursor: default; }
.daily-chat-admin-actions { display: flex; gap: 10px; padding-top: 8px; }
.daily-chat-admin-actions button { border: 0; background: none; color: #e6a8a8; font-size: .7rem; cursor: pointer; padding: 1px; }
.daily-chat-status { flex: 0 0 auto; min-height: 0; margin: 0 3px 3px; color: #e9adad; font-size: .75rem; }
.daily-chat-status:empty { display: none; }
.daily-chat-form { flex: 0 0 auto; display: flex; align-items: center; gap: 5px; padding: 4px 6px; border: 1px solid var(--border); border-radius: 17px; background: var(--card-bg); }
.daily-chat-form textarea { flex: 1; min-width: 0; min-height: 24px; max-height: 88px; resize: none; overflow-y: auto; background: transparent; border: 0; outline: 0; color: var(--text-main); font: inherit; font-size: .91rem; line-height: 1.4; padding: 5px 6px; }
.daily-chat-form button { flex: 0 0 34px; height: 34px; border: 0; border-radius: 12px; color: #15292e; background: linear-gradient(135deg, #a9e8e6, #c7bbf1); font-size: 1rem; cursor: pointer; transition: transform .16s ease; }
.daily-chat-form button:active { transform: scale(.9); }
.daily-chat-form button:disabled { opacity: .45; }
.public-friend-row { display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap; color: var(--text-sub); font-size: .82rem; margin: 15px auto 0; }
.public-friend-row button { border-radius: 20px; padding: 8px 15px; }
@media (prefers-reduced-motion: reduce) { .daily-chat-enter { animation: none; } .daily-chat-form button { transition: none; } }
body.kb-open .daily-chat-head { min-height: 42px; padding: 7px 12px; }
body.kb-open .daily-chat-head h2 { font-size: 1.05rem; }
body.kb-open .daily-chat-day { display: none; }
body.chat-open #main-header { margin-bottom: 8px; }
body.chat-typing .daily-chat-head { min-height: 46px; padding: 7px 12px; }
body.chat-typing .daily-chat-shell { margin-top: 4px; }
@media (max-width: 760px) {
    #view-daily-chat { width: calc(100% + 2 * var(--container-pad)); margin-left: calc(-1 * var(--container-pad)); }
    .daily-chat-shell { width: 100%; }
}
body.chat-typing .bnav { display: flex !important; bottom: var(--chat-keyboard-bottom, 0px); }
.bnav-dot {
    position: absolute;
    top: 7px; left: 50%;
    margin-left: 8px;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--error);
    box-shadow: 0 0 0 2px var(--card-bg);
}
/* 導覽列蓋在內容上，所以內容要自己讓開這段高度 */
body.has-bnav .container { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
.container { transition: padding-bottom .32s cubic-bezier(.22,.7,.2,1); }
/* 鍵盤打開的時候導覽列要收起來，不然它會浮在鍵盤上面 */
body.kb-open .bnav { display: none; }
body.chat-typing.kb-open .bnav { display: flex !important; }
body.kb-open.has-bnav .container { padding-bottom: calc(var(--kb-height, 250px) + 24px); transition: none; }
html[data-fx="low"] .bnav, html[data-fx="low"] .bnav.hidden, html[data-fx="low"] .container { transition: none; }
@media (prefers-reduced-motion: reduce) {
    .bnav, .bnav.hidden, .container { transition: none; }
}

/* ==========================================================
   首頁儀表板
   ========================================================== */
/* 首頁的節奏。
   回報兩次「太緊湊」。原因不只是間距 —— 八張長得一模一樣、間距也一樣的
   卡片疊在一起，眼睛沒有地方可以停，所以就算每個間距都加寬還是覺得擠。
   所以除了放大間距，也把內容分成三段，每段給一個小標。
   標題本身佔的空間就是留白，而且讓人知道自己看到哪裡了。 */
.hm-sec { margin-bottom: 34px; }
.hm-sec.hidden { display: none; }
.hm-sec-label {
    font-size: 0.72rem; letter-spacing: 3px;
    color: var(--text-sub); opacity: 0.75;
    margin: 0 0 14px 4px;
}
.hm-gap { margin-top: 14px; }

.hm-streak {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 16px 18px;
    margin-bottom: 30px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 14px;
    color: var(--text-main);
    font-family: inherit;
    cursor: pointer;
    text-align: left;
}
.hm-streak:active { transform: scale(0.99); }
.hm-streak-icon { width: 22px; height: 22px; color: #ff8a3d; flex-shrink: 0; }
.hm-streak-icon svg { width: 100%; height: 100%; display: block; }
.hm-streak-txt { display: flex; align-items: baseline; gap: 2px; }
.hm-streak-n {
    font-size: 1.45rem; font-weight: 700; line-height: 1;
    font-family: 'Courier New', Courier, monospace; color: var(--text-main);
}
.hm-streak-unit { font-size: 0.8rem; color: var(--text-sub); }
.hm-streak-note { flex: 1; font-size: 0.78rem; color: var(--text-sub); text-align: right; }
.hm-go { color: var(--text-sub); font-size: 1.3rem; font-weight: 300; line-height: 1; flex-shrink: 0; }

.hm-today { margin-bottom: 0; }
.hm-main {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 24px 20px;
    background: linear-gradient(135deg, rgba(0,188,212,0.16) 0%, rgba(0,188,212,0.06) 100%);
    border: 1px solid rgba(0,188,212,0.42);
    border-radius: 16px;
    color: var(--text-main);
    font-family: inherit;
    cursor: pointer;
    text-align: left;
    transition: transform 0.12s ease, border-color 0.18s ease;
}
.hm-main:active { transform: scale(0.99); }
.hm-main-txt { flex: 1; font-size: 1.12rem; font-weight: 700; letter-spacing: 1px; }
.hm-main-sub {
    display: block; margin-top: 5px;
    font-size: 0.8rem; font-weight: 400; letter-spacing: 0.5px; color: var(--text-sub);
}
.hm-main-go { color: #00bcd4; font-size: 1.6rem; font-weight: 300; line-height: 1; }

/* 原本這一行只是一段灰字加一顆細細的外框按鈕，回報是「找不到」。
   整行變成一顆可以按的東西，而且左邊掛一條色帶點出它是可以動的。 */
.hm-scope {
    width: 100%;
    display: flex; align-items: center; gap: 10px;
    margin-top: 12px; padding: 14px 16px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-left: 3px solid rgba(0, 188, 212, 0.55);
    border-radius: 12px;
    font-family: inherit; cursor: pointer; text-align: left;
}
.hm-scope:active { transform: scale(0.99); }
.hm-scope-label {
    font-size: 0.72rem; letter-spacing: 1px; color: var(--text-sub);
    flex-shrink: 0; padding-right: 8px; border-right: 1px solid var(--border);
}
.hm-scope-txt { flex: 1; font-size: 0.82rem; color: var(--text-main); overflow-wrap: anywhere; }
.hm-scope-btn {
    background: rgba(0, 188, 212, 0.14); border: 1px solid rgba(0, 188, 212, 0.45);
    color: #00bcd4; font-family: inherit; font-size: 0.76rem; font-weight: 600;
    padding: 5px 12px; border-radius: 11px; flex-shrink: 0;
}

/* 連結力訓練：跟精通模式同一層級，但視覺上退半步，
   免得兩顆一樣重的按鈕讓人不知道該按哪一顆 */
.hm-second {
    width: 100%;
    display: flex; align-items: center; gap: 10px;
    margin-top: 12px; padding: 19px 20px;
    background: var(--card-bg);
    border: 1px solid rgba(0, 188, 212, 0.28);
    border-radius: 16px;
    color: var(--text-main);
    font-family: inherit; cursor: pointer; text-align: left;
    transition: transform 0.12s ease, border-color 0.18s ease;
}
.hm-second:active { transform: scale(0.99); }
@media (hover: hover) { .hm-second:hover { border-color: rgba(0, 188, 212, 0.55); } }
.hm-second-txt { flex: 1; font-size: 1rem; font-weight: 600; letter-spacing: 0.5px; }
.hm-second-sub {
    display: block; margin-top: 4px;
    font-size: 0.78rem; font-weight: 400; color: var(--text-sub);
}
.hm-second-go { color: #00bcd4; font-size: 1.4rem; font-weight: 300; line-height: 1; }

.hm-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px; }
.hm-duo-btn { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 0; padding: 15px 14px; border-radius: 16px;
    background: var(--card-bg); color: var(--text-main); font-family: inherit; text-align: left; cursor: pointer; transition: transform 0.12s ease, border-color 0.18s ease; }
.hm-duo-btn:active { transform: scale(0.98); }
.hm-duo-commute { border: 1px solid rgba(38, 198, 218, 0.3); }
.hm-duo-cram { border: 1px solid rgba(255, 138, 101, 0.32); }
@media (hover: hover) { .hm-duo-commute:hover { border-color: rgba(38, 198, 218, 0.6); } .hm-duo-cram:hover { border-color: rgba(255, 138, 101, 0.6); } }
.hm-duo-name { font-size: 0.98rem; font-weight: 700; letter-spacing: 0.5px; }
.hm-duo-commute .hm-duo-name::after { content: ''; display: inline-block; width: 7px; height: 7px; margin-left: 7px; border-radius: 50%; background: #26c6da; vertical-align: 2px; }
.hm-duo-cram .hm-duo-name::after { content: ''; display: inline-block; width: 7px; height: 7px; margin-left: 7px; border-radius: 50%; background: #ff8a65; vertical-align: 2px; }
.hm-duo-sub { font-size: 0.74rem; color: var(--text-sub); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }

.hm-rank, .hm-friends {
    width: 100%;
    display: flex; align-items: center; gap: 14px;
    padding: 17px 18px; margin-bottom: 12px;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 16px; color: var(--text-main);
    font-family: inherit; cursor: pointer; text-align: left;
}
.hm-rank.hidden, .hm-friends.hidden { display: none; }
.hm-rank:active, .hm-friends:active { transform: scale(0.99); }
.hm-rank-emblem { width: 40px; height: 40px; flex-shrink: 0; }
.hm-rank-emblem svg { width: 100%; height: 100%; display: block; }
.hm-rank-info { flex: 1; min-width: 0; }
.hm-rank-tier { display: block; font-size: 0.98rem; font-weight: 600; letter-spacing: 1px; }
.hm-rank-sub { display: block; margin-top: 3px; font-size: 0.76rem; color: var(--text-sub); }

.hm-friends-avatars { display: flex; flex-shrink: 0; }
.hm-fr-av { display: block; margin-right: -9px; position: relative; }
.hm-fr-av .fr-avatar { border: 2px solid var(--card-bg); }
.hm-fr-on::after {
    content: ''; position: absolute; right: 0; bottom: 0;
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--success); border: 2px solid var(--card-bg);
}
.hm-friends-txt { flex: 1; font-size: 0.85rem; color: var(--text-sub); padding-left: 14px; }
.hm-friends-hi { border-color: rgba(0,188,212,0.5); }
.hm-friends-hi .hm-friends-txt { color: var(--text-main); font-weight: 600; }

/* 還沒有好友的時候。這張卡以前整個藏起來，於是最需要看到它的人
   反而看不到（見 friends.js 的 paintHomeFriends）。沒有頭像可以排，
   就用一個加號佔住那個位置，讓它看起來還是一張「可以點」的卡。 */
.hm-friends-empty .hm-friends-txt { padding-left: 0; }
.hm-friends-empty .hm-friends-avatars::before {
    content: '+';
    width: 40px; height: 40px; flex: 0 0 40px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%; border: 1px dashed var(--border);
    color: var(--text-sub); font-size: 1.2rem; line-height: 1;
}

.ai-home-btn {
    width: 100%; padding: 15px; border-radius: 12px;
    background: linear-gradient(135deg, rgba(0,188,212,0.12) 0%, rgba(156,39,176,0.12) 100%);
    border: 1px solid rgba(0,188,212,0.35); color: var(--text-main);
    font-size: 1rem; letter-spacing: 2px; font-weight: 600;
    font-family: inherit; cursor: pointer; transition: background 0.2s;
}
.ai-home-btn:active { transform: scale(0.99); }

/* 回報：「不太明顯，用戶可能找不到」。虛線框加灰字在深色底上幾乎是隱形的，
   所以改成實心的一列，左邊一顆會呼吸的點，右邊標出裡面有幾種。 */
.hm-modes-toggle {
    width: 100%; margin-top: 14px; padding: 17px 18px;
    display: flex; align-items: center; gap: 10px;
    background: var(--card-bg);
    border: 1px solid rgba(0, 188, 212, 0.3);
    border-radius: 13px; color: var(--text-main);
    font-family: inherit; font-size: 0.92rem; letter-spacing: 1px; cursor: pointer;
    transition: border-color 0.18s ease, background 0.18s ease;
}
.hm-modes-toggle:active { transform: scale(0.99); }
@media (hover: hover) { .hm-modes-toggle:hover { border-color: rgba(0, 188, 212, 0.6); } }
.hm-modes-dot {
    width: 7px; height: 7px; border-radius: 50%; background: #00bcd4;
    flex-shrink: 0; animation: hmPulse 2.4s ease-in-out infinite;
}
@keyframes hmPulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(0, 188, 212, 0.45); }
    50%      { opacity: 0.55; box-shadow: 0 0 0 6px rgba(0, 188, 212, 0); }
}
.hm-modes-label { flex: 1; font-weight: 600; }
.hm-modes-count {
    font-size: 0.75rem; color: #00bcd4;
    background: rgba(0, 188, 212, 0.12); border-radius: 10px; padding: 3px 9px;
}
.hm-modes-arrow { color: var(--text-sub); transition: transform 0.28s ease; }
.hm-modes-open .hm-modes-arrow { transform: rotate(180deg); }

/* 展開要看得到它在長出來。高度由 JS 量出來寫成 inline style，
   動畫跑完就拿掉上限（內容之後可能變高，夾住會被切掉）。 */
.hm-modes {
    margin-top: 14px;
    overflow: hidden;
    transition: max-height 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}
.hm-modes.hidden { display: none; }
@media (prefers-reduced-motion: reduce) {
    .hm-modes { transition: none; }
    .hm-modes-dot { animation: none; }
}

/* 原本中翻英 / 英翻中 / 選擇題兩個方向各佔一顆，四顆在問同一件事。
   併成一列，方向變成列內的選項。 */
.mode-split {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 14px; margin-bottom: 10px;
    background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px;
}
.mode-split-name { flex: 1; font-size: 0.95rem; color: var(--text-main); letter-spacing: 0.5px; }
.mode-split-sub { display: block; margin-top: 3px; font-size: 0.74rem; color: var(--text-sub); }
.mode-split-btns { display: flex; gap: 8px; flex-shrink: 0; }
.mode-split-btn {
    background: transparent; border: 1px solid var(--border);
    color: var(--text-main); font-family: inherit; font-size: 0.82rem;
    padding: 8px 12px; border-radius: 10px; cursor: pointer;
    transition: border-color 0.16s ease, background 0.16s ease;
}
.mode-split-btn:active { transform: scale(0.96); }
@media (hover: hover) {
    .mode-split-btn:hover { border-color: #00bcd4; color: #00bcd4; }
}

/* ==========================================================
   對戰 / 我的 分頁
   ========================================================== */
.hub-head { margin-bottom: 20px; }
.hub-title { font-size: 1.5rem; letter-spacing: 3px; font-weight: 700; color: var(--text-main); margin: 0 0 6px; }
.hub-sub { font-size: 0.85rem; color: var(--text-sub); letter-spacing: 0.5px; margin: 0; }
.hub-go { color: var(--text-sub); font-size: 1.3rem; font-weight: 300; line-height: 1; flex-shrink: 0; }

.hub-list { display: flex; flex-direction: column; gap: 10px; }
/* 對戰分頁分成兩段：先看排名，再決定要不要下場。
   標題本身就是那道分隔線，所以上緣要留得比卡片間距明顯。 */
.hub-sec-label {
    font-size: 0.72rem; letter-spacing: 3px;
    color: var(--text-sub); opacity: 0.75;
    margin: 30px 0 14px 4px;
}
.hub-item {
    width: 100%; display: flex; align-items: center; gap: 10px;
    padding: 16px 16px;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 13px; color: var(--text-main);
    font-family: inherit; cursor: pointer; text-align: left;
    transition: border-color 0.16s ease;
}
.hub-item:active { transform: scale(0.99); }
@media (hover: hover) { .hub-item:hover { border-color: #00bcd4; } }
.hub-item-name { flex: 1; font-size: 0.98rem; font-weight: 600; letter-spacing: 0.5px; }
.hub-item-sub { display: block; margin-top: 4px; font-size: 0.76rem; font-weight: 400; color: var(--text-sub); line-height: 1.45; }
.hub-item-hi { border-color: rgba(240,192,64,0.45); margin-bottom: 10px; }
/* 好友不屬於「下場比一場」那一組，所以獨立擺在最後面，多留一點間距 */
.hub-item-tail { margin-top: 24px; }
.hub-item-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--error); flex-shrink: 0; }
.me-pro { color: #f0c040; }

.ai-points-charge-toast {
    position: fixed; left: 50%; bottom: max(80px, env(safe-area-inset-bottom));
    transform: translate(-50%, 12px); opacity: 0; pointer-events: none; z-index: 10050;
    max-width: calc(100vw - 32px); padding: 12px 18px; border-radius: 16px;
    border: 1px solid rgba(240,192,64,.48); background: #242019;
    color: #ffe19b; font-size: .86rem; font-weight: 600; text-align: center;
    box-shadow: 0 10px 28px rgba(0,0,0,.32);
    transition: opacity .2s ease, transform .2s ease;
}
.ai-points-charge-toast.visible { opacity: 1; transform: translate(-50%, 0); }

.ah-rank {
    width: 100%; display: flex; align-items: center; gap: 14px;
    padding: 18px 16px; margin-bottom: 18px;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 16px; color: var(--text-main);
    font-family: inherit; cursor: pointer; text-align: left;
}
.ah-rank:active { transform: scale(0.99); }
.ah-rank-emblem { width: 52px; height: 52px; flex-shrink: 0; }
.ah-rank-emblem svg { width: 100%; height: 100%; display: block; }
.ah-rank-info { flex: 1; min-width: 0; }
.ah-rank-tier { display: block; font-size: 1.1rem; font-weight: 700; letter-spacing: 1.5px; }
.ah-rank-sub { display: block; margin-top: 4px; font-size: 0.78rem; color: var(--text-sub); }
.ah-rank-bar {
    display: block; margin-top: 10px; height: 4px; border-radius: 2px;
    background: rgba(255,255,255,0.09); overflow: hidden;
}
.ah-rank-fill { display: block; height: 100%; width: 0; background: #00bcd4; transition: width 0.5s ease; }

.me-card {
    width: 100%; display: flex; align-items: center; gap: 14px;
    padding: 16px; margin-bottom: 14px;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 16px; color: var(--text-main);
    font-family: inherit; cursor: pointer; text-align: left;
}
.me-card:active { transform: scale(0.99); }
.me-avatar {
    width: 52px; height: 52px; border-radius: 50%; flex-shrink: 0;
    background: rgba(255,255,255,0.08); border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.3rem; font-weight: 700; color: var(--text-sub); overflow: hidden;
}
.me-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.me-card-info { flex: 1; min-width: 0; }
.me-name { display: block; font-size: 1.05rem; font-weight: 600; letter-spacing: 0.5px; overflow-wrap: anywhere; }
.me-card-sub { display: block; margin-top: 4px; font-size: 0.78rem; color: var(--text-sub); }

.me-stats { display: flex; gap: 10px; margin-bottom: 18px; }
.me-stat {
    flex: 1; text-align: center; padding: 14px 6px;
    background: var(--card-bg); border: 1px solid var(--border); border-radius: 13px;
}
.me-stat-v {
    font-size: 1.35rem; font-weight: 700; color: var(--text-main);
    font-family: 'Courier New', Courier, monospace;
}
.me-stat-l { margin-top: 4px; font-size: 0.72rem; color: var(--text-sub); letter-spacing: 0.5px; }

/* 「我的」按用途分區，常用學習工具以兩欄顯示，減少尋找入口所需的捲動。 */
#view-me .me-section { margin: 0 0 24px; }
#view-me .me-section-title {
    margin: 0 0 10px 2px; color: var(--text-sub);
    font-size: 0.8rem; font-weight: 600; letter-spacing: 1.2px;
}
#view-me .me-tool-grid, #view-me .me-reward-grid {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px;
}
#view-me .me-tool-card, #view-me .me-reward-card {
    min-width: 0; min-height: 76px; padding: 12px 13px;
    align-items: flex-start; gap: 5px;
}
#view-me .me-tool-card .hub-item-name,
#view-me .me-reward-card .hub-item-name { min-width: 0; font-size: 0.9rem; letter-spacing: 0; overflow-wrap: anywhere; }
#view-me .me-tool-card .hub-item-sub,
#view-me .me-reward-card .hub-item-sub { margin-top: 5px; font-size: 0.72rem; }
#view-me .me-tool-card .hub-go,
#view-me .me-reward-card .hub-go { font-size: 1.1rem; }
#view-me .me-reward-card { border-color: rgba(240,192,64,0.35); }
#view-me .me-group-list { gap: 8px; }
#view-me .me-group-list .hub-item { padding: 13px 15px; }
@media (max-width: 350px) {
    #view-me .me-tool-grid, #view-me .me-reward-grid { gap: 8px; }
    #view-me .me-tool-card, #view-me .me-reward-card { padding: 11px; }
}

/* 商城的三個分店。
   它們是三個獨立畫面（各自有自己的資料與按鈕），但在使用者眼裡是同一個
   地方的三個分頁，所以切換要用滑的 —— 依照分頁的左右關係決定方向。 */
/* 選擇器要跟上面那條「每個 view 顯示時淡入」同等具體，否則會被它蓋掉 */
div[id^="view-"].st-in-left  { animation: stInLeft  0.28s cubic-bezier(0.22, 1, 0.36, 1) both; }
div[id^="view-"].st-in-right { animation: stInRight 0.28s cubic-bezier(0.22, 1, 0.36, 1) both; }
@keyframes stInLeft {
    from { opacity: 0; transform: translateX(26px); }
    to   { opacity: 1; transform: none; }
}
@keyframes stInRight {
    from { opacity: 0; transform: translateX(-26px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    div[id^="view-"].st-in-left, div[id^="view-"].st-in-right { animation: none; }
}

/* 沒有下緣間距的話，分頁列會直接黏在下面那張點數卡上 */
.store-tabs { display: flex; gap: 8px; margin-bottom: 20px; }
.store-tab {
    flex: 1; padding: 10px 6px;
    background: transparent; border: 1px solid var(--border); border-radius: 11px;
    color: var(--text-sub); font-family: inherit; font-size: 0.85rem;
    letter-spacing: 0.5px; cursor: pointer;
}
.store-tab-on { border-color: #00bcd4; color: #00bcd4; font-weight: 600; }
.store-tab:active { transform: scale(0.97); }

/* 引導列跟底部導覽都貼在畫面下緣。引導的第 4、5 步就是要使用者去點
   導覽列，蓋住它等於在叫他點一個看不到的東西 —— 有導覽列的時候把
   引導列往上抬一整條的高度。 */
body.has-bnav .ob-bar {
    bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    padding-bottom: 14px;
}
.bnav-item.ob-spotlight { border-radius: 10px; }

/* ── 既有使用者的一次性指引 ── */
.nav-hint {
    position: fixed;
    inset: 0;
    z-index: 8600;
    background: rgba(0, 0, 0, 0.62);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: 0 16px calc(84px + env(safe-area-inset-bottom, 0px));
    animation: navHintIn 0.24s ease both;
}
.nav-hint-out { animation: navHintOut 0.2s ease both; }
@keyframes navHintIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes navHintOut { from { opacity: 1; } to { opacity: 0; } }
.nav-hint-box {
    width: 100%;
    max-width: 420px;
    /* card-bg 在多數主題下是半透明的，字會跟後面的內容疊在一起糊成一片。
       這一塊是要讀的，底色必須是實心的。 */
    background: #12161c;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55);
    border: 1px solid #00bcd4;
    border-radius: 16px;
    padding: 20px 18px 16px;
    animation: navHintRise 0.3s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes navHintRise {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: none; }
}
.nav-hint-title { font-size: 1.05rem; font-weight: 700; letter-spacing: 1px; color: var(--text-main); }
.nav-hint-text { margin-top: 8px; font-size: 0.86rem; line-height: 1.65; color: var(--text-sub); }
.nav-hint-ok {
    width: 100%; margin-top: 16px; padding: 12px;
    background: rgba(0, 188, 212, 0.14); border: 1px solid rgba(0, 188, 212, 0.5);
    border-radius: 11px; color: #00bcd4; font-family: inherit;
    font-size: 0.92rem; letter-spacing: 1px; font-weight: 600; cursor: pointer;
}
/* 指引出現時把導覽列抬到遮罩上面，使用者才看得到在指什麼 */
.nav-hint-lift { z-index: 8700; }
@media (prefers-reduced-motion: reduce) {
    .nav-hint, .nav-hint-box, .nav-hint-out { animation: none; }
}

.settings-select {
    background: var(--card-bg);
    border: 1px solid var(--border);
    color: var(--text-main);
    font-family: inherit;
    font-size: 0.85rem;
    padding: 6px 10px;
    border-radius: 10px;
    cursor: pointer;
}

/* ── 本週戰報 ── */
#wr-overlay {
    position: fixed; inset: 0; z-index: 8400;
    background: rgba(0, 0, 0, 0.72);
    display: flex; align-items: center; justify-content: center;
    padding: 20px 16px;
    opacity: 0; transition: opacity 0.2s ease;
}
#wr-overlay.show { opacity: 1; }
#wr-overlay.hidden { display: none; }
.wr-box { max-width: 380px; width: 100%; max-height: 92vh; display: flex; flex-direction: column; }
.wr-title {
    font-size: 1.05rem; font-weight: 700; letter-spacing: 2px;
    color: var(--text-main); text-align: center; margin-bottom: 14px;
}
.wr-host {
    flex: 1; min-height: 0; overflow-y: auto;
    display: flex; align-items: center; justify-content: center;
    scrollbar-width: none;
}
.wr-host::-webkit-scrollbar { display: none; }
.wr-canvas { width: 100%; height: auto; border-radius: 12px; display: block; }
.wr-loading { color: var(--text-sub); font-size: 0.85rem; padding: 60px 0; letter-spacing: 1px; }
.wr-note { margin-top: 12px; font-size: 0.8rem; color: var(--text-sub); line-height: 1.6; text-align: center; }
.wr-note.hidden { display: none; }
.wr-actions { display: flex; gap: 8px; margin-top: 16px; }
.wr-actions .btn { flex: 1; margin: 0; }
.wr-actions .hidden { display: none; }

/* ==========================================================
   生死戰
   ==========================================================
   血條、傷害、瀕死。這一區跟其他畫面最大的不同是它有「狀態」——
   同一個畫面在瀕死與生死時刻要長得不一樣，所以那兩個狀態掛在 body
   上（.dm-critical / .dm-sudden），底下的東西各自反應。
   ========================================================== */

/* ── 入口 ────────────────────────────────────────────────── */
.dm-intro { padding: 4px 0 40px; }
.dm-intro-title { font-size: 1.28rem; font-weight: 700; letter-spacing: 1.5px; margin-bottom: 8px; }
.dm-intro-sub { font-size: 0.86rem; color: var(--text-sub); line-height: 1.6; margin-bottom: 22px; }
.dm-rule-list { display: flex; flex-direction: column; gap: 10px; }
.dm-rule {
    display: flex; gap: 12px; align-items: flex-start;
    padding: 13px 14px; background: var(--card-bg);
    border: 1px solid var(--border); border-radius: 12px;
    font-size: 0.82rem; line-height: 1.55;
}
.dm-rule-k { flex-shrink: 0; width: 60px; color: var(--text-sub); letter-spacing: 1px; }
.dm-roles-preview { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; }
.dm-rp {
    display: flex; align-items: baseline; gap: 10px;
    padding: 11px 14px; border: 1px solid var(--border);
    border-radius: 11px; font-size: 0.8rem;
}
.dm-rp-n { font-weight: 600; letter-spacing: 1px; flex-shrink: 0; }
.dm-rp-d { color: var(--text-sub); }
.dm-remain { margin-top: 14px; text-align: center; font-size: 0.76rem; color: var(--text-sub); }

/* ── 配對 / 滾輪 ─────────────────────────────────────────── */
.dm-center {
    min-height: 62vh; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 18px;
}
/* 配對畫面。
 *
 * 舊版是三個紅圈在一片空白裡脹大，除了「還在跑」以外什麼都沒說，
 * 玩家只能盯著它猜還要等多久。
 *
 * 伺服器其實每 1.5 秒就回三個數字（佇列人數、目前可接受的實力差距、
 * 已等待時間），只是前端一直丟掉。現在畫出來：中間是自己，外圈是
 * 同時在找對手的其他人，倒數環轉完就是電腦對手上場。等待因此變成
 * 看得到進度的事，而不是死時間。
 */
.dm-hunt {
    position: relative; width: 168px; height: 168px;
    display: flex; align-items: center; justify-content: center;
}
/* 雷達掃描。用 conic-gradient 轉一圈，比脹大的圈更像「正在搜尋」 */
.dm-hunt-sweep {
    position: absolute; inset: 6px; border-radius: 50%;
    background: conic-gradient(from 0deg, rgba(224,85,79,0) 0deg,
        rgba(224,85,79,0) 250deg, rgba(224,85,79,0.20) 340deg, rgba(224,85,79,0.42) 360deg);
    animation: dmSweep 2.8s linear infinite;
    -webkit-mask: radial-gradient(circle, transparent 34%, #000 36%);
    mask: radial-gradient(circle, transparent 34%, #000 36%);
}
@keyframes dmSweep { to { transform: rotate(360deg); } }

.dm-radar { position: absolute; inset: 22px; }
.dm-radar span {
    position: absolute; inset: 0; border-radius: 50%;
    border: 1px solid #e0554f; opacity: 0; animation: dmRadar 2.8s ease-out infinite;
}
.dm-radar span:nth-child(2) { animation-delay: 0.93s; }
.dm-radar span:nth-child(3) { animation-delay: 1.86s; }
@keyframes dmRadar {
    0% { transform: scale(0.42); opacity: 0.6; }
    100% { transform: scale(1.32); opacity: 0; }
}

/* 倒數環。--dm-hunt-dur 由 dm.js 設成實際的放棄時間，轉完就換電腦對手 */
.dm-hunt-ring { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.dm-hunt-ring-bg, .dm-hunt-ring-arc { fill: none; stroke-width: 2; }
.dm-hunt-ring-bg { stroke: var(--border); }
.dm-hunt-ring-arc {
    stroke: #e0554f; stroke-linecap: round;
    stroke-dasharray: 339.3; stroke-dashoffset: 0;
    animation: dmHuntArc var(--dm-hunt-dur, 25s) linear forwards;
}
@keyframes dmHuntArc { to { stroke-dashoffset: 339.3; } }

/* 佇列上的其他人。--i 是第幾個、--n 是總共幾個，位置由 CSS 算 */
.dm-hunt-orbit { position: absolute; inset: 0; animation: dmSweep 18s linear infinite; }
.dm-hunt-dot {
    position: absolute; left: 50%; top: 50%; width: 9px; height: 9px; margin: -4.5px;
    border-radius: 50%; background: var(--text-sub); opacity: 0.55;
    transform: rotate(calc(360deg * var(--i) / var(--n))) translateY(-78px);
    animation: dmHuntDot 2.4s ease-in-out infinite;
    animation-delay: calc(var(--i) * 0.28s);
}
@keyframes dmHuntDot { 50% { opacity: 0.95; } }

.dm-hunt-face { position: relative; z-index: 1; }
.dm-hunt-face img, .dm-hunt-face > span { display: block; }

.dm-matching-text { font-size: 1rem; letter-spacing: 1.5px; }
.dm-matching-hint { font-size: 0.78rem; color: var(--text-sub); text-align: center; padding: 0 24px; }

/* 三個數字。全部來自伺服器，沒收到就留破折號 —— 不要編一個好看的數字 */
.dm-hunt-stats { display: flex; gap: 10px; width: 100%; max-width: 330px; padding: 0 16px; }
.dm-hunt-stat {
    flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 3px;
    padding: 10px 4px; border: 1px solid var(--border); border-radius: 12px; background: var(--card-bg);
}
.dm-hunt-num { font-size: 1.05rem; font-weight: 600; letter-spacing: 0.5px; font-variant-numeric: tabular-nums; }
.dm-hunt-cap {
    font-size: 0.6rem; color: var(--text-sub); letter-spacing: 0.3px;
    text-align: center; white-space: nowrap;
}
/* 配對畫面比別的 dm-center 高一截 —— 中間多了三個數字，用同一個高度
 * 會整塊擠在上半部，下面留一大片空白 */
.dm-center-hunt { min-height: 74vh; }

@media (prefers-reduced-motion: reduce) {
    .dm-hunt-sweep, .dm-hunt-orbit, .dm-hunt-dot, .dm-radar span { animation: none; }
    .dm-radar span { opacity: 0.25; }
    /* 倒數環留著 —— 它是資訊不是裝飾，但改成不動的滿環 */
    .dm-hunt-ring-arc { animation: none; stroke-dashoffset: 0; }
}

.dm-vs-row { display: flex; align-items: center; gap: 18px; }
.dm-vs-side { text-align: center; flex: 1; min-width: 0; }
.dm-vs-side img, .dm-vs-side > div:first-child { margin: 0 auto; }
.dm-vs-name { margin-top: 10px; font-size: 0.9rem; font-weight: 600; letter-spacing: 0.5px; }
.dm-vs-tag { margin-top: 5px; font-size: 0.68rem; color: var(--text-sub); letter-spacing: 1px; }
.dm-vs-ghost { color: #7c9cff; }
.dm-vs-mark { font-size: 1.5rem; font-weight: 700; color: #e0554f; letter-spacing: 2px; }

.dm-wheel-box { position: relative; width: 240px; }
.dm-wheel-view {
    height: 58px; overflow: hidden; border-radius: 12px;
    border: 1px solid var(--border); background: var(--card-bg);
}
.dm-wheel-item {
    display: flex; align-items: center; justify-content: center;
    font-size: 0.92rem; letter-spacing: 1px;
}
.dm-wheel-line {
    position: absolute; inset: 0; border-radius: 12px;
    border: 1px solid transparent; pointer-events: none; transition: border-color 0.25s;
}
.dm-wheel-locked .dm-wheel-line { border-color: #e0554f; box-shadow: 0 0 0 3px rgba(224,85,79,0.16); }
.dm-wheel-result { font-size: 1.05rem; font-weight: 700; letter-spacing: 1.5px; min-height: 26px; }

/* ── 選定位 ──────────────────────────────────────────────── */
.dm-role-wrap { padding: 6px 0 20px; }
.dm-role-head { margin-bottom: 10px; }
.dm-role-title { font-size: 1.2rem; font-weight: 700; letter-spacing: 1.5px; margin-bottom: 6px; }
.dm-role-sub { font-size: 0.8rem; color: var(--text-sub); }
/* 角色從 3 個變成 8 個之後，原本的尺寸會讓整頁高到 1089px（畫面只有
   844px），倒數 12 秒內要捲 245px 才看得完 —— 等於逼人亂選。
   所以卡片壓扁：留白收掉、字級縮一階、第三行的補充說明只在還放得下
   的畫面上顯示。 */
/* 十個定位要在一頁裡選完。
   單欄排到第十個是 1090px，手機只有 844px —— 有倒數還要捲動，
   等於逼人亂選。改成兩欄，五列就放得下。 */
.dm-roles { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; align-items: stretch; }
.dm-role {
    width: 100%; display: block; text-align: left;
    padding: 10px 12px; background: var(--card-bg);
    border: 1px solid var(--border); border-radius: 12px;
    color: var(--text-main); font-family: inherit; cursor: pointer;
    transition: border-color 0.16s, background 0.16s, transform 0.12s;
}
.dm-role.hidden { display: none; }
.dm-role:active { transform: scale(0.99); }
.dm-role-n { display: block; font-size: 0.88rem; font-weight: 700; letter-spacing: 1px; }
.dm-role-d { display: block; margin-top: 3px; font-size: 0.72rem; color: var(--text-main); opacity: 0.85; line-height: 1.35; }
/* 兩欄的寬度塞不下第三行。技能本身的敘述比「怎麼玩」重要，
   玩法提示在生死戰入口那一頁還看得到。 */
.dm-role-t { display: none; }
.dm-role-on { border-color: #e0554f; background: rgba(224,85,79,0.1); }

/* ── 對戰：血條 ──────────────────────────────────────────── */
/* 導覽列右上角同時放題號與級數，完整的「Level 4 · 中高級」會被切掉，
   所以那裡只放短的「Lv 4」，完整名稱留給滾輪與結算畫面。 */
.dm-hud { display: flex; flex-direction: column; gap: 10px; margin: 4px 0 16px; }
.dm-side {
    padding: 11px 12px; border: 1px solid var(--border);
    border-radius: 13px; background: var(--card-bg);
    transition: border-color 0.2s;
}
.dm-side-top { display: flex; align-items: center; gap: 10px; }
.dm-ava { flex-shrink: 0; }
.dm-side-info { flex: 1; min-width: 0; }
.dm-side-name {
    display: block; font-size: 0.88rem; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dm-side-role { display: block; margin-top: 2px; font-size: 0.7rem; color: var(--text-sub); letter-spacing: 1px; }
.dm-hp { flex-shrink: 0; font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.dm-bar {
    position: relative;
    margin-top: 9px; height: 9px; border-radius: 5px;
    background: rgba(128,128,128,0.22); overflow: hidden;
}
.dm-bar-fill {
    position: absolute; left: 0; top: 0;
    display: block; height: 100%; width: 100%; border-radius: 5px;
    /* 扣血要看得出來「掉了多少」，所以動畫比一般的長一點 */
    transition: width 0.45s cubic-bezier(0.22,1,0.36,1), background 0.3s;
}
/* 殘影：本體立刻縮，這一層等 0.45 秒才追上去。中間露出來的那一截
   就是「你剛剛掉了這麼多」—— 沒有它的話血條只是從一個寬度變成另一個
   寬度，看不出來掉了多少。 */
.dm-bar-ghost {
    position: absolute; left: 0; top: 0;
    display: block; height: 100%; width: 100%; border-radius: 5px;
    background: rgba(255,255,255,0.55);
    transition: width 0.55s ease 0.45s;
}
.dm-bar-me { background: #3fb98a; }
.dm-bar-foe { background: #e0554f; }
.dm-pips { display: flex; gap: 14px; margin-top: 9px; }
.dm-pip-g { display: flex; gap: 4px; }
.dm-pip {
    width: 16px; height: 4px; border-radius: 2px;
    background: rgba(128,128,128,0.3);
}
.dm-pip-on { background: #3fb98a; }
.dm-pip-shield .dm-pip-on { background: #7c9cff; }
.dm-pip-slow-wrap { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.dm-pip-slow-wrap.hidden { display: none; }
.dm-pip-slow-label { font-size: .67rem; line-height: 1; color: #ffd27a; font-weight: 700; }
.dm-pip-slow .dm-pip { width: 12px; }
.dm-pip-slow .dm-pip-on { background: #ffd27a; box-shadow: 0 0 5px rgba(255, 210, 122, .5); }

/* 挨打的那一邊抖一下。位移要小 —— 大幅度的抖動在手機上會讓人想吐 */
.dm-shake { animation: dmShake 0.4s ease; }
@keyframes dmShake {
    0%, 100% { transform: translateX(0); }
    15% { transform: translateX(-5px); }
    35% { transform: translateX(4px); }
    55% { transform: translateX(-3px); }
    75% { transform: translateX(2px); }
}

/* ── 對戰：作答 ──────────────────────────────────────────── */
/* 技能鈕是 fixed 的，會浮在內容上面。底部留出它的高度，
   不然最後一個選項永遠被蓋住一半。 */
.dm-stage { position: relative; min-height: 340px; padding-bottom: 78px; }
.dm-phase.hidden { display: none; }
.dm-clock { margin-bottom: 18px; }
.dm-clock-bar {
    height: 5px; border-radius: 3px;
    background: rgba(128,128,128,0.22); overflow: hidden;
}
.dm-clock-bar > span {
    display: block; height: 100%; width: 100%;
    background: #00bcd4; border-radius: 3px;
    transition: width 0.1s linear, background 0.3s;
}
.dm-clock-hot .dm-clock-bar > span { background: #e0554f; }
.dm-clock-num {
    margin-top: 6px; text-align: right; font-size: 0.78rem;
    color: var(--text-sub); font-variant-numeric: tabular-nums;
}
.dm-clock-hot .dm-clock-num { color: #e0554f; }
.dm-word {
    text-align: center; font-size: 2rem; font-weight: 700;
    letter-spacing: 1px; margin: 22px 0 26px; word-break: break-word;
}
.dm-word canvas { display: block; max-width: 100%; margin: 0 auto; }
.dm-options { display: flex; flex-direction: column; gap: 9px; }
.dm-option {
    width: 100%; padding: 15px 14px;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 12px; color: var(--text-main);
    font-family: inherit; font-size: 0.92rem; cursor: pointer;
    transition: border-color 0.14s, background 0.14s, transform 0.1s;
}
.dm-option:active:not(:disabled) { transform: scale(0.99); }
.dm-option:disabled { cursor: default; }
.dm-option-right { border-color: #3fb98a; background: rgba(63,185,138,0.14); }
.dm-option-wrong { border-color: #e0554f; background: rgba(224,85,79,0.12); }
@keyframes dmSubmitPulse {
    0% { transform: scale(1); }
    50% { transform: scale(0.97); }
    100% { transform: scale(1); }
}
.dm-option.dm-option-submitted {
    box-shadow: inset 0 0 0 2px var(--accent, #fff);
    animation: dmSubmitPulse 0.25s ease-out both;
}
@keyframes dmOwnFeedback {
    0% { transform: scale(0.97); }
    55% { transform: scale(1.025); }
    100% { transform: scale(1); }
}
.dm-option.dm-option-own-feedback { animation: dmOwnFeedback 0.32s ease-out both; }
.dm-note { margin-top: 12px; text-align: center; font-size: 0.78rem; color: var(--text-sub); min-height: 18px; }
.dm-note.dm-waiting { display: flex; align-items: center; justify-content: center; gap: 8px; }
.dm-note.dm-waiting::before {
    content: ''; width: 12px; height: 12px; flex: 0 0 12px;
    border: 2px solid currentColor; border-right-color: transparent;
    border-radius: 50%; animation: dmWaitSpin 0.8s linear infinite;
}
@keyframes dmWaitSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .dm-note.dm-waiting::before { animation: none; border-right-color: currentColor; }
}

/* 被偷時間：題目真的看不到，不是只把秒數扣掉 */
.dm-veil {
    position: absolute; inset: 0; z-index: 3;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
    /* 這裡不能用 var(--card-bg) —— 多數主題是半透明的，題目會透出來，
       那就等於沒遮 */
    background: #12161c; border-radius: 14px;
}
.dm-veil.hidden { display: none; }
.dm-veil-t { font-size: 0.86rem; color: #e0554f; letter-spacing: 2px; }
.dm-veil-n { font-size: 3rem; font-weight: 700; font-variant-numeric: tabular-nums; color: #fff; }
.dm-veil-s { font-size: 0.78rem; color: rgba(255,255,255,0.55); }

/* ── 對戰：決策 ──────────────────────────────────────────── */
.dm-decide-head { text-align: center; margin: 10px 0 22px; }
.dm-decide-title { font-size: 1.25rem; font-weight: 700; letter-spacing: 1.5px; }
.dm-decide-sub { margin-top: 7px; font-size: 0.84rem; color: var(--text-sub); line-height: 1.5; }
/* 「為什麼是他出手」。這一行的存在理由是：兩邊都答對時比的是快慢，
   不講的話玩家只會覺得自己答對了卻被打，是程式壞掉。 */
.dm-decide-why {
    margin-top: 10px; font-size: 0.76rem; letter-spacing: 1px;
    color: var(--text-sub); opacity: 0.9;
}
.dm-decide-count {
    margin-top: 14px; font-size: 2.2rem; font-weight: 700;
    font-variant-numeric: tabular-nums; color: #e0554f;
}
.dm-choices { display: flex; flex-direction: column; gap: 11px; }
.dm-choices.hidden { display: none; }
.dm-choice.hidden { display: none; }
.dm-choice {
    width: 100%; display: block; text-align: left;
    padding: 17px 16px; background: var(--card-bg);
    border: 1px solid var(--border); border-radius: 14px;
    color: var(--text-main); font-family: inherit; cursor: pointer;
    transition: border-color 0.14s, background 0.14s, transform 0.1s, opacity 0.14s;
}
.dm-choice:active:not(:disabled) { transform: scale(0.99); }
.dm-choice:disabled { opacity: 0.4; cursor: default; }
.dm-choice-n { display: block; font-size: 1rem; font-weight: 700; letter-spacing: 1.5px; }
.dm-choice-d { display: block; margin-top: 5px; font-size: 0.78rem; color: var(--text-sub); }
.dm-choice-atk { border-color: rgba(224,85,79,0.4); }
.dm-choice-shield { border-color: rgba(124,156,255,0.4); }
.dm-choice-heal { border-color: rgba(63,185,138,0.4); }
.dm-choice-burst { border-color: rgba(95,208,255,0.5); }
/* 快慢直接畫在行動鈕上；底邊的能量條讓玩家不用讀說明也看得到增減。
   動畫只動裝飾層，按鈕本身不位移，避免限時選擇時誤觸。 */
body.dm-playing .dm-choice[data-pace-label] { position: relative; overflow: hidden; }
body.dm-playing .dm-choice[data-pace-label] .dm-choice-n { padding-right: 45px; }
body.dm-playing .dm-choice[data-pace-label]::before {
    content: attr(data-pace-label);
    position: absolute; top: 7px; right: 7px;
    padding: 3px 6px; border-radius: 7px;
    font-size: 0.65rem; font-weight: 800; letter-spacing: 0;
    line-height: 1.2; pointer-events: none;
    animation: dmPaceTagIn 0.42s cubic-bezier(.2,1.4,.4,1) both;
}
body.dm-playing .dm-choice[data-pace-label]::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: 0;
    height: 4px; pointer-events: none; transform-origin: left center;
}
body.dm-playing .dm-choice.dm-pace-fast {
    border-color: rgba(255, 207, 92, .82);
    background: linear-gradient(120deg, rgba(255, 197, 73, .13), var(--card-bg));
}
body.dm-playing .dm-choice.dm-pace-fast::before { color: #251a05; background: #ffd27a; }
body.dm-playing .dm-choice.dm-pace-fast::after {
    background: #ffd27a; animation: dmPaceGain .65s ease-out both;
}
body.dm-playing .dm-choice.dm-pace-slow {
    border-color: rgba(255, 126, 144, .72);
    background: linear-gradient(120deg, rgba(240, 98, 123, .12), var(--card-bg));
}
body.dm-playing .dm-choice.dm-pace-slow::before { color: #fff; background: #aa3655; }
body.dm-playing .dm-choice.dm-pace-slow::after {
    background: #ed7891; animation: dmPaceLoss .65s ease-out both;
}
body.dm-playing .dm-choice.dm-pace-fast .dm-choice-d { color: #ffe0a4; }
body.dm-playing .dm-choice.dm-pace-slow .dm-choice-d { color: #ffc3ce; }
@keyframes dmPaceTagIn {
    from { opacity: 0; transform: translateY(-7px) scale(.82); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes dmPaceGain { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes dmPaceLoss { from { transform: scaleX(1); } to { transform: scaleX(.5); } }
@media (prefers-reduced-motion: reduce) {
    body.dm-playing .dm-choice[data-pace-label]::before,
    body.dm-playing .dm-choice[data-pace-label]::after { animation: none; }
    body.dm-playing .dm-choice.dm-pace-slow::after { transform: scaleX(.5); }
}
/* 按下去之後其他按鈕會 disabled 變淡，選中的這顆要維持全亮 —— 
   不然會看起來像「我剛剛按的那個也沒生效」 */
.dm-choice-on { opacity: 1 !important; border-width: 2px; background: rgba(255,255,255,0.06); }

/* ── 決策窗：選了什麼要一眼看得出來 ──────────────────────────
   玩家回報「我不知道有沒有點下去」。原本選中只差一級邊框，在對戰
   那種緊張的兩秒裡根本分不出來。所以選中的那一顆整個亮起來、外面
   多一圈光，沒選的那一顆退到背景去。
   ────────────────────────────────────────────────────────── */
.dm-choice-on {
    box-shadow: 0 0 0 2px rgba(255, 152, 0, 0.55), 0 0 18px rgba(255, 152, 0, 0.18);
    border-color: #ff9800 !important;
    background: rgba(255, 152, 0, 0.1) !important;
}
.dm-choice-dim { opacity: 0.35; }
/* 送出去之後換成綠的 —— 「選好了」跟「已經送出去了」是兩件事 */
.dm-choice-sent {
    box-shadow: 0 0 0 2px rgba(63, 185, 138, 0.6), 0 0 18px rgba(63, 185, 138, 0.2);
    border-color: #3fb98a !important;
    background: rgba(63, 185, 138, 0.1) !important;
    opacity: 1 !important;
}

/* 確定鈕。裡面那條會自己跑完 —— 跑完就自動送出，所以玩家看得到
   「我還有多久可以改」，而不是被一個看不見的計時器偷走選擇。 */
.dm-commit {
    position: relative; overflow: hidden;
    width: 100%; margin-top: 12px; padding: 15px 16px;
    border: 1px solid #ff9800; border-radius: 14px;
    background: transparent; color: var(--text-main);
    font-family: inherit; font-size: 0.95rem; font-weight: 700; letter-spacing: 1.5px;
    cursor: pointer;
}
.dm-commit.hidden { display: none; }
.dm-commit:active:not(:disabled) { transform: scale(0.99); }
.dm-commit.on { border-color: #3fb98a; color: #3fb98a; cursor: default; }
/* 還沒選東西的時候：在那裡、但明顯按不下去。
   這樣玩家一進決策窗就知道「要選、然後要送出」是兩步。 */
.dm-commit-idle {
    border-color: var(--border);
    color: var(--text-sub);
    font-weight: 500;
    cursor: default;
}
.dm-commit:disabled { cursor: default; }
.dm-commit-fill {
    position: absolute; inset: 0; width: 0;
    background: rgba(255, 152, 0, 0.22);
    pointer-events: none;
}
.dm-commit-label { position: relative; }
@keyframes dmCommitDrain { from { width: 0; } to { width: 100%; } }
@media (prefers-reduced-motion: reduce) {
    .dm-commit-fill { animation: none !important; }
}

/* ── 選定位：鎖定 ─────────────────────────────────────────────
   兩邊明明都選好了還要等倒數跑完，玩家覺得莫名其妙。
   鎖定之後對方看得到，兩邊都鎖就直接開打。
   ────────────────────────────────────────────────────────── */
.dm-role-lock {
    width: 100%; margin-top: 14px; padding: 15px;
    border: 1px solid #ff9800; border-radius: 14px;
    background: transparent; color: #ff9800;
    font-family: inherit; font-size: 0.95rem; font-weight: 700; letter-spacing: 1.5px;
    cursor: pointer; transition: opacity .15s;
}
.dm-role-lock:disabled { opacity: 0.32; cursor: default; border-color: var(--border); color: var(--text-sub); }
.dm-role-lock:active:not(:disabled) { transform: scale(0.99); }
.dm-role-lock.on { border-color: #3fb98a; color: #3fb98a; }
.dm-role-foe {
    margin-top: 8px; font-size: 0.78rem; letter-spacing: 1px; color: #3fb98a;
}
.dm-role-foe.hidden { display: none; }

/* ── 對戰：結算演出 ──────────────────────────────────────── */
.dm-reveal {
    min-height: 300px; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 12px; text-align: center;
}
.dm-reveal-title { font-size: 1.7rem; font-weight: 700; letter-spacing: 2px; }
.dm-reveal-sub { font-size: 0.88rem; color: var(--text-sub); line-height: 1.6; }

/* ── 偷時間按鈕 ──────────────────────────────────────────── */
.dm-steal {
    position: fixed; right: 16px; bottom: 22px; z-index: 40;
    display: flex; align-items: center; gap: 8px;
    padding: 13px 17px; border-radius: 26px;
    background: #12161c; border: 1px solid var(--border);
    color: var(--text-main); font-family: inherit; font-size: 0.84rem;
    letter-spacing: 1px; cursor: pointer;
    box-shadow: 0 6px 20px rgba(0,0,0,0.4);
    transition: border-color 0.2s, opacity 0.2s, transform 0.12s;
}
.dm-steal.hidden { display: none; }
.dm-steal:disabled { opacity: 0.45; cursor: default; }
.dm-steal:active:not(:disabled) { transform: scale(0.97); }
.dm-steal-icon {
    width: 9px; height: 9px; border-radius: 50%;
    background: rgba(128,128,128,0.5); flex-shrink: 0;
}
.dm-steal-ready { border-color: #c98bff; }
.dm-steal-ready .dm-steal-icon { background: #c98bff; animation: dmPulse 1.4s ease-in-out infinite; }
.dm-steal-armed { border-color: #c98bff; background: rgba(201,139,255,0.16); }
.dm-steal-armed .dm-steal-icon { background: #c98bff; }
@keyframes dmPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(201,139,255,0.55); }
    70% { box-shadow: 0 0 0 7px rgba(201,139,255,0); }
}

/* ── 橫幅（生死時刻）─────────────────────────────────────── */
/* 橫幅蓋在對戰畫面正中央。一定要有自己的底色 —— 只放文字的話會直接
   壓在血條上，兩層字疊在一起誰都看不清楚。 */
.dm-banner {
    position: fixed; left: 0; right: 0; top: 42%; z-index: 60;
    padding: 26px 16px; text-align: center; pointer-events: none;
    background: linear-gradient(90deg,
        rgba(10,12,16,0) 0%, rgba(10,12,16,0.94) 12%,
        rgba(10,12,16,0.94) 88%, rgba(10,12,16,0) 100%);
    opacity: 0; transform: scale(0.92);
    transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.22,1,0.36,1);
}
.dm-banner.hidden { display: none; }
.dm-banner-in { opacity: 1; transform: scale(1); }
.dm-banner-title {
    font-size: 2.1rem; font-weight: 700; letter-spacing: 6px;
    color: #e0554f; text-shadow: 0 2px 24px rgba(224,85,79,0.5);
}
.dm-banner-sub { margin-top: 10px; font-size: 0.82rem; color: rgba(255,255,255,0.72); }

/* ── 全域狀態 ────────────────────────────────────────────── */
/* 瀕死：畫面邊緣壓一圈紅。用 body::after 而不是改各個元件的顏色，
   這樣它蓋在所有東西上面，而且一個 class 就能開關 */
body.dm-critical::after {
    content: ''; position: fixed; inset: 0; z-index: 30; pointer-events: none;
    box-shadow: inset 0 0 90px rgba(224,85,79,0.5);
    animation: dmCrit 1.1s ease-in-out infinite;
}
@keyframes dmCrit {
    0%, 100% { opacity: 0.55; }
    50% { opacity: 1; }
}
/* 生死時刻：整個畫面往下沉一點，血條也變得更刺眼 */
body.dm-sudden .dm-bar-foe { background: #ff6b63; }
body.dm-sudden .dm-word { color: #ffd9d7; }
body.dm-sudden .dm-side { border-color: rgba(224,85,79,0.35); }
/* 被偷時間的瞬間閃一下 */
body.dm-stolen .dm-stage { animation: dmStolen 0.5s ease; }
@keyframes dmStolen {
    0% { filter: brightness(1.6) saturate(0.2); }
    100% { filter: none; }
}
/* 反作弊：切出畫面就把題目糊掉 */
body.dm-guard .dm-word,
body.dm-guard .dm-options { filter: blur(11px); }

/* ── 結算 ────────────────────────────────────────────────── */
.dm-result-wrap { padding: 10px 0 40px; }
.dm-result-title { text-align: center; font-size: 1.9rem; font-weight: 700; letter-spacing: 3px; }
.dm-r-win { color: #3fb98a; }
.dm-r-lose { color: #e0554f; }
.dm-r-draw { color: var(--text-sub); }
.dm-result-sub { margin-top: 8px; text-align: center; font-size: 0.8rem; color: var(--text-sub); }
.dm-score-cards { display: flex; gap: 10px; margin-top: 24px; }
.dm-score-card {
    flex: 1; min-width: 0; text-align: center;
    padding: 18px 10px; background: var(--card-bg);
    border: 1px solid var(--border); border-radius: 14px;
}
.dm-score-name {
    font-size: 0.82rem; color: var(--text-sub);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dm-score-num { margin-top: 8px; font-size: 1.8rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.dm-score-sub { margin-top: 5px; font-size: 0.72rem; color: var(--text-sub); }
.dm-points { margin-top: 18px; text-align: center; font-size: 1.05rem; font-weight: 600; color: #f0c040; }
.dm-points-none { color: var(--text-sub); font-weight: 400; font-size: 0.85rem; }
.dm-bot-note {
    margin-top: 12px; padding: 11px 13px; border-radius: 11px;
    border: 1px solid var(--border); font-size: 0.76rem;
    color: var(--text-sub); line-height: 1.55; text-align: center;
}
.dm-bot-note.hidden { display: none; }
.dm-wrong-wrap { margin-top: 20px; }
.dm-wrong-title { font-size: 0.78rem; color: var(--text-sub); letter-spacing: 2px; margin-bottom: 10px; }
.dm-wrong-row {
    display: flex; justify-content: space-between; gap: 12px;
    padding: 11px 13px; border: 1px solid var(--border);
    border-radius: 10px; margin-bottom: 7px; font-size: 0.85rem;
}
.dm-wrong-en { font-weight: 600; }
.dm-wrong-zh { color: var(--text-sub); }
.dm-wrong-empty { font-size: 0.8rem; color: var(--text-sub); text-align: center; padding: 14px 0; }

/* 收進錯字本。按下去之後自己變成一句回報，不用再跳彈窗打斷結算畫面。 */
.dm-wrong-save {
    width: 100%; margin-top: 10px; padding: 12px;
    border: 1px solid var(--border); border-radius: 10px;
    background: transparent; color: var(--text);
    font-size: 0.85rem; font-weight: 600; letter-spacing: 1px;
    cursor: pointer; transition: opacity .15s, border-color .15s;
}
.dm-wrong-save:active { opacity: 0.7; }
.dm-wrong-save.on, .dm-wrong-save:disabled {
    cursor: default; opacity: 1;
    border-color: var(--accent, var(--border));
    color: var(--text-sub);
}
.dm-wrong-note {
    font-size: 0.72rem; color: var(--text-sub);
    text-align: center; margin-top: 8px; line-height: 1.5;
}

/* ── 錯字整理台 ──────────────────────────────────────────────
   對戰錯的字先在這裡分組，玩家自己決定合併成哪一本單字簿。
   一場一組，所以卡片會很多，密度要壓低一點才不會變成一面牆。
   ────────────────────────────────────────────────────────── */
.wi-entry {
    width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 14px 16px; margin-bottom: 16px;
    border: 1px solid var(--border); border-radius: 12px;
    background: transparent; color: var(--text-main);
    font-family: inherit; text-align: left; cursor: pointer;
    transition: border-color .2s;
}
.wi-entry:active { transform: scale(0.99); }
.wi-entry-busy { border-color: #ff9800; }
.wi-entry-main { min-width: 0; }
.wi-entry-name { display: block; font-size: 0.92rem; font-weight: 600; }
.wi-entry-sub { display: block; font-size: 0.74rem; color: var(--text-sub); margin-top: 3px; }
.wi-entry-go { flex-shrink: 0; font-size: 0.78rem; color: #ff9800; letter-spacing: 1px; }

.wi-summary { font-size: 0.8rem; color: var(--text-sub); letter-spacing: 1px; margin: 4px 2px 14px; }
.wi-hint {
    font-size: 0.78rem; line-height: 1.6; color: var(--text-sub);
    border: 1px solid rgba(255, 152, 0, 0.35); border-radius: 10px;
    padding: 11px 13px; margin-bottom: 14px;
}
.wi-hint.hidden, .wi-empty.hidden { display: none; }
.wi-empty {
    font-size: 0.84rem; line-height: 1.8; color: var(--text-sub);
    text-align: center; padding: 48px 20px;
}

.wi-card {
    border: 1px solid var(--border); border-radius: 12px;
    margin-bottom: 10px; overflow: hidden;
    transition: border-color .15s;
}
.wi-card.wi-on { border-color: #ff9800; }
.wi-head {
    width: 100%; display: flex; align-items: center; gap: 12px;
    padding: 13px 14px; background: transparent; border: none;
    color: var(--text-main); font-family: inherit; text-align: left; cursor: pointer;
}
.wi-box {
    flex-shrink: 0; width: 18px; height: 18px; border-radius: 5px;
    border: 1px solid var(--text-sub);
}
.wi-box-on { border-color: #ff9800; background: #ff9800; }
.wi-head-main { min-width: 0; }
.wi-name { display: block; font-size: 0.9rem; font-weight: 600; }
.wi-sub { display: block; font-size: 0.73rem; color: var(--text-sub); margin-top: 3px; }

.wi-tools { display: flex; gap: 8px; padding: 0 14px 12px 44px; }
.wi-tool {
    padding: 5px 12px; border-radius: 999px;
    border: 1px solid var(--border); background: transparent;
    color: var(--text-sub); font-family: inherit; font-size: 0.72rem; cursor: pointer;
}
.wi-tool:active { opacity: 0.6; }

.wi-words { border-top: 1px solid var(--border); padding: 6px 14px 10px; }
.wi-sub-title {
    font-size: 0.7rem; color: var(--text-sub); letter-spacing: 1px;
    margin: 10px 0 4px;
}
.wi-word {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 5px 10px;
    padding: 8px 0; font-size: 0.83rem;
    border-bottom: 1px solid var(--border);
}
.wi-word:last-child { border-bottom: none; }
.wi-w-en { grid-column: 1; grid-row: 1; font-weight: 600; overflow-wrap: anywhere; }
.wi-w-zh { flex: 1; min-width: 0; color: var(--text-sub); font-size: 0.78rem;
           grid-column: 1; grid-row: 2; overflow-wrap: anywhere; }
/* 一直錯的那幾個字才是該先念的，所以只有錯過不只一次的會標出來 */
.wi-w-hot {
    flex-shrink: 0; font-size: 0.68rem; letter-spacing: 0.5px;
    color: #ff9800; border: 1px solid rgba(255, 152, 0, 0.4);
    border-radius: 999px; padding: 2px 8px;
}
.wi-w-review { color: var(--text-sub); border-color: var(--border); }
.wi-word .wi-w-hot { grid-column: 2; grid-row: 1; justify-self: end; }
.wi-word .wi-w-del { grid-column: 2; grid-row: 2; justify-self: end; }
.wi-w-del {
    flex-shrink: 0; width: 26px; height: 26px; line-height: 1;
    border: none; background: transparent; color: var(--text-sub);
    font-size: 1.1rem; cursor: pointer;
}

.wi-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 800;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    background: var(--card-bg); border-top: 1px solid var(--border);
}
.wi-bar.hidden { display: none; }
.wi-bar-count { font-size: 0.76rem; color: var(--text-sub); margin-bottom: 9px; letter-spacing: 1px; }
.wi-bar-btns { display: flex; gap: 8px; }
.wi-act {
    flex: 1; padding: 11px 4px; border-radius: 10px;
    border: 1px solid var(--border); background: transparent;
    color: var(--text-main); font-family: inherit; font-size: 0.8rem; cursor: pointer;
}
.wi-act:disabled { opacity: 0.3; cursor: default; }
.wi-act-go { border-color: #ff9800; color: #ff9800; flex: 1.6; }
.wi-act-del { color: var(--text-sub); }

#wi-dest-overlay {
    position: fixed; inset: 0; z-index: 9000;
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
    background: rgba(0, 0, 0, 0.78);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    opacity: 0; transition: opacity 0.2s;
}
#wi-dest-overlay.show { opacity: 1; }
#wi-dest-overlay.hidden { display: none !important; }
#wi-dest-overlay.show .fr-send-box {
    animation: frBoxIn 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* 內層清單滑到底不要把整頁一起帶著跑 */
#wi-dest-list { overscroll-behavior-y: contain; }


/* ── 生死戰：打擊感 ──────────────────────────────────────────
   血條從 150 換成 122 只是一個數字換成另一個數字。要讓它像「被打到」，
   得同時給三種訊號：數字在跑（countTo）、血條後面留一截殘影、
   傷害數字從挨打那一側浮上來。三個少一個都會覺得少了什麼。
   ────────────────────────────────────────────────────────── */

.dm-side { position: relative; }

/* 靠右但要讓開血量數字 —— 疊在一起的話「-21」跟「130」會糊成一團，
   那是這個回饋唯一要傳達的兩個數字 */
.dm-float {
    position: absolute; right: 68px; top: 10px;
    pointer-events: none; z-index: 5;
}
.dm-float-n {
    display: block; text-align: right;
    font-size: 1.5rem; font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 2px 10px rgba(0,0,0,0.6);
    animation: dmFloat 1.05s cubic-bezier(0.22,1,0.36,1) both;
}
.dm-float-dmg { color: #ff6b63; }
/* 減免過的傷害用另一個顏色。玩家要一眼看出「我答對了所以這一下比較輕」，
   靠下面那行小字是看不到的 */
.dm-float-soft { color: #ffc46b; font-size: 1.3rem; }
.dm-float-heal { color: #4fd8a0; }
.dm-float-block { color: #9db8ff; font-size: 1.15rem; letter-spacing: 2px; }
.dm-float-chip { color: var(--text-sub); font-size: 1.1rem; }
@keyframes dmFloat {
    0% { opacity: 0; transform: translateY(6px) scale(0.85); }
    18% { opacity: 1; transform: translateY(-2px) scale(1.12); }
    35% { transform: translateY(-8px) scale(1); }
    100% { opacity: 0; transform: translateY(-34px) scale(0.95); }
}

/* 挨打／擋下／回血的一瞬間，那一整格閃一下。
   畫在 .dm-side-fx 上，不畫在卡片本身 —— 理由見下面「特效層」那一段。 */
.dm-side-fx.dm-flash-hit { animation: dmFlashHit 0.5s ease both; }
.dm-side-fx.dm-flash-block { animation: dmFlashBlock 0.5s ease both; }
.dm-side-fx.dm-flash-heal { animation: dmFlashHeal 0.6s ease both; }
/* 三個閃爍現在畫在 .dm-side-fx 那一層上。
   那一層沒有邊框、而且蓋在卡片底色上面，所以：
   邊框的高光改用 inset box-shadow，結尾一律退到全透明 ——
   原本結尾是 background: var(--card-bg)，在覆蓋層上那是一塊
   不透明的色塊，會一直蓋著卡片直到 class 被收掉。 */
@keyframes dmFlashHit {
    0%   { background: rgba(224,85,79,0.30); box-shadow: inset 0 0 0 1px rgba(255,107,99,0.9); }
    100% { background: rgba(224,85,79,0);    box-shadow: inset 0 0 0 1px rgba(255,107,99,0); }
}
@keyframes dmFlashBlock {
    0%   { background: rgba(124,156,255,0.28); box-shadow: inset 0 0 0 1px rgba(157,184,255,0.9); }
    100% { background: rgba(124,156,255,0);    box-shadow: inset 0 0 0 1px rgba(157,184,255,0); }
}
@keyframes dmFlashHeal {
    0%   { background: rgba(63,185,138,0.26); box-shadow: inset 0 0 0 1px rgba(79,216,160,0.9); }
    100% { background: rgba(63,185,138,0);    box-shadow: inset 0 0 0 1px rgba(79,216,160,0); }
}

/* 階段切換。一回合切三次、一整場四五十次，硬跳就是「不順」的來源。 */
.dm-phase-in { animation: dmPhaseIn 0.32s cubic-bezier(0.22,1,0.36,1) both; }
@keyframes dmPhaseIn {
    from { opacity: 0; transform: translateY(14px); }
    to { opacity: 1; transform: translateY(0); }
}

/* 選項一個一個進場（延遲由 JS 逐顆設定），四個同時蹦出來會像畫面閃了一下 */
.dm-option { animation: dmOptIn 0.3s cubic-bezier(0.22,1,0.36,1) both; }
@keyframes dmOptIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

/* 題目本身也要進場，不然換題時只有選項在動，單字是瞬間換掉的 */
.dm-phase-in .dm-word { animation: dmWordIn 0.38s cubic-bezier(0.22,1,0.36,1) both; }
@keyframes dmWordIn {
    from { opacity: 0; transform: scale(0.92); letter-spacing: 6px; }
    to { opacity: 1; transform: scale(1); letter-spacing: 1px; }
}

/* 結算那一句要有重量，尤其是「你挨了一擊」 */
.dm-phase-in .dm-reveal-title { animation: dmRevealPop 0.42s cubic-bezier(0.22,1,0.36,1) both; }
.dm-phase-in .dm-reveal-sub { animation: dmPhaseIn 0.4s ease 0.1s both; }
@keyframes dmRevealPop {
    0% { opacity: 0; transform: scale(0.7); }
    55% { opacity: 1; transform: scale(1.08); }
    100% { opacity: 1; transform: scale(1); }
}

/* 決策窗的兩顆按鈕：這是整局最需要玩家立刻注意的地方 */
.dm-phase-in .dm-choice { animation: dmOptIn 0.3s cubic-bezier(0.22,1,0.36,1) both; }
.dm-phase-in .dm-choice:nth-child(2) { animation-delay: 60ms; }
.dm-phase-in .dm-decide-count { animation: dmRevealPop 0.4s cubic-bezier(0.22,1,0.36,1) both; }

/* 倒數剩不到 3.5 秒時整條會跳，提醒得比變紅明顯 */
.dm-clock-hot .dm-clock-num { animation: dmTick 1s ease-in-out infinite; }
@keyframes dmTick {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.18); }
}

/* 會動的東西一多，暈車的人就受不了。系統層級關掉動態效果時全部收起來，
   只留最基本的淡入 —— 資訊照樣看得到，畫面不再動。 */
@media (prefers-reduced-motion: reduce) {
    .dm-float-n, .dm-phase-in, .dm-option, .dm-phase-in .dm-word,
    .dm-phase-in .dm-reveal-title, .dm-phase-in .dm-reveal-sub,
    .dm-phase-in .dm-choice, .dm-phase-in .dm-decide-count,
    .dm-flash-hit, .dm-flash-block, .dm-flash-heal,
    .dm-shake, .dm-clock-hot .dm-clock-num {
        animation: none !important;
    }
    .dm-bar-fill, .dm-bar-ghost { transition: none !important; }
    .dm-float-n { opacity: 1; }
    body.dm-critical::after { animation: none; opacity: 0.7; }
}

/* ── 自製鍵盤：長按選重音 ────────────────────────────────────
   給少數人用的：學德文法文捷克文，或單字簿裡本來就有 café、naïve、
   Dvořák 這種字的人。長按不是會誤觸的手勢，所以不需要另外做開關藏它。
   ────────────────────────────────────────────────────────── */
.kb-acc {
    position: absolute; z-index: 30;
    display: flex; gap: 2px; padding: 5px;
    /* 不能用 var(--card-bg) —— 多數主題是半透明的，底下的按鍵會透出來，
       那正是這一排最不能發生的事（要能看清楚選了哪一個） */
    background: #1b2028;
    border: 1px solid rgba(255,255,255,0.14);
    border-radius: 12px;
    box-shadow: 0 8px 26px rgba(0,0,0,0.55);
    animation: kbAccIn 0.14s cubic-bezier(0.22,1,0.36,1) both;
}
@keyframes kbAccIn {
    from { opacity: 0; transform: translateY(6px) scale(0.94); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
.kb-acc-opt {
    min-width: 34px; height: 42px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.15rem; color: #e8ecf1;
    border-radius: 8px;
    transition: background 0.1s, transform 0.1s;
}
.kb-acc-on {
    background: #00bcd4; color: #05080c;
    transform: scale(1.12);
}

/* ── 無傷更新的提示 ────────────────────────────────────────────────
   只在「有新版、但現在重載會弄壞東西」的時候出現（練習中、對戰中）。
   不擋任何操作，使用者也不用理它 —— 事情結束回到首頁就會自己更新。
   放在底部導覽列上面一點，才不會蓋到按鈕。 */
.silen-update-note {
    position: fixed;
    left: 50%;
    bottom: calc(var(--bnav-h, 64px) + 14px);
    transform: translateX(-50%);
    z-index: 9000;
    max-width: calc(100vw - 32px);
    padding: 8px 16px;
    border-radius: 999px;
    background: rgba(24, 24, 28, 0.92);
    color: #e8e8ea;
    border: 1px solid rgba(255, 255, 255, 0.14);
    font-size: 13px;
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.38);
    cursor: pointer;
    animation: silen-update-in 0.32s ease both;
}

@keyframes silen-update-in {
    from { opacity: 0; transform: translateX(-50%) translateY(8px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* ── 賭命者：押注 ──────────────────────────────────────────────────
   跟偷時間同一個位置的設計語彙，但用暖色 —— 它是「押上去會痛」的動作，
   不該看起來跟其他技能一樣安全。按下去就鎖住，不能看到題目再反悔。 */
.dm-bet {
    position: fixed; right: 16px; bottom: 22px; z-index: 40;
    display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
    padding: 11px 17px; border-radius: 26px;
    background: #12161c; border: 1px solid var(--border);
    color: var(--text-main); font-family: inherit; font-size: 0.84rem;
    letter-spacing: 1px; cursor: pointer;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
    transition: border-color 0.2s, opacity 0.2s, transform 0.12s, background 0.2s;
}
.dm-bet.hidden { display: none; }
.dm-bet:disabled { opacity: 0.45; cursor: default; }
.dm-bet:active:not(:disabled) { transform: scale(0.97); }
.dm-bet-sub {
    font-size: 0.66rem; letter-spacing: 0.4px; opacity: 0.55;
}
.dm-bet-on {
    border-color: #ffb03a;
    background: linear-gradient(180deg, #1d1710, #12161c);
}
.dm-bet-on #dm-bet-label { color: #ffb03a; }

/* ── 預言家：跟偷時間同一個位置，兩者不會同時出現 ───────────── */
/* 名字不能叫 dm-reveal —— 那個早就被每回合的結算面板用掉了
   （#dm-phase-reveal 裡的 .dm-reveal / .dm-reveal-title / .dm-reveal-sub）。
   撞名的結果是按鈕套到面板的字級，變成一個 300px 高的方塊蓋住選項。 */
.dm-seer {
    position: fixed; right: 16px; bottom: 22px; z-index: 40;
    display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
    padding: 11px 17px; border-radius: 26px;
    background: #12161c; border: 1px solid var(--border);
    color: var(--text-main); font-family: inherit; font-size: 0.84rem;
    letter-spacing: 1px; cursor: pointer;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
    transition: border-color 0.2s, opacity 0.2s, transform 0.12s, background 0.2s;
}
.dm-seer.hidden { display: none; }
.dm-seer:disabled { opacity: 0.45; cursor: default; }
.dm-seer:active:not(:disabled) { transform: scale(0.97); }
.dm-seer-sub { font-size: 0.66rem; letter-spacing: 0.4px; opacity: 0.55; }
.dm-seer-on { border-color: #8ad4a0; background: linear-gradient(180deg, #101d16, #12161c); }
.dm-seer-on #dm-seer-label { color: #8ad4a0; }

/* 被預言劃掉的選項。
   不隱藏 —— 位置一變玩家會點錯。但要一眼就看得出它死了：
   邊框、底色、文字全部熄掉，連刪除線都壓暗。原本只調了 opacity，
   在對戰畫面那個暗底上幾乎看不出差別。 */
.dm-option-cut,
.dm-option-cut:disabled {
    opacity: 1;                       /* 交給下面的顏色自己講，不靠半透明 */
    background: transparent !important;
    border-color: rgba(128, 128, 128, 0.14) !important;
    color: rgba(150, 150, 150, 0.3) !important;
    box-shadow: none !important;
    text-decoration: line-through;
    text-decoration-color: rgba(150, 150, 150, 0.35);
    text-decoration-thickness: 1px;
    filter: saturate(0);
    pointer-events: none;
}

/* ── 免疫者：還剩幾次 ───────────────────────────────────────── */
.dm-ward { display: inline-flex; align-items: center; gap: 4px; margin-left: 10px; }
.dm-ward.hidden { display: none; }
.dm-ward-label { font-size: 0.64rem; letter-spacing: 0.5px; color: #8ad4a0; opacity: 0.8; }
.dm-ward .dm-pip { width: 7px; height: 7px; border-radius: 50%; background: rgba(128,128,128,0.35); }
.dm-ward .dm-pip-on { background: #8ad4a0; box-shadow: 0 0 6px rgba(138, 212, 160, 0.6); }

/* 對手押注中的小標。跟自己的押注鈕同一個暖色，一眼就知道是同一件事 */
.dm-foe-bet {
    flex-shrink: 0; margin-right: 8px;
    padding: 3px 8px; border-radius: 9px;
    border: 1px solid #ffb03a; color: #ffb03a;
    font-size: 0.64rem; letter-spacing: 0.5px;
    animation: dmPulse 1.6s ease-in-out infinite;
}
.dm-foe-bet.hidden { display: none; }

/* ── 蓄能者：層數 ──────────────────────────────────────────────── */
.dm-charge {
    position: fixed; left: 16px; bottom: 26px; z-index: 40;
    display: flex; align-items: center; gap: 8px;
    padding: 9px 14px; border-radius: 22px;
    background: #12161c; border: 1px solid var(--border);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
}
.dm-charge.hidden { display: none; }
.dm-charge-label {
    font-size: 0.74rem; letter-spacing: 1px; opacity: 0.6;
}
.dm-charge-pips { display: flex; gap: 5px; }
/* 蓄能者的層數要用自己的 class。
   這裡本來也叫 .dm-pip —— 跟回血／護盾那一排撞名，而且寫在後面，
   所以 .dm-pip-on 的綠色被這裡的灰色蓋掉：兩顆包紮球從頭到尾都是灰的，
   玩家永遠看不出自己還剩幾次。撞名的兩條 CSS 特異性一樣，後寫的贏。 */
.dm-cpip {
    width: 9px; height: 9px; border-radius: 50%;
    background: rgba(128, 128, 128, 0.35);
    transition: background 0.25s, box-shadow 0.25s;
}
.dm-cpip.on {
    background: #5fd0ff;
    box-shadow: 0 0 8px rgba(95, 208, 255, 0.7);
}
.dm-charge-full { border-color: #5fd0ff; }
.dm-charge-full .dm-cpip.on { animation: dmPulse 1.4s ease-in-out infinite; }

/* 對手版本比較舊時的說明。不是錯誤，所以用一般說明的顏色，
   但要講清楚 —— 不然玩家會以為新角色壞掉了。 */
.dm-role-compat {
    margin-top: 6px;
    font-size: 0.72rem;
    color: var(--text-sub);
    line-height: 1.35;
}
.dm-role-compat:empty { display: none; }


/* 後台的紅點：有待審的案子才出現 */
.admin-alert-dot {
    display: inline-block; min-width: 20px; padding: 1px 6px;
    border-radius: 999px; background: #e57373; color: #fff;
    font-size: 0.7rem; font-weight: 700; text-align: center; vertical-align: middle;
}
.admin-alert-dot.hidden { display: none; }

/* ── 牌位賽 / 休閒模式的切換 ─────────────────────────────────── */
/* 擺在「返回首頁」跟賽季之間，所以要能被擠扁而不撐破那一列。 */
.rk-modes {
    display: flex;
    gap: 4px;
    background: var(--surface-strong, rgba(255, 255, 255, 0.05));
    border-radius: 999px;
    padding: 3px;
    min-width: 0;
    flex-shrink: 1;
}

/* 「返回」不能被擠到換行 —— 那一列要塞下返回、兩個分頁、賽季、規則 */
.rk-back { white-space: nowrap; flex-shrink: 0; }

.rk-mode {
    border: none;
    background: transparent;
    color: var(--text-sub);
    font-size: 0.73rem;
    font-family: inherit;
    padding: 5px 10px;
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.18s, color 0.18s;
}

.rk-mode.on {
    background: var(--card-bg);
    color: var(--text-main);
    font-weight: 600;
}

/* 賽季與這一季的遊戲（卡片最上面一行） */
.rk-season-kicker { text-align: center; font-size: 0.8rem; font-weight: 700; letter-spacing: 2px; color: #d9a54a; margin: -2px 0 8px; }

/* 導覽列：返回、兩個分頁、規則一定要放得下（窄螢幕把分頁再縮一點） */
#view-ranked .nav-bar { gap: 8px; }
@media (max-width: 380px) { .rk-mode { padding: 5px 8px; font-size: 0.7rem; } }

/* ── 休閒模式的說明卡 ────────────────────────────────────────── */
.rk-chill-card { text-align: left; }
.rk-chill-title { font-size: 1.15rem; font-weight: 600; margin-bottom: 10px; }
.rk-chill-lead { font-size: 0.86rem; color: var(--text-sub); line-height: 1.8; }
.rk-chill-rows { margin-top: 16px; }

.rk-chill-row {
    display: flex;
    gap: 12px;
    align-items: baseline;
    padding: 8px 0;
    border-top: 1px solid var(--border);
    font-size: 0.82rem;
    line-height: 1.6;
}

.rk-chill-k {
    color: var(--text-sub);
    flex-shrink: 0;
    width: 56px;
}

/* 休閒模式兩個遊戲：各一張卡片、各一顆開始按鈕 */
.rk-chill-games { display: grid; gap: 14px; }
.rk-chill-games .rk-card { margin-bottom: 0; }
.rk-chill-play { width: 100%; margin: 14px 0 0; }
.rk-chill-bomb .rk-chill-title { color: #ff9a6b; }
.rk-chill-note { margin: 12px 4px 0; font-size: 0.76rem; color: var(--text-sub); text-align: center; line-height: 1.6; }

/* ── 休閒模式：抽到的人選難度 ────────────────────────────────── */
.dm-level-title { font-size: 1.3rem; font-weight: 600; text-align: center; }
.dm-level-sub {
    font-size: 0.84rem;
    color: var(--text-sub);
    text-align: center;
    margin-top: 8px;
    line-height: 1.7;
}

.dm-levels {
    display: flex;
    flex-direction: column;
    gap: 9px;
    margin-top: 22px;
    width: 100%;
    max-width: 380px;
}

.dm-level-btn {
    width: 100%;
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--card-bg);
    color: var(--text-main);
    font-family: inherit;
    font-size: 0.95rem;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.08s;
}

.dm-level-btn:active { transform: translateY(1px); }
.dm-level-btn:hover:not(:disabled) { border-color: var(--text-sub); }
.dm-level-btn:disabled { opacity: 0.4; cursor: default; }
/* Pro 個人化：僅在取得後端授權的設定後才加上 data-personalized。 */
html[data-personal-button] .btn:not(.btn-outline) {
    --btn-tint: var(--personal-button-rgb, 255, 255, 255);
}
html[data-personal-button] .hub-item,
html[data-personal-button] .hm-rank,
html[data-personal-button] .hm-friends {
    border-color: rgba(var(--personal-button-rgb, 255, 255, 255), 0.38);
}
html[data-personal-background] body::before {
    background: radial-gradient(120% 90% at 50% 20%, rgba(var(--personal-background-rgb, 18, 24, 38), 0.74), transparent 80%), var(--app-bg-grad);
}
html[data-personal-home] #view-profile .profile-header,
html[data-personal-home] #view-profile .stat-card,
html[data-personal-home] #view-home #home-rank-card {
    border-color: var(--personal-home-color, var(--border));
}
html[data-personal-home] #view-profile .profile-header {
    border: 1px solid var(--personal-home-color, var(--border));
    border-radius: 18px;
    padding: 24px 12px;
    background: color-mix(in srgb, var(--personal-home-color, transparent) 12%, var(--card-bg));
}
html[data-personal-font] #view-profile,
html[data-personal-font] #view-home {
    font-family: var(--personal-home-font, var(--font-family));
}
html[data-personal-leaderboard] #view-leaderboard .lb-item-me,
html[data-personal-leaderboard] #view-ranked-lb .rk-lb-me {
    border-color: var(--personal-leaderboard-color, var(--border));
    box-shadow: inset 3px 0 var(--personal-leaderboard-color, transparent);
}
html[data-personal-leaderboard] #view-leaderboard #lb-my-score {
    color: var(--personal-leaderboard-color, var(--text-main));
}
html[data-personal-font] #view-leaderboard #lb-my-score {
    font-family: var(--personal-home-font, var(--font-family)) !important;
}
#view-public-profile .profile-header,
#view-public-profile .stat-card {
    border-color: var(--public-home-color, var(--border));
}
#view-public-profile[style*="--public-home-color"] .profile-header {
    border: 1px solid var(--public-home-color);
    border-radius: 18px;
    padding: 24px 12px;
    background: color-mix(in srgb, var(--public-home-color) 12%, var(--card-bg));
}
#view-public-profile { font-family: var(--public-home-font, var(--font-family)); }

.personal-card { margin-bottom: 18px; }
.personal-card h2, .personal-card h3, #view-collectibles h2 { margin-top: 0; }
.personal-note { color: var(--text-sub); font-size: .85rem; line-height: 1.5; }
.personal-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin: 18px 0; }
.personal-grid label, .personal-full { display: flex; flex-direction: column; gap: 8px; color: var(--text-main); font-size: .9rem; }
.personal-grid input, .personal-grid select, .personal-full input, .personal-full select {
    min-height: 42px; width: 100%; border: 1px solid var(--border); border-radius: 10px;
    background: var(--card-bg); color: var(--text-main); padding: 6px 10px;
}
.personal-grid input[type="color"] { padding: 4px; cursor: pointer; }
.personal-full { margin: 12px 0; }
.admin-collect-choice { display: inline-block; margin: 4px 6px 4px 0; padding: 7px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--card-bg); color: var(--text-main); cursor: pointer; }
.personal-actions { display: flex; gap: 10px; }
.personal-actions .btn { min-width: 0; }
.collectibles-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 20px; }
.collectible-item { border: 1px solid var(--border); border-radius: 14px; padding: 12px; min-width: 0; }
.collectible-item strong { display: block; margin-top: 10px; }
.collectible-item p { color: var(--text-sub); font-size: .82rem; line-height: 1.4; margin-bottom: 0; }
.collectible-art { position: relative; display: grid; place-items: center; width: 100%; aspect-ratio: 1; border-radius: 10px; background: var(--surface-strong); color: var(--text-sub); overflow: hidden; }
.collectible-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
@media (max-width: 380px) { .personal-grid { grid-template-columns: 1fr; } }
html[data-personal-fx] #theme-fx[data-fx="galaxy"]::before {
    background-image: radial-gradient(1.4px 1.4px at 18px 32px, rgba(var(--personal-fx-rgb), .9), transparent),
        radial-gradient(1.2px 1.2px at 96px 128px, rgba(var(--personal-fx-rgb), .75), transparent),
        radial-gradient(1.6px 1.6px at 172px 64px, rgba(var(--personal-fx-rgb), .95), transparent),
        radial-gradient(1.1px 1.1px at 58px 196px, rgba(var(--personal-fx-rgb), .7), transparent),
        radial-gradient(1.3px 1.3px at 216px 172px, rgba(var(--personal-fx-rgb), .8), transparent);
}
html[data-personal-fx] #theme-fx[data-fx="galaxy"]::after {
    background-image: radial-gradient(1px 1px at 44px 88px, rgba(var(--personal-fx-rgb), .65), transparent),
        radial-gradient(1px 1px at 148px 24px, rgba(var(--personal-fx-rgb), .55), transparent),
        radial-gradient(1.2px 1.2px at 88px 264px, rgba(var(--personal-fx-rgb), .7), transparent),
        radial-gradient(1px 1px at 268px 148px, rgba(var(--personal-fx-rgb), .55), transparent);
}
html[data-personal-fx] #theme-fx[data-fx="galaxy"] i {
    background: linear-gradient(to bottom, rgba(var(--personal-fx-rgb), 0), rgba(var(--personal-fx-rgb), .55) 55%, rgba(var(--personal-fx-rgb), .95));
}
.mod-admin-nav { position:sticky; top:0; z-index:20; display:flex; gap:8px; padding:8px; margin-bottom:14px; background:var(--bg-color, #191510); border:1px solid var(--border); border-radius:12px; }
.mod-admin-nav button { flex:1; margin:0; }
.admin-dashboard-nav { display:block; }
.admin-dashboard-nav label { display:flex; gap:12px; align-items:center; font-size:.85rem; }
.admin-dashboard-nav select { flex:1; min-width:0; padding:10px; border:1px solid var(--border); border-radius:8px; background:var(--card-bg); color:var(--text-main); }
.admin-page-controls { display:flex; gap:8px; align-items:center; justify-content:space-between; margin:10px 0; font-size:.78rem; flex-wrap:wrap; }
.admin-page-controls .btn { width:auto; margin:0; flex:1; }
#view-admin > .card[hidden] { display:none !important; }
.admin-history-details { border-top:1px solid var(--border); margin-top:12px; padding-top:10px; }
.admin-history-details summary { cursor:pointer; padding:8px 0; font-size:.85rem; color:var(--text-sub); }
.admin-history-details[open] { max-height:60vh; overflow:auto; overscroll-behavior:contain; }
#admin-cheat-section, #admin-market-section, #admin-learning-section { scroll-margin-top:75px; }
.mod-note { color:var(--text-sub); font-size:.8rem; line-height:1.65; overflow-wrap:anywhere; }
.mod-words { display:flex; flex-wrap:wrap; gap:8px; margin:12px 0; }
.mod-words span { padding:6px 12px; border:1px solid var(--border); border-radius:20px; overflow-wrap:anywhere; }
.mod-record { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 0; border-bottom:1px solid var(--border); font-size:.8rem; color:var(--text-sub); }
.mod-record b { color:var(--success, #7cb342); }
.mod-actions { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; margin-top:12px; }
.mod-actions .btn { margin:0; font-size:.8rem; }
.mod-user { border:1px solid var(--border); border-radius:12px; padding:14px; }

.dm-start-recovery { display:flex; gap:10px; margin-top:16px; }
.dm-start-recovery .btn { flex:1; margin:0; }

/* Meaningful word structure: static labels, independent of pronunciation timing. */
.word-chunks-panel { width:100%; margin:8px 0 20px; text-align:center; }
.word-chunks-title { margin:0; color:var(--text-sub); font-size:.82rem; font-weight:600; }
.word-chunks-row { display:flex; flex-wrap:wrap; justify-content:center; align-items:stretch; gap:6px; padding:12px 0; }
.word-chunk { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:5px; box-sizing:border-box; max-width:100%; flex:0 1 auto; min-width:64px; min-height:60px; overflow-wrap:anywhere; padding:10px 14px; border:1px solid var(--border); border-radius:10px; color:var(--text-main); background:var(--card-bg); font-family:inherit; font-size:clamp(1.25rem,5vw,1.9rem); font-weight:600; }
button.word-chunk { cursor:pointer; animation:word-structure-enter .28s ease-out both; transition:transform .16s ease,border-color .16s ease,box-shadow .16s ease; }
button.word-chunk:nth-child(2) { animation-delay:.04s; }
button.word-chunk:nth-child(3) { animation-delay:.08s; }
button.word-chunk:nth-child(n+4) { animation-delay:.12s; }
button.word-chunk:hover, button.word-chunk:focus-visible { border-color:var(--accent); box-shadow:0 4px 14px #0002; }
button.word-chunk:active { transform:scale(.96); }
button.word-chunk:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.word-chunk--whole { flex-basis:auto; }
.word-chunk-role { color:var(--accent); font-size:.72rem; font-weight:600; }
.word-chunk.is-speaking { border-color:var(--accent); box-shadow:0 0 0 1px var(--accent),0 5px 20px #0003; }
.word-chunk.is-speaking .word-chunk-text { animation:word-structure-speaking .32s cubic-bezier(.2,.8,.2,1); }
@keyframes word-structure-speaking { 0%,100% { transform:translateY(0) scale(1); } 40% { transform:translateY(-5px) scale(1.07); } }
/* Reading dialogs need the opaque theme base; card-bg is glass in most themes. */
.word-structure-detail { width:min(400px,calc(100vw - 40px)); box-sizing:border-box; max-height:80vh; overflow-y:auto; padding:24px; border:1px solid var(--border); border-radius:20px; color:var(--text-main); background:var(--bg-color, #161616); box-shadow:0 12px 50px #0006; }
.word-structure-detail::backdrop { background:#0009; }
.word-structure-detail[open] { animation:word-structure-dialog-enter .24s cubic-bezier(.2,.8,.2,1) both; }
.word-structure-detail[open]::backdrop { animation:word-structure-backdrop-enter .2s ease-out both; }
.word-structure-detail h2 { margin:0 0 18px; font-size:1.35rem; overflow-wrap:anywhere; }
.word-structure-detail p { margin:0 0 22px; white-space:pre-wrap; font-size:.95rem; line-height:1.65; overflow-wrap:anywhere; }
.word-structure-detail .btn { margin:0; width:100%; min-height:44px; }
.word-structure-detail h2 { text-align:center; }
.word-structure-detail #word-structure-detail-content { display:grid; gap:10px; margin:0 0 24px; }
.word-structure-detail #word-structure-detail-content p { margin:0; white-space:pre-wrap; line-height:1.6; }
.word-structure-detail .word-structure-meaning { color:var(--text-main); font-size:1rem; }
.word-structure-detail .word-structure-grammar { color:var(--text-main); font-size:.92rem; }
.word-structure-detail .word-structure-meta, .word-structure-detail .word-structure-hint { color:var(--text-sub); font-size:.82rem; }
/* #silen-voice-notice 的浮動提示框已移除（玩家回報它蓋住作答區），樣式一併清掉 */
@keyframes word-structure-enter { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:translateY(0); } }
@keyframes word-structure-dialog-enter { from { opacity:0; transform:translateY(14px) scale(.96); } to { opacity:1; transform:translateY(0) scale(1); } }
@keyframes word-structure-backdrop-enter { from { opacity:0; } to { opacity:1; } }
@media (prefers-reduced-motion:reduce) {
    button.word-chunk, .word-structure-detail[open], .word-structure-detail[open]::backdrop { animation:none; transition:none; }
    .word-chunk.is-speaking .word-chunk-text { animation:none; }
}
.word-chunks-note { margin:4px 0 8px; color:var(--text-sub); font-size:.76rem; line-height:1.55; overflow-wrap:anywhere; }
.word-structure-retry { display:block; margin:8px auto 0; min-height:44px; padding:6px 14px; font:inherit; color:var(--accent); background:var(--card-bg); border:1px solid var(--border); border-radius:10px; cursor:pointer; }
.word-chunk-separator { white-space:pre-wrap; }
.word-chunks-status { color:var(--text-sub); font-size:.76rem; min-height:1.4em; margin:2px 0 10px; }
.word-chunks-actions { display:flex; flex-wrap:wrap; justify-content:center; gap:8px; }
.word-chunks-actions .btn { width:auto; min-height:44px; margin:0; padding:8px 14px; font-size:.85rem; }

/* Feedback is one reading card with a compact status and a clear next action. */
.training-feedback { width:100%; max-width:560px; margin-left:auto; margin-right:auto; gap:14px; }
.training-feedback-heading { display:flex; align-items:center; justify-content:center; gap:9px; flex-wrap:wrap; }
.training-feedback-heading .big-icon { font-size:1.65rem; line-height:1; margin:0; }
.training-feedback-heading .result-status { font-size:.95rem; min-height:0; margin:0; }
.training-question-copy { font-size:.85rem; color:var(--text-sub); overflow-wrap:anywhere; }
.training-answer-card { width:100%; box-sizing:border-box; border:1px solid var(--border); background:var(--card-bg); border-radius:20px; padding:22px 18px 18px; text-align:center; }
.training-answer-card .answer-reveal-label { margin-bottom:10px; font-size:.75rem; letter-spacing:1px; color:var(--text-sub); }
.training-answer-card .answer-reveal-en { font-size:clamp(1.65rem,6vw,2.1rem); line-height:1.25; overflow-wrap:anywhere; }
.training-answer-card .answer-reveal-zh { font-size:.98rem; line-height:1.5; margin-top:10px; color:var(--text-sub); }
.training-answer-card .word-chunks-panel { margin:18px 0 10px; }
.training-answer-card .word-chunks-row { gap:6px; padding:8px 0; }
.training-answer-card .word-chunk { font-size:clamp(1.15rem,4.6vw,1.6rem); padding:6px 9px; }
.training-answer-card .word-chunks-status { margin:8px 0 0; }
.training-answer-card .word-chunks-actions { margin-top:15px; }
.spelling-diff { box-sizing:border-box; margin:13px 0 2px; padding:9px 11px; border:1px solid color-mix(in srgb,var(--error) 32%,var(--border)); border-radius:12px; background:color-mix(in srgb,var(--error) 6%,var(--card-bg)); text-align:left; }
.spelling-diff-main { display:flex; align-items:baseline; gap:9px; min-width:0; }
.spelling-diff-label { flex:none; color:var(--text-sub); font-size:.73rem; white-space:nowrap; }
.spelling-diff-typed { min-width:0; overflow-x:auto; white-space:nowrap; font-family:ui-monospace,SFMono-Regular,Consolas,monospace; font-size:1rem; font-weight:650; letter-spacing:.02em; color:var(--text-main); }
.spelling-diff-typed .spelling-wrong { color:var(--error); background:color-mix(in srgb,var(--error) 15%,transparent); border-radius:3px; }
.spelling-diff-typed .spelling-missing { color:var(--error); border-bottom:2px dashed var(--error); font-size:.8em; }
#mastery-fb-ans-en .spelling-correct { color:var(--success); border-bottom:2px solid var(--success); }
.spelling-diff-notes { display:flex; gap:6px; margin-top:7px; overflow-x:auto; white-space:nowrap; }
.spelling-diff-note { flex:none; padding:3px 7px; border-radius:7px; background:color-mix(in srgb,var(--error) 10%,var(--card-bg)); color:var(--text-sub); font-size:.71rem; }
.training-answer-card.has-spelling-diff { padding-bottom:14px; }
.training-answer-card.has-spelling-diff .word-chunks-panel { margin-top:12px; }
.training-feedback-note { font-size:.8rem; line-height:1.5; color:var(--text-sub); margin:0; }
.training-feedback-heading .training-feedback-note:not(:empty) { padding-left:9px; border-left:1px solid var(--border); }
.mastery-feedback-action { position:fixed; left:0; right:0; bottom:0; z-index:1000; box-sizing:border-box; display:flex; justify-content:center; padding:12px max(16px,env(safe-area-inset-left,0px)) calc(12px + env(safe-area-inset-bottom,0px)); background:linear-gradient(to top, color-mix(in srgb,var(--bg-color) 96%,transparent) 0%, color-mix(in srgb,var(--bg-color) 82%,transparent) 70%, transparent 100%); pointer-events:none; }
.mastery-feedback-action .btn-next-big { width:min(100%,560px); min-height:52px; margin:0; font-size:1rem; pointer-events:auto; }
#view-mastery.mastery-feedback-visible { padding-bottom:calc(96px + env(safe-area-inset-bottom,0px)); }
@media (max-height:740px) {
    .training-feedback { gap:10px; }
    .training-answer-card { padding:17px 14px 14px; }
    .training-answer-card .word-chunks-panel { margin-top:12px; }
}
.vocab-range { display:flex; justify-content:center; align-items:center; gap:8px; margin:14px auto 24px; flex-wrap:wrap; }
.vocab-range > span { color:var(--text-sub); margin-right:8px; font-size:.9rem; }
.vocab-range button { min-height:44px; min-width:86px; padding:10px 18px; border:1px solid var(--border); border-radius:24px; background:var(--card-bg); color:var(--text-main); cursor:pointer; transition:transform .2s, background .2s; }
.vocab-range button.active { background:var(--text-main); color:var(--bg-color); font-weight:600; }
.vocab-range button:active { transform:scale(.96); }
@media (max-width:440px) {
    .vocab-range > span { flex-basis:100%; margin:0 0 4px; text-align:center; }
    .vocab-range button { flex:1; min-width:0; padding:10px 8px; }
}
.dc-pos { color:var(--text-sub); font-size:.95rem; min-height:1.4em; margin:8px 0; }
.toeic-draw-panel { margin-top:40px; border-top:1px solid var(--border); padding-top:20px; }
.toeic-draw-panel h3 { font-weight:500; }
.toeic-draw-panel p { color:var(--text-sub); line-height:1.7; font-size:.9rem; }
.toeic-draw-panel label { display:block; color:var(--text-sub); font-size:.85rem; margin:18px 0 6px; }
.toeic-draw-panel .input-box { width:100%; box-sizing:border-box; min-height:44px; }
.toeic-draw-panel select { background:var(--card-bg); color:var(--text-main); }
.toeic-draw-panel .btn { width:100%; margin-top:24px; }
.toeic-draw-panel .toeic-credit { font-size:.75rem; margin-top:22px; }
.toeic-credit a { color:var(--text-main); text-decoration:underline; }
.vocab-topic-caption { color:var(--text-sub); margin-bottom:24px; text-align:center; }
#lib-options { background:var(--bg-color, #161616); min-width:180px; box-shadow:0 12px 30px #0007; }
@media (prefers-reduced-motion:reduce) { .vocab-range button { transition:none; } }

/* TOEIC and admin selectors share one readable liquid-glass menu. Native
   <select> popups are painted by the OS and ignore the site's theme. */
.liquid-select { position:relative; display:block; width:100%; min-width:0; }
.liquid-select-native {
    position:absolute !important; width:1px !important; height:1px !important;
    margin:0 !important; padding:0 !important; opacity:0 !important;
    pointer-events:none; clip-path:inset(50%);
}
.liquid-select-trigger {
    display:flex; align-items:center; justify-content:space-between; gap:16px;
    width:100%; min-height:48px; padding:11px 15px; box-sizing:border-box;
    border:1px solid var(--border); border-radius:14px;
    background:linear-gradient(145deg,#fff2,#fff0 70%),
        color-mix(in srgb,var(--bg-color) 78%,transparent);
    color:var(--text-main); font:inherit; font-size:.96rem; text-align:left;
    box-shadow:inset 0 1px #fff2,0 7px 20px #0003;
    backdrop-filter:blur(22px) saturate(145%);
    -webkit-backdrop-filter:blur(22px) saturate(145%);
    cursor:pointer; transition:border-color .18s,box-shadow .18s,transform .18s;
}
.liquid-select-trigger:hover, .liquid-select.is-open .liquid-select-trigger {
    border-color:var(--surface-strong-border,var(--border));
    box-shadow:inset 0 1px #fff3,0 9px 26px #0005;
}
.liquid-select-trigger:active { transform:scale(.995); }
.liquid-select-trigger:focus-visible, .liquid-select-option:focus-visible {
    outline:2px solid var(--accent,var(--text-main)); outline-offset:2px;
}
.liquid-select-value { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.liquid-select-chevron {
    flex:none; width:8px; height:8px; border-right:2px solid currentColor;
    border-bottom:2px solid currentColor; opacity:.75;
    transform:rotate(45deg) translateY(-2px); transition:transform .18s;
}
.liquid-select.is-open .liquid-select-chevron { transform:rotate(225deg) translate(-2px,-1px); }
.liquid-select-menu {
    position:absolute; z-index:160; top:calc(100% + 8px); left:0; right:0;
    box-sizing:border-box; max-height:min(52vh,420px); overflow-y:auto;
    padding:7px; border:1px solid var(--surface-strong-border,var(--border));
    border-radius:17px;
    background:linear-gradient(150deg,#fff2,transparent 36%),
        color-mix(in srgb,var(--bg-color) 94%,transparent);
    color:var(--text-main);
    box-shadow:inset 0 1px #fff2,0 20px 50px #0009,0 0 0 1px #0002;
    backdrop-filter:blur(28px) saturate(155%);
    -webkit-backdrop-filter:blur(28px) saturate(155%);
    overscroll-behavior:contain;
    animation:liquid-select-enter .18s cubic-bezier(.2,.8,.2,1) both;
}
.liquid-select-menu[hidden] { display:none !important; }
.liquid-select.opens-up .liquid-select-menu { top:auto; bottom:calc(100% + 8px); }
.liquid-select-option {
    display:flex; align-items:center; justify-content:space-between; gap:12px;
    width:100%; min-height:42px; padding:9px 12px; border:1px solid transparent;
    border-radius:10px; background:transparent; color:var(--text-main);
    font:inherit; font-size:.9rem; text-align:left; cursor:pointer;
    transition:background .15s,border-color .15s;
}
.liquid-select-option:hover, .liquid-select-option:focus-visible {
    background:var(--surface-strong); border-color:var(--surface-strong-border,var(--border));
}
.liquid-select-option.is-selected {
    background:color-mix(in srgb,var(--accent,var(--text-main)) 17%,transparent);
    border-color:color-mix(in srgb,var(--accent,var(--text-main)) 35%,transparent);
    font-weight:600;
}
.liquid-select-option.is-selected::after { content:'✓'; color:var(--accent,var(--text-main)); font-size:1rem; }
.admin-dashboard-nav label .liquid-select { flex:1; }
.admin-dashboard-nav .liquid-select-trigger { min-height:44px; font-size:.86rem; }
.toeic-draw-panel .liquid-select { margin-bottom:2px; }
@keyframes liquid-select-enter {
    from { opacity:0; transform:translateY(-5px) scale(.985); }
    to { opacity:1; transform:translateY(0) scale(1); }
}
@media (prefers-reduced-motion:reduce) {
    .liquid-select-trigger, .liquid-select-chevron, .liquid-select-option { transition:none; }
    .liquid-select-menu { animation:none; }
}

/* ========================================================================
   個人主頁：目前牌位與牌位印記
   ========================================================================
   玩家要的是「打開主頁就看得到自己在哪一階」，以及「賽季打到大師以上
   拿到的印記要擺得出來」。

   排版上刻意跟舊版共用 .profile-header / .stat-card / .card ——
   PRO 與 ULTRA 的個人化是掛在那幾個選擇器上的（見 html[data-personal-home]），
   換掉 class 名稱等於默默關掉會員買的東西。 */

.pf-nameline {
    display: flex; align-items: center; justify-content: center;
    gap: 10px; margin-bottom: 4px; max-width: 100%;
}
.pf-nameline h2 {
    margin: 0; font-weight: 500; letter-spacing: 2px; font-size: 1.35rem;
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pf-rename {
    flex: 0 0 auto;
    background: none; border: 1px solid var(--border); color: var(--text-sub);
    border-radius: 999px; padding: 4px 11px; font-size: 0.75rem;
    letter-spacing: 0.5px; cursor: pointer; font-family: inherit;
}
.pf-rename:hover { color: var(--text-main); border-color: var(--text-sub); }
.pf-email {
    color: var(--text-sub); font-size: 0.8rem; margin-top: 2px;
    letter-spacing: 0.5px; word-break: break-all; max-width: 100%;
}

/* ── 目前牌位 ── */
.pf-rank {
    display: flex; align-items: center; gap: 14px;
    width: 100%; margin: 0 0 18px; padding: 14px 16px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-left: 3px solid var(--rk-c, var(--border));
    border-radius: 16px;
    text-align: left; font-family: inherit; cursor: pointer;
}
.pf-rank-static { cursor: default; }
.pf-rank.hidden { display: none; }
.pf-rank-badge { flex: 0 0 auto; width: 54px; height: 54px; }
.pf-rank-body { flex: 1; min-width: 0; }
.pf-rank-top { display: flex; align-items: baseline; gap: 8px; }
.pf-rank-tier {
    font-size: 1.1rem; font-weight: 700; letter-spacing: 2px;
    color: var(--rk-c, var(--text-main));
}
.pf-rank-score { margin-left: auto; font-size: 0.95rem; color: var(--text-main); }
.pf-rank-bar {
    height: 6px; border-radius: 3px; margin: 8px 0 7px;
    background: color-mix(in srgb, var(--rk-c, #888) 18%, transparent);
    overflow: hidden;
}
.pf-rank-bar span {
    display: block; height: 100%; width: 0;
    background: var(--rk-c, #888);
    transition: width 0.6s ease;
}
.pf-rank-foot {
    display: flex; flex-direction: column; gap: 2px;
    font-size: 0.72rem; color: var(--text-sub); letter-spacing: 0.3px; line-height: 1.45;
}

/* ── 牌位印記 ── */
.pf-card { border-color: var(--border); margin-bottom: 16px; }
.pf-h3 {
    margin: 0 0 14px; font-weight: 500; font-size: 1.05rem; letter-spacing: 1px;
    border-bottom: 1px solid var(--border); padding-bottom: 13px;
    color: var(--text-main);
}
.pf-marks { display: flex; flex-wrap: wrap; gap: 12px; }
.pf-marks:empty { display: none; }
.pf-mark {
    flex: 0 0 auto; width: 76px;
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 10px 4px 8px; border-radius: 14px;
    border: 1px solid color-mix(in srgb, var(--rk-c, #888) 40%, transparent);
    background: color-mix(in srgb, var(--rk-c, #888) 9%, transparent);
}
.pf-mark-art { width: 40px; height: 40px; }
.pf-mark-tier {
    font-size: 0.74rem; font-weight: 700; letter-spacing: 1px;
    color: var(--rk-c, var(--text-main));
}
.pf-mark-season { font-size: 0.66rem; color: var(--text-sub); letter-spacing: 0.5px; }
.pf-note {
    text-align: center; color: var(--text-sub); font-size: 0.8rem;
    margin: 12px 0 0; letter-spacing: 0.3px; line-height: 1.6;
}
.pf-note:empty { display: none; }

/* PRO / ULTRA 的個人化：新的卡片刻意不加規則。
 *
 * .card 是 `border: 1px solid var(--glass-card-border) !important`（磨砂
 * 玻璃那套，上面有註解說明為什麼要 !important），所以個人化的邊框色
 * 本來就套不到任何一張 .card —— 舊的榮譽徽章卡也一樣，它那條
 * inline 的 border-color 從來沒生效過。
 *
 * 要讓它生效只能再疊一個 !important 上去，那會把玻璃卡片打回不吃主題的
 * 灰板（就是那條註解在講的問題）。個人化真正掛得住的是 .profile-header
 * 與 .stat-card，那兩塊照舊。 */

/* 牌位榜整列可以點開玩家主頁。列裡面的檢舉鈕自己吃掉點擊。 */
.rk-lb-open { cursor: pointer; }
.rk-lb-open:focus-visible {
    outline: 2px solid var(--rk-c, var(--text-main));
    outline-offset: 2px;
}

/* 巔峰的外環慢慢轉，像一圈能量。只有那一階有。 */
.rk-aura { animation: rk-aura-spin 16s linear infinite; transform-origin: 50px 52px; }
@keyframes rk-aura-spin { to { transform: rotate(360deg); } }

/* ========================================================================
   生死戰：正解與打擊感
   ======================================================================== */

/* ── 正解 ──
   跨階段留在畫面上，直到下一題。答錯的時候這是玩家唯一學得到東西的
   地方，所以它不能跟著作答面板一起被藏掉。 */
.dm-ans {
    display: flex; align-items: center; gap: 10px;
    margin: 2px 0 10px; padding: 9px 14px; max-width: 100%;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, var(--dm-ans-c, #8aa) 45%, transparent);
    background: color-mix(in srgb, var(--dm-ans-c, #8aa) 12%, transparent);
    animation: dmAnsIn 0.3s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.dm-ans.hidden { display: none; }
.dm-ans-wrong { --dm-ans-c: #ff8b84; }
.dm-ans-right { --dm-ans-c: #4fd8a0; }
.dm-ans-tag {
    flex: 0 0 auto; font-size: 0.68rem; font-weight: 700; letter-spacing: 1px;
    padding: 3px 8px; border-radius: 999px;
    color: var(--dm-ans-c); background: color-mix(in srgb, var(--dm-ans-c) 18%, transparent);
}
.dm-ans-en {
    flex: 0 1 auto; min-width: 0; font-weight: 700; font-size: 0.95rem;
    color: var(--text-main); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dm-ans-zh {
    flex: 1 1 auto; min-width: 0; text-align: right;
    font-size: 0.95rem; color: var(--dm-ans-c);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@keyframes dmAnsIn {
    0%   { opacity: 0; transform: translateY(-6px); }
    100% { opacity: 1; transform: translateY(0); }
}

/* ── 打擊感 ──
   原本只有：那一格閃一下、數字飄上去、震一下。三個效果都只發生在
   血條那一小格，手機上很容易整個錯過。補的是「這一下打到我了」的
   身體感覺：整個畫面震、一層衝擊光、以及手機震動。

   強度跟傷害掛勾 —— 每一下都一樣重，就等於每一下都不重。 */
/* 畫面震動。幅度由 --dm-quake-a 決定，傷害越高震越大。
 *
 * 只震對戰內容（血條那兩格＋中間的舞台），不震整個 view。
 *
 * 一開始我把 transform 加在 #view-dm-game 上。玩家回報「震動完會
 * 閃黑一下，整個 UI 都不見 0.幾秒」—— 那不是動畫，是重繪：
 * #main-header、.sidebar、.bnav 三條都是 backdrop-filter: blur(22px)，
 * 而它們糊的就是這個 view。整頁被提升成合成層再銷毀，那三條就得
 * 整個重算一次，中間會空一兩幀。
 *
 * 換成只動兩個小元素之後，那三條模糊條的來源不再整塊換層。
 * 另外拿掉 fill-mode：最後一格本來就是原位，留著只是讓元素在動畫
 * 結束後仍掛著一個 transform，白白多維持一個層。 */
.dm-hud.dm-quake,
.dm-stage.dm-quake { animation: dmQuake var(--dm-quake-ms, 320ms) cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@keyframes dmQuake {
    0%, 100% { transform: translate3d(0, 0, 0); }
    12%      { transform: translate3d(calc(var(--dm-quake-a, 4px) * -1), 1px, 0); }
    26%      { transform: translate3d(var(--dm-quake-a, 4px), -2px, 0); }
    42%      { transform: translate3d(calc(var(--dm-quake-a, 4px) * -0.7), 2px, 0); }
    58%      { transform: translate3d(calc(var(--dm-quake-a, 4px) * 0.6), -1px, 0); }
    74%      { transform: translate3d(calc(var(--dm-quake-a, 4px) * -0.3), 1px, 0); }
}

/* 血條被打掉的那一瞬間自己也亮一下 —— 眼睛在看數字的時候，
   餘光要能看到血條有反應。 */
.dm-bar-hurt { animation: dmBarHurt 0.45s ease both; }
@keyframes dmBarHurt {
    0%   { filter: brightness(2.4) saturate(0.4); }
    100% { filter: none; }
}

@media (prefers-reduced-motion: reduce) {
    .dm-ans { animation: none; }
    .dm-hud.dm-quake, .dm-stage.dm-quake { animation: none; }
    .dm-bar-hurt { animation: none; }
}

/* 出手的那一方往對手撲過去。
   只有目標在抖的時候，看起來像「他自己在抖」；加上攻擊方的前衝，
   才看得出是「這一邊打了那一邊」。方向由 --dm-lunge 決定：
   上面那格往下打是正的，下面那格往上打是負的。 */
.dm-lunge { animation: dmLunge 0.34s cubic-bezier(0.34, 1.3, 0.5, 1) both; }
@keyframes dmLunge {
    0%   { transform: translate3d(0, 0, 0); }
    26%  { transform: translate3d(0, calc(var(--dm-lunge, 8px) * -0.45), 0); }
    52%  { transform: translate3d(0, var(--dm-lunge, 8px), 0); }
    100% { transform: translate3d(0, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .dm-lunge { animation: none; }
}

/* ========================================================================
   生死戰：技能特效
   ========================================================================
   以前十一個角色的技能，畫面上的差別只有按鈕變色，音效還全部共用
   同一個。玩家分不出「我的角色做了什麼」，角色就只是一行說明文字。

   每個技能發動時：自己那一格亮起該角色的顏色、技能名浮出來、
   受影響的那一邊有對應的視覺。顏色由 --dm-skill 帶進來。 */

/* ── 特效層 ──────────────────────────────────────────────
 *
 * 所有「發光」類的效果都畫在 .dm-side-fx 這一層，不畫在 .dm-side 上。
 *
 * 原因：CSS 的 animation 是單一屬性。.dm-shake、.dm-flash-hit、
 * .dm-cast 全部掛在同一個 .dm-side 上的時候，只有樣式表裡最後
 * 那一條會生效，而且「加一個 class」或「移掉一個 class」都會讓
 * 正在跑的那個動畫重新開始。
 *
 * 玩家回報的兩件事都是這個造成的：
 *   ·「被打或是打別人，震動動畫結束後都會閃一下」
 *      —— 震動的 class 在 420ms 被移掉，那時 flash 還在跑（500ms），
 *         animation 重新解析 → flash 從頭再播一次 → 看起來就是閃一下。
 *   ·「角色動畫也會撥到一半被中斷」
 *      —— 技能光環被後面宣告的另一個 animation 直接取代。
 *
 * 分層之後：位移類（震動、前撲）留在卡片本身，發光類全部在特效層，
 * 而且特效層一次只跑一個 —— 由 fxPulse 一個函式決定要放哪一個。
 */
.dm-side-fx {
    position: absolute; inset: 0; z-index: 0;
    border-radius: inherit; pointer-events: none; opacity: 0;
}
/* 特效層要壓在卡片底色上、但在文字底下。所以內容逐一抬高 —— 不能
   用 `> *` 通殺，.dm-float 是 absolute 的，被改成 relative 就飛掉了。 */
.dm-side > .dm-side-top,
.dm-side > .dm-bar,
.dm-side > .dm-pips { position: relative; z-index: 1; }

.dm-side-fx.dm-flash-hit,
.dm-side-fx.dm-flash-block,
.dm-side-fx.dm-flash-heal,
.dm-side-fx.dm-cast,
.dm-side-fx.dm-marked,
.dm-side-fx.dm-ward-pop { opacity: 1; }

/* 技能發動：一圈由內往外的光。
 *
 * 淡出用 ease-out 而且佔掉大半的時間 —— 第一版用
 * cubic-bezier(0.22,1,0.36,1)，那條曲線在 40% 的時間就跑完 95% 的
 * 進度，於是「亮起來再慢慢退掉」變成「亮一下就不見」。影片裡量到
 * 光暈只存在 10 格（約 170ms），就是這個。 */
/* linear，不是 ease-out。ease-out 也會前重後輕，退場還是太快 ——
   光暈要的是「均勻地淡掉」。 */
.dm-side-fx.dm-cast { animation: dmCast 0.75s linear both; }
@keyframes dmCast {
    0%   { box-shadow: inset 0 0 0 0 transparent; }
    18%  { box-shadow: inset 0 0 26px -4px var(--dm-skill, #8cf); }
    100% { box-shadow: inset 0 0 26px -4px transparent; }
}

/* 被技能指到的那一格。跟「挨打」要分得出來 —— 挨打是紅的、
   被下技能是那個角色的顏色。 */
.dm-side-fx.dm-marked { animation: dmMarked 0.8s ease-out both; }
@keyframes dmMarked {
    0%   { background: transparent; }
    22%  { background: color-mix(in srgb, var(--dm-skill, #8cf) 16%, transparent); }
    100% { background: transparent; }
}

/* 免疫者：擋下來的那一瞬間套上一層殼。 */
.dm-side-fx.dm-ward-pop { animation: dmWardPop 0.7s ease-out both; }
@keyframes dmWardPop {
    0%   { box-shadow: inset 0 0 0 1px rgba(157, 184, 255, 0.95), 0 0 0 0 rgba(157, 184, 255, 0.45); }
    100% { box-shadow: inset 0 0 0 1px transparent, 0 0 0 22px rgba(157, 184, 255, 0); }
}

/* 技能名。浮在那一格上面，不佔版面 —— 對戰畫面已經很擠了。
   它是自己一個元素，所以不會跟上面那些搶 animation。 */
.dm-cast-tag {
    position: absolute; left: 50%; top: 4px; z-index: 12;
    transform: translateX(-50%);
    padding: 3px 11px; border-radius: 999px; white-space: nowrap;
    font-size: 0.72rem; font-weight: 700; letter-spacing: 1.5px;
    color: var(--dm-skill, #8cf);
    background: color-mix(in srgb, var(--dm-skill, #8cf) 16%, rgba(0, 0, 0, 0.55));
    border: 1px solid color-mix(in srgb, var(--dm-skill, #8cf) 55%, transparent);
    pointer-events: none;
    animation: dmCastTag 1.2s ease-out both;
}
@keyframes dmCastTag {
    0%   { opacity: 0; transform: translate(-50%, 8px) scale(0.9); }
    12%  { opacity: 1; transform: translate(-50%, -2px) scale(1.04); }
    70%  { opacity: 1; transform: translate(-50%, -6px) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -16px) scale(0.98); }
}

/* 預言家：一道光掃過選項，掃完那兩個錯的就被劃掉了。 */
.dm-options.dm-scan { position: relative; overflow: hidden; }
.dm-options.dm-scan::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(100deg, transparent 38%,
        rgba(255, 240, 190, 0.28) 50%, transparent 62%);
    animation: dmScan 0.5s ease-out both;
}
@keyframes dmScan {
    0%   { transform: translateX(-110%); }
    100% { transform: translateX(110%); }
}

/* 吸血者：一條從對手流回自己的線。 */
.dm-drain {
    position: absolute; left: 50%; width: 3px; z-index: 11;
    transform: translateX(-50%); pointer-events: none;
    background: linear-gradient(to top, rgba(224, 85, 79, 0), rgba(224, 85, 79, 0.85));
    animation: dmDrain 0.55s ease-in both;
}
@keyframes dmDrain {
    0%   { opacity: 0; clip-path: inset(100% 0 0 0); }
    30%  { opacity: 1; }
    100% { opacity: 0; clip-path: inset(0 0 100% 0); }
}

/* 蓄能者：多一層的時候那排小點跳一下。 */
.dm-charge-up { animation: dmChargeUp 0.5s cubic-bezier(0.22, 1.4, 0.4, 1) both; }
@keyframes dmChargeUp {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.35); }
    100% { transform: scale(1); }
}

/* 處刑者：對手掉到一半血以下，那一格會一直帶著一個記號。
   畫在卡片的 ::before 上 —— 虛擬元素有自己的 animation，
   不會跟特效層或卡片本身搶。 */
.dm-side.dm-exec-mark::before {
    content: ''; position: absolute; inset: -1px; border-radius: inherit;
    pointer-events: none; z-index: 2;
    box-shadow: inset 0 0 0 1px rgba(255, 110, 90, 0.55);
    animation: dmExecMark 1.8s ease-in-out infinite;
}
@keyframes dmExecMark {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 0.9; }
}

@media (prefers-reduced-motion: reduce) {
    .dm-side-fx.dm-cast, .dm-side-fx.dm-marked, .dm-side-fx.dm-ward-pop,
    .dm-cast-tag, .dm-drain, .dm-charge-up,
    .dm-options.dm-scan::after { animation: none; }
    .dm-side-fx { opacity: 0 !important; }
    .dm-cast-tag { opacity: 1; }
    .dm-side.dm-exec-mark::before { animation: none; opacity: 0.6; }
}

/* ── 入場動畫（牌位獎勵，白金以上） ─────────────────────────────
   規則在 entrance.js，演出在 entrancefx.js，這裡是看得到的部分。

   每一階是不一樣的演出，不是同一支換顏色 —— 顏色靠 --ent-c 帶進來，
   但碎片的形狀、光環的厚度、軌道點數各階不同，在最底下分流。

   動畫只掛在 .ent-stage 自己的子元素上，不碰頁面上任何既有的東西。
   以前在對戰那邊學到的：給整頁套 transform 會讓 backdrop-filter 的
   那幾條 bar 重新合成，整個 UI 會閃一下黑。 */
.ent-stage {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: grid;
    place-items: center;
    align-content: center;
    gap: 42px;
    cursor: pointer;
    overflow: hidden;
    animation: entIn 240ms ease-out both;
}
.ent-stage.ent-out { animation: entOut 300ms ease-in both; }
@keyframes entIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes entOut { from { opacity: 1; } to { opacity: 0; } }

/* 要蓋住後面的頁面。半透明會讓登入畫面的字透出來，整段就廉價了。 */
.ent-veil {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(circle at 50% 42%, color-mix(in srgb, var(--ent-c) 30%, transparent) 0%, transparent 55%),
        radial-gradient(circle at 50% 42%, rgba(10, 14, 26, 0.6) 0%, #03040a 72%),
        #03040a;
}

/* 放射光線。從中心往外掃一圈。 */
.ent-rays { position: absolute; inset: 0; display: grid; place-items: center; }
.ent-rays i {
    position: absolute;
    width: 2px;
    height: 54vmin;
    transform-origin: 50% 100%;
    rotate: var(--a);
    translate: 0 -27vmin;
    background: linear-gradient(to top, color-mix(in srgb, var(--ent-c) 85%, transparent), transparent 72%);
    opacity: 0;
    animation: entRay 1200ms ease-out both;
}
@keyframes entRay {
    0% { opacity: 0; scale: 1 0.2; }
    35% { opacity: 0.9; }
    100% { opacity: 0; scale: 1 1.4; }
}

.ent-core {
    position: relative;
    display: grid;
    place-items: center;
    width: 260px;
    height: 260px;
}

/* 一直在呼吸的光暈。一次性的特效播完之後畫面不能就定住不動 ——
   那一刻才是玩家盯最久的。 */
.ent-halo {
    position: absolute;
    width: 260px; height: 260px;
    border-radius: 50%;
    background: radial-gradient(circle, color-mix(in srgb, var(--ent-c) 34%, transparent) 0%, transparent 64%);
    animation: entHalo 2600ms ease-in-out infinite;
}
@keyframes entHalo {
    0%, 100% { opacity: 0.5; scale: 0.88; }
    50% { opacity: 1; scale: 1.1; }
}

/* 持續旋轉的軌道與光點。 */
.ent-orbit {
    position: absolute;
    width: 218px; height: 218px;
    border-radius: 50%;
    border: 1px dashed color-mix(in srgb, var(--ent-c) 45%, transparent);
    animation: entSpin 14s linear infinite;
}
.ent-orbit i {
    position: absolute;
    inset: 0;
    rotate: var(--a);
}
.ent-orbit i::before {
    content: '';
    position: absolute;
    top: -3px; left: 50%;
    width: 6px; height: 6px;
    margin-left: -3px;
    border-radius: 50%;
    background: var(--ent-c);
    box-shadow: 0 0 10px var(--ent-c);
}
@keyframes entSpin { to { rotate: 360deg; } }

/* 光環。一圈一圈往外推。 */
.ent-rings { position: absolute; display: grid; place-items: center; }
.ent-rings i {
    position: absolute;
    width: 190px; height: 190px;
    border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--ent-c) 80%, transparent);
    opacity: 0;
    animation: entRing 1600ms cubic-bezier(0.16, 0.9, 0.3, 1) both;
}
@keyframes entRing {
    0% { opacity: 0; scale: 0.3; }
    25% { opacity: 1; }
    100% { opacity: 0; scale: 2.3; }
}

/* 碎片收束。從外面飛進來，停在徽章上。 */
.ent-shards { position: absolute; display: grid; place-items: center; }
.ent-shards i {
    position: absolute;
    width: 7px; height: 7px;
    background: var(--ent-c);
    rotate: var(--a);
    opacity: 0;
    box-shadow: 0 0 8px color-mix(in srgb, var(--ent-c) 80%, transparent);
    animation: entShard 950ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
@keyframes entShard {
    0% { opacity: 0; translate: 0 calc(var(--d) * -1); scale: 0.4; }
    30% { opacity: 1; }
    100% { opacity: 0; translate: 0 0; scale: 1.1; }
}

/* 徽章。轉進來、定住、再彈一下。 */
.ent-badge {
    position: relative;
    display: grid;
    place-items: center;
    filter: drop-shadow(0 0 18px color-mix(in srgb, var(--ent-c) 75%, transparent))
            drop-shadow(0 0 48px color-mix(in srgb, var(--ent-c) 45%, transparent));
    animation: entBadge 1200ms cubic-bezier(0.14, 0.9, 0.24, 1) both;
    animation-delay: 160ms;
}
@keyframes entBadge {
    0% { opacity: 0; scale: 0.3; rotate: var(--ent-spin); }
    62% { opacity: 1; scale: 1.14; rotate: 0deg; }
    78% { scale: 0.97; }
    100% { opacity: 1; scale: 1; rotate: 0deg; }
}

.ent-caption {
    position: relative;
    text-align: center;
    padding: 0 16px;
}
.ent-tier {
    font-size: 1.6rem;
    font-weight: 800;
    letter-spacing: 4px;
    color: #fff;
    text-shadow: 0 0 20px color-mix(in srgb, var(--ent-c) 90%, transparent);
    animation: entRise 700ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
    animation-delay: 620ms;
}
@keyframes entRise {
    from { opacity: 0; translate: 0 14px; }
    to { opacity: 1; translate: 0 0; }
}

/* S1。蓋在徽章右上角 —— 它是這一枚徽章的季別，擺到畫面角落就
   只是一個不相干的標籤。整段動畫的收尾：徽章定住之後才蓋上去。 */
.ent-seal {
    position: absolute;
    top: 26px;
    right: 18px;
    display: flex;
    align-items: baseline;
    gap: 1px;
    padding: 4px 11px 3px;
    border: 2px solid var(--ent-c);
    border-radius: 999px;
    background: #05070e;
    color: var(--ent-c);
    font-weight: 900;
    font-style: italic;
    box-shadow: 0 0 22px color-mix(in srgb, var(--ent-c) 70%, transparent),
                inset 0 0 12px color-mix(in srgb, var(--ent-c) 28%, transparent);
    animation: entSeal 620ms cubic-bezier(0.1, 1.4, 0.4, 1) both;
    animation-delay: 1000ms;
}
.ent-seal-s { font-size: 0.9rem; }
.ent-seal-n { font-size: 1.25rem; line-height: 1; }
@keyframes entSeal {
    0% { opacity: 0; scale: 2.6; rotate: -18deg; }
    70% { opacity: 1; scale: 0.92; rotate: 4deg; }
    100% { opacity: 1; scale: 1; rotate: -8deg; }
}

/* ── 每一階自己的味道 ──────────────────────────────────────── */
/* 白金：裝甲板。方的、厚的、軌道也是實線。 */
.ent-platinum .ent-shards i { width: 11px; height: 4px; border-radius: 1px; }
.ent-platinum .ent-rings i { border-width: 3px; }
.ent-platinum .ent-orbit { border-style: solid; animation-duration: 20s; }

/* 鑽石：稜面。菱形，轉得快一點。 */
.ent-diamond .ent-shards i {
    width: 10px; height: 10px;
    clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
.ent-diamond .ent-orbit i::before {
    border-radius: 0;
    rotate: 45deg;
}
.ent-diamond .ent-orbit { animation-duration: 11s; }

/* 大師：羽毛。細長、帶弧度。 */
.ent-master .ent-shards i {
    width: 4px; height: 16px;
    border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
}
.ent-master .ent-orbit { animation-duration: 9s; animation-direction: reverse; }

/* 傳奇：火舌。上尖下圓，光更濃。 */
.ent-legend .ent-shards i {
    width: 6px; height: 18px;
    border-radius: 50% 50% 50% 50% / 70% 70% 30% 30%;
}
.ent-legend .ent-halo { animation-duration: 1800ms; }
.ent-legend .ent-orbit { animation-duration: 7s; border-style: dotted; }

/* 巔峰：全部疊上去，再加一圈實心外環。 */
.ent-pinnacle .ent-shards i {
    width: 7px; height: 20px;
    border-radius: 50% 50% 50% 50% / 72% 72% 28% 28%;
}
.ent-pinnacle .ent-halo { animation-duration: 1500ms; }
.ent-pinnacle .ent-orbit { animation-duration: 6s; }
.ent-pinnacle .ent-core::after {
    content: '';
    position: absolute;
    width: 248px; height: 248px;
    border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--ent-c) 55%, transparent);
    box-shadow: 0 0 30px color-mix(in srgb, var(--ent-c) 40%, transparent),
                inset 0 0 30px color-mix(in srgb, var(--ent-c) 25%, transparent);
    animation: entSpin 24s linear infinite reverse;
    pointer-events: none;
}
.ent-pinnacle .ent-rings i { border-width: 3px; }

/* 關掉動態效果的人：一張定格的卡。資訊一樣在，只是不動。 */
.ent-still .ent-rays,
.ent-still .ent-rings,
.ent-still .ent-shards { display: none; }
.ent-still .ent-halo,
.ent-still .ent-orbit,
.ent-still .ent-core::after { animation: none; }
.ent-still .ent-badge,
.ent-still .ent-tier,
.ent-still .ent-seal { animation: none; opacity: 1; scale: 1; rotate: 0deg; translate: 0; }
.ent-still .ent-seal { rotate: -8deg; }

/* ── 個人主頁：編輯入場動畫 ──────────────────────────────────── */
.ent-pick {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 10px;
}
.ent-chip {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 12px 6px 10px;
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(255, 255, 255, 0.04);
    cursor: pointer;
    transition: border-color 160ms, background 160ms, transform 160ms;
}
.ent-chip:hover { transform: translateY(-2px); }
.ent-chip[aria-pressed="true"] {
    border-color: var(--ent-c);
    background: color-mix(in srgb, var(--ent-c) 14%, transparent);
    box-shadow: 0 0 0 1px var(--ent-c) inset;
}
.ent-chip-name { font-size: 0.74rem; letter-spacing: 0.5px; color: var(--text-sub); }
.ent-chip[aria-pressed="true"] .ent-chip-name { color: var(--ent-c); font-weight: 700; }
.ent-chip-s {
    position: absolute;
    top: 5px; right: 6px;
    font-size: 0.62rem;
    font-weight: 900;
    font-style: italic;
    color: var(--ent-c);
    opacity: 0.85;
}
.ent-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 18px 10px;
    font-size: 0.82rem;
    line-height: 1.7;
    color: var(--text-sub);
}
.ent-row { display: flex; gap: 8px; margin-top: 12px; }
.ent-row .btn { flex: 1; }

/* Keep the animated themes and primary glass panels intact. On mobile, only
   repeated list tiles avoid creating a separate live blur layer each. */
@media (max-width: 700px) {
    html:not([data-fx="low"]) :is(
        .book-item, .store-card, .acc-card, .dc-card, .mode-btn,
        .nav-icon-btn, .dc-sum-row, .wb-grid, .wb-word
    ) {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }

    html:not([data-fx="low"]) :is(.book-item, .store-card, .acc-card) {
        background-color: color-mix(in srgb, var(--glass-card-bg) 40%, var(--bg-color) 60%) !important;
    }
    html:not([data-fx="low"]) .book-item.selected {
        background-color: color-mix(in srgb, var(--accent) 12%, var(--bg-color) 88%) !important;
    }
}

/* 綜合精通測試版：只在組別切換時使用短動畫，不增加長駐模糊圖層。 */
.hm-beta {
    width: 100%; display: flex; align-items: center; gap: 13px;
    margin-top: 12px; padding: 19px 20px; text-align: left;
    color: var(--text-main); font-family: inherit; cursor: pointer;
    border: 1px solid rgba(249, 200, 73, .48); border-radius: 16px;
    background: linear-gradient(125deg, rgba(249, 200, 73, .17), rgba(249, 200, 73, .045) 70%), var(--card-bg);
    box-shadow: inset 0 1px 0 rgba(255, 236, 172, .12), 0 8px 25px rgba(38, 28, 3, .12);
    transition: transform .16s ease, border-color .2s ease, box-shadow .2s ease;
}
.hm-beta:hover { border-color: rgba(255, 224, 125, .85); box-shadow: inset 0 1px 0 rgba(255, 236, 172, .2), 0 10px 28px rgba(168, 120, 13, .16); }
.hm-beta:active { transform: scale(.99); }
.hm-beta-mark { color: #f9c849; font-size: 1.45rem; text-shadow: 0 0 14px rgba(249, 200, 73, .4); }
.hm-beta-txt { flex: 1; font-size: 1rem; font-weight: 700; letter-spacing: .5px; }
.hm-beta-tag { display: inline-block; margin-left: 5px; padding: 2px 6px; border-radius: 6px; border: 1px solid rgba(249, 200, 73, .55); color: #ffe29a; font-size: .65rem; vertical-align: middle; }
.hm-beta-sub { display: block; margin-top: 5px; color: var(--text-sub); font-size: .78rem; font-weight: 400; letter-spacing: 0; line-height: 1.5; }
.hm-beta-go { color: #f9c849; font-size: 1.4rem; font-weight: 300; }

.mastery-beta-progress { margin: -3px 0 20px; padding: 11px 14px; border: 1px solid rgba(249, 200, 73, .34); border-radius: 13px; background: rgba(249, 200, 73, .075); }
.mastery-beta-progress-copy { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 3px 10px; color: #ffe49a; font-size: .78rem; }
.mastery-beta-progress-copy span { color: var(--text-sub); text-align: right; white-space: nowrap; }
.mastery-beta-track { height: 5px; margin-top: 10px; border-radius: 9px; overflow: hidden; background: rgba(249, 200, 73, .16); }
.mastery-beta-track span { display: block; height: 100%; width: 0; border-radius: inherit; background: linear-gradient(90deg, #c78922, #ffe492); transition: width .38s ease; }
.mastery-beta-overall { display:flex; align-items:center; gap:10px; margin-top:8px; color:var(--text-sub); font-size:.72rem; white-space:nowrap; }
.mastery-beta-overall-track { flex:1; min-width:32px; height:3px; overflow:hidden; border-radius:9px; background:rgba(255,255,255,.14); }
.mastery-beta-overall-track span { display:block; width:0; height:100%; border-radius:inherit; background:linear-gradient(90deg,#d0b47a,#fff0cb); transition:width .38s ease; }
.mastery-beta-transition { min-height: 220px; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 9px; text-align: center; border-radius: 20px; color: #ffe7a9; border: 1px solid rgba(249, 200, 73, .35); background: radial-gradient(circle at 50% 35%, rgba(249, 200, 73, .2), transparent 68%), var(--card-bg); }
.mastery-beta-transition-star { font-size: 2.5rem; color: #f9c849; filter: drop-shadow(0 0 12px rgba(249, 200, 73, .45)); }
.mastery-beta-transition small { color: var(--text-sub); }
.mastery-beta-enter { animation: masteryBetaEnter .8s cubic-bezier(.2,.8,.25,1) both; }
@keyframes masteryBetaEnter { 0% { opacity: 0; transform: translateY(13px) scale(.97); } 50% { opacity: 1; transform: translateY(-3px) scale(1.015); } 100% { opacity: 1; transform: none; } }
.mastery-beta-active .mode-badge { border: 1px solid rgba(249, 200, 73, .42); color: #ffe5a3 !important; background: rgba(249, 200, 73, .12) !important; }

.mastery-beta-survey { position: fixed; inset: 0; z-index: 10010; display: grid; place-items: center; padding: 18px; background: rgba(9, 8, 6, .78); }
.mastery-beta-survey-card { width: min(100%, 440px); max-height: min(90vh, 780px); overflow-y: auto; padding: 24px; border-radius: 20px; border: 1px solid rgba(249, 200, 73, .48); background: color-mix(in srgb, var(--bg-color) 86%, #432c08 14%); box-shadow: 0 24px 70px rgba(0, 0, 0, .45), inset 0 1px 0 rgba(255, 237, 180, .15); color: var(--text-main); }
.mastery-beta-survey-mark { display: block; color: #f9c849; font-size: 2rem; text-align: center; }
.mastery-beta-survey-card h3 { margin: 5px 0 8px; text-align: center; color: #ffe49a; }
.mastery-beta-survey-card p { color: var(--text-sub); font-size: .87rem; line-height: 1.65; }
.mastery-beta-survey-card fieldset { border: 0; padding: 0; margin: 20px 0 0; }
.mastery-beta-survey-card legend, .mastery-beta-comment-label { display: block; margin-bottom: 10px; font-size: .88rem; font-weight: 650; }
.mastery-beta-survey-card fieldset:first-of-type label { display: inline-flex; align-items: center; gap: 4px; margin-right: 12px; font-size: .83rem; cursor: pointer; }
.mastery-beta-survey-card input[type=radio] { accent-color: #e7b53f; }
.mastery-beta-ratings { display: flex; gap: 8px; }
.mastery-beta-ratings label { flex: 1; cursor: pointer; }
.mastery-beta-ratings input { position: absolute; opacity: 0; }
.mastery-beta-ratings span { display: grid; place-items: center; min-height: 42px; border: 1px solid rgba(249, 200, 73, .3); border-radius: 10px; color: var(--text-main); }
.mastery-beta-ratings input:checked + span { border-color: #f9c849; background: rgba(249, 200, 73, .22); color: #ffe49a; }
.mastery-beta-ratings input:focus-visible + span { outline: 2px solid #f9c849; outline-offset: 2px; }
.mastery-beta-comment-label { margin-top: 19px; }
.mastery-beta-survey-card textarea { width: 100%; box-sizing: border-box; padding: 11px; border-radius: 10px; border: 1px solid var(--border); background: var(--card-bg); color: var(--text-main); resize: vertical; font: inherit; }
.mastery-beta-survey-actions { display: flex; gap: 10px; margin-top: 18px; }
.mastery-beta-survey-actions .btn { flex: 1; margin: 0; }
#mastery-beta-survey-status { min-height: 1.2em; margin-top: 8px; font-size: .8rem; color: #ffe49a; }
@media (prefers-reduced-motion: reduce) { .mastery-beta-enter { animation: none; } .mastery-beta-track span, .mastery-beta-overall-track span { transition: none; } }

.voice-prep { position: fixed; inset: 0; z-index: 10020; display: grid; place-items: center; padding: 20px; background: rgba(8, 9, 14, .82); }
.voice-prep-card { width: min(100%, 410px); padding: 25px; border: 1px solid rgba(249, 200, 73, .38); border-radius: 20px; background: var(--card-bg); box-shadow: 0 25px 75px rgba(0, 0, 0, .5); text-align: center; color: var(--text-main); }
.voice-prep-mark { display: block; color: #f9c849; font-size: 2rem; animation: voicePrepPulse 1.5s ease-in-out infinite; }
.voice-prep-card h3 { margin: 8px 0 10px; }
.voice-prep-card p { color: var(--text-sub); font-size: .88rem; line-height: 1.5; }
#voice-prep-status:empty { display: none; }
.voice-prep-track { height: 6px; margin: 18px 0; border-radius: 8px; overflow: hidden; background: rgba(249, 200, 73, .15); }
.voice-prep-track span { display: block; width: 0; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #d59e31, #ffe095); transition: width .3s ease; }
.voice-prep-actions { display: flex; gap: 9px; justify-content: center; flex-wrap: wrap; }
.voice-prep-actions .btn { margin: 0; min-width: 100px; }
@keyframes voicePrepPulse { 50% { opacity: .55; transform: scale(.92); } }
@media (prefers-reduced-motion: reduce) { .voice-prep-mark { animation: none; } .voice-prep-track span { transition: none; } }

/* ==================== 選定位之後的過渡畫面（雙方對戰卡） ==================== */
.dm-vs {
    position: fixed; inset: 0; z-index: 70; display: flex; flex-direction: column;
    align-items: center; justify-content: center; padding: 20px 14px;
    background:
        linear-gradient(115deg, rgba(63,185,138,0.16) 0%, rgba(10,12,16,0) 42%),
        linear-gradient(295deg, rgba(224,85,79,0.18) 0%, rgba(10,12,16,0) 42%),
        #0a0c10;
    opacity: 0; transition: opacity .25s ease;
}
.dm-vs.hidden { display: none; }
.dm-vs.dm-vs-in { opacity: 1; }
.dm-vs-row { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; max-width: 560px; }
.dm-vs-card {
    flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; text-align: center;
    padding: 18px 8px 16px; border-radius: 16px; border: 1px solid rgba(255,255,255,0.08);
    background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.01));
}
.dm-vs-me { border-color: rgba(63,185,138,0.45); animation: dmVsLeft .55s cubic-bezier(.2,.8,.25,1) both; }
.dm-vs-foe { border-color: rgba(224,85,79,0.45); animation: dmVsRight .55s cubic-bezier(.2,.8,.25,1) .08s both; }
@keyframes dmVsLeft { from { opacity: 0; transform: translateX(-60px) skewX(-6deg); } }
@keyframes dmVsRight { from { opacity: 0; transform: translateX(60px) skewX(6deg); } }
.dm-vs-name { margin-top: 10px; font-size: 0.95rem; font-weight: 700; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dm-vs-role { margin-top: 4px; font-size: 0.75rem; letter-spacing: 2px; color: var(--text-sub); }
.dm-vs-rank { margin-top: 12px; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }
.dm-vs-rank svg { width: 44px; height: 44px; flex-shrink: 0; }
.dm-vs-rank b { display: block; font-size: 0.85rem; color: var(--tier, #fff); letter-spacing: 1px; }
.dm-vs-rank span { display: block; margin-top: 2px; font-size: 0.68rem; color: var(--text-sub); }
.dm-vs-norank { font-size: 0.72rem; color: var(--text-sub); }
.dm-vs-mid {
    flex-shrink: 0; font-size: 1.6rem; font-weight: 900; font-style: italic; letter-spacing: 2px;
    color: #fff; text-shadow: 0 0 18px rgba(255,255,255,0.35); animation: dmVsMid .5s cubic-bezier(.2,.8,.25,1) .2s both;
}
@keyframes dmVsMid { from { opacity: 0; transform: scale(2.2); } }
.dm-vs-penalty {
    margin-top: 18px; max-width: 420px; padding: 10px 14px; border-radius: 12px; font-size: 0.8rem; line-height: 1.55;
    color: #f0c040; border: 1px solid rgba(240,192,64,0.4); background: rgba(240,192,64,0.08); text-align: center;
}
.dm-vs-count { margin-top: 22px; font-size: 0.82rem; letter-spacing: 2px; color: var(--text-sub); font-variant-numeric: tabular-nums; }
.dm-vs-bar { margin-top: 10px; width: 100%; max-width: 360px; height: 3px; border-radius: 2px; background: rgba(255,255,255,0.1); overflow: hidden; }
.dm-vs-bar i { display: block; height: 100%; width: 100%; background: linear-gradient(90deg, #3fb98a, #e0554f); transform-origin: left; animation: dmVsBar linear both; }
@keyframes dmVsBar { from { transform: scaleX(0); } to { transform: scaleX(1); } }


/* 題目區、回饋區切換的淡入淡出（app.js 的 animateAreaIn / leaveThen）。
   只動透明度：裡面有固定在畫面底部的按鈕，整塊位移會讓它跟著跳。 */
/* 同一塊如果也在跑題目卡片的進場／離場動畫，以那個為準（不要被淡入蓋掉）。 */
.sv-area-in:not(.question-animate):not(.mq-exit-ok):not(.mq-exit-bad) { animation: svAreaIn 0.24s ease-out both; }
.sv-area-out { animation: svAreaOut 0.16s ease-in both; pointer-events: none; }
@keyframes svAreaIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes svAreaOut { from { opacity: 1; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
    .sv-area-in, .sv-area-out { animation: none; }
}

/* ── 鍵盤操作提示（電腦版，設定裡可以關；關掉一樣能用鍵盤） ── */
.kbd-tip { display: none; }
html[data-keyhints] .kbd-tip {
    display: block; margin-top: 12px; text-align: center;
    font-size: 0.72rem; color: var(--text-sub); opacity: 0.7; letter-spacing: 0.5px;
}
html[data-keyhints] [data-keylabel] { position: relative; }
html[data-keyhints] [data-keylabel]::after {
    content: attr(data-keylabel);
    position: absolute; top: 4px; right: 8px;
    font-size: 0.6rem; line-height: 1; font-weight: 500; letter-spacing: 0;
    opacity: 0.45; pointer-events: none;
}
/* 選項的按鍵：app.js 依「按鍵設定」標在每個按鈕的 data-optkey（可能是 1、Q、A…） */
html[data-keyhints] [data-optkey] { position: relative; }
html[data-keyhints] [data-optkey]::after {
    content: attr(data-optkey);
    position: absolute; top: 4px; left: 8px;
    font-size: 0.62rem; line-height: 1; opacity: 0.5; pointer-events: none; font-weight: 600;
}
/* 設定裡的按鍵設定 */
.key-settings { margin-top: 12px; display: grid; gap: 8px; }
.key-settings-row { display: flex; align-items: center; gap: 10px; }
.key-settings-row > span { flex: 1; font-size: 0.88rem; color: var(--text-main); }
.key-settings select { padding: 7px 10px; border-radius: 10px; border: 1px solid var(--border); background: var(--bg-color); color: var(--text-main); font: inherit; font-size: 0.85rem; }
.key-custom { display: flex; flex-wrap: wrap; gap: 6px; }
.key-custom.hidden { display: none; }
.key-custom button { min-width: 64px; padding: 6px 8px; border-radius: 9px; border: 1px solid var(--border); background: rgba(255,255,255,0.05);
    color: var(--text-main); font: inherit; font-size: 0.8rem; cursor: pointer; }
.key-custom button small { display: block; font-size: 0.62rem; color: var(--text-sub); }
.key-custom button.listening { border-color: #fbbf24; color: #fde68a; }
/* 鍵盤游標停在已經有字母的格子上（← → 移過去，Backspace 拿掉的就是它） */
.letter-tile.cursor { box-shadow: 0 0 0 2px var(--text-main); }

/* ── 文字大小（設定 → 外觀） ──
   整站的字大多是 rem，改根元素字級就跟著縮放；按鈕和選項的寬高是 px，
   字變大時讓它換行、高度跟著長，不要超出框。 */
html[data-font="s"] { font-size: 90%; }
html[data-font="l"] { font-size: 112.5%; }
html[data-font="xl"] { font-size: 125%; }
html[data-font="l"] :is(.btn, .btn-mcq, .mode-btn, .hub-item, .dm-option, .option-btn),
html[data-font="xl"] :is(.btn, .btn-mcq, .mode-btn, .hub-item, .dm-option, .option-btn) {
    white-space: normal; overflow-wrap: anywhere; height: auto; min-height: fit-content;
}
.font-scale { margin-top: 14px; }
.font-scale-label { font-size: 0.85rem; color: var(--text-sub); margin-bottom: 8px; }
.font-scale-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.font-scale-row button {
    padding: 8px 0; border-radius: 10px; border: 1px solid var(--border);
    background: transparent; color: var(--text-sub); font: inherit; font-size: 0.85rem; cursor: pointer;
}
.font-scale-row button.on { border-color: var(--accent); color: var(--text-main); background: rgba(255,255,255,0.08); font-weight: 600; }
/* 精通 Lv4、Lv5 拼字：中文旁邊的詞性 */
.mastery-typing-pos {
    display: inline-block;
    margin-left: 4px;
    padding: 2px 10px;
    border-radius: 8px;
    background: rgba(255,152,0,.14);
    border: 1px solid rgba(255,152,0,.45);
    color: #ffb74d;
    font-size: .95rem;
    font-weight: 700;
    font-style: italic;
    vertical-align: middle;
    white-space: nowrap;
}
.mastery-l0-senses {
    max-width: 38rem;
    margin: 10px auto 0;
    color: var(--text-sub);
    opacity: .78;
    font-size: .85rem;
    line-height: 1.55;
}

/* ==================== 信箱分頁＋系統公告（announcements.js） ==================== */
.mb-tabs { display: flex; gap: 6px; padding: 4px; margin: 0 0 16px; border: 1px solid var(--border); border-radius: 14px; background: rgba(255,255,255,0.03); }
.mb-tab { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 10px 8px; border: 0; border-radius: 10px;
    background: transparent; color: var(--text-sub); font: inherit; font-size: 0.9rem; font-weight: 600; letter-spacing: 1px; cursor: pointer; transition: background .18s, color .18s; }
.mb-tab.active { background: rgba(255,255,255,0.1); color: var(--text-main); }
.mb-tab-count { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: #ff5a5a; color: #fff; font-size: 0.68rem; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center; letter-spacing: 0; }
.mb-tab-count[hidden] { display: none; }

/* 分類顏色 */
.an-chip { display: inline-block; padding: 2px 8px; border-radius: 99px; font-size: 0.68rem; font-weight: 700; letter-spacing: 1px; border: 1px solid; }
.an-chip-update { color: #7dd3fc; border-color: rgba(125,211,252,0.45); background: rgba(125,211,252,0.1); }
.an-chip-event { color: #fbbf24; border-color: rgba(251,191,36,0.45); background: rgba(251,191,36,0.1); }
.an-chip-maintenance { color: #fb923c; border-color: rgba(251,146,60,0.45); background: rgba(251,146,60,0.1); }
.an-chip-important { color: #ff8a80; border-color: rgba(255,138,128,0.5); background: rgba(255,138,128,0.12); }
.an-thumb-update { background: linear-gradient(135deg, rgba(125,211,252,0.35), rgba(59,130,246,0.15)); }
.an-thumb-event { background: linear-gradient(135deg, rgba(251,191,36,0.4), rgba(234,88,12,0.15)); }
.an-thumb-maintenance { background: linear-gradient(135deg, rgba(251,146,60,0.35), rgba(120,113,108,0.2)); }
.an-thumb-important { background: linear-gradient(135deg, rgba(255,90,90,0.4), rgba(127,29,29,0.2)); }

/* 公告列表 */
.an-list { display: flex; flex-direction: column; gap: 10px; }
.an-row { position: relative; display: flex; gap: 12px; align-items: stretch; width: 100%; padding: 10px; text-align: left; border: 1px solid var(--border);
    border-radius: 16px; background: var(--card-bg); color: var(--text-main); font: inherit; cursor: pointer; transition: transform .12s, border-color .2s; }
.an-row:active { transform: scale(0.985); }
.an-row.unread { border-color: rgba(255,255,255,0.28); }
.an-thumb { flex: 0 0 76px; height: 76px; border-radius: 12px; overflow: hidden; display: flex; align-items: center; justify-content: center;
    font-size: 0.8rem; font-weight: 700; letter-spacing: 2px; color: rgba(255,255,255,0.85); }
.an-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.an-row-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 4px; justify-content: center; }
.an-row-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.an-when { font-size: 0.72rem; color: var(--text-sub); }
.an-row-title { font-size: 0.98rem; font-weight: 700; line-height: 1.35; overflow-wrap: anywhere; }
.an-row-sub { font-size: 0.78rem; color: var(--text-sub); line-height: 1.5; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.an-dot { position: absolute; top: 10px; right: 10px; width: 9px; height: 9px; border-radius: 50%; background: #ff5a5a; box-shadow: 0 0 8px rgba(255,90,90,0.6); }

/* 內文（底部抽屜；寬螢幕置中） */
.an-overlay { position: fixed; inset: 0; z-index: 9100; display: flex; align-items: flex-end; justify-content: center; background: rgba(0,0,0,0.78);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); opacity: 0; transition: opacity .2s; }
.an-overlay.show { opacity: 1; }
.an-overlay.hidden { display: none !important; }
.an-sheet { width: 100%; max-width: 560px; max-height: 88vh; display: flex; flex-direction: column; background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 22px 22px 0 0; backdrop-filter: var(--glass-blur) saturate(var(--glass-sat)); -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat)); }
.an-overlay.show .an-sheet { animation: addBookIn .28s cubic-bezier(.22,1,.36,1) both; }
.an-sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.an-sheet-label { font-size: 0.8rem; letter-spacing: 2px; color: var(--text-sub); }
.an-sheet-body { overflow-y: auto; padding: 0 20px calc(22px + env(safe-area-inset-bottom)); }
.an-cover { display: block; width: calc(100% + 40px); margin: 0 -20px 16px; aspect-ratio: 16 / 9; object-fit: cover; }
.an-detail-head { display: flex; align-items: center; gap: 8px; margin-top: 18px; }
.an-cover + .an-detail-head { margin-top: 0; }
.an-detail-title { margin: 10px 0 6px; font-size: 1.35rem; line-height: 1.35; letter-spacing: 0.5px; overflow-wrap: anywhere; }
.an-body { font-size: 0.95rem; line-height: 1.8; color: var(--text-main); overflow-wrap: anywhere; }
.an-p { margin: 0 0 12px; }
.an-h { margin: 18px 0 8px; font-size: 1.02rem; letter-spacing: 0.5px; }
.an-ul { margin: 0 0 12px; padding-left: 1.3em; }
.an-ul li { margin: 3px 0; }
.an-body strong { color: #fde68a; }
.an-link { color: #7dd3fc; text-decoration: underline; text-underline-offset: 3px; }
.an-img { display: block; width: 100%; border-radius: 12px; margin: 6px 0 14px; }
.an-action { width: 100%; margin: 8px 0 0; font-weight: 700; letter-spacing: 1px; }
@media (min-width: 700px) {
    .an-overlay { align-items: center; padding: 24px; }
    .an-sheet { border-radius: 22px; max-height: 82vh; }
}

/* 預告卡：置中的卡片，有封面（沒有就用分類色帶） */
.an-popup-overlay { align-items: center; padding: 20px; }
.an-popup { width: 100%; max-width: 380px; overflow: hidden; border-radius: 22px; border: 1px solid rgba(255,255,255,0.18); background: var(--card-bg);
    box-shadow: 0 24px 60px rgba(0,0,0,0.45); backdrop-filter: var(--glass-blur) saturate(var(--glass-sat)); -webkit-backdrop-filter: var(--glass-blur) saturate(var(--glass-sat)); }
.an-popup-overlay.show .an-popup { animation: anPopIn .38s cubic-bezier(.22,1.3,.36,1) both; }
@keyframes anPopIn { from { transform: translateY(18px) scale(.94); opacity: 0; } }
.an-popup-cover { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.an-popup-banner { height: 92px; display: flex; align-items: center; justify-content: center; font-size: 1.05rem; font-weight: 800; letter-spacing: 6px; color: rgba(255,255,255,0.9); }
.an-popup-inner { padding: 16px 20px 18px; }
.an-popup-inner .an-detail-head { margin-top: 0; }
.an-popup-title { margin: 10px 0 6px; font-size: 1.2rem; line-height: 1.4; overflow-wrap: anywhere; }
.an-popup-text { margin: 0 0 16px; font-size: 0.88rem; line-height: 1.7; color: var(--text-sub); }
.an-popup-actions { display: flex; flex-direction: column; gap: 8px; }
.an-popup-actions .btn { width: 100%; margin: 0; }
.an-popup-more { font-weight: 700; letter-spacing: 1px; }
.an-popup-hint { margin-top: 10px; text-align: center; font-size: 0.72rem; color: var(--text-sub); opacity: .8; }

/* 管理員編輯器 */
.an-admin { border-color: var(--border); background: var(--card-bg); }
.an-admin-h { margin-top: 0; color: var(--text-main); font-weight: 500; letter-spacing: 1px; border-bottom: 1px solid var(--border); padding-bottom: 15px; }
.an-admin-p { font-size: 0.85rem; color: var(--text-sub); margin-bottom: 14px; line-height: 1.7; }
.an-admin-note { min-height: 20px; font-size: 0.85rem; color: #fbbf24; margin-bottom: 8px; }
#an-admin-new { width: 100%; margin: 0 0 14px; }
.an-admin-list { display: flex; flex-direction: column; gap: 8px; }
.an-admin-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; }
.an-admin-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.an-admin-empty { font-size: 0.85rem; color: var(--text-sub); padding: 8px 2px; }
.an-status { font-size: 0.7rem; padding: 2px 7px; border-radius: 6px; background: rgba(255,255,255,0.08); color: var(--text-sub); }
.an-status-live { color: #4ade80; background: rgba(74,222,128,0.12); }
.an-status-scheduled { color: #7dd3fc; background: rgba(125,211,252,0.12); }
.an-editor { border: 1px solid var(--border); border-radius: 16px; padding: 14px; margin-bottom: 14px; }
.an-editor-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.an-editor-grid { display: grid; gap: 16px; }
@media (min-width: 900px) { .an-editor-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.an-label { display: block; font-size: 0.78rem; color: var(--text-sub); margin: 12px 0 6px; letter-spacing: 0.5px; }
.an-input { width: 100%; box-sizing: border-box; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-color);
    color: var(--text-main); font: inherit; font-size: 0.92rem; margin-bottom: 6px; }
.an-input.hidden { display: none; }
.an-textarea { min-height: 200px; resize: vertical; line-height: 1.6; }
.an-toolbar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.an-toolbar button { padding: 6px 10px; border-radius: 8px; border: 1px solid var(--border); background: rgba(255,255,255,0.05); color: var(--text-main); font: inherit; font-size: 0.78rem; cursor: pointer; }
.an-cover-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.an-cover-thumb { width: 120px; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 8px; border: 1px solid var(--border); }
.an-cover-thumb.hidden { display: none; }
.an-file { margin: 0; cursor: pointer; }
.an-check { display: flex; align-items: center; gap: 8px; font-size: 0.86rem; color: var(--text-main); margin: 10px 0 0; cursor: pointer; }
.an-check.hidden { display: none; }
.an-editor-actions { display: flex; gap: 10px; margin-top: 16px; }
.an-editor-actions .btn { flex: 1; margin: 0; }
.an-editor-actions .btn.hidden { display: none; }
.an-preview { border: 1px dashed var(--border); border-radius: 16px; max-height: 70vh; overflow: hidden auto; padding-top: 0; }
.an-preview .an-cover { border-radius: 16px 16px 0 0; }
@media (prefers-reduced-motion: reduce) { .an-overlay.show .an-sheet, .an-popup-overlay.show .an-popup { animation: none; } }

/* ==================== 生死戰好友房：自定義對戰設定（dm-custom-ui.js） ==================== */
.aw-custom { margin: 14px 0 16px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 14px; background: rgba(255,255,255,0.03); text-align: left; }
.aw-custom-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.aw-custom-preset { font-size: 0.78rem; font-weight: 700; padding: 2px 9px; border-radius: 99px; border: 1px solid var(--border); color: var(--text-sub); }
.aw-custom-preset.on { color: #fbbf24; border-color: rgba(251,191,36,0.5); background: rgba(251,191,36,0.1); }
.aw-custom-edit { margin-left: auto; padding: 5px 12px; border-radius: 10px; border: 1px solid var(--border); background: rgba(255,255,255,0.06);
    color: var(--text-main); font: inherit; font-size: 0.8rem; cursor: pointer; }
.aw-custom-edit.hidden { display: none; }
.aw-custom-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.aw-chip { font-size: 0.74rem; padding: 3px 9px; border-radius: 8px; background: rgba(255,255,255,0.07); color: var(--text-main); white-space: nowrap; }
.aw-custom-note { margin-top: 8px; font-size: 0.76rem; color: var(--text-sub); line-height: 1.5; }
.aw-custom-note:empty { display: none; }
.aw-custom-ready { width: 100%; margin: 10px 0 0; font-weight: 700; }
.aw-custom-ready.hidden { display: none; }

.dmc-body { padding-top: 6px; }
.dmc-label { font-size: 0.8rem; color: var(--text-sub); margin: 10px 0 8px; letter-spacing: 1px; }
.dmc-presets { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.dmc-preset { display: flex; flex-direction: column; gap: 3px; text-align: left; padding: 11px 12px; border-radius: 14px; border: 1px solid var(--border);
    background: rgba(255,255,255,0.04); color: var(--text-main); font: inherit; cursor: pointer; transition: border-color .15s, background .15s; }
.dmc-preset b { font-size: 0.95rem; letter-spacing: 1px; }
.dmc-preset span { font-size: 0.72rem; color: var(--text-sub); line-height: 1.45; }
.dmc-preset.on { border-color: #fbbf24; background: rgba(251,191,36,0.12); }
.dmc-adv-toggle { width: 100%; margin: 12px 0 4px; padding: 8px; border: 0; background: transparent; color: var(--text-sub); font: inherit; font-size: 0.85rem; cursor: pointer; }
.dmc-adv.hidden { display: none; }
.dmc-row { display: flex; flex-direction: column; gap: 6px; padding: 9px 0; border-top: 1px solid rgba(255,255,255,0.06); }
.dmc-row.hidden { display: none; }
.dmc-row > span { font-size: 0.8rem; color: var(--text-sub); }
.dmc-seg { display: flex; flex-wrap: wrap; gap: 6px; }
.dmc-opt { padding: 6px 11px; border-radius: 9px; border: 1px solid var(--border); background: rgba(255,255,255,0.04); color: var(--text-main);
    font: inherit; font-size: 0.82rem; cursor: pointer; }
.dmc-opt.on { border-color: #fbbf24; background: rgba(251,191,36,0.14); color: #fde68a; font-weight: 700; }
.dmc-number { width: 92px; min-height: 36px; padding: 6px 9px; border: 1px solid var(--border);
    border-radius: 9px; background: var(--card-bg); color: var(--text-main); font: inherit; font-size: 0.88rem; }
.dmc-number:focus-visible { outline: 2px solid #fbbf24; outline-offset: 2px; }
.dm-pip-g.dm-pip-count { font-size: 0.72rem; font-weight: 700; color: var(--text-sub); }
.dmc-summary { margin-top: 14px; }
.dmc-note { margin: 12px 0 4px; font-size: 0.76rem; line-height: 1.6; color: var(--text-sub); }
.dmc-status { min-height: 18px; font-size: 0.8rem; color: #fbbf24; }
.dmc-save { width: 100%; margin: 8px 0 0; font-weight: 700; }

/* 精通模式錯誤頁：正確答案「自然拆字」（音節）與「字根拆字」切換，一次只顯示一種 */
.training-answer-card.split-natural, .training-answer-card.split-root { display:flex; flex-direction:column; align-items:stretch; }
:is(.split-natural, .split-root) > .answer-reveal-label { order:1; }
:is(.split-natural, .split-root) > .split-toggle { order:2; }
:is(.split-natural, .split-root) > .answer-reveal-en { order:3; }
:is(.split-natural, .split-root) > .word-chunks-panel { order:4; }
:is(.split-natural, .split-root) > .answer-reveal-zh { order:5; }
:is(.split-natural, .split-root) > .spelling-diff { order:6; }
:is(.split-natural, .split-root) > .word-chunks-actions { order:7; }
.split-natural > .word-chunks-panel { display:none !important; }
.split-root > .answer-reveal-en { display:none; }
.split-root > .word-chunks-panel { margin:0 0 4px; }
.split-root .word-chunks-title { display:none; }
.split-root .word-chunks-row { padding-top:2px; }
.split-toggle { display:flex; align-self:center; gap:3px; padding:3px; margin:0 0 14px; border:1px solid var(--border); border-radius:999px; background:var(--card-bg); }
.split-toggle.hidden { display:none; }
.split-toggle button { border:0; border-radius:999px; padding:6px 14px; min-height:32px; background:transparent; color:var(--text-sub); font:inherit; font-size:.8rem; letter-spacing:.5px; cursor:pointer; transition:background .15s, color .15s; }
.split-toggle button.is-on { background:rgba(255,255,255,0.12); color:var(--text-main); font-weight:600; box-shadow:inset 0 0 0 1px var(--accent); }
.answer-reveal-en .syl-cell { display:inline-block; border-radius:8px; padding:0 .06em; transition:color .15s, background .15s; }
.answer-reveal-en .syl-cell.is-speaking { color:var(--accent); background:rgba(255,255,255,0.07); }
.answer-reveal-en .syl-dot { color:var(--text-sub); opacity:.5; font-weight:400; margin:0 .06em; }
.answer-reveal-en .syl-bound { text-decoration:underline; text-decoration-color:var(--accent); text-decoration-thickness:2px; text-underline-offset:.18em; }
.answer-reveal-en .syl-silent { opacity:.45; }

/* ==================== 詞性轉換：入口、課程、測驗 ==================== */
/* 字尾的重點色固定用金色：有些主題的 accent 是白色，字尾會跟單字混在一起 */
:root { --ps-hi: #f0c040; }
.ps-hero { text-align: center; padding: 18px 0 22px; }
.ps-hero-demo { font-size: clamp(2rem, 9vw, 2.5rem); font-weight: 700; letter-spacing: .5px; color: var(--text-main); }
.ps-hero-suf { display: inline-block; vertical-align: bottom; overflow: hidden; white-space: nowrap; color: var(--ps-hi); animation: psHeroSuf 3.6s ease-in-out infinite; }
@keyframes psHeroSuf { 0%, 15% { max-width: 0; opacity: 0; } 35%, 80% { max-width: 4em; opacity: 1; } 100% { max-width: 0; opacity: 0; } }
.ps-hero-title { margin-top: 12px; font-size: 1.1rem; font-weight: 600; color: var(--text-main); letter-spacing: 1px; }
.ps-hero-sub { margin-top: 6px; font-size: .82rem; color: var(--text-sub); }
.ps-entry {
    display: flex; flex-direction: column; align-items: flex-start; gap: 6px; width: 100%; text-align: left;
    padding: 20px 18px; margin-bottom: 12px; border: 1px solid var(--border); border-radius: 18px;
    background: var(--card-bg); color: var(--text-main); font-family: inherit; cursor: pointer;
    transition: transform .15s ease, border-color .15s ease; animation: psRise .4s ease-out both;
}
.ps-entry-quiz { animation-delay: .06s; }
.ps-entry:active { transform: scale(.985); }
@media (hover: hover) { .ps-entry:hover { border-color: var(--ps-hi); } }
.ps-entry-tag { font-size: .7rem; letter-spacing: 2px; color: var(--ps-hi); font-weight: 700; }
.ps-entry-title { font-size: 1.15rem; font-weight: 600; letter-spacing: .5px; color: var(--text-main); }
.ps-entry-sub { font-size: .8rem; color: var(--text-sub); line-height: 1.5; }
@keyframes psRise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.ps-lesson-list { display: flex; flex-direction: column; gap: 10px; padding-bottom: 24px; }
.ps-lesson-card {
    display: flex; flex-direction: column; gap: 6px; width: 100%; text-align: left; padding: 16px;
    border: 1px solid var(--border); border-radius: 16px; background: var(--card-bg); color: var(--text-main);
    font-family: inherit; cursor: pointer; animation: psRise .35s ease-out both;
}
.ps-lesson-card.is-done { border-color: rgba(76, 175, 80, .45); }
.ps-lesson-top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.ps-lesson-title { font-size: 1.05rem; font-weight: 600; }
.ps-lesson-state { font-size: .72rem; color: var(--text-sub); white-space: nowrap; }
.is-done .ps-lesson-state { color: #66bb6a; }
.ps-lesson-lead { font-size: .8rem; color: var(--text-sub); line-height: 1.55; }
.ps-lesson-marks { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 2px; }
.ps-lesson-marks span { font-size: .72rem; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-sub); }

.ps-dots { display: flex; justify-content: center; gap: 6px; margin: 2px 0 14px; }
.ps-dots span { width: 7px; height: 7px; border-radius: 50%; background: var(--border); transition: width .2s, background .2s; }
.ps-dots span.is-past { background: var(--text-sub); opacity: .5; }
.ps-dots span.is-on { width: 20px; border-radius: 4px; background: var(--ps-hi); }
.ps-slide {
    min-height: 360px; padding: 26px 18px; border: 1px solid var(--border); border-radius: 20px;
    background: var(--card-bg); text-align: center; touch-action: pan-y;
}
.ps-slide-in { animation: psSlideIn .32s cubic-bezier(.2, .8, .2, 1) both; }
.ps-slide-back { animation: psSlideBack .32s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes psSlideIn { from { opacity: 0; transform: translateX(26px); } to { opacity: 1; transform: none; } }
@keyframes psSlideBack { from { opacity: 0; transform: translateX(-26px); } to { opacity: 1; transform: none; } }
.ps-slide-nav { display: flex; gap: 10px; margin: 14px 0 26px; }
.ps-slide-nav .btn { flex: 1; margin: 0; }
.ps-slide-nav .btn.hidden { display: none; }

.ps-intro { display: flex; flex-direction: column; align-items: center; gap: 12px; padding-top: 18px; }
.ps-intro-title { font-size: 1.5rem; font-weight: 700; color: var(--text-main); letter-spacing: 1px; }
.ps-intro-lead { font-size: .9rem; color: var(--text-sub); line-height: 1.7; max-width: 320px; }
.ps-intro-marks { display: flex; flex-wrap: wrap; justify-content: center; gap: 7px; margin: 8px 0 4px; }
.ps-intro-marks span {
    padding: 6px 12px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-main);
    font-size: .92rem; font-weight: 600; animation: psPop .35s cubic-bezier(.2, .9, .3, 1.3) both;
}
@keyframes psPop { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: none; } }
.ps-intro-tip { margin-top: 14px; font-size: .74rem; color: var(--text-sub); opacity: .8; }

.ps-rule-marks { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.ps-rule-marks span { font-size: 1.5rem; font-weight: 700; color: var(--ps-hi); letter-spacing: .5px; }
.ps-rule-say { margin: 8px 0 22px; font-size: .92rem; color: var(--text-sub); line-height: 1.6; }
.ps-morph { padding: 22px 8px 18px; border-radius: 16px; background: rgba(255, 255, 255, .035); }
.ps-morph-word { font-size: clamp(2rem, 9vw, 2.6rem); font-weight: 700; color: var(--text-main); letter-spacing: .5px; white-space: nowrap; }
.ps-m-keep { display: inline-block; }
.ps-m-drop { display: inline-block; max-width: 6em; overflow: hidden; vertical-align: bottom; }
.ps-m-add { display: inline-block; max-width: 0; overflow: hidden; vertical-align: bottom; color: var(--ps-hi); white-space: nowrap; }
.ps-morph.is-go .ps-m-drop { animation: psDrop .7s ease-in forwards; }
.ps-morph.is-go .ps-m-add { animation: psAdd .55s .55s cubic-bezier(.2, .8, .2, 1) forwards; }
@keyframes psDrop { 0% { color: inherit; } 35% { color: #e57373; text-decoration: line-through; max-width: 6em; opacity: 1; } 100% { color: #e57373; text-decoration: line-through; max-width: 0; opacity: 0; } }
@keyframes psAdd { from { max-width: 0; } to { max-width: 8em; } }
.ps-morph-pos, .ps-morph-zh { position: relative; height: 1.9em; margin-top: 10px; perspective: 400px; }
.ps-morph-zh { height: 1.5em; margin-top: 6px; font-size: .82rem; color: var(--text-sub); }
.ps-morph-pos span, .ps-morph-zh span { position: absolute; left: 0; right: 0; backface-visibility: hidden; transition: transform .45s ease, opacity .45s ease; }
.ps-morph-pos span { display: inline-block; width: fit-content; margin: 0 auto; padding: 3px 14px; border-radius: 999px; font-size: .82rem; font-weight: 600; }
.ps-morph-pos .ps-m-from { border: 1px solid var(--border); color: var(--text-sub); }
.ps-morph-pos .ps-m-to { border: 1px solid var(--ps-hi); color: var(--ps-hi); }
.ps-morph .ps-m-to { opacity: 0; transform: rotateX(-90deg); }
.ps-morph.is-go .ps-morph-pos .ps-m-from, .ps-morph.is-go .ps-morph-zh .ps-m-from { opacity: 0; transform: rotateX(90deg); transition-delay: .9s; }
.ps-morph.is-go .ps-morph-pos .ps-m-to, .ps-morph.is-go .ps-morph-zh .ps-m-to { opacity: 1; transform: none; transition-delay: 1.05s; }
.ps-eg-tabs { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-top: 16px; }
.ps-eg-tabs button, .ps-scope button {
    border: 1px solid var(--border); background: transparent; color: var(--text-sub); border-radius: 999px;
    padding: 6px 12px; font: inherit; font-size: .8rem; cursor: pointer;
}
.ps-eg-tabs button.is-on, .ps-scope button.is-on { border-color: var(--ps-hi); color: var(--text-main); background: rgba(255, 255, 255, .07); }
.ps-replay { margin-top: 12px; border: 0; background: none; color: var(--text-sub); font: inherit; font-size: .78rem; text-decoration: underline; cursor: pointer; }

.ps-irr-slide { display: flex; flex-direction: column; text-align: left; }
.ps-irr-item { display: flex; justify-content: space-between; gap: 10px; padding: 11px 2px; border-bottom: 1px solid var(--border); animation: psRise .3s ease-out both; }
.ps-irr-item:last-child { border-bottom: 0; }
.ps-irr-item b { color: var(--ps-hi); font-weight: 600; }
.ps-end { display: flex; flex-direction: column; align-items: center; gap: 10px; padding-top: 30px; }
.ps-end-mark {
    width: 58px; height: 58px; border-radius: 50%; display: grid; place-items: center; font-size: 1.6rem;
    color: #66bb6a; border: 2px solid #66bb6a; animation: psPop .45s cubic-bezier(.2, .9, .3, 1.4) both;
}
.ps-end-btn { width: 100%; max-width: 280px; margin: 6px 0 0; }

.ps-quiz-card { padding: 18px 16px; margin-bottom: 12px; border: 1px solid var(--border); border-radius: 18px; background: var(--card-bg); }
.ps-quiz-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.ps-best { font-size: .75rem; color: var(--ps-hi); white-space: nowrap; padding-top: 4px; }
.ps-scope { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0; }
.ps-quiz-go { width: 100%; margin: 0; }
.ps-quiz-card .ps-dir-list { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 14px; }
.ps-quiz-card .ps-dir {
    display: flex; flex-direction: column; align-items: flex-start; gap: 3px; padding: 12px; text-align: left;
    border: 1px solid var(--border); border-radius: 12px; background: transparent; color: var(--text-main); font: inherit; cursor: pointer;
}
.ps-quiz-card .ps-dir-title { font-size: .86rem; font-weight: 600; }
.ps-dir-n { font-size: .72rem; color: var(--text-sub); }

.ps-bar { height: 4px; border-radius: 2px; background: var(--border); overflow: hidden; margin: 0 0 18px; }
.ps-bar-fill { height: 100%; width: 0; background: var(--ps-hi); transition: width .35s ease; }
.ps-play-pos .ps-card { padding: 34px 16px; margin-bottom: 18px; }
.ps-play-pos .ps-word { font-size: clamp(2.1rem, 10vw, 2.8rem); }
.ps-play-pos .ps-word-zh:empty { display: none; }
.ps-mark { color: var(--ps-hi); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 5px; }
.ps-fb-pos { display: inline-block; margin-left: 10px; padding: 2px 10px; border-radius: 999px; border: 1px solid var(--ps-hi); color: var(--ps-hi); font-size: .8rem; font-weight: 600; vertical-align: middle; }
.ps-fb-rule { margin: 14px auto 0; max-width: 360px; padding: 12px 14px; border-radius: 12px; background: rgba(255, 255, 255, .05); font-size: .85rem; color: var(--text-sub); line-height: 1.6; text-align: left; }
.ps-fb-rule b { color: var(--ps-hi); }
.ps-fb-family { margin-top: 14px; }
.ps-fam-title { font-size: .72rem; color: var(--text-sub); letter-spacing: 1px; margin-bottom: 8px; }
.ps-fam-list { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.ps-fam-chip { display: flex; flex-direction: column; align-items: center; gap: 1px; padding: 7px 10px; border: 1px solid var(--border); border-radius: 10px; min-width: 70px; }
.ps-fam-chip b { font-size: .9rem; color: var(--text-main); font-weight: 600; }
.ps-fam-chip i { font-style: normal; font-size: .68rem; color: var(--ps-hi); }
.ps-fam-chip small { font-size: .68rem; color: var(--text-sub); }
.ps-fam-chip.is-me { border-color: var(--ps-hi); }
@media (prefers-reduced-motion: reduce) {
    .ps-hero-suf, .ps-entry, .ps-lesson-card, .ps-slide-in, .ps-slide-back, .ps-intro-marks span, .ps-irr-item, .ps-end-mark { animation: none; }
}
/* 答完：題目收起來，換成解說卡 */
.ps-play.is-answered :is(.ps-task, .ps-card, .ps-arrow, .ps-target, .ps-stem, .ps-options, .ps-hint) { display: none !important; }
.ps-play.is-answered .ps-feedback {
    margin-top: 0; padding: 24px 18px 20px; border: 1px solid var(--border); border-radius: 20px;
    background: var(--card-bg); animation: psRise .32s cubic-bezier(.2, .8, .2, 1) both;
}
.ps-fb-picked { margin-top: 4px; font-size: .8rem; color: var(--text-sub); }
.ps-fb-picked:empty { display: none; }
.ps-play.is-answered .ps-fb-answer { font-size: clamp(2rem, 9vw, 2.5rem); }

/* ==================== 設定頁 ==================== */
#view-settings { padding-bottom: 40px; }
.settings-tabs {
    position: sticky; top: 8px; z-index: 5; display: flex; gap: 4px; overflow-x: auto; scrollbar-width: none;
    margin: 0 0 16px; padding: 5px; border-radius: 999px; border: 1px solid var(--border);
    background: rgba(12, 14, 20, .55); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.settings-tabs::-webkit-scrollbar { display: none; }
.settings-tabs button {
    flex: 0 0 auto; padding: 7px 14px; border-radius: 999px; border: 0;
    background: transparent; color: var(--text-sub); font: inherit; font-size: .82rem; cursor: pointer; white-space: nowrap;
}
.settings-tabs button.is-on { color: var(--text-main); background: rgba(255, 255, 255, .12); font-weight: 600; }
.settings-section { margin-bottom: 22px; scroll-margin-top: 70px; }
.settings-section-title { margin: 0 2px 10px; font-size: .78rem; font-weight: 600; letter-spacing: 2px; color: var(--text-sub); }
.settings-card { padding: 16px; margin-bottom: 10px; border: 1px solid var(--border); border-radius: 16px; background: var(--card-bg); }
.settings-card-title { font-size: .98rem; font-weight: 600; color: var(--text-main); margin-bottom: 4px; }
.settings-card-sub { font-size: .76rem; color: var(--text-sub); line-height: 1.55; margin-bottom: 12px; }
.settings-card .theme-grid { margin-bottom: 4px; }
.settings-card.settings-danger-zone { margin-top: 0; padding-top: 16px; border-top: 1px solid var(--border); }
.settings-logout { width: 100%; margin: 6px 0 0; color: var(--error); }

.cosmetic-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.cos-card {
    position: relative; display: flex; flex-direction: column; gap: 3px; min-height: 128px; padding: 12px; overflow: hidden;
    border: 1px solid var(--border); border-radius: 14px; background: rgba(255, 255, 255, .03); cursor: pointer;
    transition: border-color .15s, transform .1s;
}
.cos-card:active { transform: scale(.98); }
.cos-card.is-using { border-color: #f0c040; box-shadow: inset 0 0 0 1px rgba(240, 192, 64, .35); }
.cos-name { position: relative; font-size: .95rem; font-weight: 600; color: var(--text-main); }
.cos-desc { position: relative; font-size: .72rem; color: var(--text-sub); line-height: 1.45; flex: 1; }
.theme-sound-opts { display: grid; gap: 8px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border-color, rgba(128,128,128,.2)); }
.theme-sound-row { display: flex; justify-content: space-between; color: var(--text-sub); font-size: .9rem; }
.theme-sound-val { color: var(--primary, #8e7cff); font-weight: bold; }
#set-theme-vol { width: 100%; accent-color: var(--primary, #8e7cff); cursor: pointer; }
.theme-sound-check { display: flex; gap: 10px; align-items: flex-start; margin-top: 4px; font-size: .9rem; cursor: pointer; }
.theme-sound-check input { width: 18px; height: 18px; margin-top: 2px; flex: none; accent-color: var(--primary, #8e7cff); }
.theme-sound-check small { display: block; color: var(--text-sub); font-size: .76rem; }
.cos-foot { position: relative; display: flex; justify-content: flex-end; margin-top: 6px; }
.cos-foot .btn { margin: 0; padding: 5px 12px; min-height: 0; font-size: .78rem; width: auto; }
.cos-buy { --btn-tint: 240, 192, 64; color: #f0c040; }
.cos-state { font-size: .74rem; color: var(--text-sub); padding: 5px 0; }
.cos-state.is-on { color: #f0c040; font-weight: 600; }
.cos-fx-canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.cos-wave { display: flex; align-items: flex-end; gap: 3px; height: 16px; margin-bottom: 4px; }
.cos-wave i { width: 3px; height: 30%; border-radius: 2px; background: var(--text-sub); opacity: .6; }
.cos-card.is-playing .cos-wave i { background: #f0c040; opacity: 1; animation: cosWave .5s ease-in-out infinite alternate; }
.cos-card.is-playing .cos-wave i:nth-child(2) { animation-delay: .12s; }
.cos-card.is-playing .cos-wave i:nth-child(3) { animation-delay: .24s; }
.cos-card.is-playing .cos-wave i:nth-child(4) { animation-delay: .36s; }
@keyframes cosWave { from { height: 25%; } to { height: 100%; } }

/* 特效那一層：蓋在整個畫面上，但不擋點擊 */
#silen-fx-layer { position: fixed; inset: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 2147483000; }

/* ==================== 拍照匯入（photo-import.js） ==================== */
.pi { --pi-c: #00bcd4; position: relative; }
.pi-steps { display: flex; align-items: center; gap: 6px; margin: 0 0 14px; font-size: 0.72rem; color: var(--text-sub); }
.pi-steps i { flex: 1; height: 1px; background: var(--border); }
.pi-dot { position: relative; padding-left: 14px; letter-spacing: 1px; transition: color .25s; white-space: nowrap; }
.pi-dot::before { content: ''; position: absolute; left: 0; top: 50%; width: 8px; height: 8px; margin-top: -4px; border-radius: 50%; border: 1.5px solid var(--border); transition: all .25s; }
.pi-dot.on { color: var(--text-main); }
.pi-dot.on::before { background: var(--pi-c); border-color: var(--pi-c); box-shadow: 0 0 0 4px rgba(0,188,212,0.18); }
.pi-dot.done::before { background: rgba(0,188,212,0.45); border-color: transparent; }
.pi-step { display: none; }
.pi-step.pi-show { display: block; animation: piIn .32s cubic-bezier(.2,.8,.25,1) both; }
@keyframes piIn { from { opacity: 0; transform: translateX(18px); } }

.pi-drop { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 26px 12px; border-radius: 14px;
    border: 1.5px dashed rgba(0,188,212,0.5); background: rgba(0,188,212,0.06); color: var(--text-main); font: inherit; cursor: pointer;
    transition: transform .15s, background .2s, padding .25s; }
.pi-drop:active { transform: scale(0.98); }
.pi-drop.pi-over { background: rgba(0,188,212,0.16); }
.pi-drop b { font-size: 0.98rem; letter-spacing: 1px; }
.pi-drop span { font-size: 0.75rem; color: var(--text-sub); }
.pi-drop.pi-drop-small { padding: 12px; flex-direction: row; justify-content: center; }
.pi-drop.pi-drop-small span:last-child { display: none; }
.pi-drop-icon { position: relative; width: 38px; height: 28px; border: 2px solid var(--pi-c); border-radius: 7px; }
.pi-drop-icon::before { content: ''; position: absolute; left: 50%; top: 50%; width: 11px; height: 11px; margin: -6.5px; border: 2px solid var(--pi-c); border-radius: 50%; }
.pi-drop-icon i { position: absolute; left: 7px; top: -6px; width: 10px; height: 4px; border-radius: 2px 2px 0 0; background: var(--pi-c); }
.pi-drop-small .pi-drop-icon { transform: scale(0.75); }
.pi-thumbs { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.pi-thumb { position: relative; width: 82px; height: 82px; border-radius: 10px; overflow: hidden; border: 1px solid var(--border);
    animation: piPop .35s cubic-bezier(.2,.8,.25,1) both; animation-delay: calc(var(--i) * 0.06s); }
@keyframes piPop { from { opacity: 0; transform: scale(0.8); } }
.pi-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pi-thumb-x { position: absolute; right: 4px; top: 4px; width: 22px; height: 22px; border-radius: 50%; border: 0; background: rgba(0,0,0,0.6); color: #fff; font-size: 0.85rem; line-height: 22px; padding: 0; cursor: pointer; }
.pi-thumb-n { position: absolute; left: 5px; bottom: 4px; font-size: 0.7rem; color: #fff; background: rgba(0,0,0,0.55); border-radius: 6px; padding: 1px 6px; }
.pi-tips { margin: 12px 0 0; padding-left: 18px; font-size: 0.75rem; color: var(--text-sub); line-height: 1.7; }
.pi-next { width: 100%; margin-top: 12px; }
.pi-row { display: flex; gap: 8px; margin-top: 12px; }
.pi-row .btn { flex: 1; margin: 0; }

.pi-crop-head { display: flex; justify-content: space-between; gap: 8px; font-size: 0.75rem; color: var(--text-sub); margin-bottom: 8px; }
.pi-crop-head span:first-child { color: var(--text-main); white-space: nowrap; }
.pi-stage { position: relative; width: 100%; min-height: 160px; border-radius: 10px; overflow: hidden; background: rgba(0,0,0,0.35); touch-action: none; }
.pi-stage canvas { position: absolute; top: 0; }
.pi-box { position: absolute; border: 2px solid var(--pi-c); border-radius: 4px; box-shadow: 0 0 0 2000px rgba(0,0,0,0.5); cursor: move; touch-action: none;
    transition: box-shadow .2s; }
.pi-box.pi-dragging { box-shadow: 0 0 0 2000px rgba(0,0,0,0.62); }
.pi-box::after { content: ''; position: absolute; inset: 0; background:
    linear-gradient(to right, transparent 33%, rgba(0,188,212,0.35) 33%, rgba(0,188,212,0.35) calc(33% + 1px), transparent calc(33% + 1px), transparent 66%, rgba(0,188,212,0.35) 66%, rgba(0,188,212,0.35) calc(66% + 1px), transparent calc(66% + 1px)),
    linear-gradient(to bottom, transparent 33%, rgba(0,188,212,0.35) 33%, rgba(0,188,212,0.35) calc(33% + 1px), transparent calc(33% + 1px), transparent 66%, rgba(0,188,212,0.35) 66%, rgba(0,188,212,0.35) calc(66% + 1px), transparent calc(66% + 1px));
    opacity: 0; transition: opacity .2s; pointer-events: none; }
.pi-box.pi-dragging::after { opacity: 1; }
.pi-h { position: absolute; width: 26px; height: 26px; }
.pi-h::before { content: ''; position: absolute; width: 14px; height: 14px; border: 3px solid #fff; }
.pi-h[data-h="nw"] { left: -13px; top: -13px; cursor: nwse-resize; } .pi-h[data-h="nw"]::before { left: 10px; top: 10px; border-right: 0; border-bottom: 0; }
.pi-h[data-h="ne"] { right: -13px; top: -13px; cursor: nesw-resize; } .pi-h[data-h="ne"]::before { right: 10px; top: 10px; border-left: 0; border-bottom: 0; }
.pi-h[data-h="sw"] { left: -13px; bottom: -13px; cursor: nesw-resize; } .pi-h[data-h="sw"]::before { left: 10px; bottom: 10px; border-right: 0; border-top: 0; }
.pi-h[data-h="se"] { right: -13px; bottom: -13px; cursor: nwse-resize; } .pi-h[data-h="se"]::before { right: 10px; bottom: 10px; border-left: 0; border-top: 0; }
.pi-tools { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.pi-tools .btn { margin: 0; flex: 1; min-width: 64px; }

.pi-scanview { position: relative; display: flex; justify-content: center; border-radius: 10px; overflow: hidden; background: rgba(0,0,0,0.3); min-height: 120px; }
.pi-scanview canvas { display: block; max-width: 100%; filter: grayscale(1) contrast(1.1); opacity: 0.85; }
.pi-scanview.pi-scan-in canvas { animation: piFade .4s ease both; }
@keyframes piFade { from { opacity: 0; transform: scale(0.97); } }
.pi-scanline { position: absolute; left: 0; right: 0; height: 26%; top: -26%;
    background: linear-gradient(to bottom, rgba(0,188,212,0), rgba(0,188,212,0.28) 85%, rgba(0,229,255,0.9) 100%);
    animation: piSweep 1.6s cubic-bezier(.45,0,.55,1) infinite; pointer-events: none; }
@keyframes piSweep { to { top: 100%; } }
.pi-scangrid { position: absolute; inset: 0; pointer-events: none; opacity: 0.25;
    background-image: linear-gradient(rgba(0,188,212,0.5) 1px, transparent 1px), linear-gradient(90deg, rgba(0,188,212,0.5) 1px, transparent 1px);
    background-size: 22px 22px; animation: piGrid 3s linear infinite; }
@keyframes piGrid { to { background-position: 0 22px, 22px 0; } }
.pi-scan-status { margin-top: 12px; text-align: center; font-size: 0.9rem; font-weight: 600; letter-spacing: 0.5px; }
.pi-scan-sub { margin-top: 6px; text-align: center; font-size: 0.75rem; color: var(--text-sub); }
.pi-bar { margin-top: 10px; height: 6px; border-radius: 3px; background: var(--border); overflow: hidden; }
.pi-bar i { display: block; height: 100%; background: linear-gradient(90deg, #00bcd4, #7c9cff); transform: scaleX(0); transform-origin: left; transition: transform .3s ease; }

.pi-summary { display: flex; flex-direction: column; gap: 2px; margin-bottom: 10px; }
.pi-summary b { font-size: 1rem; letter-spacing: 1px; }
.pi-summary span { font-size: 0.75rem; color: var(--text-sub); line-height: 1.5; }
.pi-list { display: flex; flex-direction: column; gap: 6px; }
.pi-item { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 10px; border: 1px solid var(--border); background: var(--card-bg);
    transition: border-color .2s, background .2s, opacity .2s; animation: piRow .35s cubic-bezier(.2,.8,.25,1) both; animation-delay: calc(var(--i, 0) * 0.035s); opacity: 0.6; }
.pi-item.on { opacity: 1; border-color: rgba(0,188,212,0.45); background: rgba(0,188,212,0.06); }
@keyframes piRow { from { opacity: 0; transform: translateY(8px); } }
.pi-item.pi-new { animation: piNew .9s ease; }
@keyframes piNew { 0% { box-shadow: 0 0 0 0 rgba(0,188,212,0.6); } 100% { box-shadow: 0 0 0 10px rgba(0,188,212,0); } }
.pi-check { flex: none; width: 22px; height: 22px; border-radius: 6px; border: 2px solid var(--border); background: transparent; position: relative; cursor: pointer; padding: 0; transition: all .2s; }
.pi-item.on .pi-check { background: var(--pi-c); border-color: var(--pi-c); }
.pi-item.on .pi-check::after { content: ''; position: absolute; left: 6px; top: 2px; width: 6px; height: 11px; border: solid #fff; border-width: 0 2.5px 2.5px 0; transform: rotate(45deg); animation: piTick .2s ease both; }
@keyframes piTick { from { transform: rotate(45deg) scale(0.3); opacity: 0; } }
.pi-item-body { flex: 1; min-width: 0; }
.pi-en { font-weight: 700; font-size: 0.95rem; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.pi-pos { font-size: 0.7rem; font-weight: 600; color: #ff9800; }
.pi-tag { font-size: 0.65rem; font-weight: 500; color: var(--text-sub); border: 1px solid var(--border); border-radius: 5px; padding: 0 5px; }
.pi-tag-fix { color: #f0c040; border-color: rgba(240,192,64,0.45); }
.pi-zh { font-size: 0.8rem; color: var(--text-sub); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; }
.pi-zh.pi-flip { animation: piFlip .35s ease; }
@keyframes piFlip { 0% { opacity: 0; transform: translateY(-6px); } 100% { opacity: 1; transform: none; } }
.pi-item-tools { display: flex; flex-direction: column; gap: 4px; flex: none; }
.pi-mini { font: inherit; font-size: 0.7rem; padding: 3px 8px; border-radius: 7px; border: 1px solid var(--border); background: transparent; color: var(--text-main); cursor: pointer; white-space: nowrap; }
.pi-mini:active { transform: scale(0.96); }
.pi-more { margin-top: 12px; border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; }
.pi-more summary { cursor: pointer; font-size: 0.85rem; font-weight: 600; }
.pi-more-sub { font-size: 0.72rem; color: var(--text-sub); margin: 6px 0 8px; }
.pi-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pi-chip { font: inherit; font-size: 0.78rem; padding: 4px 10px; border-radius: 999px; border: 1px dashed var(--border); background: transparent; color: var(--text-main); cursor: pointer; }
.pi-add { display: flex; gap: 8px; margin-top: 12px; }
.pi-add input { flex: 1; margin: 0; min-width: 0; }
.pi-add .btn { margin: 0; flex: none; }
@media (prefers-reduced-motion: reduce) {
    .pi-step.pi-show, .pi-thumb, .pi-item, .pi-scanline, .pi-scangrid { animation: none; }
}

/* ── 商城：外觀飾品分兩類（頭像框、入場動畫） ───────────────────── */
.acc-cats { display: flex; gap: 8px; margin: 4px 0 2px; }
.acc-cat { flex: 1 1 0; min-width: 0; padding: 9px 0; border-radius: 12px; border: 1px solid var(--border); background: transparent; color: var(--text-sub); font: inherit; font-weight: 700; letter-spacing: 1px; cursor: pointer; transition: background .15s, color .15s, border-color .15s; }
.acc-cat.on { border-color: #f1c40f; color: #f1c40f; background: rgba(241,196,15,0.1); }
.acc-cat:focus-visible { outline: 2px solid #f1c40f; outline-offset: 2px; }
.acc-grid.acc-grid-ent { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.acc-ent-lead { grid-column: 1 / -1; font-size: 0.8rem; color: var(--text-sub); line-height: 1.6; }
.acc-card.acc-ent { padding: 12px; gap: 8px; justify-content: flex-start; }
.acc-card.acc-ent.on { border-color: var(--ent-c); box-shadow: 0 0 0 1px var(--ent-c) inset; }
.acc-ent-art { display: block; width: 100%; aspect-ratio: 1; max-width: 100%; padding: 0; border: 0; border-radius: 12px; overflow: hidden; background: #07080b; cursor: pointer; }
.acc-ent-art canvas { display: block; width: 100%; height: 100%; }
.acc-card.acc-ent .acc-title { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px; margin: 2px 0 0; }
.acc-ent-tag { font-size: 0.66rem; font-weight: 700; padding: 1px 7px; border-radius: 999px; border: 1px solid currentColor; letter-spacing: 1px; }
.acc-ent-tag.rare { color: #5fb6ff; } .acc-ent-tag.epic { color: #b78cff; } .acc-ent-tag.legend { color: #ffc94a; }
.acc-card .acc-ent-desc { height: auto; min-height: 0; margin-bottom: 4px; line-height: 1.5; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.acc-ent-actions { display: flex; gap: 6px; margin-top: auto; }
.acc-ent-actions .btn { flex: 1 1 0; min-width: 0; margin: 0; padding-left: 4px; padding-right: 4px; white-space: nowrap; }
.acc-ent-equip { border-color: var(--ent-c) !important; color: var(--ent-c) !important; }

/* 商城的入場動畫：整個畫面一張畫布，點一下就關 */
.ent-shop-stage { position: fixed; inset: 0; z-index: 9000; background: #000; cursor: pointer; animation: entIn 240ms ease-out both; }
.ent-shop-stage.ent-out { animation: entOut 300ms ease-in both; }
.ent-shop-stage canvas { display: block; width: 100%; height: 100%; }
.ent-chip-canvas { display: block; width: 46px; height: 46px; border-radius: 10px; }

/* 離線中：標題下面「幾人正在學習」那一行換成「離線中」，圓點變橘色 */
#sv-offline-bar { display: none; color: #ffb74d; font-weight: 600; letter-spacing: .5px; }
#sv-offline-bar.show { display: inline; }
.sv-offline #online-presence-badge .hdr-presence-text:not(#sv-offline-bar) { display: none; }
.sv-offline #online-presence-badge .breathing-dot { background-color: #ffb74d; box-shadow: none; animation: none; }
/* 沒有標題列的畫面：浮在最上面 */
#sv-offline-bar.floating {
    position: fixed; left: 50%; top: calc(env(safe-area-inset-top, 0px) + 6px); transform: translateX(-50%);
    z-index: 9500; padding: 5px 12px; border-radius: 999px; font-size: .78rem;
    background: rgba(28, 26, 34, .94); border: 1px solid rgba(255, 183, 77, .55); pointer-events: none;
}
/* 離線時要網路的入口看起來淡一點 */
.sv-offline [data-needs-network] { opacity: .45; }
/* 「離線中」那一行短暫換成提示（例如這個字的發音還沒下載） */
#sv-offline-bar.flash { color: #ffd54f; animation: svOfflineFlash .5s ease-out; }
@keyframes svOfflineFlash { 0% { opacity: .2; } 100% { opacity: 1; } }

/* ── 離線發音（設定頁、單字簿編輯頁，offline-voice.js）── */
.offline-voice-box { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.ov-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ov-num b { font-size: 1.6rem; font-weight: 800; color: var(--text-main); }
.ov-num span { color: var(--text-sub); font-size: .85rem; }
.ov-bar { height: 6px; border-radius: 6px; background: rgba(255,255,255,.08); overflow: hidden; }
.ov-bar i { display: block; height: 100%; border-radius: 6px; background: linear-gradient(90deg, #f7c948, #ffb74d); transition: width .5s cubic-bezier(.2,.9,.25,1); }
.ov-status { font-size: .8rem; color: var(--text-sub); }
.ov-status.ok { color: #81c784; }
.ov-books { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.ov-book { display: flex; align-items: center; gap: 10px; padding: 10px 12px; transition: background .2s; }
.ov-book + .ov-book { border-top: 1px solid var(--border); }
.ov-book:not(.on) { opacity: .7; }
.ov-bt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ov-bt b { font-size: .92rem; color: var(--text-main); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-bt small { font-size: .75rem; color: var(--text-sub); margin-top: 2px; }
.ov-tg { flex: none; width: 40px; height: 23px; border-radius: 999px; border: 0; padding: 0; cursor: pointer; background: #3a3a3a; position: relative; transition: background .2s; }
.ov-tg::after { content: ''; position: absolute; left: 3px; top: 3px; width: 17px; height: 17px; border-radius: 50%; background: #fff; transition: transform .22s cubic-bezier(.2,1.4,.4,1); }
.ov-tg.on { background: #22c55e; }
.ov-tg.on::after { transform: translateX(17px); }
.ov-book-card { display: flex; align-items: center; gap: 12px; }
.ov-book-card[hidden] { display: none; }

/* ── 每週學習週報（Pro／Ultra，weekly-report.js）── */
.wr-overlay {
    position: fixed; inset: 0; z-index: 9100;
    display: flex; align-items: flex-end; justify-content: center;
    background: rgba(0, 0, 0, 0.8);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.wr-sheet {
    width: 100%; max-width: 460px; max-height: 88vh; overflow-y: auto;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: 20px 20px 0 0; padding: 18px 18px 24px;
    animation: addBookIn 0.3s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@media (min-width: 700px) { .wr-overlay { align-items: center; padding: 24px; } .wr-sheet { border-radius: 20px; } }
.wr-head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 14px; }
.wr-h1 { font-size: 1.15rem; font-weight: 700; }
.wr-h2 { font-size: 0.78rem; color: var(--text-sub); margin-top: 2px; }
.wr-close { background: none; border: none; color: var(--text-sub); font-size: 1.1rem; cursor: pointer; padding: 4px 8px; }
.wr-hero { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px; }
.wr-hero > div, .wr-card { background: rgba(255, 255, 255, 0.04); border: 1px solid var(--border); border-radius: 14px; padding: 12px 14px; }
.wr-big { font-size: 1.9rem; font-weight: 800; line-height: 1.1; }
.wr-label { font-size: 0.8rem; color: var(--text-sub); margin-top: 2px; }
.wr-sub { font-size: 0.74rem; color: var(--text-sub); margin-top: 6px; }
.wr-card { margin-bottom: 10px; }
.wr-title { font-size: 0.85rem; font-weight: 600; margin-bottom: 10px; }
.wr-note { font-size: 0.7rem; color: var(--text-sub); margin-top: 6px; }
.wr-bars { display: flex; align-items: flex-end; gap: 8px; height: 110px; }
.wr-bar { flex: 1; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 4px; }
.wr-bar-fill { width: 100%; max-width: 26px; border-radius: 6px 6px 2px 2px; background: linear-gradient(180deg, #f0c040, #c98a1c); }
.wr-bar-n { font-size: 0.7rem; color: var(--text-sub); min-height: 1em; }
.wr-bar-d { font-size: 0.72rem; color: var(--text-sub); }
.wr-due { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; text-align: center; }
.wr-due b { display: block; font-size: 1.4rem; }
.wr-due span { font-size: 0.72rem; color: var(--text-sub); }
.wr-stage { display: flex; height: 12px; border-radius: 6px; overflow: hidden; gap: 2px; }
.wr-st0 { background: #6b7280; } .wr-st1 { background: #c98a1c; } .wr-st2 { background: #6aa6ff; } .wr-st3 { background: #4ccf8a; }
.wr-legend { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 8px; font-size: 0.72rem; color: var(--text-sub); }
.wr-legend i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 4px; vertical-align: middle; }
.wr-top { list-style: none; margin: 0; padding: 0; }
.wr-top li { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 0.88rem; }
.wr-top li:last-child { border-bottom: none; }
.wr-top b { font-weight: 500; color: #ff8a80; font-size: 0.78rem; }
.wr-muted { color: var(--text-sub); }
.wr-lock { text-align: center; padding: 18px 6px 6px; }
.wr-lock-icon { font-size: 2rem; color: #f0c040; }
.wr-lock-title { font-weight: 700; margin: 8px 0 6px; }
.wr-lock-text { font-size: 0.86rem; color: var(--text-sub); line-height: 1.6; margin-bottom: 16px; }

/* ── 匯出與列印（book-export.js）── */
.bx-overlay { position: fixed; inset: 0; z-index: 9100; display: flex; align-items: flex-end; justify-content: center; background: rgba(0, 0, 0, 0.8); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.bx-sheet { width: 100%; max-width: 980px; height: 92vh; display: flex; flex-direction: column; background: var(--card-bg); border: 1px solid var(--border); border-radius: 20px 20px 0 0; animation: addBookIn 0.3s cubic-bezier(0.22, 1, 0.36, 1) both; }
@media (min-width: 700px) { .bx-overlay { align-items: center; padding: 20px; } .bx-sheet { border-radius: 20px; } }
.bx-head { display: flex; justify-content: space-between; align-items: center; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.bx-h1 { font-size: 1.1rem; font-weight: 700; }
.bx-close { background: none; border: none; color: var(--text-sub); font-size: 1.1rem; cursor: pointer; }
.bx-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; }
@media (min-width: 820px) { .bx-body { flex-direction: row; overflow: hidden; } .bx-form { width: 380px; overflow-y: auto; border-right: 1px solid var(--border); } .bx-preview { flex: 1; } }
.bx-form { padding: 12px 16px; }
.bx-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0; }
.bx-row > span { width: 64px; font-size: 0.82rem; color: var(--text-sub); }
.bx-row input[type=text] { flex: 1; min-width: 140px; margin: 0; }
.bx-seg { display: flex; flex-wrap: wrap; gap: 6px; }
.bx-seg button { background: rgba(255, 255, 255, 0.05); border: 1px solid var(--border); color: inherit; border-radius: 999px; padding: 5px 12px; font-size: 0.82rem; cursor: pointer; }
.bx-seg button.on { background: #f0c040; color: #000; border-color: #f0c040; font-weight: 600; }
.bx-seg button.lock, .bx-counts label.lock, .bx-checks label.lock { opacity: 0.55; }
.bx-books { display: flex; flex-direction: column; gap: 4px; max-height: 150px; overflow-y: auto; padding: 6px 10px; margin-left: 72px; border: 1px solid var(--border); border-radius: 10px; font-size: 0.85rem; }
.bx-counts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-left: 72px; }
.bx-counts label { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-size: 0.82rem; }
.bx-counts input { width: 64px; margin: 0; padding: 4px 6px; }
.bx-checks { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 0.84rem; align-items: center; }
.bx-link { background: none; border: none; color: #f0c040; cursor: pointer; font-size: 0.84rem; padding: 0; }
.bx-lockn { font-size: 0.74rem; color: var(--text-sub); font-style: normal; }
.bx-tip { font-size: 0.76rem; color: var(--text-sub); line-height: 1.6; margin-top: 12px; }
.bx-preview { display: flex; flex-direction: column; min-height: 420px; padding: 10px 12px; }
.bx-pv-label { font-size: 0.8rem; color: var(--text-sub); margin-bottom: 6px; }
.bx-preview iframe { flex: 1; width: 100%; min-height: 380px; border: 1px solid var(--border); border-radius: 10px; background: #9aa0a6; }
.bx-foot { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; padding: 12px 16px; border-top: 1px solid var(--border); }
.bx-foot .btn { margin: 0; }

/* ── 系統管理：使用數據 ── */
.as-seg { display: flex; gap: 6px; flex-wrap: wrap; margin: 8px 0; }
.as-seg .btn.on { border-color: #00bcd4; color: #00bcd4; background: rgba(0, 188, 212, 0.1); }
.as-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; margin: 10px 0 14px; }
.as-tile { padding: 12px; border-radius: 12px; border: 1px solid var(--border); background: var(--card-bg); }
.as-tile-v { font-size: 1.6rem; font-weight: 800; color: var(--text-main); font-family: 'Courier New', Courier, monospace; }
.as-tile-l { font-size: 0.82rem; color: var(--text-main); margin-top: 2px; }
.as-tile-s { font-size: 0.72rem; color: var(--text-sub); margin-top: 3px; }
.as-block { margin: 14px 0; padding: 12px; border-radius: 12px; border: 1px solid var(--border); background: var(--card-bg); }
.as-h { font-weight: 700; color: var(--text-main); margin-bottom: 8px; font-size: 0.95rem; }
.as-chart { width: 100%; height: auto; display: block; }
.as-grid { stroke: var(--border); stroke-width: 1; }
.as-ax { fill: var(--text-sub); font-size: 11px; }
.as-ax-s { fill: #ffb74d; }
.as-bar { fill: rgba(255, 183, 77, 0.55); }
.as-line { fill: none; stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.as-line-d { stroke: #00bcd4; }
.as-line-p { stroke: #9c6bff; }
.as-legend { display: flex; flex-wrap: wrap; gap: 12px; font-size: 0.75rem; color: var(--text-sub); margin-bottom: 6px; }
.as-k::before { content: ''; display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.as-k-d::before { background: #00bcd4; } .as-k-p::before { background: #9c6bff; } .as-k-s::before { background: rgba(255, 183, 77, 0.7); }
.as-step { display: grid; grid-template-columns: auto minmax(80px, 1.2fr) 2fr auto; align-items: center; gap: 8px; padding: 5px 0; font-size: 0.85rem; }
.as-step-n { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; font-size: 0.72rem; font-weight: 700; background: rgba(0, 188, 212, 0.15); color: #00bcd4; }
.as-step-name { color: var(--text-main); overflow-wrap: anywhere; }
.as-step-v { color: var(--text-sub); font-size: 0.78rem; white-space: nowrap; font-family: 'Courier New', Courier, monospace; }
.as-meter { display: block; height: 8px; border-radius: 999px; background: rgba(255, 255, 255, 0.07); overflow: hidden; min-width: 40px; }
.as-meter i { display: block; height: 100%; border-radius: 999px; background: #00bcd4; }
.as-meter-step i { background: linear-gradient(90deg, #00bcd4, #9c6bff); }
.as-meter-low i { background: #ef5350; }
.as-table { display: flex; flex-direction: column; font-size: 0.82rem; }
.as-tr { display: grid; grid-template-columns: 1.4fr 0.6fr 0.6fr 1.4fr 0.8fr; gap: 8px; align-items: center; padding: 7px 0; border-bottom: 1px solid var(--border); color: var(--text-main); }
.as-ret .as-tr { grid-template-columns: 1fr 0.7fr 0.8fr 0.9fr 0.9fr; }
.as-th { color: var(--text-sub); font-size: 0.74rem; border-bottom-color: var(--border); }
.as-mode { font-weight: 600; overflow-wrap: anywhere; }
.as-comp { display: flex; align-items: center; gap: 6px; }
.as-comp .as-meter { flex: 1; }
.as-comp small { color: var(--text-sub); min-width: 32px; text-align: right; }
.as-na { color: var(--text-sub); font-size: 0.74rem; }

/* ==================== 我的風格（mystyle.js） ==================== */
#view-mystyle { --ms-common: #9aa4b2; --ms-rare: #5fb6ff; --ms-epic: #b78cff; --ms-legend: #ffc94a; --ms-limited: #ff9a3c; --ms-season: #6fd6c4; --ms-special: #3de8ff; padding-bottom: 40px; }
.me-style-card {
    width: 100%; display: flex; align-items: center; gap: 14px; padding: 14px 16px; margin-bottom: 14px;
    border: 1px solid color-mix(in srgb, #f0c040 45%, var(--border)); border-radius: 16px; cursor: pointer; text-align: left;
    background: linear-gradient(120deg, color-mix(in srgb, #f0c040 12%, var(--card-bg)), var(--card-bg) 60%);
    color: var(--text-main); font-family: inherit;
}
.me-style-card:active { transform: scale(0.99); }
.me-style-avatar { flex: 0 0 52px; width: 52px; height: 52px; display: grid; place-items: center; }
.me-style-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.me-style-title { font-weight: 700; font-size: 1.02rem; letter-spacing: 1px; }
.me-style-sub { font-size: 0.78rem; color: var(--text-sub); }
.me-style-progress { font-size: 0.72rem; color: #f0c040; letter-spacing: 0.5px; }
.me-style-progress:empty { display: none; }

.ms-ava { position: relative; flex-shrink: 0; }
.ms-ava-img, .ms-ava-ph { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; border: 2px solid var(--border); box-sizing: border-box; }
.ms-ava-ph { display: grid; place-items: center; background: rgba(255,255,255,0.08); color: var(--text-sub); font-weight: 700; font-size: 1.2em; }

.ms-hero {
    position: relative; display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
    padding: 22px 18px; margin: 4px 0 16px; border: 1px solid var(--border); border-radius: 18px;
    background: radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, #f0c040 10%, transparent), transparent 60%), var(--card-bg);
}
.ms-hero-avatar { flex: 0 0 auto; padding: 8px; }
.ms-hero-info { flex: 1; min-width: 150px; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.ms-hero-nameline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ms-name { font-size: 1.3rem; font-weight: 700; letter-spacing: 0.5px; overflow-wrap: anywhere; }
.ms-hero-badges { display: flex; gap: 6px; }
.ms-badge { width: 30px; height: 30px; border-radius: 50%; object-fit: cover; border: 1px solid var(--border); }
.ms-replay { margin: 0; }
.ms-replay:disabled { opacity: 0.55; cursor: default; }
.ms-tryon {
    flex-basis: 100%; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 10px 12px; border-radius: 12px; border: 1px dashed #f0c040;
    background: color-mix(in srgb, #f0c040 8%, transparent); font-size: 0.85rem;
}
.ms-tryon span { flex: 1; min-width: 120px; color: #f0c040; }
.ms-tryon .btn { margin: 0; }

.ms-sec-title { margin: 0 0 10px; font-size: 1rem; letter-spacing: 1px; }
.ms-presets { margin-bottom: 18px; }
.ms-preset-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.ms-preset {
    display: flex; flex-direction: column; gap: 4px; min-width: 0; padding: 12px 10px; min-height: 66px;
    border: 1px solid var(--border); border-radius: 13px; background: var(--card-bg); color: var(--text-main);
    font-family: inherit; text-align: left; cursor: pointer;
}
.ms-preset.is-empty { border-style: dashed; color: var(--text-sub); background: transparent; }
.ms-preset:active { transform: scale(0.98); }
.ms-preset-name { font-weight: 600; font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-preset-sub { font-size: 0.7rem; color: var(--text-sub); line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ms-note { margin: 8px 0 0; font-size: 0.75rem; color: var(--text-sub); transition: color 0.2s; }
.ms-note.is-flash { color: #f0c040; }

.ms-tabs { position: sticky; top: 0; z-index: 5; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; padding: 6px; margin: 0 0 10px; border-radius: 14px; background: var(--bg-color, #0a0a0a); box-shadow: 0 6px 14px -8px #000; border: 1px solid var(--border); }
.ms-tabs button { min-height: 40px; border: 0; border-radius: 10px; background: transparent; color: var(--text-sub); font-family: inherit; font-size: 0.9rem; font-weight: 600; cursor: pointer; }
.ms-tabs button.on { background: var(--card-bg); color: var(--text-main); box-shadow: inset 0 0 0 1px var(--border); }
.ms-filters { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; margin-bottom: 8px; scrollbar-width: none; }
.ms-filters::-webkit-scrollbar { display: none; }
.ms-filters button { flex: 0 0 auto; min-height: 34px; padding: 0 14px; border: 1px solid var(--border); border-radius: 999px; background: transparent; color: var(--text-sub); font-family: inherit; font-size: 0.8rem; cursor: pointer; }
.ms-filters button.on { border-color: #f0c040; color: #f0c040; background: color-mix(in srgb, #f0c040 10%, transparent); }

.ms-block { padding: 16px 0 6px; border-top: 1px solid var(--border); }
.ms-pane > .ms-block:first-child { border-top: 0; }
.ms-cat-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.ms-cat-title { margin: 0; font-size: 1.02rem; letter-spacing: 1px; }
.ms-progress { font-size: 0.75rem; color: var(--text-sub); font-variant-numeric: tabular-nums; }
.ms-progress-bar { height: 4px; border-radius: 4px; background: rgba(255,255,255,0.08); overflow: hidden; margin-bottom: 8px; }
.ms-progress-bar span { display: block; height: 100%; border-radius: 4px; background: linear-gradient(90deg, #f0c040, #ffe08a); transition: width 0.4s; }
.ms-cat-sub { margin: 0 0 10px; font-size: 0.78rem; color: var(--text-sub); line-height: 1.5; }
.ms-pro-tag { font-size: 0.62rem; font-weight: 700; letter-spacing: 1px; padding: 1px 7px; border-radius: 6px; background: linear-gradient(135deg, #ffe08a, #f0c040); color: #2a2000; }
.ms-block > .btn { margin: 4px 0 10px; }
.ms-link { margin: 4px 0 10px; padding: 0; border: 0; background: none; color: var(--text-sub); font-family: inherit; font-size: 0.8rem; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }

.ms-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 10px; margin-bottom: 10px; }
.ms-grid-theme { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
.ms-empty { grid-column: 1 / -1; padding: 18px 0; text-align: center; color: var(--text-sub); font-size: 0.82rem; }
.ms-card {
    --r: var(--ms-common);
    position: relative; display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 8px 8px 9px;
    border: 1px solid color-mix(in srgb, var(--r) 40%, var(--border)); border-radius: 14px;
    background: linear-gradient(180deg, color-mix(in srgb, var(--r) 12%, var(--card-bg)), var(--card-bg) 70%);
    color: var(--text-main); font-family: inherit; text-align: left; cursor: pointer; overflow: hidden;
    transition: transform 0.12s, border-color 0.2s;
}
.ms-card:active { transform: scale(0.97); }
.ms-card.r-rare, .ms-sheet-body.r-rare { --r: var(--ms-rare); }
.ms-card.r-epic, .ms-sheet-body.r-epic { --r: var(--ms-epic); }
.ms-card.r-legend, .ms-sheet-body.r-legend { --r: var(--ms-legend); }
.ms-card.r-limited, .ms-sheet-body.r-limited { --r: var(--ms-limited); }
.ms-card.r-season, .ms-sheet-body.r-season { --r: var(--ms-season); }
.ms-card.r-special, .ms-sheet-body.r-special { --r: var(--ms-special); }
.ms-card.r-common, .ms-sheet-body.r-common { --r: var(--ms-common); }
.ms-card.s-on { border-color: #f0c040; box-shadow: 0 0 0 1px #f0c040 inset, 0 0 16px -6px #f0c040; }
.ms-card:not(.s-on):not(.s-owned) .ms-art > * { opacity: 0.5; filter: saturate(0.6); }
.ms-card.s-gone { opacity: 0.6; }
.ms-art { position: relative; display: grid; place-items: center; width: 100%; aspect-ratio: 1; border-radius: 10px; background: rgba(0,0,0,0.22); overflow: hidden; }
.ms-grid-theme .ms-art { aspect-ratio: 4 / 3; }
.ms-art canvas { width: 100%; height: 100%; display: block; }
.ms-swatch { width: 100%; height: 100%; }
.ms-wave { height: 30px; margin: 0; }
.ms-wave i { width: 5px; }
.ms-none { color: var(--text-sub); font-size: 0.9rem; }
.ms-card-name { font-size: 0.82rem; font-weight: 600; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-card-foot { display: flex; justify-content: space-between; align-items: center; gap: 4px; font-size: 0.66rem; }
.ms-rar { color: var(--r, var(--ms-common)); font-weight: 700; letter-spacing: 1px; }
.ms-state { color: var(--text-sub); white-space: nowrap; }
.ms-card.s-on .ms-state { color: #f0c040; font-weight: 700; }
.ms-card.s-buy .ms-state { color: var(--text-main); font-variant-numeric: tabular-nums; }
.ms-card.s-pro .ms-state, .ms-card.s-ultra .ms-state, .ms-card.s-mail .ms-state { color: #c9a8ff; }
.ms-lock { position: absolute; top: 12px; right: 12px; min-width: 22px; height: 22px; padding: 0 6px; box-sizing: border-box; display: grid; place-items: center; border-radius: 999px; background: rgba(0,0,0,0.6); color: #fff; font-size: 0.56rem; font-weight: 700; letter-spacing: 0.6px; }
.ms-lock:empty { width: 22px; padding: 0; }
.ms-lock:empty::before { content: ''; position: absolute; left: 7px; top: 10px; width: 8px; height: 6px; background: #fff; border-radius: 1.5px; }
.ms-lock:empty::after { content: ''; position: absolute; left: 8px; top: 5px; width: 3px; height: 5px; border: 1.5px solid #fff; border-bottom: 0; border-radius: 3px 3px 0 0; }
.ms-card.s-pro .ms-lock, .ms-card.s-ultra .ms-lock, .ms-card.s-mail .ms-lock { background: linear-gradient(135deg, #b388ff, #7c4dff); }
.ms-card.s-pro .ms-lock { background: linear-gradient(135deg, #ffe08a, #f0c040); color: #2a2000; }
.ms-gone { margin: 4px 0 10px; }
.ms-gone summary { cursor: pointer; color: var(--text-sub); font-size: 0.82rem; padding: 6px 0; }
.ms-gone .ms-grid { margin-top: 8px; }

.ms-sheet {
    box-sizing: border-box; width: min(440px, calc(100vw - 24px)); max-height: min(760px, 88vh); padding: 20px 18px 16px;
    border: 1px solid var(--border); border-radius: 20px; background: var(--bg-color, #111); color: var(--text-main);
    box-shadow: 0 20px 60px #0009; overflow-y: auto;
}
.ms-sheet::backdrop { background: #000b; }
.ms-sheet-body { --r: var(--ms-common); display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.ms-art-big { width: min(240px, 70vw); border: 1px solid color-mix(in srgb, var(--r) 45%, var(--border)); box-shadow: 0 0 40px -16px var(--r); }
.ms-sheet-title { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 1.2rem; font-weight: 700; }
.ms-sheet-title .ms-rar { font-size: 0.7rem; padding: 1px 8px; border: 1px solid currentColor; border-radius: 999px; }
.ms-sheet-cat { font-size: 0.78rem; color: var(--text-sub); }
.ms-sheet-desc { margin: 2px 0; font-size: 0.86rem; line-height: 1.55; }
.ms-sheet-how { margin: 0; font-size: 0.8rem; color: #f0c040; line-height: 1.5; }
.ms-sheet-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 8px; width: 100%; }
.ms-sheet-actions .btn { margin: 0; min-width: 96px; }
.ms-sheet-col { flex-direction: column; align-items: stretch; }
.ms-buy { background: linear-gradient(135deg, #ffe08a, #f0c040) !important; color: #2a2000 !important; border-color: transparent !important; }
.ms-primary { background: color-mix(in srgb, #f0c040 18%, var(--card-bg)) !important; color: #f0c040 !important; border: 1px solid #f0c040 !important; }
.ms-danger { color: #ff7a7a !important; border-color: color-mix(in srgb, #ff7a7a 50%, var(--border)) !important; }
.ms-sheet-close { display: block; margin: 14px auto 0; padding: 8px 18px; border: 0; background: none; color: var(--text-sub); font-family: inherit; cursor: pointer; }

/* 名字特效（Ultra）：公開主頁那份定義，預覽卡共用 */
.ms-name.ultra-name {
    background: linear-gradient(100deg, #e9dcff 0%, #b388ff 30%, #ffe6a8 50%, #b388ff 70%, #e9dcff 100%);
    background-size: 220% 100%; -webkit-background-clip: text; background-clip: text; color: transparent;
    filter: drop-shadow(0 0 10px rgba(179, 136, 255, 0.45)); animation: ultra-name-flow 4s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .ms-name.ultra-name { animation: none; } }

.settings-style-link {
    width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 14px 16px; margin-bottom: 12px;
    border: 1px solid color-mix(in srgb, #f0c040 40%, var(--border)); border-radius: 14px; background: var(--card-bg);
    color: var(--text-main); font-family: inherit; text-align: left; cursor: pointer;
}
.settings-style-link span:first-child { display: flex; flex-direction: column; gap: 3px; }
.settings-style-link small { color: var(--text-sub); font-size: 0.76rem; }
.settings-inline-link { margin-left: 6px; padding: 0; border: 0; background: none; color: #f0c040; font-family: inherit; font-size: inherit; cursor: pointer; }
.rk-rewards-style { width: 100%; margin: 14px 0 0; }
@media (max-width: 380px) { .ms-preset-row { grid-template-columns: 1fr; } .ms-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); } }

/* ==================== 快速匯入（quick-import.js） ==================== */
.import-trigger.import-trigger-btn {
    display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; margin: 4px 0 10px; padding: 11px 14px;
    border: 1px dashed color-mix(in srgb, var(--text-main) 35%, var(--border)); border-radius: 12px; background: transparent;
    color: var(--text-main); font-family: inherit; font-size: 0.88rem; text-decoration: none; letter-spacing: 0.5px; cursor: pointer;
}
.import-trigger.import-trigger-btn:active { transform: scale(0.99); }
.qi-lead { margin: 0 0 10px; font-size: 0.8rem; color: var(--text-sub); line-height: 1.6; }
.qi-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 8px 0 12px; }
.qi-tools .btn { margin: 0; }
.qi-limit { font-size: 0.74rem; color: var(--text-sub); }
.qi-result { margin-top: 16px; }
.qi-summary { font-size: 0.86rem; font-weight: 600; margin-bottom: 6px; }
.qi-legend { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; font-size: 0.72rem; color: var(--text-sub); }
.qi-k::before { content: ''; display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.qi-k-ok::before { background: #48c774; } .qi-k-warn::before { background: #f0c040; } .qi-k-bad::before { background: #ff6b6b; }
.qi-ai { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.qi-ai .btn { margin: 0; flex: 1; min-width: 140px; }
.qi-list { display: grid; gap: 8px; max-height: 52vh; overflow-y: auto; padding-right: 2px; }
.qi-row { display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px 9px 12px; border: 1px solid var(--border); border-left: 4px solid #48c774; border-radius: 10px; background: var(--card-bg); }
.qi-row.qi-fixed, .qi-row.qi-warn { border-left-color: #f0c040; background: color-mix(in srgb, #f0c040 6%, var(--card-bg)); }
.qi-row.qi-bad { border-left-color: #ff6b6b; background: color-mix(in srgb, #ff6b6b 7%, var(--card-bg)); }
.qi-main { flex: 1; min-width: 0; }
.qi-en { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.qi-word { font-weight: 700; overflow-wrap: anywhere; }
.qi-pos { font-size: 0.7rem; color: #ff9800; }
.qi-tag { font-size: 0.66rem; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-sub); }
.qi-topic { border-color: color-mix(in srgb, #8e7cff 60%, var(--border)); color: #b9adff; }
.qi-zh { font-size: 0.82rem; color: var(--text-sub); margin-top: 2px; }
.qi-bad .qi-zh { color: #ff8a8a; font-weight: 600; }
.qi-ex { font-size: 0.76rem; color: var(--text-sub); font-style: italic; margin-top: 3px; line-height: 1.45; }
.qi-fix, .qi-sug { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 5px; font-size: 0.75rem; color: #f0c040; }
.qi-link { padding: 0; border: 0; background: none; color: var(--text-main); font-family: inherit; font-size: inherit; text-decoration: underline; cursor: pointer; }
.qi-chip { padding: 3px 10px; border: 1px solid #f0c040; border-radius: 999px; background: color-mix(in srgb, #f0c040 10%, transparent); color: var(--text-main); font-family: inherit; font-size: 0.75rem; cursor: pointer; }
.qi-acts { display: flex; flex-direction: column; gap: 4px; flex-shrink: 0; }
.qi-btn { padding: 4px 9px; border: 1px solid var(--border); border-radius: 8px; background: transparent; color: var(--text-main); font-family: inherit; font-size: 0.74rem; cursor: pointer; }
.qi-del { color: #ff8a8a; }
.qi-split { display: flex; align-items: center; gap: 8px; margin: 12px 0 0; font-size: 0.84rem; }
.qi-confirm { width: 100%; margin-top: 12px; }
.qi-done { box-sizing: border-box; width: min(380px, calc(100vw - 32px)); padding: 22px 20px 18px; border: 1px solid var(--border); border-radius: 18px; background: var(--bg-color, #111); color: var(--text-main); text-align: center; }
.qi-done::backdrop { background: #000a; }
.qi-done-title { font-size: 1.15rem; font-weight: 700; margin-bottom: 6px; }
.qi-done-text { margin: 0 0 4px; font-size: 0.9rem; }
.qi-done-sub { margin: 0; font-size: 0.78rem; color: var(--text-sub); }
.qi-done-actions { display: flex; gap: 10px; justify-content: center; margin-top: 16px; }
.qi-done-actions .btn { margin: 0; flex: 1; }

/* ==================== 傳說頭像框特效（frame-fx.js） ==================== */
.frame-fx { position: absolute; inset: 0; pointer-events: none; z-index: 11; transform: scale(var(--avatar-frame-scale, 1.15)); }
/* 1. 金屬反光：一道斜光掃過，只照在框有畫東西的地方（用框本身的圖當遮罩） */
.ff-shine { position: absolute; inset: 0; overflow: hidden;
  -webkit-mask: var(--ff-img) center / contain no-repeat; mask: var(--ff-img) center / contain no-repeat; }
.ff-shine::before { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%;
  background: linear-gradient(115deg, transparent 42%, rgba(255,250,225,.0) 44%, rgba(255,252,235,.95) 50%, rgba(255,250,225,0) 56%, transparent 58%);
  mix-blend-mode: screen; animation: ff-shine 3.2s cubic-bezier(.45,.05,.55,.95) infinite; }
@keyframes ff-shine { 0% { transform: translateX(-60%); } 55%, 100% { transform: translateX(60%); } }
/* 2. 光沿著主環繞圈 */
.ff-orbit { position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 78%, rgba(255,240,190,.9) 86%, #fff 87%, rgba(200,160,255,.0) 95%, transparent);
  -webkit-mask: radial-gradient(closest-side, transparent 89.5%, #000 91%, #000 94.5%, transparent 96%);
  mask: radial-gradient(closest-side, transparent 89.5%, #000 91%, #000 94.5%, transparent 96%);
  mix-blend-mode: screen; animation: ff-spin 4.5s linear infinite; }
@keyframes ff-spin { to { transform: rotate(360deg); } }
/* 3. 頂端寶石呼吸發光 */
.ff-gem { position: absolute; left: 50%; top: 3.7%; width: 13%; height: 13%; margin: -6.5% 0 0 -6.5%; border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,.95) 0 12%, rgba(190,150,255,.75) 30%, rgba(140,90,255,0) 70%);
  mix-blend-mode: screen; animation: ff-pulse 2.4s ease-in-out infinite; }
@keyframes ff-pulse { 0%, 100% { transform: scale(.55); opacity: .5; } 50% { transform: scale(1.15); opacity: 1; } }
/* 4. 月桂葉上閃爍的星點 */
.ff-spark { position: absolute; width: 7%; height: 7%; margin: -3.5% 0 0 -3.5%; opacity: 0;
  background: radial-gradient(circle, #fff 0 10%, transparent 11%),
    linear-gradient(90deg, transparent 46%, #fff 50%, transparent 54%),
    linear-gradient(0deg, transparent 46%, #fff 50%, transparent 54%);
  -webkit-mask: radial-gradient(circle, #000 0 30%, transparent 70%); mask: radial-gradient(circle, #000 0 30%, transparent 70%);
  filter: drop-shadow(0 0 3px #ffe9a8); animation: ff-twinkle 2.8s ease-in-out infinite; }
@keyframes ff-twinkle { 0%, 70%, 100% { opacity: 0; transform: scale(.2) rotate(0deg); } 80% { opacity: 1; transform: scale(1) rotate(45deg); } 90% { opacity: 0; transform: scale(.4) rotate(90deg); } }

.frame-fx.ff-paused *, .frame-fx.ff-paused *::before { animation-play-state: paused !important; }
/* 降低特效、減少動態效果：不放 */
html[data-fx="low"] .frame-fx { display: none; }
@media (prefers-reduced-motion: reduce) { .frame-fx { display: none; } }

/* ==================== 操作教學（tips.js） ==================== */
.tip-card { box-sizing: border-box; width: min(420px, calc(100vw - 28px)); max-height: 88vh; overflow-y: auto; padding: 18px 18px 16px; border: 1px solid var(--border); border-radius: 18px; background: var(--bg-color, #111); color: var(--text-main); box-shadow: 0 20px 60px #0009; }
.tip-card::backdrop { background: #000b; }
.tip-clip { display: block; width: 100%; aspect-ratio: 9 / 10; object-fit: cover; border-radius: 12px; background: #000; margin-bottom: 14px; border: 1px solid var(--border); }
img.tip-clip { aspect-ratio: auto; height: auto; object-fit: contain; background: #101010; }
.tip-kicker { font-size: 0.75rem; color: #f0c040; letter-spacing: 1px; margin-bottom: 4px; }
.tip-title { font-size: 1.12rem; font-weight: 700; margin-bottom: 10px; }
.tip-points { margin: 0 0 6px; padding-left: 1.3em; display: grid; gap: 8px; font-size: 0.88rem; line-height: 1.55; }
.tip-points li::marker { color: #f0c040; font-weight: 700; }
.tip-text { margin: 10px 0 4px; font-size: 0.9rem; line-height: 1.6; }
.tip-sub { margin: 4px 0 0; font-size: 0.78rem; color: var(--text-sub); line-height: 1.55; }
.tip-steps { display: grid; grid-template-columns: repeat(6, 1fr); gap: 5px; margin: 6px 0 4px; }
.tip-step { display: grid; place-items: center; min-height: 30px; border-radius: 8px; border: 1px solid var(--border); font-size: 0.72rem; color: var(--text-sub); }
.tip-step.done { background: color-mix(in srgb, #48c774 18%, transparent); border-color: color-mix(in srgb, #48c774 50%, var(--border)); color: var(--text-main); }
.tip-step.now { background: color-mix(in srgb, #f0c040 20%, transparent); border-color: #f0c040; color: #f0c040; font-weight: 700; }
.tip-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px; }
.tip-actions .btn { margin: 0; min-width: 96px; }
.tip-help { flex: 0 0 auto; width: 26px; height: 26px; padding: 0; border: 1px solid var(--border); border-radius: 50%; background: transparent; color: var(--text-sub); font: 700 0.8rem/1 inherit; cursor: pointer; }
.tip-help-link { display: block; margin: -18px auto 22px; padding: 4px 8px; border: 0; background: none; color: #f0c040; font-family: inherit; font-size: 0.82rem; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.settings-card .tip-help-link { margin: 6px 0 0; }
.tip-guide { position: fixed; inset: 0; z-index: 9990; pointer-events: none; }
.tip-ring { position: fixed; border-radius: 14px; box-shadow: 0 0 0 3px #f0c040, 0 0 0 9999px rgba(0,0,0,0.55); transition: left 0.25s, top 0.25s, width 0.25s, height 0.25s, opacity 0.2s; animation: tip-pulse 1.6s ease-in-out infinite; }
@keyframes tip-pulse { 0%, 100% { box-shadow: 0 0 0 3px #f0c040, 0 0 0 9999px rgba(0,0,0,0.55); } 50% { box-shadow: 0 0 0 6px rgba(240,192,64,0.55), 0 0 0 9999px rgba(0,0,0,0.55); } }
.tip-bubble { position: fixed; width: 280px; padding: 12px 14px; border-radius: 14px; background: var(--bg-color, #111); border: 1px solid #f0c040; color: var(--text-main); box-shadow: 0 10px 30px #0008; pointer-events: auto; transition: top 0.25s, left 0.25s, opacity 0.2s; }
.tip-bubble-text { font-size: 0.9rem; line-height: 1.55; }
.tip-bubble-acts { display: flex; justify-content: space-between; align-items: center; margin-top: 10px; }
.tip-bubble-acts .btn { margin: 0; }
.tip-link { padding: 0; border: 0; background: none; color: var(--text-sub); font-family: inherit; font-size: 0.8rem; text-decoration: underline; cursor: pointer; }
.hm-reward { width: 100%; display: flex; align-items: center; gap: 10px; padding: 12px 14px; margin-bottom: 12px; border: 1px solid color-mix(in srgb, #f0c040 55%, var(--border)); border-radius: 14px; background: color-mix(in srgb, #f0c040 10%, var(--card-bg)); color: var(--text-main); font-family: inherit; font-size: 0.9rem; text-align: left; cursor: pointer; }
.hm-reward span:nth-child(2) { flex: 1; }
.hm-reward-dot { width: 9px; height: 9px; border-radius: 50%; background: #f0c040; box-shadow: 0 0 10px #f0c040; animation: tip-dot 1.4s ease-in-out infinite; }
@keyframes tip-dot { 50% { opacity: 0.35; } }
.bs-confirm-bar { position: sticky; bottom: 0; z-index: 4; padding: 12px 0 calc(12px + env(safe-area-inset-bottom)); margin-top: 16px; background: linear-gradient(to top, var(--bg-color, #111) 70%, transparent); }
.bs-confirm { width: 100%; margin: 0; }
@media (prefers-reduced-motion: reduce) { .tip-ring, .hm-reward-dot { animation: none; } }

/* 閱讀模式的文章要能選取：選兩個字以上才會跳出「AI 查詞組」。
   以前整個網站都關掉選取（body user-select: none），這個功能其實一直按不出來。 */
#reading-article-body { user-select: text; -webkit-user-select: text; -webkit-touch-callout: default; }

/* ==================== 新背景（app.js SILEN_THEMES、bg-fx.js、bg-scenes.js） ====================
   畫面由 bg-scenes.js 用兩張畫布畫（後面那張靜態、前面那張動態）；這裡只有每一款的配色和縮圖。
   顏色偏暗、對比低，卡片上的字照樣看得清楚。 */
html[data-theme="day"], html[data-theme="garden"], html[data-theme="combo"], html[data-theme="snow"], html[data-theme="fireflies"],
html[data-theme="letters"], html[data-theme="library"], html[data-theme="chalk"], html[data-theme="xmas26"], html[data-theme="fireworks27"], html[data-theme="lantern27"] {
    --bg-color: #0c0b1e; --card-bg: rgba(255, 225, 200, 0.07); --border: rgba(255, 225, 200, 0.15);
    --text-main: #f8efe8; --text-sub: #b9a9b4; --surface-strong: rgba(255, 225, 200, 0.13); --surface-strong-border: rgba(255, 225, 200, 0.22);
    --theme-glow: rgba(255, 170, 100, 0.13);
    --app-bg-grad: linear-gradient(180deg, #0a0c24 0%, #171a3c 45%, #3a2a4a 74%, #4a2c38 86%, #120c18 100%);
}
html[data-theme="day"] {
    --bg-color: #0d1626; --card-bg: rgba(200, 220, 255, 0.075); --border: rgba(200, 220, 255, 0.16);
    --text-main: #eef3fb; --text-sub: #9fb0c8; --surface-strong: rgba(200, 220, 255, 0.14); --surface-strong-border: rgba(200, 220, 255, 0.24);
    --theme-glow: rgba(160, 200, 255, 0.12);
    --app-bg-grad: linear-gradient(180deg, #13223d 0%, #0d1626 60%, #070b14 100%);
}
html[data-theme="day"][data-day="dawn"]      { --app-bg-grad: linear-gradient(180deg, #232850 0%, #463c66 26%, #6a4a60 46%, #221d36 72%, #0c0b16 100%); --theme-glow: rgba(255, 170, 190, 0.14); }
html[data-theme="day"][data-day="morning"]   { --app-bg-grad: linear-gradient(180deg, #22466c 0%, #31587e 28%, #3c5873 48%, #162436 74%, #0a111d 100%); --theme-glow: rgba(255, 230, 180, 0.14); }
html[data-theme="day"][data-day="noon"]      { --app-bg-grad: linear-gradient(180deg, #23507e 0%, #31638e 30%, #2a5076 52%, #142438 76%, #0a121e 100%); --theme-glow: rgba(255, 245, 210, 0.16); }
html[data-theme="day"][data-day="afternoon"] { --app-bg-grad: linear-gradient(180deg, #2c4b6e 0%, #485a74 30%, #665a50 52%, #21212b 76%, #0e0c12 100%); --theme-glow: rgba(255, 210, 150, 0.15); }
html[data-theme="day"][data-day="dusk"]      { --app-bg-grad: linear-gradient(180deg, #222346 0%, #55324b 26%, #8a4a2c 46%, #2c1824 70%, #10090e 100%); --theme-glow: rgba(255, 140, 80, 0.16); }
html[data-theme="day"][data-day="night"]     { --app-bg-grad: linear-gradient(180deg, #0c1530 0%, #0b1226 50%, #050812 100%); --theme-glow: rgba(140, 170, 255, 0.10); }
html[data-theme="day"][data-weather="rain"], html[data-theme="day"][data-weather="storm"] { --app-bg-grad: linear-gradient(180deg, #2a3442 0%, #222a36 50%, #0e1218 100%); }
html[data-theme="day"][data-weather="rain"][data-day="night"], html[data-theme="day"][data-weather="storm"][data-day="night"] { --app-bg-grad: linear-gradient(180deg, #111722 0%, #0c1018 60%, #06080c 100%); }
html[data-theme="day"][data-weather="fog"] { --app-bg-grad: linear-gradient(180deg, #4a5560 0%, #333b45 46%, #12161b 100%); }
html[data-theme="garden"] {
    --bg-color: #0a120e; --card-bg: rgba(190, 235, 200, 0.07); --border: rgba(190, 235, 200, 0.15);
    --text-main: #e6f3e8; --text-sub: #93ad9a; --surface-strong: rgba(190, 235, 200, 0.13); --surface-strong-border: rgba(190, 235, 200, 0.22);
    --theme-glow: rgba(140, 220, 160, 0.12);
    --app-bg-grad: radial-gradient(120% 70% at 80% 110%, rgba(60, 120, 70, 0.30), transparent 62%), radial-gradient(90% 60% at 10% -10%, rgba(40, 80, 90, 0.25), transparent 60%), linear-gradient(180deg, #0f1c16 0%, #0a120e 60%, #050906 100%);
}
html[data-theme="combo"] {
    --bg-color: #080a1a; --card-bg: rgba(190, 200, 255, 0.075); --border: rgba(190, 200, 255, 0.16);
    --text-main: #eceffd; --text-sub: #a0a6c8; --surface-strong: rgba(190, 200, 255, 0.14); --surface-strong-border: rgba(190, 200, 255, 0.24);
    --theme-glow: rgba(150, 160, 255, 0.12);
    --app-bg-grad: radial-gradient(110% 80% at 50% 120%, rgba(90, 70, 200, 0.25), transparent 60%), linear-gradient(180deg, #0d0f24 0%, #080a1a 60%, #04050d 100%);
}
html[data-theme="snow"], html[data-theme="xmas26"] {
    --bg-color: #0c1220; --card-bg: rgba(210, 225, 255, 0.075); --border: rgba(210, 225, 255, 0.16);
    --text-main: #eef2fa; --text-sub: #a2adc4; --surface-strong: rgba(210, 225, 255, 0.14); --surface-strong-border: rgba(210, 225, 255, 0.24);
    --theme-glow: rgba(200, 220, 255, 0.12);
    --app-bg-grad: radial-gradient(70% 40% at 82% 96%, rgba(255, 196, 120, 0.20), transparent 70%), linear-gradient(180deg, #172238 0%, #0f1828 55%, #070b14 100%);
}
html[data-theme="xmas26"] { --app-bg-grad: radial-gradient(60% 40% at 50% 104%, rgba(255, 180, 100, 0.22), transparent 70%), radial-gradient(80% 50% at 50% -10%, rgba(60, 120, 90, 0.20), transparent 70%), linear-gradient(180deg, #13202e 0%, #0d1622 55%, #06090f 100%); }
html[data-theme="fireflies"] {
    --bg-color: #071214; --card-bg: rgba(190, 240, 220, 0.07); --border: rgba(190, 240, 220, 0.15);
    --text-main: #e5f4ef; --text-sub: #8fb0a8; --surface-strong: rgba(190, 240, 220, 0.13); --surface-strong-border: rgba(190, 240, 220, 0.22);
    --theme-glow: rgba(200, 240, 120, 0.10);
    --app-bg-grad: radial-gradient(120% 60% at 50% 115%, rgba(30, 70, 50, 0.45), transparent 60%), linear-gradient(180deg, #0c1a2a 0%, #0a161c 50%, #050a0b 100%);
}
html[data-theme="letters"] {
    --bg-color: #0a0f1c; --card-bg: rgba(200, 210, 255, 0.075); --border: rgba(200, 210, 255, 0.16);
    --text-main: #ecf0fb; --text-sub: #9ca6c4; --surface-strong: rgba(200, 210, 255, 0.14); --surface-strong-border: rgba(200, 210, 255, 0.24);
    --theme-glow: rgba(140, 170, 255, 0.12);
    --app-bg-grad: radial-gradient(100% 60% at 50% -10%, rgba(60, 80, 160, 0.30), transparent 62%), linear-gradient(180deg, #111a30 0%, #0a0f1c 60%, #05070e 100%);
}
html[data-theme="library"] {
    --bg-color: #140e09; --card-bg: rgba(255, 228, 190, 0.07); --border: rgba(255, 228, 190, 0.15);
    --text-main: #f6ece0; --text-sub: #b8a48c; --surface-strong: rgba(255, 228, 190, 0.13); --surface-strong-border: rgba(255, 228, 190, 0.22);
    --theme-glow: rgba(255, 190, 110, 0.13);
    --app-bg-grad: radial-gradient(80% 50% at 20% -5%, rgba(255, 180, 90, 0.20), transparent 64%), radial-gradient(70% 50% at 85% 0%, rgba(255, 170, 80, 0.14), transparent 62%),
        linear-gradient(180deg, #22170e 0%, #160f09 55%, #0a0704 100%);
}
html[data-theme="chalk"] {
    --bg-color: #0e1813; --card-bg: rgba(220, 240, 225, 0.07); --border: rgba(220, 240, 225, 0.15);
    --text-main: #eef5ef; --text-sub: #9fb3a5; --surface-strong: rgba(220, 240, 225, 0.13); --surface-strong-border: rgba(220, 240, 225, 0.22);
    --theme-glow: rgba(200, 240, 210, 0.10);
    --app-bg-grad: radial-gradient(90% 60% at 30% 20%, rgba(70, 110, 85, 0.30), transparent 65%), radial-gradient(70% 50% at 80% 80%, rgba(40, 80, 60, 0.30), transparent 60%),
        linear-gradient(160deg, #1b2b22 0%, #14211a 50%, #0b130e 100%);
}
html[data-theme="fireworks27"] {
    --bg-color: #06081a; --card-bg: rgba(200, 200, 255, 0.075); --border: rgba(200, 200, 255, 0.16);
    --text-main: #eeeffc; --text-sub: #a0a3c6; --surface-strong: rgba(200, 200, 255, 0.14); --surface-strong-border: rgba(200, 200, 255, 0.24);
    --theme-glow: rgba(255, 190, 140, 0.12);
    --app-bg-grad: radial-gradient(120% 50% at 50% 115%, rgba(80, 40, 120, 0.35), transparent 60%), linear-gradient(180deg, #0b0e26 0%, #070a1c 60%, #03040c 100%);
}
html[data-theme="lantern27"] {
    --bg-color: #0c0b1e; --card-bg: rgba(255, 225, 200, 0.07); --border: rgba(255, 225, 200, 0.15);
    --text-main: #f8efe8; --text-sub: #b9a9b4; --surface-strong: rgba(255, 225, 200, 0.13); --surface-strong-border: rgba(255, 225, 200, 0.22);
    --theme-glow: rgba(255, 170, 100, 0.13);
    --app-bg-grad: linear-gradient(180deg, #0a0c24 0%, #171a3c 45%, #33284a 74%, #3e2836 86%, #100b16 100%);
}
#theme-fx canvas.bgs { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#theme-fx canvas.bgs-back { transition: opacity 0.8s; }
#theme-fx[data-fx="garden"] .g-day { position: absolute; right: 5%; bottom: calc(66px + env(safe-area-inset-bottom, 0px)); font-size: 11px; letter-spacing: 1px; color: rgba(220, 245, 225, 0.42); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6); }
/* 小縮圖：卡片上先用這些漸層，畫布的靜止畫面畫好就蓋上去 */
.sw-day { background: linear-gradient(180deg, #2c5b8c 0%, #6e8fae 45%, #d0703f 70%, #2b2c58 100%); }
.sw-garden { background: radial-gradient(circle at 75% 90%, #4f9a5c 0 12%, transparent 13%), linear-gradient(180deg, #16281d, #0a120e); }
.sw-combo { background: radial-gradient(circle at 30% 70%, rgba(120,90,255,.7), transparent 50%), radial-gradient(circle at 75% 30%, rgba(255,210,120,.6), transparent 40%), linear-gradient(180deg, #0d0f24, #04050d); }
.sw-snow { background: radial-gradient(2px 2px at 20% 30%, #fff, transparent), radial-gradient(2px 2px at 60% 50%, #fff, transparent), radial-gradient(1.6px 1.6px at 80% 20%, #fff, transparent), radial-gradient(circle at 85% 95%, rgba(255,196,120,.5), transparent 40%), linear-gradient(180deg, #1c2a44, #0b111c); }
.sw-fireflies { background: radial-gradient(3px 3px at 30% 60%, #e8ff9a, transparent), radial-gradient(3px 3px at 70% 40%, #e8ff9a, transparent), radial-gradient(2px 2px at 50% 75%, #e8ff9a, transparent), linear-gradient(180deg, #0c1a2a, #050a0b); }
.sw-letters { background: linear-gradient(180deg, #16223e, #070a14); position: relative; }
.sw-library { background: linear-gradient(170deg, rgba(255,200,120,.35), transparent 50%), repeating-linear-gradient(90deg, transparent 0 14px, rgba(60,36,20,.5) 14px 16px), linear-gradient(180deg, #2a1c10, #0a0704); }
.sw-chalk { background: linear-gradient(160deg, #24382c, #0b130e); position: relative; }
.sw-xmas { background: radial-gradient(4px 4px at 20% 12%, #ff5a5a, transparent), radial-gradient(4px 4px at 45% 18%, #ffd34d, transparent), radial-gradient(4px 4px at 70% 12%, #5aff8a, transparent), radial-gradient(2px 2px at 30% 60%, #fff, transparent), radial-gradient(2px 2px at 70% 70%, #fff, transparent), linear-gradient(180deg, #1a2a3a, #06090f); }
.sw-fireworks { background: radial-gradient(circle at 35% 35%, rgba(255,120,120,.8) 0 3%, rgba(255,120,120,.25) 4% 16%, transparent 17%), radial-gradient(circle at 70% 55%, rgba(120,200,255,.8) 0 3%, rgba(120,200,255,.25) 4% 14%, transparent 15%), linear-gradient(180deg, #0b0e26, #03040c); }
.sw-lantern { background: radial-gradient(ellipse 9% 12% at 30% 45%, #ffe2a0, #f39a48 55%, transparent 60%), radial-gradient(ellipse 6% 8% at 68% 30%, #ffe2a0, #f39a48 55%, transparent 60%), linear-gradient(180deg, #0a0c24, #3a2a4a 75%, #120c18); }
.ms-swatch, .acc-theme-art { position: relative; overflow: hidden; }
.bg-thumb { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: inherit; }


/* 新背景的卡片與頂部列：背景有書架、樹林、城市這種細節，卡片要夠實才看得清楚字
   （原本 7% 的透明度是給幾乎純色的背景用的）。毛玻璃照樣有，只是底色厚一點。 */
html[data-theme="day"] { --card-bg: rgba(14, 22, 38, 0.76); --surface-strong: rgba(26, 37, 61, 0.84); --scene-bar: rgba(14, 22, 38, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="garden"] { --card-bg: rgba(12, 22, 16, 0.76); --surface-strong: rgba(23, 37, 29, 0.84); --scene-bar: rgba(12, 22, 16, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="combo"] { --card-bg: rgba(14, 14, 34, 0.76); --surface-strong: rgba(26, 26, 55, 0.84); --scene-bar: rgba(14, 14, 34, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="snow"] { --card-bg: rgba(14, 20, 34, 0.76); --surface-strong: rgba(26, 35, 55, 0.84); --scene-bar: rgba(14, 20, 34, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="xmas26"] { --card-bg: rgba(14, 22, 30, 0.76); --surface-strong: rgba(26, 37, 49, 0.84); --scene-bar: rgba(14, 22, 30, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="fireflies"] { --card-bg: rgba(9, 20, 22, 0.76); --surface-strong: rgba(19, 35, 37, 0.84); --scene-bar: rgba(9, 20, 22, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="letters"] { --card-bg: rgba(13, 17, 33, 0.76); --surface-strong: rgba(24, 30, 53, 0.84); --scene-bar: rgba(13, 17, 33, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="library"] { --card-bg: rgba(28, 19, 12, 0.76); --surface-strong: rgba(46, 33, 23, 0.84); --scene-bar: rgba(28, 19, 12, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="chalk"] { --card-bg: rgba(16, 28, 22, 0.76); --surface-strong: rgba(29, 46, 37, 0.84); --scene-bar: rgba(16, 28, 22, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="fireworks27"] { --card-bg: rgba(12, 12, 30, 0.76); --surface-strong: rgba(23, 23, 49, 0.84); --scene-bar: rgba(12, 12, 30, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="lantern27"] { --card-bg: rgba(18, 15, 36, 0.76); --surface-strong: rgba(32, 27, 58, 0.84); --scene-bar: rgba(18, 15, 36, 0.82); --glass-blur: blur(24px); --glass-sat: 120%; }
html[data-theme="day"] #main-header, html[data-theme="garden"] #main-header, html[data-theme="combo"] #main-header, html[data-theme="snow"] #main-header, html[data-theme="xmas26"] #main-header, html[data-theme="fireflies"] #main-header, html[data-theme="letters"] #main-header, html[data-theme="library"] #main-header, html[data-theme="chalk"] #main-header, html[data-theme="fireworks27"] #main-header, html[data-theme="lantern27"] #main-header { background: var(--scene-bar); }

/* 我的風格：一日背景的地點、整套搭配、管理員按鈕；商城的背景卡片 */
.ms-day { margin-top: 14px; padding: 12px; border-radius: 12px; background: var(--surface-strong, rgba(255,255,255,.06)); border: 1px solid var(--border); text-align: left; }
.ms-day-title { font-size: 0.8rem; color: var(--text-sub); margin-bottom: 6px; }
.ms-day-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.ms-day-select { flex: 1 1 120px; min-width: 0; padding: 7px 10px; border-radius: 9px; border: 1px solid var(--border); background: var(--card-bg); color: var(--text-main); font-size: 0.9rem; }
.ms-day-now { margin: 8px 0 0; font-size: 0.78rem; color: var(--text-sub); line-height: 1.5; }
.ms-sets { margin-top: 18px; }
.ms-sets-title { margin: 0 0 4px; font-size: 1rem; }
.ms-set { display: flex; align-items: center; gap: 12px; padding: 12px; margin-top: 8px; border-radius: 12px; background: var(--card-bg); border: 1px solid var(--border); }
.ms-set-info { flex: 1; min-width: 0; }
.ms-set-name { font-weight: 700; }
.ms-set-items { font-size: 0.78rem; color: var(--text-sub); margin-top: 3px; line-height: 1.5; }
.ms-set-side { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; }
.ms-set-full { font-size: 0.75rem; color: var(--text-sub); }
.ms-set-note { font-size: 0.8rem; color: var(--text-sub); }
.ms-admin-grant { margin-top: 8px; border-style: dashed; }
.ms-card.s-soon .ms-lock { font-size: 0.55rem; }
.theme-swatch-shop { background: rgba(255, 255, 255, 0.85); color: #222; }
.acc-grid-theme .acc-theme { display: flex; flex-direction: column; }
.acc-theme-art { display: block; width: 100%; aspect-ratio: 16 / 10; border-radius: 10px; border: 1px solid var(--border); cursor: pointer; margin-bottom: 8px; }
.acc-theme.on { border-color: rgba(241, 196, 15, 0.6); }
.acc-theme-until { font-size: 0.75rem; color: #f1c40f; margin: 4px 0 2px; }

/* 封閉測試人員徽章 */
.badge-tester { width: 60px; height: 60px; border-radius: 50%; border: 2px solid #4dd0c8; color: #7fe6df;
    background: radial-gradient(circle at 35% 30%, rgba(77, 208, 200, 0.28), rgba(20, 60, 64, 0.35) 70%);
    box-shadow: 0 0 12px rgba(77, 208, 200, 0.22); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; }
.badge-tester-cap { font-size: 0.62rem; font-weight: 700; letter-spacing: 1px; color: #7fe6df; }

/* 系統管理：安卓封閉測試 */
.ab-range { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0; font-size: 0.85rem; color: var(--text-sub); }
.ab-range input, .ab-range select { width: auto; padding: 6px 8px; margin: 0 0 0 4px; }
.ab-summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 10px 0; }
.ab-stat { padding: 10px; border-radius: 10px; border: 1px solid var(--border); background: var(--card-bg); text-align: center; }
.ab-stat b { display: block; font-size: 1.3rem; color: var(--text-main); }
.ab-stat span { font-size: 0.72rem; color: var(--text-sub); }
.ab-chart { margin: 6px 0 2px; }
.ab-row3 { display: flex; gap: 3px; }
.ab-row3 > span { flex: 1; min-width: 0; text-align: center; }
.ab-bars { position: relative; display: flex; gap: 3px; align-items: flex-end; height: 84px; border-bottom: 1px solid var(--border); }
.ab-bars i { flex: 1; min-width: 0; border-radius: 3px 3px 0 0; background: #26a69a; }
.ab-bars i.low { background: #ef5350; }
.ab-bars i.future { background: var(--border); }
.ab-need { position: absolute; left: 0; right: 0; border-top: 1px dashed rgba(255, 255, 255, 0.4); pointer-events: none; }
.ab-v { font-size: 0.66rem; color: var(--text-main); }
.ab-d { font-size: 0.58rem; color: var(--text-sub); white-space: nowrap; }
.ab-tools { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.ab-tools select { width: auto; padding: 6px 8px; }
.ab-list { display: flex; flex-direction: column; gap: 6px; }
.ab-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "cb who num" "cb dots dots"; gap: 4px 10px; align-items: center;
    padding: 10px; border-radius: 10px; border: 1px solid var(--border); background: var(--card-bg); cursor: pointer; }
.ab-row input { grid-area: cb; width: 18px; height: 18px; margin: 0; }
.ab-row.has-badge { opacity: 0.7; }
.ab-who { grid-area: who; min-width: 0; }
.ab-who b, .ab-who span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ab-who span, .ab-num span { font-size: 0.72rem; color: var(--text-sub); }
.ab-num { grid-area: num; text-align: right; }
.ab-num b { display: block; font-size: 0.85rem; }
.ab-dots { grid-area: dots; display: flex; gap: 3px; }
.ab-dots i { flex: 1; max-width: 18px; height: 10px; border-radius: 3px; background: rgba(255, 255, 255, 0.08); }
.ab-dots i.on { background: #26a69a; }
.ab-dots i.future { background: transparent; border: 1px dashed var(--border); }

/* 帳號資料讀不到時的提示 */
#account-retry-note { position: fixed; left: 50%; top: calc(10px + env(safe-area-inset-top, 0px)); transform: translateX(-50%); z-index: 9000;
    width: min(92vw, 460px); display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 12px;
    background: rgba(40, 32, 12, 0.95); border: 1px solid rgba(241, 196, 15, 0.5); color: #f6e7b8; font-size: 0.82rem; line-height: 1.45;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4); }
#account-retry-note.hidden { display: none; }
#account-retry-note span { flex: 1; }
#account-retry-note button { flex-shrink: 0; padding: 6px 10px; border-radius: 8px; border: 1px solid rgba(241, 196, 15, 0.6); background: transparent; color: #f1c40f; font-size: 0.8rem; }

/* 精通模式的片語題型（phrase-drill.js） */
.phd-example { margin: 12px auto 4px; max-width: 520px; padding: 10px 14px; border-radius: 12px; background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--border); text-align: left; line-height: 1.6; }
.phd-en { font-size: 1.02rem; color: var(--text-main); }
.phd-zh { margin-top: 4px; font-size: 0.85rem; color: var(--text-sub); }
.phd-mark { background: rgba(255, 193, 7, 0.22); color: #ffd54f; border-radius: 4px; padding: 0 3px; }
.phd-blank { display: inline-flex; gap: 6px; vertical-align: baseline; }
.phd-blank i { display: inline-block; min-width: 46px; border-bottom: 2px solid #ffc107; font-style: normal; text-align: center; color: #ffd54f; padding: 0 2px; }
.phd-blank i.on { border-bottom-color: #4caf50; color: #a5d6a7; }
.phd-board { width: 100%; }
.phd-slots { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin: 12px 0 4px; }
.phd-tile { min-width: 64px; padding: 10px 14px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface-strong, rgba(255,255,255,.08));
    color: var(--text-main); font-size: 1.05rem; font-weight: 600; cursor: pointer; }
.phd-tile.phd-typing { border-color: #ffc107; box-shadow: 0 0 0 2px rgba(255, 193, 7, 0.25); }
.phd-slot { min-height: 44px; border-style: dashed; background: transparent; }
.phd-slot.filled { border-style: solid; border-color: #ffc107; background: rgba(255, 193, 7, 0.12); }
#mastery-puzzle-pool .phd-tile { margin: 4px; }

/* 翻譯整句、整段（translate-panel.js） */
.tr-sheet { position: fixed; inset: 0; z-index: 9000; background: rgba(0, 0, 0, 0.55); display: flex; align-items: flex-end; justify-content: center; }
.tr-sheet.hidden { display: none; }
.tr-box { width: min(680px, 100%); max-height: 86vh; overflow-y: auto; background: var(--bg-color, #111); border: 1px solid var(--border);
    border-radius: 18px 18px 0 0; padding: 16px 16px calc(84px + env(safe-area-inset-bottom, 0px)); box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.4); }
@media (min-width: 700px) { .tr-sheet { align-items: center; } .tr-box { border-radius: 18px; } }
.tr-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.tr-title { font-weight: 800; font-size: 1.1rem; }
.tr-close { border: 1px solid var(--border); background: transparent; color: var(--text-sub); border-radius: 999px; padding: 4px 12px; cursor: pointer; }
.tr-loading, .tr-error { padding: 28px 8px; text-align: center; color: var(--text-sub); }
.tr-error { color: #ff8a80; }
.tr-row { padding: 12px 0; border-bottom: 1px solid var(--border); }
.tr-row:last-child { border-bottom: 0; }
.tr-zh { font-size: 1.02rem; line-height: 1.6; color: var(--text-main); margin-bottom: 6px; }
.tr-en { font-size: 0.98rem; line-height: 1.8; color: var(--text-sub); }
.tr-en .wp-word { cursor: pointer; border-radius: 4px; }
.tr-en .wp-word:hover { background: rgba(255, 196, 107, 0.15); }
.tr-phrase { background: linear-gradient(#ffc107, #ffc107) 0 100% / 100% 2px no-repeat; padding-bottom: 2px; color: var(--text-main);
    -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.tr-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.tr-chips-label { font-size: 0.72rem; color: var(--text-sub); letter-spacing: 1px; }
.tr-chip { display: inline-flex; align-items: baseline; gap: 6px; padding: 5px 10px; border-radius: 999px; border: 1px solid rgba(255, 193, 7, 0.45);
    background: rgba(255, 193, 7, 0.1); color: var(--text-main); font-size: 0.85rem; cursor: pointer; }
.tr-chip b { color: #ffd54f; font-weight: 700; }
.tr-chip span { color: var(--text-sub); font-size: 0.78rem; }
.tr-report-btn { display: inline-block; margin-top: 6px; border: 0; background: transparent; color: var(--text-sub); font-size: 0.75rem; padding: 2px 0;
    cursor: pointer; text-decoration: underline; text-decoration-color: rgba(255, 255, 255, 0.25); text-underline-offset: 3px; opacity: 0.8; }
.tr-report-btn:hover { opacity: 1; color: var(--text-main); }
.tr-inline-tools .tr-report-btn { margin-top: 0; margin-left: auto; }
.tr-report-form { margin-top: 8px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--border); background: rgba(255, 255, 255, 0.04);
    display: flex; flex-direction: column; gap: 6px; }
.tr-report-title { font-size: 0.82rem; font-weight: 700; color: var(--text-main); }
.tr-report-opt { display: flex; align-items: flex-start; gap: 8px; font-size: 0.85rem; color: var(--text-main); line-height: 1.45; cursor: pointer; }
.tr-report-opt input { margin-top: 3px; flex: none; }
.tr-report-note { width: 100%; box-sizing: border-box; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border); background: var(--card-bg);
    color: var(--text-main); font-size: 0.88rem; }
.tr-report-actions { display: flex; gap: 8px; }
.tr-report-done { font-size: 0.85rem; color: #81c784; }
.tra-filter { display: flex; gap: 8px; align-items: center; margin: 6px 0 10px; }
.tra-item { padding: 12px; border: 1px solid var(--border); border-radius: 12px; margin: 10px 0; display: flex; flex-direction: column; gap: 6px; }
.tra-item.tra-done { opacity: 0.55; }
.tra-head { display: flex; gap: 8px; align-items: center; font-size: 0.78rem; color: var(--text-sub); }
.tra-kind { padding: 1px 8px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-main); }
.tra-en { font-size: 0.9rem; line-height: 1.6; color: var(--text-main); }
.tra-phrase-name { font-weight: 800; color: #ffd54f; }
.tra-zh, .tra-note, .tra-fixed { font-size: 0.85rem; line-height: 1.5; color: var(--text-sub); }
.tra-fixed { color: #81c784; }
.tra-input { width: 100%; box-sizing: border-box; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border); background: var(--card-bg); color: var(--text-main); font-size: 0.9rem; }
textarea.tra-input { min-height: 64px; resize: vertical; }
.tra-skip { font-size: 0.82rem; color: var(--text-sub); }
.tra-acts { display: flex; gap: 8px; }
.tr-tools { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.tr-note { margin: 0; font-size: 0.75rem; color: var(--text-sub); line-height: 1.5; }
.tr-ai { margin: 4px 0 8px; padding: 12px; border-radius: 12px; background: rgba(156, 39, 176, 0.12); border: 1px solid rgba(186, 104, 200, 0.4); }
.tr-ai-label { font-size: 0.72rem; color: #ce93d8; letter-spacing: 1px; margin-bottom: 4px; }
.tr-ai-zh { line-height: 1.7; }
.tr-input { width: 100%; min-height: 140px; padding: 12px; border-radius: 12px; border: 1px solid var(--border); background: var(--card-bg); color: var(--text-main);
    font-size: 0.95rem; line-height: 1.6; resize: vertical; box-sizing: border-box; }
.tr-go { margin-top: 10px; width: 100%; }
body.tr-open .wp-chip { z-index: 9600; }
.dict-translate-btn { margin: 4px 0 12px; border: 1px dashed var(--border); background: transparent; color: var(--text-sub); border-radius: 10px; padding: 8px 12px; font-size: 0.88rem; cursor: pointer; width: 100%; }
.dict-translate-row { display: flex; gap: 8px; margin: 4px 0 12px; }
.dict-translate-row .dict-translate-btn { margin: 0; flex: 1; }
.dict-example { padding: 8px 0; border-bottom: 1px solid var(--border); }
.dict-example:last-of-type { border-bottom: 0; }
.dict-example-en { margin: 0; line-height: 1.6; }
.dict-example-en mark { background: rgba(255, 193, 7, 0.22); color: inherit; border-radius: 3px; padding: 0 2px; }
.dict-example-zh { margin: 2px 0 0; font-size: 0.85rem; color: var(--text-sub); }

/* ── 每日單字錦標賽（tournament-ui.js）── */
.tour-banner { width: 100%; display: flex; align-items: center; gap: 10px; padding: 12px 14px; margin-bottom: 12px; border: 1px solid color-mix(in srgb, #ffc107 40%, var(--border));
    border-radius: 14px; background: color-mix(in srgb, #ffc107 7%, var(--card-bg)); color: var(--text-main); font-family: inherit; text-align: left; cursor: pointer; }
.tour-banner.hidden { display: none; }
/* 平常：首頁最上面一條細細的跑馬燈（晚上 8:30 起才換成大的入口卡） */
.tour-ticker { display: block; width: 100%; height: 30px; margin: 0 0 10px; padding: 0; overflow: hidden; border: 0; border-radius: 999px; cursor: pointer;
    background: color-mix(in srgb, #ffc107 8%, transparent); color: #e9cf86; font-family: inherit; font-size: 0.8rem; line-height: 30px; text-align: left;
    -webkit-mask: linear-gradient(90deg, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%); mask: linear-gradient(90deg, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%); }
.tour-ticker.hidden { display: none; }
.tour-ticker-track { display: inline-flex; white-space: nowrap; animation: tourTicker 28s linear infinite; }
.tour-ticker-item { padding-right: 56px; }
.tour-ticker:hover .tour-ticker-track { animation-play-state: paused; }
@keyframes tourTicker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .tour-ticker-track { animation: none; } .tour-ticker-item + .tour-ticker-item { display: none; } .tour-ticker { text-overflow: ellipsis; padding: 0 14px; } }
.tour-banner.soon { border-color: color-mix(in srgb, #ffc107 70%, var(--border)); background: color-mix(in srgb, #ffc107 13%, var(--card-bg)); }
.tour-banner.live { border-color: #ffc107; background: linear-gradient(90deg, color-mix(in srgb, #ffc107 22%, var(--card-bg)), color-mix(in srgb, #ff7043 14%, var(--card-bg)));
    animation: tourPulse 1.8s ease-in-out infinite; }
@keyframes tourPulse { 50% { box-shadow: 0 0 0 4px rgba(255, 193, 7, 0.18); } }
.tour-b-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tour-b-title { font-weight: 800; font-size: 0.95rem; color: #ffd36a; }
.tour-b-sub { font-size: 0.8rem; color: var(--text-sub); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tour-banner.live .tour-b-sub { color: var(--text-main); }
.tour-b-go { flex-shrink: 0; font-size: 0.8rem; font-weight: 700; color: #1a1204; background: #ffc107; border-radius: 999px; padding: 5px 12px; }
/* ── 每日單字錦標賽：夜間競技場 ── */
.tour-view { position: fixed; inset: 0; z-index: 9100; color: #f2f2f2; display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden;
    background: radial-gradient(90% 55% at 50% -5%, rgba(255,196,64,.22), transparent 60%), radial-gradient(70% 50% at 50% 115%, rgba(80,120,255,.18), transparent 60%),
    linear-gradient(180deg, #0b1024 0%, #070a16 55%, #05060c 100%); }
.tour-view.hidden { display: none; }
body.tour-open, html.tour-lock { overflow: hidden !important; overscroll-behavior: none; }
.tour-view { overscroll-behavior: contain; touch-action: pan-y; }
.tour-lights { position: fixed; inset: 0; pointer-events: none; overflow: hidden; z-index: 0; }
.tour-lights::before, .tour-lights::after { content: ''; position: absolute; top: -20%; width: 46vmax; height: 140%; opacity: .16; filter: blur(8px);
    background: linear-gradient(180deg, rgba(255,214,120,.9), rgba(255,214,120,0) 75%); clip-path: polygon(46% 0, 54% 0, 100% 100%, 0 100%); transform-origin: 50% 0; }
.tour-lights::before { left: 0; animation: tourBeamL 9s ease-in-out infinite alternate; }
.tour-lights::after { right: 0; animation: tourBeamR 11s ease-in-out infinite alternate; }
@keyframes tourBeamL { from { transform: rotate(-28deg); } to { transform: rotate(-6deg); } }
@keyframes tourBeamR { from { transform: rotate(26deg); } to { transform: rotate(5deg); } }
/* 只有排版的區塊（頂端列、內容）要疊在燈光上面；中央跳出來的提示、飛起來的應援要保持固定在畫面上，不能被排進內容最下面 */
.tour-view > :not(.tour-lights):not(.tour-splash):not(.tour-pop):not(.tour-fly) { position: relative; z-index: 1; }
.tour-head { display: flex; align-items: center; gap: 10px; padding: calc(12px + env(safe-area-inset-top, 0px)) 16px 8px; }
.tour-close { border: 1px solid rgba(255,255,255,.2); background: rgba(255,255,255,.04); color: #ddd; border-radius: 999px; padding: 5px 14px; font: inherit; font-size: 0.85rem; cursor: pointer; }
.tour-head-title { flex: 1; text-align: center; font-weight: 900; letter-spacing: 3px; background: linear-gradient(90deg, #ffe7a3, #ffc94a, #ffe7a3); -webkit-background-clip: text; background-clip: text; color: transparent; }
.tour-head-count { min-width: 56px; text-align: right; font-size: 0.82rem; color: #cfd6ee; font-variant-numeric: tabular-nums; }
.tour-head-count.live::before { content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: #ff5a4f; margin-right: 6px; vertical-align: 1px; box-shadow: 0 0 8px #ff5a4f; animation: tourLive 1.4s ease-in-out infinite; }
@keyframes tourLive { 50% { opacity: .3; } }
.tour-body { flex: 1; width: min(560px, 100%); margin: 0 auto; padding: 6px 16px calc(28px + env(safe-area-inset-bottom, 0px)); display: flex; flex-direction: column; gap: 14px; box-sizing: border-box; }
.tour-body.shake { animation: tourShake .45s ease; }
@keyframes tourShake { 20% { transform: translateX(-8px); } 40% { transform: translateX(7px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(3px); } }
.tour-panel { border-radius: 16px; background: rgba(255,255,255,.045); border: 1px solid rgba(255,255,255,.09); padding: 12px 14px; backdrop-filter: blur(6px); }
.tour-panel-title { display: flex; justify-content: space-between; align-items: center; font-size: 0.78rem; letter-spacing: 2px; color: #aab3d1; margin-bottom: 8px; }
.tour-hero { text-align: center; padding: 10px 0 2px; }
.tour-kicker { text-align: center; font-size: 0.78rem; letter-spacing: 3px; color: #ffd36a; }
.tour-big { text-align: center; font-size: 1.5rem; font-weight: 900; margin-top: 4px; }
.tour-count { text-align: center; font-size: 1.1rem; color: #ffd36a; font-variant-numeric: tabular-nums; }
.tour-count-big { font-size: 3.8rem; font-weight: 900; letter-spacing: 3px; text-shadow: 0 0 28px rgba(255,201,74,.45); line-height: 1.1; margin: 4px 0; }
.tour-count-big.final { font-size: 5.6rem; color: #fff; text-shadow: 0 0 40px rgba(255,90,79,.8); }
.tour-count-big.beat { animation: tourBeat .6s ease; }
@keyframes tourBeat { 0% { transform: scale(1.35); opacity: .4; } 40% { transform: scale(.94); opacity: 1; } 100% { transform: scale(1); } }
.tour-wait { text-align: center; color: #cfd6ee; font-size: .9rem; }
.tour-rules { margin: 0; padding: 12px 14px 12px 32px; border-radius: 14px; background: rgba(255,255,255,.045); border: 1px solid rgba(255,255,255,.08); color: #d6dbea; font-size: 0.88rem; line-height: 1.8; }
.tour-rules-box summary { cursor: pointer; color: #aab3d1; font-size: .85rem; padding: 6px 2px; }
.tour-rules-box .tour-rules { margin-top: 6px; }
.tour-msg { text-align: center; color: #cfd6ee; padding: 16px 8px; }
.tour-last, .tour-leaders { display: flex; flex-direction: column; gap: 6px; }
.tour-last-title { font-size: 0.8rem; color: #aab3d1; margin-bottom: 2px; }
.tour-last-row, .tour-leader { display: flex; align-items: center; gap: 10px; font-size: 0.92rem; }
.tour-last-row span:nth-of-type(1), .tour-leader span:nth-of-type(1) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tour-leader { padding: 6px 8px; border-radius: 10px; animation: tourRow .45s cubic-bezier(.2,.9,.3,1) both; }
.tour-leader.rise { background: rgba(126,224,138,.1); }
@keyframes tourRow { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: none; } }
.tour-move { font-style: normal; font-size: .7rem; width: 18px; text-align: center; }
.tour-move.up { color: #7ee08a; } .tour-move.down { color: #ff8a80; } .tour-move.new { color: #ffd36a; font-size: .66rem; }
.tour-last-score { color: #ffd36a; font-variant-numeric: tabular-nums; font-weight: 700; }
.tour-medal { width: 24px; height: 24px; border-radius: 50%; display: inline-grid; place-items: center; font-size: 0.75rem; background: rgba(255,255,255,.12); color: #ddd; flex-shrink: 0; }
.tour-medal.m1 { background: linear-gradient(135deg,#ffe58a,#ffb300); color: #1a1204; } .tour-medal.m2 { background: linear-gradient(135deg,#f3f7fb,#b9c6d6); color: #10161e; } .tour-medal.m3 { background: linear-gradient(135deg,#f0b58a,#c97b42); color: #1b0d04; }
/* 等候室 */
.tour-wall-row { display: flex; gap: 10px; overflow-x: auto; padding: 2px 2px 6px; scrollbar-width: none; min-height: 64px; }
.tour-wall-row::-webkit-scrollbar { display: none; }
.tour-arrive { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 54px; flex-shrink: 0; animation: tourPop .5s cubic-bezier(.2,1.4,.4,1) both; }
@keyframes tourPop { from { opacity: 0; transform: scale(.3) translateY(10px); } to { opacity: 1; transform: none; } }
.tour-arrive-name { font-size: .68rem; color: #cfd6ee; width: 100%; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tour-ava { width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center; background: #1c2340; color: #fff; font-weight: 800; border: 2px solid rgba(255,255,255,.18); overflow: hidden; flex-shrink: 0; }
.tour-ava img { width: 100%; height: 100%; object-fit: cover; }
.tour-arrive.champ .tour-ava { border-color: #ffc94a; box-shadow: 0 0 0 2px rgba(255,201,74,.35), 0 0 14px rgba(255,201,74,.6); }
.tour-warm-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.tour-warm-word { font-size: 1.5rem; font-weight: 900; letter-spacing: .5px; }
.tour-warm-clock { font-size: .8rem; color: #aab3d1; font-variant-numeric: tabular-nums; }
.tour-warm-score { color: #7ee08a; letter-spacing: 0; }
.tour-warm-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tour-warm-opt { padding: 10px 8px; border-radius: 12px; border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.04); color: #eef; font: inherit; font-size: .9rem; cursor: pointer; transition: transform .1s; }
.tour-warm-opt:active { transform: scale(.97); }
.tour-warm-opt.right { border-color: #4caf50; background: rgba(76,175,80,.2); }
.tour-warm-opt.wrong { border-color: #ff5a4f; background: rgba(255,90,79,.18); }
.tour-feed { height: 190px; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding-right: 4px; margin-bottom: 10px; overscroll-behavior: contain; }
.tour-feed-empty { color: #8891ad; font-size: .85rem; text-align: center; margin: auto; }
.tour-line { display: flex; align-items: baseline; gap: 6px; font-size: .88rem; line-height: 1.45; animation: tourRow .35s ease both; }
.tour-line-name { color: #ffd36a; font-weight: 700; flex-shrink: 0; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tour-line-text { color: #eef; word-break: break-word; min-width: 0; }
.tour-line.cheer .tour-line-text { color: #9fb4ff; }
.tour-line-mod { margin-left: auto; border: 1px solid rgba(255,255,255,.18); background: transparent; color: #ccc; border-radius: 8px; padding: 1px 7px; font: inherit; font-size: .7rem; cursor: pointer; flex-shrink: 0; }
.tour-line-mod + .tour-line-mod { margin-left: 4px; }
.tour-cheers { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 8px; }
.tour-cheer-btn { padding: 8px 4px; border-radius: 12px; border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.05); color: #fff; font: inherit; font-size: .8rem; font-weight: 700; cursor: pointer; white-space: nowrap; }
.tour-cheer-btn.c0 { border-color: rgba(255,201,74,.45); } .tour-cheer-btn.c1 { border-color: rgba(255,112,67,.45); } .tour-cheer-btn.c2 { border-color: rgba(143,184,255,.45); } .tour-cheer-btn.c3 { border-color: rgba(126,224,138,.45); }
.tour-cheer-btn.tap { animation: tourTap .35s ease; }
@keyframes tourTap { 40% { transform: scale(.9); } 70% { transform: scale(1.06); } }
.tour-chat-form { display: flex; gap: 8px; }
.tour-chat-input { flex: 1; min-width: 0; padding: 10px 12px; border-radius: 12px; border: 1px solid rgba(255,255,255,.16); background: rgba(0,0,0,.25); color: #fff; font: inherit; font-size: .9rem; }
.tour-chat-input:focus { outline: none; border-color: #ffc94a; }
.tour-chat-send { padding: 0 16px; border-radius: 12px; border: 0; background: linear-gradient(135deg, #ffd36a, #ffb300); color: #1a1204; font: inherit; font-weight: 800; cursor: pointer; }
.tour-chat-send:disabled, .tour-chat-input:disabled { opacity: .5; cursor: default; }
.tour-chat-note { min-height: 1em; margin-top: 6px; font-size: .78rem; color: #ff8a80; }
.tour-chat-note:empty { display: none; }
.tour-fly { position: fixed; inset: 0; pointer-events: none; z-index: 3; overflow: hidden; }
.tour-fly-item { position: absolute; bottom: 8%; padding: 6px 12px; border-radius: 999px; font-weight: 800; font-size: .9rem; color: #1a1204; background: #ffd36a; box-shadow: 0 6px 20px rgba(0,0,0,.35); animation: tourFly 3s ease-out forwards; white-space: nowrap; }
.tour-fly-item.c1 { background: #ff8a65; } .tour-fly-item.c2 { background: #9fb4ff; } .tour-fly-item.c3 { background: #7ee08a; }
@keyframes tourFly { 0% { opacity: 0; transform: translateY(0) scale(.6); } 12% { opacity: 1; transform: translateY(-20px) scale(1.05); } 100% { opacity: 0; transform: translateY(-46vh) scale(.95); } }
/* 作答 */
.tour-q { display: flex; flex-direction: column; gap: 12px; }
.tour-q-meta { display: flex; gap: 8px; align-items: center; font-size: 0.82rem; color: #aab3d1; }
.tour-q-no { color: #fff; font-weight: 800; letter-spacing: 1px; }
.tour-q-kind { margin-left: auto; }
.tour-double { background: linear-gradient(135deg, #ff7043, #ff3d6e); color: #fff; border-radius: 999px; padding: 2px 9px; font-weight: 800; font-size: 0.75rem; box-shadow: 0 0 12px rgba(255,80,90,.5); }
.tour-prompt-wrap { position: relative; }
.tour-prompt { text-align: center; font-size: 1.7rem; font-weight: 900; padding: 30px 56px; border-radius: 18px; word-break: break-word;
    background: linear-gradient(160deg, rgba(255,255,255,.1), rgba(255,255,255,.03)); border: 1px solid rgba(255,214,120,.28); box-shadow: 0 10px 40px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.12); }
.tour-prompt.en { font-size: 2.2rem; letter-spacing: .5px; }
.tour-q.entering .tour-prompt { animation: tourIn .45s cubic-bezier(.2,.9,.3,1) both; }
@keyframes tourIn { from { opacity: 0; transform: translateY(18px) scale(.96); } to { opacity: 1; transform: none; } }
.tour-ring { position: absolute; top: 8px; right: 8px; width: 44px; height: 44px; transform: rotate(-90deg); }
.tour-ring circle { fill: none; stroke-width: 4; }
.tour-ring .bg { stroke: rgba(255,255,255,.12); }
.tour-ring .fg { stroke: #ffc94a; stroke-linecap: round; transition: stroke .2s; }
.tour-ring.low .fg { stroke: #ff5a4f; }
.tour-ring text { transform: rotate(90deg); transform-origin: 22px 22px; fill: #fff; font-size: 14px; font-weight: 900; }
.tour-timer { height: 6px; border-radius: 999px; background: rgba(255,255,255,.1); overflow: hidden; }
.tour-timer i { display: block; height: 100%; width: 100%; background: linear-gradient(90deg, #ffb300, #ffe08a); border-radius: 999px; transition: width .05s linear; }
.tour-timer i.low { background: linear-gradient(90deg, #ff3d3d, #ff8a65); }
.tour-opts { display: grid; grid-template-columns: 1fr; gap: 10px; }
.tour-opts.grid { grid-template-columns: 1fr 1fr; }
.tour-opt { position: relative; overflow: hidden; display: flex; align-items: center; gap: 12px; text-align: left; padding: 14px; border-radius: 16px; border: 1px solid rgba(255,255,255,.14);
    background: rgba(255,255,255,.05); color: #f2f2f2; font: inherit; font-size: 1.05rem; cursor: pointer; min-height: 60px; transition: transform .12s, border-color .15s, background .15s, opacity .2s;
    border-left: 4px solid var(--oc, #ffc94a); }
.tour-q.entering .tour-opt { animation: tourOpt .4s cubic-bezier(.2,.9,.3,1) both; }
@keyframes tourOpt { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.tour-opt.o0 { --oc: #ffc94a; } .tour-opt.o1 { --oc: #8fb8ff; } .tour-opt.o2 { --oc: #ff8a65; } .tour-opt.o3 { --oc: #7ee08a; }
.tour-opt.en .tour-opt-text { font-weight: 700; letter-spacing: .3px; }
.tour-opt:active:not(:disabled) { transform: scale(.97); }
.tour-opt:disabled { cursor: default; }
.tour-opt.dim { opacity: .45; }
.tour-opt::before { content: ''; position: absolute; inset: 0 auto 0 0; width: var(--pct, 0%); background: rgba(255,255,255,.08); transition: width .9s cubic-bezier(.2,.9,.3,1); }
.tour-key { position: relative; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; background: color-mix(in srgb, var(--oc) 28%, transparent); color: #fff; font-size: 0.8rem; font-weight: 800; flex-shrink: 0; }
.tour-opt-text { position: relative; flex: 1; }
.tour-pct { position: relative; font-size: 0.8rem; color: #cfd6ee; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tour-opt.picked { border-color: #ffc94a; background: rgba(255,193,7,.14); box-shadow: 0 0 0 2px rgba(255,201,74,.35); animation: tourPick .3s ease; }
@keyframes tourPick { 50% { transform: scale(1.03); } }
.tour-opt.right { border-color: #4caf50; background: rgba(76,175,80,.18); opacity: 1; box-shadow: 0 0 22px rgba(76,175,80,.45); animation: tourRight .8s ease; }
@keyframes tourRight { 30% { transform: scale(1.04); } }
.tour-opt.right::before { background: rgba(76,175,80,.25); }
.tour-opt.wrong { border-color: #ff5a4f; background: rgba(255,90,79,.16); opacity: 1; }
.tour-note { align-self: center; text-align: center; font-size: .85rem; color: #cfd6ee; padding: 3px 14px; border-radius: 999px; }
.tour-note:empty { display: none; }
.tour-note.done { color: #ffe7a3; background: rgba(255,201,74,.12); border: 1px solid rgba(255,201,74,.3); }
.tour-note.warn { color: #ffb3ab; background: rgba(255,90,79,.12); border: 1px solid rgba(255,90,79,.35); font-weight: 700; }
/* 畫面中央跳出來的提示（答對加分、答錯、時間到），像過濾工廠的「加班時刻」 */
.tour-pop { position: fixed; left: 50%; top: 45%; z-index: 9300; width: max-content; max-width: 92vw; text-align: center; pointer-events: none; opacity: 0;
    transform: translate(-50%, -50%) scale(.8); transition: opacity .18s, transform .35s cubic-bezier(.2,1.6,.4,1); padding: 26px 40px; border-radius: 26px;
    background: radial-gradient(closest-side, rgba(4,6,14,.9), rgba(4,6,14,.7) 65%, rgba(4,6,14,0)); }
.tour-pop.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.tour-pop-big { font-weight: 900; font-size: clamp(2.4rem, 12vw, 3.6rem); line-height: 1.1; letter-spacing: 4px; color: #fff3df; text-shadow: 0 3px 0 #000, 0 0 26px rgba(255,190,60,.7); white-space: nowrap; font-variant-numeric: tabular-nums; }
.tour-pop-small { margin-top: 8px; font-size: 1rem; font-weight: 800; color: #eee3cc; text-shadow: 0 2px 0 #000; }
.tour-pop.good .tour-pop-big { color: #8dffb0; text-shadow: 0 3px 0 #000, 0 0 26px rgba(60,255,140,.65); }
.tour-pop.bad .tour-pop-big { color: #ff5a4a; text-shadow: 0 3px 0 #000, 0 0 26px rgba(255,30,20,.85); }
.tour-pop.none .tour-pop-big { color: #dfe4f2; text-shadow: 0 3px 0 #000, 0 0 20px rgba(160,180,255,.5); }
@media (prefers-reduced-motion: reduce) { .tour-pop { transition: opacity .15s; transform: translate(-50%, -50%); } }
/* 錦標賽是獨立頁面：首頁的頂端列、下方導覽列、字靈、背景特效都收起來 */
body.tour-page #main-header, body.tour-page #bottom-nav, body.tour-page .bnav, body.tour-page #nav-pet, body.tour-page #nav-pet-ground-shadow,
body.tour-page #flow-ball, body.tour-page #theme-fx { display: none !important; }
.tour-splash { position: fixed; inset: 0; z-index: 9200; display: grid; place-items: center; pointer-events: none; font-size: 4.6rem; font-weight: 900; letter-spacing: 6px; color: #fff;
    text-shadow: 0 0 40px rgba(255,201,74,.9); animation: tourSplash 1.2s cubic-bezier(.2,.9,.3,1) forwards; }
.tour-splash.double { color: #ffd1d8; text-shadow: 0 0 40px rgba(255,61,110,.95); background: radial-gradient(circle, rgba(255,61,110,.25), transparent 60%); }
@keyframes tourSplash { 0% { opacity: 0; transform: scale(2.2); } 25% { opacity: 1; transform: scale(1); } 75% { opacity: 1; } 100% { opacity: 0; transform: scale(.9); } }
/* 公布答案 */
.tour-result { text-align: center; padding: 10px 12px; border-radius: 16px; animation: tourIn .4s ease both; display: flex; flex-direction: column; gap: 6px; }
.tour-result-line { display: flex; flex-wrap: wrap; justify-content: center; align-items: baseline; gap: 4px 10px; }
.tour-result .tour-result-big { font-size: 1.35rem; }
.tour-result .tour-streak { margin-top: 0; }
.tour-result .tour-me { font-size: .9rem; }
.tour-result .tour-me-score { font-size: 1.2rem; }
.tour-result.ok { background: rgba(76,175,80,.12); border: 1px solid rgba(76,175,80,.35); }
.tour-result.bad { background: rgba(255,90,79,.1); border: 1px solid rgba(255,90,79,.3); }
.tour-result.none { background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.08); }
.tour-result-big { font-size: 2rem; font-weight: 900; font-variant-numeric: tabular-nums; }
.tour-result.ok .tour-result-big { color: #7ee08a; text-shadow: 0 0 20px rgba(126,224,138,.5); }
.tour-result.bad .tour-result-big { color: #ff8a80; }
.tour-result-sub { color: #cfd6ee; font-size: .88rem; margin-top: 2px; }
.tour-streak { display: inline-block; margin-top: 8px; padding: 3px 12px; border-radius: 999px; font-weight: 800; font-size: .85rem; color: #1a0f00;
    background: linear-gradient(90deg, #ffb300, #ff5722); box-shadow: 0 0 16px rgba(255,120,30,.6); animation: tourPop .5s cubic-bezier(.2,1.4,.4,1) .25s both; }
.tour-me { display: flex; justify-content: center; align-items: baseline; gap: 6px; color: #cfd6ee; }
.tour-me-score { font-size: 1.5rem; color: #ffd36a; font-variant-numeric: tabular-nums; }
.tour-me-rank { margin-left: 8px; padding: 2px 10px; border-radius: 999px; background: rgba(255,201,74,.12); color: #ffd36a; font-size: .85rem; }
/* 結果 */
.tour-done { position: relative; display: flex; flex-direction: column; gap: 14px; }
.tour-confetti { position: absolute; left: 0; top: 0; width: 100%; height: 450px; pointer-events: none; z-index: 5; }
.tour-podium { display: grid; grid-template-columns: 1fr 1.15fr 1fr; align-items: end; gap: 8px; margin: 10px 0 4px; }
.tour-pod { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; animation: tourPodium .7s cubic-bezier(.2,1.2,.4,1) both; }
@keyframes tourPodium { from { opacity: 0; transform: translateY(40px); } to { opacity: 1; transform: none; } }
.tour-ava.big { width: 56px; height: 56px; font-size: 1.2rem; }
.tour-pod.p1 .tour-ava.big { width: 70px; height: 70px; border-color: #ffc94a; box-shadow: 0 0 22px rgba(255,201,74,.7); }
.tour-pod.p2 .tour-ava.big { border-color: #cfd8e3; } .tour-pod.p3 .tour-ava.big { border-color: #e0a06a; }
.tour-pod-name { font-weight: 800; font-size: .88rem; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tour-pod-score { font-size: .78rem; color: #ffd36a; font-variant-numeric: tabular-nums; }
.tour-pod-block { width: 100%; margin-top: 6px; border-radius: 12px 12px 4px 4px; display: grid; place-items: center; font-size: 1.6rem; font-weight: 900; color: rgba(0,0,0,.55); }
.tour-pod.p1 .tour-pod-block { height: 110px; background: linear-gradient(180deg, #ffe58a, #ffb300); }
.tour-pod.p2 .tour-pod-block { height: 80px; background: linear-gradient(180deg, #f3f7fb, #a9b7c8); }
.tour-pod.p3 .tour-pod-block { height: 62px; background: linear-gradient(180deg, #f0b58a, #b86d35); }
.tour-final { text-align: center; padding: 18px 12px; border-radius: 18px; background: linear-gradient(160deg, rgba(255,201,74,.14), rgba(255,201,74,.04)); border: 1px solid rgba(255,201,74,.4); display: flex; flex-direction: column; gap: 6px; animation: tourIn .5s ease 1.6s both; }
.tour-final-label { font-size: .78rem; letter-spacing: 3px; color: #aab3d1; }
.tour-final-rank { font-size: 2.8rem; font-weight: 900; color: #ffd36a; text-shadow: 0 0 24px rgba(255,201,74,.45); font-variant-numeric: tabular-nums; }
.tour-final-sub { color: #dce1f0; }
.tour-final-sub b { color: #ffd36a; font-variant-numeric: tabular-nums; }
.tour-prize { margin-top: 6px; font-size: 0.9rem; color: #f2f2f2; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.tour-prize.gold { color: #ffd36a; font-weight: 700; }
.tour-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.tour-admin-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 6px 0; }
.tour-admin-qs { margin: 4px 0 10px; padding-left: 22px; font-size: 0.85rem; line-height: 1.7; }
@media (max-width: 380px) { .tour-opts.grid { grid-template-columns: 1fr; } .tour-prompt { padding: 26px 52px; font-size: 1.5rem; } .tour-prompt.en { font-size: 1.9rem; } }
@media (prefers-reduced-motion: reduce) {
    .tour-banner.live, .tour-lights::before, .tour-lights::after, .tour-leader, .tour-arrive, .tour-line, .tour-q.entering .tour-prompt, .tour-q.entering .tour-opt,
    .tour-pod, .tour-final, .tour-result, .tour-streak, .tour-count-big.beat, .tour-body.shake, .tour-opt.right, .tour-opt.picked { animation: none !important; }
}
html[data-fx="low"] .tour-lights { display: none; }
/* 新手第一步：選目標（onboarding.js） */
.ob-goal-sub { margin: 4px 0 14px; color: var(--text-sub); font-size: 0.9rem; line-height: 1.6; }
.ob-goal-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.ob-goal-btn { padding: 16px 10px; border-radius: 14px; border: 1px solid var(--border); background: color-mix(in srgb, var(--text-main) 5%, transparent); color: var(--text-main);
    font: inherit; font-size: 1rem; font-weight: 700; cursor: pointer; }
.ob-goal-btn:last-child { grid-column: 1 / -1; }
.ob-goal-btn:active { transform: scale(.98); }
.ob-goal-skip { display: block; margin: 14px auto 0; border: 0; background: transparent; color: var(--text-sub); font: inherit; font-size: 0.85rem; text-decoration: underline; cursor: pointer; }
/* 比賽畫面、翻譯畫面打開時：音樂球（flow-ball）和字靈先收起來，不要擋到選項 */
body.tour-open #flow-ball, body.tr-open #flow-ball,
body.tour-open .nav-pet, body.tour-open .nav-pet-ground-shadow, body.tr-open .nav-pet, body.tr-open .nav-pet-ground-shadow { display: none !important; }

/* 編輯單字簿：一次加入很多字（借用建立單字簿的匯入框，只留快速、手動） */
.edit-import { margin: 14px 0 6px; display: flex; flex-direction: column; align-items: flex-end; }
.edit-import #edit-import-host { width: 100%; }
.import-area.import-append, .import-section.import-append { margin-top: 10px; }
.import-append #import-mode-smart-btn, .import-append #import-mode-scan-btn, .import-append #qi-split-wrap,
.import-append #qi-ai-organize { display: none !important; }

/* 複習：看中文拼英文時的「聽發音」提示、同義字再想一個 */
.rv-hear.rv-hear-hint { border-color: rgba(0, 188, 212, 0.45); color: #7fdcea; background: rgba(0, 188, 212, 0.08); }
.rv-hear.rv-hear-hint::before { content: ''; display: inline-block; width: 0; height: 0; margin-right: 7px; border-style: solid; border-width: 5px 0 5px 8px; border-color: transparent transparent transparent currentColor; vertical-align: 0; }
.rv-hear-in { animation: rv-hear-in 0.35s cubic-bezier(.2, .9, .3, 1.2) both; }
@keyframes rv-hear-in { from { opacity: 0; transform: translateY(6px) scale(0.94); } to { opacity: 1; transform: none; } }
.rv-hint-pop { animation: rv-hint-pop 0.4s ease both; color: var(--warning); }
@keyframes rv-hint-pop { 0% { transform: scale(0.96); opacity: 0.4; } 60% { transform: scale(1.03); opacity: 1; } 100% { transform: none; } }
@media (prefers-reduced-motion: reduce) { .rv-hear-in, .rv-hint-pop { animation: none; } }

/* 效能：「降低特效」時所有毛玻璃都關掉（模糊是捲動卡頓最大的來源）；
   單字簿編輯頁的長清單，畫面外的字先不排版 */
html[data-fx="low"] *, html[data-fx="low"] *::before, html[data-fx="low"] *::after {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}
#word-list > .word-item { content-visibility: auto; contain-intrinsic-size: auto 76px; }

/* 綜合精通：學新字、過場時連擊倒數停住 */
.combo-frozen-note { display: none; margin: -2px 0 5px; color: var(--text-sub); font-size: 0.72rem; letter-spacing: 0.5px; }
#combo-container.combo-frozen .combo-frozen-note { display: block; animation: popScale 0.3s ease both; }
#combo-container.combo-frozen #combo-bar { opacity: 0.45; background: #b0bec5 !important; }
#combo-container.combo-frozen #combo-text { opacity: 0.75; }

/* 每日單字卡：學測級數拉條（最左邊是隨機） */
.dc-lvpick { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 6px 14px; border: 1px solid var(--border); border-radius: 24px; background: var(--card-bg); }
.dc-lvpick.hidden { display: none; }
.dc-lvpick-label { color: var(--text-sub); font-size: .82rem; }
.dc-lvpick input[type="range"] { width: 120px; margin: 0; accent-color: var(--warning, #f9c849); }
.dc-lvpick-value { min-width: 38px; color: var(--text-main); font-weight: 600; font-size: .9rem; text-align: center; }
/* 級數拉條自己一行，不跟範圍按鈕搶位置（按鈕維持原本的大小） */
.vocab-range .dc-lvpick { flex: 0 0 100%; max-width: 360px; justify-content: space-between; box-sizing: border-box; }
.vocab-range .dc-lvpick input[type="range"] { flex: 1; min-width: 90px; width: auto; }

/* 上方導覽列：按鈕永遠不被擠成直的；空間不夠時縮的是中間的標題文字（多的變成…） */
.nav-bar { gap: 10px; }
.nav-bar > button, .nav-bar > .btn-icon, .nav-bar-right > button, .nav-bar-right > .btn-icon { flex-shrink: 0; white-space: nowrap; }
.nav-bar-right { min-width: 0; flex-shrink: 1; }
.nav-bar-right > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 420px) {
    .nav-bar { gap: 6px; }
    .nav-bar-right { gap: 6px; }
    .nav-bar-right > span { letter-spacing: 0 !important; font-size: 0.95rem; }
    #mastery-room-btn { margin-right: 0 !important; padding: 4px 10px !important; }
    .nav-bar .btn-quit, .nav-bar-right .export-quiz-btn { padding-left: 12px !important; padding-right: 12px !important; }
    .nav-bar-right .tip-help { margin-left: 0 !important; }
}

/* 錦標賽公布答案：「幾人」放到右下角，不跟選項文字搶寬度（手機上長的中文意思會被擠成一個字一行） */
.tour-q.revealed .tour-opt { padding-bottom: 26px; }
.tour-q.revealed .tour-pct { position: absolute; right: 12px; bottom: 6px; font-size: 0.72rem; }

/* ── 詞性顏色（pos-meanings.js）：每個中文意思前面一個詞性色塊，中文字帶淡淡的同色 ──
   顏色一定配文字標籤（色弱的人只靠顏色分不出來）；設定裡關掉時全部回到單色 */
:root {
    --pos-n: #6aa8ff; --pos-v: #ff7a59; --pos-adj: #4cd18a; --pos-adv: #b38cff;
    --pos-prep: #3fd0d6; --pos-conj: #ff7eb6; --pos-phr: #f0c040; --pos-pron: #9fb2cf; --pos-x: #8c8c8c;
}
.pos-c-n { --pc: var(--pos-n); } .pos-c-v { --pc: var(--pos-v); } .pos-c-adj { --pc: var(--pos-adj); }
.pos-c-adv { --pc: var(--pos-adv); } .pos-c-prep { --pc: var(--pos-prep); } .pos-c-conj { --pc: var(--pos-conj); }
.pos-c-phr { --pc: var(--pos-phr); } .pos-c-pron { --pc: var(--pos-pron); } .pos-c-x { --pc: var(--pos-x); }
.pos-pill { display: inline-flex; align-items: center; flex: none; padding: 1px 7px; border-radius: 6px; font-size: .72em; font-weight: 700;
    line-height: 1.5; letter-spacing: .02em; color: var(--pc, var(--pos-x)); background: color-mix(in srgb, var(--pc, var(--pos-x)) 18%, transparent);
    border: 1px solid color-mix(in srgb, var(--pc, var(--pos-x)) 40%, transparent); vertical-align: 1px; }
.pos-gloss { display: inline-flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; }
.pos-part { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; min-width: 0; max-width: 100%; }
.pos-part .pos-zh { color: color-mix(in srgb, var(--pc, var(--pos-x)) 32%, var(--text-main)); }
.pos-part.pos-c-x .pos-zh { color: var(--text-sub); }
.word-unsorted { display: inline-block; margin-top: 4px; font-size: .74rem; color: var(--text-sub); }
html[data-pos-color="off"] .pos-pill { color: var(--text-sub); background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.14); }
html[data-pos-color="off"] .pos-part .pos-zh { color: inherit; }

/* 匯入預覽：每個字的意思依詞性分組成小方塊（亮的會匯入），最上面一排整批開關詞性 */
.qi-means { display: grid; gap: 5px; margin-top: 5px; }
.qi-mg { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.qi-mg.off { opacity: .38; }
.qi-mc { font: inherit; font-size: .8rem; line-height: 1.3; padding: 3px 9px; border-radius: 999px; cursor: pointer; color: var(--text-sub);
    background: transparent; border: 1px dashed color-mix(in srgb, var(--pc, var(--pos-x)) 45%, transparent); }
.qi-mc.on { color: color-mix(in srgb, var(--pc, var(--pos-x)) 30%, var(--text-main)); border-style: solid;
    background: color-mix(in srgb, var(--pc, var(--pos-x)) 16%, transparent); }
.qi-mc.unsorted { border-style: dashed; color: var(--text-main); }
.qi-posbar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 8px 0 4px; }
.qi-posbar-label { font-size: .78rem; color: var(--text-sub); margin-right: 2px; }
.qi-pb { font: inherit; font-size: .78rem; padding: 4px 10px; border-radius: 999px; cursor: pointer; color: var(--text-sub); background: transparent;
    border: 1px solid rgba(255,255,255,.14); }
.qi-pb.on { color: var(--pc); border-color: color-mix(in srgb, var(--pc) 55%, transparent); background: color-mix(in srgb, var(--pc) 14%, transparent); font-weight: 700; }
.pos-picker { margin: -2px 0 6px; padding: 12px; border-radius: 12px; border: 1px solid rgba(255,255,255,.16); background: var(--surface-strong, #1c1f27); }
.pos-picker-title { font-size: .85rem; margin-bottom: 8px; color: var(--text-main); }
.pos-picker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 6px; }
.pos-pk { font: inherit; font-size: .8rem; padding: 8px 6px; border-radius: 10px; cursor: pointer; color: var(--pc); font-weight: 700;
    background: color-mix(in srgb, var(--pc) 14%, transparent); border: 1px solid color-mix(in srgb, var(--pc) 45%, transparent); }
.pos-pk.dim { opacity: .45; font-weight: 500; }
.pos-picker-acts { display: flex; justify-content: space-between; margin-top: 8px; }
html[data-pos-color="off"] .qi-mc.on, html[data-pos-color="off"] .qi-pb.on, html[data-pos-color="off"] .pos-pk { color: var(--text-main); background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.2); }
.pos-picker-hint { font-size: .76rem; color: var(--text-sub); margin: -4px 0 8px; line-height: 1.5; }
.pos-pk.current { outline: 2px solid var(--pc); outline-offset: 1px; }
.pos-picker-link { font: inherit; font-size: .8rem; background: none; border: none; color: var(--text-sub); text-decoration: underline; cursor: pointer; padding: 4px 2px; }
.pos-picker-acts { gap: 10px; }
/* 意思很多時：每個意思整個換行，不會被擠成一個字一行（中文的最小寬度是一個字） */
.pos-zh-btn { font: inherit; background: none; border: none; padding: 0; cursor: pointer; color: inherit; flex: 0 0 auto; max-width: 100%; text-align: left; }
.pos-part .pos-zh-btn { color: color-mix(in srgb, var(--pc, var(--pos-x)) 32%, var(--text-main)); }
.pos-zh-btn.unsorted { color: var(--text-main); text-decoration: underline dotted; text-underline-offset: 3px; }
html[data-pos-color="off"] .pos-part .pos-zh-btn { color: inherit; }

/* 詞性：單字簿上方「整理詞性」提示列與一次一張卡的整理畫面 */
.pos-sort-banner { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 6px 0 10px; padding: 10px 12px;
    border-radius: 12px; border: 1px dashed rgba(255,255,255,.22); background: rgba(255,255,255,.04); font-size: .85rem; color: var(--text-sub); }
.pos-sort-banner .btn { margin: 0; width: auto; padding: 6px 14px; }
.pos-queue { width: min(420px, calc(100vw - 32px)); padding: 22px 20px 18px; border-radius: 20px; border: 1px solid rgba(255,255,255,.16);
    background: #171b24; color: var(--text-main); text-align: center; box-shadow: 0 24px 60px rgba(0,0,0,.55); }
.pos-queue::backdrop { background: rgba(0,0,0,.6); }
.pq-progress { font-size: .78rem; color: var(--text-sub); letter-spacing: .05em; }
.pq-word { font-size: 1.7rem; font-weight: 800; margin-top: 6px; letter-spacing: .02em; }
.pq-zh { font-size: 1.3rem; margin-top: 6px; }
.pq-hint { min-height: 1.4em; margin: 8px 0 14px; font-size: .8rem; color: var(--text-sub); line-height: 1.5; }
.pq-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.pq-pk { position: relative; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 14px 8px; border-radius: 14px; cursor: pointer;
    font: inherit; color: var(--pc); background: color-mix(in srgb, var(--pc) 14%, transparent); border: 1px solid color-mix(in srgb, var(--pc) 45%, transparent); }
.pq-pk b { font-size: 1rem; } .pq-pk span { font-size: .85rem; color: var(--text-main); }
.pq-pk small { position: absolute; left: 9px; top: 6px; font-size: .65rem; color: var(--text-sub); }
.pq-pk.dim { opacity: .45; }
.pq-acts { display: flex; justify-content: center; gap: 10px; margin-top: 14px; }
.pq-acts .btn { margin: 0; width: auto; }
.pq-title { font-size: 1.2rem; font-weight: 800; margin-bottom: 8px; }
.pq-done { color: var(--text-sub); margin-bottom: 14px; }
html[data-pos-color="off"] .pq-pk { color: var(--text-main); background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.2); }
.pos-queue:focus, .pos-queue:focus-visible { outline: none; }

/* 詞性：拼字題的詞性標籤、選擇題依詞性上色、複習卡的詞性 */
.pos-pill-q { font-size: .55em; margin-left: 8px; vertical-align: middle; }
.pos-tint { color: color-mix(in srgb, var(--pc, var(--pos-x)) 50%, currentColor); }
.pos-tint.pos-c-x { color: inherit; }
.rv-pos.rv-pos-tinted { color: var(--pc); font-weight: 700; }
html[data-pos-color="off"] .pos-tint { color: inherit; }
html[data-pos-color="off"] .rv-pos.rv-pos-tinted { color: var(--text-sub); }

/* 點字小視窗：在這句的意思、詳細字義、AI 解釋 */
.wp-tip-pos[class*="pos-c-"]:not(.pos-c-x) { color: var(--pc); background: color-mix(in srgb, var(--pc) 16%, transparent); font-style: normal; }
html[data-pos-color="off"] .wp-tip-pos[class*="pos-c-"] { color: #ffc46b; background: rgba(255, 183, 77, .16); }
.wp-here { margin: 2px 0 8px; padding: 8px 10px; border-radius: 10px; background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.1); }
.wp-here-label { display: block; font-size: .7rem; color: var(--text-sub); letter-spacing: .08em; margin-bottom: 4px; }
.wp-here-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.wp-here-zh { font-size: 1rem; }
.wp-here-src { font-size: .65rem; padding: 0 6px; border-radius: 6px; border: 1px solid rgba(179,136,255,.5); color: #c9b2ff; }
.wp-here-note { margin-top: 5px; font-size: .78rem; color: var(--text-sub); line-height: 1.5; }
.wp-here-syn { margin-top: 4px; font-size: .78rem; color: var(--text-main); }
.wp-here-wait { font-size: .78rem; color: var(--text-sub); line-height: 1.5; }
.wp-tip-hit { color: var(--text-main); text-decoration: underline; text-underline-offset: 3px; }
.wp-tip-sub { margin: 8px 0 3px; font-size: .7rem; color: var(--text-sub); letter-spacing: .06em; }
.wp-tip-tools { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 8px; }
.wp-tip-link { font: inherit; font-size: .8rem; background: none; border: none; padding: 2px 0; color: #9fc6ff; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.wp-tip-link.wp-tip-ai { color: #c9b2ff; }
.wp-tip-link:disabled { opacity: .6; cursor: default; }
