/* 数学互动共用样式（2026-09-19 从 build_lesson_pages.py 的 <style> 里整体迁出；2026-09-20 配色改走 --c-mp-*，见 网页风格统一-LearnPal风-v001/handoff.md §6）
   由 baike/index.html 一次性引入。第一/二/三版共用的 .math-pilot / .mp-* 都在这里；
   模块自己的样式写在 pilots/<id>.css，类名前缀 mp-<id 小写>-，不要改本文件。
   2026-09-24：.mp-keys 键盘替代条改为 sr-only 视觉隐藏（用户定：孩子端不看「键盘：…」备用条）；仍在 DOM、可 focus、可收事件，验收 POKE 兜底照用，不许改成 display:none。
   2026-09-24：旁白 #v3Say 改成逐行累加（.mp-say-line，一句一行）；最新一行 --c-ink、旧行 --c-ink-2；非空时固定 6 行高、超出自己滚（总控 07:29 定，保 R7 不跳）。
   2026-09-24 晚（儿童体验六条 · 前端五项）：舞台加定位；图上指令条 .mp-instr、放错气泡 .mp-bubble、fx 层 .mp-fx（抖 / 亮 / 勾）、做完横幅 .mp-banner、
   演示手 .mp-hand；字幕新句入场 + 当前句高亮 + 旧句变淡。样式照 10-课程资产/设计/精细化样板-互动儿童体验-v001/demo.html。 */
/* 未在册的课：页面留的空壳不占位 */
.mp-host:empty{display:none}
.mp-body{display:block}
.math-pilot{border:1px solid var(--c-line);border-radius:var(--r-lg);background:var(--c-mp-panel);padding:var(--sp-4);overflow:hidden}
.math-pilot.-preview{padding:var(--sp-3) var(--sp-4)}
.mp-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-3);margin-bottom:var(--sp-3)}
.mp-kicker{font-size:var(--fs-xs);font-weight:700;letter-spacing:.06em;color:var(--c-mp-a)}
.mp-title{font-weight:700;font-size:var(--fs-lg);line-height:1.3;margin-top:2px}.mp-sub{font-size:var(--fs-sm);color:var(--c-ink-2);margin-top:3px}
.mp-stage{position:relative;border:1px solid var(--c-mp-grid);border-radius:var(--r-md);background:var(--c-mp-stage);padding:var(--sp-2);overflow:hidden}
.mp-stage svg{display:block;width:100%;height:auto;overflow:visible}.mp-stage text{font-family:var(--font);fill:var(--c-mp-ink)}
.mp-readout{margin-top:var(--sp-3);padding:var(--sp-3);border-radius:var(--r-md);background:var(--c-accent-soft);line-height:1.55;color:var(--c-accent-hover)}
.mp-readout strong{font-variant-numeric:tabular-nums}.mp-note{margin-top:var(--sp-2);font-size:var(--fs-sm);color:var(--c-ink-2)}
.mp-controls{display:grid;grid-template-columns:1fr;gap:var(--sp-3);margin-top:var(--sp-3)}
@media(min-width:641px){.mp-controls.-two{grid-template-columns:repeat(2,minmax(0,1fr))}}
.mp-control{display:grid;grid-template-columns:minmax(86px,auto) minmax(100px,1fr) auto;align-items:center;gap:var(--sp-2);min-height:44px}
.mp-control label{font-size:var(--fs-sm);font-weight:700}.mp-control output{min-width:3.4em;text-align:right;font-weight:800;font-variant-numeric:tabular-nums}
.mp-control input[type=range]{width:100%;min-height:44px;accent-color:var(--c-accent)}
.mp-steps{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3)}
.mp-steps .btn{min-height:44px;flex:1 1 120px}.mp-steps .btn.is-on{background:var(--c-accent);border-color:var(--c-accent);color:var(--c-accent-ink)}
.mp-cut-piece{transition:transform 420ms var(--ease)}
@media(prefers-reduced-motion:reduce){.mp-cut-piece{transition:none}.pilot-link{scroll-behavior:auto}
  .mp-say-line.is-new,.mp-instr.is-swap,.mp-instr.is-flash,.mp-bubble,.mp-banner,.mp-stage.is-done,.mp-fx>*{animation:none}.mp-say{scroll-behavior:auto}}
