/* ═══════════════════════════════════════════════════════════════════
   Ladder Lessons · ll-skin.css　　品牌層，最後載入
   100% 對齊 06_LADDER_LESSONS_STYLE_GUIDE.html 同 games/index.html
   只改外觀，唔碰 app.js 任何邏輯同 class 名。 2026-08-03
   ═══════════════════════════════════════════════════════════════════ */
:root{
  --coral:#FF6B6B; --coral-dark:#FF8E53; --coral-pale:rgba(255,107,107,.12);
  --teal:#4ECDC4; --teal-dark:#44A08D; --teal-pale:rgba(78,205,196,.14);
  --yellow:#FFE66D; --yellow-deep:#FFC93C;
  --ink:#2C3E50; --ink-soft:#5A6C7D;
  --cream:#FFF9F0; --cream-deep:#F6EDE0;
  --success:#22C55E; --warn:#F59E0B; --error:#E74C3C;
  --line:#E5E7EB; --muted:#9CA3AF;
  --purple-1:#667EEA;
  /* ⚠️ 無障礙：珊瑚 #FF6B6B 配白字得 2.78:1，連 AA 大字 3:1 都過唔到。
     規矩兩條 —— 珊瑚做「底」時文字用 --ink；珊瑚做「文字」時用 --coral-ink。
     --coral-ink 同原色同一個色相（H=0°），對白 4.77:1、對 cream 4.55:1。
     2026-08-03 全庫對比度審計。*/
  --coral-ink:#C9453F;
  /* 同 --coral-ink 一樣嘅道理：--error #E74C3C 做實色底時，白字得 3.82:1、
     墨字得 2.87:1，兩邊都唔夠。深一級（同色相 H≈6°）白字有 5.67:1。
     只用喺「實色 danger 掣」；--error 本身照舊做邊框／文字色。2026-08-04 */
  --error-deep:#B93A2B;
  --r-rung:12px; --r-sm:8px; --r-md:16px; --r-lg:24px; --r-pill:9999px;
  --sh-rung:0 4px 0 rgba(44,62,80,.14);
  --sh-lift:0 14px 34px rgba(44,62,80,.14);
  --ff-head:'Fredoka','Noto Sans HK','PingFang HK','Microsoft JhengHei',sans-serif;
  --ff-body:'Nunito','Noto Sans HK','PingFang HK','Microsoft JhengHei',sans-serif;
}

body{font-family:var(--ff-body);color:var(--ink);background:var(--cream);line-height:1.65}
h1,h2,h3,h4,h5,h6{font-family:var(--ff-head);font-weight:700;letter-spacing:.02em;color:var(--ink)}

/* ── HERO ── */
#group-title{font-size:clamp(28px,5.5vw,42px);line-height:1.2;margin-bottom:10px}
#group-description{font-size:clamp(15px,2.5vw,18px);color:var(--ink-soft);font-weight:600;
  max-width:56ch;margin-bottom:28px}

/* ── 「開始冒險」主 CTA ── */
#startAdventureBtn{
  font-family:var(--ff-head);font-weight:700;font-size:18px;letter-spacing:.02em;
  padding:14px 34px;border:3px solid var(--ink);border-radius:var(--r-pill);
  background:linear-gradient(135deg,#FF6B6B 0%,#FF8E53 100%);color:var(--ink);
  box-shadow:var(--sh-rung);transition:transform .15s,box-shadow .15s;margin-bottom:28px}
#startAdventureBtn:hover{transform:translateY(-3px);box-shadow:var(--sh-lift);color:var(--ink)}

/* ── 組別卡 ── */
/* style.css 387 行有 #groupList{display:flex;flex-wrap:wrap}，同specificity，
   靠載入次序贏。但 style.css 全檔有 98 個 !important，穩陣起見直接標死。*/
/* desktop 固定 3 欄（照舊版排得公整）。auto-fill 會跟卡闊度變成 4／3／2 欄
   參差不齊 —— 第 16 組有 5 個音素，卡就闊過人哋。Shari 2026-08-03 指正。*/
/* ⚠️ 一定要 :not(.d-none)。app.js 撳入一組之後係用 classList.add("d-none")
   收埋個清單，但 #groupList（ID，1-0-0）加 !important 會蓋過 .d-none（0-1-0），
   結果入到組內個清單仲喺度。2026-08-03 修（我上一輪自己整出嚟嘅）。*/
#groupList:not(.d-none){display:grid!important;gap:16px;
  grid-template-columns:repeat(3,1fr);margin-inline:0}
#groupList.d-none{display:none!important}
#groupList>.col{width:auto!important;padding-inline:0;flex:none!important}

/* Basics / Advanced 分隔帶 —— 跨足成行，令 22 組睇落係兩段而唔係一條長梯 */
.se-stage-band{grid-column:1/-1;display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;
  margin:8px 0 2px;padding:10px 16px;border:3px solid var(--ink);border-radius:var(--r-pill);
  background:var(--cream-deep);box-shadow:var(--sh-rung)}
.se-stage-band b{font-family:var(--ff-head);font-weight:700;font-size:15px;
  letter-spacing:.10em;color:var(--coral-ink)}
.se-stage-band span{font-size:13.5px;font-weight:600;color:var(--ink-soft)}
#groupList.d-none .se-stage-band{display:none}

/* ⚠️ style.css 715 行仲留住 min-height:8.75rem（140px），744 行 media query
   仲有 7.5rem。嗰個係舊設計嘅遺物 —— 當時 header 係「圓形編號 + 標題」直向
   疊起嘅大色塊，先要撐高。而家改咗做橫向一行（編號 badge + 標題），
   140px 純粹係空氣，白白拉長成頁 24 張卡。
   同一行卡片嘅高度由 grid 嘅 stretch 拉齊，唔需要 min-height 幫手。
   標題保留 line-clamp:2，長標題（第 20 組 Magic E 家族…）唔會爆到第三行。
   （Shari 2026-08-04：「.se-gcard__head 不用那麼高，還需要 min height 嗎？」→ 唔需要）*/
.se-gcard__head{min-height:0!important}
@media (max-width:900px){.se-gcard__head{min-height:0!important}}
.se-gcard__title{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden}
/* ── 組別卡 · style guide §08 配方 ────────────────────────────────
   白底 · 3px ink 框 · --r-lg 圓角 · 硬陰影 · 頂 10px 階段色條。
   ⚠️ 唔用漸層鋪滿 header：漸層會蓋過 ink 框，成張卡冇咗品牌輪廓，
      而且 22 張卡疊埋一齊就變成一大片色。色條係一條線，唔係一塊底。
      （Shari 2026-08-04：「沒有 ink 邊框，太多漸層」）*/
.phonics-card,#groupList>.col>.phonics-card{
  --stage:var(--coral);
  background:#fff!important;border:3px solid var(--ink)!important;
  border-radius:var(--r-lg)!important;box-shadow:var(--sh-rung)!important;
  transition:transform .15s,box-shadow .15s;height:100%;overflow:hidden}
.phonics-card:hover,#groupList>.col>.phonics-card:hover{
  transform:translateY(-4px);box-shadow:var(--sh-lift)!important}
.phonics-card:focus-visible{outline:none;
  box-shadow:0 0 0 4px var(--yellow),var(--sh-rung)!important}
/* 頂 10px 階段色條 = §08「category 色條」*/
.se-gcard__bar{height:10px;background:var(--stage);flex:0 0 10px}
.se-gcard__head{display:flex;align-items:center;gap:12px;padding:14px 16px 12px!important;
  background:#fff!important;border-bottom:3px solid var(--cream-deep)!important;
  border-radius:0!important;text-align:left!important}
/* 編號 badge —— 佢係組別最主要嘅識別，唔靠顏色 */
.se-gcard__num{flex:0 0 42px;width:42px;height:42px;display:grid;place-items:center;
  font-family:var(--ff-head);font-weight:700;font-size:20px;color:var(--ink);
  background:var(--stage);border:3px solid var(--ink);border-radius:var(--r-rung)}
.se-gcard__title{font-family:var(--ff-head);font-weight:600;font-size:16px;
  line-height:1.3;color:var(--ink)!important;margin:0}
.se-gcard__letters{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;
  padding:14px 16px!important;background:#fff!important;
  font-family:var(--ff-head);font-weight:700;flex:1;align-items:center}

/* ── 音素卡（大字面）── */
.se-face{border:3px solid var(--ink);border-radius:var(--r-md);background:#fff;
  box-shadow:var(--sh-rung)}
.se-face__letter{font-family:var(--ff-head);font-weight:700;color:var(--ink)}
.se-face__ipa{font-family:var(--ff-body);font-weight:800;color:var(--coral-ink)}

/* ── 掣 ── */
.btn{font-family:var(--ff-head);font-weight:600;letter-spacing:.01em;
  border-radius:var(--r-pill);border:3px solid var(--ink);
  box-shadow:var(--sh-rung);transition:transform .15s,box-shadow .15s}
.btn:hover{transform:translateY(-2px)}
.btn:active:not(.disabled){transform:translateY(1px);box-shadow:0 1px 0 rgba(44,62,80,.14)}
.btn:focus-visible{outline:none;box-shadow:0 0 0 4px var(--coral-pale),var(--sh-rung)}
/* ⚠️⚠️ 全部要 !important。style.css 171 行寫住 color:#fff !important，
   我呢層唔加 !important 就永遠輸 —— 即係我之前寫嘅「珊瑚底用墨字」規矩
   喺 Ladder Phonics 從來冇生效過，成隻遊戲所有主掣一直都係白字落珊瑚
   2.78:1。對比度 script 有報，但我當咗係靜態分析嘅假陽性，冇追落去。
   2026-08-04 追返。教訓：見到 audit 報一條你以為已經修好嘅嘢，
   要去查 cascade，唔好假設自己贏咗。*/
.btn.btn-primary{background:var(--coral)!important;color:var(--ink)!important;
  border-color:var(--ink)!important}
.btn.btn-primary:hover:not(.disabled),.btn.btn-primary:focus:not(.disabled){
  background:var(--coral-dark)!important;border-color:var(--ink)!important;
  color:var(--ink)!important;box-shadow:var(--sh-lift)!important}
.btn.btn-primary:active:not(.disabled){background:var(--coral-dark)!important;
  border-color:var(--ink)!important;transform:translateY(4px);box-shadow:none!important}
.btn.btn-secondary{background:var(--teal)!important;color:var(--ink)!important;
  border-color:var(--ink)!important}
.btn.btn-secondary:hover:not(.disabled),.btn.btn-secondary:focus:not(.disabled){
  background:var(--teal-dark)!important;color:var(--ink)!important;
  border-color:var(--ink)!important;box-shadow:var(--sh-lift)!important}
.btn.btn-success{background:var(--success)!important;color:var(--ink)!important;
  border-color:var(--ink)!important}
.btn.btn-danger{background:var(--error-deep)!important;color:#fff!important;
  border-color:var(--ink)!important}
.btn.btn-danger:hover:not(.disabled),.btn.btn-danger:focus:not(.disabled){
  background:var(--error-deep)!important;color:#fff!important;
  border-color:var(--ink)!important;box-shadow:var(--sh-lift)!important}
