/* =============================================
   质数与合数（prime）— 批 1–2 样式
   spec §四「关卡界面设计（ASCII 一等公民）」：界面不是判定之后的动画奖励，
   "摆得成整齐长方形"这个界面动作**就是**质合判定本身。所以下面每一条都要对得上那张 ASCII 图。

   两套色系分层、⛔ 不许串用（spec §四 约束 3）：
     · 状态色（跨关唯一）：质数紫 / 合数青 / 可操作蓝 / 禁用灰
     · 标记色（仅该关内有效）：L7 划除四色、L15 余数三色 —— 批 3 起才用到
   ⛔ 标记色一律避开状态色的紫 / 青 / 蓝；模块主色也避开三者（选玫红），
      否则"紫"会在同一屏里既是质数又是别的意思。
   ============================================= */

/* --- 答错抖动：GameHost.feedback.wrong 给 el 加 .shake。
       why 自带 @keyframes：全局无统一 .shake 定义（各专题各自带），prime 自包含不依赖他模块。--- */
#primeGame .shake, .prime-stage .shake { animation: primeShake 0.4s var(--ease-out); }
@keyframes primeShake {
  0%,100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

/* --- 顶栏（进度 + ❓帮助 · 不自动弹 UX-16）--- */
.prime-topbar {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--module-light);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);
}
/* 标题不许被右边的进度文案挤换行（实测 L5 长文案把它挤成"质数与合/数"两行）。*/
.prime-topbar-title { font-weight: var(--weight-bold); color: var(--module-dark); white-space: nowrap; }
.prime-progress { margin-left: auto; font-size: var(--text-caption); color: var(--text-secondary); }
/* 触控区 44px：这是独立按钮、⛔ 不是密集网格，没有"挤不下"的借口
   （宪法 §4.4 / DP-界面UX-06 一般可点元素下限）。*/
.prime-help-btn {
  border: none; background: var(--surface); color: var(--module-color);
  width: 44px; height: 44px; border-radius: 50%; font-size: var(--text-body);
  box-shadow: var(--shadow-sm); cursor: pointer;
}

.prime-stage { width: 100%; max-width: 480px; margin: 0 auto; padding: 0 var(--space-2); min-width: 0; }

/* --- 题面文案：规则 ≤2–3 句（UX-15）--- */
.prime-ask {
  font-size: var(--text-title); font-weight: var(--weight-bold);
  color: var(--text-primary); text-align: center; margin: var(--space-3) 0 var(--space-2);
}
.prime-sub {
  font-size: var(--text-caption); color: var(--text-secondary);
  text-align: center; margin-bottom: var(--space-4); line-height: 1.6;
}

/* --- 摆放盘：点击落位（ADR-0018），命中区＝整个格子，⛔ 无对齐精度门槛 ---
   ⚠️ "命中区＝整个格子"有个前提：格子本身得够大。列数由数学定死（要摆得出 1×n
   那条线），旧实现用 1fr 均分，16 列时每格被挤到 24px，精度门槛当场回来了
   （真玩实测连戳 15 下只进 12 个）。故改：格子固定尺寸 + 超宽横向滚动。--- */
:root { --prime-cell: 40px; }
.prime-board-scroll {
  /* ⚠️ width:100% 不能省：没有确定宽度时，里面 width:max-content 的棋盘会把
     .prime-stage / .prime-game-wrap 一路撑到 480px，整块内容溢出手机屏
     （真玩原话："这是咋了？画面歪了！"）。宽度由父定、内容超了就滚。*/
  overflow-x: auto; width: 100%; max-width: 100%; margin: 0 auto var(--space-3);
  -webkit-overflow-scrolling: touch;
}
.prime-board {
  display: grid; gap: 3px; width: max-content; margin: 0 auto;
}
.prime-cell {
  width: var(--prime-cell); height: var(--prime-cell);
  /* 空格子是这一屏**孩子真正该点的东西**，就得看起来最像能点的（§3.13）。
     旧值 --surface-dim 几乎与背景同色，孩子先去戳了最鲜艳的棋子堆（点不动），
     误打误撞才发现要点格子——"最醒目的点不了，能点的最不醒目"。*/
  border: 2px dashed var(--text-muted);
  border-color: color-mix(in srgb, var(--module-color) 45%, var(--surface-dim));
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer; touch-action: manipulation;
  transition: background 0.12s var(--ease-out), border-color 0.12s var(--ease-out);
}
/* 可交互（描边）vs 装饰（扁平）一眼可辨（UX-04）：空格是虚线描边、放了棋子是实心圆点。*/
.prime-cell.placed {
  border-style: solid; border-color: var(--module-color);
  background:
    radial-gradient(circle at center, var(--module-color) 0 42%, transparent 43%),
    var(--surface);
}
/* 摆成了：整块亮起。⛔ 这是唯一的"对"的信号——没有弹窗、没有红叉、没有分数飘字。*/
.prime-cell.placed.lit {
  border-color: var(--correct);
  background:
    radial-gradient(circle at center, var(--correct) 0 42%, transparent 43%),
    var(--correct-bg);
  animation: primeLit 0.35s var(--ease-bounce);
}
/* ▨ 缺角：包围盒里没填上的格子。界面**只是不亮**，⛔ 不写"错了"——
   缺角就是不合法这件事由棋子自己裁定（spec §5.3 第一处自证装置）。*/
