/* ============================================================================
   汉字乐园 · 前识字  ——  视觉系统（第八套）
   ============================================================================
   八套之间的关系（沿用「每套必须互相区隔」的规矩，第八列）：

     四上 深蓝紫渐变 + 霓虹光晕       材质底
     五上 米白纸 + 22px 网格          材质底
     六上 冷灰蓝坐标纸（双密度格）    材质底
     三上 近黑深空 + 星点 + 星云       材质底
     二上 奶油白 + 糖纸波点           材质底
     一上 绘本纸 + 纸纤维 + 蜡笔颗粒   材质底
     七上 天空 / 云 / 远山 / 草坡 / 树  **户外场景底**（站在森林里）
     八上 泥墙 / 木台面 / 挂绳卡片     **室内台面底**（坐在书桌前看牌子）

   第七套与第八套都用「场景底」，但一个是**户外**（有天空、有草坡、动物站在地上），
   一个是**室内**（一面暖灰泥墙，底下一条木台面，卡片"放在台面上"）。
   这不是为了不一样而不一样 —— 第八套 8 个游戏里的东西
   （门牌、货架、清单、便签、招牌、描画）本来就全是室内和街面的物件。

   ⚠ 主色为什么从森林绿换成赭石 #A9663A：
     这一套的主角是「字」，而赭石就是甲骨段的颜色。用一个语义自洽的颜色当主色，
     比"换个好看的绿"有道理。品牌色 --sun 阳光黄继续沿用，两套放在一起还是一家的。

   ⚠ 两条从第七套带过来的教训，这里同样适用：
     ① 白底衬：暖墙底上，浅色元素靠"更浅"是分不出来的，要么给白底衬，要么靠色相差。
     ② 亮底必须用深字：白描边只适合衬托深色字，不能用来"提亮"浅色字。

   ⚠ 一条第八套自己的新规矩：
     **游戏里不许用颜色区分字形。**「字在长大」关如果三段各带自己的材质色
     （赭石 / 铜绿 / 墨），孩子按颜色就排出来了 —— 考的是看形状，那就得先同色。
     所以 .glyph 一律中性底，材质色只在「字表 / 家长看板」这类"看完就懂"的地方出现。
     见 art.js 的 recolor()。
   ============================================================================ */

:root{
  /* 底：室内 —— 泥墙 + 木台面 */
  --wall:#F4EEE4;   --wall-d:#E8DFD1;  --wall-l:#FBF7F0;
  --desk:#C99A6B;   --desk-d:#A87A50;  --desk-l:#D9BE9A;
  /* 主色：赭石（= 甲骨段的颜色） */
  --ochre:#A9663A;  --ochre-d:#8A4E28; --ochre-l:#FBF1E9;
  /* 辅色 */
  --bronze:#5E7A56; --bronze-d:#4A6244; --bronze-l:#F0F5EE;
  --sun:#F2B33D;    --sun-d:#D9862A;   --sun-l:#FFF6DC;
  --sky:#74C7E8;    --berry:#E4574C;   --plum:#8B5FA8;  --blue:#4A7FE8;
  --cream:#FFF8EC;
  /* 墨 */
  --ink:#3A3025;    --ink-2:#6B5B49;   --ink-3:#9A8A76;
  --line:rgba(58,48,37,.10);

  --r:26px; --r-s:18px;
  --sh:0 6px 0 rgba(58,48,37,.15), 0 11px 20px rgba(58,48,37,.12);
  --sh-s:0 4px 0 rgba(58,48,37,.14), 0 7px 14px rgba(58,48,37,.10);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;height:100%}
body{
  background:#E4DCD0;font-family:"PingFang SC","Microsoft YaHei",-apple-system,sans-serif;
  color:var(--ink);-webkit-font-smoothing:antialiased;
  display:flex;align-items:center;justify-content:center;
}

/* ⚠ 宽度别写死 390：414 / 430 的真机（大屏 iPhone、安卓旗舰）占比不小，
   写死的话就是中间一条 390、两侧各留 12px 底色，像在看预览器而不像在用 App。
   clamp 让它在 320~430 之间撑满屏幕，再往上（平板 / 桌面）才定死在 430。
   内部元素绝大多数是百分比或 flex，宽度略变不会错位；固定 px 的那几个
   （门 132px、字形格 82px）本来就是居中的，也安全。 */
.phone{
  position:relative;width:clamp(320px,100vw,430px);height:844px;max-height:100vh;overflow:hidden;
  background:var(--wall);
  box-shadow:0 0 0 1px rgba(0,0,0,.06), 0 22px 60px rgba(58,48,37,.28);
}

/* ---- 底：一面泥墙 ---------------------------------------------------------
   两层极淡的横向抹痕 + 三块色斑 —— 目的是"有温度的手工墙面"，
   不是"贴了一张花纹纸"。所以全部用低对比度的大尺度渐变，凑近才看得出。 */