.btn.btn-outline-primary,.btn.btn-outline-secondary,
.btn.btn-outline-success,.btn.btn-outline-danger{
  background:#fff!important;color:var(--ink)!important;border-color:var(--ink)!important}
.btn.btn-outline-primary:hover:not(.disabled),.btn.btn-outline-primary:focus:not(.disabled){
  background:var(--coral-pale)!important;color:var(--ink)!important;
  border-color:var(--ink)!important;box-shadow:var(--sh-rung)!important}
.btn.btn-outline-secondary:hover:not(.disabled),.btn.btn-outline-secondary:focus:not(.disabled){
  background:var(--teal-pale)!important;color:var(--ink)!important;
  border-color:var(--ink)!important;box-shadow:var(--sh-rung)!important}
.btn.btn-outline-danger:hover:not(.disabled),.btn.btn-outline-danger:focus:not(.disabled){
  background:rgba(231,76,60,.12)!important;color:var(--ink)!important;
  border-color:var(--ink)!important;box-shadow:var(--sh-rung)!important}
.btn.btn-outline-success:hover:not(.disabled),.btn.btn-outline-success:focus:not(.disabled){
  background:rgba(34,197,94,.13)!important;color:var(--ink)!important;
  border-color:var(--ink)!important;box-shadow:var(--sh-rung)!important}
/* style guide §07：所有掣最細 44×44 觸控目標 */
.btn{min-height:44px}

/* app.js 個 dropArea 有 class="text-muted"，字卡係佢個仔，色會被繼承拉到極淡。
   喺字卡度標死。（Shari 2026-08-03 報：「字色淡到看不到」）*/
.text-muted .letter-tile,.text-muted .spelling-letter,
.letter-tile,.spelling-letter,.letter-choice{color:var(--ink)!important}

/* ── 選字區（letter-choice）：細、白、安靜 ──
   佢係「選項」，唔應該搶。app.js 原本已經係 bg-white + border + shadow-sm。*/
.letter-choice,.letter-tile,.spelling-letter,#letterBank button{
  font-family:var(--ff-head);font-weight:700;
  border:2.5px solid var(--ink);border-radius:var(--r-rung);background:#fff;
  box-shadow:0 3px 0 rgba(44,62,80,.12)}
.letter-choice:hover{background:var(--cream-deep);transform:translateY(-2px)}

/* ── 已揀嘅字（letter-card）：大、實色、白字 ──
   小朋友要一眼睇到自己而家砌緊邊個字。同 letter-choice 差三樣：
   實色底 vs 白底、白字 vs 深字、4px 邊 + 大陰影 vs 2.5px。
   （app.js 本身已經畀咗 text-white / fs-1 / border-0，我上一輪一刀切
     全部拉成白底深字，兩者先會撞樣。2026-08-03 改返。）*/
