  :root{
    --paper:#FAF3E7;
    --paper-deep:#F0E6D2;
    --ink:#211C18;
    --ink-soft:#7A6F61;
    --coral:#E8704A;
    --coral-soft:#F4C9B8;
    --seal:#B8412F;
    --seal-wash:#F1DAD2;
    --sage:#7A9B76;
    --sage-soft:#D9E6D4;
    --line:#DDD0B4;
    --hairline:#E6D9BD;
    --radius:18px;
    --serif:-apple-system,"PingFang TC","Microsoft JhengHei","Noto Sans TC",sans-serif;
  }
  *{box-sizing:border-box;}
  html,body{
    margin:0;padding:0;height:100%;
    background:var(--paper);
    color:var(--ink);
    font-family:-apple-system,"PingFang TC","Microsoft JhengHei","Noto Sans TC",sans-serif;
    -webkit-tap-highlight-color:transparent;
    overscroll-behavior:none;
    user-select:none;
    /* 擋掉「連點兩下把整個畫面放大」的瀏覽器手勢。
       ⚠️ 上面的 <meta viewport user-scalable=no> 在 iOS 上是無效的——Apple 從
       iOS 10 起基於無障礙考量刻意忽略它，所以 Android 擋得住、iPad 擋不住。
       實際症狀：小孩點圖鑑裡鎖住的動物沒反應，就再點一次，整個畫面就被放大。
       manipulation = 保留捲動與雙指縮放（無障礙需要），只關掉雙擊縮放。
       日文練習畫布另外設 touch-action:none（那裡連捲動都不能有，見kanjiEngine）。 */
    touch-action:manipulation;
  }
  #app{
    min-height:100vh;
    display:flex;
    flex-direction:column;
    align-items:center;
    padding:20px 16px 32px;
  }

  #lang-screen{
    position:fixed;
    inset:0;
    background:var(--paper);
    z-index:999;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:12px;
    padding:24px;
  }
  .lang-card{
    width:100%;
    max-width:300px;
    display:flex;
    flex-direction:column;
    gap:12px;
  }
  .lang-icon{
    width:56px;height:56px;
    border-radius:16px;
    background:var(--coral);
    display:flex;align-items:center;justify-content:center;
    margin:0 auto 8px;
  }
  .lang-option{
    width:100%;
    padding:14px 18px;
    background:#fff;
    border:1.5px solid var(--line);
    border-radius:16px;
    color:var(--ink);
    font-size:15px;
    cursor:pointer;
    text-align:left;
    display:flex;
    align-items:center;
    gap:14px;
  }
  .lang-flag{ font-size:22px; }
  .lang-name{ font-weight:700; }
  .lang-app-name{ font-size:12px; color:var(--ink-soft); margin-top:2px; }

  /* ---- Header ---- */
  header{
    width:100%;
    max-width:420px;
    display:flex;
    align-items:center;
    justify-content:space-between;
    padding-bottom:14px;
    margin-bottom:20px;
    border-bottom:1px solid var(--hairline);
  }
  .brand{
    font-family:var(--serif);
    font-size:18px;
    font-weight:700;
    letter-spacing:1px;
    color:var(--ink);
    display:flex;
    align-items:center;
    gap:8px;
  }
  .brand .dot{
    width:7px;height:7px;border-radius:50%;
    background:var(--seal);
    display:inline-block;
  }
  .icon-btn{
    width:36px;height:36px;
    border-radius:50%;
    border:1px solid var(--line);
    background:#fff;
    display:flex;align-items:center;justify-content:center;
    cursor:pointer;
    color:var(--ink-soft);
  }
  .icon-btn svg{width:18px;height:18px;}

  .revive-card{
    width:100%;
    max-width:420px;
    background:var(--sage-soft);
    border-radius:18px;
    padding:16px 18px;
    margin-bottom:14px;
  }
  .revive-card p{
    margin:0 0 12px;
    font-size:14px;
    color:var(--ink);
    line-height:1.5;
  }
  .revive-actions{
    display:flex;
    gap:10px;
  }
  .revive-actions .btn{
    padding:10px;
    font-size:14px;
  }

  #home-view{
    width:100%;
    max-width:420px;
  }

  /* ---- 今日字卡：簽名元素，像一張落了印章的紙條 ---- */
  .today-stamp-card{
    position:relative;
    background:#fff;
    border:1px solid var(--line);
    border-radius:6px;
    padding:24px 22px 22px;
    margin-bottom:22px;
    cursor:pointer;
    overflow:hidden;
  }
  .stamp-eyebrow{
    font-size:11px;
    letter-spacing:2px;
    color:var(--ink-soft);
    text-transform:uppercase;
    margin-bottom:14px;
  }
  .stamp-char{
    font-family:var(--serif);
    font-size:64px;
    font-weight:600;
    color:var(--ink);
    line-height:1;
    margin-bottom:18px;
  }
  .stamp-cta{
    display:flex;
    align-items:center;
    gap:6px;
    font-size:15px;
    font-weight:600;
    color:var(--seal);
  }
  .stamp-cta svg{ width:15px; height:15px; }
  .seal-mark{
    position:absolute;
    top:20px;
    right:20px;
    width:34px;
    height:34px;
    border:1.5px solid var(--seal);
    border-radius:3px;
    display:flex;
    align-items:center;
    justify-content:center;
    color:var(--seal);
    font-family:var(--serif);
    font-size:13px;
    font-weight:700;
    opacity:0.85;
    transform:rotate(-4deg);
  }

  /* ---- 統計細線列 ---- */
  .stat-hairline-row{
    display:flex;
    align-items:center;
    border-top:1px solid var(--hairline);
    border-bottom:1px solid var(--hairline);
    padding:18px 4px;
    margin-bottom:22px;
  }
  .stat-block{
    flex:1;
    display:flex;
    flex-direction:column;
    align-items:center;
    gap:4px;
  }
  .stat-num{
    font-family:var(--serif);
    font-size:30px;
    font-weight:700;
    color:var(--ink);
  }
  .stat-label{
    font-size:12px;
    letter-spacing:0.5px;
    color:var(--ink-soft);
  }
  .stat-divider{
    width:1px;
    height:32px;
    background:var(--hairline);
  }

  /* ---- 文字連結式入口（小測驗） ---- */
  .text-link-row{
    width:100%;
    background:none;
    border:none;
    border-top:1px solid var(--hairline);
    padding:16px 4px;
    display:flex;
    align-items:center;
    justify-content:space-between;
    font-size:14px;
    font-weight:600;
    color:var(--ink);
    cursor:pointer;
  }
  .text-link-row svg{ width:15px; height:15px; color:var(--ink-soft); }

  /* ---- 我的字庫：填補首頁下方，也讓家長一眼看到學過的字 ---- */
  .library-section{
    margin-top:8px;
    padding-top:18px;
  }
  .library-title{
    font-size:12px;
    letter-spacing:1.5px;
    color:var(--ink-soft);
    text-transform:uppercase;
    margin-bottom:12px;
  }
  .library-grid{
    display:flex;
    flex-wrap:wrap;
    gap:10px;
  }
  .library-chip{
    width:48px;
    height:48px;
    display:flex;
    align-items:center;
    justify-content:center;
    background:#fff;
    border:1px solid var(--line);
    border-radius:8px;
    font-size:22px;
    font-weight:600;
    color:var(--ink);
  }
  .library-empty{
    font-size:13px;
    color:var(--ink-soft);
    padding:8px 0;
  }

  /* ---- Practice stage ---- */
  .stage-wrap{
    width:100%;
    max-width:420px;
    background:#fff;
    border-radius:24px;
    padding:22px 18px 18px;
    box-shadow:0 2px 0 var(--line), 0 14px 30px -18px rgba(43,38,34,0.25);
    display:flex;
    flex-direction:column;
    align-items:center;
  }
  .progress-row{
    width:100%;
    display:flex;
    justify-content:space-between;
    align-items:center;
    margin-bottom:14px;
    font-size:13px;
    color:var(--ink-soft);
  }
  .streak{
    display:flex;align-items:center;gap:5px;
    font-weight:600;
    color:var(--coral);
  }
  .streak svg{width:14px;height:14px;flex-shrink:0;}
  .canvas-stage{
    position:relative;
    width:100%;
    max-width:260px;
    aspect-ratio:1/1;
    margin:0 auto;
  }
  #char-canvas-holder{
    width:100%;
    height:100%;
    background:
      linear-gradient(var(--paper-deep) 1px, transparent 1px) 0 0/100% 50%,
      linear-gradient(90deg, var(--paper-deep) 1px, transparent 1px) 0 0/50% 100%;
    background-color:#FFFDF9;
    border:2px solid var(--line);
    border-radius:16px;
  }

  .mistake-bubble{
    position:absolute;
    top:-14px;
    right:-8px;
    background:#fff;
    border:1.5px solid var(--coral-soft);
    color:var(--ink);
    font-size:13px;
    padding:8px 14px;
    border-radius:16px;
    box-shadow:0 6px 16px -8px rgba(43,38,34,0.3);
    pointer-events:none;
    opacity:0;
    transform:translateY(4px) scale(0.92);
    transition:opacity .2s, transform .2s;
    white-space:nowrap;
    z-index:10;
  }
  .mistake-bubble::after{
    content:'';
    position:absolute;
    bottom:-5px;
    right:22px;
    width:10px;height:10px;
    background:#fff;
    border-right:1.5px solid var(--coral-soft);
    border-bottom:1.5px solid var(--coral-soft);
    transform:rotate(45deg);
  }
  .mistake-bubble.show{
    opacity:1;
    transform:translateY(0) scale(1);
  }
  .controls{
    width:100%;
    display:flex;
    gap:10px;
    margin-top:18px;
  }
  .btn{
    flex:1;
    border:none;
    border-radius:14px;
    padding:13px 10px;
    font-size:15px;
    font-weight:600;
    cursor:pointer;
    display:flex;align-items:center;justify-content:center;gap:6px;
  }
  .btn-primary{
    background:var(--coral);
    color:#fff;
  }
  .btn-secondary{
    background:var(--paper-deep);
    color:var(--ink);
  }
  /* 停用時要「看起來就是不能按」。原本只有面板裡的按鈕有停用樣式，
     練習畫面這顆沒有——重複練習階段它是停用的，但看起來是完全正常的橘色按鈕，
     小孩會一直按、一直沒反應，不知道是壞了還是自己按錯。 */
  .btn:disabled{
    background:var(--paper-deep);
    color:var(--ink-soft);
    cursor:not-allowed;
  }
  .btn:disabled:active{ transform:none; }
  .btn:active{ transform: scale(0.97); }

  .hint-banner{
    margin-top:14px;
    width:100%;
    text-align:center;
    font-size:13px;
    color:var(--ink-soft);
    background:var(--paper-deep);
    border-radius:12px;
    padding:9px;
    min-height:18px;
    transition:opacity .2s;
  }

  .practice-record{
    margin-top:10px;
    width:100%;
    text-align:center;
    font-size:12px;
    color:var(--ink-soft);
    min-height:16px;
  }

  /* ---- Today list FAB & panel ---- */
  .sheet-overlay{
    position:fixed;inset:0;
    background:rgba(43,38,34,0.4);
    display:none;
    align-items:flex-end;
    justify-content:center;
    z-index:100;
  }
  .sheet-overlay.open{display:flex;}
  /* 底部不留內距：關閉按鈕是sticky釘在最下面的，只要面板底下還有內距，
     那條縫就會透出正在捲動的內容（用box-shadow去補會蓋到相鄰按鈕，不可靠）。
     讓按鈕直接貼齊面板底緣，縫就不存在。 */
  .sheet{
    width:100%;
    max-width:460px;
    background:var(--paper);
    border-radius:24px 24px 0 0;
    padding:22px 20px 0;
    max-height:78vh;
    overflow-y:auto;
  }
  /* 扭蛋機面板的按鈕一開始是隱藏的（要轉完才出現），
     底部沒內距的話文字會貼到螢幕邊緣，這裡補回來 */
  .gacha-sheet{ padding-bottom:24px; }
  .sheet h3{
    margin:0 0 4px;
    font-size:18px;
  }
  .sheet p.sub{
    margin:0 0 16px;
    font-size:13px;
    color:var(--ink-soft);
  }
  .input-row{
    display:flex;
    gap:8px;
    margin-bottom:16px;
  }
  .input-row input{
    -webkit-appearance:none;
    appearance:none;
    flex:1;
    border:1.5px solid var(--line);
    border-radius:12px;
    padding:11px 14px;
    font-size:16px;
    background:#fff;
    color:var(--ink);
    font-family:inherit;
  }
  .input-row input:focus{ outline:2px solid var(--coral-soft); border-color:var(--coral); }
  .input-row button{
    border:none;
    background:var(--ink);
    color:#fff;
    border-radius:12px;
    padding:0 18px;
    font-size:15px;
    font-weight:600;
    cursor:pointer;
  }
  .chip-list{
    display:flex;
    flex-wrap:wrap;
    gap:8px;
    margin-bottom:18px;
  }
  .chip{
    display:flex;align-items:center;gap:6px;
    background:#fff;
    border:1.5px solid var(--line);
    border-radius:20px;
    padding:7px 8px 7px 14px;
    font-size:15px;
  }
  .chip button{
    border:none;background:var(--paper-deep);
    width:20px;height:20px;border-radius:50%;
    font-size:13px;line-height:1;
    color:var(--ink-soft);
    cursor:pointer;
  }
  .chip.selectable{
    cursor:pointer;
    border-color:var(--line);
  }
  .chip.selectable.selected{
    background:var(--coral);
    border-color:var(--coral);
    color:#fff;
  }
  .btn-primary-sheet{
    background:var(--coral) !important;
    color:#fff !important;
    margin-bottom:8px;
  }
  .btn-primary-sheet:disabled{
    background:var(--paper-deep) !important;
    color:var(--ink-soft) !important;
    cursor:not-allowed;
  }
  .quiz-summary-item{
    display:flex;
    align-items:center;
    justify-content:space-between;
    padding:12px 14px;
    background:#fff;
    border:1.5px solid var(--line);
    border-radius:12px;
    margin-bottom:8px;
    font-size:15px;
  }
  .quiz-summary-item .status{
    font-size:13px;
    color:var(--sage);
    font-weight:600;
  }
  .quiz-summary-item.needs-practice .status{
    color:var(--coral);
  }

  /* 全部清除：刻意做成低調的文字連結，不是按鈕。
     它是逃生門（家長貼錯東西時一次清掉重來），不是主要動作，
     不該跟「加入」「完成」搶注意力。 */
  /* 練習畫面的範例開關。跟 .clear-all-link 同一種調性（輔助動作、不搶注意力），
     但置中而不是靠右——它在提示列正下方，靠右會跟上面置中的提示文字錯開。 */
  .outline-link{
    display:block;
    margin:8px auto 0;
    padding:6px 10px;
    background:none;
    border:none;
    font-size:13px;
    color:var(--ink-soft);
    text-decoration:underline;
    cursor:pointer;
    touch-action:manipulation;
  }

  .clear-all-link{
    display:block;
    margin:-8px 0 18px auto;
    padding:6px 2px;
    background:none;
    border:none;
    font-size:13px;
    color:var(--ink-soft);
    text-decoration:underline;
    cursor:pointer;
    touch-action:manipulation;
  }

  .empty-note{
    font-size:13px;
    color:var(--ink-soft);
    background:#fff;
    border:1px dashed var(--line);
    border-radius:12px;
    padding:14px;
    text-align:center;
  }
  .onboarding-hint{
    font-size:13px;
    color:var(--seal);
    text-align:center;
    margin-top:-4px;
    margin-bottom:12px;
  }
  .repeat-options{
    display:flex;
    gap:10px;
    margin-bottom:20px;
  }
  .repeat-option{
    flex:1;
    border:1.5px solid var(--line);
    background:#fff;
    color:var(--ink);
    border-radius:14px;
    padding:14px 8px;
    font-size:16px;
    font-weight:600;
    cursor:pointer;
  }
  .repeat-option.active{
    background:var(--coral);
    border-color:var(--coral);
    color:#fff;
  }

  /* 釘在面板底部：內容（圖鑑30格、學過的字清單）長起來之後，
     原本要一路捲到底才按得到關閉按鈕，很不方便。sticky讓按鈕永遠停在
     畫面下緣，內容從後面捲過去。改共用樣式，所有面板一次全部受惠。 */
  .close-sheet{
    display:block;
    width:100%;
    text-align:center;
    margin-top:6px;
    padding:13px 13px 20px;
    border:none;
    background:var(--paper-deep);
    color:var(--ink);
    border-radius:14px;
    font-size:15px;
    font-weight:600;
    cursor:pointer;
    position:sticky;
    bottom:0;
    z-index:2;
  }
  /* 小測驗面板有上下兩顆按鈕（開始複習／先不要），
     上面那顆要往上墊一顆按鈕的高度，不然兩顆會疊在一起 */
  /* 小測驗面板有上下兩顆按鈕（開始複習／先不要）：上面那顆要往上墊
     一顆按鈕的高度才不會疊在一起，並用同色陰影補掉兩顆之間6px的margin縫 */
  #start-quiz-btn,
  .onboarding-mode #close-sheet-btn{
    bottom:60px;
    z-index:3;
    padding-bottom:13px;
    box-shadow:0 6px 0 var(--paper);
  }

  .star-burst{
    position:fixed;
    pointer-events:none;
    width:36px;height:36px;
    z-index:200;
    animation:burst 0.85s ease-out forwards;
  }
  .star-burst svg{ width:100%; height:100%; }
  @keyframes burst{
    0%{ transform:translate(-50%,-50%) scale(0.3); opacity:0; }
    25%{ transform:translate(-50%,-50%) scale(1.15); opacity:1; }
    100%{ transform:translate(-50%,-160%) scale(0.9); opacity:0; }
  }

  /* =========================================================
     動物收藏：首頁橫向縮圖列 + 扭蛋機抽獎 + 圖鑑頁面
     ========================================================= */
  .collection-header{
    display:flex;
    align-items:center;
    justify-content:space-between;
    margin-bottom:12px;
  }
  .collection-header .library-title{ margin-bottom:0; }
  .collection-view-all{
    display:flex;
    align-items:center;
    gap:2px;
    border:none;
    background:none;
    padding:0;
    font-size:13px;
    color:var(--ink-soft);
    cursor:pointer;
  }
  .collection-view-all svg{ width:14px; height:14px; }
  .collection-strip{
    display:flex;
    gap:10px;
    overflow-x:auto;
    padding-bottom:4px;
    -webkit-overflow-scrolling:touch;
  }
  .collection-strip::-webkit-scrollbar{ display:none; }
  .collection-thumb{
    flex:0 0 auto;
    width:48px;
    height:48px;
    border-radius:50%;
    background:#fff;
    border:1px solid var(--line);
    overflow:hidden;
  }
  .collection-thumb img{ width:100%; height:100%; display:block; }

  /* ---- 圖鑑：30格方格牆，沒收集到的顯示灰色剪影 ---- */
  .badge-row{
    display:flex;
    flex-direction:column;
    gap:8px;
    margin-bottom:18px;
  }
  /* 徽章牆固定兩列高、自己橫向捲動：21輪之後全是同色的硃紅徽章，
     再多也不會有新資訊，讓它無限往下長會把動物格子整個推出畫面外。
     grid-auto-flow:column＋兩列，徽章會一欄兩個往右排，高度永遠固定。 */
  .badge-wall{
    display:grid;
    grid-template-rows:repeat(2, auto);
    grid-auto-flow:column;
    grid-auto-columns:38px;
    gap:6px;
    overflow-x:auto;
    padding-bottom:4px;
    -webkit-overflow-scrolling:touch;
  }
  .badge-wall::-webkit-scrollbar{ height:4px; }
  .badge-wall::-webkit-scrollbar-thumb{ background:var(--line); border-radius:2px; }
  .badge-wall img{ width:38px; height:auto; display:block; }
  .badge-row .badge-caption{
    font-size:13px;
    color:var(--ink-soft);
  }
  .gallery-grid{
    display:grid;
    grid-template-columns:repeat(5, 1fr);
    gap:10px;
    margin-bottom:18px;
  }
  .gallery-cell{
    aspect-ratio:1 / 1;
    border-radius:50%;
    background:#fff;
    border:1px solid var(--line);
    overflow:hidden;
  }
  .gallery-cell img{ width:100%; height:100%; display:block; }
  .gallery-cell.locked{
    background:var(--paper-deep);
    display:flex;
    align-items:center;
    justify-content:center;
    color:var(--ink-soft);
    font-size:18px;
  }
  .gallery-cell.locked img{
    filter:grayscale(1) opacity(0.28);
  }
  /* 已收集的才點得開放大檢視；鎖住的維持預設游標、點了沒反應 */
  .gallery-cell:not(.locked){ cursor:pointer; }
  /* touch-action 不會繼承，body 設了不代表這裡有。這格是雙擊縮放的實際災區：
     鎖住的動物點了沒反應 → 小孩再點一次 → 整個畫面被放大。 */
  .gallery-cell{ touch-action:manipulation; }

  /* ---- 動物放大檢視（疊在圖鑑面板上面的第二層） ----
     z-index 要比 .sheet-overlay(100) 高，才不會被圖鑑蓋住；
     但要比 .star-burst(200) 低，星星特效仍該飛在最上層。 */
  .animal-view-overlay{ z-index:150; }
  .animal-view-sheet{ text-align:center; }
  .animal-view-figure{
    width:180px; height:180px;
    margin:8px auto 0;
    border-radius:50%;
    background:#fff;
    border:1px solid var(--line);
    display:flex; align-items:center; justify-content:center;
    overflow:visible;
  }
  .animal-view-figure img{
    width:150px; height:150px; display:block;
    /* 進場彈跳一次，之後持續呼吸。兩個動畫接在一起：第二個delay等於第一個的長度。
       動畫套在整張圖上（不拆解動物內部部件）——這些SVG是靜態圖形、沒有可獨立
       活動的部位，拆解30隻的工作量會爆炸，跟「圖案是現成素材」的定位也不符。
       手法跟扭蛋機的 prizePop 一致。 */
    animation:animalPopIn 0.6s cubic-bezier(.34,1.56,.64,1) both,
              animalBreathe 2.2s ease-in-out 0.6s infinite;
  }
  @keyframes animalPopIn{
    0%{ transform:scale(0.3); opacity:0; }
    60%{ transform:scale(1.12); opacity:1; }
    80%{ transform:scale(0.97); }
    100%{ transform:scale(1); opacity:1; }
  }
  @keyframes animalBreathe{
    0%,100%{ transform:scale(1); }
    50%{ transform:scale(1.06); }
  }
  .animal-view-sheet h3{ margin:16px 0 4px; }
  /* 會暈車/前庭敏感的使用者：關掉動畫，圖案照樣看得到 */
  @media (prefers-reduced-motion: reduce){
    .animal-view-figure img{ animation:none; }
  }

  /* ---- 扭蛋機：轉旋鈕 → 蛋掉下來 → 自動散開 → 圖案彈出 ---- */
  .gacha-sheet{ text-align:center; }
  .gacha-machine-wrap{ padding-top:4px; }
  .gacha-machine{ width:170px; height:auto; overflow:visible; }
  #gacha-knob{ transform-origin:150px 186px; cursor:pointer; }
  .gacha-knob-idle{ animation:knobIdle 1.6s ease-in-out infinite; }
  .gacha-knob-spin{ animation:knobSpin 0.7s cubic-bezier(.35,0,.25,1); }
  @keyframes knobIdle{
    0%,88%,100%{ transform:rotate(0); }
    92%{ transform:rotate(-11deg); }
    96%{ transform:rotate(7deg); }
  }
  @keyframes knobSpin{ to{ transform:rotate(360deg); } }
  .gacha-eggs-shake{ animation:eggsShake 0.16s 4; }
  @keyframes eggsShake{
    0%,100%{ transform:translateY(0); }
    25%{ transform:translateY(-3px) rotate(-2deg); }
    75%{ transform:translateY(3px) rotate(2deg); }
  }

  .gacha-stage{
    position:relative;
    height:96px;
    display:flex;
    align-items:center;
    justify-content:center;
  }
  .gacha-egg{
    position:absolute;
    width:76px;
    height:76px;
    transition:transform .3s ease, opacity .3s ease;
  }
  .gacha-egg.dropping{ animation:eggDrop 0.55s cubic-bezier(.3,1.4,.6,1); }
  .gacha-egg.opening{ transform:scale(1.15); opacity:0; }
  @keyframes eggDrop{
    0%{ transform:translateY(-56px) scale(0.7); opacity:0; }
    60%{ transform:translateY(6px) scale(1.05); opacity:1; }
    100%{ transform:translateY(0) scale(1); opacity:1; }
  }
  .gacha-confetti{
    position:absolute;
    width:90px;
    height:90px;
    pointer-events:none;
  }
  .gacha-prize{
    position:absolute;
    width:92px;
    height:92px;
    animation:prizePop 0.4s cubic-bezier(.3,1.5,.6,1);
  }
  .gacha-prize img{ width:100%; height:100%; display:block; }
  @keyframes prizePop{
    0%{ transform:scale(0.3); opacity:0; }
    70%{ transform:scale(1.12); }
    100%{ transform:scale(1); opacity:1; }
  }
  .gacha-caption{
    margin:6px 0 14px;
    font-size:14px;
    color:var(--ink-soft);
    min-height:20px;
  }
  /* 轉扭蛋的按鈕。原本唯一能點的是SVG裡的旋鈕，實際只有約29×29px——
     低於iOS(44)跟Android(48)的最小觸控建議，而使用者是3-8歲、手指準頭差。
     而且最大最顯眼的蛋艙(約105px)反而不能點，小孩的直覺會落空。
     .btn 預設是 flex:1（給並排的按鈕列用的），這裡是單獨一顆，要改成滿寬。 */
  .gacha-spin-btn{
    flex:none;
    width:100%;
    margin:10px 0 4px;
  }

  /* =========================================================
     星星獎勵：首頁展示區（小孩只能看）+ 設定裡的獎勵設定（大人操作）
     ========================================================= */
  .reward-stars{
    display:flex;
    align-items:center;
    gap:3px;
  }
  .reward-stars svg{ width:18px; height:18px; }
  .reward-stars .star-num{
    font-size:14px;
    font-weight:600;
    color:var(--ink);
    margin-left:2px;
  }
  .reward-progress{
    font-size:13px;
    color:var(--ink-soft);
  }
  #reward-section.locked{ cursor:pointer; }

  .reward-setup input[type="text"],
  .reward-setup input[type="number"]{
    -webkit-appearance:none;
    appearance:none;
    border:1.5px solid var(--line);
    border-radius:12px;
    padding:11px 13px;
    font-size:15px;
    font-family:inherit;
    background:#fff;
    color:var(--ink);
    width:100%;
    margin-bottom:8px;
  }
  .reward-rule{
    background:#fff;
    border:1px solid var(--line);
    border-radius:14px;
    padding:12px 12px 4px;
    margin-bottom:10px;
  }
  .reward-rule-row{
    display:flex;
    align-items:center;
    gap:8px;
  }
  .reward-rule-row input[type="number"]{ width:78px; flex:0 0 auto; }
  .reward-rule-row span{
    font-size:14px;
    color:var(--ink-soft);
    margin-bottom:8px;
    flex:1;
  }
  .reward-rule-remove{
    flex:0 0 auto;
    width:30px;
    height:30px;
    margin-bottom:8px;
    border:none;
    border-radius:50%;
    background:var(--paper-deep);
    color:var(--ink-soft);
    font-size:14px;
    line-height:1;
    cursor:pointer;
  }
  .reward-rule .reward-redeem-btn{ margin-bottom:8px; }
  .reward-add-btn{
    display:block;
    width:100%;
    padding:11px;
    border:1.5px dashed var(--line);
    border-radius:14px;
    background:none;
    color:var(--ink-soft);
    font-size:14px;
    font-family:inherit;
    cursor:pointer;
  }
  .reward-status{
    font-size:13px;
    color:var(--ink-soft);
    margin:2px 0 10px;
  }
  .reward-redeem-btn{
    display:block;
    width:100%;
    padding:12px;
    border:none;
    border-radius:14px;
    background:var(--coral);
    color:#fff;
    font-size:15px;
    font-weight:600;
    font-family:inherit;
    cursor:pointer;
  }
  .reward-redeem-btn:disabled{
    background:var(--paper-deep);
    color:var(--ink-soft);
    cursor:default;
  }
  .reward-locked{
    font-size:13px;
    color:var(--ink-soft);
    padding:12px 0 4px;
  }

  /* ---- 獎勵檢視面板（小孩看得到目標，但沒有兌換按鈕） ---- */
  .reward-view-stars{
    display:flex;
    align-items:center;
    flex-wrap:wrap;
    gap:3px;
    margin-bottom:18px;
  }
  .reward-view-stars svg{ width:22px; height:22px; }
  .reward-view-stars .star-num{
    font-size:14px;
    color:var(--ink-soft);
    margin-left:6px;
  }
  .reward-view-item{
    background:#fff;
    border:1px solid var(--line);
    border-radius:14px;
    padding:14px 16px;
    margin-bottom:10px;
  }
  .reward-view-item.ready{ border-color:var(--coral); }
  .reward-view-name{
    font-size:16px;
    font-weight:600;
    color:var(--ink);
    margin-bottom:8px;
  }
  .reward-view-meter{
    display:flex;
    align-items:center;
    flex-wrap:wrap;
    gap:3px;
  }
  .reward-view-meter svg{ width:18px; height:18px; }
  .reward-view-note{
    font-size:13px;
    color:var(--ink-soft);
    margin-left:6px;
  }
  .reward-view-item.ready .reward-view-note{ color:var(--coral); font-weight:600; }
  .reward-view-empty{
    font-size:14px;
    color:var(--ink-soft);
    padding:8px 0 12px;
  }
  .reward-view-howto{ margin-top:14px; }
  /* 付費牆的說明文字裡有換行，預設會被摺成一行 */
  #paywall-desc-text{ white-space:pre-line; }

  /* 輸入提示有兩種性質完全不同的訊息，顏色要分開：
     warn＝字被擋下來了（紅），info＝只是告知（灰）。
     「已經學會了」是好消息，用紅色會讓家長以為出事了。 */
  #char-warning-hint .hint-warn{ color:var(--seal); }
  #char-warning-hint .hint-info{ color:var(--ink-soft); }
  #char-warning-hint .hint-warn + .hint-info{ margin-top:4px; }

  /* ---- 橫向（landscape）：欄寬與練習格子放寬，維持置中卡片、兩側留白，
     避免內容被拉得過寬、閱讀操作體驗變差。只在橫向生效，直向不受影響。 ---- */
  @media (min-width: 700px) and (orientation: landscape){
    header, .revive-card, #home-view, .stage-wrap{
      max-width:520px;
    }
    .canvas-stage{
      max-width:340px;
    }
    .stamp-char{
      font-size:78px;
    }
  }

  /* ---- 直向（portrait）：不管螢幕多寬（手機還是平板直放），都滿版貼齊邊緣，
     不要置中卡片留白。手機本來就比420px窄，這條規則主要影響直放的平板。 ---- */
  @media (orientation: portrait) and (min-width: 421px){
    header, .revive-card, #home-view, .stage-wrap, .sheet{
      max-width:none;
    }
  }