@media(max-width:390px){.math-pilot{padding:var(--sp-3)}.mp-control{grid-template-columns:1fr auto}.mp-control input[type=range]{grid-column:1 / -1}.mp-stage{padding:4px}}
@media(max-width:390px){.axis-tick-label{font-size:26px}.axis-tick-label:not(.axis-major),[data-math-pilot="axis"] .axis-point-label{display:none}}
/* 第二版互动（2026-09-19）：先猜 → 自己拖图上的东西 → 动到位才出结论。第一版样式在上面，未改。 */
.mp-ver{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;margin-bottom:var(--sp-2)}
.mp-ver-l{font-size:var(--fs-xs);color:var(--c-ink-2);font-weight:700}
.mp-ver-b{min-height:36px;padding:6px 14px;border:1px solid var(--c-line);border-radius:var(--r-pill);background:var(--c-surface);font-size:var(--fs-sm)}
.mp-ver-b.is-on{background:var(--c-accent-soft);border-color:var(--c-accent);color:var(--c-accent-hover);font-weight:700}
.math-pilot.mp-v2 .mp-stage svg{touch-action:none;-webkit-user-select:none;user-select:none}
.mp-hit{fill:transparent;stroke:transparent;cursor:grab}
.mp-ask{margin-top:var(--sp-3);padding:var(--sp-3);border:1px solid var(--c-line);border-radius:var(--r-md);background:var(--c-surface-2)}
.mp-ask[hidden]{display:none}
.mp-ask .q{font-weight:700;line-height:1.5;margin-bottom:var(--sp-2)}
.mp-opts{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.mp-opt{min-height:44px;flex:1 1 104px;padding:8px 12px;border:1px solid var(--c-line);border-radius:var(--r-md);background:var(--c-surface)}
.mp-opt.is-pick{border-color:var(--c-accent);background:var(--c-accent-soft);color:var(--c-accent-hover);font-weight:700}
.mp-opt[disabled]{opacity:.55}
.mp-do{margin-top:var(--sp-3);font-size:var(--fs-sm);color:var(--c-ink-2);line-height:1.55}
.mp-keys{display:flex;gap:var(--sp-2);flex-wrap:wrap;position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;margin:-1px;border:0}
.mp-key{min-height:44px;padding:8px 12px;border:1px solid var(--c-line);border-radius:var(--r-md);background:var(--c-surface);font-size:var(--fs-sm);text-align:left}
.mp-key:focus-visible,.mp-key.is-sel{border-color:var(--c-accent);background:var(--c-accent-soft);color:var(--c-accent-hover);outline:2px solid var(--c-accent);outline-offset:1px}
.mp-cmp{margin-top:var(--sp-2);font-size:var(--fs-sm);color:var(--c-mp-no);line-height:1.55}
.mp-prog{margin-top:var(--sp-2);font-size:var(--fs-sm);color:var(--c-ink-2)}
.mp-sum{margin-top:var(--sp-3);padding:var(--sp-3);border-radius:var(--r-md);background:var(--c-ok-soft);color:var(--c-ok-deep);font-weight:700;line-height:1.55}
.mp-sum:empty,.mp-cmp:empty,.mp-prog:empty,.mp-do:empty{display:none}
.mp-again{min-height:44px;margin-top:var(--sp-3);padding:8px 16px;border:1px solid var(--c-line);border-radius:var(--r-md);background:var(--c-surface);font-weight:700}
@media(max-width:390px){.mp-opt{flex:1 1 100%}}
/* 第三版互动（2026-09-19）：看它做 → 你来做 → 换个数。前两版样式在上面，未改。 */
.math-pilot.mp-v3 .mp-stage svg{touch-action:none;-webkit-user-select:none;user-select:none}
.mp-phases{display:flex;gap:6px;flex-wrap:wrap;margin:var(--sp-3) 0 var(--sp-2)}
.mp-ph{flex:1 1 92px;font-size:var(--fs-xs);font-weight:700;color:var(--c-ink-2);background:var(--c-surface-2);border:1px solid var(--c-line);border-radius:var(--r-pill);padding:7px 10px;text-align:center;white-space:nowrap}
.mp-ph.is-on{background:var(--c-accent);border-color:var(--c-accent);color:var(--c-accent-ink)}
.mp-say{margin-top:var(--sp-3);padding:var(--sp-3);border-radius:var(--r-md);background:var(--c-surface-2);line-height:1.6}
.mp-say:empty{display:none}
/* 2026-09-24 总控定：旁白盒非空时固定 6 行高、超出自己滚（不用 max-height），累加时盒子不长高、下面按钮区不跳（R7 不改） */
.mp-say:not(:empty){height:calc(6*1.6em + 2*var(--sp-3));overflow:auto}
/* 2026-09-24 晚（用户改口径）：累加不消失；新句 0.36s 从下淡入；当前句（最后一行）加粗 + 左侧竖条 + 淡底；旧句灰字 72% 靠上 */
.mp-say{scroll-behavior:smooth}
.mp-say-line{color:var(--c-ink-2);opacity:.72;padding-left:12px;border-left:3px solid transparent;transition:color .35s,opacity .35s}
.mp-say-line:last-child{color:var(--c-ink);opacity:1;font-weight:700;border-left-color:var(--c-accent);background:var(--c-accent-soft);border-radius:0 6px 6px 0;padding:4px 8px 4px 12px}
.mp-say-line+.mp-say-line{margin-top:4px}
.mp-say-line.is-new{animation:mpSayIn .36s var(--ease)}
@keyframes mpSayIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.mp-acts{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3)}
.mp-act{min-height:44px;flex:1 1 140px;padding:8px 16px;border:1px solid var(--c-line);border-radius:var(--r-md);background:var(--c-surface);font-weight:700}
.mp-act.-go{background:var(--c-accent);border-color:var(--c-accent);color:var(--c-accent-ink)}
.mp-act[hidden],.mp-keys[hidden],.mp-phases[hidden]{display:none!important}
@media(max-width:390px){.mp-act{flex:1 1 100%}}
/* 公共部件收拢（2026-09-19）：用户实测定的六条规矩落在这里。
   ① 一个互动只给一个抓手（.mp-grip 由 ctx.handle 画，另一头只画 .mp-mark 小标记）
   ⑤ 画面下方只留一条说明：键盘提示条压成小字（2026-09-21 起放不下会换行，不再切字，见下面 .mp-keys）
   ⑥ 示范播放中动手有独立提示槽 .mp-tip，下一帧 draw() 冲不掉 */