.letter-card{
  font-family:var(--ff-head);font-weight:700!important;
  /* 白字落珊瑚 2.78:1 過唔到 AA；深墨字 3.96:1，78px 大字綽綽有餘 */
  color:var(--ink)!important;
  background:linear-gradient(135deg,#FF6B6B 0%,#FF8E53 100%)!important;
  border:4px solid var(--ink)!important;border-radius:18px!important;
  box-shadow:0 6px 0 rgba(44,62,80,.22)!important;
  min-width:78px;min-height:78px;
  text-shadow:0 2px 0 rgba(255,255,255,.35);
  letter-spacing:.02em;transition:transform .12s,box-shadow .12s}
.letter-card:hover{transform:translateY(-3px);box-shadow:0 9px 0 rgba(44,62,80,.22)!important}
.letter-card:active{transform:translateY(3px);box-shadow:0 3px 0 rgba(44,62,80,.22)!important}
/* 撳中嗰張再突出多一級 —— 用黃色，同珊瑚色明顯分得開 */
.letter-card.clicked{
  background:linear-gradient(135deg,#FFC93C 0%,#FFE66D 100%)!important;
  color:var(--ink)!important;text-shadow:none;
  transform:translateY(-4px) scale(1.06);
  box-shadow:0 10px 0 rgba(44,62,80,.22)!important}
@media (max-width:560px){.letter-card{min-width:62px;min-height:62px}}
.drop-placeholder{border:3px dashed var(--ink);border-radius:var(--r-rung);
  background:var(--cream-deep)}
/* 音素 chip —— 白底墨字墨框，同 letter-choice 一套語言。
   之前用 --color-*-100 底 + --color-*-600 字，逐張卡都唔同色。*/
.se-chip{font-family:var(--ff-head);font-weight:700;font-size:24px;
  min-width:44px;min-height:44px;padding:5px;
  display:inline-flex;align-items:center;justify-content:center;
  border:2.5px solid var(--ink);border-radius:var(--r-rung);
  background:var(--cream);color:var(--ink);cursor:pointer;line-height:1.1;
  box-shadow:0 2px 0 rgba(44,62,80,.14);transition:transform .1s,background .1s}
/* ── chip 一行放得晒，但唔好縮得滯 ──────────────────────────────
   ⚠️ 我上一輪為咗「一行放得晒」寫咗 min-width:0 + flex-shrink + 固定收字，
      結果第 3 組（5 個短音素）明明張卡仲有大把位，啲 chip 都縮到窄過條 border。
      （Shari 2026-08-04：「太窄了，明明卡片的 width 還有很多空間嘛？」）
      根因：我按「chip 數量」硬收，冇睇實際內容闊度。ck 兩個字母同
      a_e 三個字母食嘅位差好遠，一刀切就一定有一邊唔啱。

   而家：min-width:max-content —— chip 永遠唔會縮到切字或者迫窄，
   字級改用 clamp 跟 viewport 走，窄螢幕先自動細啲。
   真係塞唔落（第 20 組 5 × 3 字母 + 細螢幕）就准佢 wrap，
   總好過五個都縮到睇唔清。*/
.se-gcard__letters{flex-wrap:wrap!important;gap:7px!important;min-width:0}
.se-chip{flex:0 0 auto;min-width:max-content;white-space:nowrap;
  padding-inline:11px}
/* 4 個或以下 —— 一定夠位，用足 24px */
.se-gcard__letters:has(.se-chip:nth-child(5)){gap:6px!important}
.se-gcard__letters:has(.se-chip:nth-child(5)) .se-chip{
  font-size:clamp(17px,1.75vw,24px);padding-inline:9px}
.se-gcard__letters:has(.se-chip:nth-child(6)) .se-chip{
  font-size:clamp(15px,1.5vw,21px);padding-inline:7px}
.se-chip:hover{background:var(--stage);transform:translateY(-2px)}
.se-chip:active{transform:translateY(2px);box-shadow:none}

/* ── 狀態色，對齊 SSOT ── */
.bg-primary{background:var(--coral)!important}
.bg-secondary{background:var(--teal)!important}
.bg-success{background:var(--success)!important}
.bg-danger{background:var(--error)!important}
.bg-primary-pale{background:var(--coral-pale)!important}
.bg-secondary-pale{background:var(--teal-pale)!important}
.bg-success-pale{background:rgba(34,197,94,.13)!important}
.bg-danger-pale{background:rgba(231,76,60,.12)!important}
.border-primary{border-color:var(--coral)!important}
.border-secondary{border-color:var(--teal)!important}
.border-success{border-color:var(--success)!important}
.border-danger{border-color:var(--error)!important}
.text-primary{color:var(--coral-ink)!important}
.text-muted{color:var(--ink-soft)!important}
.text-danger{color:var(--error)!important}

/* ── 錄音 ── */
.recording-timer{font-family:var(--ff-head);font-weight:700;color:var(--error)}
.recording-dot{background:var(--error)}

.card{border:3px solid var(--ink);border-radius:var(--r-md);box-shadow:var(--sh-rung);
  background:#fff}
.phonics-image{border-radius:var(--r-rung)}

/* pill 喺左上角浮住（fixed，x 大約 10–54px）。
   ⚠️ 唔可以無條件拆走 padding-top —— 條 pill 唔佔文檔空間，
      窄螢幕嗰陣 .container 貼到最左，個標題就會畀 pill 蓋住。
   幾時先安全：.container 封頂 1140px 且置中，左邊空隙 = (100vw - 1140) / 2。
   要大過 62px（pill 闊 + 少少罅），即係 100vw > 1264px。
   所以 1265px 以上先拆 —— 呢個亦係 Shari desktop 見到嘅情況。
   （Shari 2026-08-04：「.container.my-5 個 padding-top:64px 可以拿掉」）*/
.container.my-5{padding-top:64px}
@media (min-width:1265px){.container.my-5{padding-top:0}}

@media (max-width:900px){#groupList:not(.d-none){grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){
  #groupList:not(.d-none){grid-template-columns:1fr}
  .container.my-5{padding-top:58px}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}

/* ═══════════════════════════════════════════════════════════════════
   2026-08-04 · Shari 真機 review 修正
   ═══════════════════════════════════════════════════════════════════ */

/* ── 1. 覆蓋 style.css 成套 Bootstrap／Tailwind 色票 ──
   style.css 頂部有一大堆 --bs-* / --color-* token（indigo、pink、
   teal-500 之類），完全唔喺 SSOT 入面。冇必要逐個 hex 去改 style.css
   （21KB、98 個 !important），直接喺呢層重新定義啲變數就一次過對齊。
   Shari 2026-08-03：「感覺要換掉這堆色彩，因為不符合 style guide」*/
:root{
  --bs-primary:var(--coral);          --bs-primary-hover:var(--coral-dark);
  --bs-secondary:var(--teal);         --bs-secondary-hover:var(--teal-dark);
  --bs-success:var(--success);        --bs-danger:var(--error);
  --bs-warning:var(--yellow-deep);    --bs-info:var(--purple-1);
  --bs-light:var(--cream-deep);       --bs-dark:var(--ink);

  --color-bg-surface:var(--cream);    --color-bg-elevated:#fff;
  --color-text-heading:var(--ink);    --color-text-body:var(--ink);
  --color-text-muted:var(--ink-soft); --color-border-default:var(--ink);

  /* 色階全部指返 SSOT。冇對應嘅（indigo-400 之類）就用最近嗰隻品牌色，
     寧願少啲層次，都好過出現唔屬於品牌嘅顏色。*/
  --color-indigo-100:var(--coral-pale); --color-indigo-200:var(--coral-pale);
  --color-indigo-300:var(--coral);      --color-indigo-400:var(--coral);
  --color-indigo-500:var(--coral);      --color-indigo-600:var(--coral-ink);
  --color-indigo-700:var(--coral-ink);
  --color-pink-100:var(--coral-pale);   --color-pink-200:var(--coral-pale);
  --color-pink-300:var(--coral);        --color-pink-400:var(--coral);
  --color-pink-500:var(--coral);        --color-pink-600:var(--coral-ink);
  --color-pink-700:var(--coral-ink);
  --color-blue-100:var(--teal-pale);    --color-blue-200:var(--teal-pale);
  --color-blue-300:var(--teal);         --color-blue-400:var(--teal);
  --color-blue-500:var(--teal);         --color-blue-600:var(--teal-dark);
  --color-blue-700:var(--teal-dark);
  --color-teal-100:var(--teal-pale);    --color-teal-200:var(--teal-pale);
  --color-teal-300:var(--teal);         --color-teal-400:var(--teal);
  --color-teal-500:var(--teal);         --color-teal-600:var(--teal-dark);
  --color-teal-700:var(--teal-dark);
  --color-purple-100:var(--coral-pale); --color-purple-200:var(--coral-pale);
  --color-purple-300:var(--purple-1);   --color-purple-400:var(--purple-1);
  --color-purple-500:var(--purple-1);   --color-purple-600:var(--purple-1);
  --color-purple-700:var(--purple-1);
  --color-orange-100:var(--cream-deep); --color-orange-200:var(--cream-deep);
  --color-orange-300:var(--coral-dark); --color-orange-400:var(--coral-dark);
  --color-orange-500:var(--coral-dark); --color-orange-600:var(--coral-ink);
  --color-orange-700:var(--coral-ink);
  --color-yellow-100:var(--cream-deep); --color-yellow-200:var(--yellow);
  --color-yellow-300:var(--yellow);     --color-yellow-400:var(--yellow-deep);
  --color-yellow-500:var(--yellow-deep);--color-yellow-600:var(--yellow-deep);
  --color-yellow-700:var(--ink);
  --color-green-100:rgba(34,197,94,.13);--color-green-200:rgba(34,197,94,.13);
  --color-green-300:var(--success);     --color-green-400:var(--success);
  --color-green-500:var(--success);     --color-green-600:#15803D;
  --color-green-700:#15803D;
  --color-red-100:rgba(231,76,60,.12);  --color-red-200:rgba(231,76,60,.12);
  --color-red-300:var(--error);         --color-red-400:var(--error);
  --color-red-500:var(--error);         --color-red-600:var(--error);
  --color-red-700:var(--error);
  --color-gray-50:var(--cream);   --color-gray-100:var(--cream-deep);
  --color-gray-200:var(--line);   --color-gray-300:var(--line);
  --color-gray-400:var(--muted);  --color-gray-500:var(--ink-soft);
  --color-gray-600:var(--ink-soft);--color-gray-700:var(--ink);
  --color-gray-800:var(--ink);    --color-gray-900:var(--ink);
}

/* ── 2. .text-primary 用墨色 ──
   珊瑚做文字太搶，而且落白底得 2.78:1。Shari：「用 ink #2C3E50 更好」*/
.text-primary{color:var(--ink)!important}

/* ── 3.（已撤回）字母配對遊戲壓縮 ──
   ⚠️ 呢度本來有一組「壓扁卡片」規則：.card{font-size:.92em}、
      :nth-child(n+5){font-size:.84em}、.phonics-image{max-height:2.2em}。
      目的係硬塞落 780px。結果：
        · font-size 一縮，SVG 用 em 度大細，圖畫跟住縮到得原本三分一
        · 兩欄各自高度唔同，同一個 max-height 就切走咗左欄最後一張
      Shari 2026-08-04：「連線遊戲排版走位嚴重，圖畫也變超小」——
      全部係我加出嚟嘅。撤回，改為喺下面 §16 用正路方法重做。
      教訓：唔好用 font-size 做 layout 壓縮，佢會拖埋所有 em 單位落水。*/

/* ── 4. letter-card 太長要縮，唔可以斷行 ──
   拼字區嗰行大字卡，字一長就 wrap 落第二行，睇落似兩個字。
   用 flex-wrap:nowrap + 跟數量收窄，永遠保持一行。*/
#dropArea,[class*="d-flex"][class*="flex-wrap"]:has(> .letter-card){flex-wrap:nowrap!important}
.letter-card{flex:0 1 auto;min-width:clamp(38px,7vw,78px)!important;
  min-height:clamp(38px,7vw,78px)!important;font-size:clamp(20px,4.4vw,40px)!important;
  margin:2px!important}

/* ── 5. letter-choice 排成細鍵盤 ──
   窄啲、密啲，一行放多幾個。除咗拖，撳一下都可以加入去（app.js 已經
   綁咗 click，呢度只係令佢睇落似掣）。*/
#letterBank,[class*="letter-bank"],.letter-choice{}
.letter-choice{padding:5px 11px!important;min-width:2.1em;font-size:1.05em!important;
  margin:3px!important;line-height:1.15;cursor:pointer}
.letter-choice:active{transform:translateY(2px);box-shadow:0 1px 0 rgba(44,62,80,.12)}

/* ── 6. 底部三個掣要對齊 ──
   app.js 用 .row + .col-auto 排「返回首頁／上一關／下一關」，
   但 .btn-link 冇對齊基線，三個掣高度唔同就會參差。*/
/* ⚠️ 唔可以用 justify-content:space-between。最後一組（第 24 組）冇「下一關」，
   space-between 就會將「上一關」推去右邊 —— 但返後嘅掣一路都喺左邊，
   位置跳咗學生會搵唔到。（Shari 2026-08-04）
   改用 flex-start，靠右嘅事交返畀 app.js 個 .ms-auto（只有下一關先有）。*/
#content .row.mt-4{align-items:center;gap:8px;justify-content:flex-start;flex-wrap:wrap}
#content .row.mt-4 .col-auto{display:flex;align-items:center;padding-inline:0}
#content .row.mt-4 .col-auto.ms-auto{margin-left:auto!important}
.btn.btn-link,#topBackBtn{display:inline-flex;align-items:center;gap:6px;
  font-family:var(--ff-head);font-weight:600;font-size:14.5px;
  padding:9px 18px;border:2.5px solid var(--ink);border-radius:var(--r-pill);
  background:#fff;color:var(--ink);text-decoration:none;
  box-shadow:var(--sh-rung);line-height:1}
.btn.btn-link:hover{background:var(--cream-deep);transform:translateY(-2px)}

/* ── 7. 第 22 組配色 ──
   我加第 22 組時用咗 "purple"／"blue"／"green" 做 color 值，但 style.css
   只認得舊嗰套色名，所以出嚟亂晒。統一交返畀品牌色處理。*/
.se-face,.phonics-card .card{background:#fff!important}
.se-face__letter{color:var(--ink)!important}
.se-face__ipa{color:var(--coral-ink)!important}

/* ═══ 2026-08-04 · 第二輪真機修正 ═══════════════════════════════ */

/* ── 8. 音素卡最多 4 個一行，5／6 個要平均分兩行 ──
   第 22 組有 6 個，原本 auto-fit 排成 5 + 1，最尾嗰張孤零零。
   :has() 數子元素，直接指定欄數 —— 每行總闊 100%，唔會參差。
   Shari 2026-08-04：「5 個 → 3+2，6 個 → 3+3」*/
/* ⚠️⚠️ 一定要 minmax(0,1fr)，唔可以淨係寫 1fr。
   1fr 嘅實際定義係 minmax(auto,1fr) —— 個 auto 下限 = 內容嘅 min-content 闊度。
   我加咗 .se-recgroup{flex-wrap:nowrap} 之後，「錄我把聲／停／聽返」一行嘅
   min-content 闊過 1/4 行，grid 就被撐爆，最右邊嗰張卡標出容器外。
   （Shari 2026-08-04：「4 個一行的話卡片爆格到右手邊外面」）
   minmax(0,1fr) 將下限拉返做 0，內容就會乖乖縮。*/
.se-phonics-grid{grid-template-columns:repeat(4,minmax(0,1fr))!important;
  max-width:100%;overflow:visible}
.se-phonics-cell{min-width:0}
.se-phonics-cell>.card{min-width:0;max-width:100%}
.se-phonics-grid:has(>:nth-child(1)):not(:has(>:nth-child(2))){grid-template-columns:minmax(0,1fr)!important}
.se-phonics-grid:has(>:nth-child(2)):not(:has(>:nth-child(3))){grid-template-columns:repeat(2,minmax(0,1fr))!important}
.se-phonics-grid:has(>:nth-child(3)):not(:has(>:nth-child(4))){grid-template-columns:repeat(3,minmax(0,1fr))!important}
/* ⚠️ 4 個音素本來跌落預設嘅 4 欄 —— 每張卡只得畫面四分一闊，
   但入面個錄音掣組（「錄我把聲｜停｜聽返」）係 min-width:max-content，
   縮唔細，所以直接頂爆卡片左右兩邊。
   中招嘅係第 7（ai/ay, j, oa）、13（ou/ow, oi, ue）、15（wh, ph, kn, wr）、
   21（un-, re-, pre-, dis-）組。（Shari 2026-08-05）
   4 個改 2×2 —— 一半闊度，錄音掣鬆鬆哋。 */
.se-phonics-grid:has(>:nth-child(4)):not(:has(>:nth-child(5))){
  grid-template-columns:repeat(2,minmax(0,1fr))!important}
/* 5 個同 6 個都用 3 欄 → 5 變 3+2、6 變 3+3 */
.se-phonics-grid:has(>:nth-child(5)):not(:has(>:nth-child(7))){
  grid-template-columns:repeat(3,minmax(0,1fr))!important}
@media (max-width:820px){
  .se-phonics-grid,.se-phonics-grid:has(>:nth-child(5)):not(:has(>:nth-child(7)))
    {grid-template-columns:repeat(2,minmax(0,1fr))!important}
}
@media (max-width:520px){
  .se-phonics-grid,.se-phonics-grid:has(>:nth-child(5)):not(:has(>:nth-child(7)))
    {grid-template-columns:minmax(0,1fr)!important}
}
/* ⚠️ 上面幾條 :has() 規則帶 !important 而且排喺 media query 之後 —— 
   純粹靠 media query 蓋唔到（同樣 !important，後面嗰個贏）。
   所以要喺呢度用「同樣嘅 :has() selector + media query」再寫一次，
   特異度先夠高。手機一排一張 —— 音素卡入面有大字、聽發音掣、
   三個錄音掣、嘴型提示，擠兩三張落 620px 就每樣都睇唔清。
   （Shari 2026-08-04：「發音練習 card 每排一張」）*/
@media (max-width:767.98px){
  .se-phonics-grid,
  .se-phonics-grid:has(>:nth-child(1)):not(:has(>:nth-child(2))),
  .se-phonics-grid:has(>:nth-child(2)):not(:has(>:nth-child(3))),
  .se-phonics-grid:has(>:nth-child(3)):not(:has(>:nth-child(4))),
  .se-phonics-grid:has(>:nth-child(5)):not(:has(>:nth-child(7)))
    {grid-template-columns:minmax(0,1fr)!important;gap:14px!important}
  /* 一排一張之後，卡入面可以橫向排得鬆手啲 */
  .card.se-pcard{padding:18px 16px 16px!important}
  .se-face{min-height:0!important}
  .mt-4.text-center p{margin-bottom:2px}
}

/* ── 9.（已撤回）配對遊戲 780px 捲動 ──
   overflow:auto 令兩欄底部畀切走，左欄見到 5 張、右欄見到 6 張 ——
   睇落似漏咗一張，其實係捲走咗。而呢個遊戲最緊要係「兩邊同時見到」，
   加捲動 = 直接打爛佢個 core loop。撤回，改用 §16 嘅自適應高度。*/

/* ── 10. 黃色組別 WCAG ──
   第 8／18 組頭部係黃／金底，原本白字得 1.2:1。改用墨字（7.15:1）。
   同時：入到組內原本完全冇咗組別顏色 —— 加返一條色帶喺標題底，
   令學生知道自己仍然喺同一組。*/
.se-gcard__head{color:var(--ink)!important}
.se-gcard__head h3,.se-gcard__head *{color:var(--ink)!important}
#group-title{border-bottom:6px solid var(--yellow-deep);padding-bottom:10px;
  display:inline-block}

/* ── 11. letter-card 唔可以超出拼字格 ──
   dropArea 有 min-height:144px 但冇 max-width 限制內容，長字就會迫爆。
   用 overflow:hidden + 內容自動縮。*/
#content .bborder,[class*="border-dashed"]{overflow:hidden;
  display:flex!important;flex-wrap:nowrap!important;
  align-items:center;justify-content:center;padding:10px!important}
[class*="border-dashed"] .letter-card{
  flex:0 1 auto;min-width:0!important;
  width:clamp(30px,calc((100% - 24px) / 12),74px);
  height:clamp(30px,calc((100% - 24px) / 12),74px);
  font-size:clamp(15px,3.2vw,34px)!important;margin:1px!important}

/* ── 27. 字卡入面嘅字唔可以突出框外 ──────────────────────────────
   卡係固定方形，但音素由 1 個字元（M）去到 4 個（PRE-）。
   同一個 font-size，長嗰啲一定爆。跟 data-len 逐級收細，
   再加 overflow:hidden + padding:0 做最後一道保險。
   （Shari 2026-08-04：「字如果太長可以相應弄小點，不要突出外框外」）*/
.letter-card{overflow:hidden;padding:0!important;line-height:1;
  text-align:center;letter-spacing:0}
.letter-card[data-len="1"]{font-size:clamp(20px,4.4vw,40px)!important}
.letter-card[data-len="2"]{font-size:clamp(15px,3.1vw,28px)!important}
.letter-card[data-len="3"]{font-size:clamp(11px,2.3vw,21px)!important}
.letter-card[data-len="4"]{font-size:clamp(9px,1.8vw,17px)!important}
.letter-card[data-len="5"]{font-size:clamp(8px,1.5vw,14px)!important}
[class*="border-dashed"] .letter-card[data-len="1"]{font-size:clamp(15px,3.2vw,34px)!important}
[class*="border-dashed"] .letter-card[data-len="2"]{font-size:clamp(12px,2.3vw,24px)!important}
[class*="border-dashed"] .letter-card[data-len="3"]{font-size:clamp(9px,1.7vw,18px)!important}
[class*="border-dashed"] .letter-card[data-len="4"]{font-size:clamp(8px,1.4vw,15px)!important}
[class*="border-dashed"] .letter-card[data-len="5"]{font-size:clamp(7px,1.2vw,12px)!important}

/* ── 12. letter-choice 細鍵盤 ──
   顏色交返品牌層（app.js 原本硬編 pink/blue/green，已拆走）。*/
.letter-choice{background:#fff!important;color:var(--ink)!important;
  padding:4px 9px!important;min-width:2em;font-size:.98em!important;
  margin:0!important;line-height:1.2;cursor:pointer;
  border:2px solid var(--ink)!important;border-radius:9px!important;
  box-shadow:0 2px 0 rgba(44,62,80,.14)!important;transition:transform .1s}
.letter-choice:hover{background:var(--cream-deep)!important;transform:translateY(-1px)}
.letter-choice:active,.letter-choice.just-added{
  background:var(--yellow)!important;transform:translateY(2px);
  box-shadow:0 0 0 rgba(44,62,80,.14)!important}
.letter-choice:focus-visible{outline:none;
  box-shadow:0 0 0 3px var(--coral-pale),0 2px 0 rgba(44,62,80,.14)!important}

/* ═══ 2026-08-04 · UX/UI review 修正 ═══════════════════════════════ */

/* ── 13. 「返回首頁」壓住標題 ──
   我上輪將 .btn-link 由 block 改成 inline-flex，佢就唔再迫下一行。
   加返 width:fit-content + margin-bottom，令佢自己佔一行。*/
#topBackBtn{display:flex!important;width:fit-content;margin-bottom:14px!important}

/* ── 14. 主 CTA 交返品牌 ──
   app.js 嗰個 indigo inline gradient 已經拆走，呢度接手。*/
#startAdventureBtn{
  background:linear-gradient(135deg,var(--coral) 0%,var(--coral-dark) 100%)!important;
  color:var(--ink)!important;border:3px solid var(--ink)!important;
  box-shadow:var(--sh-rung)!important;font-family:var(--ff-head);font-size:18px;
  /* wrapper 個 my-5（上下各 3rem）已經拆走，隔開嘅責任落返個掣度 */
  margin-top:28px!important;margin-bottom:0!important}