.prime-cell.gap {
  border-style: solid; border-color: var(--text-muted);
  background: repeating-linear-gradient(45deg,
    var(--surface-dim) 0 4px, transparent 4px 8px);
}
.prime-board.readonly .prime-cell { cursor: default; }
@keyframes primeLit { 0% { transform: scale(0.88); } 60% { transform: scale(1.06); } 100% { transform: scale(1); } }

/* --- 棋子堆（还没放下去的）。L0 ⛔ 不显示数字，只显示一排点 --- */
.prime-tray {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  padding: var(--space-3); background: var(--surface-dim);
  border-radius: var(--radius-md); margin-bottom: var(--space-3);
}
.prime-tray-label { font-size: var(--text-caption); color: var(--text-secondary); }
.prime-tray-dots { display: flex; gap: 4px; flex-wrap: wrap; align-items: center; }
/* 每 N 颗留一道缝：孩子**数得清**有几颗（"数不清就不知道摆几排"），⛔ 数字仍然不出现。*/
.prime-dot.grouped { margin-right: var(--space-3); }
/* 棋子堆是"这些"的实体，鲜艳没问题；但它点不了，就 ⛔ 不能长得像个按钮。*/
.prime-tray { cursor: default; }
.prime-dot {
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--module-color); display: inline-block;
}

/* --- 双栏：左摆盘 / 右记录（L1 报数栏 · L3 算式栏），窄屏自动堆叠 --- */
.prime-two-col { display: flex; gap: var(--space-4); align-items: flex-start; flex-wrap: wrap; }
.prime-two-col > div:first-child { flex: 1 1 220px; min-width: 0; }
.prime-side {
  flex: 0 1 150px; min-width: 130px;
  background: var(--surface); border-radius: var(--radius-md);
  padding: var(--space-3); box-shadow: var(--shadow-sm);
}
.prime-side-title { font-weight: var(--weight-bold); color: var(--text-primary); margin-bottom: var(--space-2); }
.prime-side-empty { color: var(--text-muted); font-size: var(--text-caption); }
.prime-found-row, .prime-eq-row {
  display: flex; align-items: center; gap: 4px;
  padding: var(--space-1) 0; font-size: var(--text-body); color: var(--text-primary);
}
.prime-eq-row.done { color: var(--correct); }
.prime-star-row {
  margin-top: var(--space-2); padding-top: var(--space-2);
  border-top: 1px solid var(--surface-dim);
  font-size: var(--text-caption); color: var(--text-secondary);
}

/* --- 报数槽（X-09 堵死"乱放也能过关"：摆成了还要说出"几排 × 每排几个"）--- */
.prime-narration {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  justify-content: center;
  background: var(--warning-bg); border-radius: var(--radius-md);
  padding: var(--space-3); margin: var(--space-3) 0;
  font-size: var(--text-caption);
}
.prime-num {
  width: 56px; padding: var(--space-2); text-align: center;
  font-size: var(--text-body); font-family: var(--font-body);
  border: 2px solid var(--module-color); border-radius: var(--radius-sm);
  background: var(--surface);
}
.prime-eq-btn { padding: var(--space-1) var(--space-3); font-size: var(--text-caption); }

/* --- 那排数字（L1 Act2 两条推进器交付的同一样东西）--- */
.prime-batch {
  margin: var(--space-4) 0; padding: var(--space-3);
  background: var(--surface); border-radius: var(--radius-md); box-shadow: var(--shadow-sm);
}
.prime-batch-tip { font-size: var(--text-caption); color: var(--text-secondary); }
.prime-batch-row, .prime-chip-row {
  display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-2);
  justify-content: center;       /* 与上方 .prime-slots 同轴；不加会在只剩一个候选时左贴边 */
}
.prime-num-chip {
  min-width: 44px; min-height: 44px;           /* 触摸目标 ≥44dp（UX-06）*/
  border: 2px solid var(--module-color); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--module-dark);
  font-size: var(--text-body); font-weight: var(--weight-bold);
  cursor: pointer; touch-action: manipulation;
}
.prime-num-chip.done { background: var(--module-light); color: var(--text-muted); border-color: var(--surface-dim); }

/* --- 因数栏（L2）：格子填不满就不给过，⛔ 让空格说话、不弹红叉 --- */
.prime-slots { display: flex; gap: var(--space-2); justify-content: center; margin: var(--space-3) 0; }
.prime-slot {
  width: 52px; height: 52px; line-height: 48px; text-align: center;
  border: 2px dashed var(--module-color); border-radius: var(--radius-sm);
  background: var(--surface); font-size: var(--text-title); color: var(--text-primary);
  cursor: pointer;
}
.prime-slot.filled { border-style: solid; background: var(--module-light); }

/* 搭桥（L2 唯一一次显式说"因数"是什么）*/
.prime-bridge {
  background: var(--info-bg); border-left: 4px solid var(--module-color);
  border-radius: var(--radius-sm); padding: var(--space-3);
  margin-bottom: var(--space-3); font-size: var(--text-caption); line-height: 1.7;
}
.prime-eq-line { text-align: center; font-size: var(--text-title); color: var(--text-primary); margin: var(--space-2) 0; }
.prime-readonly-rect { display: flex; justify-content: center; margin-bottom: var(--space-3); }
.prime-readonly-rect .prime-board { max-width: 280px; }

