{
  "schema_version": "np-ui-inventory.v1",
  "audited_at": "2026-10-11T17:41:39.922399+08:00",
  "scope": "最新 prototype/dist 静态源码只读盘点；运行行为由绑定与状态条件推导，根代理另做浏览器复核。未改demo、PPT或图片。",
  "source_snapshot": {
    "prototype/dist/cards.js": {
      "sha256": "d9fb59d7743aee2ce09b19d5621a92a40f0a4e5682cbf1a65b5598d6114f875d",
      "bytes": 3807,
      "line_count": 63,
      "modified_at": "2026-10-11T01:55:38.165103+08:00"
    },
    "prototype/dist/combat.js": {
      "sha256": "5ae9c45db60bb7522639c72f5e119a732e87c854cb592edb396498f12da96438",
      "bytes": 42134,
      "line_count": 769,
      "modified_at": "2026-10-11T17:39:33.961380+08:00"
    },
    "prototype/dist/index.html": {
      "sha256": "51c732c579232be0c0bd7a418f3caa3d1dfb0f37bec5d24a673253b5a3d1ec2e",
      "bytes": 12489,
      "line_count": 24,
      "modified_at": "2026-10-11T17:01:54.501758+08:00"
    },
    "prototype/dist/rules.js": {
      "sha256": "afab57f4adab35c5dedfecb7036fcf2ae05ba6c6dfdd1aa9caa1cc9c7e798f90",
      "bytes": 19868,
      "line_count": 352,
      "modified_at": "2026-10-11T11:38:26.360895+08:00"
    },
    "prototype/dist/试玩下载.html": {
      "sha256": "da1b874deae54404dca8906a42cf02dbc77ffe80419e133737d3bace59945bfe",
      "bytes": 246128,
      "line_count": 6186,
      "modified_at": "2026-10-11T17:35:47.738383+08:00"
    },
    "prototype/dist/economy.js": {
      "sha256": "563bd8a670211660ac48cd2ec449fcf2b011753e0250bdf05fc779f91a0c430e",
      "bytes": 3528,
      "line_count": 61,
      "modified_at": "2026-10-11T11:37:59.652768+08:00"
    },
    "prototype/dist/levels.js": {
      "sha256": "8463874fc039aac56122126d89bbad17384d13b5cc9233f6b2494d4d00d9fcc3",
      "bytes": 79365,
      "line_count": 4186,
      "modified_at": "2026-10-11T17:39:34.003005+08:00"
    },
    "prototype/dist/inventory.js": {
      "sha256": "f2d3029c5b38f70b73edea216930e1afd66c6e7770a42e92d79c2c5e6a809a90",
      "bytes": 7711,
      "line_count": 130,
      "modified_at": "2026-10-11T01:55:06.032140+08:00"
    },
    "prototype/dist/style.css": {
      "sha256": "dd4ccbd5d32c1d3d05ae63caf9d647bc6d6805e76e9449363f5d4d5ff322c661",
      "bytes": 30443,
      "line_count": 179,
      "modified_at": "2026-10-11T15:50:28.657530+08:00"
    },
    "prototype/dist/unitVisual.js": {
      "sha256": "51b7f6e1c1bfb00a796a640a0cda346a4817a0c495baf3de0a7b69f29f91c15b",
      "bytes": 6521,
      "line_count": 132,
      "modified_at": "2026-10-11T11:13:24.678508+08:00"
    },
    "prototype/dist/app.js": {
      "sha256": "34165c87eeab74f0f84d1435e5500176dc153d5356f7a855df3ca2bca07917f5",
      "bytes": 39267,
      "line_count": 221,
      "modified_at": "2026-10-11T17:34:21.726187+08:00"
    }
  },
  "source_refs_base": "/Users/dingzhuqi/Documents/ChatGPT/NP/prototype/dist",
  "summary": {
    "level_count": 16,
    "native_dialog_count": 5,
    "state_count": 68,
    "categories": {
      "全屏": 6,
      "弹窗": 10,
      "局部状态": 29,
      "提示文案": 23
    }
  },
  "entries": [
    {
      "id": "F01",
      "category": "全屏",
      "name": "手机主游戏：准备开始",
      "trigger": "首次载入、切关、重开或结算按钮返回关卡",
      "visible_copy": [
        "{level.name}",
        "{level.kicker} ▾",
        "待开始",
        "00:00",
        "开始本关",
        "{level.goal}",
        "建造点",
        "换一批",
        "出"
      ],
      "source_refs": [
        "index.html:8-14",
        "app.js:80-87",
        "app.js:123-134",
        "style.css:64-103"
      ],
      "behavior": "开始按钮叠在整块游戏中央；候选卡、棋盘、换批禁用；开始前仍可选关、开菜单、调倍速、开关音效。",
      "design": "independent"
    },
    {
      "id": "F02",
      "category": "全屏",
      "name": "手机主游戏：实时布阵与交战",
      "trigger": "点击开始本关或继续战斗",
      "visible_copy": [
        "交战中",
        "{MM:SS}",
        "Ⅱ",
        "{resources}",
        "+{incomeAmount} / {seconds}s",
        "{wave_status}"
      ],
      "source_refs": [
        "app.js:55-64",
        "app.js:123-146",
        "app.js:147-148"
      ],
      "behavior": "战斗进行同时摆牌、移动、交换、合并、换批；计时是已战斗时长递增，不是倒计时。",
      "design": "independent"
    },
    {
      "id": "F03",
      "category": "全屏",
      "name": "手机主游戏：暂停中可布阵",
      "trigger": "运行中暂停后收起菜单，或页面切后台触发自动暂停",
      "visible_copy": [
        "已暂停",
        "继续战斗",
        "已暂停，可以继续调整布阵",
        "☰"
      ],
      "source_refs": [
        "app.js:123-137",
        "app.js:194",
        "app.js:217"
      ],
      "behavior": "继续入口只覆盖上方战场；卡牌与棋盘仍可调整。资源、出兵、战斗及奖励冷却暂停；点击继续才恢复。",
      "design": "independent"
    },
    {
      "id": "F04",
      "category": "全屏",
      "name": "英雄关主游戏：赵云与传承",
      "trigger": "进入第16关，同一单位依次获得赵和云",
      "visible_copy": [
        "赵云初阵",
        "赵云",
        "赵云!",
        "赵云变身：金色主字，伤害系数1.8、攻速翻倍；原基础组合的专属能力保留。"
      ],
      "source_refs": [
        "levels.js:3923-4186",
        "app.js:140",
        "unitVisual.js:3-8",
        "unitVisual.js:28-38"
      ],
      "behavior": "没有英雄领取/合成/升级弹窗；金色主字、附字/血条仍随阵营色；赵/云是普通候选字牌。",
      "design": "independent_variant"
    },
    {
      "id": "F05",
      "category": "全屏",
      "name": "桌面试玩框架",
      "trigger": "视口宽于850px",
      "visible_copy": [
        "一字成兵",
        "十六关试炼",
        "玩法说明",
        "从一字到一支军队",
        "字成兵，\n路成阵。",
        "玩法要诀",
        "可玩原型 · 赵云变身",
        "这一条路会造出什么",
        "行军预览",
        "字的力量",
        "先规划路线，再观察前线。"
      ],
      "source_refs": [
        "index.html:5-7",
        "index.html:16",
        "style.css:1-4",
        "style.css:64-66"
      ],
      "behavior": "左侧16关导航，中央游戏，右侧预览/选择说明/反馈；移动端隐藏这些侧栏与品牌头。",
      "design": "responsive_extension"
    },
    {
      "id": "F06",
      "category": "全屏",
      "name": "单文件试玩下载页",
      "trigger": "直接打开试玩下载.html",
      "visible_copy": [
        "一字成兵 · 十六关试炼"
      ],
      "source_refs": [
        "试玩下载.html:1-205"
      ],
      "behavior": "离线单文件同款游戏，不是额外下载引导页；模块核验与当前dist七个模块一致。",
      "design": "reuse_F01_F05"
    },
    {
      "id": "M01",
      "category": "弹窗",
      "name": "暂停菜单：战斗已开始",
      "trigger": "点击运行状态Ⅱ，或暂停态☰",
      "visible_copy": [
        "一字成兵",
        "战斗已暂停",
        "收起菜单后可以调整路线，点击战场中央继续。",
        "继续战斗",
        "重新开始本关",
        "玩法说明",
        "×"
      ],
      "source_refs": [
        "index.html:19",
        "app.js:131-137",
        "app.js:194",
        "style.css:54-60"
      ],
      "dismiss": "×/Esc只收起菜单，保持暂停；继续按钮恢复；重开立即重置，无二次确认。",
      "design": "independent"
    },
    {
      "id": "M02",
      "category": "弹窗",
      "name": "暂停菜单：准备出阵",
      "trigger": "未开始时点击☰",
      "visible_copy": [
        "一字成兵",
        "准备出阵",
        "点击开始本关后才能布阵。",
        "开始本关",
        "重新开始本关",
        "玩法说明",
        "×"
      ],
      "source_refs": [
        "index.html:19",
        "app.js:131",
        "app.js:194"
      ],
      "design": "variant_M01"
    },
    {
      "id": "M03",
      "category": "弹窗",
      "name": "选关",
      "trigger": "点击游戏标题上方{level.kicker} ▾",
      "visible_copy": [
        "01–04 教学 · 05–15 挑战 · 16 赵云",
        "十六关试炼",
        "{01…16}",
        "{level.name}",
        "{教学/挑战/进阶/武将试玩} · {kicker后半段}",
        "✓",
        "×"
      ],
      "source_refs": [
        "index.html:20",
        "app.js:37-39",
        "app.js:189-193",
        "style.css:30-36"
      ],
      "behavior": "两列16关；当前关高亮，通关加✓。全部可直接点击，没有锁定关卡。打开会暂停；关闭恢复此前运行状态，选择新关进入待开始。",
      "design": "independent"
    },
    {
      "id": "M04",
      "category": "弹窗",
      "name": "玩法说明：长滚动册页",
      "trigger": "桌面玩法说明，或暂停菜单玩法说明",
      "visible_copy": [
        "行军小册",
        "认清开口，顺路成兵。",
        "知道了",
        "×",
        "字",
        "上、左",
        "上、右",
        "右、下",
        "下、左",
        "上、右、左",
        "上、右、下",
        "右、下、左",
        "上、下、左"
      ],
      "source_refs": [
        "index.html:21",
        "app.js:207-212",
        "style.css:1"
      ],
      "behavior": "8种开口图鉴+8段长规则；当前没有分页/Tab。菜单进入后关闭回菜单；桌面运行中直接进入，关闭恢复战斗。",
      "exact_long_copy_key": "help_paragraphs",
      "design": "independent_scroll_screen_and_content_board"
    },
    {
      "id": "M05",
      "category": "弹窗",
      "name": "奖励演示：补充建造点",
      "trigger": "开始后资源低于最便宜未购候选字牌，奖励可用时点击+60",
      "visible_copy": [
        "奖励视频 · 机制演示",
        "▶",
        "领取建造点",
        "观看后获得60建造点，用于摆牌或换批。",
        "当前为奖励机制演示，领取即模拟观看完成，取消不会发奖。",
        "模拟观看 · 领取60",
        "本关还可领{remaining}次，两次奖励间隔40秒战斗时间",
        "×"
      ],
      "source_refs": [
        "index.html:18",
        "app.js:62-63",
        "app.js:197-205",
        "economy.js:1",
        "economy.js:39-60"
      ],
      "behavior": "打开暂停；取消不发奖，领取模拟完成立即发60；关闭恢复打开前运行状态。不是实际视频、没有视频倒计时。",
      "design": "independent"
    },
    {
      "id": "M06",
      "category": "弹窗",
      "name": "奖励演示：免费换批",
      "trigger": "资源不足换批且奖励可用时点击带播放图标的换一批",
      "visible_copy": [
        "奖励视频 · 机制演示",
        "▶",
        "免费换一批",
        "换掉当前三张手牌，已购字牌也会弃掉。",
        "当前为奖励机制演示，领取即模拟观看完成，取消不会发奖。",
        "模拟观看 · 换一批",
        "本关还可领{remaining}次，两次奖励间隔40秒战斗时间",
        "×"
      ],
      "source_refs": [
        "index.html:18",
        "app.js:55-61",
        "app.js:195-205"
      ],
      "design": "variant_M05"
    },
    {
      "id": "M07",
      "category": "弹窗",
      "name": "普通关胜利结算",
      "trigger": "敌城HP清零，胜利动画2.3秒后",
      "visible_copy": [
        "胜",
        "第{N}关完成",
        "{level.name}",
        "{level.lesson}",
        "抵达战场",
        "击败敌兵",
        "战斗秒数",
        "{produced}",
        "{kills}",
        "{round(time)}",
        "进入下一关",
        "再试一种路线"
      ],
      "source_refs": [
        "index.html:22",
        "app.js:149-153",
        "app.js:210-211"
      ],
      "dismiss": "无×；Esc不可关闭。主按钮进下一关，次按钮重开本关。",
      "design": "independent"
    },
    {
      "id": "M08",
      "category": "弹窗",
      "name": "16关全部完成结算",
      "trigger": "第16关胜利，2.3秒后",
      "visible_copy": [
        "胜",
        "第16关完成",
        "16关试炼完成",
        "赵云出阵，十六关试炼完成。试试更短的路线，或让更多兵带上名字。",
        "抵达战场",
        "击败敌兵",
        "战斗秒数",
        "回到第一关",
        "再试一种路线"
      ],
      "source_refs": [
        "app.js:149-153",
        "app.js:210-211"
      ],
      "design": "variant_M07"
    },
    {
      "id": "M09",
      "category": "弹窗",
      "name": "失败结算：路线有产出",
      "trigger": "己城HP清零且trace.outputs非空，0.9秒后",
      "visible_copy": [
        "再战",
        "重新布阵，再来一次",
        "这条路，还能更强",
        "试着增加合并等级、分支数量，或缩短到出兵口的路线。",
        "抵达战场",
        "击败敌兵",
        "战斗秒数",
        "重新布阵",
        "再试一种路线"
      ],
      "source_refs": [
        "index.html:22",
        "app.js:149-153",
        "app.js:210-211"
      ],
      "dismiss": "无×；Esc不可关闭；两个按钮都重开本关。",
      "design": "independent_variant_M07"
    },
    {
      "id": "M10",
      "category": "弹窗",
      "name": "失败结算：路线无产出",
      "trigger": "己城HP清零且trace.outputs为空，0.9秒后",
      "visible_copy": [
        "再战",
        "重新布阵，再来一次",
        "这条路，还能更强",
        "检查开口是否对准。四边都能接入外环，沿箭头走到左上出兵口才参战。封闭边和障碍会挡住单位。",
        "重新布阵",
        "再试一种路线"
      ],
      "source_refs": [
        "app.js:152-153"
      ],
      "design": "copy_variant_M09"
    },
    {
      "id": "L01",
      "category": "局部状态",
      "name": "倍速按钮：1× / 2×",
      "trigger": "点击speed切换，切关/重开重置1×",
      "visible_copy": [
        "1×",
        "2×"
      ],
      "source_refs": [
        "app.js:85",
        "app.js:122",
        "app.js:194",
        "style.css:162"
      ],
      "tooltip": [
        "正常速度",
        "2倍加速中"
      ],
      "design": "component_board"
    },
    {
      "id": "L02",
      "category": "局部状态",
      "name": "音效开/关",
      "trigger": "点击♪，默认关闭",
      "visible_copy": [
        "♪"
      ],
      "source_refs": [
        "index.html:9",
        "app.js:206"
      ],
      "behavior": "图标不变，开时绿色；aria文案打开音效/关闭音效；无独立设置弹窗。",
      "design": "component_board"
    },
    {
      "id": "L03",
      "category": "局部状态",
      "name": "关卡按钮当前/完成",
      "trigger": "加载关卡或胜利保存",
      "visible_copy": [
        "{01…16}",
        "{level.name}",
        "✓"
      ],
      "source_refs": [
        "app.js:37-39",
        "app.js:150"
      ],
      "design": "component_board"
    },
    {
      "id": "L04",
      "category": "局部状态",
      "name": "教学推荐候选牌与落点",
      "trigger": "第1–4关，目标尚未达到，显示下一个未完成hint",
      "visible_copy": [
        "推荐",
        "{hint.letter}"
      ],
      "source_refs": [
        "app.js:34-36",
        "app.js:42-52",
        "style.css:1"
      ],
      "behavior": "候选牌推荐标签；目标空格虚线圆+字形提示。当前没有提示按钮/开关，hintsOn每关固定true。",
      "design": "component_board"
    },
    {
      "id": "L05",
      "category": "局部状态",
      "name": "普通候选卡",
      "trigger": "抽到字牌",
      "visible_copy": [
        "刀",
        "盾",
        "弓",
        "骑",
        "赵",
        "云",
        "{cost}",
        "{level}阶"
      ],
      "source_refs": [
        "app.js:22-30",
        "app.js:47-52",
        "cards.js:18-59",
        "economy.js:1-19"
      ],
      "behavior": "固定朝向，粗封边；大于1阶才显示阶。报价冻结，以牌面为准。",
      "design": "component_board"
    },
    {
      "id": "L06",
      "category": "局部状态",
      "name": "候选卡选中",
      "trigger": "点击/键盘选中手牌",
      "visible_copy": [
        "{letter}",
        "{cost}"
      ],
      "source_refs": [
        "app.js:52",
        "app.js:114",
        "app.js:187",
        "style.css:1"
      ],
      "behavior": "选中框与底色；再次点可取消；再点格子放牌。",
      "design": "component_board"
    },
    {
      "id": "L07",
      "category": "局部状态",
      "name": "候选卡资源不足",
      "trigger": "resources低于该候选报价",
      "visible_copy": [
        "{cost}"
      ],
      "source_refs": [
        "app.js:52",
        "app.js:64",
        "style.css:1",
        "style.css:169"
      ],
      "behavior": "普通卡整体半透明；分裂观看卡播放角标保持清楚，其字与价格降低不透明度。",
      "design": "component_board"
    },
    {
      "id": "L08",
      "category": "局部状态",
      "name": "已购牌在候选区",
      "trigger": "新牌替换棋盘不同字牌，旧实体回到同一手牌槽",
      "visible_copy": [
        "已购 · 免费",
        "{letter}"
      ],
      "source_refs": [
        "inventory.js:74-81",
        "app.js:51-52",
        "style.css:139-141"
      ],
      "behavior": "绿色存放态；再次摆放免费，成功放到空位后手牌槽为空。没有独立背包页。",
      "design": "component_board"
    },
    {
      "id": "L09",
      "category": "局部状态",
      "name": "候选空槽",
      "trigger": "已购实体放回棋盘后，没有新候选补入",
      "visible_copy": [
        "＋",
        "换批补牌"
      ],
      "source_refs": [
        "inventory.js:78",
        "app.js:49",
        "style.css:142-143"
      ],
      "design": "component_board"
    },
    {
      "id": "L10",
      "category": "局部状态",
      "name": "建造点奖励卡",
      "trigger": "抽到reward卡",
      "visible_copy": [
        "金",
        "+30"
      ],
      "source_refs": [
        "cards.js:4",
        "app.js:28",
        "app.js:50-52",
        "app.js:99"
      ],
      "behavior": "点击直接领取并补新牌，无摆放/弹窗。",
      "design": "component_board"
    },
    {
      "id": "L11",
      "category": "局部状态",
      "name": "新分裂牌需观看",
      "trigger": "本局成功买过前两张三口新牌后，再抽到未解锁三口字牌",
      "visible_copy": [
        "▶",
        "{cost}"
      ],
      "source_refs": [
        "inventory.js:12-16",
        "inventory.js:79-91",
        "app.js:50-52",
        "app.js:97",
        "style.css:164-169"
      ],
      "behavior": "金色卡态+右上播放角标；直接点击即模拟观看解锁，不弹ad-dialog、不暂停；仍支付报价；不占补给广告次数。",
      "design": "component_board"
    },
    {
      "id": "L12",
      "category": "局部状态",
      "name": "分裂牌已观看待购买",
      "trigger": "点击需观看候选卡",
      "visible_copy": [
        "✓",
        "{cost}"
      ],
      "source_refs": [
        "app.js:52",
        "app.js:97",
        "inventory.js:83-91",
        "style.css:167-168"
      ],
      "behavior": "绿色勾角标；刷新该候选会丢失观看标记，成功购买后消失。",
      "design": "component_board"
    },
    {
      "id": "L13",
      "category": "局部状态",
      "name": "普通换批 / 广告换批 / 禁用",
      "trigger": "资源足够 / 不够且奖励可用 / 未开始或结算或资源不足且奖励不可用",
      "visible_copy": [
        "换一批",
        "{10,12,…,30}",
        "▶"
      ],
      "source_refs": [
        "app.js:55-61",
        "app.js:195-205",
        "economy.js:1-19",
        "style.css:144-145"
      ],
      "design": "component_board"
    },
    {
      "id": "L14",
      "category": "局部状态",
      "name": "补给入口可用/隐藏",
      "trigger": "已开始、未结束、低于最便宜未购字牌，且补给奖励可用",
      "visible_copy": [
        "▶",
        "+60"
      ],
      "source_refs": [
        "app.js:62-63",
        "economy.js:39-60",
        "style.css:133-138"
      ],
      "behavior": "冷却40战斗秒或3次用尽时隐藏，当前不显示灰置冷却按钮或独立耗尽弹窗。",
      "design": "component_board"
    },
    {
      "id": "L15",
      "category": "局部状态",
      "name": "自然收入计时",
      "trigger": "战斗进行时每6秒+5；暂停冻结",
      "visible_copy": [
        "建造点",
        "{floor(resources)}",
        "+5 / {1…6}s"
      ],
      "source_refs": [
        "app.js:55-58",
        "app.js:145",
        "economy.js:1"
      ],
      "design": "component_board"
    },
    {
      "id": "L16",
      "category": "局部状态",
      "name": "固定营地、障碍、出兵口",
      "trigger": "各关地图数据",
      "visible_copy": [
        "营",
        "↑",
        "→",
        "↓",
        "←",
        "石",
        "出"
      ],
      "source_refs": [
        "app.js:22-27",
        "app.js:83-84",
        "style.css:172-175"
      ],
      "behavior": "营地方向随关卡变化；地图固定格不可移动，外环不可放牌；出兵口触发发光。",
      "design": "component_board"
    },
    {
      "id": "L17",
      "category": "局部状态",
      "name": "棋盘牌选中",
      "trigger": "点击非固定棋盘字牌",
      "visible_copy": [
        "{letter}",
        "{level}阶"
      ],
      "source_refs": [
        "app.js:44",
        "app.js:105",
        "app.js:114",
        "app.js:188",
        "style.css:1"
      ],
      "behavior": "卡片描边；再点格可移动或合并/交换；无旋转按钮。",
      "design": "interaction_board"
    },
    {
      "id": "L18",
      "category": "局部状态",
      "name": "拖拽浮牌",
      "trigger": "指针移动距离超过6px",
      "visible_copy": [
        "{dragged.letter}"
      ],
      "source_refs": [
        "app.js:110-111",
        "index.html:23",
        "style.css:1"
      ],
      "behavior": "浮牌随指针、略旋转与阴影；失焦/指针取消复位。",
      "design": "interaction_board"
    },
    {
      "id": "L19",
      "category": "局部状态",
      "name": "有效/无效落点",
      "trigger": "拖动悬停棋盘格",
      "visible_copy": [],
      "source_refs": [
        "app.js:89",
        "app.js:111",
        "inventory.js:47-52",
        "style.css:1"
      ],
      "behavior": "绿色/红色落点底色与描边；第五阶同脸不再接受合并，固定格或外环不能放。",
      "design": "interaction_board"
    },
    {
      "id": "L20",
      "category": "局部状态",
      "name": "候选区临时丢弃态",
      "trigger": "仅将棋盘字牌拖入整个三候选牌区域",
      "visible_copy": [
        "可丢弃"
      ],
      "source_refs": [
        "app.js:109-119",
        "style.css:158-161",
        "inventory.js:121-127"
      ],
      "behavior": "区域红色虚线覆盖、浮牌降低不透明度；松手删除，不退款、不改候选；移出再松手取消。无确认弹窗。",
      "design": "interaction_board"
    },
    {
      "id": "L21",
      "category": "局部状态",
      "name": "移动/交换/合并成功",
      "trigger": "有效操作",
      "visible_copy": [
        "{level}阶"
      ],
      "source_refs": [
        "inventory.js:57-105",
        "app.js:90-94",
        "rules.js:279-289"
      ],
      "behavior": "目标格短暂pulse400ms+棋盘toast；同字同开口接收方未满5阶则升1阶，来牌不必同阶。",
      "design": "interaction_board"
    },
    {
      "id": "L22",
      "category": "局部状态",
      "name": "棋盘路径与错误标记",
      "trigger": "每次改路刷新trace",
      "visible_copy": [
        "×"
      ],
      "source_refs": [
        "app.js:42-45",
        "app.js:166-169",
        "style.css:1"
      ],
      "behavior": "路线虚线箭头常显；错误圆标与坏字格×。没有当前可点击的预览开关。",
      "design": "feedback_board"
    },
    {
      "id": "L23",
      "category": "局部状态",
      "name": "入口出阵反馈",
      "trigger": "单位到左上出兵口",
      "visible_copy": [
        "{main} 入阵 ↑"
      ],
      "source_refs": [
        "app.js:142",
        "style.css:19-22",
        "style.css:126-128"
      ],
      "behavior": "出口闪光、扩散圈，战场左下提示900ms；对象含兵/刀盾/骑射/赵云。",
      "design": "feedback_board"
    },
    {
      "id": "L24",
      "category": "局部状态",
      "name": "波次/增援",
      "trigger": "本关配置显式wave时",
      "visible_copy": [
        "守军 {waveCount} 波",
        "{waveIndex}/{waveCount} 波 · {waveLabel}",
        " · {seconds}秒后增援"
      ],
      "source_refs": [
        "app.js:147",
        "combat.js:467-474",
        "style.css:37-39"
      ],
      "behavior": "有未来波次才拼接倒计时，无wave配置隐藏。",
      "design": "feedback_board"
    },
    {
      "id": "L25",
      "category": "局部状态",
      "name": "单位：主字/附字/层数/聚合人数/血条",
      "trigger": "行军和战场持续渲染",
      "visible_copy": [
        "兵",
        "刀盾",
        "骑射",
        "赵云",
        "刀×{N}",
        "盾×{N}",
        "弓×{N}",
        "骑×{N}",
        "赵×{N}",
        "云×{N}",
        "{N}名"
      ],
      "source_refs": [
        "unitVisual.js:3-8",
        "unitVisual.js:28-43",
        "unitVisual.js:98-125",
        "rules.js:210-228",
        "combat.js:514-558",
        "combat.js:742-759"
      ],
      "behavior": "主字22px、附字11px；友军#28796C、敌军#B84C35、赵云主字#A87826；主字已表达的组成层隐藏；聚合小队前排有完整标注，后排不逐个画条。",
      "design": "feedback_board"
    },
    {
      "id": "L26",
      "category": "局部状态",
      "name": "命中、免疫、死亡、攻城",
      "trigger": "单位/城被击中，或单位死亡",
      "visible_copy": [
        "−{N}",
        "−{0.x}",
        "免疫"
      ],
      "source_refs": [
        "combat.js:11-12",
        "combat.js:272-332",
        "combat.js:634-661"
      ],
      "behavior": "字下接地影；受击亮底光不改阵营色；跳字贴目标上方0.65秒，同目标120ms内合并；死亡字短暂飘淡。",
      "design": "feedback_board"
    },
    {
      "id": "L27",
      "category": "局部状态",
      "name": "即时胜利/失败演出",
      "trigger": "城池HP降至0，结算弹窗前",
      "visible_copy": [
        "城破",
        "0",
        "破城！",
        "防线失守",
        "胜利",
        "败北"
      ],
      "source_refs": [
        "combat.js:307-308",
        "combat.js:663-716",
        "app.js:149-153",
        "style.css:153-155"
      ],
      "behavior": "胜：敌城碎裂/粒子、画面震动2.3秒后结算；败0.9秒后结算。",
      "design": "feedback_board"
    },
    {
      "id": "L28",
      "category": "局部状态",
      "name": "桌面产出预览有/无产出",
      "trigger": "刷新路线",
      "visible_copy": [
        "暂无单位能出阵。\n检查开口与行进方向。",
        "每批 {count} 名 · 行军约 {seconds}秒",
        "近战 {damage}",
        " · 远程 {damage} / 射程 {range}",
        "生命 {hp} · 防御 {defense}（减伤 {percent}%）",
        "每秒 {speed} 次攻击",
        "刀盾 · {percent}% 免疫",
        "刀盾传承 · {percent}% 免疫",
        "武将变身 · 伤害系数 1.8 / 攻速 ×2",
        "骑射传承 · 保留 320 射程"
      ],
      "source_refs": [
        "index.html:16",
        "app.js:68-70",
        "style.css:177-179"
      ],
      "behavior": "仅桌面侧栏；不是移动端弹窗。",
      "design": "responsive_component_board"
    },
    {
      "id": "L29",
      "category": "局部状态",
      "name": "桌面选中说明",
      "trigger": "选候选字牌、棋盘牌、营/障碍；或清空选择",
      "visible_copy": [
        "固定障碍",
        "不能放牌，也不能通行。让路线绕开这个格子。",
        "营地 · 向{方向}出发",
        "每9秒出一批兵，营地位置固定。空格直走，利用字格改变方向。",
        "选择一张文字卡",
        "拖动或点选字牌，再点格子。异字可交换；把棋盘字牌拖到下方三张牌区域，松手丢弃。",
        "点击「开始」后布阵，战斗同时进行。",
        "「{letter}」{level}阶",
        "{openNames}开口。兵必须从开放边进入，之后排除来路。首次经过会尝试分成两路。",
        "{openNames}开口。兵必须从开放边进入，之后排除来路。另一开口就是本次出口。"
      ],
      "source_refs": [
        "app.js:74-78"
      ],
      "ability_copy": {
        "刀": "第一层近战 +8，之后每层近战 +6；每层另加2远攻。有弓才开启远攻。",
        "盾": "每层防御 +25；防御会减免每次伤害。刀盾另外有30%概率免疫本次伤害。",
        "弓": "开启远程攻击，每层远攻 +6；与骑先凑齐可成为骑射。",
        "骑": "每层战场移速 +18%、攻速 +12%。",
        "赵": "每层全部攻击 +5%；同一名兵再经过云字就变身赵云。新名字牌两口40、三口60起，以牌面报价为准。",
        "云": "每层全部攻击 +5%；同一名兵再经过赵字就变身赵云。新名字牌两口40、三口60起，以牌面报价为准。"
      },
      "design": "responsive_component_board"
    },
    {
      "id": "T01",
      "category": "提示文案",
      "name": "摆放失败：分裂播放未解锁",
      "trigger": "未解锁分裂卡购买失败",
      "visible_copy": [
        "先点右上角播放图标，再按牌面价格摆放。"
      ],
      "source_refs": [
        "app.js:91"
      ],
      "channel": "global_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T02",
      "category": "提示文案",
      "name": "摆放失败：资源不足",
      "trigger": "资源类receipt失败",
      "visible_copy": [
        "建造点不足，等补给后再换入，或调整已有路线。"
      ],
      "source_refs": [
        "app.js:91"
      ],
      "channel": "global_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T03",
      "category": "提示文案",
      "name": "摆放失败：无效目标",
      "trigger": "其余失败，如固定格、满阶同脸",
      "visible_copy": [
        "这里不能放置，字牌仍留在原处。"
      ],
      "source_refs": [
        "app.js:91"
      ],
      "channel": "global_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T04",
      "category": "提示文案",
      "name": "手牌满的保留文案",
      "trigger": "receipt含full/slot",
      "visible_copy": [
        "手牌里都是已购字牌，请先放回或换一批。"
      ],
      "source_refs": [
        "app.js:91",
        "inventory.js:107-119"
      ],
      "channel": "global_toast",
      "design": "copy_catalog",
      "reachability": "当前正常UI无withdraw入口；保留分支，勿据此新增背包容量弹窗。"
    },
    {
      "id": "T05",
      "category": "提示文案",
      "name": "合并成功",
      "trigger": "merge receipt",
      "visible_copy": [
        "同字同向，升了一阶。"
      ],
      "source_refs": [
        "app.js:93-94",
        "inventory.js:80",
        "inventory.js:97-104"
      ],
      "channel": "board_toast_and_desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T06",
      "category": "提示文案",
      "name": "交换成功",
      "trigger": "swap receipt",
      "visible_copy": [
        "交换完成，换下的字牌可免费再放。"
      ],
      "source_refs": [
        "app.js:93-94",
        "inventory.js:80",
        "inventory.js:97-104"
      ],
      "channel": "board_toast_and_desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T07",
      "category": "提示文案",
      "name": "丢弃成功",
      "trigger": "discard receipt",
      "visible_copy": [
        "字牌已丢弃。"
      ],
      "source_refs": [
        "app.js:93-94",
        "inventory.js:80",
        "inventory.js:97-104"
      ],
      "channel": "board_toast_and_desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T08",
      "category": "提示文案",
      "name": "移牌成功",
      "trigger": "move receipt",
      "visible_copy": [
        "位置已调整。"
      ],
      "source_refs": [
        "app.js:93-94",
        "inventory.js:80",
        "inventory.js:97-104"
      ],
      "channel": "board_toast_and_desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T09",
      "category": "提示文案",
      "name": "已购牌放回成功",
      "trigger": "place receipt",
      "visible_copy": [
        "摆放成功。"
      ],
      "source_refs": [
        "app.js:93-94",
        "inventory.js:80",
        "inventory.js:97-104"
      ],
      "channel": "board_toast_and_desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T10",
      "category": "提示文案",
      "name": "购买或未移动通用成功",
      "trigger": "purchase/noop等无特定文案的成功receipt",
      "visible_copy": [
        "布阵已调整。"
      ],
      "source_refs": [
        "app.js:93-94",
        "inventory.js:80",
        "inventory.js:97-104"
      ],
      "channel": "board_toast_and_desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T11",
      "category": "提示文案",
      "name": "固定格提醒",
      "trigger": "点击营/固定地图格",
      "visible_copy": [
        "营地与地图格位置固定。"
      ],
      "source_refs": [
        "app.js:105"
      ],
      "channel": "board_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T12",
      "category": "提示文案",
      "name": "资源卡领取",
      "trigger": "点击金卡",
      "visible_copy": [
        "获得{reward}建造点"
      ],
      "source_refs": [
        "app.js:99"
      ],
      "channel": "global_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T13",
      "category": "提示文案",
      "name": "补给广告领取",
      "trigger": "领取补充建造点奖励",
      "visible_copy": [
        "获得 {reward} 建造点"
      ],
      "source_refs": [
        "app.js:202"
      ],
      "channel": "global_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T14",
      "category": "提示文案",
      "name": "本关重开",
      "trigger": "暂停菜单重新开始本关",
      "visible_copy": [
        "本关已重置，点击画面中央开始。"
      ],
      "source_refs": [
        "app.js:194"
      ],
      "channel": "global_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T15",
      "category": "提示文案",
      "name": "开始时路线受阻",
      "trigger": "点击开始且无产出",
      "visible_copy": [
        "出阵路线被阻挡，可以边出兵边调整。"
      ],
      "source_refs": [
        "app.js:134"
      ],
      "channel": "board_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T16",
      "category": "提示文案",
      "name": "开始旁白",
      "trigger": "首次点击开始",
      "visible_copy": [
        "已开始：拖入文字格，规划路线，让正在行进的兵获得能力。"
      ],
      "source_refs": [
        "app.js:134"
      ],
      "channel": "desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T17",
      "category": "提示文案",
      "name": "存档失败",
      "trigger": "胜利保存localStorage失败，本会话仅一次",
      "visible_copy": [
        "浏览器未允许保存进度，当前试玩不受影响。"
      ],
      "source_refs": [
        "app.js:150"
      ],
      "channel": "global_toast",
      "design": "copy_catalog"
    },
    {
      "id": "T18",
      "category": "提示文案",
      "name": "行军增益浮字",
      "trigger": "首次获得/重复获得某字、完成组合、首次分路",
      "visible_copy": [
        "+{letter}",
        "{letter}×{N}",
        "{main}!",
        "分流 ×2"
      ],
      "source_refs": [
        "app.js:140",
        "app.js:175"
      ],
      "channel": "board_float",
      "design": "copy_catalog"
    },
    {
      "id": "T19",
      "category": "提示文案",
      "name": "组合旁白",
      "trigger": "主字发生变身",
      "visible_copy": [
        "刀盾成型：伤害系数1.5，每次受击有30%概率免疫。",
        "骑射成型。远距离停步，继续积累火力。",
        "赵云变身：金色主字，伤害系数1.8、攻速翻倍；原基础组合的专属能力保留。"
      ],
      "source_refs": [
        "app.js:140"
      ],
      "channel": "desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T20",
      "category": "提示文案",
      "name": "行军死亡/阻断标记",
      "trigger": "stepRoute dead/blocked",
      "visible_copy": [
        "×",
        "止"
      ],
      "source_refs": [
        "app.js:143"
      ],
      "channel": "board_float",
      "design": "copy_catalog"
    },
    {
      "id": "T21",
      "category": "提示文案",
      "name": "行军死亡/阻断原因",
      "trigger": "首次损失或每第8次损失",
      "visible_copy": [
        "单位方向无效",
        "单位超出外围通道，停止前进",
        "绕回营地，单位死亡",
        "撞到障碍，单位死亡",
        "从{上/右/下/左}侧撞入封闭边，单位死亡",
        "前进方向的{上/右/下/左}侧封闭，单位死亡",
        "路线超出外围通道，单位停止前进",
        "路线中断"
      ],
      "source_refs": [
        "rules.js:103-127",
        "rules.js:173-178",
        "app.js:143"
      ],
      "channel": "board_toast_and_desktop_live_feedback",
      "design": "copy_catalog"
    },
    {
      "id": "T22",
      "category": "提示文案",
      "name": "提示持续时长",
      "trigger": "每次同类消息覆盖前条",
      "visible_copy": [],
      "source_refs": [
        "app.js:182-184"
      ],
      "channel": "presentation_rule",
      "design": "copy_catalog",
      "behavior": "全局toast 2300ms；棋盘toast 2500ms；均无用户关闭按钮。"
    },
    {
      "id": "T23",
      "category": "提示文案",
      "name": "鼠标悬停与无障碍文案",
      "trigger": "hover/读屏",
      "visible_copy": [
        "正常速度",
        "2倍加速中",
        "切换速度",
        "音效开关",
        "打开音效",
        "关闭音效",
        "游戏菜单",
        "暂停游戏",
        "沿外环走到这里，进入上方战场",
        "换批会弃掉手牌中已购的字牌",
        "播放奖励：免费换一批",
        "换一批需要{cost}建造点",
        "播放奖励：补充建造点",
        "战斗进行时每6秒补充5建造点",
        "开始后可操作",
        "拖动摆牌；棋盘字牌拖到下方三张牌区域可丢弃"
      ],
      "source_refs": [
        "index.html:9-14",
        "app.js:58-63",
        "app.js:71",
        "app.js:122-132",
        "app.js:206"
      ],
      "channel": "tooltip_or_screenreader",
      "design": "copy_catalog",
      "behavior": "hand-instruction是sr-only，不应画成常驻下方提示条。"
    }
  ],
  "level_copy_catalog": [
    {
      "id": 1,
      "name": "一字成兵",
      "kicker": "第一关 · 转向",
      "description": "点击开始后摆上「刀」，兵进入外圈后沿较短路线走到左上出兵口。",
      "lesson": "左上开口从左进、向上走。四边均可入环，沿最短方向到左上出兵口参战。",
      "goal": "试着给兵带上刀，再观察攻营速度。",
      "resources": 125,
      "unlocked": [
        "刀"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:7",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 2,
      "name": "刀盾合一",
      "kicker": "第二关 · 组合",
      "description": "让同一名兵依次路过「刀」和「盾」。",
      "lesson": "两字齐全，就进化为「刀盾」。先转向上，再转向右。",
      "goal": "试着造出刀盾兵，比较更强的军队。",
      "resources": 150,
      "unlocked": [
        "刀",
        "盾"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:117",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 3,
      "name": "一兵分两路",
      "kicker": "第三关 · 分流",
      "description": "用三口「盾」分出两队，再给右路配上「弓」。",
      "lesson": "三口格排除来路，两条出路各产生一名兵；后续经过的字各自生效。",
      "goal": "让一次出兵分成两队，再给其中一路加上弓。",
      "resources": 195,
      "unlocked": [
        "刀",
        "盾",
        "弓"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:257",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 4,
      "name": "骑射先成",
      "kicker": "第四关 · 骑射",
      "description": "先让兵路过「弓」和「骑」，再加上「刀」「盾」。",
      "lesson": "先凑齐弓骑，就成为骑射。后来再得刀盾，主字也不会改变。",
      "goal": "试着造出骑射，再给它加刀盾，观察主字保持不变。",
      "resources": 250,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:442",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 5,
      "name": "百炼成锋",
      "kicker": "第5关 · 同字叠层",
      "description": "叠加刀与盾，带着更强的单兵突破近战防线。",
      "lesson": "同字经过不同格可以叠加；也可以搭配其他文字，比较你的军队变化。",
      "goal": "叠加刀与盾，带着更强的单兵突破近战防线。",
      "resources": 100,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:697",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 6,
      "name": "刀盾护骑射",
      "kicker": "第6关 · 双路配合",
      "description": "尝试用不同兵种配合，压过有弓手掩护的守军。",
      "lesson": "分流后的部队各自成长，试试不同字组合和出阵位置。",
      "goal": "尝试用不同兵种配合，压过有弓手掩护的守军。",
      "resources": 105,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:948",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 7,
      "name": "三路齐发",
      "kicker": "第7关 · 连续分流",
      "description": "增加有效出兵支路，用持续兵力顶住敌人的成阵反扑。",
      "lesson": "三口格能增加出兵支路；兼顾有效出口、单兵强度和补兵速度。",
      "goal": "增加有效出兵支路，用持续兵力顶住敌人的成阵反扑。",
      "resources": 110,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:1238",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 8,
      "name": "以骑制弓",
      "kicker": "第8关 · 远程对抗",
      "description": "在远程对射中补足生存与火力，突破城前弓阵。",
      "lesson": "远程单位会在射程内停下，补盾或叠弓都可能帮你稳住阵地。",
      "goal": "在远程对射中补足生存与火力，突破城前弓阵。",
      "resources": 115,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:1540",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 9,
      "name": "同字异阵",
      "kicker": "第9关 · 组合先后",
      "description": "相同的四个字，先成刀盾或先成骑射，会打出不同效果。",
      "lesson": "先完成的组合决定主字；相同文字换个经过顺序，也能形成不同兵种。",
      "goal": "比较成型顺序，搭配两路军队突破长弓防线。",
      "resources": 120,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:1862",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 10,
      "name": "四路破城",
      "kicker": "第10关 · 综合城战",
      "description": "把分路增兵与叠字结合，顶住刀盾和弓阵后夺城。",
      "lesson": "分流、叠字和兵种各有收益，按到手的开口调整你的军队。",
      "goal": "自由规划多路军队，用产量、叠字与兵种配合突破防线。",
      "resources": 125,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:2247",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 11,
      "name": "绕石接阵",
      "kicker": "第11关 · 单障碍绕行",
      "description": "从营地自行规划路线，绕开石块，让同一名兵连续获得文字加成。",
      "lesson": "从营地自行规划路线，绕开石块，让同一名兵连续获得文字加成。",
      "goal": "从营地自行规划路线，绕开石块，让同一名兵连续获得文字加成。",
      "resources": 125,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:2688",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 12,
      "name": "双石成阵",
      "kicker": "第12关 · 双石绕行",
      "description": "两块石头挡住直线；从空盘接通产线，在叠字、分流和行军距离之间选择。",
      "lesson": "两块石头挡住直线；从空盘接通产线，在叠字、分流和行军距离之间选择。",
      "goal": "两块石头挡住直线；从空盘接通产线，在叠字、分流和行军距离之间选择。",
      "resources": 125,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:2928",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 13,
      "name": "精兵与分兵",
      "kicker": "第13关 · 质量数量取舍",
      "description": "从空盘安排叠字与分流；每条支路都要接通，并获得足够战力。",
      "lesson": "从空盘安排叠字与分流；每条支路都要接通，并获得足够战力。",
      "goal": "从空盘安排叠字与分流；每条支路都要接通，并获得足够战力。",
      "resources": 125,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:3175",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 14,
      "name": "远营先至",
      "kicker": "第14关 · 到场时机",
      "description": "营地从右向左出兵；自行规划转向，在路线长度与文字加成之间选择。",
      "lesson": "营地从右向左出兵；自行规划转向，在路线长度与文字加成之间选择。",
      "goal": "营地从右向左出兵；自行规划转向，在路线长度与文字加成之间选择。",
      "resources": 125,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:3422",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 15,
      "name": "三石破围",
      "kicker": "第15关 · 变向综合阵",
      "description": "营地从下向上出兵，三块石头阻挡前进；自行选择转向、叠字与分流。",
      "lesson": "营地从下向上出兵，三块石头阻挡前进；自行选择转向、叠字与分流。",
      "goal": "营地从下向上出兵，三块石头阻挡前进；自行选择转向、叠字与分流。",
      "resources": 125,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑"
      ],
      "heroIntro": null,
      "source_ref": "levels.js:3669",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    },
    {
      "id": 16,
      "name": "赵云初阵",
      "kicker": "第16关 · 英雄试玩",
      "description": "从空盘接通路线，同一名兵经过赵、云才成为赵云；弓盾等能力也由自己摆牌获得。",
      "lesson": "从空盘接通路线，同一名兵经过赵、云才成为赵云；弓盾等能力也由自己摆牌获得。",
      "goal": "从空盘接通路线，同一名兵经过赵、云才成为赵云；弓盾等能力也由自己摆牌获得。",
      "resources": 125,
      "unlocked": [
        "刀",
        "盾",
        "弓",
        "骑",
        "赵",
        "云"
      ],
      "heroIntro": true,
      "source_ref": "levels.js:3923",
      "rendered_fields": {
        "name": "game heading / level list / win result",
        "kicker": "level picker / level list subtitle",
        "goal": "ready overlay / desktop selection",
        "lesson": "desktop feedback / win result"
      },
      "description_visibility": "level config only; not directly rendered by current app",
      "selection": "all levels selectable; completed state is checkmark only"
    }
  ],
  "static_regions": [
    {
      "selector": "brand",
      "text": "兵一字成兵十六关试炼玩法说明 ?",
      "source_ref": "index.html:5",
      "note": "初始HTML原文；运行时变量以状态条目覆盖为准"
    },
    {
      "selector": "chapter-panel",
      "text": "从一字到一支军队字成兵，\n路成阵。让每一名兵走过你铺设的文字，\n把一条路线变成一支军队。玩法要诀字格缺口通行，黑环自动抄近路。\n左上出兵，先成的做主字。可玩原型 · 赵云变身",
      "source_ref": "index.html:7",
      "note": "初始HTML原文；运行时变量以状态条目覆盖为准"
    },
    {
      "selector": "inspector",
      "text": "这一条路会造出什么行军预览选择一张文字卡可以拖动，也可以点选后再点格子。摆好的文字还可以移动。字的力量刀近战攻击盾防御与减伤弓远程射箭骑移动与攻速刀 + 盾 = 刀盾\n弓 + 骑 = 骑射经过不同的同字格，能力叠加。\n刀×2 = 刀的总层数为 2。\n成型后也保留层数；主字不额外计层。先规划路线，再观察前线。",
      "source_ref": "index.html:16",
      "note": "初始HTML原文；运行时变量以状态条目覆盖为准"
    }
  ],
  "help_paragraphs": [
    {
      "text": "点击关名上方可切换十六关。前四关有推荐卡牌和落点，帮助学习规则。第五关起卡牌随机出现，自主布阵。11–16关从只有少量固定石头的空盘开始，营地位置和朝向会变化，需要自行购牌规划路线；第16关提供弓、赵、云试玩开手，购入后继续补牌，短队列结束后回到随机供牌；手牌不合适时可以改路或换一批。路线始终预览当前摆法。挑战关迎战分批守军，敌方增援会显示倒计时。每关点击画面中央「开始本关」，战斗启动后才能拖卡、移格或换牌。每关和重试默认1倍速，右上角可切到2倍速。右上角「Ⅱ」暂停战斗，菜单内可以继续、重开或查看说明；收起菜单后可在暂停中调整路线。所有关卡共用每9秒一批的基础出兵速度，不随关卡改变。可以先接好一段路线，观察交战，再等收入调整。兵从「营」持续出发，空格直走，经过字格获得能力。进入四周黑色输送环后，会自动选择较近的方向，沿环走到左上角「出」口，才进入上方战场。空格会直走；前方没有障碍时，普通兵也可沿环出兵。11–16关初始直线路径被石头阻挡，必须先摆字格改路。",
      "source_ref": "index.html:21"
    },
    {
      "text": "字格的黑边封闭，缺口可以进出。进入一个开口后，排除来路，剩余开口决定接下来怎么走。三口格首次经过会分成两路，接错的支路仍会损失单位。每场前两张新分裂牌按建造点价格购入；第三张起新分裂牌右上角显示圆形播放图标，点击模拟观看后仍按牌面建造点价格购买。观看只解除额外条件，不赠送免费牌；未购买就换批，观看记录随该候选一起清除。未使用就刷新掉的牌不计次；移动或交换已有牌不重复计次，重新开始本关后重置。分裂牌观看不占补给奖励的次数。",
      "source_ref": "index.html:21"
    },
    {
      "text": "刀 + 盾成为刀盾，弓 + 骑成为骑射。先凑齐的组合做主字，后来获得的字保留为附加能力。刀盾拿到弓仍会射箭。刀盾伤害系数1.5，并有30%概率免疫单次伤害；触发时在受击处显示「免疫」。每次命中独立判定，重复盾不提高免疫概率。",
      "source_ref": "index.html:21"
    },
    {
      "text": "第16关：赵 + 云 = 赵云。两个字必须由同一名兵经过，分开的两名兵不会合将。每层赵或云各加5%攻击；凑齐后主字升级为赵云，伤害系数1.8、攻速翻倍。武将的被动技能就是变身：主字变金色，伤害系数1.8替换刀盾的1.5，攻速只翻倍一次，不叠成4倍。刀、盾、弓、骑的逐层加成仍保留。先成刀盾再升赵云，保留30%免疫；先成骑射再升赵云，保留320超远射程。有弓的其他赵云射程为220。先直接成赵云、再补齐基础字，只得到单字属性，不补领基础组合能力。路线持续产出赵云，不设唯一武将名额。",
      "source_ref": "index.html:21"
    },
    {
      "text": "同字可以叠加，层数写作「刀×2」。基础攻击为8；第一层刀增加100%基础攻击（+8），之后每层增加75%基础攻击（+6），所以单刀近战16、双刀22、三刀28；刀盾的1.5系数下分别为24、33、42。这里是固定增加基础值，不是每层将当前伤害翻倍。每层弓增加75%基础攻击到远攻，刀另增加25%基础攻击到远攻。有弓才开启远攻。附字显示「刀×2」。×N 表示累计层数，不代表最终伤害乘 N；战场上的「3名」则表示聚在一起的兵数。",
      "source_ref": "index.html:21"
    },
    {
      "text": "盾提供防御，骑提供速度。基础生命42；无盾时防御0，每层盾增加25防御。减伤率=防御÷（100+防御），最高85%；一盾减伤20%，两盾约33.3%。未免疫的伤害至少为0.1，低于1的伤害显示小数。每层骑增加18%战场移速和12%攻速，骑射或赵云再将攻速翻倍。重复层数相加，不逐层相乘。金币升级尚未开放，本版使用统一基础属性。",
      "source_ref": "index.html:21"
    },
    {
      "text": "外围可双向行走，单位自动选择到左上出兵口的最短环路。左侧直接向上，右侧向上后沿顶边向左，底边向左后沿左边向上；右下角两路等长时固定向上。实际路程越短，参战越快。营地和环上的出兵口固定，外环不能放卡。边缘文字格仍会先执行转向与加成，再进入外圈。相同文字、相同开口的格子可以合并升级。不同字牌拖到已占用的格子会交换：新牌支付一次报价，旧牌回到手牌并标记「已购」，以后免费放回。棋盘字牌之间也能交换。要丢掉棋盘上的字牌，直接拖到下方三张候选牌的整个区域：出现「可丢弃」后松手，字牌立即删除，不退款、不替换候选牌。拖出该区域再松手则取消丢弃。换下回到手牌的已购字牌仍可免费放回；「换一批」会弃掉手牌中的已购字牌。绕回同一个字格不会重复获得，绕回同一分岔也不会继续分兵。",
      "source_ref": "index.html:21"
    },
    {
      "text": "普通字两口25、三口45起；赵、云名字牌两口40、三口60起。后续新牌随同字、同开口购买次数涨价，手中报价保持不变，以牌面为准。第16关开手为弓25、赵40、云40，合计105点；随后补出的盾为25点，弓、赵、云、盾四字路线共130点。初始125点，等待一轮自然回复即可补齐，无需广告。建造点每6秒回复5点。全部16关换批费用统一为10、12、14、16…30，之后保持30；每关重新从10开始。缺资源时可点击圆形播放图标体验奖励：补60建造点或免费换一批，每关合计最多3次，两次间隔40秒战斗时间。无需领取也可以正常挑战。",
      "source_ref": "index.html:21"
    }
  ],
  "static_buttons": [
    {
      "id": "help-open",
      "text": "玩法说明 ?",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:5",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "level-kicker",
      "text": "第一关 · 转向 ▾",
      "title": null,
      "aria_label": "选择关卡，当前第1关，共16关",
      "source_ref": "index.html:9",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "speed",
      "text": "1×",
      "title": "切换速度",
      "aria_label": "当前1倍速，切换为2倍速",
      "source_ref": "index.html:9",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "sound",
      "text": "♪",
      "title": "音效开关",
      "aria_label": "打开音效",
      "source_ref": "index.html:9",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "pause-toggle",
      "text": "☰",
      "title": "游戏菜单",
      "aria_label": "游戏菜单",
      "source_ref": "index.html:9",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "ad-resources",
      "text": "+60",
      "title": null,
      "aria_label": "播放奖励：补充60建造点",
      "source_ref": "index.html:12",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "reroll",
      "text": "换一批10",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:13",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "play",
      "text": "开始本关 ▶",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:14",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "ad-close",
      "text": "×",
      "title": null,
      "aria_label": "取消奖励",
      "source_ref": "index.html:18",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "ad-claim",
      "text": "领取奖励",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:18",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "pause-close",
      "text": "×",
      "title": null,
      "aria_label": "收起菜单",
      "source_ref": "index.html:19",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "pause-resume",
      "text": "继续战斗",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:19",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "restart",
      "text": "重新开始本关",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:19",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "pause-help",
      "text": "玩法说明",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:19",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "level-close",
      "text": "×",
      "title": null,
      "aria_label": "关闭选关",
      "source_ref": "index.html:20",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "help-close",
      "text": "×",
      "title": null,
      "aria_label": "关闭玩法说明",
      "source_ref": "index.html:21",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "help-play",
      "text": "知道了",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:21",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "next",
      "text": "下一关",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:22",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    },
    {
      "id": "result-retry",
      "text": "再试一种路线",
      "title": null,
      "aria_label": null,
      "source_ref": "index.html:22",
      "note": "初始HTML文案；以对应状态条目的运行时覆盖为准"
    }
  ],
  "design_recommendations": [
    {
      "id": "D01",
      "type": "独立图",
      "name": "主战斗标准页",
      "covers": [
        "F02",
        "L01",
        "L02",
        "L15",
        "L16",
        "L22",
        "L24",
        "L25"
      ]
    },
    {
      "id": "D02",
      "type": "独立图",
      "name": "准备开始页",
      "covers": [
        "F01",
        "L04"
      ]
    },
    {
      "id": "D03",
      "type": "独立图",
      "name": "暂停后仍可布阵页",
      "covers": [
        "F03"
      ]
    },
    {
      "id": "D04",
      "type": "独立图",
      "name": "暂停菜单",
      "covers": [
        "M01",
        "M02"
      ],
      "note": "准备出阵作为同板文案变体"
    },
    {
      "id": "D05",
      "type": "独立图",
      "name": "16关选关",
      "covers": [
        "M03",
        "L03"
      ]
    },
    {
      "id": "D06",
      "type": "独立长图",
      "name": "玩法说明首屏与滚动内容",
      "covers": [
        "M04"
      ],
      "note": "沿现有内容做信息分段；不能把现有长帮助误列为多个程序页面"
    },
    {
      "id": "D07",
      "type": "独立图+变体",
      "name": "奖励弹窗",
      "covers": [
        "M05",
        "M06"
      ],
      "note": "补建造点/免费换批共享一套版式，展示两种文案"
    },
    {
      "id": "D08",
      "type": "独立图+变体",
      "name": "结算",
      "covers": [
        "M07",
        "M08",
        "M09",
        "M10"
      ],
      "note": "胜利/失败至少各完整展示，通关与失败原因作为同板变体"
    },
    {
      "id": "D09",
      "type": "独立图",
      "name": "第16关赵云成型",
      "covers": [
        "F04"
      ]
    },
    {
      "id": "D10",
      "type": "合并设计板",
      "name": "卡牌与资源控件状态",
      "covers": [
        "L05",
        "L06",
        "L07",
        "L08",
        "L09",
        "L10",
        "L11",
        "L12",
        "L13",
        "L14"
      ]
    },
    {
      "id": "D11",
      "type": "合并设计板",
      "name": "拖拽、交换、合并与丢弃",
      "covers": [
        "L17",
        "L18",
        "L19",
        "L20",
        "L21"
      ]
    },
    {
      "id": "D12",
      "type": "合并设计板",
      "name": "行军、战斗、弹字与提示",
      "covers": [
        "L23",
        "L25",
        "L26",
        "L27",
        "T01",
        "T02",
        "T03",
        "T04",
        "T05",
        "T06",
        "T07",
        "T08",
        "T09",
        "T10",
        "T11",
        "T12",
        "T13",
        "T14",
        "T15",
        "T16",
        "T17",
        "T18",
        "T19",
        "T20",
        "T21",
        "T22",
        "T23"
      ]
    },
    {
      "id": "D13",
      "type": "可选桌面适配板",
      "name": "桌面外框及侧栏",
      "covers": [
        "F05",
        "L28",
        "L29"
      ],
      "note": "若本轮只交手游美术，可保留为布局规范，不必单独高保真出图"
    }
  ],
  "important_boundaries": [
    {
      "finding": "当前16关，可直接任意选关；不是十关，也没有关卡解锁锁链。",
      "refs": [
        "app.js:37-39",
        "app.js:192-193"
      ]
    },
    {
      "finding": "没有独立背包页；已购免费牌占用三候选槽。",
      "refs": [
        "app.js:47-52",
        "inventory.js:74-81"
      ]
    },
    {
      "finding": "没有分解卡/返材料页面；只有分裂牌观看与字牌丢弃。withdraw存在但未绑定UI。",
      "refs": [
        "inventory.js:83-129",
        "app.js:97-118"
      ]
    },
    {
      "finding": "没有提示弹窗/提示按钮：只有前四关自动推荐卡+落点。hint-button、mission、preview-toggle、route-summary、mobile-chapters只是旧CSS，当前HTML无对应入口。",
      "refs": [
        "app.js:34-36",
        "app.js:42-52",
        "index.html:1-24",
        "style.css:1-8"
      ]
    },
    {
      "finding": "分裂牌点击播放立即解除购买附加条件，没有打开ad-dialog；补给视频是模拟领取弹窗。",
      "refs": [
        "app.js:97",
        "app.js:114",
        "app.js:197-205"
      ]
    },
    {
      "finding": "奖励耗尽/冷却没有独立弹窗或toast，入口隐藏/换批禁用；内部limit/cooldown/duplicate错误不可当UI文案。",
      "refs": [
        "app.js:55-64",
        "economy.js:39-60"
      ]
    },
    {
      "finding": "自动后台暂停没有新弹窗；显示现有暂停战场继续入口。",
      "refs": [
        "app.js:217",
        "app.js:123-135"
      ]
    },
    {
      "finding": "没有升级商店、永久成长、武将选择、登录、支付、加载页或设置页；音效与倍速为主界面按钮。",
      "refs": [
        "index.html:1-24",
        "app.js:186-221"
      ]
    },
    {
      "finding": "trace预览诊断文字和成功rules事件原文大多不直出UI，仅驱动错误标记；当前可见文案以app浮字/反馈为准。",
      "refs": [
        "rules.js:294-329",
        "app.js:140-143",
        "app.js:166-169"
      ]
    },
    {
      "finding": "当前城池血条在城上方；移动单位条在字下；概念美术此前城脚血条是用户设计要求，不是源码现状。",
      "refs": [
        "combat.js:715-716",
        "unitVisual.js:118-124"
      ]
    },
    {
      "finding": "新购普通卡成功显示“布阵已调整。”，不是“摆放成功。”；后者专指已购牌重放的place receipt。",
      "refs": [
        "inventory.js:80",
        "app.js:93-94"
      ]
    }
  ]
}