#startAdventureBtn:hover{transform:translateY(-3px);box-shadow:var(--sh-lift)!important}

/* ── 15. 階段分隔帶要夠份量 ──
   佢係全頁唯一嘅章節分界，原本太淡，掃過去唔覺。*/
.se-stage-band{padding:14px 20px!important;background:#fff!important;
  border-width:3px!important}
.se-stage-band b{font-size:17px!important;letter-spacing:.14em!important}
.se-stage-band::before{content:'';width:14px;height:14px;border-radius:50%;
  border:3px solid var(--ink);background:var(--coral);flex:0 0 14px}
/* ⚠️ 本來寫 :nth-of-type(2) —— 但 :nth-of-type 係數同類元素（div），
   而兩條帶中間隔住 12 個 .col，所以第二條帶根本唔係第 2 個 div，
   呢條規則由頭到尾冇生效過。加咗第三條帶之後更加唔夠用。
   改為跟 data-stage 逐個指定，同 body[data-stage] 一套色。*/
#groupList .se-stage-band[data-stage="basics"]::before{background:var(--coral)}
#groupList .se-stage-band[data-stage="advanced"]::before{background:var(--teal)}
#groupList .se-stage-band[data-stage="longwords"]::before{background:var(--purple-1)}

/* ═══════════════════════════════════════════════════════════════════
   2026-08-04 · 第三輪 —— 唔再補鑊，照 06_LADDER_LESSONS_STYLE_GUIDE 重做
   ═══════════════════════════════════════════════════════════════════
   Shari 問：「明明 style guide 裡面的卡片跟按鈕設計配色就好看很多，為什麼？」
   答案：style guide 嗰啲卡係跟足 §08 由零砌 —— 頂 10px category 色條、
   3px ink 框、--r-lg 24px 圓角、--sh-rung-lg 硬陰影、16px padding。
   Ladder Phonics 呢邊係舊 Bootstrap .card，我一路只係喺上面「蓋」
   （改色、加 !important、壓 font-size），從來冇照 §08 個配方重砌過。
   所以佢永遠似「上咗品牌色嘅 Bootstrap」，唔係 Ladder Lessons 卡。
   由呢一段開始，元件跟 §07／§08 逐項對齊，唔再靠壓縮同微調。
   ═══════════════════════════════════════════════════════════════════ */

/* ── 16. Hero：標題唔再偏左 ────────────────────────────────────────
   根因喺 app.js（已修）：佢將一個 <h1> 塞落 <h1 id="group-title"> 入面，
   再喺內層加 .text-center；但外層有 display:inline-block（做黃色底線用），
   個框收窄到啱啱包住字，內層點 center 都係喺個窄框入面 center。
   而家 #group-title 淨係一段純文字，直接處理對齊。*/
#group-title{display:block;border-bottom:0;padding-bottom:0;
  font-family:var(--ff-head);font-weight:700}
/* 底線用 ::after，唔用 border-bottom + inline-block —— 咁就唔使動 display，
   而且條線可以跟字寬（左對齊）或者置中（首頁）。*/
#group-title::after{content:'';display:block;height:6px;border-radius:3px;
  background:var(--yellow-deep);margin-top:12px;width:120px}
body.at-home #group-title,body.at-home #group-description{text-align:center;
  margin-left:auto;margin-right:auto}
body.at-home #group-title::after{margin-left:auto;margin-right:auto}
body.at-home #group-description{max-width:56ch}
/* 入到組內：條線換成階段色，學生一望知自己喺 Basics 定 Advanced。
   （之前入到組內就完全冇咗組別顏色）*/
#group-title[data-stage="basics"]::after{background:var(--coral)}
#group-title[data-stage="advanced"]::after{background:var(--teal)}

/* ── 17. 配對遊戲重做（style guide §08）──────────────────────────
   規矩：3px ink 框、--r-lg 圓角、硬陰影、左邊一條階段色條。
   高度用 clamp 跟卡數收，唔用 font-size —— font-size 會拖埋 SVG 落水。
   ⚠️ drawLines() 用 getBoundingClientRect，所以只可以改尺寸／間距，
      唔可以改 display 或者搬 DOM。呢度全部係 box metrics，安全。*/
/* ⚠️ 唔可以用 align-items:flex-start —— 中間畫線嗰欄要撐滿高度，
   一縮返 350px，SVG（預設 overflow:hidden）就會切走下面幾條線。
   我上一輪加咗 flex-start，就係「線消失一截」嘅原因。用 stretch。*/
#content .row:has(.col-md-5){align-items:stretch;margin-inline:0!important}
#content .row:has(.col-md-5)>.col-md-2{align-self:stretch;padding-inline:0!important}
/* 左右兩欄留少少內距，但中間嗰欄一定要 0 —— 條線先貼得到卡片邊 */
#content .col-md-5{gap:10px!important;padding-inline:0!important}
#content .col-md-5.ps-5{padding-left:0!important}
#content .col-md-5.pe-5{padding-right:0!important}
.letter-match-card,.match-click-target{
  border:3px solid var(--ink)!important;border-radius:var(--r-lg)!important;
  background:#fff!important;box-shadow:var(--sh-rung)!important;
  height:clamp(84px,11vh,128px)!important;overflow:hidden;
  transition:transform .12s,box-shadow .12s}
.letter-match-card:hover,.match-click-target:hover{
  transform:translateY(-3px);box-shadow:var(--sh-lift)!important}
/* 左邊一條階段色條 = style guide §08「category 色條」，轉咗做直向 */
.letter-match-card{position:relative;padding-left:14px!important}
.letter-match-card::before{content:'';position:absolute;left:0;top:0;bottom:0;width:10px;
  background:var(--stage)}
/* ── 右欄改成純字彙（2026-08-04）──────────────────────────────────
   插畫收起咗（SHOW_ART = false）。個字佔晒成張卡，目標音素標珊瑚色。
   ⚠️ 標色先係張卡教嘢嗰部分 —— 之前標色淨係喺「冇插畫」嗰啲後備圖出現，
      有插畫嗰啲反而冇標，即係做得最靚嗰批教得最少。反轉咗。*/
.card-img-left[hidden]{display:none!important}
.card-img-left{width:42%!important;padding:8px!important}
.phonics-image{max-height:100%;max-width:100%;width:auto;height:auto}
.match-click-target .card-body{padding:6px 14px!important;flex:1;min-width:0;
  align-items:center;justify-content:center}
.se-wc__w{font-family:var(--ff-head);font-weight:700;
  font-size:clamp(22px,3.4vw,40px);line-height:1.1;color:var(--ink);
  letter-spacing:.01em;word-break:break-word;text-align:center}
/* 目標音素 —— 珊瑚色 + 底線，兩個訊號，唔淨係靠顏色（色盲都睇到）*/
.se-wc__hit{color:var(--coral-ink);font-weight:700;
  border-bottom:4px solid var(--coral);padding-bottom:1px}
body[data-stage="advanced"] .se-wc__hit{border-bottom-color:var(--teal)}
.se-wc__l{font-family:var(--ff-head);font-size:clamp(12px,1.5vw,16px)!important;
  color:var(--ink-soft)!important;margin-top:2px}
.se-wc__l:empty{display:none}
.match-click-target .card-text{margin:0!important}
.letter-match-card .display-1{font-size:clamp(38px,6vw,68px)!important;
  color:var(--ink)!important;line-height:1;margin-right:.35em!important}
.letter-match-card .fs-2{font-size:clamp(15px,2vw,24px)!important;color:var(--ink-soft)!important}
/* 揀中：唔再加 text-white（白字落珊瑚 2.78:1），用黃底 + 粗框 */
.letter-match-card.border-primary,.match-click-target.border-primary,
.letter-match-card.bg-primary-pale,.match-click-target.bg-primary-pale{
  background:var(--yellow)!important;border-color:var(--ink)!important;
  color:var(--ink)!important;transform:translateY(-3px)}
.letter-match-card.text-white,.match-click-target.text-white{color:var(--ink)!important}
.letter-match-card.text-white *,.match-click-target.text-white *{color:var(--ink)!important}

/* ── 18. 「聽發音」掣（style guide §07 primary）────────────────────
   之前係 inline backgroundColor:var(--color-*-500) + text-white
   → 珊瑚 2.78:1、teal 1.9:1，兩個都過唔到 AA，而且 inline 蓋唔到。*/
.btn.se-play{background:linear-gradient(135deg,var(--coral) 0%,var(--coral-dark) 100%)!important;
  color:var(--ink)!important;border:3px solid var(--ink)!important;
  border-radius:var(--r-rung)!important;padding:12px 16px!important;min-height:44px;
  box-shadow:var(--sh-rung)!important;font-family:var(--ff-head);font-weight:600}
body[data-stage="advanced"] .btn.se-play{
  background:linear-gradient(135deg,var(--teal) 0%,var(--teal-dark) 100%)!important}
