/* 中盘实战 100 题的样式。gomemo-app.html 的 <head> 里 <link> 引入。
   风格沿用新界面：纯色、无渐变、描边 + 厚底边；颜色取自首页真实用到的那几个
   （底 #F2FAFF、描边 #CFE3F1、标题 #2C4A7A、主色 #4C8DFF）。
   所有类名以 zp- 开头，选择器尽量挂在 #zpScreen 下，避免影响别的画面。
   点击区域一律 ≥ 44px（孩子手指粗，iPad 上也要点得准）。 */

/* ===== 屏幕外壳 ===== */
/* .screen 基类没有 flex-direction，不写的话头部和内容会并排摆（branchCatScreen 当年就踩过） */
#zpScreen {
  flex-direction: column; align-items: stretch;
  background: #F2FAFF;
  overflow-y: auto;
}
#zpScreen .ms-header {
  background: #F2FAFF; border-bottom: 2px solid #CFE3F1; backdrop-filter: none;
}
#zpScreen .ms-title { color: #2C4A7A; }
#zpScreen .btn { min-width: 44px; min-height: 44px; justify-content: center; }
#zpScreen .btn-outline {
  background: #fff; border: 2px solid #CFE3F1; border-bottom-width: 4px; box-shadow: none;
  border-radius: 14px; color: #3A5570;
}

/* ===== 内容区 ===== */
.zp-body { padding-top: 16px; }
.zp-empty { text-align: center; color: #5B7590; font-size: 15px; font-weight: 700; padding: 40px 16px; }

/* 通用的"大按钮"：≥44px 高，主色底 + 厚底边，按下时往下沉 */
.zp-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 44px; min-height: 44px; padding: 10px 22px;
  background: #4C8DFF; color: #fff;
  border: 2px solid #2E6FE0; border-bottom-width: 5px; border-radius: 14px;
  font-size: 16px; font-weight: 800; cursor: pointer;
}
.zp-btn:active { transform: translateY(3px); border-bottom-width: 2px; }