.mp-grip{cursor:grab}
.math-pilot.mp-v3 .mp-stage svg:active .mp-grip{cursor:grabbing}
.mp-mark{pointer-events:none}
/* 示范段里抓手降级成的普通点（R4，2026-09-21）：只是画面的一部分，冻结拍照留，不算可操作件 */
.mp-dot{pointer-events:none}
.mp-grip-tip{pointer-events:none}
/* 层次处理（2026-10-06）：被抓手 / 虚线碰到的课程字提到最上层，和「拖这里」一样加底色描边；描边宽由 runtime 按屏幕 5px 写行内 */
.mp-text-lifted{paint-order:stroke fill;stroke:var(--c-mp-panel,var(--c-surface,#fff));stroke-width:5px;stroke-linejoin:round;pointer-events:none}
/* 「看它做」这一段（st.phase===0，runtime 把 data-ph 写在块上）一律没有可操作件（V8，2026-09-21）：
   ctx.handle 已经把抓手降级成 .mp-dot，但它和模块自己画的 hitDot / hitRect 还留着一圈 .mp-hit
   （fill:transparent + cursor:grab，自检按「可见的抓手 / 命中区」算，M04/M08/M09/M12 共 14 条都是它）。
   示范段本来就拖不动（ctx.can() 恒 false），命中区一点用没有，这里整段收掉，
   顺带和第 1 拍（-still 已收）对齐 —— 两拍画面件数一致。模块不用改。 */
.math-pilot[data-ph="0"] .mp-hit,.math-pilot[data-ph="0"] .mp-grip,
.math-pilot[data-ph="0"] .mp-grip-tip{display:none!important}
.mp-tip{margin-top:var(--sp-2);padding:8px 12px;border-radius:var(--r-md);background:var(--c-accent-soft);border:1px solid var(--c-accent);font-size:var(--fs-sm);font-weight:700;line-height:1.5}
.mp-tip:empty{display:none}
/* 键盘提示条（2026-09-21 改，V14）：原来是「永远一行 + 省略号」，结果 390 上两三个按钮挤成 158px，
   「键盘：空格（← → 换一个，Enter 放）」被切成「键盘：空格（← → 换一个，En」—— 孩子看不到按哪个键，
   等于这条提示白写。lesson-v4 里 --fs-xs 已经是 14px 地板（任务单 §1），再缩字号也没得缩，
   所以改成：一行塞不下就换行，按钮内的文字也允许折成两行，一个字都不切。 */
.mp-keys{flex-wrap:wrap}
.mp-key{flex:1 1 150px;min-width:0;white-space:normal;overflow:visible;overflow-wrap:anywhere;text-overflow:clip;font-size:var(--fs-xs);padding:8px 10px;line-height:1.35}
/* 图上要在窄屏放大的文字：ctx.g.label(...,{cls:'mp-up'}) */
@media(max-width:430px){.mp-stage text.mp-up{font-size:26px}}
/* 四步走页面（#inner.lesson-v3，2026-09-19）：一屏只留一个柿色主按钮（底栏「做好了，看例题」）。
   互动块自己的「我来做一遍 / 会了，换个数 / 再来一组」降成白底次要样式。只改颜色，不动结构、行为与模块。 */
.lesson-v3 .mp-acts .mp-act.-go{background:var(--c-surface);border-color:var(--c-ink);color:var(--c-ink)}
/* 只看不动（2026-09-19 v002）：讲解步的静态起始画面。MathPilot.mount(host,id,n,{still:true}) 挂出来的块 ——
   只留画面，按钮 / 旁白 / 提示 / 总结 / 三段格全收掉，整块不可点不可拖。只改这一个块的样式，动手步不受影响。 */
.math-pilot.-still{border:0;background:none;padding:0;pointer-events:none}
.math-pilot.-still .mp-head,.math-pilot.-still .mp-phases,.math-pilot.-still .mp-acts,
.math-pilot.-still .mp-keys,.math-pilot.-still .mp-ask,.math-pilot.-still .mp-say,
.math-pilot.-still .mp-tip,.math-pilot.-still .mp-do,.math-pilot.-still .mp-cmp,
.math-pilot.-still .mp-prog,.math-pilot.-still .mp-sum,.math-pilot.-still .mp-note{display:none!important}
/* R4（2026-09-21）：冻结拍只留画面 —— 抓手、「拖这里」、命中区收掉（说明行由 runtime 的 freeze() 清空）。
   .mp-keys 上面那条已经收了；这里只影响 -still 这一个块，动手的那几拍一字不变。
   `.mp-mark` 故意没收：它是画面的一部分（M12-U005 拿它画三角形的顶点、M04-U018 画联动的另一头），
   收掉的话第 1、4、5 拍会比第 3 拍少几个点，反而违反「与第 1 拍静态图一致」。 */
.math-pilot.-still .mp-grip,.math-pilot.-still .mp-grip-tip,
.math-pilot.-still .mp-hit{display:none!important}
.math-pilot.-still .mp-stage svg{touch-action:auto}
/* 故事线页面（#inner.lesson-v4，2026-09-20 v004）：块自己的「我来做一遍 / 会了，换个数 / 再来一组」、三段格、标题行
   收起来，由页顶七个拍点与底栏代替（一屏只留一个柿色按钮、进度只画一遍）；只看不动（-still）时保留卡片外框和内边距，
   画布大小从第 1 拍到第 6 拍一毫米不变。全部限定在 .lesson-v4 容器里，别的页面一字不受影响。 */
.lesson-v4 .mp-acts .mp-act.-go{display:none!important}
.lesson-v4 .mp-phases,.lesson-v4 .mp-head{display:none!important}
.lesson-v4 .math-pilot.-still{border:1px solid var(--c-line);background:var(--c-mp-panel);padding:var(--sp-4)}
@media(max-width:390px){.lesson-v4 .math-pilot.-still{padding:var(--sp-3)}}
/* 一拍一屏（2026-09-20 v002）：页面把 --v4-k（viewBox 单位 / CSS px）写在 .mp-host 上，画布缩小时抓手的命中区按它反比放大，
   触控始终 ≥44 CSS px（可见的把手本体不动，pulse 动画不受影响）；旁白留两行高免得播放中一跳一跳；
   竖屏窄压缩档（.is-tight）里块自己的「跳过 / 再看一遍」与键盘提示收起，由页面底栏的影子按钮顶上。全部限定 .lesson-v4。 */
.lesson-v4 .mp-host circle.mp-hit{r:max(44px,calc(24px*var(--v4-k,1)))}
.lesson-v4 .mp-host path.mp-hit{stroke-width:max(88px,calc(46px*var(--v4-k,1)))}
.lesson-v4 .mp-host .mp-say:not(:empty){min-height:calc(2*1.6em + 2*var(--sp-3))}
.lesson-v4[data-fit=tall].is-tight .mp-keys,.lesson-v4[data-fit=tall].is-tight .mp-acts{display:none!important}
.lesson-v4[data-fit=tall].is-tight .mp-say{margin-top:var(--sp-2);padding:var(--sp-2) var(--sp-3);height:calc(6*1.55em + 2*var(--sp-2));overflow:auto;line-height:1.55}   /* 2026-09-24：min-height 2 行 → 固定 6 行高（字幕累加，总控定） */
.lesson-v4[data-fit=tall].is-tight .mp-do,.lesson-v4[data-fit=tall].is-tight .mp-cmp,.lesson-v4[data-fit=tall].is-tight .mp-sum,.lesson-v4[data-fit=tall].is-tight .mp-tip{margin-top:var(--sp-2);padding:var(--sp-2) var(--sp-3)}
.lesson-v4[data-fit=tall].is-tight .math-pilot{padding:var(--sp-3)}
.lesson-v4[data-fit=tall].is-tighter .mp-do{display:none}
.lesson-v4 .mp-host .mp-ask{display:none!important}   /* 第 6 拍不猜（2026-09-20 用户定）：runtime 按 skipAsk 已收起，这里再压一道 */
/* ================= 儿童体验五项（2026-09-24 晚）：运行时通用件的样式。深浅色走 --c-instr / --c-instr-ink（页面没给就退回 ink / surface 反色） ================= */
/* 必-1 指令条：图框内、深色、随步骤变；贴上或贴下由运行时定（写在 .mp-stage[data-instr] 上），占一条预留带不压画 */
.mp-instr{position:absolute;left:8px;right:8px;top:8px;z-index:3;display:flex;align-items:center;gap:10px;padding:9px 14px;min-height:44px;box-sizing:border-box;border-radius:var(--r-md);
  background:var(--c-instr,var(--c-ink));color:var(--c-instr-ink,var(--c-surface));font-weight:700;font-size:17px;line-height:1.35;text-align:left;
  box-shadow:0 4px 14px rgba(0,0,0,.18);pointer-events:none}
.mp-instr:empty{display:none}
.mp-instr[data-at=bottom]{top:auto;bottom:8px}
.mp-instr[data-at=near]{right:auto;bottom:auto}
.mp-instr .n{flex:none;min-width:26px;height:26px;padding:0 5px;border-radius:13px;background:var(--c-accent);color:var(--c-accent-ink);display:grid;place-items:center;font-size:14px;font-weight:800}
.mp-instr .t{min-width:0}
.mp-instr .t b{color:var(--c-accent-2);font-weight:800}
.mp-instr.is-swap{animation:mpInstrIn .32s var(--ease)}
.mp-instr.is-flash{animation:mpInstrFlash .5s}
@keyframes mpInstrIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@keyframes mpInstrFlash{0%,100%{box-shadow:0 4px 14px rgba(0,0,0,.18)}50%{box-shadow:0 0 0 4px var(--c-accent-2)}}
/* 应该改 ④-3（2026-09-25）：条随当前件上下换边，上下两条带一直留着，换边时图不动 */
.mp-stage[data-instr]{padding-top:calc(var(--mp-ih,44px) + 16px)!important;padding-bottom:calc(var(--mp-ih,44px) + 16px)!important}
@media(max-width:430px){
  .mp-instr{left:4px;right:4px;top:4px;font-size:15px;padding:7px 10px;gap:8px;min-height:40px}
  .mp-instr[data-at=bottom]{top:auto;bottom:4px}
  .mp-stage[data-instr]{padding-top:calc(var(--mp-ih,40px) + 8px)!important;padding-bottom:calc(var(--mp-ih,40px) + 8px)!important}}
/* 必-2 放错气泡：贴在被拖件旁（≤120px），停到下一次按下；-zero 放 0 的「哦？」、-info 中性（老课兜底里不像纠错的那句） */
.mp-bubble{position:absolute;z-index:4;max-width:min(300px,72%);padding:8px 12px;border-radius:var(--r-md);background:var(--c-surface);border:1.5px solid var(--c-mp-no);color:var(--c-ink);
  font-size:15px;font-weight:700;line-height:1.4;box-shadow:0 6px 18px rgba(0,0,0,.14);pointer-events:none;transform-origin:left top;animation:mpBubIn .22s var(--ease)}
.mp-bubble::before{content:"";position:absolute;left:-7px;top:12px;width:12px;height:12px;background:var(--c-surface);border-left:1.5px solid var(--c-mp-no);border-bottom:1.5px solid var(--c-mp-no);transform:rotate(45deg)}
.mp-bubble[data-side=left]{transform-origin:right top}.mp-bubble[data-side=left]::before{left:auto;right:-7px;transform:rotate(-135deg)}
.mp-bubble[data-side=below]::before,.mp-bubble[data-side=above]::before,.mp-bubble[data-side=free]::before{display:none}
.mp-bubble.-zero{border-color:var(--c-accent-2)}.mp-bubble.-zero::before{border-color:var(--c-accent-2)}
.mp-bubble.-info{border-color:var(--c-accent)}.mp-bubble.-info::before{border-color:var(--c-accent)}
@keyframes mpBubIn{from{opacity:0;transform:scale(.85)}to{opacity:1;transform:none}}
/* 应该改 ④（2026-09-25）：先藏着算好位置再亮（不先落再跳）；放不下时小一号字；再不行放到图外贴边（视口定位）+ 指向线 */
.mp-bubble.-wait{visibility:hidden;animation:none}
.mp-bubble.-sm{font-size:13px;padding:6px 10px;line-height:1.35}
.mp-bubble.-out{position:fixed;z-index:40}
.mp-bubble[data-side^=out]::before{display:none}
.mp-bubble-line{position:fixed;z-index:39;pointer-events:none;overflow:visible}
.mp-bubble-line line{stroke:var(--c-mp-no);stroke-width:2;stroke-dasharray:4 3}
.mp-bubble-line circle{fill:var(--c-mp-no)}
.math-pilot.-still .mp-bubble-line{display:none!important}
/* fx 层（HTML 覆盖层，模块每帧重画 svg 冲不掉）：抖框 / 目标亮一圈 / 小对勾 */
.mp-fx{position:absolute;inset:0;z-index:2;pointer-events:none;overflow:hidden}
.mp-fx:empty{display:none}
.mp-fx .mp-shake{position:absolute;box-sizing:border-box;border:3px solid var(--c-mp-no);border-radius:10px;animation:mpShake .42s var(--ease)}
.mp-fx .mp-shake.-zero{border-color:var(--c-accent-2)}
.mp-fx .mp-shake.-soft{border:2px dashed var(--c-accent-2);border-radius:50%;animation:mpShake .42s var(--ease)}   /* 应该改 ③：按错了对象，当前抓手那件轻晃 */
@keyframes mpShake{0%,100%{transform:translateX(0)}20%{transform:translateX(-6px)}40%{transform:translateX(6px)}60%{transform:translateX(-4px)}80%{transform:translateX(4px)}}
.mp-fx .mp-flash{position:absolute;box-sizing:border-box;border:3px solid var(--c-mp-ok);border-radius:50%;opacity:0;animation:mpFlash .6s var(--ease) forwards}
@keyframes mpFlash{0%{opacity:0;box-shadow:0 0 0 0 var(--c-mp-ok)}30%{opacity:1;box-shadow:0 0 0 6px var(--c-mp-ok)}100%{opacity:0;box-shadow:0 0 0 14px var(--c-mp-ok)}}
.mp-fx .mp-check{position:absolute;width:26px;height:26px;border-radius:50%;background:var(--c-mp-ok);display:grid;place-items:center;animation:mpCheck .55s var(--ease) forwards}
.mp-fx .mp-check svg{width:16px;height:16px;fill:none;stroke:#fff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round}
@keyframes mpCheck{0%{opacity:0;transform:scale(.3)}50%{opacity:1;transform:scale(1.25)}100%{opacity:1;transform:scale(1)}}
/* 做完横幅：占指令条那条带（条先让位），≥0.5s 动效；图框描一圈绿光 */
.mp-banner{position:absolute;left:50%;top:8px;z-index:5;transform:translateX(-50%);display:flex;align-items:center;gap:10px;padding:8px 18px;border-radius:var(--r-pill);
  background:var(--c-mp-ok);color:#fff;font-weight:800;font-size:17px;line-height:1.35;box-shadow:0 8px 22px rgba(0,0,0,.2);animation:mpBannerIn .7s var(--ease);pointer-events:none;white-space:nowrap;max-width:calc(100% - 16px)}
.mp-banner[data-at=bottom]{top:auto;bottom:8px}
.mp-banner .ck{flex:none;width:26px;height:26px;border-radius:50%;background:#fff;color:var(--c-mp-ok);display:grid;place-items:center}
.mp-banner .ck svg{width:16px;height:16px;stroke:currentColor;stroke-width:3;fill:none;stroke-linecap:round;stroke-linejoin:round}
.mp-banner .bt{overflow:hidden;text-overflow:ellipsis}
@keyframes mpBannerIn{0%{opacity:0;transform:translate(-50%,16px) scale(.8)}55%{opacity:1;transform:translate(-50%,-4px) scale(1.06)}100%{transform:translate(-50%,0) scale(1)}}
.mp-stage.has-banner .mp-instr{visibility:hidden}
.mp-stage.is-done{animation:mpStageDone .7s}
@keyframes mpStageDone{30%{box-shadow:0 0 0 4px var(--c-mp-ok)}100%{box-shadow:none}}
@media(max-width:430px){.mp-banner{font-size:15px;padding:7px 14px;top:4px}.mp-banner[data-at=bottom]{top:auto;bottom:4px}}
/* 必-3 演示手：HTML 覆盖层，屏幕像素 46px，指尖对准 viewBox 坐标 */
.mp-hand{position:absolute;left:0;top:0;z-index:6;width:46px;height:46px;margin:-6px 0 0 -14px;pointer-events:none;opacity:0;transition:opacity .2s,transform .12s;filter:drop-shadow(0 3px 6px rgba(0,0,0,.25))}
.mp-hand.is-on{opacity:1}.mp-hand.is-press{transform:scale(.88) rotate(-6deg)}
.mp-hand svg{display:block;width:100%;height:100%}
/* 只看不动（冻结拍）：画面当照片看 —— 指令条 / 气泡 / 横幅 / 手 / fx 全收 */
.math-pilot.-still :is(.mp-instr,.mp-bubble,.mp-banner,.mp-hand,.mp-fx){display:none!important}
/* 上课模式（页面给 body 加 is-class）：提示与说明全走图上的指令条 / 气泡，右栏这两条不再单独上屏（节点还在，字照写） */
body.is-class .mp-tip,body.is-class .mp-do{display:none!important}
/* 验证轮 1 退回②（2026-09-25）：上课模式里右栏绿色总结不上屏 —— 做完由图内横幅说一句，示范的结论在字幕最后一句；节点与字照写（页面 / 验收读它判到位） */
body.is-class .mp-sum{display:none!important}