.room{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.room::before{
  content:"";position:absolute;inset:0;
  background:
    repeating-linear-gradient(180deg,rgba(255,255,255,.5) 0 3px,rgba(0,0,0,0) 3px 17px),
    radial-gradient(ellipse 300px 160px at 18% 22%,rgba(255,255,255,.62),transparent 70%),
    radial-gradient(ellipse 260px 200px at 86% 46%,rgba(169,102,58,.055),transparent 72%),
    radial-gradient(ellipse 340px 180px at 40% 82%,rgba(94,122,86,.05),transparent 74%);
}
/* 木台面：卡片"放在台面上"的那条边
   ⚠ 必须 pointer-events:none。它是装饰层，盖在内容之上；
     第一版忘了加，结果它把底部 150px 内的所有按钮点击全吃掉了
     —— 游戏页的答题按钮正好在这一带，孩子点不动，Playwright 也点不动。 */
.desk{position:absolute;left:0;right:0;bottom:0;height:150px;pointer-events:none}
.desk::before{
  content:"";position:absolute;left:0;right:0;top:0;height:14px;border-radius:8px 8px 0 0;
  background:linear-gradient(180deg,var(--desk-l),var(--desk));
  box-shadow:0 -4px 12px rgba(58,48,37,.14);
}
.desk::after{
  content:"";position:absolute;left:0;right:0;top:14px;bottom:0;
  background:
    repeating-linear-gradient(96deg,rgba(138,94,60,.14) 0 2px,rgba(0,0,0,0) 2px 26px),
    linear-gradient(180deg,var(--desk),var(--desk-d));
}
/* 墙上挂的几枚小木钉 —— 让"这面墙可以挂东西"成立 */
.pegs{position:absolute;inset:0}
.peg{position:absolute;width:11px;height:11px;border-radius:50%;
  background:linear-gradient(160deg,var(--desk-l),var(--desk-d));
  box-shadow:0 2px 3px rgba(58,48,37,.25), inset 0 -1px 1px rgba(0,0,0,.14)}

/* ---- 状态栏（与第七套一致：是个装饰性的假状态栏）------------------------- */
.statusbar{position:absolute;top:0;left:0;right:0;height:46px;z-index:7;
  display:flex;align-items:center;justify-content:space-between;padding:0 24px;
  font-size:13px;font-weight:800;color:var(--ink);pointer-events:none}
.sb-right{display:inline-flex;align-items:center;gap:6px}
.sb-bat{width:23px;height:11.5px;border-radius:3.5px;border:1.6px solid var(--ink);
  position:relative;display:inline-block}
.sb-bat i{position:absolute;left:1.6px;top:1.6px;bottom:1.6px;width:68%;
  border-radius:2px;background:var(--ink)}
.sb-bat::after{content:"";position:absolute;right:-4px;top:3.2px;width:2.4px;height:5px;
  border-radius:0 1.6px 1.6px 0;background:var(--ink)}

/* ---- 滚动容器 -------------------------------------------------------------
   ⚠ 真滚动容器是 #app，不是 .scroll —— .scroll 只是内层一个 padding-bottom 的类。
     第七套就是在这里栽过：对 .scroll 调 scrollTo 完全没反应，
     而且被 .catch(()=>{}) 吞掉，录出来五个镜头画面一模一样。 */
#app{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;z-index:2;
  scrollbar-width:none;-webkit-overflow-scrolling:touch}
#app::-webkit-scrollbar{display:none}
.scroll{padding-bottom:170px}

/* ---- 字：三级字重 + 一套"墨色深浅"---------------------------------------- */
.t1{font-size:37px;line-height:1.24;font-weight:900}
.t2{font-size:25px;line-height:1.3;font-weight:900}
/* ⚠ 中文长标题换行时特别容易掉出"孤字"（最后一行只剩一个字）。
   414 宽下「每个字都带着它的画，和它的用处」就会把「处」单独挤到第二行 ——
   看着像排版坏了。balance 让两行尽量等长，比手写 <br> 稳：
   字号或屏宽一改，<br> 的位置就错了，balance 会跟着重算。 */