/* 標題底線同樣讀 --stage，唔使逐個 data-stage 寫 */
#group-title[data-stage]::after{background:var(--stage)}
.btn.se-play:active{transform:translateY(4px);box-shadow:none!important}
/* 老師現場示範 = 唔係一個可撳嘅行動 → §07 disabled 樣式 */
/* ⚠️ 用 --ink 唔用 --ink-soft：--ink-soft 落 --line 得 4.38:1，差少少過唔到 AA。
   （style guide §07 個 disabled 配方本身就有呢個問題 —— 已記低，下次更新 SSOT 要改。）
   而且呢個唔算 disabled，係「由老師示範」嘅說明，睇得清楚反而啱。*/
.btn.se-play-teacher{background:var(--line)!important;color:var(--ink)!important;
  border:3px dashed var(--muted)!important;border-radius:var(--r-rung)!important;
  padding:12px 16px!important;min-height:44px;box-shadow:none!important;
  font-family:var(--ff-head);font-weight:600}

/* ── 19. 錄音三個掣：有字、夠大 ───────────────────────────────────
   原本淨係 icon 而且細過 44px。§07：所有掣最細 44×44。*/
/* 三個掣連成一條 segmented control ——「錄 → 停 → 聽返」本來就係一組動作，
   分開三粒藥丸每邊都要留圓角同罅，橫向好蝕位。
   拆走 gap 同內側圓角，只留外側 —— 慳返約 30% 闊度，而且睇落係一件嘢。
   （Shari 2026-08-04：「更節省左右兩邊的位置，拿掉按鈕之間的 padding 跟圓角」）
   ⚠️ 高度仍然守 44px 觸控底線，只收左右 padding。*/
.se-recgroup{display:flex;gap:0;flex-wrap:nowrap!important;justify-content:center;
  align-items:stretch;width:100%;
  border:2.5px solid var(--ink);border-radius:var(--r-rung);overflow:hidden;
  box-shadow:var(--sh-rung);
  /* 只闊到啱啱夠，唔再硬撐滿張卡 —— 撐滿先要平均分，平均分先會切字 */
  width:fit-content;max-width:100%;margin-inline:auto}
/* ⚠️ 唔可以用 flex:1 1 0 —— 0 basis = 三個掣平均分闊度，但
   「錄我把聲」4 個字闊過「停」1 個字兩倍有多。平均分之下長嗰個爆位，
   再撞上 .se-recgroup 個 overflow:hidden（做圓角用），個字就畀切走。
   （Shari 2026-08-04：「錄我把聲按鈕的字被砍了」）
   改用 flex:0 1 auto —— basis 跟內容闊度，多出嚟嘅位由 group 置中吸收。
   min-width:max-content 保證永遠唔會縮到切字；真係太窄就靠 font-size
   個 clamp 同下面 media query 收起 icon。*/
.btn.se-recbtn{display:inline-flex;align-items:center;justify-content:center;gap:4px;
  flex:0 1 auto;min-width:max-content;white-space:nowrap;
  min-height:44px;padding:5px clamp(4px,1vw,8px)!important;
  font-family:var(--ff-head);font-weight:600;font-size:clamp(11px,1.05vw,13.5px);
  border:0!important;border-radius:0!important;
  background:#fff!important;color:var(--ink)!important;box-shadow:none!important}
/* 內側分隔線代替原本嘅罅 */
.btn.se-recbtn + .btn.se-recbtn{border-left:2.5px solid var(--ink)!important}
.btn.se-recbtn:hover{background:var(--cream-deep)!important;transform:none}
.btn.se-recbtn:active{background:var(--yellow)!important;transform:none}
.btn.se-recbtn:focus-visible{outline:none;background:var(--yellow)!important;
  box-shadow:inset 0 0 0 3px var(--ink)!important}
/* 錄緊音 = 紅底白字。⚠️ 唔用 --coral：珊瑚配墨字 3.96:1，喺呢個掣得 13px
   就過唔到 AA 細字 4.5。--error-deep 配白字有 5.67:1，而且紅色本身就係
   錄音嘅慣例訊號。（對比度 script 攔唔到 —— 呢條 rule 冇寫 color，
   佢淨係查「同一條 rule 有齊 color + background」嗰啲。）*/
.btn.se-recbtn.recording-pulse{background:var(--error-deep)!important;color:#fff!important}
.se-recbtn i{flex:0 0 auto}
/* ⚠️ 本來呢度寫住 @media (max-width:1100px){.se-recbtn i{display:none}} ——
   結果 768–1100px（即係 iPad 直向）三個掣完全冇 icon，而手機同 desktop 都有。
   （Shari 2026-08-04 iPad 截圖）
   收起 icon 呢個做法本身係錯嘅解法：icon 係「錄音／停／播放」三個最通用嘅
   視覺訊號，慳嗰十幾 px 唔值。真正嘅風險係「字被切走」，所以改成正面解決：
     · icon 縮細啲 + gap 收窄 —— 慳返差唔多同樣嘅位，但 icon 留住
     · 拆走 .se-recgroup 個 overflow:hidden —— 圓角改用第一／最後個掣自己做。
       overflow:hidden 係之前「錄我把聲」畀切走嗰次嘅共犯：爆位唔會報錯，
       淨係靜靜地切。冇咗佢，萬一真係爆位會睇得見，改得返。*/
@media (max-width:1100px){
  .btn.se-recbtn{gap:3px;padding:5px clamp(3px,.9vw,7px)!important}
  .se-recbtn i{font-size:.9em}
}
.se-recgroup{overflow:visible}
.btn.se-recbtn:first-child{
  border-radius:calc(var(--r-rung) - 2px) 0 0 calc(var(--r-rung) - 2px)!important}
.btn.se-recbtn:last-child{
  border-radius:0 calc(var(--r-rung) - 2px) calc(var(--r-rung) - 2px) 0!important}

/* ── 20. 音素鍵盤：分層，唔再一次過出 76 個鍵 ─────────────────────
   （app.js 已改成「今組 + 上一組」，撳「全部音素」先展開）*/
.se-pool{border:3px solid var(--ink);border-radius:var(--r-lg);background:#fff;
  box-shadow:var(--sh-rung);padding:14px 16px}
.se-pool__head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin-bottom:12px;padding-bottom:10px;border-bottom:3px solid var(--cream-deep)}
.se-pool__head b{font-family:var(--ff-head);font-weight:700;font-size:15px}
.se-pool__count{font-size:13px;font-weight:600;color:var(--ink-soft);margin-right:auto}
.se-pool__toggle{font-family:var(--ff-head);font-weight:600;font-size:13.5px;
  min-height:44px;padding:9px 16px;border:2.5px solid var(--ink);border-radius:var(--r-pill);
  background:var(--yellow);color:var(--ink);box-shadow:var(--sh-rung);cursor:pointer}
.se-pool__toggle:hover{transform:translateY(-2px)}
.se-pool__toggle:active{transform:translateY(4px);box-shadow:none}
.se-pool__keys{gap:6px!important}

/* ── 21. 拼字格：撳都得，唔止拖 ───────────────────────────────────*/
[class*="border-dashed"]:empty::before,#dropArea:empty::before{
  content:'撳下面嘅音素，或者拖入嚟';color:var(--ink-soft);font-weight:600}

/* ── 22. 完成 Basics 嘅里程碑 ─────────────────────────────────────
   之前 Basics／Advanced 只有視覺分隔，做完第 12 組冇任何回饋。*/
.se-stage-band[data-stage="advanced"]{background:var(--teal-pale)!important}
.se-stage-band[data-stage="advanced"] b{color:var(--teal-dark)}
.se-stage-band em{font-style:normal;font-weight:700;color:var(--ink);
  background:var(--yellow);padding:1px 9px;border-radius:var(--r-pill);
  border:2px solid var(--ink);margin-left:6px;white-space:nowrap}

/* ── 23. 最尾一行唔夠三個就置中 ───────────────────────────────────
   22 組 ÷ 3 = 7 行 + 1。孤零零一張喺左邊好突兀，置中至少睇落係故意。*/
/* ── 28. Tab：一屏一件事 ─────────────────────────────────────────
   組別頁三個環節（發音／配對／拼字）改成 tab。老師 Zoom share screen
   嗰陣，學生應該淨係見到而家做緊嗰樣。（Shari 2026-08-04）
   ⚠️ panel 用 [hidden] 收埋，唔用 opacity/visibility —— 隱藏嗰個唔可以
      仲佔住高度，唔係成頁一樣咁長，做 tab 就冇意思。

   ── 簡化版（Shari 2026-08-04：「簡化這些按鈕設計，省位置就好」）──
   之前一個 tab 係一張大卡（兩行字 + 副標 + x/3 角標），三個就食晒成行。
   而家：一行 pill，flex:0 0 auto 唔再撐滿闊度 —— 佢係導航，唔係內容。
   步驟號用細圓點，選中先變階段色實心。高度由 ~76px 收到 44px。*/
.se-tabs{margin-bottom:18px}
.se-tabs__list{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}
.se-tab{flex:0 0 auto;min-width:0;min-height:44px;
  display:inline-flex;align-items:center;gap:7px;
  padding:0 15px 0 8px;cursor:pointer;
  font-family:var(--ff-head);font-weight:600;font-size:14.5px;line-height:1;
  background:#fff;color:var(--ink);
  border:2.5px solid var(--ink);border-radius:var(--r-pill);
  box-shadow:var(--sh-rung);transition:transform .12s,box-shadow .12s,background .12s}
.se-tab:hover{transform:translateY(-2px);box-shadow:var(--sh-lift)}
.se-tab:active{transform:translateY(4px);box-shadow:none}
.se-tab:focus-visible{outline:none;box-shadow:0 0 0 4px var(--yellow),var(--sh-rung)}
.se-tab.is-on{background:var(--stage-soft);border-width:3px}
/* 步驟號：細圓點，選中先填階段色 */
.se-tab__n{flex:0 0 26px;width:26px;height:26px;display:grid;place-items:center;
  font-size:12.5px;font-weight:700;font-variant-numeric:tabular-nums;
  background:var(--cream-deep);color:var(--ink);
  border:2px solid var(--ink);border-radius:50%}
.se-tab.is-on .se-tab__n{background:var(--stage)}
.se-tab__i{font-size:15px;line-height:1}
.se-tab__t{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.se-tabs__panel[hidden]{display:none!important}
/* panel 個 <h2> 而家喺 app.js 度已經係 .visually-hidden，唔使喺呢度收。
   （之前用 .se-tabs__panel>h2，但配對遊戲個 h2 包咗兩層 .row>.col，
     `>` 選唔中 —— 所以佢一直仲喺度。2026-08-04 由源頭改。）*/

/* 配對遊戲頂部：一句提示 + 重新排過 */
.se-matchbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  margin-bottom:18px;padding:12px 16px;
  border:2.5px solid var(--ink);border-radius:var(--r-rung);
  background:var(--cream);box-shadow:var(--sh-rung)}
.se-matchbar__t{margin:0;flex:1;min-width:200px;
  font-size:13.5px;font-weight:600;color:var(--ink-soft);line-height:1.5}
.se-matchbar__t strong{color:var(--ink);font-family:var(--ff-head)}
.btn.se-matchbar__b{display:inline-flex;align-items:center;gap:7px;flex:0 0 auto;
  min-height:44px;padding:9px 18px!important;font-size:13.5px}
@media (max-width:640px){
  /* ⚠️ 之前 flex:1 1 calc(50% - 4px) → 2 + 1，第三個孤零零一行，
     而且睇落似「兩個 tab 加一個掣」。三個係一組流程，一定要同一排。
     （Shari 2026-08-04 手機截圖）*/
  .se-tabs__list{flex-wrap:nowrap;gap:6px}
  .se-tab{flex:1 1 0;min-width:0;justify-content:center;padding:0 8px;gap:5px}
  .se-tab__i{display:none}
  .se-tab__n{flex:0 0 22px;width:22px;height:22px;font-size:11px}
  .se-tab__t{font-size:13px}
}
@media (max-width:380px){.se-tab__t{font-size:12px}.se-tab{padding:0 5px}}