/* 并排对照（L2-02：先让"够不够两个"立住，再谈 1 算不算质数）*/
.prime-contrast { display: flex; gap: var(--space-6); justify-content: center; margin: var(--space-4) 0; }
.prime-contrast-col { text-align: center; }
.prime-contrast-n { font-size: var(--text-title); font-weight: var(--weight-bold); margin-bottom: var(--space-2); }
.prime-contrast .prime-slot { width: 40px; height: 40px; line-height: 36px; font-size: var(--text-body); }

/* --- Act3 两堆（先给画面、后给名字）---
   合数堆用合数青、质数堆用质数紫 —— 两套状态色在本专题跨关唯一，⛔ 不许别处再用这两个色相。*/
.prime-two-heap { display: flex; gap: var(--space-3); margin: var(--space-4) 0; }
.prime-heap {
  flex: 1; background: var(--surface); border-radius: var(--radius-md);
  padding: var(--space-3); box-shadow: var(--shadow-sm);
  border-top: 4px solid #0891B2;              /* 合数青 */
}
.prime-heap:last-child { border-top-color: #7C3AED; }   /* 质数紫 */
.prime-heap-title { font-size: var(--text-caption); color: var(--text-secondary); margin-bottom: var(--space-2); }
.prime-heap-nums { font-size: var(--text-title); color: var(--text-primary); line-height: 1.6; }
.prime-reveal {
  background: var(--module-light); border-radius: var(--radius-md);
  padding: var(--space-4); text-align: center; line-height: 1.8;
  font-size: var(--text-body); color: var(--text-primary);
}

/* --- 动作区 / 安全出口（X-19：[↺ 重来] 每关常驻、撤销一步）--- */
.prime-actions { display: flex; gap: var(--space-3); justify-content: center; margin: var(--space-4) 0; }
.prime-safety-bar {
  display: flex; gap: var(--space-2); justify-content: center;
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: 1px solid var(--surface-dim);
}
.prime-card-desc { font-size: var(--text-caption); color: var(--text-secondary); margin-top: 4px; }

/* --- 窄屏：双栏堆叠，格子不缩到点不中 --- */
@media (max-width: 420px) {
  .prime-two-col { flex-direction: column; }
  .prime-side { width: 100%; flex: none; }
  .prime-slot { width: 44px; height: 44px; line-height: 40px; font-size: var(--text-body); }
}

/* 答题屏外壳（对齐 .eq-game-wrap 的页面容器约定：内容区 max-width 480 居中）*/
/* ⚠️ width:100% 不能省：.screen 是 flex 容器，子项 width:auto 会取**内容宽度**而不是
   填满容器——棋盘 513px 的内容宽一路传上来，就把这层撑到 max-width 480px，
   而屏幕只有 390px。body 是 overflow-x:hidden，于是不滚动、直接被裁掉右边一截，
   看起来就是"画面歪了、棋子跑出屏幕"（真玩实测）。*/
.prime-game-wrap {
  width: 100%; max-width: 480px; margin: 0 auto; min-width: 0;
  padding: var(--space-4);
  /* 底部多留一块：.nav-controls（草稿铅笔）是 fixed 在屏幕底部的，
     页面内容一长，关间导航（返回选关 / 下一关）就正好被它压住。*/
  padding-bottom: 96px;
}

/* =============================================
   批 3：L4 下注 / L5 形状对照 / L6 交叉分类贴标签
   配色纪律同上：状态色（质数紫 #7C3AED / 合数青 #0891B2 / 可操作蓝）跨关唯一，
   ⛔ 本批新增的任何装饰色都不许落到紫 / 青 / 蓝上。
   ============================================= */

/* --- 下注区（L4 押注 · L5 产出槽 · L6 判定）---
   why 做成两颗并排大按钮而不是下拉/输入：下注要的是"当场表态"，
   多一步操作就会把"我真的这么想"变成"我再想想哪个是对的"。*/
.prime-bet { display: flex; gap: var(--space-3); justify-content: center; margin: var(--space-4) 0; flex-wrap: wrap; }
.prime-bet-btn {
  min-width: 104px; min-height: 52px; padding: 0 var(--space-4);
  border: 2px solid var(--module-color); border-radius: var(--radius-md);
  background: var(--surface); color: var(--module-dark);
  font-size: var(--text-body); font-weight: var(--weight-bold); cursor: pointer;
}
.prime-bet-btn:active { background: var(--module-light); }

/* --- L4 数字键（往第二个因数格里试着填）---
   why 给键盘而不是 input：他要**一个一个试**、每次被拒都是一次证据；
   自由输入只会得到一个"随便打的数"，撞不出"哪个都填不进去"。*/
.prime-numpad {
  display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: center; margin: var(--space-3) 0;
}
.prime-num-key {
  width: 48px; height: 48px; border-radius: var(--radius-md);
  border: 1px solid var(--surface-dim); background: var(--surface);
  font-size: var(--text-body); color: var(--text-primary); cursor: pointer;
}
.prime-num-key:active { background: var(--module-light); }

/* --- L4 回看：把「他押的」与「他数出来的」并排，让他自己推翻 --- */
.prime-contrast-label { font-size: var(--text-caption); color: var(--text-secondary); margin-bottom: var(--space-2); }
.prime-bet-echo {
  font-size: var(--text-heading); font-weight: var(--weight-bold);
  color: var(--module-dark); padding: var(--space-3) 0;
}
.prime-count-echo { margin-top: var(--space-2); font-size: var(--text-body); color: var(--text-primary); }

/* --- L5 形状对照：2 的"两排"转 90° 后与"一条线"同形 ---
   why 用小方块拼而不是贴图：这两个形状必须看得出**是同一批棋子摆的**，
   换成插画就成了"系统告诉你它们一样"，本关要的恰恰相反。*/
.prime-contrast-zone { margin: var(--space-4) 0; }
.prime-shape-pair { display: flex; align-items: center; justify-content: center; gap: var(--space-4); flex-wrap: wrap; }
.prime-shape-col { text-align: center; }
.prime-shape-eq { font-size: var(--text-caption); color: var(--text-secondary); }
.prime-shape-cap { margin-top: var(--space-2); font-size: var(--text-caption); color: var(--text-secondary); }
.prime-mini { display: grid; gap: 3px; justify-content: center; }
.prime-mini i {
  display: block; width: 22px; height: 22px; border-radius: 50%;
  background: var(--module-color);
}
.prime-mini.v2 { grid-template-columns: repeat(1, 22px); }
.prime-mini.h2 { grid-template-columns: repeat(2, 22px); }
/* 对照组 4/6/8 一律摆成**两排**——它们真摆得成，这是 2 摆不成的参照物（表 D E2）。*/
.prime-mini.rows2 { grid-auto-flow: column; grid-template-rows: repeat(2, 22px); }
.prime-ref-row { display: flex; gap: var(--space-4); justify-content: center; flex-wrap: wrap; margin: var(--space-3) 0; }
.prime-ref-col { text-align: center; }

/* --- L6 预测槽（贴之前先猜 · ICAP A→C）--- */
.prime-predict { display: flex; justify-content: center; margin: var(--space-3) 0; }
.prime-predict-input {
  width: 100%; max-width: 320px; min-height: 48px; padding: 0 var(--space-3);
  border: 2px solid var(--surface-dim); border-radius: var(--radius-md);
  font-size: var(--text-body); color: var(--text-primary); background: var(--surface);
}
.prime-predict-input:focus { outline: none; border-color: var(--module-color); }

/* --- L6 两栏各贴一次 ---
   ⚠️ 承重结构在这里：左栏两个位、右栏**三个**位（[质][合][贴不上]）。
   写成一堆标签任选、或右栏只给两个位，1 那一行就会死锁（PRIME-L6-02）。*/
.prime-label-table { margin: var(--space-3) 0; }
.prime-label-head, .prime-label-row {
  display: grid; grid-template-columns: 48px 1fr 1.4fr; align-items: center; gap: var(--space-2);
}
.prime-label-head {
  font-size: var(--text-caption); color: var(--text-secondary);
  padding-bottom: var(--space-2); border-bottom: 1px solid var(--surface-dim);
}
.prime-label-row { padding: var(--space-3) 0; border-bottom: 1px solid var(--surface-dim); }
.prime-label-n { font-size: var(--text-heading); font-weight: var(--weight-bold); color: var(--module-dark); }
.prime-label-slot { display: flex; gap: 4px; flex-wrap: wrap; }
.prime-tag {
  padding: 8px 10px; min-height: 40px;
  border: 1px solid var(--surface-dim); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text-secondary);
  font-size: var(--text-caption); cursor: pointer; white-space: nowrap;
}
.prime-tag.on { color: #FFF; border-color: transparent; font-weight: var(--weight-bold); }
/* 质 / 合 选中时穿状态色（跨关唯一那两个色相）；[贴不上] 走中性灰——
   它不是第三类数，是"这把尺子量不了它"。*/
.prime-tag.on { background: var(--text-secondary); }
.prime-tag.on[data-label="质"] { background: #7C3AED; }
.prime-tag.on[data-label="合"] { background: #0891B2; }

/* --- 窄屏：表格三列会挤，标签换行、数字列收窄 --- */
@media (max-width: 420px) {
  .prime-label-head, .prime-label-row { grid-template-columns: 36px 1fr 1.5fr; gap: 4px; }
  .prime-tag { padding: 8px 7px; font-size: 12px; }
  .prime-num-key { width: 44px; height: 44px; }
  .prime-bet-btn { min-width: 88px; }
}

/* =============================================
   批 4：L7 划掉倍数筛质数（百数表 PrimeSieve）
   划除四色是**标记色**（仅本关有效）：2 橙 / 3 绿 / 5 品红 / 7 棕，
   ⛔ 一律避开状态色紫 / 青 / 蓝——紫在本专题永远只表示"质数"。
   ============================================= */

/* --- 三猜下注（⛔ 在给出百数表之前）--- */
.prime-bet3 { display: flex; flex-direction: column; gap: var(--space-3); margin: var(--space-4) 0; }
.prime-bet3-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-3); background: var(--surface); border-radius: var(--radius-md);
}
.prime-bet3-row span { font-size: var(--text-body); color: var(--text-primary); }
.prime-bet3-row .prime-num { width: 84px; }

/* --- 百数表：10 列必须在 375px 手机塞得下（技术方案 §不确定②）---
   不画行列表头（grid.js 原版有，这里不需要：本关要的是"一族数被一起划掉"，不是定位行列）。*/
.prime-sieve { display: grid; gap: 3px; margin: var(--space-3) auto; max-width: 420px; }
.prime-sieve-cell {
  position: relative; aspect-ratio: 1; min-width: 0;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--surface-dim); border-radius: var(--radius-sm);
  background: var(--surface); font-size: var(--text-caption); color: var(--text-primary);
}
/* 剩下的发光格＝质数（收口那句"剩下的发光格就是质数"靠它成立）*/
.prime-sieve-cell.alive { background: #FFF7ED; border-color: var(--module-color); font-weight: var(--weight-bold); }
.prime-sieve-cell.struck { background: var(--surface-dim); color: var(--text-secondary); }
.prime-sieve-cell.struck .prime-sieve-n { text-decoration: line-through; }
/* 1 单独一种：既不是质数也不是合数，⛔ 不能留在"剩下"里，也不该染上任何一种倍数色 */
.prime-sieve-cell.one { background: #EEE; border-style: dashed; }
.prime-sieve-cell.just { animation: primeStrikeIn 0.25s var(--ease-out); }
@keyframes primeStrikeIn { from { transform: scale(1.18); } to { transform: scale(1); } }
/* 连错两次时高亮"他划对的部分"（PRIME-L7-04），⛔ 不直接指出漏了哪一轮 */
.prime-sieve-cell.ok-hl { box-shadow: 0 0 0 2px var(--success, #16A34A) inset; }
.prime-sieve-n { line-height: 1; }
/* ★色盲可及性：颜色之外的数字冗余——角标写明"被谁划的"，6 显示 2·3 */
/* ⚠️ 实测教训：9px 角标在 30px 格子里**肉眼几乎不可辨**，等于没有冗余。
   格子尺寸是硬约束（10 列必须塞进 375px），所以改成两级：
     · 单次划——角标 10px 加粗（够认出"被谁划的"）
     · **划了多次**——加粗边框 + 角标着重：这是本关的关键教学信号（收口就问"6 为什么被划两次"），
       它必须在**不靠颜色**的情况下也一眼看得出来（形状冗余），⛔ 不能只靠四色区分。*/
.prime-sieve-by {
  position: absolute; right: 1px; bottom: 0;
  font-size: 10px; font-weight: var(--weight-bold); color: var(--text-secondary); line-height: 1;
}
.prime-sieve-cell.multi { border-width: 3px; border-style: double; }
.prime-sieve-cell.multi .prime-sieve-by { color: var(--text-primary); }
.prime-sieve-one { display: flex; justify-content: center; margin: var(--space-3) 0; }
.prime-sieve-one .prime-sieve-cell { width: 64px; height: 64px; aspect-ratio: auto; font-size: var(--text-heading); }

/* --- 已划图例 + 报数条（X-09：先说划几的倍数再开划）--- */
.prime-sieve-legend { display: flex; gap: var(--space-2); flex-wrap: wrap; justify-content: center; font-size: var(--text-caption); color: var(--text-secondary); }
.prime-legend-item { padding: 2px 8px; border-radius: 999px; border: 2px solid var(--mark); }
.prime-sieve-bar { margin-top: var(--space-4); text-align: center; }
.prime-sieve-keys { display: flex; gap: var(--space-2); justify-content: center; margin: var(--space-3) 0; }
.prime-sieve-key {
  width: 52px; height: 52px; border-radius: var(--radius-md);
  border: 2px solid var(--mark); background: var(--surface); color: var(--text-primary);
  font-size: var(--text-heading); font-weight: var(--weight-bold); cursor: pointer;
}
.prime-sieve-key.on { background: var(--mark); color: #FFF; }
.prime-sieve-key.done { opacity: 0.4; cursor: default; }

/* --- 预测槽圈选 / 对照 --- */
.prime-circle-grid { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: center; margin: var(--space-3) 0; }
.prime-circle {
  min-width: 46px; min-height: 46px; padding: 0 6px;
  border: 2px dashed var(--surface-dim); border-radius: 50%;
  background: var(--surface); font-size: var(--text-body); color: var(--text-primary); cursor: pointer;
}
.prime-circle.on { border-style: solid; border-color: var(--module-color); background: var(--module-light); font-weight: var(--weight-bold); }
.prime-compare-row { display: flex; gap: var(--space-3); align-items: baseline; margin: var(--space-2) 0; }
.prime-compare-label { flex: none; width: 84px; font-size: var(--text-caption); color: var(--text-secondary); }
.prime-compare-nums { font-size: var(--text-body); color: var(--text-primary); }

/* --- 自检数 / 收口追问 --- */
.prime-selfcheck { display: flex; gap: var(--space-2); align-items: center; justify-content: center; flex-wrap: wrap; margin: var(--space-4) 0; }
.prime-selfcheck .prime-num { width: 72px; }
.prime-choices { display: flex; flex-direction: column; gap: var(--space-2); max-width: 360px; margin: var(--space-3) auto; }
.prime-choice {
  padding: var(--space-3); min-height: 52px;
  border: 2px solid var(--surface-dim); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text-primary); font-size: var(--text-body);
  text-align: left; cursor: pointer;
}
.prime-choice:active { border-color: var(--module-color); background: var(--module-light); }

@media (max-width: 420px) {
  .prime-sieve { gap: 2px; }
  .prime-sieve-cell { border-width: 1px; font-size: 12px; }
  .prime-sieve-by { font-size: 8px; }
  .prime-sieve-key { width: 46px; height: 46px; }
}
.prime-count-btn { margin-left: var(--space-2); }

/* =============================================
   批 5：L8 秒杀分栏 / L9 试除盘（PrimeTrial）
   ============================================= */

/* --- L8 待判的一批数 + 三个栏 --- */
.prime-pool { display: flex; gap: var(--space-2); flex-wrap: wrap; justify-content: center; margin: var(--space-3) 0; }
.prime-pool-n {
  min-width: 64px; min-height: 48px; padding: 0 var(--space-3);
  border: 2px solid var(--surface-dim); border-radius: var(--radius-md);
  background: var(--surface); font-size: var(--text-body); font-weight: var(--weight-bold);
  color: var(--text-primary); cursor: pointer;
}
.prime-pool-n.on { border-color: var(--module-color); background: var(--module-light); }
.prime-bins { display: flex; gap: var(--space-2); margin: var(--space-3) 0; }
.prime-bin {
  flex: 1; min-height: 96px; padding: var(--space-3);
  border: 2px dashed var(--surface-dim); border-radius: var(--radius-md);
  background: var(--surface); cursor: pointer; text-align: center;
}
.prime-bin-label { font-size: var(--text-caption); color: var(--text-secondary); margin-bottom: var(--space-2); }
.prime-bin-items { font-size: var(--text-body); color: var(--text-primary); font-weight: var(--weight-bold); }
/* 对照例里被划掉的那几个（E5：个位是 3 却不是 3 的倍数）*/
.prime-circle.crossed { text-decoration: line-through; opacity: 0.55; border-style: solid; }

/* --- L9 试除盘：一排**递增的质数卡**（DOM 顺序即数学顺序）---
   ⛔ 不做转盘：转盘角度不映射任何数学量（DP-效果-80 圆形棋盘式失配）。*/
.prime-tray-cards { display: flex; gap: var(--space-2); flex-wrap: wrap; justify-content: center; margin: var(--space-3) 0; }
.prime-card {
  min-width: 46px; min-height: 58px;
  border: 2px solid var(--module-color); border-radius: var(--radius-md);
  background: var(--surface); color: var(--module-dark);
  font-size: var(--text-heading); font-weight: var(--weight-bold); cursor: pointer;
}
.prime-card.on { background: var(--module-color); color: #FFF; }
/* 试过的牌**留在盘上**、只是淡一点：⛔ 不许移走或禁用——"我试到哪儿了"要一直看得见 */
.prime-card.used { opacity: 0.45; }

/* --- 试除记录条（bansho · UX-26）：append-only，整关留存可回看，⛔ 提交后不清屏 --- */
.prime-record-title { margin-top: var(--space-4); font-size: var(--text-caption); color: var(--text-secondary); }
.prime-record {
  margin: var(--space-2) 0; padding: var(--space-3);
  background: var(--surface); border-radius: var(--radius-md); border: 1px solid var(--surface-dim);
  font-variant-numeric: tabular-nums;
}
.prime-record-row { padding: 4px 0; font-size: var(--text-body); color: var(--text-primary); }
.prime-record-empty { font-size: var(--text-caption); color: var(--text-secondary); }
.prime-record-note { margin-left: var(--space-2); font-size: var(--text-caption); color: var(--text-secondary); }
/* 分段里程碑：⛔ 不是分数、不是星星，就是一句安静的确认 */
.prime-seg { margin-left: var(--space-2); font-size: var(--text-caption); color: var(--success, #16A34A); }

/* --- ★因数阶梯：排成一排，中间折返 --- */
.prime-ladder {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center; justify-content: center;
  margin: var(--space-3) 0; padding: var(--space-3);
  background: var(--module-light); border-radius: var(--radius-md);
}
.prime-ladder-pair {
  padding: 4px 8px; border-radius: var(--radius-sm);
  background: var(--surface); font-size: var(--text-caption); color: var(--text-primary);
}
/* 折返之后的每一对，只是前面某一对倒过来——用同色淡化表达"回头路" */
.prime-ladder-pair.mirror { opacity: 0.5; }
.prime-ladder-axis {
  width: 100%; text-align: center; font-size: var(--text-caption);
  color: var(--module-dark); font-weight: var(--weight-bold); padding: var(--space-2) 0;
}

/* --- 9×9 面积图（⛔ 辅助图、不作主线）--- */
.prime-area9 {
  display: grid; grid-template-columns: repeat(9, 1fr); gap: 2px;
  max-width: 260px; margin: var(--space-3) auto;
}
.prime-area9 i { display: block; aspect-ratio: 1; border-radius: 50%; background: var(--module-color); }
.prime-area9 i.empty { background: transparent; border: 1px dashed var(--surface-dim); }

@media (max-width: 420px) {
  .prime-bins { flex-direction: column; }
  .prime-bin { min-height: 72px; }
  .prime-card { min-width: 42px; min-height: 52px; }
}

/* =============================================
   批 6：L10 骗子数显形 / LV 相变验收闸
   ============================================= */

/* --- L10 整除显形：⛔ 绝不用"一颗棋子代表 10"的缩放 ---
   n ≤ 100 真点阵成形；n > 100 画一行真的 + 省略号 + "这样的一排有 N 排"。
   why 不缩放：一缩放，"摆得成长方形"就不再是 n 的物理事实（DP-效果-80）。*/
.prime-dots { display: grid; gap: 3px; max-width: 320px; margin: var(--space-3) auto; }
.prime-dots i { display: block; aspect-ratio: 1; border-radius: 50%; background: var(--module-color); }
.prime-dots-row { display: flex; gap: 3px; flex-wrap: wrap; align-items: center; justify-content: center; margin: var(--space-3) 0; }
.prime-dots-row i { display: block; width: 12px; height: 12px; border-radius: 50%; background: var(--module-color); }
.prime-dots-more { margin-left: var(--space-2); font-size: var(--text-caption); color: var(--text-secondary); }
.prime-rows-hint { text-align: center; font-size: var(--text-caption); color: var(--text-secondary); }

/* --- LV 相变验收：一屏三题，每题「质/合 + 理由」 --- */
.prime-lv-list { margin: var(--space-3) 0; }
.prime-lv-item {
  padding: var(--space-3); margin-bottom: var(--space-3);
  background: var(--surface); border-radius: var(--radius-md); border: 1px solid var(--surface-dim);
}
.prime-lv-n { font-size: var(--text-heading); font-weight: var(--weight-bold); color: var(--module-dark); text-align: center; }
.prime-lv-item .prime-bet { margin: var(--space-2) 0; }
.prime-lv-item .prime-bet-btn { min-width: 88px; min-height: 46px; }
.prime-bet-btn.on { background: var(--module-color); color: #FFF; }
.prime-lv-reason {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; justify-content: center;
  font-size: var(--text-body); color: var(--text-primary);
}
.prime-lv-reason .prime-num { width: 88px; }
.prime-lv-reason-hint { text-align: center; font-size: var(--text-caption); color: var(--text-secondary); }

/* --- ★ CALC 与草稿位：⛔ 不在收走之列（收的是判定工具，不是算术卸载）--- */
.prime-lv-tools {
  margin: var(--space-4) 0; padding: var(--space-3);
  background: var(--module-light); border-radius: var(--radius-md);
}
.prime-lv-tools-title { font-size: var(--text-caption); color: var(--text-secondary); margin-bottom: var(--space-2); }
.prime-calc { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.prime-calc .prime-num { width: 92px; }
.prime-calc-out { font-size: var(--text-body); font-weight: var(--weight-bold); color: var(--module-dark); min-width: 72px; }
.prime-scratch {
  width: 100%; min-height: 72px; margin-top: var(--space-3); padding: var(--space-2);
  border: 1px solid var(--surface-dim); border-radius: var(--radius-sm);
  background: var(--surface); font-size: var(--text-body); color: var(--text-primary); resize: vertical;
}

/* =============================================
   批 7：L11 配对推奇偶 / L12 负荷最高关（减负三件套）
   ============================================= */

/* --- L11 两两配对：**落单那颗居中高亮** ＝ 奇（物理判据要看得见）--- */
.prime-pairs { display: flex; flex-direction: column; gap: var(--space-3); margin: var(--space-3) 0; }
.prime-pair-row {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  padding: var(--space-2) var(--space-3); background: var(--surface); border-radius: var(--radius-md);
}
.prime-pair-n { min-width: 32px; font-size: var(--text-heading); font-weight: var(--weight-bold); color: var(--module-dark); }
.prime-pair-dots { display: flex; gap: 3px; flex-wrap: wrap; align-items: center; flex: 1; }
.prime-pair-dots i { display: block; width: 16px; height: 16px; border-radius: 50%; background: var(--module-color); }
/* 每两颗之间拉开一点，"两两一组"要在视觉上成组 */
.prime-pair-dots i.pairstart { margin-left: 8px; }
.prime-pair-dots i.lone {
  background: var(--surface); border: 3px solid var(--module-color);
  box-shadow: 0 0 0 4px var(--module-light);
}
.prime-pair-dots.big { justify-content: center; margin: var(--space-3) 0; }
.prime-pair-dots.big i { width: 22px; height: 22px; }
.prime-pair-verdict { font-size: var(--text-caption); color: var(--text-secondary); }

/* --- L11 规律表：三格由他填，每格下面挂着**他自己摆过的那次配对** --- */
.prime-parity-table { display: flex; gap: var(--space-2); margin: var(--space-3) 0; }
.prime-parity-col { flex: 1; text-align: center; }
.prime-parity-head { font-size: var(--text-caption); color: var(--text-secondary); margin-bottom: var(--space-2); }
.prime-parity-cell { display: flex; gap: 4px; justify-content: center; }
.prime-parity-backing { margin-top: var(--space-2); font-size: 11px; color: var(--text-secondary); line-height: 1.4; }

/* --- L12 常驻区：关键信息钉在屏上，⛔ 不用回忆、不用翻页 --- */
.prime-pinned {
  position: sticky; top: 0; z-index: 2;
  margin: var(--space-3) 0; padding: var(--space-3);
  background: var(--module-light); border-radius: var(--radius-md);
}
.prime-pinned-title { font-size: var(--text-caption); color: var(--text-secondary); margin-bottom: var(--space-2); }
.prime-pinned-grid { display: flex; gap: var(--space-3); flex-wrap: wrap; font-size: var(--text-body); color: var(--module-dark); }
/* "2 是唯一偶质数"分段点亮：第③步作答前不显示，⛔ 否则减负就减到动脑门槛上了 */
.prime-pinned-hint {
  margin-top: var(--space-2); padding: var(--space-2);
  background: var(--surface); border-radius: var(--radius-sm);
  font-weight: var(--weight-bold); color: var(--module-dark);
}
.prime-pinned-ask {
  margin-top: var(--space-2); padding: 6px 10px;
  border: 1px dashed var(--module-color); border-radius: var(--radius-sm);
  background: transparent; color: var(--module-dark); font-size: var(--text-caption); cursor: pointer;
}

/* --- L12 一屏一事：一次只显示一步 --- */
.prime-step { margin: var(--space-4) 0; }
.prime-step-q { font-size: var(--text-body); color: var(--text-primary); margin-bottom: var(--space-3); text-align: center; }
.prime-step-in { display: flex; gap: var(--space-2); justify-content: center; align-items: center; }
.prime-step-in .prime-num { width: 96px; }
/* 答错分支：⛔ 不判错、不换答案，要他指依据（问的是依据不是答案）*/
.prime-depend {
  margin-top: var(--space-3); padding: var(--space-3);
  background: var(--surface); border: 1px dashed var(--module-color); border-radius: var(--radius-md);
}
.prime-verify-row { display: flex; gap: var(--space-3); justify-content: center; margin: var(--space-3) 0; }

@media (max-width: 420px) {
  .prime-parity-table { gap: 4px; }
  .prime-parity-backing { font-size: 10px; }
  .prime-pinned-grid { gap: var(--space-2); font-size: var(--text-caption); }
}

/* =============================================
   批 8：L13 判型 / L14 分层枚举 / L15 三色分堆论证
   ============================================= */

/* --- L13 先判型再动笔（四道题里必须有干扰题）--- */
.prime-keylist { margin: var(--space-3) 0; }
.prime-keyrow {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  flex-wrap: wrap; padding: var(--space-3);
  background: var(--surface); border-radius: var(--radius-md); margin-bottom: var(--space-2);
}
.prime-keyq { font-size: var(--text-body); color: var(--text-primary); }
.prime-keybtns { display: flex; gap: 4px; }

/* --- L14 分层枚举格：重复的落回同一格、漏整层就空着（⛔ 不提示）--- */
.prime-layers { display: flex; flex-direction: column; gap: var(--space-3); margin: var(--space-3) 0; }
.prime-layer { padding: var(--space-3); background: var(--surface); border-radius: var(--radius-md); }
.prime-layer-head { font-size: var(--text-caption); color: var(--text-secondary); margin-bottom: var(--space-2); }
.prime-layer-cells { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.prime-layer-cell {
  min-width: 54px; min-height: 40px; line-height: 36px; text-align: center;
  border: 2px dashed var(--surface-dim); border-radius: var(--radius-sm);
  font-size: var(--text-body); color: var(--text-primary);
}
.prime-layer-cell.got { border-style: solid; border-color: var(--module-color); background: var(--module-light); font-weight: var(--weight-bold); }

/* --- L15 三色分堆（⛔ 脚手架撤不得）---
   颜色**另配形状冗余**（●▲■）：色盲可及性，且三色里避开了状态色紫/青/蓝。*/
.prime-bins3 { display: flex; gap: var(--space-2); margin: var(--space-3) 0; }
.prime-bin3 {
  flex: 1; min-height: 84px; padding: var(--space-3); text-align: center;
  border: 3px solid var(--mark); border-radius: var(--radius-md); background: var(--surface);
}
.prime-bin3-head { font-size: var(--text-caption); color: var(--mark); font-weight: var(--weight-bold); }
.prime-bin3-items { margin-top: var(--space-2); font-size: var(--text-body); color: var(--text-primary); }
.prime-termrow { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-3) 0; }
.prime-term {
  display: flex; align-items: center; gap: var(--space-2); justify-content: space-between;
  padding: var(--space-2) var(--space-3); background: var(--surface); border-radius: var(--radius-md);
  font-size: var(--text-body); color: var(--text-primary);
}

/* --- L15 结论链：三段由他补，⛔ 系统不替他说完 --- */
.prime-chain { margin: var(--space-3) 0; }
.prime-chain-row {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  padding: var(--space-3); margin-bottom: var(--space-2);
  background: var(--surface); border-radius: var(--radius-md);
  font-size: var(--text-body); color: var(--text-primary);
}
.prime-chain-row select {
  min-height: 44px; padding: 0 var(--space-2);
  border: 2px solid var(--surface-dim); border-radius: var(--radius-sm);
  background: var(--surface); font-size: var(--text-body); color: var(--text-primary);
}
.prime-chain-row .prime-num { width: 88px; }

@media (max-width: 420px) {
  .prime-bins3 { gap: 4px; }
  .prime-bin3 { padding: var(--space-2); }
  .prime-keyrow { flex-direction: column; align-items: flex-start; }
}

/* --- 批 9：四张复习卡（先闪坑卡 → 再做同类新题）--- */
.prime-pit {
  margin: var(--space-3) 0; padding: var(--space-3);
  background: #FEF3C7; border-left: 4px solid var(--warning, #D97706); border-radius: var(--radius-sm);
  font-size: var(--text-body); color: var(--text-primary); text-align: left;
}
/* 卡一换材料：面积矩形，⛔ 不用棋子（T-21 多重具体化）*/
.prime-card-rects { display: flex; gap: var(--space-3); justify-content: center; flex-wrap: wrap; margin: var(--space-3) 0; }
.prime-card-rect { text-align: center; }
.prime-card-rect .prime-mini { display: grid; gap: 2px; justify-content: center; }
.prime-card-rect .prime-mini i { width: 10px; height: 10px; border-radius: 2px; background: var(--module-color); }

/* --- L0 走过的痕迹：一堆一个记号。⛔ 不给分不给星（暖场关不进积分体系），
       但"玩了半天跟没玩一样"同样不行——痕迹是他走过的路，不是奖励。--- */
.prime-l0-trail { display: flex; gap: var(--space-2); justify-content: center; margin: var(--space-3) 0; }
.prime-l0-trail i {
  width: 10px; height: 10px; border-radius: 50%;
  border: 2px solid var(--surface-dim); background: transparent;
}
.prime-l0-trail i.done { border-color: var(--correct); background: var(--correct); }
.prime-l0-trail i.cur { border-color: var(--module-color); transform: scale(1.35); }