.t1,.t2{text-wrap:balance}
.t3{font-size:19px;line-height:1.34;font-weight:900}
.t4{font-size:16px;font-weight:900}
.t5{font-size:13.5px;font-weight:800}
.mut{color:var(--ink-3);font-weight:700}
.hl{background:linear-gradient(transparent 62%,#FFE9A8 62%);font-weight:800}
.ochre{color:var(--ochre-d)}
.bronze{color:var(--bronze-d)}

/* ---- 页头 ---------------------------------------------------------------- */
.head{padding:52px 22px 0;text-align:center;position:relative;z-index:1}
.kicker{display:inline-flex;align-items:center;gap:6px;background:rgba(255,255,255,.94);
  border-radius:999px;padding:6px 13px;font-size:11.5px;font-weight:900;
  color:var(--ochre-d);box-shadow:0 3px 0 rgba(58,48,37,.10)}
.kicker i{width:7px;height:7px;border-radius:50%;background:var(--ochre);display:block}
.head h1{margin:13px 0 0}
.head .sub{margin:11px 0 0;font-size:12.5px;color:var(--ink-2);font-weight:800}

/* 首页第一句：「这里不是识字课」—— 和第七套首页同一位置、同一角色 */
.firstword{margin:19px 0 0;display:inline-flex;align-items:center;gap:8px;
  background:#fff;border-radius:999px;padding:9px 18px;font-size:15px;font-weight:900;
  color:var(--ochre-d);box-shadow:var(--sh-s)}
.firstword .dot{width:9px;height:9px;border-radius:50%;background:var(--sun)}

/* ---- 字卡：这一套的主角 ---------------------------------------------------
   .zika = 挂绳卡片。::before 是穿孔，::after 是那根绳。
   只在「字表 / 字卡墙」用 —— 游戏里的选项卡不带绳，免得干扰。 */
.zika{position:relative;background:#fff;border-radius:20px;padding:14px 12px 12px;
  border:2px solid rgba(58,48,37,.07);box-shadow:var(--sh-s)}
.zika.hole{padding-top:22px}
.zika.hole::before{content:"";position:absolute;top:7px;left:50%;transform:translateX(-50%);
  width:9px;height:9px;border-radius:50%;background:var(--wall-d);
  box-shadow:inset 0 1.5px 2.5px rgba(58,48,37,.3)}
.zika.hole::after{content:"";position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:1.6px;height:7px;background:rgba(58,48,37,.22)}

/* ---- 字形框 ---------------------------------------------------------------
   ⚠ 中性底。见文件头那条「游戏里不许用颜色区分字形」。
     材质色只由 .glyph 里的 SVG 自己带（字表里），游戏里一律 recolor 成同色。 */
.glyph{width:100%;aspect-ratio:1;display:flex;align-items:center;justify-content:center;
  border-radius:15px;background:#FFFDF8;border:2px solid rgba(58,48,37,.09)}
.glyph svg{width:80%;height:80%;display:block}
.glyph.lg{aspect-ratio:auto;height:150px}
.glyph.xl{aspect-ratio:auto;height:196px}
/* 只有「看完就懂」的地方才能上材质色底（字表 / 家长看板） */
.tint.jia{background:var(--ochre-l);border-color:rgba(169,102,58,.2)}
.tint.zh{background:var(--bronze-l);border-color:rgba(94,122,86,.2)}
.tint.kai{background:#F8F6F1;border-color:rgba(58,48,37,.14)}

/* ---- 三段的小标签 -------------------------------------------------------- */
.stag{display:inline-flex;align-items:center;justify-content:center;border-radius:999px;
  padding:2px 9px;font-size:10.5px;font-weight:900;letter-spacing:.04em}
.stag.jia{background:var(--ochre-l);color:var(--ochre-d)}
.stag.zh {background:var(--bronze-l);color:var(--bronze-d)}
.stag.kai{background:#F0EDE6;color:var(--ink-2)}

/* ---- 插图框 -------------------------------------------------------------- */
.pic{width:100%;aspect-ratio:1;display:flex;align-items:center;justify-content:center;
  border-radius:18px;background:#fff;border:2px solid rgba(58,48,37,.07)}
.pic svg{width:86%;height:86%;display:block}

/* ---- 区块标题 ------------------------------------------------------------ */
.sec{padding:0 18px;margin-top:22px;position:relative;z-index:1}
.sec-h{display:flex;align-items:center;gap:8px;margin:0 4px 12px}
.sec-h .bar{width:5px;height:17px;border-radius:3px;background:var(--ochre)}
.sec-h .tx{font-size:16px;font-weight:900}
.sec-h .n{margin-left:auto;font-size:11.5px;font-weight:800;color:var(--ink-2);
  background:#fff;border-radius:999px;padding:3px 10px;box-shadow:0 2px 0 rgba(58,48,37,.09)}

/* ---- 面板 / 按钮 --------------------------------------------------------- */
.panel{background:#fff;border-radius:var(--r);padding:16px 17px;box-shadow:var(--sh);
  position:relative;z-index:1}
.panel p{margin:0 0 9px;font-size:13px;line-height:1.75;color:var(--ink-2);font-weight:700}
.panel p:last-child{margin-bottom:0}
.panel .hi{color:var(--ochre-d);font-weight:900}
.panel .gd{background:linear-gradient(transparent 62%,#FFE9A8 62%);font-weight:800;color:var(--ink)}
.panel ul{margin:0;padding-left:17px}
.panel li{font-size:12.5px;line-height:1.8;color:var(--ink-2);font-weight:700}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  border:0;border-radius:999px;padding:14px 24px;font-size:15px;font-weight:900;
  font-family:inherit;color:#fff;background:var(--ochre);cursor:pointer;
  box-shadow:0 4px 0 var(--ochre-d);transition:transform .1s,box-shadow .1s}
.btn:active{transform:translateY(3px);box-shadow:0 1px 0 var(--ochre-d)}
.btn.sun{background:var(--sun);color:var(--ink);box-shadow:0 4px 0 var(--sun-d)}
.btn.sun:active{box-shadow:0 1px 0 var(--sun-d)}
.btn.wide{display:flex;width:100%}
.btn.ghost{background:#fff;color:var(--ochre-d);box-shadow:0 4px 0 rgba(58,48,37,.14)}
.btn.ghost:active{box-shadow:0 1px 0 rgba(58,48,37,.14)}

/* ---- 首页：字卡墙（把"从画到字"直接摆出来，不用文字解释）------------------ */
.wall{display:flex;gap:10px;overflow-x:auto;padding:4px 18px 12px;
  scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;position:relative;z-index:1}
.wall::-webkit-scrollbar{display:none}
.wcard{flex:0 0 auto;width:118px;scroll-snap-align:start;
  background:#fff;border-radius:20px;padding:10px 9px;border:2px solid rgba(58,48,37,.07);
  box-shadow:var(--sh-s)}
.wcard .row3{display:flex;gap:3px;align-items:center}
.wcard .row3 .mini{flex:1;aspect-ratio:1;border-radius:9px;display:flex;
  align-items:center;justify-content:center}
.wcard .row3 .mini svg{width:100%;height:100%;display:block}
.wcard .row3 .arw{flex:0 0 auto;width:8px;text-align:center;font-size:9px;color:#CFC4B2}
.wcard .nm{margin-top:7px;text-align:center;font-size:11.5px;font-weight:900;color:var(--ink-2)}

/* ---- 首页：游戏卡（按三阶段分组）---------------------------------------- */
.stage-blk{margin-top:22px}
.stage-hd{display:flex;align-items:center;gap:10px;margin:0 22px 12px}
.stage-hd .no{width:36px;height:36px;border-radius:12px;flex:0 0 auto;display:flex;
  align-items:center;justify-content:center;font-size:15px;font-weight:900;color:#fff;
  box-shadow:0 3px 0 rgba(58,48,37,.18)}
.stage-hd .mid{flex:1;min-width:0}
.stage-hd .mid .nm{font-size:14.5px;font-weight:900}
.stage-hd .mid .sh{font-size:11.5px;font-weight:800;color:var(--ink-3);margin-top:2px}

.card{position:relative;display:flex;align-items:center;gap:13px;background:#fff;
  border-radius:var(--r-s);padding:13px 14px;margin-bottom:11px;cursor:pointer;
  border:2px solid rgba(58,48,37,.06);box-shadow:var(--sh-s);
  transition:transform .1s,box-shadow .1s}
.card:active{transform:translateY(3px) scale(.985);box-shadow:var(--sh-s)}
.card .thumb{width:58px;height:58px;border-radius:19px;flex:0 0 auto;display:flex;
  align-items:center;justify-content:center;background:var(--wall-l)}
.card .thumb svg{width:54px;height:54px;display:block}
.card .t{font-size:17px;font-weight:900}
.card .d{font-size:11.5px;color:var(--ink-3);margin-top:3px;font-weight:800}
.card .go{margin-left:auto;flex:0 0 auto;width:36px;height:36px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;background:var(--wall-l);
  color:var(--ochre-d);font-size:17px;font-weight:900}
.card .st{position:absolute;right:56px;top:12px;display:flex;gap:3px}
.card .st i{width:9px;height:9px;border-radius:50%;background:#E4DED4;display:block}
.card .st i.on{background:var(--sun);box-shadow:0 0 0 1.5px #fff inset}

/* ---- 字表：一张卡一个字 ------------------------------------------------ */
.zlist{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.zfull{background:#fff;border-radius:22px;padding:13px 12px 12px;
  border:2px solid rgba(58,48,37,.07);box-shadow:var(--sh-s)}
.zfull .top{display:flex;align-items:center;gap:8px;margin-bottom:9px}
.zfull .pic-top{width:44px;height:44px;flex:0 0 auto;border-radius:14px;
  background:var(--wall-l);display:flex;align-items:center;justify-content:center}
.zfull .pic-top svg{width:40px;height:40px;display:block}
.zfull .ziwrap{flex:1;min-width:0;text-align:right;font-size:30px;font-weight:900;
  color:var(--ink);line-height:1}
.zfull .three{display:flex;gap:5px}
.zfull .three .glyph{border-radius:12px}
.zfull .say{margin-top:9px;font-size:11.5px;line-height:1.62;font-weight:800;color:var(--ink-2)}
.zfull .life{margin-top:7px;font-size:10.5px;line-height:1.55;font-weight:800;
  color:var(--bronze-d);background:var(--bronze-l);border-radius:9px;padding:6px 8px}

/* ---- 游戏页 ------------------------------------------------------------- */
.g-top{display:flex;align-items:center;gap:10px;padding:52px 16px 0;position:relative;z-index:3}
.g-back{width:40px;height:40px;border-radius:50%;background:#fff;flex:0 0 auto;border:0;
  display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:900;
  color:var(--ink-2);box-shadow:var(--sh-s);cursor:pointer;font-family:inherit}
.g-back:active{transform:translateY(2px)}
.g-ti{background:#fff;border-radius:999px;padding:8px 16px;box-shadow:0 3px 0 rgba(58,48,37,.13);
  display:flex;align-items:center;gap:7px;font-size:14.5px;font-weight:900}
.g-prog{margin-left:auto;display:flex;gap:4px}
.g-prog i{width:9px;height:9px;border-radius:50%;background:rgba(255,255,255,.85);
  box-shadow:0 1px 2px rgba(58,48,37,.2)}
.g-prog i.on{background:var(--sun)}
.g-hint{margin:14px 22px 0;text-align:center;font-size:13px;font-weight:800;
  color:var(--ink-2);line-height:1.6}
.g-body{padding:16px 16px 0;position:relative;z-index:1}
.g-fb{margin-top:16px;border-radius:22px;padding:15px 17px;background:#fff;display:none;
  box-shadow:var(--sh)}
.g-fb.on{display:block;animation:pop .34s cubic-bezier(.2,1.5,.4,1)}
@keyframes pop{0%{transform:scale(.9) translateY(10px);opacity:0}100%{transform:none;opacity:1}}
.g-fb .h{display:flex;align-items:center;gap:8px;font-size:16px;font-weight:900}
.g-fb .h .dot{width:26px;height:26px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;color:#fff;font-size:14px;font-weight:900;flex:0 0 auto}
.g-fb .b{margin-top:8px;font-size:13px;line-height:1.7;color:var(--ink-2);font-weight:700}
.g-fb .act{margin-top:13px;display:flex;gap:9px}

@keyframes shakeX{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
@keyframes shakeY{0%,100%{transform:translateY(0)}40%{transform:translateY(-7px)}}

/* ---- 1 · 找标志：场景 + 相对坐标的可点目标 ------------------------------ */
.sg-stage{position:relative;width:100%;aspect-ratio:4/3;border-radius:22px;overflow:hidden;
  box-shadow:var(--sh);border:3px solid #fff;background:#DCEBF7}
.sg-stage svg.sg-bg{position:absolute;inset:0;width:100%;height:100%;display:block}
/* ⚠ 目标用绝对定位 + translate(-50%,-50%) 落在相对坐标上；
     命中区比看到的牌子大一圈（padding），手指按得准。 */
.sg-spot{position:absolute;transform:translate(-50%,-50%);border:0;background:none;padding:14px;
  cursor:pointer;font-family:inherit}
.sg-spot .tx{display:inline-flex;align-items:center;gap:5px;border-radius:12px;
  padding:6px 10px;font-size:13px;font-weight:900;box-shadow:0 3px 0 rgba(58,48,37,.18);
  transition:transform .12s;white-space:nowrap}
.sg-spot.sig .tx{background:var(--blue);color:#fff}
.sg-spot.wrd .tx{background:#fff;color:var(--ink);border:2.5px solid var(--bronze)}
.sg-spot.dec .tx{background:rgba(255,255,255,.9);color:var(--ink-3);box-shadow:none;
  font-weight:800;border:2px dashed #D8D0C0}
.sg-spot .tx svg{width:20px;height:20px;display:block}
.sg-spot:active .tx{transform:scale(.94)}
.sg-spot.found .tx{background:var(--sun)!important;color:var(--ink)!important;
  border-color:var(--sun-d)!important;animation:pop .36s}
.sg-spot.miss .tx{animation:shakeX .4s}
.sg-said{margin-top:13px;background:#fff;border-radius:20px;padding:13px 15px;
  box-shadow:var(--sh-s);min-height:56px;display:flex;align-items:center;gap:10px}
.sg-said .ic{width:32px;height:32px;border-radius:12px;flex:0 0 auto;display:flex;
  align-items:center;justify-content:center;background:var(--sun-l);font-size:16px}
.sg-said .tx{font-size:13px;font-weight:800;line-height:1.6;color:var(--ink-2)}
.sg-count{display:flex;gap:5px;justify-content:center;margin-top:11px}

/* ---- 2 · 门牌找家 ------------------------------------------------------- */
.door-house{background:#fff;border-radius:var(--r);padding:16px;box-shadow:var(--sh);
  text-align:center}
.door-house .ask{font-size:13.5px;font-weight:900;color:var(--ink-2);margin-bottom:12px}
.door-house .pic{width:132px;margin:0 auto;background:var(--wall-l);border:0}
.door-row{display:grid;grid-template-columns:repeat(3,1fr);gap:11px;margin-top:16px}
.door-plate{background:#fff;border:3px solid rgba(58,48,37,.1);border-radius:20px 20px 14px 14px;
  padding:16px 6px 12px;cursor:pointer;font-family:inherit;position:relative;
  box-shadow:0 4px 0 rgba(58,48,37,.12);transition:transform .1s}
.door-plate .zi{font-size:34px;font-weight:900;line-height:1;color:var(--ink)}
.door-plate .knob{margin:9px auto 0;width:13px;height:13px;border-radius:50%;
  background:var(--desk-l);box-shadow:inset 0 -1.5px 2px rgba(0,0,0,.18)}
.door-plate:active{transform:translateY(3px)}
.door-plate.right{border-color:var(--bronze);background:var(--bronze-l);animation:pop .4s}
.door-plate.wrong{border-color:var(--berry);background:#FDF0EE;animation:shakeX .4s}

/* ---- 3 · 认得出来吗 ----------------------------------------------------- */
.p3-pic{background:#fff;border-radius:var(--r);padding:16px;box-shadow:var(--sh)}
.p3-pic .pic{width:100%;aspect-ratio:1.5;background:var(--wall-l);border:0}
.p3-opts{display:grid;grid-template-columns:repeat(3,1fr);gap:11px;margin-top:14px}
.p3-opt{background:#fff;border:3px solid rgba(58,48,37,.1);border-radius:22px;padding:11px 7px;
  cursor:pointer;font-family:inherit;box-shadow:0 4px 0 rgba(58,48,37,.1);
  transition:transform .1s}
.p3-opt .glyph{border:0;background:transparent}
.p3-opt:active{transform:translateY(3px)}
.p3-opt.right{border-color:var(--bronze);background:var(--bronze-l);animation:pop .4s}
.p3-opt.wrong{border-color:var(--berry);background:#FDF0EE;animation:shakeX .4s}
.p3-rev{margin-top:14px;background:#fff;border-radius:22px;padding:14px;box-shadow:var(--sh);
  display:none}
.p3-rev.on{display:block;animation:pop .38s cubic-bezier(.2,1.5,.4,1)}
.p3-rev .row{display:flex;align-items:center;justify-content:center;gap:8px}
.p3-rev .row .glyph{width:82px;height:82px;aspect-ratio:auto;border:0;background:transparent}
.p3-rev .row .arw{font-size:16px;color:#CFC4B2;font-weight:900}
.p3-rev .note{margin-top:10px;text-align:center;font-size:12.5px;font-weight:800;color:var(--ink-2)}

/* ---- 4 · 一样的字 ------------------------------------------------------- */
.sm-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:11px}
.sm-cell{aspect-ratio:1;background:#fff;border:3px solid rgba(58,48,37,.1);border-radius:20px;
  display:flex;align-items:center;justify-content:center;cursor:pointer;font-family:inherit;
  box-shadow:0 4px 0 rgba(58,48,37,.1);transition:transform .1s}
.sm-cell .zi{font-size:40px;font-weight:900;line-height:1;color:var(--ink)}
.sm-cell:active{transform:scale(.95)}
.sm-cell.sel{border-color:var(--sun);background:var(--sun-l)}
.sm-cell.right{border-color:var(--bronze);background:var(--bronze-l);animation:pop .4s}
.sm-cell.wrong{border-color:var(--berry);background:#FDF0EE;animation:shakeX .4s}

/* ---- 5 · 字在长大 ------------------------------------------------------- */
.gr-slots{display:flex;gap:9px;justify-content:center}
.gr-slot{flex:1;aspect-ratio:.82;border-radius:20px;border:3px dashed #D8D0C0;
  background:rgba(255,255,255,.62);display:flex;flex-direction:column;
  align-items:center;justify-content:center;position:relative;padding:6px}
.gr-slot .no{position:absolute;top:7px;left:50%;transform:translateX(-50%);
  font-size:10.5px;font-weight:900;color:var(--ink-3)}
.gr-slot .glyph{width:100%;flex:1;border:0;background:transparent}
.gr-slot .stag{opacity:0;transition:opacity .4s}
.gr-slot.filled{border-style:solid;border-color:var(--bronze);background:#fff}
.gr-slot.filled .stag{opacity:1}
.gr-slots.done .gr-slot{border-color:var(--sun);background:#FFFCF4}
.gr-pool{display:grid;grid-template-columns:repeat(3,1fr);gap:11px;margin-top:16px}
.gr-card{background:#fff;border:3px solid rgba(58,48,37,.1);border-radius:20px;padding:10px 6px;
  cursor:pointer;font-family:inherit;box-shadow:0 4px 0 rgba(58,48,37,.1);
  transition:transform .1s,opacity .2s}
.gr-card .glyph{border:0;background:transparent}
.gr-card:active{transform:translateY(3px)}
.gr-card.wrong{border-color:var(--berry);background:#FDF0EE;animation:shakeX .4s}
.gr-card.used{opacity:.24;pointer-events:none}
.gr-arrow{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:15px;
  font-size:12px;font-weight:900;color:var(--ink-3)}

/* ---- 6 · 清单装篮 ------------------------------------------------------- */
.ls-stage{display:grid;grid-template-columns:1fr 92px;gap:12px;align-items:start}
.ls-note{background:#fff;border-radius:var(--r);padding:15px;box-shadow:var(--sh)}
.ls-note .ttl{font-size:11.5px;font-weight:900;color:var(--ink-3);letter-spacing:.06em}
.ls-note .want{margin-top:9px;display:flex;align-items:center;gap:11px;
  background:var(--sun-l);border-radius:16px;padding:10px 12px}
.ls-note .want .zi{font-size:38px;font-weight:900;line-height:1;color:var(--ink)}
.ls-note .want .q{font-size:12px;font-weight:800;color:var(--ink-2);line-height:1.5}
.ls-basket{background:#fff;border-radius:var(--r);padding:10px;box-shadow:var(--sh);
  display:flex;flex-direction:column;align-items:center;gap:6px}
.ls-basket svg{width:68px;height:68px;display:block}
.ls-basket .cnt{font-size:11.5px;font-weight:900;color:var(--ink-3)}
.ls-pool{display:grid;grid-template-columns:repeat(3,1fr);gap:11px;margin-top:14px}
.ls-card{background:#fff;border:3px solid rgba(58,48,37,.1);border-radius:22px;padding:10px 6px;
  cursor:pointer;font-family:inherit;box-shadow:0 4px 0 rgba(58,48,37,.1);transition:transform .1s}
.ls-card .pic{width:100%;aspect-ratio:1;border:0;background:var(--wall-l)}
.ls-card:active{transform:translateY(3px)}
.ls-card.right{border-color:var(--bronze);background:var(--bronze-l);animation:pop .4s}
.ls-card.wrong{border-color:var(--berry);background:#FDF0EE;animation:shakeX .4s}
.ls-card.used{opacity:.26;pointer-events:none}

/* ---- 7 · 写个便条 ------------------------------------------------------- */
.nt-note{position:relative;background:#FFFDF4;border-radius:6px 22px 22px 22px;
  padding:16px 17px;box-shadow:var(--sh);border:2px solid rgba(242,179,61,.32)}
.nt-note::before{content:"";position:absolute;left:0;top:0;width:0;height:0;
  border-left:20px solid var(--wall-d);border-bottom:20px solid transparent}
.nt-note .who{display:flex;align-items:center;gap:9px}
.nt-note .who svg{width:44px;height:44px;flex:0 0 auto;display:block}
.nt-note .who .tx{font-size:14.5px;font-weight:900;line-height:1.5}
.nt-blank{margin-top:13px;display:flex;align-items:center;gap:9px;
  background:#fff;border-radius:16px;padding:11px 13px;border:2px dashed var(--sun)}
.nt-blank .slot{width:44px;height:44px;border-radius:12px;background:var(--sun-l);
  display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:900;
  color:var(--ink-3);flex:0 0 auto}
.nt-blank .slot.on{color:var(--ink);font-size:30px;line-height:1}
.nt-opts{display:grid;grid-template-columns:repeat(3,1fr);gap:11px;margin-top:14px}
.nt-opt{background:#fff;border:3px solid rgba(58,48,37,.1);border-radius:20px;padding:14px 6px;
  cursor:pointer;font-family:inherit;box-shadow:0 4px 0 rgba(58,48,37,.1);transition:transform .1s}
.nt-opt .zi{font-size:36px;font-weight:900;line-height:1;color:var(--ink)}
.nt-opt:active{transform:translateY(3px)}
.nt-opt.right{border-color:var(--bronze);background:var(--bronze-l);animation:pop .4s}
.nt-opt.wrong{border-color:var(--berry);background:#FDF0EE;animation:shakeX .4s}

/* ---- 8 · 假装写字（描画）---------------------------------------------- */
.tr-wrap{background:#fff;border-radius:var(--r);padding:12px;box-shadow:var(--sh)}
/* ⚠ 这里用 .tr-wrap svg 而不是 svg.trace —— ART.trace() 出来的 SVG 上没有 class，
    第一版写成 svg.trace，结果是 querySelector 返回 null，描画关直接崩。 */
.tr-wrap svg{display:block;width:100%;height:auto;touch-action:none;cursor:crosshair}
/* ⚠ 描画的墨迹直接画在这个 overlay 上，而不是给 tr-line 改色 ——
     改色会让"已经描过的笔画"和"还没描的"分不清，而且没法重画。 */
.tr-prog{display:flex;align-items:center;gap:9px;margin-top:13px;padding:0 4px}
.tr-prog .bar{flex:1;height:11px;border-radius:6px;background:#EFEAE0;overflow:hidden}
.tr-prog .bar i{display:block;height:100%;width:0;border-radius:6px;
  background:linear-gradient(90deg,var(--ochre),var(--sun));transition:width .2s}
.tr-prog .pc{font-size:13px;font-weight:900;color:var(--ochre-d);min-width:44px;text-align:right}
.tr-note{text-align:center;font-size:12.5px;font-weight:800;color:var(--ink-3);margin-top:11px}

/* ---- 结果页 ------------------------------------------------------------ */
.res-wrap{text-align:center;padding:26px 22px 0;position:relative;z-index:1}
.res-badge{width:132px;height:132px;border-radius:50%;margin:0 auto;background:#fff;
  display:flex;align-items:center;justify-content:center;position:relative;
  box-shadow:var(--sh)}
.res-badge svg{width:86px;height:86px;display:block}
.res-badge::after{content:"";position:absolute;inset:-16px;border-radius:50%;
  border:4px dashed rgba(242,179,61,.55);animation:spin 9s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.res-t{margin:22px 0 0;font-size:25px;font-weight:900}
.res-s{margin:9px 0 0;font-size:13px;font-weight:800;color:var(--ink-2)}
.res-stars{display:flex;gap:9px;justify-content:center;margin-top:17px}
.res-stars svg{width:40px;height:40px}
/* ⚠ 选择器要和 HTML 对得上：亮不亮是在外层 <span> 上加 .on，
   不是加在 svg 上。第一版写成 `.res-stars svg.on path`，
   结果三颗星永远是灰的 —— 而"星是灰的"在截图里一点都不显眼，很容易放过。 */
.res-stars span svg path{fill:#E4DED4}
.res-stars span.on svg path{fill:var(--sun)}
.res-stars span.on svg{filter:drop-shadow(0 3px 0 rgba(217,134,42,.35))}
.res-act{display:grid;gap:10px;margin-top:22px}

/* ---- 家长看板 ---------------------------------------------------------- */
.rep-top{padding:52px 22px 0;text-align:center;position:relative;z-index:1}
.rep-top .tt{font-size:23px;font-weight:900}
.rep-top .ss{font-size:12.5px;font-weight:800;color:var(--ink-2);margin-top:8px}
.stage-line{display:flex;flex-direction:column;gap:0}
.sl-row{display:flex;gap:12px}
.sl-left{display:flex;flex-direction:column;align-items:center;flex:0 0 34px}
.sl-dot{width:34px;height:34px;border-radius:12px;display:flex;align-items:center;
  justify-content:center;font-size:14px;font-weight:900;color:#fff;flex:0 0 auto;
  box-shadow:0 3px 0 rgba(58,48,37,.16)}
.sl-dot.off{background:#DED6C8!important;color:#fff;box-shadow:none}
.sl-bar{flex:1;width:5px;border-radius:3px;background:#E8DFD1;margin:5px 0}
.sl-body{flex:1;min-width:0;padding-bottom:16px}
.sl-body .nm{font-size:14.5px;font-weight:900}
.sl-body .sh{font-size:12px;font-weight:800;color:var(--ink-3);margin-top:3px}
.sl-body .gd{margin-top:8px;font-size:11px;line-height:1.6;font-weight:800;
  color:var(--ink-2);background:#fff;border-radius:12px;padding:8px 10px}
.sl-body ul{margin:9px 0 0;padding-left:16px}
.sl-body li{font-size:12px;line-height:1.7;color:var(--ink-2);font-weight:700}
.sl-games{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.sl-games span{font-size:10.5px;font-weight:900;border-radius:999px;padding:4px 9px;
  background:#fff;color:var(--ink-2);box-shadow:0 2px 0 rgba(58,48,37,.1)}
.sl-games span.done{background:var(--sun-l);color:var(--ochre-d)}
.sl-row.now .nm{color:var(--ochre-d)}
.sl-row.now .sl-body .gd{border:2px solid var(--sun)}

/* ---- 底部标签栏（木台面上的一条）--------------------------------------- */
.tabbar{position:absolute;left:0;right:0;bottom:0;height:76px;display:flex;z-index:8;
  background:rgba(255,255,255,.93);backdrop-filter:blur(12px);
  border-top:2px solid rgba(58,48,37,.08);
  box-shadow:0 -6px 18px rgba(58,48,37,.1)}
.tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:3px;border:0;background:none;font-family:inherit;font-size:10.5px;font-weight:900;
  color:var(--ink-3);cursor:pointer;padding:0}
.tab svg{width:25px;height:25px;display:block}
.tab path,.tab circle,.tab rect,.tab polygon{fill:var(--ink-3)}
.tab.on{color:var(--ochre-d)}
.tab.on path,.tab.on circle,.tab.on rect,.tab.on polygon{fill:var(--ochre)}

/* ---- 特效 / 提示 ------------------------------------------------------- */
#fx{position:absolute;inset:0;pointer-events:none;z-index:9;overflow:hidden}
.fx-star{position:absolute;width:14px;height:14px}
.fx-star path{fill:var(--sun)}
.fx-ring{position:absolute;border-radius:50%;border:4px solid rgba(169,102,58,.5)}
.fx-mark{position:absolute;font-size:20px;font-weight:900;color:var(--ochre-d)}
.toast{position:absolute;left:50%;bottom:112px;transform:translateX(-50%);
  background:rgba(58,48,37,.92);color:#fff;border-radius:999px;padding:11px 20px;
  font-size:13px;font-weight:800;opacity:0;transition:opacity .25s;z-index:10;
  pointer-events:none;max-width:300px;text-align:center;line-height:1.5}
.toast.on{opacity:1}
.note{margin:0 18px;background:rgba(255,255,255,.82);border-radius:20px;padding:13px 15px;
  font-size:12px;line-height:1.72;color:var(--ink-2);font-weight:700}
.note b{color:var(--ochre-d)}
.empty-tip{text-align:center;font-size:12.5px;font-weight:800;color:var(--ink-3);
  padding:22px 0}