/* ── 24. 一個階段 token 控制成頁 ──────────────────────────────────
   之前每個元件各自睇 p.color（逐個音素喺數據寫死嘅顏色），所以
   第 3 組（Basics）出綠底、第 22 組（Advanced）出粉紅底 —— 同組別
   一啲關係都冇。而家全部改為讀 --stage / --stage-soft，
   由 body[data-stage] 一個地方決定。*/
body{--stage:var(--coral);--stage-soft:var(--coral-pale);--stage-deep:var(--coral-ink)}
body[data-stage="basics"]{--stage:var(--coral);--stage-soft:var(--coral-pale);
  --stage-deep:var(--coral-ink)}
body[data-stage="advanced"]{--stage:var(--teal);--stage-soft:var(--teal-pale);
  --stage-deep:var(--teal-dark)}

/* ── 25. 發音練習卡（style guide §08）────────────────────────────
   白底 · 3px ink 框 · 頂階段色條。唔再用 --color-*-100 做底。*/
.card.se-pcard{background:#fff!important;border:3px solid var(--ink)!important;
  border-radius:var(--r-lg)!important;box-shadow:var(--sh-rung)!important;
  /* ⚠️ 條色條係 ::before position:absolute，唔佔位。留位要靠張卡自己嘅
     padding-top。我原本寫咗 >*:first-child{margin-top:22px}，但第一個仔
     其實係 .wave-background（絕對定位嘅裝飾），margin 落咗喺佢度冇效果，
     結果 .se-face 貼住頂，白色大字框蓋住咗色條中間 —— 得返左右兩隻角見到色。
     （Shari 2026-08-04 影到）改為將留位寫死喺 padding。*/
  padding:22px 16px 16px!important;overflow:hidden}
.card.se-pcard::before{content:'';position:absolute;top:0;left:0;right:0;height:10px;
  background:var(--stage);z-index:1}
.se-face{background:var(--cream)!important}
.wave-background{color:var(--stage-soft)!important}

/* ── 29. 多讀音卡：揭面 ───────────────────────────────────────────
   一個 grapheme 兩個音 → 一張卡兩面。揭嘅動作本身就係 Flip It 策略
   （讀唔通就轉另一個音再試），所以個掣要明顯，唔可以收埋。*/
.se-flip{width:100%;min-height:44px;margin-bottom:10px;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  font-family:var(--ff-head);font-weight:600;font-size:13.5px;
  padding:9px 12px;cursor:pointer;
  background:var(--yellow);color:var(--ink);
  border:2.5px solid var(--ink);border-radius:var(--r-pill);
  box-shadow:0 3px 0 rgba(44,62,80,.14);transition:transform .1s}
.se-flip b{font-family:var(--ff-body);font-weight:800}
.se-flip:hover{transform:translateY(-2px)}
.se-flip:active{transform:translateY(3px);box-shadow:none}
.se-flip:focus-visible{outline:none;box-shadow:0 0 0 3px var(--ink)}
/* 揭嘅時候閃一閃，畀學生知道係換咗面唔係換咗卡 */
@keyframes se-flip-in{from{transform:rotateY(-14deg);opacity:.35}to{transform:none;opacity:1}}
.se-pcard--multi.se-flipped .se-face{animation:se-flip-in .26s ease}
.se-pcard--multi{border-color:var(--ink)!important}
/* 卡角標「2 個音」，喺組別頁一眼睇得出邊個 grapheme 有兩個音 */
/* ⚠️ 本來寫死 content:'2 個音' —— ough 有 6 個音都係顯示「2 個音」，
   直接呃緊老師。（Shari 2026-08-10）用 attr() 讀返真數。 */
.se-pcard--multi::after{content:attr(data-nsounds) ' 個音';position:absolute;top:14px;right:12px;
  font-family:var(--ff-head);font-weight:700;font-size:10.5px;letter-spacing:.04em;
  padding:2px 8px;border:2px solid var(--ink);border-radius:var(--r-pill);
  background:var(--yellow);color:var(--ink);z-index:2}

/* 「幾時讀呢個音」—— 左邊色條表示可靠度：
   A 綠 = 硬規則，照跟就啱
   B 黃 = 規則可靠但有例外
   C 珊瑚 = 冇規則，要靠認字 + Flip It */
.se-when{display:flex;flex-direction:column;gap:5px;margin-top:12px;
  padding:11px 13px;border:2.5px solid var(--ink);border-radius:var(--r-rung);
  background:var(--cream);border-left-width:8px;text-align:left}