/* ===== 大关列表（首页）===== */
/* 样式抄参考原型的 .catcard：白底、描边 + 6px 厚底边、20px 圆角；"接着做"的那张换黄色边 */
.zp-glist { display: flex; flex-direction: column; gap: 12px; }
.zp-gcard {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 76px; padding: 12px 14px;
  background: #fff; color: #2C4A7A; font: inherit; text-align: left;
  border: 2px solid #CFE3F1; border-bottom-width: 6px; border-radius: 20px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.zp-gcard:active { transform: translateY(3px); border-bottom-width: 3px; }
.zp-gcard.next { background: #FFFBE6; border-color: #FFC800; border-bottom-color: #E0A800; }
.zp-gcard.lock { background: #EEF1F5; border-color: #D5DBE4; color: #5F6F86; }
/* min-width:0：flex 子项默认不肯缩到比内容窄，320px 的手机上名字一长就会把卡片撑出屏幕 */
.zp-ginfo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.zp-gname { font-size: 18px; font-weight: 800; overflow-wrap: anywhere; }
.zp-gstars { font-size: 14px; font-weight: 800; }
.zp-gbar { display: block; height: 10px; border-radius: 6px; background: #E3EEF8; overflow: hidden; }
.zp-gbar i { display: block; height: 100%; background: #FFC800; border-radius: 6px; }
.zp-ggo { flex: none; font-size: 22px; font-weight: 800; color: #4C8DFF; }
.zp-gcard.lock .zp-ggo { color: inherit; }
.zp-empty-ic { font-size: 56px; margin-bottom: 8px; }

/* ===== 题目地图 ===== */
.zp-ptop { display: flex; align-items: center; gap: 12px; min-height: 44px; }
/* 星数和进度条：跟大关卡片里那条一样，放在左边（以前孤零零靠右，和中间的节点对不上） */
.zp-pmeter { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.zp-pstars { font-size: 16px; font-weight: 800; color: #2C4A7A; }
/* 图标按钮：一个"‹"（玩法顶栏里还有 🔊），读屏名字写在 aria-label 里 */
.zp-back, .zp-icbtn {
  flex: none; width: 44px; height: 44px; padding: 0;
  background: #fff; color: #2C4A7A; font: inherit; font-size: 28px; font-weight: 800; line-height: 1;
  border: 2px solid #CFE3F1; border-bottom-width: 5px; border-radius: 50%;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.zp-back:active, .zp-icbtn:active { transform: translateY(3px); border-bottom-width: 2px; }

/* 数字节点连成一条路，宽度不够就换行（320px 一行 3 个）。
   样式抄参考原型的 .path/.node：蛋形（50%/42%）、3px 描边 + 7px 厚底边；
   当前该做的黄色高亮、做完的绿色带星、锁着的灰色带锁。不加动画：一直在动的按钮自动化测试点不稳，
   也不利于对动效敏感的孩子，黄色 + 下面的"▶ 继续"已经足够显眼。 */
/* 一行一轮：每 5 题一块底（休息画面也是每 5 题一次），一行 5 个节点，节点中间穿一条路，做完的那段变绿。
   这一轮有"该做的题"的底是黄的，全满星的底是绿的。--nw 是节点宽度，手机随屏宽在 50–66px 之间，平板 96px。 */
.zp-path { --nw: clamp(50px, 14.2vw, 66px); display: flex; flex-direction: column; gap: 14px; max-width: 760px; margin: 16px auto; }
.zp-round { background: #fff; border: 2px solid #DCE9F5; border-radius: 22px; padding: 10px 10px 14px; }
.zp-round.cur { background: #FFFCEB; border-color: #FFC800; }
.zp-round.full { background: #F1FAF3; border-color: #BFE5C9; }
.zp-rh { display: flex; justify-content: space-between; align-items: center; margin: 0 4px 8px; font-size: 14px; font-weight: 800; color: #5F6F86; }
.zp-rs { color: #2C4A7A; }
.zp-rrow { --n: 5; --pf: 0; --step: calc(var(--nw) + (100% - 5 * var(--nw)) / 4); position: relative; display: flex; justify-content: flex-start; column-gap: calc((100% - 5 * var(--nw)) / 4); }
.zp-rrow::before, .zp-rrow::after { content: ''; position: absolute; left: calc(var(--nw) / 2); top: calc(var(--nw) * .52); height: 6px; margin-top: -3px; border-radius: 3px; }
.zp-rrow::before { width: calc((var(--n) - 1) * var(--step)); background: #DCE9F5; }
.zp-rrow::after { width: calc((var(--n) - 1) * var(--step) * var(--pf)); background: #4CC36B; }
.zp-node {
  position: relative; z-index: 1; flex: none;
  box-sizing: border-box; width: var(--nw); height: calc(var(--nw) * 1.14); padding: 6px 0 0;
  display: flex; flex-direction: column; align-items: center;
  background: #fff; color: #2C4A7A; font: inherit; font-size: clamp(17px, 5vw, 22px); font-weight: 800; line-height: 1.2;
  border: 3px solid #4C8DFF; border-bottom-width: 6px; border-radius: 50% / 44%;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.zp-node:active { transform: translateY(3px); border-bottom-width: 3px; }
.zp-st { display: block; min-height: 12px; margin-top: 1px; font-size: clamp(9px, 2.8vw, 12px); line-height: 1.2; white-space: nowrap; }
.zp-node.next { background: #FFF1B8; color: #3B2300; border-color: #FFC800; border-bottom-color: #E0A800; }
.zp-node.done { background: #D7F0DD; border-color: #4CC36B; border-bottom-color: #1D8537; }
.zp-node.lock { background: #EEF1F5; border-color: #B7C0CE; color: #9AA6B8; }   /* 锁着的也画题号（看得出排到第几题），下面一把小锁 */

.zp-foot { text-align: center; }
.zp-go, .zp-nextgrp, .zp-rest-btn { display: flex; width: 100%; max-width: 320px; min-height: 56px; margin: 0 auto; font-size: 22px; }
.zp-alldone { font-size: 56px; line-height: 1.2; }
.zp-restar { margin-top: 8px; }                                   /* 做完整个大关但没满星：🎉 下面的"再拿满星"按钮 */
.zp-gatetip { margin: 10px auto 0; max-width: 320px; font-size: 15px; font-weight: 700; color: #5F6F86; text-align: center; }
.zp-node.need { box-shadow: 0 0 0 4px #FFC800; }                  /* 做完了但没满星的题圈一圈黄边，提醒回去拿满星 */
.zp-glock { display: block; margin-top: 2px; font-size: 13px; font-weight: 700; color: #5F6F86; }

/* ===== 休息画面（每 5 题一次）===== */
/* 一列：🎉、星数、"继续"、"休息一下"。🎉 只弹三下就停（有限次数）：一直在动的东西会让按钮在自动化测试里点不稳，
   对动效敏感的孩子也不友好——系统开了"减弱动态效果"时连这三下也不弹。"继续"是主色大按钮，"休息一下"是白底次要按钮，不会点混。 */
.zp-rest { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: clamp(24px, 8vh, 96px) 0 16px; text-align: center; }
.zp-rest-party { font-size: 88px; line-height: 1.1; animation: zpParty .9s ease-in-out 3; }
@keyframes zpParty {
  0%, 100% { transform: scale(1) rotate(0); }
  35% { transform: scale(1.3) rotate(-10deg); }
  70% { transform: scale(.95) rotate(8deg); }
}
.zp-rest-stars { margin-bottom: 8px; font-size: 30px; font-weight: 800; color: #2C4A7A; }
.zp-rest-btn.alt { background: #fff; color: #2C4A7A; border-color: #CFE3F1; }
@media (prefers-reduced-motion: reduce) { .zp-rest-party { animation: none; } }

/* ===== 一题的玩法（看 → 想 → 下 → 学会了）===== */
/* 布局、配色、文案抄参考原型（docs/superpowers/reference/zp-prototype.html）。
   玩的时候外壳的头部（"← 返回"回主菜单）收起来：一题里只留一个返回（回地图），孩子不会点错；
   题名和 🔊 在这一题自己的顶栏里。内容区放宽，平板横屏才能把棋盘和面板左右摆开。 */
#zpScreen.zp-playing > .ms-header { display: none; }
#zpScreen.zp-playing .zp-body { max-width: 1120px; padding: 8px 12px 24px; }

/* touch-action:manipulation —— iPad 上快速连点不会被当成"双击放大"；user-select:none —— 连点不会选中一片字 */
.zp-play { display: flex; flex-direction: column; gap: 8px; touch-action: manipulation; -webkit-user-select: none; user-select: none; }
.zp-bar { display: flex; align-items: center; gap: 8px; min-height: 44px; }
.zp-ptitle { flex: 1; min-width: 0; font-size: 17px; font-weight: 800; color: #2C4A7A; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 手机上标题放不下"攻击与防守 · 第 12 题"（题号被截掉），只留"第 12 题"（老师 2026-10-31 定）；平板够宽，完整显示 */
@media (max-width: 699px) { .zp-pt-grp { display: none; } }
.zp-icbtn.zp-sound { font-size: 20px; }
/* 语音速度按钮：圆的、44px，里面是"1.5×"这样的小字 */
.zp-icbtn.zp-rate { font-size: 14px; letter-spacing: -.5px; }

/* 步骤条：当前一步亮黄、做完的变绿（绿字比原型深一点，13px 小字在浅绿底上也够清楚） */
.zp-steps { display: flex; gap: 6px; margin: 0; padding: 0; list-style: none; }
.zp-step {
  flex: 1; min-width: 0; padding: 5px 0; text-align: center;
  background: #E9F1FB; color: #5B6B80; font-size: 13px; font-weight: 800;
  border-radius: 14px; border-bottom: 4px solid #CFE0F3;
}
.zp-step.on { background: #FFC800; color: #3B2300; border-bottom-color: #E0A800; }
.zp-step.done { background: #D7F0DD; color: #176B2C; border-bottom-color: #B5E0C0; }
.zp-si { display: flex; align-items: center; justify-content: center; height: 21px; font-size: 18px; line-height: 1; }

/* 棋盘 + 面板。竖着摆时棋盘宽 = min(可用宽度, 屏高的 66%, 640px)：一进来整盘都在屏幕里 */
.zp-main { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.zp-boardwrap { width: min(100%, 66vh, 640px); }
.zp-board { display: block; width: 100%; height: auto; border-radius: 12px; touch-action: manipulation; cursor: pointer; }
.zp-panel { width: 100%; max-width: 640px; display: flex; flex-direction: column; gap: 8px; }
/* 平板横屏 / 电脑：棋盘在左、面板在右；棋盘高度扣掉顶栏和步骤条（约 150px），整盘不出屏 */
@media (min-aspect-ratio: 5/4) and (min-width: 820px) {
  .zp-main { flex-direction: row; align-items: flex-start; justify-content: center; }
  .zp-boardwrap { flex: none; width: min(60vw, calc(100vh - 150px), 720px); }
  .zp-panel { width: min(34vw, 380px); }
}

/* 小魔王 + 说话气泡 */
.zp-say { display: flex; align-items: center; gap: 8px; }
.zp-mascot {
  flex: none; width: 48px; height: 48px; border-radius: 50%;
  background: #2B3040; border: 3px solid #fff; box-shadow: 0 0 0 2px #CFE3F1;
  font-size: 24px; line-height: 42px; text-align: center;
}
/* "看"那一步的"你执黑"黑子：气泡右边，棋盘外面（以前盖在棋盘右上角，挡住交叉点）。30px 的黑子，闪的时候放大到约 40px，容器留 32px */
.zp-turn { flex: none; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; }
.zp-turn svg { display: block; }
/* 气泡至少两行高：换成一句短话时，下面的按钮不会往上跳（孩子双击的第二下还落在同一个按钮上） */
.zp-bubble {
  flex: 1; min-width: 0; box-sizing: border-box; min-height: 66px;
  display: flex; flex-direction: column; justify-content: center;
  background: #fff; color: #2C4A7A; font-size: 15px; font-weight: 800; line-height: 1.5;
  border: 2px solid #CFE3F1; border-bottom-width: 5px; border-radius: 16px; padding: 8px 12px;
  overflow-wrap: anywhere;
}
.zp-bubble small { display: block; margin-top: 2px; color: #5B6B80; font-size: 12.5px; font-weight: 700; }

/* 大按钮（我看好了 / 我选这个 / ▶ / 学会了 ⭐） */
.zp-act {
  display: block; width: 100%; min-height: 52px; padding: 12px;
  background: #4C8DFF; color: #fff; font: inherit; font-size: 17px; font-weight: 800; text-align: center;
  border: 0; border-bottom: 6px solid #2E6FE0; border-radius: 18px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.zp-act:active { transform: translateY(3px); border-bottom-width: 3px; }
.zp-act { position: relative; overflow: hidden; }
/* 灰着的"学会了"按钮里的进度条：按钮底边一条白线从左走到右（估计语音还要多久，见 _zpLearnEstMs），装饰；话放完按钮马上亮，进度条随之消失。
   孩子在灰着时点按钮：晃一下（.zp-wiggle），告诉他"收到了，还没到时候"。都是有限次动画；系统开了"减弱动态效果"就不动 */
.zp-fill { position: absolute; left: 0; bottom: 0; height: 8px; width: 0; background: rgba(255, 255, 255, .7); animation: zpFill linear forwards; }
@keyframes zpFill { to { width: 100%; } }
.zp-wiggle { animation: zpWiggle .45s ease-in-out; }
@keyframes zpWiggle { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-9px); } 40% { transform: translateX(9px); } 60% { transform: translateX(-6px); } 80% { transform: translateX(4px); } }
@media (prefers-reduced-motion: reduce) { .zp-wiggle { animation: none; } .zp-fill { animation: none; width: 100%; opacity: .5; } }
/* "看一看"按钮下面的"观察时间"提示（zp-ui.js 的 _zpObserveHtml）：等待中 = 蓝底，👀 观察时间 + 一条走满 10 秒的进度条（没有数字，怕分散观察）；
   想够了 = 绿底 ✅ 观察好了，点「我看好了」。颜色同上面的卡片（#E8F4FD / #CFE3F1 / #2C4A7A） */
.zp-observe { display: flex; align-items: center; gap: 12px; margin: 16px 0 0; padding: 12px 16px; background: #E8F4FD; border: 2px solid #CFE3F1; border-bottom-width: 5px; border-radius: 16px; color: #2C4A7A; font-weight: 800; font-size: 20px; }
.zp-observe-ic { flex: none; font-size: 28px; line-height: 1; }
.zp-observe-txt { flex: none; }
.zp-observe-track { flex: 1 1 auto; height: 16px; border-radius: 8px; background: #CFE3F1; overflow: hidden; }
.zp-observe-fill { display: block; height: 100%; width: 0; border-radius: 8px; background: #4C8DFF; animation: zpObserveFill linear forwards; }
@keyframes zpObserveFill { to { width: 100%; } }
.zp-observe.ok { background: #E6F6EA; border-color: #BFE5CB; color: #1F6B3A; }
@media (max-width: 699px) { .zp-observe { gap: 10px; padding: 10px 12px; font-size: 17px; } .zp-observe-ic { font-size: 24px; } .zp-observe-track { height: 14px; } }
/* 系统开了"减弱动态效果"：进度条不动，会变成一条静止的满格或空条，容易误会——干脆不画条，只剩"观察时间"和暗着的按钮 */
@media (prefers-reduced-motion: reduce) { .zp-observe-track { display: none; } }
.zp-act.y { background: #FFC800; color: #3B2300; border-bottom-color: #E0A800; }
/* 灰着的大按钮（"先点一个字母"、学会了 ⭐ 在等那句话放完、演示走完）：以前是白字压淡灰蓝 #C9D3DF，对比度只有约 1.5:1，
   学会了页上它要灰 8–12 秒，不识字的孩子看到的只是一个发白、看不清字的按钮。换成页面自己的次要文字色 #5B6B80（白字对比约 5.4:1）：
   字看得清，又和亮着时的蓝/黄明显不同，一眼看得出"还没到时候"。纯色、不用渐变；是否可点仍由 aria-disabled 表达，不靠颜色。 */
/* 次要按钮（再看一遍 / 跳过 / 不玩了）：白底描边，不和主要的蓝、黄大按钮抢 */
.zp-act.alt { min-height: 56px; background: #fff; color: #2C4A7A; border: 2px solid #CFE3F1; border-bottom-width: 6px; }
.zp-aux { margin-top: 6px; }
/* "不玩了吗？"：盖住整个画面的一层（做了一半点返回时出现），中间一张卡、两个大按钮。纯色、不用渐变 */
.zp-confirm { position: fixed; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center; padding: 16px; background: rgba(44, 74, 122, .5); }
.zp-confirm-card { box-sizing: border-box; width: min(100%, 420px); display: flex; flex-direction: column; gap: 12px; padding: 22px 20px; background: #fff; border: 2px solid #CFE3F1; border-bottom-width: 7px; border-radius: 28px; text-align: center; }
.zp-confirm-q { font-size: 26px; font-weight: 800; color: #2C4A7A; }
.zp-act.dis { background: #5B6B80; color: #fff; border-bottom-color: #46566B; cursor: default; }
.zp-act.dis:active { transform: none; border-bottom-width: 6px; }
/* 学会了 ⭐ 在等"我学会了"那句放完：按钮暗着（上面的 .dis），字后面跟一个小 🔊，告诉不识字的孩子"先听" */
.zp-wait { font-size: .85em; margin-left: 2px; }
.zp-row { display: flex; gap: 8px; }
.zp-row .zp-act { flex: 1; min-width: 0; }
.zp-hint {
  flex: none; width: 64px; min-height: 52px; padding: 0;
  background: #FFE9A8; font: inherit; font-size: 22px;
  border: 2px solid #FFC800; border-bottom-width: 6px; border-radius: 18px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.zp-hint:active { transform: translateY(3px); border-bottom-width: 3px; }
.zp-hint.dis { opacity: .5; }
.zp-note { text-align: center; color: #5B6B80; font-size: 13px; font-weight: 700; }

/* 做完"学会了 ⭐"之后屏幕中间的大星星：盖在整个画面上但不挡点击（双击的第二下要落在下面的按钮上，由状态机挡掉）。
   动画用页面结果页现成的 starPop（gomemo-app.html 里定义的关键帧，有限次；无渐变）；系统开了"减弱动态效果"就不动、直接出现。 */
.zp-starmoment { position: fixed; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.zp-starcard { display: flex; gap: 6px; padding: 14px 22px; background: #fff; border: 2px solid #CFE3F1; border-bottom-width: 7px; border-radius: 28px; }
.zp-bigstar { display: inline-block; font-size: min(76px, 20vw); line-height: 1; animation: starPop .5s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
@media (prefers-reduced-motion: reduce) { .zp-bigstar { animation: none; } }
/* 没得到的星：灰着、淡淡的、不动，让孩子看出"满星是 3 颗"（老师：没有明显的知道满星是 3 颗）。大星星卡片里、地图节点、按钮上都用 */
.zp-bigstar-off { display: inline-block; font-size: min(76px, 20vw); line-height: 1; filter: grayscale(1); opacity: .28; }
.zp-stoff { filter: grayscale(1); opacity: .3; }
/* 顶栏的星星（这一题现在最多能得几颗）：刚少的那一颗从亮的抖一下再变灰，有限次 */
/* 试一试里提醒"点这里"：发亮的点外面有圈往外扩两下（有限次；不用红色、不用叉——不是"错了"，是"看这里"） */
.zp-ripple { transform-box: fill-box; transform-origin: center; pointer-events: none; animation: zpRipple .45s ease-out 2 both; }
@keyframes zpRipple { from { transform: scale(1); opacity: 1; } to { transform: scale(3.2); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .zp-ripple { animation: none; opacity: .8; } }
/* 自己来一遍点错了：点的地方一个灰圈往外扩着淡出（灰的，不是红的、不是叉：不是"你错了"，是"换一个"），有限次 */
.zp-missring { transform-box: fill-box; transform-origin: center; pointer-events: none; animation: zpMiss .7s ease-out both; }
@keyframes zpMiss { from { transform: scale(.8); opacity: 1; } to { transform: scale(2.4); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .zp-missring { animation: none; opacity: .7; } }
.zp-meter { flex: none; display: flex; gap: 2px; font-size: 20px; line-height: 1; }
.zp-meter > span { display: inline-block; }
.zp-starlost { animation: zpLose .9s ease-out both; }
@keyframes zpLose {
  0% { filter: none; opacity: 1; transform: scale(1.6) rotate(-20deg); }
  50% { filter: none; opacity: 1; transform: scale(1.1) rotate(14deg); }
  100% { filter: grayscale(1); opacity: .3; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .zp-starlost { animation: none; } }

/* 点过 💡 之后面板里的"各点的用处"小图例：一个点一条，只有文字 */
/* 图例：每列竖着读（老师 2026-10-29："A B C D 竖排版"）。平板横屏面板在棋盘右边、够高，四行一列竖排；手机和竖屏面板在棋盘下面、高度紧，分两列（左 A B、右 C D）。字母画成跟棋盘上候选点一样的蓝圈，孩子对着棋盘上的字母找 */
.zp-legend { display: grid; grid-auto-flow: column; grid-template-rows: repeat(2, auto); grid-template-columns: 1fr 1fr; gap: 6px 8px; margin: 0; padding: 0; list-style: none; }
.zp-chip { display: flex; align-items: center; gap: 10px; min-height: 40px; box-sizing: border-box; padding: 5px 12px; background: #EAF3FF; color: #2C4A7A; font-size: 14px; font-weight: 800; line-height: 1.4; border: 2px solid #CFE3F1; border-radius: 12px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.zp-chip:active { transform: translateY(2px); }
.zp-chip.sel { background: #DCEBFF; border-color: #2E6FE0; }
.zp-chip.off { cursor: default; }
.zp-chip.off:active { transform: none; }
.zp-chip b {
  flex: none; width: 1.7em; height: 1.7em; box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center;
  margin: 0; color: #2E6FE0; background: #fff; border: 2px solid #2E6FE0; border-radius: 50%; font-size: .9em; line-height: 1;
}
.zp-chip.off { opacity: .45; }

/* 学会了 */
.zp-card { background: #fff; border: 2px solid #CFE3F1; border-bottom-width: 6px; border-radius: 20px; padding: 14px; text-align: center; }
.zp-card-face { font-size: 38px; line-height: 1.2; }
.zp-learned { color: #2C4A7A; font-size: 20px; font-weight: 800; line-height: 1.7; overflow-wrap: anywhere; }
/* 学会了页上正确这一手的用处，一行小字（只有文字） */
.zp-learned-use { margin-top: 4px; color: #5B6B80; font-size: 14px; font-weight: 800; }

/* 动效：正解点 / "你执黑"的黑子（在气泡旁边，不在棋盘上）轻轻闪；选错的子淡出。对动效敏感的孩子（系统开了"减弱动态效果"）不闪 */
#zpBoard .zp-cand { cursor: pointer; outline: none; }
#zpBoard .zp-cand:focus-visible .zp-hit { fill: rgba(255, 200, 0, .3); stroke: #E0A800; stroke-width: 1.4; }
.zp-pulse { transform-box: fill-box; transform-origin: center; animation: zpPulse 1s ease-in-out infinite; }
@keyframes zpPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.35); } }
.zp-fade { animation: zpFade .6s ease-out forwards; }
@keyframes zpFade { to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .zp-pulse { animation: none; } }

/* 字大一点（老师 2026-10-29 在 iPad 上看后说："右边的字太小，孩子和家长能够清晰看见，优化排版"）。
   上面的字号是按手机写的（气泡 15px、小字 12.5px），到了 iPad 上相对大棋盘显得很小。这里只改"一题的玩法"屏幕里的字号和面板宽度，
   放在玩法样式的最后，后面同优先级的规则不会盖掉它：
   · 手机（< 700px）：各处字号小幅加大（气泡 17px、小字 14px、按钮 18px），320px 宽也不溢出（有布局用例守着）；
   · 平板 / 电脑（≥ 700px）：字号约加大 1.6 倍（气泡 26px、小字 19px、按钮 24px、学会了 28px），小魔王、按钮、步骤条跟着放大，
     按钮高度 ≥ 64px，孩子手指和家长的眼睛都够用。 */
.zp-ptitle { font-size: 18px; }
.zp-step { font-size: 14px; }
.zp-bubble { min-height: 60px; padding: 6px 12px; font-size: 17px; text-wrap: balance; }   /* 折行时各行长短接近，不会剩一个字单独占一行（旧浏览器不认就忽略） */
.zp-bubble small { font-size: 14px; }
.zp-act { font-size: 18px; }
.zp-note { font-size: 14px; }
.zp-chip { padding: 3px 8px; gap: 8px; font-size: 14px; }
.zp-chip b { font-size: .85em; }
.zp-learned { font-size: 22px; }
.zp-learned-use { font-size: 15px; }
@media (min-width: 700px) {
  .zp-bar { min-height: 52px; }
  .zp-meter { gap: 4px; font-size: 32px; }
  .zp-ptitle { font-size: 24px; }
  .zp-step { padding: 7px 0; font-size: 17px; }
  .zp-si { height: 26px; font-size: 22px; }
  .zp-mascot { width: 68px; height: 68px; font-size: 34px; line-height: 62px; }
  .zp-say { gap: 12px; }
  /* 气泡至少"一句大字 + 一行小字"那么高：换成一句短话时，下面的按钮不会往上跳 */
  .zp-bubble { min-height: 100px; padding: 12px 18px; font-size: 26px; line-height: 1.45; border-radius: 20px; }
  .zp-bubble small { margin-top: 4px; font-size: 19px; }
  .zp-act { min-height: 68px; font-size: 24px; border-radius: 22px; }
  .zp-act.alt { min-height: 64px; }
  .zp-confirm-card { width: min(100%, 520px); gap: 16px; padding: 30px 28px; }
  .zp-confirm-q { font-size: 36px; }
  .zp-hint { width: 80px; min-height: 68px; font-size: 30px; border-radius: 22px; }
  .zp-row { gap: 12px; }
  .zp-panel { gap: 12px; }
  .zp-note { font-size: 17px; }
  .zp-legend { gap: 8px 12px; }
  .zp-chip { gap: 14px; min-height: 56px; padding: 8px 16px; font-size: 22px; border-radius: 16px; }
  .zp-card { padding: 20px 18px; }
  .zp-card-face { font-size: 52px; }
  .zp-learned { font-size: 28px; line-height: 1.65; }
  .zp-learned-use { margin-top: 8px; font-size: 19px; }
}
/* 平板上，大关列表、题目地图、休息页的字和按钮也放大（老师 2026-10-29 选了"地图和休息页的字也放大"）：
   同样是按手机写的小字号，到 iPad 上显得又小又挤。内容区也放宽（原来最宽 640px），节点一行放得下 5 个。
   只在 ≥700px 生效，手机上不变。 */
@media (min-width: 700px) {
  #zpScreen:not(.zp-playing) .zp-body { max-width: 860px; padding-top: 24px; }
  #zpScreen:not(.zp-playing) .ms-header { padding: 16px 24px 12px; }
  #zpScreen:not(.zp-playing) .ms-header .btn { min-height: 52px; padding: 8px 22px; font-size: 20px; }
  #zpScreen:not(.zp-playing) .ms-title { font-size: 30px; }
  .zp-glist { gap: 16px; }
  .zp-gcard { min-height: 108px; gap: 18px; padding: 16px 22px; border-radius: 26px; }
  .zp-ginfo { gap: 10px; }
  .zp-gname { font-size: 28px; }
  .zp-gstars { font-size: 22px; }
  .zp-gbar { height: 14px; border-radius: 8px; }
  .zp-ggo { font-size: 32px; }
  .zp-ptop { min-height: 56px; gap: 16px; }
  .zp-pstars { font-size: 26px; }
  .zp-back, .zp-icbtn { width: 56px; height: 56px; font-size: 34px; }
  .zp-path { --nw: 96px; gap: 20px; margin: 28px auto; }
  .zp-round { border-radius: 28px; padding: 18px 32px 24px; }
  .zp-rh { margin: 0 4px 14px; font-size: 22px; }
  .zp-node { padding-top: 10px; font-size: 36px; }
  .zp-rrow::before, .zp-rrow::after { height: 8px; margin-top: -4px; border-radius: 4px; }
  .zp-st { min-height: 22px; margin-top: 4px; font-size: 20px; }
  .zp-go, .zp-nextgrp, .zp-rest-btn { max-width: 460px; min-height: 76px; font-size: 30px; border-radius: 24px; }
  .zp-gatetip { max-width: 460px; font-size: 22px; }
  .zp-glock { font-size: 18px; }
  .zp-rest { gap: 22px; }
  .zp-rest-party { font-size: 128px; }
  .zp-rest-stars { font-size: 44px; }
  .zp-empty { font-size: 22px; }
}
/* 演示 / 试一试的进度：一排带数字的小圆（数字 = 棋盘上子的序号）。走过的绿、正要下的黄、还没到的灰 */
.zp-prog { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin: 4px 0 0; padding: 0; list-style: none; }
.zp-dot {
  width: 36px; height: 36px; box-sizing: border-box; display: flex; align-items: center; justify-content: center;
  background: #EEF2F7; color: #6F7F95; font-size: 17px; font-weight: 900; line-height: 1;
  border: 3px solid #CFE0F3; border-radius: 50%;
}
.zp-dot.done { background: #4CC36B; color: #fff; border-color: #3AA859; }
.zp-dot.now { background: #FFC800; color: #3B2300; border-color: #E0A800; }
@media (min-width: 700px) {
  .zp-prog { gap: 12px; margin-top: 10px; }
  .zp-dot { width: 54px; height: 54px; font-size: 26px; border-width: 4px; }
}
/* 平板竖屏：面板在棋盘下面，竖着摆的四行图例再加上大字、大按钮会把"我选这个"挤出屏幕（820×1180 实测按钮掉到 1225px，要孩子自己滚）。
   所以竖屏时图例分两列、每列竖着读（左列 A B、右列 C D，仍是"竖排"，高度减半），棋盘也略小一点（最高 600px、不超过屏高的 52%；768×1024 实测 56% 还差 11px） */
@media (max-aspect-ratio: 5/4) and (min-width: 700px) {
  .zp-boardwrap { width: min(100%, 52vh, 600px); }
}
/* 平板横屏：棋盘在左、面板在右。面板不再卡死在 34vw / 380px，而是拿走棋盘之外剩下的宽度（最宽 480px），字才放得下；
   棋盘宽度再扣一项"给面板留 340px"，窄一点的横屏（820px）也不会把面板挤没 */
@media (min-aspect-ratio: 5/4) and (min-width: 820px) {
  .zp-boardwrap { width: min(60vw, calc(100vh - 150px), 720px, calc(100vw - 24px - 350px)); }
  .zp-panel { flex: 1 1 0; width: auto; min-width: 0; max-width: 480px; }
  .zp-legend { display: flex; flex-direction: column; }
}

/* ===== 后台「中盘实战」页签（老师看题、预览、发布开关）===== */
/* 复用后台已有的 .admin-item / .btn 外观，这里只补这个页签特有的：提示条、总数、一行里的几块、两种提醒。
   管理页是桌面优先，但按钮照样 ≥44px 高（iPad 上老师也点得准）。 */
#zpAdminMsg { color: #059669; }
#zpAdminList { display: flex; flex-direction: column; gap: 8px; }
.zp-adm-sum { font-size: 13px; font-weight: 800; color: #5B7590; }
.zp-adm-empty { color: #5B7590; font-size: 14px; font-weight: 700; padding: 18px 4px; }
.zp-adm-row { gap: 12px; flex-wrap: wrap; }
.zp-adm-main { flex: 1; min-width: 220px; }
.zp-adm-pid { display: inline-block; font-family: monospace; font-size: 12px; font-weight: 700; color: #3A5570; background: #EAF3FB; border-radius: 6px; padding: 1px 6px; }
.zp-adm-uses { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.zp-adm-use b { color: #2E6FE0; }
.zp-adm-btns { display: flex; gap: 6px; flex-shrink: 0; flex-wrap: wrap; }
.zp-adm-btns .btn { min-height: 44px; }
/* 两种提醒：棋谱有问题（红，整行也染红，一眼看得到）；候选点靠得近（黄，只是提醒） */
.zp-adm-warn { margin-top: 6px; font-size: 12px; font-weight: 800; color: #92400E; background: #FFFBEB; border: 1px solid #FDE68A; border-radius: 8px; padding: 5px 10px; }
.zp-adm-warn.bad { color: #B91C1C; background: #FEF2F2; border-color: #FECACA; }
.zp-adm-row.bad { border-color: #F5B5B5; background: #FFF8F8; }
/* 页脚：提醒"改完要点下载游戏"，旁边放一个同样的下载按钮（跟「打谱关卡管理」页底那张卡同一个意思，纯色不渐变） */
.zp-adm-foot { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; padding: 18px 22px; background: #FFF7ED; border: 2px solid #FED7AA; border-radius: 20px; }
.zp-adm-foot-t { font-size: 14px; font-weight: 800; color: #EA580C; margin-bottom: 4px; }
.zp-adm-foot-s { font-size: 12px; font-weight: 600; color: #78716C; line-height: 1.6; }

/* ===== 学习周报里的"中盘实战"卡（gomemo-app.html 的 renderWeeklyReport → zp-ui.js 的 zpWeeklyHtml）=====
   外壳复用周报自己的 .ms-cat / .ms-prog，这里只加里面的几行；颜色同上面（标题 #2C4A7A、描边 #E4EAF2、底 #F2FAFF、金色 #FFF3C4） */
.zp-wr .zp-wr-prog { margin-top: 12px; }
.zp-wr-week { margin: 0 16px 10px; font-size: 14px; font-weight: 700; color: #2C4A7A; }
.zp-wr-groups { margin: 0 16px 12px; display: flex; flex-direction: column; gap: 8px; }
.zp-wr-grp {
  display: flex; align-items: center; gap: 4px 10px; flex-wrap: wrap;
  background: #F2FAFF; border: 2px solid #E4EEF6; border-radius: 12px; padding: 8px 12px;
}
.zp-wr-gname { flex: 1 1 8em; font-size: 15px; font-weight: 800; color: #2C4A7A; }
.zp-wr-gstar { font-size: 14px; font-weight: 700; color: #5B7590; }
.zp-wr-chip { font-size: 13px; font-weight: 800; padding: 3px 10px; border-radius: 999px; border: 2px solid transparent; white-space: nowrap; }
.zp-wr-chip.ok   { background: #E6F6EA; border-color: #BFE5CB; color: #1F6B3A; }
.zp-wr-chip.run  { background: #E8F4FD; border-color: #CFE3F1; color: #2C4A7A; }
.zp-wr-chip.tip  { background: #FFF3C4; border-color: #F5D061; color: #92400E; }
.zp-wr-chip.lock { background: #F1F5F9; border-color: #E4EAF2; color: #5B7590; }
.zp-wr-lines { list-style: none; margin: 0 16px 14px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.zp-wr-lines li { display: flex; gap: 8px; align-items: flex-start; font-size: 14px; line-height: 1.6; color: #2C4A7A; }
.zp-wr-mark { flex: none; }