.se-when[data-level="A"]{border-left-color:var(--success)}
.se-when[data-level="B"]{border-left-color:var(--yellow-deep)}
.se-when[data-level="C"]{border-left-color:var(--coral)}
.se-when__t{font-family:var(--ff-head);font-weight:700;font-size:13px;color:var(--ink)}
.se-when__w{font-size:12.5px;font-weight:600;color:var(--ink-soft);line-height:1.55}
.se-when__e{display:flex;flex-wrap:wrap;gap:5px;margin-top:2px}
.se-when__e i{font-style:normal;font-family:var(--ff-head);font-weight:600;font-size:12px;
  padding:2px 8px;border:2px solid var(--ink);border-radius:var(--r-pill);background:#fff}
.se-when[data-level="C"]::before{content:'冇規則 —— 讀唔通就撳上面轉另一個音再試';
  font-family:var(--ff-head);font-weight:700;font-size:11px;color:var(--coral-ink)}

/* ── 26. 「一張圖收兩個字母」要講明 ──────────────────────────────
   第 3 組 C 同 K 都讀 /k/，所以 4 張字母卡對 3 張圖。教學上啱，
   但畫面睇落似漏咗一張。（Shari 2026-08-04：「有時候缺少 item」）*/
.se-multi-badge{display:inline-block;margin-top:4px;
  font-family:var(--ff-head);font-weight:700;font-size:11px;letter-spacing:.02em;
  padding:2px 9px;border-radius:var(--r-pill);border:2px solid var(--ink);
  background:var(--yellow);color:var(--ink);white-space:nowrap}
.match-click-target[data-multi]{border-width:3px!important}
.match-click-target[data-multi] .se-wc__w{font-size:clamp(18px,2.6vw,30px)}
/* 欄標題 */
/* ⚠️ 兩欄標題一定要同高。中文「係邊個音？」一行，英文
   "Tap a word to hear it" 喺窄位會變兩行 —— 一高一矮，成欄卡片就上下錯開，
   本來打橫嘅連線變咗斜線。（Shari 2026-08-05 英文化之後見到）
   鎖死兩行高度，邊種語言都對齊。 */
.se-col-h{font-family:var(--ff-head);font-weight:700;font-size:14px!important;
  letter-spacing:.06em;color:var(--ink-soft);text-transform:none;
  min-height:2.6em;display:flex;align-items:center;justify-content:center;
  text-align:center;line-height:1.3}

/* 2026-08-04：第 22 組拆成 22（軟音 c）／23（軟音 g）／24（-le -y）之後，
   Advanced 有 12 組，全庫 24 組 —— 24 ÷ 3 = 8 行啱啱好，最後一行唔再空。
   之前嗰條「最後一張置中」嘅 hack 已經冇用，拆走。*/


/* ═══ 2026-08-04 · 三層閘（見 _brand/ll-funnel.js）═══════════════════ */

/* 鎖住嘅組別卡：淡啲、加一把鎖，但仲要撳得（撳落去出解鎖畫面）。
   ⚠️ 唔用 opacity 落成張卡 —— opacity 會連 ink 框都淡埋，
      張卡就冇咗品牌輪廓。只淡內容，框同色條照舊。*/
.phonics-card.is-locked .se-gcard__letters,
.phonics-card.is-locked .se-gcard__title{opacity:.45}
.phonics-card.is-locked .se-gcard__num{background:var(--line)}
.se-gcard__lock{margin-left:auto;flex:0 0 auto;white-space:nowrap;
  font-family:var(--ff-head);font-weight:700;font-size:10.5px;letter-spacing:.04em;
  padding:3px 9px;border:2px solid var(--ink);border-radius:var(--r-pill);
  background:var(--yellow);color:var(--ink)}
.phonics-card[data-tier="paid"] .se-gcard__lock{background:var(--cream-deep)}

/* 解鎖畫面 —— 撳咗鎖住嘅組別先出現，唔會自己彈 */
#llPhonicsGate{position:fixed;inset:0;z-index:2147483100;
  display:grid;place-items:center;padding:18px;
  background:rgba(44,62,80,.55);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
/* ⚠️ 外層只做定位，唔可以有 overflow —— 個 X 擺喺框外，一 auto 就畀裁走。*/
.llgate__sheet{position:relative;width:min(520px,100%);overflow:visible}
/* 捲動喺內層。overflow-x 一定要 hidden —— auto 會因為內容闊少少而出橫條，
   即係 Shari 影到底部嗰條。（2026-08-04）*/
.llgate__scroll{max-height:88vh;overflow-y:auto;overflow-x:hidden;
  border-radius:var(--r-lg);-webkit-overflow-scrolling:touch}
.llgate__x{position:absolute;top:-14px;right:-14px;z-index:3;
  width:40px;height:40px;display:grid;place-items:center;cursor:pointer;
  font-size:22px;line-height:1;font-family:var(--ff-head);
  background:#fff;color:var(--ink);border:3px solid var(--ink);border-radius:50%;
  box-shadow:var(--sh-rung)}
.llgate__x:hover{background:var(--cream-deep)}
.llgate__buy{background:#fff;border:3px solid var(--ink);border-radius:var(--r-lg);
  box-shadow:var(--sh-rung);padding:24px 22px;text-align:left}
.llgate__t{display:block;font-family:var(--ff-head);font-weight:700;
  font-size:clamp(17px,2.2vw,22px);margin-bottom:8px;color:var(--ink)}
.llgate__b{font-size:14.5px;font-weight:600;color:var(--ink-soft);line-height:1.6;margin:0 0 14px}
.llgate__cta{display:inline-flex;align-items:center;min-height:48px;
  font-family:var(--ff-head);font-weight:700;font-size:16px;
  padding:12px 28px;border:3px solid var(--ink);border-radius:var(--r-pill);
  background:linear-gradient(135deg,var(--coral) 0%,var(--coral-dark) 100%);
  color:var(--ink);text-decoration:none;box-shadow:var(--sh-rung)}
.llgate__cta:hover{transform:translateY(-2px);box-shadow:var(--sh-lift)}
@media (prefers-reduced-motion:reduce){#llPhonicsGate{backdrop-filter:none}}


/* ── 導航掣上面嘅鎖標 ─────────────────────────────────────────────── */
.btn.is-locked{opacity:.72}
.se-navlock{margin-left:8px;font-family:var(--ff-head);font-weight:700;font-size:10.5px;
  letter-spacing:.04em;padding:2px 8px;border:2px solid var(--ink);
  border-radius:var(--r-pill);background:var(--yellow);color:var(--ink);white-space:nowrap}

/* ── 行完 24 組：跟住練咩 ─────────────────────────────────────────── */
.se-after{margin-top:26px;padding:22px 20px;background:#fff;
  border:3px solid var(--ink);border-radius:var(--r-lg);box-shadow:var(--sh-rung)}
.se-after__t{display:block;font-family:var(--ff-head);font-weight:700;
  font-size:clamp(17px,2.2vw,21px);margin-bottom:5px}
.se-after__b{font-size:13.5px;font-weight:600;color:var(--ink-soft);margin:0 0 16px}
.se-after__grid{display:flex;flex-direction:column;gap:10px}
.se-after__c{display:flex;align-items:center;gap:13px;text-decoration:none;
  padding:12px 15px;border:2.5px solid var(--ink);border-radius:var(--r-rung);
  background:var(--cream);color:var(--ink);
  box-shadow:0 3px 0 rgba(44,62,80,.12);transition:transform .12s}
.se-after__c:hover{transform:translateY(-2px);background:#fff}
.se-after__c:active{transform:translateY(3px);box-shadow:none}
/* 主線兩隻有編號 + 階段色點；其餘係「有需要先用」*/
.se-after__c.is-main{background:var(--stage-soft);border-width:3px}
.se-after__n{flex:0 0 30px;width:30px;height:30px;display:grid;place-items:center;
  font-family:var(--ff-head);font-weight:700;font-size:14px;
  background:#fff;border:2.5px solid var(--ink);border-radius:50%}
.se-after__c.is-main .se-after__n{background:var(--stage)}
.se-after__w{display:flex;flex-direction:column;gap:2px;min-width:0}
.se-after__w b{font-family:var(--ff-head);font-weight:700;font-size:15px}
.se-after__w i{font-style:normal;font-size:12.5px;font-weight:600;
  color:var(--ink-soft);line-height:1.5}
/* 罕見個案 —— 唔應該同主線爭注意力 */
.se-after__c.is-rare{background:#fff;border-style:dashed;border-color:var(--muted)}
.se-after__c.is-rare .se-after__w b{color:var(--ink-soft)}


/* ══ 配對遊戲 · 手機 ═══════════════════════════════════════════════
   ⚠️ 之前喺 <768px 完全壞：col-md-5 唔生效 → col-12 → 三欄變上下疊。
      畫線嗰欄（350px 高、100% 闊）夾喺中間，字母卡喺佢上面、字喺佢下面，
      條線由上畫到落下，全部超出 SVG 範圍 → 畀 overflow:hidden 裁走。
      即係手機上完全見唔到連線 —— 配對仲撳得，但用家唔知自己配咗乜。
      （2026-08-04 Shari 問「免費遊戲係咪都要 mobile friendly」時查到）

   修法：手機唔跟 Bootstrap 嘅斷點，強制保持三欄。
   375px 之下每欄約 150 / 55 / 150px —— 一個音素卡同一個英文字綽綽有餘。
   咁樣個遊戲喺手機同電腦係同一件嘢，唔使維護兩套邏輯。*/
@media (max-width:767.98px){
  #content .row:has(.col-md-5){flex-wrap:nowrap!important}
  #content .row:has(.col-md-5)>.col-12.col-md-5{width:41%!important;flex:0 0 41%!important}
  #content .row:has(.col-md-5)>.col-12.col-md-2{width:18%!important;flex:0 0 18%!important;
    min-height:0!important}
  /* 左欄本來有 ps-5（48px 左內距），喺手機會食咗成三分一闊度 */
  #content .col-md-5.ps-5{padding-left:0!important}
  #content .col-md-5.pe-5{padding-right:0!important}
  .letter-match-card,.match-click-target{height:clamp(62px,9.5vh,84px)!important}
  .letter-match-card .display-1{font-size:clamp(24px,7vw,34px)!important;margin-right:.2em!important}
  .letter-match-card .fs-2{font-size:clamp(11px,3vw,15px)!important}
  .se-wc__w{font-size:clamp(15px,4.4vw,22px)}
  .se-wc__hit{border-bottom-width:3px}
  .match-click-target .card-body{padding:4px 6px!important}
  .se-col-h{font-size:12px!important;text-align:center}
  .se-matchbar{padding:10px 12px}
  .se-matchbar__t{font-size:12.5px;min-width:0;flex:1 1 100%}
}

/* ── 配對成功嘅編號 ─────────────────────────────────────────────────
   ⚠️ 唔止係手機保險。連線係一條幼線，六對線交叉埋一齊嗰陣好難數
      邊條駁邊條。一對一個號碼，睇一眼就知配咗幾多對、邊個配邊個。
      線畫唔到（手機、窄屏、瀏覽器唔支援）嗰陣，呢個就係唯一嘅回饋。*/
/* ── 字卡嘅喇叭記號 ─────────────────────────────────────────────────
   2026-08-04 兩欄調位之後，字卡係入口：撳落去會讀出個字，學生聽咗先
   判斷得到係邊個音素。所以「撳得出聲」一定要睇得出。
   擺右下角 —— 配對編號 .se-pairno 佔咗右上（Shari 2026-08-04 指出撞位）。
   右下角同時係「撳完之後手指最近」嗰個角，順手。*/
.se-wc__spk{position:absolute;bottom:6px;right:6px;z-index:4;
  width:26px;height:26px;display:grid;place-items:center;
  /* ⚠️ 本來用 --teal-dark（同連線一個色），但落喺 --stage 上面計出嚟
     啱啱 3.01:1 —— 圖形類最低要求係 3:1，貼到咁近等於冇緩衝。改用 --ink。*/
  color:var(--ink);background:var(--stage,#fff);
  border:2.5px solid var(--ink);border-radius:50%;
  box-shadow:0 2px 0 rgba(44,62,80,.14);pointer-events:none}
.se-wc__spk svg{width:14px;height:14px;display:block}
.match-click-target.success-celebrate .se-wc__spk{opacity:.45}
@media (max-width:767.98px){
  .se-wc__spk{width:22px;height:22px;bottom:4px;right:4px}
  .se-wc__spk svg{width:12px;height:12px}
}

.se-pairno{position:absolute;top:6px;left:6px;z-index:4;
  width:24px;height:24px;display:grid;place-items:center;
  font-family:var(--ff-head);font-weight:700;font-size:12px;
  background:var(--stage);color:var(--ink);
  border:2.5px solid var(--ink);border-radius:50%;
  box-shadow:0 2px 0 rgba(44,62,80,.14)}
.match-click-target .se-pairno{left:auto;right:6px}
@media (max-width:767.98px){.se-pairno{width:20px;height:20px;font-size:10.5px;top:4px;left:4px}
  .match-click-target .se-pairno{right:4px;left:auto}}


/* ══ 拼字格 · 手機 ═══════════════════════════════════════════════════
   ⚠️ 之前 width:clamp(30px, (100% - 24px)/12, 74px) —— 個 /12 係為咗
      「最多 12 個都放得落一行」，但手機根本冇 12 個字咁長嘅練習字，
      結果每個字卡得三十幾 px，細過鍵盤啲掣。
      （Shari 2026-08-04：「letter-card 過小」）
      手機改成跟實際數量走，唔夠位就縮，最細都有 44px。*/
@media (max-width:767.98px){
  [class*="border-dashed"]{padding:14px 8px!important;min-height:110px!important}
  [class*="border-dashed"] .letter-card{
    width:auto!important;min-width:clamp(44px,13vw,64px)!important;
    height:clamp(52px,15vw,72px)!important;
    padding:0 6px!important;margin:3px!important}
  [class*="border-dashed"] .letter-card[data-len="1"]{font-size:clamp(24px,7vw,34px)!important}
  [class*="border-dashed"] .letter-card[data-len="2"]{font-size:clamp(19px,5.4vw,26px)!important}
  [class*="border-dashed"] .letter-card[data-len="3"]{font-size:clamp(15px,4.2vw,20px)!important}
  [class*="border-dashed"] .letter-card[data-len="4"],
  [class*="border-dashed"] .letter-card[data-len="5"]{font-size:clamp(12px,3.4vw,16px)!important}
  /* 字多過一行都好過個個縮到睇唔到 */
  #dropArea,[class*="border-dashed"]{flex-wrap:wrap!important}
}

/* ══ 底部導航 · 手機三個掣一排 ═══════════════════════════════════════
   ⚠️ 之前「下一關：第 3 組：c / k / ck, e, h」成句寫晒，喺手機自己佔一行。
      三個掣分三行，用家要碌先見到「下一關」。
      手機淨係留方向 + 組號，組名唔重要（撳落去就見到）。
      （Shari 2026-08-04）*/
@media (max-width:767.98px){
  #content .row.mt-4{flex-wrap:nowrap!important;gap:6px}
  #content .row.mt-4 .col-auto{flex:1 1 0;min-width:0}
  #content .row.mt-4 .col-auto.ms-auto{margin-left:0!important}
  #content .row.mt-4 .btn{width:100%;justify-content:center;
    padding:9px 6px!important;font-size:12.5px;white-space:nowrap;
    overflow:hidden;text-overflow:ellipsis}
  /* 組名收埋，淨係留「上一關 / 下一關」+ 箭嘴 */
  #content .row.mt-4 .btn .se-navname{display:none}
  .se-navlock{margin-left:4px;font-size:9.5px;padding:1px 5px}
}

/* ══ 底部導航 · 平板 768–1199px ═══════════════════════════════════════
   ⚠️ 呢個 band 之前完全冇 rule —— 手機嗰個 nowrap 規則停喺 767.98px，
      再上就當有成千 px 位使。iPad 直向係 768px，容器得約 712px，
      但三個掣連組名要 ~700px，啱啱爆 →「下一關」跌咗落第二行。
      （Shari 2026-08-04 iPad 截圖）
   ⚠️ 唔照抄手機做法（收起組名）—— 平板有位，組名有用：老師睇到下一關教咩
      先決定跳唔跳。改成截斷：「上一關：第 1 組：s…」，方向同箭嘴永遠留住。
      截斷比二選一好，因為窄啲闊啲都work，唔使再猜下一個斷點。*/
@media (min-width:768px) and (max-width:1199.98px){
  #content .row.mt-4{flex-wrap:nowrap!important;gap:8px;
    margin-inline:0!important;align-items:stretch}
  #content .row.mt-4 .col-auto{min-width:0}
  #content .row.mt-4 .col-auto:first-child{flex:0 0 auto}
  #content .row.mt-4 .col-auto:not(:first-child){flex:0 1 auto}
  #content .row.mt-4 .btn{display:flex!important;align-items:center;
    justify-content:center;min-width:0;max-width:100%;white-space:nowrap}
  /* 截斷嘅一定要係組名嗰個 span，唔可以係成粒掣 ——
     成粒掣做 ellipsis 會連箭嘴同「留 email」一齊食埋。*/
  #content .row.mt-4 .btn .se-navname{
    min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #content .row.mt-4 .btn i,
  #content .row.mt-4 .btn .se-navlock{flex:0 0 auto}
}


/* ══ 手機 · 第二輪（Shari 2026-08-04 真機）═══════════════════════════ */

/* 1. 容器頂部留白 —— 唔可以一刀切 0，pill 係 fixed 唔佔位。
   改成：容器 0，留白交畀「第一件見到嘅嘢」自己避開個 pill。
   首頁係 #group-title，組內係 #topBackBtn。咁樣就唔會兩邊都白鋪一段。*/
@media (max-width:560px){
  .container.my-5{padding-top:0!important}
  body.at-home #group-title{margin-top:58px}
  #topBackBtn{margin-top:58px}
}

/* 2. 導航掣：icon 同字要正中，唔好貼死視窗邊 ─────────────────────
   ⚠️ 兩個成因：
      · .row 有 margin-inline:-12px（Bootstrap gutter），所以成行凸出容器外
      · icon 用緊 me-2 / ms-2（單邊 margin），令「icon + 字」整體偏一邊 */
@media (max-width:767.98px){
  #content .row.mt-4{margin-inline:0!important;padding-inline:2px;gap:7px}
  #content .row.mt-4 .btn{
    display:flex!important;align-items:center;justify-content:center;
    gap:5px;text-align:center;line-height:1.2}
  /* 單邊 margin 換成 gap —— gap 對稱，唔會拉偏 */
  #content .row.mt-4 .btn .me-2,
  #content .row.mt-4 .btn .ms-2{margin:0!important}
  #content .row.mt-4 .btn i{flex:0 0 auto;font-size:12px}
}

/* 3. 錄音三個掣喺手機太細 ─────────────────────────────────────────
   ⚠️ 一排一張卡之後，成張卡有成 340px 闊，但我啲掣仲用緊「三欄擠埋一齊」
      嗰陣嘅尺寸（11px 字、44px 高）。有位就應該用返。
      （Shari 2026-08-04：「這堆看起來太小」）*/
@media (max-width:767.98px){
  .se-recgroup{border-width:3px;border-radius:var(--r-md)}
  /* 圓角跟返 group（見上面「拆走 overflow:hidden」嗰段） */
  .btn.se-recbtn:first-child{
    border-radius:calc(var(--r-md) - 3px) 0 0 calc(var(--r-md) - 3px)!important}
  .btn.se-recbtn:last-child{
    border-radius:0 calc(var(--r-md) - 3px) calc(var(--r-md) - 3px) 0!important}
  .btn.se-recbtn{min-height:54px!important;font-size:15px!important;
    padding:10px 8px!important;gap:6px}
  .se-recbtn i{font-size:15px}
  .btn.se-play,.btn.se-play-teacher{min-height:54px;font-size:16px!important}
  .recording-timer,.recording-dot{font-size:14px}
}

/* ══ 27. 首頁搜尋（2026-08-05 · 第二版：即時下拉）════════════════
   ⚠️ 第一版係「高亮中咗嘅組別卡 + 捲過去」。Shari 試完：「跳來跳去很難用」。
      佢啱 —— 搜尋唔應該搞郁底下嗰版嘢。而家結果係一個 overlay 面板，
      絕對定位，底下成排卡由頭到尾唔郁一郁。 */
.se-find{position:relative;max-width:560px;margin:0 auto 18px}
.se-find__box{display:flex;align-items:center;gap:8px;padding:0 14px;
  background:#fff;border:3px solid var(--ink);border-radius:var(--r-pill);
  box-shadow:var(--sh-rung)}
.se-find__box:focus-within{box-shadow:0 0 0 4px var(--yellow),var(--sh-rung)}
.se-find__i{flex:0 0 auto;display:grid;place-items:center;color:var(--ink-soft)}
.se-find__i svg{width:18px;height:18px}
.se-find input{flex:1;min-width:0;border:0;outline:none;background:transparent;
  /* ⚠️ 16px 起 —— 細過就會令 iOS Safari 一 focus 就放大成頁 */
  font-family:var(--ff-body);font-size:16px;font-weight:600;color:var(--ink);
  padding:12px 0;min-height:48px}
.se-find input::-webkit-search-cancel-button{display:none}
.se-find input::placeholder{color:var(--ink-soft);font-weight:600}
.se-find__box button{flex:0 0 auto;border:0;background:transparent;cursor:pointer;
  font-size:22px;line-height:1;color:var(--ink-soft);padding:6px 4px}
.se-find__box button[hidden]{display:none}
.se-find__box button:hover{color:var(--ink)}

/* ⚠️ absolute + z-index：面板浮喺卡片之上，唔會推低下面啲嘢。
   打字打到一半個版跳高跳低係最煩嗰種。 */
.se-find__res{position:absolute;top:calc(100% + 8px);left:0;right:0;z-index:30;
  max-height:min(62vh,460px);overflow-y:auto;
  background:#fff;border:3px solid var(--ink);border-radius:var(--r-lg);
  box-shadow:var(--sh-lift);padding:6px}
.se-find__res[hidden]{display:none}
.se-find__grp{display:block;padding:9px 12px 5px;
  font-family:var(--ff-head);font-weight:700;font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-soft)}
.se-find__row{display:flex;align-items:center;gap:10px;width:100%;
  padding:10px 12px;min-height:48px;cursor:pointer;text-align:left;
  background:transparent;border:0;border-radius:var(--r-rung);
  font-family:var(--ff-body);font-size:15px;font-weight:600;color:var(--ink)}
.se-find__row:hover,.se-find__row.is-on{background:var(--cream-deep)}
.se-find__row mark{background:var(--yellow);color:var(--ink);border-radius:4px;padding:0 2px}
.se-find__k{font-family:var(--ff-head);font-weight:700;font-size:17px;
  min-width:2.6em;color:var(--coral-ink)}
.se-find__g{margin-left:auto;flex:0 0 auto;
  font-family:var(--ff-head);font-weight:700;font-size:11.5px;
  padding:3px 10px;border:2px solid var(--ink);border-radius:var(--r-pill);
  background:var(--cream);color:var(--ink);white-space:nowrap}
.se-find__none{padding:16px 14px;font-size:14px;font-weight:600;color:var(--ink-soft)}
@media (max-width:560px){
  .se-find{margin-inline:8px}
  .se-find__res{max-height:56vh}
}

/* ══ 28. 組別頁頂列：返首頁 + 搜尋（2026-08-05）═════════════════════
   搜尋框由首頁搬過嚟，靠右。返首頁掣靠左。 */
.se-toprow{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.se-toprow .se-find{margin:0 0 0 auto;flex:0 1 380px;min-width:0}
@media (max-width:640px){
  /* 手機一行放唔落兩樣 —— 搜尋另起一行，佔滿闊度先撳得舒服 */
  .se-toprow{gap:8px}
  .se-toprow .se-find{margin:0;flex:1 1 100%}
}

/* ⚠️ 底部「返回首頁」：<span class="se-navname">返回</span>首頁
   —— 手機規則畀成粒掣落咗 gap:5px，連呢兩個中文字之間都撐開咗，
   讀成「返回 首頁」。gap 係為咗 icon 同文字之間，唔係字同字之間。
   （Shari 2026-08-05）*/
/* （罅嘅真正成因喺 app.js —— 兩個中文字而家包咗喺同一個 <span> 入面，
   唔再係兩個 flex item。呢度唔使再用負 margin 補鑊。） */


/* ── 26. 第三階段 LONG WORDS（第 25–32 組）· 2026-08-10 ────────────
   Basics 珊瑚紅、Advanced 湖水綠，第三層用紫。三個色要一眼分得開，
   而且要同 --stage token 一齊行 —— 唔可以逐個元件再寫死顏色
   （見上面第 24 節嗰個教訓）。 */
body[data-stage="longwords"]{--stage:var(--purple-1);
  --stage-soft:rgba(102,126,234,.14);--stage-deep:var(--purple-1)}
#group-title[data-stage="longwords"]::after{background:var(--purple-1)}
body[data-stage="longwords"] .se-wc__hit{border-bottom-color:var(--purple-1)}
.se-stage-band[data-stage="longwords"]{background:rgba(102,126,234,.14)!important}
.se-stage-band[data-stage="longwords"] b{color:var(--purple-1)}
/* 三條帶各自一粒色點。原本用 nth-of-type(2) 寫死第二條 —— 加咗第三條
   就唔夠用，改為跟 data-stage 逐個指定。 */
.se-stage-band[data-stage="basics"]::before{background:var(--coral)}
.se-stage-band[data-stage="advanced"]::before{background:var(--teal)}
.se-stage-band[data-stage="longwords"]::before{background:var(--purple-1)}

/* ── 27. 組別卡跟返自己嘅階段色 · 2026-08-10 ──────────────────────
   `.phonics-card` 上面嗰句 `--stage:var(--coral)` 係所有卡嘅預設，
   下面三條按 data-stage 覆蓋返。條頂色條（.se-gcard__bar）同個號碼牌
   （.se-gcard__num）都係讀 --stage，所以改一個 token 就夠，
   唔使逐個元件寫死顏色（見第 24 節嗰個教訓）。 */
#groupList .phonics-card[data-stage="basics"]{--stage:var(--coral);
  --stage-soft:var(--coral-pale)}
#groupList .phonics-card[data-stage="advanced"]{--stage:var(--teal);
  --stage-soft:var(--teal-pale)}
#groupList .phonics-card[data-stage="longwords"]{--stage:var(--purple-1);
  --stage-soft:rgba(102,126,234,.14)}
/* hover 陰影都跟階段走，唔係撳落去先變色 */
#groupList .phonics-card[data-stage="longwords"]:hover{
  box-shadow:0 14px 34px rgba(102,126,234,.28)!important}


/* ══ 29. 多過兩個讀音：一排 IPA 掣（2026-08-10）════════════════════
   兩個音用揭卡；三個或以上揭到頭暈，改成全部列出嚟撳。 */
.se-soundpick{display:flex;flex-wrap:wrap;gap:5px;justify-content:center;
  margin:2px 0 10px;width:100%}
.se-soundpick__b{display:inline-flex;align-items:center;gap:3px;
  font-family:var(--ff-head);font-weight:700;font-size:12.5px;line-height:1;
  min-height:34px;padding:7px 10px;cursor:pointer;
  background:#fff;color:var(--ink);border:2.5px solid var(--ink);
  border-radius:var(--r-pill);box-shadow:0 2px 0 rgba(44,62,80,.14)}
.se-soundpick__b:hover{background:var(--cream-deep)}
.se-soundpick__b.is-on{background:var(--ink);color:var(--cream)}
.se-soundpick__b:focus-visible{outline:none;box-shadow:0 0 0 3px var(--yellow)}
/* 未錄音嗰個標一標 —— 老師一眼知邊個要自己讀 */
.se-soundpick__b i{font-style:normal;font-size:10px;opacity:.75}
@media (max-width:767.98px){
  .se-soundpick__b{font-size:12px;padding:6px 9px;min-height:32px}
}

/* ══ 30. 上／下一關掣太長（2026-08-10）════════════════════════════
   ⚠️ STAGE 2 啲組名長好多：「第 28 組：靜音字母 2（mb、gn、bt、lk、-stle、hon-）」
      —— 成粒掣拉到成半版闊，而且兩粒唔同長度，排版歪晒。
      （Shari 2026-08-10 截圖）
   ⚠️ 唔可以淨係收起組名（.se-navname）—— 老師要知下一關教咩先決定跳唔跳。
      改成封頂 + 截斷：方向、組號、箭嘴永遠留住，長嘅組名尾巴用「…」。*/
/* ⚠️⚠️ 上一版加咗 max-width 同 text-overflow 但**完全冇效**，粒掣反而
   變高咗（Shari 2026-08-10 截圖：跌到三行）。
   成因：.btn 係 display:inline-flex，.se-navname 係一個 flex item。
   flex item 嘅預設 min-width 係 auto —— 即係「唔可以縮到細過內容」。
   所以 max-width:100% 同 ellipsis 永遠觸發唔到，個字照樣撐開／換行。
   一定要 min-width:0 先解得開呢個鎖。呢個係 flexbox 最常中嘅一個窿。
   ⚠️ 粒掣本身亦要 white-space:nowrap，唔係佢會換行變高。*/
/* ⚠️⚠️ 第三次。上一版加咗 min-width:0，粒掣係唔再換行（唔再高），
   但個字**衝咗出個框外面**（Shari 2026-08-10 截圖）——
   即係 flex 縮細機制根本冇啟動。
   成因：呢啲導航掣未必真係 display:inline-flex（ll-base 同 style.css
   都有 .btn 嘅定義，邊個贏視乎載入次序），唔係 flex 嘅話
   min-width:0 完全冇意義，一串 nowrap 文字就直接漏出去。
   所以呢度**強制** inline-flex，令縮細機制一定行到；
   再加 overflow:hidden 做保險 —— 就算將來又有邊個 rule 打交，
   個字都唔會走出個框（圓角亦切得靚）。
   ⚠️ 箭嘴同鎖標要 flex:0 0 auto，唔係佢哋會一齊畀縮走。*/
#content .row.mt-4 .btn{max-width:min(38vw,420px);
  display:inline-flex!important;align-items:center;flex-wrap:nowrap;
  white-space:nowrap;overflow:hidden}
#content .row.mt-4 .btn .se-navname{
  flex:0 1 auto;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
#content .row.mt-4 .btn i,
#content .row.mt-4 .btn .se-navlock{flex:0 0 auto}
@media (max-width:767.98px){
  #content .row.mt-4 .btn{max-width:none}
}
