Просмотр исходного кода

feat(v12-P0): 圆角三档 token(8/12/20)+ 按钮三形态 + 原生控件兜底

FmodeCode 5 дней назад
Родитель
Сommit
a43e7b0fd0

+ 2796 - 0
docs/v12-after-p0.json

@@ -0,0 +1,2796 @@
+{
+  "tag": "before",
+  "at": "2026-10-30T06:00:02.545Z",
+  "pages": [
+    {
+      "page": "/",
+      "radii": {
+        "0": 796,
+        "8": 108,
+        "12": 112,
+        "circle": 4
+      },
+      "controls": [
+        {
+          "tag": "button.refresh.kf-btn",
+          "w": 52,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刷新"
+        },
+        {
+          "tag": "select",
+          "w": 69,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "14px",
+          "reasons": [],
+          "text": "未选择\n            "
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        }
+      ],
+      "thickBorders": [
+        {
+          "tag": "span.live",
+          "w": 0,
+          "ow": 3,
+          "o": "0px"
+        }
+      ],
+      "blackText": [],
+      "fontSizes": {
+        "11": 78,
+        "13": 27,
+        "14": 7,
+        "16": 6,
+        "20": 13,
+        "32": 4
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 0,
+          "heights": [
+            900,
+            900
+          ]
+        },
+        {
+          "container": "div.grid2.kf-enter",
+          "top": 148,
+          "n": 2,
+          "spread": 49.2,
+          "heights": [
+            142,
+            93
+          ]
+        },
+        {
+          "container": "div.grid4",
+          "top": 352,
+          "n": 4,
+          "spread": 0,
+          "heights": [
+            77,
+            77,
+            77,
+            77
+          ]
+        },
+        {
+          "container": "div.latest",
+          "top": 444,
+          "n": 3,
+          "spread": 20.8,
+          "heights": [
+            389,
+            368,
+            368
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 620,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        }
+      ],
+      "blanks": [],
+      "clickables": 26,
+      "hoverFail": [
+        {
+          "tag": "a",
+          "text": "工作台Workbench"
+        },
+        {
+          "tag": "a",
+          "text": "机会卡池Opportun"
+        },
+        {
+          "tag": "a",
+          "text": "五阶段产出Stages "
+        },
+        {
+          "tag": "a",
+          "text": "分析报告Reports"
+        },
+        {
+          "tag": "a",
+          "text": "证据台账Ledger"
+        },
+        {
+          "tag": "a",
+          "text": "成员Members\n  "
+        },
+        {
+          "tag": "button.refresh.kf-btn",
+          "text": "刷新"
+        },
+        {
+          "tag": "a.go",
+          "text": "机会卡池 →"
+        },
+        {
+          "tag": "a.go",
+          "text": "选我"
+        },
+        {
+          "tag": "a.go",
+          "text": ""
+        },
+        {
+          "tag": "a.go",
+          "text": "9"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift.tone-ok",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        }
+      ],
+      "scrollH": 900,
+      "lastContentBottom": 0,
+      "filterLayout": null,
+      "wbCols": null,
+      "radiiWhere": {
+        "0": "html",
+        "8": "span.badge",
+        "12": "aside.side.kf-glass.is-panel"
+      }
+    },
+    {
+      "page": "/pool",
+      "radii": {
+        "0": 1628,
+        "8": 372,
+        "12": 116,
+        "circle": 4
+      },
+      "controls": [
+        {
+          "tag": "button.refresh.kf-btn",
+          "w": 52,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刷新"
+        },
+        {
+          "tag": "select",
+          "w": 69,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "14px",
+          "reasons": [],
+          "text": "未选择\n            "
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "候选4"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 73,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "已立项3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 73,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "已否决2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 57,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 58,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "A 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 58,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "B 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 47,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S11"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S21"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S34"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 51,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S42"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S51"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "拌面5"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "汤面2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "杯面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "炒面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "陈静2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "李娜1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刘洋1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "孙悦1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "王芳1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "张伟1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "赵磊1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "周涛1"
+        },
+        {
+          "tag": "button",
+          "w": 103,
+          "h": 30,
+          "bg": "rgb(24, 24, 27)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "优先级 S→A→B"
+        },
+        {
+          "tag": "button",
+          "w": 104,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "综合评分 高→低"
+        },
+        {
+          "tag": "button",
+          "w": 104,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "证据强度 高→低"
+        },
+        {
+          "tag": "button",
+          "w": 68,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "最新上传"
+        },
+        {
+          "tag": "button",
+          "w": 68,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "分歧最大"
+        },
+        {
+          "tag": "input",
+          "w": 240,
+          "h": 32,
+          "bg": "rgba(255, 255, 255, 0.5)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "搜索卡片标题 / 一句话 / 上"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        }
+      ],
+      "thickBorders": [
+        {
+          "tag": "span.live",
+          "w": 0,
+          "ow": 3,
+          "o": "0px"
+        }
+      ],
+      "blackText": [],
+      "fontSizes": {
+        "11": 196,
+        "13": 100,
+        "14": 7,
+        "16": 11,
+        "20": 29
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 835,
+          "heights": [
+            900,
+            1735
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 468,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            368,
+            368,
+            368
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 852,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            410,
+            410,
+            410
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 1276,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            410,
+            410,
+            410
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 628,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 648,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 1032,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 1456,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        }
+      ],
+      "blanks": [],
+      "clickables": 50,
+      "hoverFail": [
+        {
+          "tag": "a",
+          "text": "工作台Workbench"
+        },
+        {
+          "tag": "a",
+          "text": "机会卡池Opportun"
+        },
+        {
+          "tag": "a",
+          "text": "五阶段产出Stages "
+        },
+        {
+          "tag": "a",
+          "text": "分析报告Reports"
+        },
+        {
+          "tag": "a",
+          "text": "证据台账Ledger"
+        },
+        {
+          "tag": "a",
+          "text": "成员Members\n  "
+        },
+        {
+          "tag": "button.refresh.kf-btn",
+          "text": "刷新"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "候选4"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "已立项3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "已否决2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "A 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "B 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S11"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S21"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S34"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S42"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S51"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "拌面5"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "汤面2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "杯面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "炒面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "陈静2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "李娜1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "刘洋1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "孙悦1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "王芳1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "张伟1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "赵磊1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "周涛1"
+        },
+        {
+          "tag": "button",
+          "text": "优先级 S→A→B"
+        },
+        {
+          "tag": "button",
+          "text": "综合评分 高→低"
+        },
+        {
+          "tag": "button",
+          "text": "证据强度 高→低"
+        },
+        {
+          "tag": "button",
+          "text": "最新上传"
+        },
+        {
+          "tag": "button",
+          "text": "分歧最大"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift.tone-ok",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift.tone-ok",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        }
+      ],
+      "scrollH": 1735,
+      "lastContentBottom": 0,
+      "filterLayout": {
+        "container": false,
+        "filtersInsideToolbar": false,
+        "seg": false,
+        "segGap": "",
+        "segBtnHeights": [],
+        "chipHeights": [],
+        "chipFonts": [],
+        "searchH": null,
+        "bottomDelta": null,
+        "segBorder": []
+      },
+      "wbCols": null,
+      "radiiWhere": {
+        "0": "html",
+        "8": "span.badge",
+        "12": "aside.side.kf-glass.is-panel"
+      }
+    },
+    {
+      "page": "/stages",
+      "radii": {
+        "0": 3440,
+        "2": 12,
+        "8": 516,
+        "12": 336,
+        "circle": 4
+      },
+      "controls": [
+        {
+          "tag": "button.refresh.kf-btn",
+          "w": 52,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刷新"
+        },
+        {
+          "tag": "select",
+          "w": 69,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "14px",
+          "reasons": [],
+          "text": "未选择\n            "
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 56,
+          "h": 28,
+          "bg": "rgb(24, 24, 27)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "35"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 47,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S1 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S2 8"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S3 9"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 51,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S4 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S5 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 36,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": ""
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 36,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": ""
+        }
+      ],
+      "thickBorders": [
+        {
+          "tag": "span.live",
+          "w": 0,
+          "ow": 3,
+          "o": "0px"
+        }
+      ],
+      "blackText": [],
+      "fontSizes": {
+        "11": 416,
+        "12": 35,
+        "13": 28,
+        "14": 7,
+        "16": 105,
+        "20": 7
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 2619,
+          "heights": [
+            900,
+            3519
+          ]
+        },
+        {
+          "container": "div.overview",
+          "top": 88,
+          "n": 5,
+          "spread": 0,
+          "heights": [
+            119,
+            119,
+            119,
+            119,
+            119
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 296,
+          "n": 3,
+          "spread": 20.8,
+          "heights": [
+            276,
+            276,
+            255
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 584,
+          "n": 3,
+          "spread": 32.8,
+          "heights": [
+            255,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 852,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1084,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1320,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1552,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1788,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 2020,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 2256,
+          "n": 3,
+          "spread": 129.6,
+          "heights": [
+            222,
+            352,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 2620,
+          "n": 3,
+          "spread": 53.6,
+          "heights": [
+            222,
+            276,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 2908,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            276,
+            276,
+            276
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 3196,
+          "n": 2,
+          "spread": 0,
+          "heights": [
+            276,
+            276
+          ]
+        }
+      ],
+      "blanks": [],
+      "clickables": 26,
+      "hoverFail": [
+        {
+          "tag": "a",
+          "text": "工作台Workbench"
+        },
+        {
+          "tag": "a",
+          "text": "机会卡池Opportun"
+        },
+        {
+          "tag": "a",
+          "text": "五阶段产出Stages "
+        },
+        {
+          "tag": "a",
+          "text": "分析报告Reports"
+        },
+        {
+          "tag": "a",
+          "text": "证据台账Ledger"
+        },
+        {
+          "tag": "a",
+          "text": "成员Members\n  "
+        },
+        {
+          "tag": "button.refresh.kf-btn",
+          "text": "刷新"
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S1\n         "
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S2\n         "
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S3\n         "
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S4\n         "
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S5\n         "
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "35"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S1 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S2 8"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S3 9"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S4 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S5 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": ""
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        }
+      ],
+      "scrollH": 3519,
+      "lastContentBottom": 0,
+      "filterLayout": null,
+      "wbCols": null,
+      "radiiWhere": {
+        "0": "html",
+        "2": "i",
+        "8": "span.badge",
+        "12": "aside.side.kf-glass.is-panel"
+      }
+    },
+    {
+      "page": "/reports",
+      "radii": {
+        "0": 1984,
+        "8": 380,
+        "12": 200,
+        "circle": 4
+      },
+      "controls": [
+        {
+          "tag": "button.refresh.kf-btn",
+          "w": 52,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刷新"
+        },
+        {
+          "tag": "select",
+          "w": 69,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "14px",
+          "reasons": [],
+          "text": "未选择\n            "
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S17"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S29"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S313"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S48"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S57"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "拌面35"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "汤面7"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "炒面3"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S 级6"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "A 级6"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "B 级6"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "高4"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "中29"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "低11"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "待补1"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "会话上传8"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "Skill 上传34"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "手工录入2"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "陈静0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "周涛0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "孙悦0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "李娜0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "张伟0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "赵磊0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "王芳0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "郑凯0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "吴敏0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刘洋0"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 77,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "有证据"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 64,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "我的"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 90,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "可看全文"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 75,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "近 7 天"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "评分"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(24, 24, 27, 0.07)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "最新"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "证据"
+        },
+        {
+          "tag": "button",
+          "w": 34,
+          "h": 26,
+          "bg": "rgb(24, 24, 27)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "w": 34,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "评分"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(24, 24, 27, 0.07)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "最新"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "证据"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "上一页"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgb(91, 91, 214)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "1"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "2"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "3"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "4"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "下一页"
+        }
+      ],
+      "thickBorders": [
+        {
+          "tag": "span.live",
+          "w": 0,
+          "ow": 3,
+          "o": "0px"
+        }
+      ],
+      "blackText": [],
+      "fontSizes": {
+        "11": 201,
+        "12": 62,
+        "13": 50,
+        "14": 15,
+        "16": 37,
+        "20": 2,
+        "32": 5
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 780.7,
+          "heights": [
+            900,
+            1681
+          ]
+        },
+        {
+          "container": "div.types",
+          "top": 164,
+          "n": 5,
+          "spread": 3.2,
+          "heights": [
+            307,
+            310,
+            310,
+            310,
+            307
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 612,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            248,
+            248,
+            248
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 872,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            248,
+            248,
+            248
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1132,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            227,
+            227,
+            227
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1372,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            195,
+            195,
+            195
+          ]
+        }
+      ],
+      "blanks": [],
+      "clickables": 62,
+      "hoverFail": [
+        {
+          "tag": "a",
+          "text": "工作台Workbench"
+        },
+        {
+          "tag": "a",
+          "text": "机会卡池Opportun"
+        },
+        {
+          "tag": "a",
+          "text": "五阶段产出Stages "
+        },
+        {
+          "tag": "a",
+          "text": "分析报告Reports"
+        },
+        {
+          "tag": "a",
+          "text": "证据台账Ledger"
+        },
+        {
+          "tag": "a",
+          "text": "成员Members\n  "
+        },
+        {
+          "tag": "button.refresh.kf-btn",
+          "text": "刷新"
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "品类分析\n       "
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "竞品分析\n       "
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "VOC / 用户洞察\n "
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "痛点清单\n       "
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "概念提案\n       "
+        },
+        {
+          "tag": "summary",
+          "text": "阶段"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S17"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S29"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S313"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S48"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S57"
+        },
+        {
+          "tag": "summary",
+          "text": "品类"
+        },
+        {
+          "tag": "button.opt",
+          "text": "拌面35"
+        },
+        {
+          "tag": "button.opt",
+          "text": "汤面7"
+        },
+        {
+          "tag": "button.opt",
+          "text": "炒面3"
+        },
+        {
+          "tag": "summary",
+          "text": "优先级"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S 级6"
+        },
+        {
+          "tag": "button.opt",
+          "text": "A 级6"
+        },
+        {
+          "tag": "button.opt",
+          "text": "B 级6"
+        },
+        {
+          "tag": "summary",
+          "text": "证据"
+        },
+        {
+          "tag": "button.opt",
+          "text": "高4"
+        },
+        {
+          "tag": "button.opt",
+          "text": "中29"
+        },
+        {
+          "tag": "button.opt",
+          "text": "低11"
+        },
+        {
+          "tag": "button.opt",
+          "text": "待补1"
+        },
+        {
+          "tag": "summary",
+          "text": "方式"
+        },
+        {
+          "tag": "button.opt",
+          "text": "会话上传8"
+        },
+        {
+          "tag": "button.opt",
+          "text": "Skill 上传34"
+        },
+        {
+          "tag": "button.opt",
+          "text": "手工录入2"
+        },
+        {
+          "tag": "summary",
+          "text": "人"
+        },
+        {
+          "tag": "button.opt",
+          "text": "陈静0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "周涛0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "孙悦0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "李娜0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "张伟0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "赵磊0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "王芳0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "郑凯0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "吴敏0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "刘洋0"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "有证据"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "我的"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "可看全文"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "近 7 天"
+        },
+        {
+          "tag": "button",
+          "text": "评分"
+        },
+        {
+          "tag": "button",
+          "text": "最新"
+        },
+        {
+          "tag": "button",
+          "text": "证据"
+        },
+        {
+          "tag": "button",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": ""
+        },
+        {
+          "tag": "summary",
+          "text": "排序:最新"
+        },
+        {
+          "tag": "button",
+          "text": "评分"
+        },
+        {
+          "tag": "button",
+          "text": "最新"
+        },
+        {
+          "tag": "button",
+          "text": "证据"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        }
+      ],
+      "scrollH": 1722,
+      "lastContentBottom": 0,
+      "filterLayout": null,
+      "wbCols": null,
+      "radiiWhere": {
+        "0": "html",
+        "8": "span.badge",
+        "12": "aside.side.kf-glass.is-panel"
+      }
+    }
+  ],
+  "checks": [
+    {
+      "name": "圆角种类 ≤ 3 且 ∈ {8,12,20}(0 只允许分割线/非容器)",
+      "ok": false,
+      "detail": "种类 5:0px×7848、2px×12、8px×1376、12px×764、circlepx×16\n    违禁:2px×12(如 i)"
+    },
+    {
+      "name": "原生外观控件 = 0",
+      "ok": true,
+      "detail": "控件总数 139,原生外观 0"
+    },
+    {
+      "name": "描边 > 1px = 0",
+      "ok": true,
+      "detail": "> 1px border 0"
+    },
+    {
+      "name": "纯黑 rgb(0,0,0) = 0",
+      "ok": true,
+      "detail": "0"
+    },
+    {
+      "name": "字号档 ≤ 5 且无 13.3333px",
+      "ok": false,
+      "detail": "7 档:11×891 / 12×97 / 13×205 / 14×36 / 16×159 / 20×51 / 32×9"
+    },
+    {
+      "name": "同排卡片高度差 ≤ 2px",
+      "ok": false,
+      "detail": "测了 33 行,超差 10\n    / div.grid2.kf-enter n=2 极差 49.2px [142,93]\n    / div.latest n=3 极差 20.8px [389,368,368]\n    /pool div.shell n=2 极差 835px [900,1735]\n    /stages div.shell n=2 极差 2619px [900,3519]\n    /stages div.cards n=3 极差 20.8px [276,276,255]\n    /stages div.cards n=3 极差 32.8px [255,222,222]\n    /stages div.cards n=3 极差 129.6px [222,352,222]\n    /stages div.cards n=3 极差 53.6px [222,276,222]"
+    },
+    {
+      "name": "卡内连续空白 ≤ 24px",
+      "ok": true,
+      "detail": "超 24px 的位置 0"
+    },
+    {
+      "name": "可点元素 hover 反馈",
+      "ok": false,
+      "detail": "可点 164,无反馈 164\n    / a「工作台Workbench」\n    / a「机会卡池Opportun」\n    / a「五阶段产出Stages 」\n    / a「分析报告Reports」\n    / a「证据台账Ledger」\n    / a「成员Members\n  」\n    / button.refresh.kf-btn「刷新」\n    / a.go「机会卡池 →」\n    / a.go「选我」\n    / a.go「」\n    / a.go「9」\n    / div.frame.kf-card.is-lift「」"
+    },
+    {
+      "name": "页面底部空白 ≤ 120px",
+      "ok": false,
+      "detail": "/ 900px,/pool 1735px,/stages 3519px,/reports 1722px"
+    },
+    {
+      "name": "P1 筛选栏:一个容器 + 分段排序 + 与搜索框等高底对齐",
+      "ok": false,
+      "detail": "容器 false,filters 在内 false,seg gap= 按钮高[],chip 高[] 字号[],搜索框高 null,底边差 nullpx"
+    },
+    {
+      "name": "P3 工作台两栏等高(差 ≤ 2px)且左卡无 > 32px 连续空白",
+      "ok": false,
+      "detail": "未量 /"
+    }
+  ],
+  "errors": []
+}

+ 2804 - 0
docs/v12-before.json

@@ -0,0 +1,2804 @@
+{
+  "tag": "before",
+  "at": "2026-10-30T05:58:49.055Z",
+  "pages": [
+    {
+      "page": "/",
+      "radii": {
+        "0": 796,
+        "6": 4,
+        "8": 100,
+        "12": 116,
+        "circle": 4
+      },
+      "controls": [
+        {
+          "tag": "button.refresh.kf-btn",
+          "w": 52,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刷新"
+        },
+        {
+          "tag": "select",
+          "w": 69,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "14px",
+          "reasons": [],
+          "text": "未选择\n            "
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        }
+      ],
+      "thickBorders": [
+        {
+          "tag": "span.live",
+          "w": 0,
+          "ow": 3,
+          "o": "0px"
+        }
+      ],
+      "blackText": [],
+      "fontSizes": {
+        "11": 78,
+        "13": 27,
+        "14": 7,
+        "16": 6,
+        "20": 13,
+        "32": 4
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 0,
+          "heights": [
+            900,
+            900
+          ]
+        },
+        {
+          "container": "div.grid2.kf-enter",
+          "top": 148,
+          "n": 2,
+          "spread": 49.2,
+          "heights": [
+            142,
+            93
+          ]
+        },
+        {
+          "container": "div.grid4",
+          "top": 352,
+          "n": 4,
+          "spread": 0,
+          "heights": [
+            77,
+            77,
+            77,
+            77
+          ]
+        },
+        {
+          "container": "div.latest",
+          "top": 444,
+          "n": 3,
+          "spread": 20.8,
+          "heights": [
+            389,
+            368,
+            368
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 620,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        }
+      ],
+      "blanks": [],
+      "clickables": 26,
+      "hoverFail": [
+        {
+          "tag": "a",
+          "text": "工作台Workbench"
+        },
+        {
+          "tag": "a",
+          "text": "机会卡池Opportun"
+        },
+        {
+          "tag": "a",
+          "text": "五阶段产出Stages "
+        },
+        {
+          "tag": "a",
+          "text": "分析报告Reports"
+        },
+        {
+          "tag": "a",
+          "text": "证据台账Ledger"
+        },
+        {
+          "tag": "a",
+          "text": "成员Members\n  "
+        },
+        {
+          "tag": "button.refresh.kf-btn",
+          "text": "刷新"
+        },
+        {
+          "tag": "a.go",
+          "text": "机会卡池 →"
+        },
+        {
+          "tag": "a.go",
+          "text": "选我"
+        },
+        {
+          "tag": "a.go",
+          "text": ""
+        },
+        {
+          "tag": "a.go",
+          "text": "9"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift.tone-ok",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        }
+      ],
+      "scrollH": 900,
+      "lastContentBottom": 0,
+      "filterLayout": null,
+      "wbCols": null,
+      "radiiWhere": {
+        "0": "html",
+        "6": "div.me",
+        "8": "span.badge",
+        "12": "aside.side.kf-glass.is-panel"
+      }
+    },
+    {
+      "page": "/pool",
+      "radii": {
+        "0": 1628,
+        "6": 4,
+        "8": 364,
+        "12": 120,
+        "circle": 4
+      },
+      "controls": [
+        {
+          "tag": "button.refresh.kf-btn",
+          "w": 52,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刷新"
+        },
+        {
+          "tag": "select",
+          "w": 69,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "14px",
+          "reasons": [],
+          "text": "未选择\n            "
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "候选4"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 73,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "已立项3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 73,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "已否决2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 57,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 58,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "A 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 58,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "B 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 47,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S11"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S21"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S34"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 51,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S42"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S51"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "拌面5"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "汤面2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "杯面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "炒面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "陈静2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "李娜1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刘洋1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "孙悦1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "王芳1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "张伟1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "赵磊1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 60,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "周涛1"
+        },
+        {
+          "tag": "button",
+          "w": 103,
+          "h": 30,
+          "bg": "rgb(24, 24, 27)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "优先级 S→A→B"
+        },
+        {
+          "tag": "button",
+          "w": 104,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "综合评分 高→低"
+        },
+        {
+          "tag": "button",
+          "w": 104,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "证据强度 高→低"
+        },
+        {
+          "tag": "button",
+          "w": 68,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "最新上传"
+        },
+        {
+          "tag": "button",
+          "w": 68,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "分歧最大"
+        },
+        {
+          "tag": "input",
+          "w": 240,
+          "h": 32,
+          "bg": "rgba(255, 255, 255, 0.5)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "搜索卡片标题 / 一句话 / 上"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        },
+        {
+          "tag": "button",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "w": 42,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "w": 72,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "详情 →"
+        }
+      ],
+      "thickBorders": [
+        {
+          "tag": "span.live",
+          "w": 0,
+          "ow": 3,
+          "o": "0px"
+        }
+      ],
+      "blackText": [],
+      "fontSizes": {
+        "11": 196,
+        "13": 100,
+        "14": 7,
+        "16": 11,
+        "20": 29
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 835,
+          "heights": [
+            900,
+            1735
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 468,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            368,
+            368,
+            368
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 852,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            410,
+            410,
+            410
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 1276,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            410,
+            410,
+            410
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 628,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 648,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 1032,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 1456,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        }
+      ],
+      "blanks": [],
+      "clickables": 50,
+      "hoverFail": [
+        {
+          "tag": "a",
+          "text": "工作台Workbench"
+        },
+        {
+          "tag": "a",
+          "text": "机会卡池Opportun"
+        },
+        {
+          "tag": "a",
+          "text": "五阶段产出Stages "
+        },
+        {
+          "tag": "a",
+          "text": "分析报告Reports"
+        },
+        {
+          "tag": "a",
+          "text": "证据台账Ledger"
+        },
+        {
+          "tag": "a",
+          "text": "成员Members\n  "
+        },
+        {
+          "tag": "button.refresh.kf-btn",
+          "text": "刷新"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "候选4"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "已立项3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "已否决2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "A 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "B 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S11"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S21"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S34"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S42"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S51"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "拌面5"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "汤面2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "杯面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "炒面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "陈静2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "李娜1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "刘洋1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "孙悦1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "王芳1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "张伟1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "赵磊1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "周涛1"
+        },
+        {
+          "tag": "button",
+          "text": "优先级 S→A→B"
+        },
+        {
+          "tag": "button",
+          "text": "综合评分 高→低"
+        },
+        {
+          "tag": "button",
+          "text": "证据强度 高→低"
+        },
+        {
+          "tag": "button",
+          "text": "最新上传"
+        },
+        {
+          "tag": "button",
+          "text": "分歧最大"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift.tone-ok",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift.tone-ok",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": "候选"
+        },
+        {
+          "tag": "button.ok",
+          "text": "立项"
+        },
+        {
+          "tag": "button.no",
+          "text": "否决"
+        },
+        {
+          "tag": "button.kf-btn.ghost",
+          "text": "详情 →"
+        }
+      ],
+      "scrollH": 1735,
+      "lastContentBottom": 0,
+      "filterLayout": {
+        "container": false,
+        "filtersInsideToolbar": false,
+        "seg": false,
+        "segGap": "",
+        "segBtnHeights": [],
+        "chipHeights": [],
+        "chipFonts": [],
+        "searchH": null,
+        "bottomDelta": null,
+        "segBorder": []
+      },
+      "wbCols": null,
+      "radiiWhere": {
+        "0": "html",
+        "6": "div.me",
+        "8": "span.badge",
+        "12": "aside.side.kf-glass.is-panel"
+      }
+    },
+    {
+      "page": "/stages",
+      "radii": {
+        "0": 3440,
+        "2": 12,
+        "6": 4,
+        "8": 508,
+        "12": 340,
+        "circle": 4
+      },
+      "controls": [
+        {
+          "tag": "button.refresh.kf-btn",
+          "w": 52,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刷新"
+        },
+        {
+          "tag": "select",
+          "w": 69,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "14px",
+          "reasons": [],
+          "text": "未选择\n            "
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 56,
+          "h": 28,
+          "bg": "rgb(24, 24, 27)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "35"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 47,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S1 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S2 8"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S3 9"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 51,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S4 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S5 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 36,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": ""
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 36,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": ""
+        }
+      ],
+      "thickBorders": [
+        {
+          "tag": "span.live",
+          "w": 0,
+          "ow": 3,
+          "o": "0px"
+        }
+      ],
+      "blackText": [],
+      "fontSizes": {
+        "11": 416,
+        "12": 35,
+        "13": 28,
+        "14": 7,
+        "16": 105,
+        "20": 7
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 2619,
+          "heights": [
+            900,
+            3519
+          ]
+        },
+        {
+          "container": "div.overview",
+          "top": 88,
+          "n": 5,
+          "spread": 0,
+          "heights": [
+            119,
+            119,
+            119,
+            119,
+            119
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 296,
+          "n": 3,
+          "spread": 20.8,
+          "heights": [
+            276,
+            276,
+            255
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 584,
+          "n": 3,
+          "spread": 32.8,
+          "heights": [
+            255,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 852,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1084,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1320,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1552,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1788,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 2020,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            222,
+            222,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 2256,
+          "n": 3,
+          "spread": 129.6,
+          "heights": [
+            222,
+            352,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 2620,
+          "n": 3,
+          "spread": 53.6,
+          "heights": [
+            222,
+            276,
+            222
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 2908,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            276,
+            276,
+            276
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 3196,
+          "n": 2,
+          "spread": 0,
+          "heights": [
+            276,
+            276
+          ]
+        }
+      ],
+      "blanks": [],
+      "clickables": 26,
+      "hoverFail": [
+        {
+          "tag": "a",
+          "text": "工作台Workbench"
+        },
+        {
+          "tag": "a",
+          "text": "机会卡池Opportun"
+        },
+        {
+          "tag": "a",
+          "text": "五阶段产出Stages "
+        },
+        {
+          "tag": "a",
+          "text": "分析报告Reports"
+        },
+        {
+          "tag": "a",
+          "text": "证据台账Ledger"
+        },
+        {
+          "tag": "a",
+          "text": "成员Members\n  "
+        },
+        {
+          "tag": "button.refresh.kf-btn",
+          "text": "刷新"
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S1\n         "
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S2\n         "
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S3\n         "
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S4\n         "
+        },
+        {
+          "tag": "div.kf-card.is-lift.kf-enter",
+          "text": "S5\n         "
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "35"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S1 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S2 8"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S3 9"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S4 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "S5 6"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": ""
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        }
+      ],
+      "scrollH": 3519,
+      "lastContentBottom": 0,
+      "filterLayout": null,
+      "wbCols": null,
+      "radiiWhere": {
+        "0": "html",
+        "2": "i",
+        "6": "div.me",
+        "8": "span.badge",
+        "12": "aside.side.kf-glass.is-panel"
+      }
+    },
+    {
+      "page": "/reports",
+      "radii": {
+        "0": 1984,
+        "6": 4,
+        "8": 372,
+        "12": 204,
+        "circle": 4
+      },
+      "controls": [
+        {
+          "tag": "button.refresh.kf-btn",
+          "w": 52,
+          "h": 32,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刷新"
+        },
+        {
+          "tag": "select",
+          "w": 69,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "14px",
+          "reasons": [],
+          "text": "未选择\n            "
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S17"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S29"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S313"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S48"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S57"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "拌面35"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "汤面7"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "炒面3"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "S 级6"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "A 级6"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "B 级6"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "高4"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "中29"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "低11"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "待补1"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "会话上传8"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "Skill 上传34"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "手工录入2"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "陈静0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "周涛0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "孙悦0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "李娜0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "张伟0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "赵磊0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "王芳0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "郑凯0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "吴敏0"
+        },
+        {
+          "tag": "button.opt",
+          "w": 176,
+          "h": 30,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "刘洋0"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 77,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "有证据"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 64,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "我的"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 90,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "可看全文"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 75,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "13px",
+          "reasons": [],
+          "text": "近 7 天"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "评分"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(24, 24, 27, 0.07)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "最新"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "证据"
+        },
+        {
+          "tag": "button",
+          "w": 34,
+          "h": 26,
+          "bg": "rgb(24, 24, 27)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "w": 34,
+          "h": 26,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "11px",
+          "reasons": [],
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "评分"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(24, 24, 27, 0.07)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "最新"
+        },
+        {
+          "tag": "button",
+          "w": 38,
+          "h": 22,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "8px",
+          "font": "11px",
+          "reasons": [],
+          "text": "证据"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "上一页"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgb(91, 91, 214)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "1"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "2"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "3"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "4"
+        },
+        {
+          "tag": "button",
+          "w": 50,
+          "h": 34,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "12px",
+          "font": "13px",
+          "reasons": [],
+          "text": "下一页"
+        }
+      ],
+      "thickBorders": [
+        {
+          "tag": "span.live",
+          "w": 0,
+          "ow": 3,
+          "o": "0px"
+        }
+      ],
+      "blackText": [],
+      "fontSizes": {
+        "11": 201,
+        "12": 62,
+        "13": 50,
+        "14": 15,
+        "16": 37,
+        "20": 2,
+        "32": 5
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 780.7,
+          "heights": [
+            900,
+            1681
+          ]
+        },
+        {
+          "container": "div.types",
+          "top": 164,
+          "n": 5,
+          "spread": 3.2,
+          "heights": [
+            307,
+            310,
+            310,
+            310,
+            307
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 612,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            248,
+            248,
+            248
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 872,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            248,
+            248,
+            248
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1132,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            227,
+            227,
+            227
+          ]
+        },
+        {
+          "container": "div.cards",
+          "top": 1372,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            195,
+            195,
+            195
+          ]
+        }
+      ],
+      "blanks": [],
+      "clickables": 62,
+      "hoverFail": [
+        {
+          "tag": "a",
+          "text": "工作台Workbench"
+        },
+        {
+          "tag": "a",
+          "text": "机会卡池Opportun"
+        },
+        {
+          "tag": "a",
+          "text": "五阶段产出Stages "
+        },
+        {
+          "tag": "a",
+          "text": "分析报告Reports"
+        },
+        {
+          "tag": "a",
+          "text": "证据台账Ledger"
+        },
+        {
+          "tag": "a",
+          "text": "成员Members\n  "
+        },
+        {
+          "tag": "button.refresh.kf-btn",
+          "text": "刷新"
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "品类分析\n       "
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "竞品分析\n       "
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "VOC / 用户洞察\n "
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "痛点清单\n       "
+        },
+        {
+          "tag": "a.kf-card.is-lift.kf-enter",
+          "text": "概念提案\n       "
+        },
+        {
+          "tag": "summary",
+          "text": "阶段"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S17"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S29"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S313"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S48"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S57"
+        },
+        {
+          "tag": "summary",
+          "text": "品类"
+        },
+        {
+          "tag": "button.opt",
+          "text": "拌面35"
+        },
+        {
+          "tag": "button.opt",
+          "text": "汤面7"
+        },
+        {
+          "tag": "button.opt",
+          "text": "炒面3"
+        },
+        {
+          "tag": "summary",
+          "text": "优先级"
+        },
+        {
+          "tag": "button.opt",
+          "text": "S 级6"
+        },
+        {
+          "tag": "button.opt",
+          "text": "A 级6"
+        },
+        {
+          "tag": "button.opt",
+          "text": "B 级6"
+        },
+        {
+          "tag": "summary",
+          "text": "证据"
+        },
+        {
+          "tag": "button.opt",
+          "text": "高4"
+        },
+        {
+          "tag": "button.opt",
+          "text": "中29"
+        },
+        {
+          "tag": "button.opt",
+          "text": "低11"
+        },
+        {
+          "tag": "button.opt",
+          "text": "待补1"
+        },
+        {
+          "tag": "summary",
+          "text": "方式"
+        },
+        {
+          "tag": "button.opt",
+          "text": "会话上传8"
+        },
+        {
+          "tag": "button.opt",
+          "text": "Skill 上传34"
+        },
+        {
+          "tag": "button.opt",
+          "text": "手工录入2"
+        },
+        {
+          "tag": "summary",
+          "text": "人"
+        },
+        {
+          "tag": "button.opt",
+          "text": "陈静0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "周涛0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "孙悦0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "李娜0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "张伟0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "赵磊0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "王芳0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "郑凯0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "吴敏0"
+        },
+        {
+          "tag": "button.opt",
+          "text": "刘洋0"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "有证据"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "我的"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "可看全文"
+        },
+        {
+          "tag": "button.kf-chip",
+          "text": "近 7 天"
+        },
+        {
+          "tag": "button",
+          "text": "评分"
+        },
+        {
+          "tag": "button",
+          "text": "最新"
+        },
+        {
+          "tag": "button",
+          "text": "证据"
+        },
+        {
+          "tag": "button",
+          "text": ""
+        },
+        {
+          "tag": "button",
+          "text": ""
+        },
+        {
+          "tag": "summary",
+          "text": "排序:最新"
+        },
+        {
+          "tag": "button",
+          "text": "评分"
+        },
+        {
+          "tag": "button",
+          "text": "最新"
+        },
+        {
+          "tag": "button",
+          "text": "证据"
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        },
+        {
+          "tag": "div.frame.kf-card.is-lift",
+          "text": ""
+        }
+      ],
+      "scrollH": 1722,
+      "lastContentBottom": 0,
+      "filterLayout": null,
+      "wbCols": null,
+      "radiiWhere": {
+        "0": "html",
+        "6": "div.me",
+        "8": "span.badge",
+        "12": "aside.side.kf-glass.is-panel"
+      }
+    }
+  ],
+  "checks": [
+    {
+      "name": "圆角种类 ≤ 3 且 ∈ {8,12,20}(0 只允许分割线/非容器)",
+      "ok": false,
+      "detail": "种类 6:0px×7848、2px×12、6px×16、8px×1344、12px×780、circlepx×16\n    违禁:2px×12(如 i);6px×16(如 div.me / div.me / div.me)"
+    },
+    {
+      "name": "原生外观控件 = 0",
+      "ok": true,
+      "detail": "控件总数 139,原生外观 0"
+    },
+    {
+      "name": "描边 > 1px = 0",
+      "ok": true,
+      "detail": "> 1px border 0"
+    },
+    {
+      "name": "纯黑 rgb(0,0,0) = 0",
+      "ok": true,
+      "detail": "0"
+    },
+    {
+      "name": "字号档 ≤ 5 且无 13.3333px",
+      "ok": false,
+      "detail": "7 档:11×891 / 12×97 / 13×205 / 14×36 / 16×159 / 20×51 / 32×9"
+    },
+    {
+      "name": "同排卡片高度差 ≤ 2px",
+      "ok": false,
+      "detail": "测了 33 行,超差 10\n    / div.grid2.kf-enter n=2 极差 49.2px [142,93]\n    / div.latest n=3 极差 20.8px [389,368,368]\n    /pool div.shell n=2 极差 835px [900,1735]\n    /stages div.shell n=2 极差 2619px [900,3519]\n    /stages div.cards n=3 极差 20.8px [276,276,255]\n    /stages div.cards n=3 极差 32.8px [255,222,222]\n    /stages div.cards n=3 极差 129.6px [222,352,222]\n    /stages div.cards n=3 极差 53.6px [222,276,222]"
+    },
+    {
+      "name": "卡内连续空白 ≤ 24px",
+      "ok": true,
+      "detail": "超 24px 的位置 0"
+    },
+    {
+      "name": "可点元素 hover 反馈",
+      "ok": false,
+      "detail": "可点 164,无反馈 164\n    / a「工作台Workbench」\n    / a「机会卡池Opportun」\n    / a「五阶段产出Stages 」\n    / a「分析报告Reports」\n    / a「证据台账Ledger」\n    / a「成员Members\n  」\n    / button.refresh.kf-btn「刷新」\n    / a.go「机会卡池 →」\n    / a.go「选我」\n    / a.go「」\n    / a.go「9」\n    / div.frame.kf-card.is-lift「」"
+    },
+    {
+      "name": "页面底部空白 ≤ 120px",
+      "ok": false,
+      "detail": "/ 900px,/pool 1735px,/stages 3519px,/reports 1722px"
+    },
+    {
+      "name": "P1 筛选栏:一个容器 + 分段排序 + 与搜索框等高底对齐",
+      "ok": false,
+      "detail": "容器 false,filters 在内 false,seg gap= 按钮高[],chip 高[] 字号[],搜索框高 null,底边差 nullpx"
+    },
+    {
+      "name": "P3 工作台两栏等高(差 ≤ 2px)且左卡无 > 32px 连续空白",
+      "ok": false,
+      "detail": "未量 /"
+    }
+  ],
+  "errors": []
+}

+ 1 - 0
package.json

@@ -6,6 +6,7 @@
   "description": "康师傅产品创新看板 · 无构建原生 ESM + Lit(core / wc / page 三层)",
   "sideEffects": false,
   "scripts": {
+    "verify:visual-v12": "node scripts/verify-visual-v12.mjs",
     "config": "node scripts/config.mjs local",
     "vendor": "node scripts/vendor.mjs",
     "serve": "node src/dev/serve.mjs",

+ 402 - 0
scripts/verify-visual-v12.mjs

@@ -0,0 +1,402 @@
+#!/usr/bin/env node
+/**
+ * scripts/verify-visual-v12.mjs —— v12 深度视觉重构验收(任务书「二、硬性数值规范」逐项实测)。
+ *
+ * 两种用法:
+ *   node scripts/verify-visual-v12.mjs --tag before    只打印现状,**不判分**(改前基线)
+ *   node scripts/verify-visual-v12.mjs                  判分:任一项不达标 exit 1
+ *   --page /pool       只量一页(调试用)
+ *   --json out.json    结果落盘(before-after 文档从这里抄数字,不手填)
+ *
+ * 量什么、怎么量(每项都打印分子/分母,不打印「通过」两个字):
+ *   1. 圆角种类   所有可见元素(跨 shadow)的 computed border-radius,去重后按半径归类;只允许 0 / 8 / 12 / 20 / 9999(胶囊)
+ *   2. 原生控件   button/input/select/textarea/summary:外观被显式覆盖(非 appearance:auto / 非浏览器默认灰底 / 有字族与圆角)
+ *   3. 描边       可见元素的 border-width / outline-width 中 > 1px 的数量
+ *   4. 纯黑       computed color === rgb(0, 0, 0) 且带可见文字的元素数
+ *   5. 字号档     可见文字的 font-size 去重(容差 0.1px)
+ *   6. 同排卡高   同一个 grid 容器里的直接子项,按 top 分行(±4px),行内 height 极差
+ *   7. 卡内空白   卡片内部相邻两行内容之间的竖直间隙,> 24px 记一次
+ *   8. hover       每个可点元素 pointerover 前后,背景色 / 边框色 / 背景图 / 颜色 / 阴影任一变化
+ *   9. 底部空白    document 可滚高度 - 最后一块主内容底边
+ *   10. 框内布局   筛选容器是一个整体、排序是分段控件、搜索框与筛选区底边差(P1)
+ *   11. 左右等高   工作台两栏首行卡片高度差(P3)
+ *
+ * 注意(验收脚本的老坑,见 memory kf-verify-browser-quirks):
+ *   - 视图异步挂载:goto 后等 kf-app → view-* 的 shadowRoot 有子节点,再等 300ms;
+ *   - 跨 shadow 的可见性要沿 parentElement → getRootNode().host 一路走;
+ *   - hover 用 elementFromPoint 在已知坐标上派发,不用 mouse.move 后的轮询。
+ */
+import { mkdirSync, writeFileSync } from 'node:fs';
+import { join, dirname } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
+const argv = process.argv.slice(2);
+const arg = (k, d) => (argv.includes(k) ? argv[argv.indexOf(k) + 1] : d);
+const TAG = arg('--tag', 'after');
+const JUDGE = TAG !== 'before';
+const ONLY = arg('--page', '');
+const JSON_OUT = arg('--json', '');
+
+if (!process.env.CHROME_PATH) {
+  const pinned = '/opt/hermes/.playwright/chromium_headless_shell-1243/chrome-headless-shell-linux64/chrome-headless-shell';
+  const { existsSync } = await import('node:fs');
+  if (existsSync(pinned)) process.env.CHROME_PATH = pinned;
+}
+
+const { startServer, launch, DEEP } = await import('./v11b-lib.mjs');
+const srv = await startServer(Number(process.env.VERIFY_PORT || 4193));
+const browser = await launch();
+const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, deviceScaleFactor: 1 });
+const page = await ctx.newPage();
+const errors = [];
+page.on('pageerror', (e) => errors.push(e.message));
+page.on('console', (m) => { if (m.type() === 'error' && !/favicon/.test(m.text())) errors.push(m.text()); });
+
+const VIEW_OF = { '/': 'view-workbench', '/pool': 'view-pool', '/stages': 'view-stages', '/reports': 'view-reports' };
+const PAGES = ONLY ? [ONLY] : ['/', '/pool', '/stages', '/reports'];
+
+const gotoView = async (p) => {
+  await page.goto(new URL(p, srv.base).href, { waitUntil: 'networkidle' });
+  await page.waitForFunction((name) => {
+    const a = document.querySelector('kf-app');
+    const v = a?.shadowRoot?.querySelector(name);
+    return !!v && v.shadowRoot && v.shadowRoot.childElementCount > 0;
+  }, VIEW_OF[p], { timeout: 15000 });
+  await page.waitForTimeout(700);
+};
+
+/** 页面里执行:所有「测量」都放在这一段里,避免每次 evaluate 的字符串拼装差异 */
+const MEASURE = `(async () => {
+  ${DEEP}
+  const root = () => [document, ...[...document.querySelectorAll('*')].map((e) => e.shadowRoot).filter(Boolean)];
+  const all = [];
+  const collect = (r) => { for (const el of r.querySelectorAll('*')) { all.push(el); if (el.shadowRoot) collect(el.shadowRoot); } };
+  collect(document);
+  /* 可见:跨 shadow 链上无 display:none / visibility:hidden / opacity<.05;自身盒 ≥ 8×4 或带可见文字 */
+  const vis = (el) => {
+    const r = el.getBoundingClientRect();
+    if (r.width < 8 || r.height < 4) return false;
+    if (!shownByStyle(el)) return false;
+    return true;
+  };
+  const hasText = (el) => [...el.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim());
+  const PAGES = ${JSON.stringify(PAGES)};
+  const page = location.pathname.replace(/\\/+$/, '') || '/';
+
+  const out = { page, radii: {}, controls: [], thickBorders: [], blackText: [], fontSizes: {}, rows: [], blanks: [], clickables: 0, hoverFail: [], scrollH: 0, lastContentBottom: 0, filterLayout: null, wbCols: null };
+
+  /* ---- 1. 圆角 ---- */
+  const radKinds = {};
+  const radWhere = {};
+  for (const el of all) {
+    if (!vis(el)) continue;
+    const s = getComputedStyle(el);
+    const parts = [s.borderTopLeftRadius, s.borderTopRightRadius, s.borderBottomLeftRadius, s.borderBottomRightRadius]
+      .map((v) => v.split(' ')[0]);
+    /* 量条 / 复选框 / 色点这类 ≤ 6px 的小件:形状由尺寸决定(4px 高的进度条圆角 2px = 胶囊),
+       不作为「圆角体系」计数;8px 以上才算容器圆角,必须落在 8 / 12 / 20。 */
+    const box = el.getBoundingClientRect();
+    const tiny = box.width <= 24 || box.height <= 6;
+    if (tiny) continue;
+    for (const p of parts) {
+      const n = Math.round(parseFloat(p) || 0);
+      const pct = p.includes('%');
+      /* 百分比 = 圆形(头像 / 环),不算圆角档;9999px 以上记作胶囊 */
+      if (pct) { radKinds.circle = (radKinds.circle || 0) + 1; continue; }
+      if (n > 9000 || p.includes('calc') ) { /* 未解析 */ }
+      const k = n;
+      radKinds[k] = (radKinds[k] || 0) + 1;
+      if (!radWhere[k]) radWhere[k] = elLabel(el).slice(0, 48);
+    }
+  }
+  out.radii = radKinds; out.radiiWhere = radWhere;
+
+  /* ---- 2. 原生控件 ---- */
+  const ctrlSel = 'button, input, select, textarea';
+  for (const el of all) {
+    if (!el.matches?.(ctrlSel)) continue;
+    if (!vis(el)) continue;
+    const s = getComputedStyle(el);
+    const tag = elLabel(el);
+    const bg = s.backgroundColor;
+    const bgImg = s.backgroundImage;
+    const reasons = [];
+    /* 文本框(input)在 Chrome 里 appearance 恒为 auto,但给了 rgba 半透明底色就是已覆盖默认外观;
+       select / textarea 必须显式 appearance:none(select 默认画下拉箭头与系统边框)。 */
+    const carriesOwnLook = bg !== 'rgba(0, 0, 0, 0)' || bgImg !== 'none' || (parseFloat(s.borderTopWidth) || 0) > 0;
+    const needsAppearance = el.localName === 'select' || el.localName === 'textarea' || (el.localName === 'input' && (s.appearance !== 'none' && !carriesOwnLook));
+    if (needsAppearance && el.localName !== 'button' && s.appearance !== 'none' && s.webkitAppearance !== 'none') reasons.push('appearance:' + s.appearance);
+    /* 浏览器默认按钮外观:灰底 rgb(239,239,239|221,221,221|192,192,192) + 2px outset */
+    const m = bg.match(/rgba?\\((\\d+), (\\d+), (\\d+)/);
+    if (m && Math.abs(+m[1] - +m[2]) < 3 && Math.abs(+m[2] - +m[3]) < 3 && +m[1] >= 180 && +m[1] <= 245 && bgImg === 'none') reasons.push('灰底' + bg);
+    const bw = parseFloat(s.borderTopWidth) || 0;
+    if (el.localName === 'button' && bw >= 2 && /outset|inset|groove|ridge/.test(s.borderTopStyle)) reasons.push('浏览器浮雕边 ' + s.borderTopStyle + bw + 'px');
+    if (/^(Times|serif)/.test(s.fontFamily) || s.fontFamily === 'none') reasons.push('字族泄漏:' + s.fontFamily.slice(0, 24));
+    if ((el.localName === 'button' || el.localName === 'input') && s.borderRadius === '0px' && bw > 0) reasons.push('无圆角有边框');
+    const r = el.getBoundingClientRect();
+    out.controls.push({ tag, w: Math.round(r.width), h: Math.round(r.height), bg, bw, r: s.borderRadius, font: s.fontSize, reasons, text: (el.textContent || el.placeholder || el.getAttribute('aria-label') || '').trim().slice(0, 16) });
+  }
+
+  /* ---- 3. 描边 > 1px ---- */
+  for (const el of all) {
+    if (!vis(el)) continue;
+    const s = getComputedStyle(el);
+    const widths = [s.borderTopWidth, s.borderRightWidth, s.borderBottomWidth, s.borderLeftWidth]
+      .map((v) => parseFloat(v) || 0).filter((w) => w > 1 && s.borderTopStyle !== 'none');
+    const ow = parseFloat(s.outlineWidth) || 0;
+    if (widths.length || (s.outlineStyle !== 'none' && ow > 1)) out.thickBorders.push({ tag: elLabel(el).slice(0, 50), w: Math.max(...widths, 0), ow, o: s.outlineOffset });
+  }
+
+  /* ---- 4. 纯黑文字 ---- */
+  for (const el of all) {
+    if (!vis(el) || !hasText(el)) continue;
+    /* 只量「直接承载文字」的元素,且字形真的落在里面(子元素另有颜色的不算) */
+    const s = getComputedStyle(el);
+    if (s.color === 'rgb(0, 0, 0)') out.blackText.push({ tag: elLabel(el).slice(0, 50), text: txt(el).trim().slice(0, 20) });
+  }
+
+  /* ---- 5. 字号档 ---- */
+  for (const el of all) {
+    if (!vis(el) || !hasText(el)) continue;
+    /* 只看兄弟文本节点真的有字形的元素 */
+    const fs = Math.round(parseFloat(getComputedStyle(el).fontSize) * 100) / 100;
+    out.fontSizes[fs] = (out.fontSizes[fs] || 0) + 1;
+  }
+
+  /* ---- 6. 同排卡高:grid / flex 容器里直接子项按 top 分行 ---- */
+  const rowSeen = new Set();
+  for (const el of all) {
+    const s = getComputedStyle(el);
+    if (!/grid|flex/.test(s.display)) continue;
+    const kids = [...el.children].filter((k) => vis(k) && k.getBoundingClientRect().height > 40);
+    if (kids.length < 2) continue;
+    const tops = new Map();
+    for (const k of kids) {
+      const r = k.getBoundingClientRect();
+      const key = Math.round(r.top / 4) * 4;
+      if (!tops.has(key)) tops.set(key, []);
+      tops.get(key).push(r.height);
+    }
+    for (const [top, hs] of tops) {
+      if (hs.length < 2) continue;
+      const spread = Math.round((Math.max(...hs) - Math.min(...hs)) * 10) / 10;
+      const id = elLabel(el) + '@' + top;
+      if (rowSeen.has(id)) continue; rowSeen.add(id);
+      out.rows.push({ container: elLabel(el).slice(0, 40), top, n: hs.length, spread, heights: hs.map((h) => Math.round(h)) });
+    }
+  }
+
+  /* ---- 7. 卡内连续空白:卡片内部「有内容的直接子块」之间的竖直间隙 ----
+     卡片 = .kf-card / .frame / kf-glass-card 里的 .wrap;取每张卡内容列的直接子项(渲染树里有文字或有尺寸的),
+     相邻子项底 → 下一项顶,> 24px 记一次(padding 之外)。 */
+  const cardRoots = [];
+  for (const el of all) {
+    if (!el.matches) continue;
+    if (el.matches('kf-glass-card')) cardRoots.push(el);
+  }
+  for (const card of cardRoots) {
+    const face = card.shadowRoot?.querySelector('.face');
+    if (!face || !vis(card)) continue;
+    /* 卡里的内容列:slot 的第一个元素里的 .wrap 或直接子块 */
+    const slot = face.querySelector('slot');
+    const inst = slot ? slot.assignedElements()[0] : null;
+    if (!inst) continue;
+    const col = inst.querySelector(':scope > .wrap') || inst.querySelector(':scope > .rc') || inst;
+    const kids = [...col.children].filter((k) => {
+      const r = k.getBoundingClientRect();
+      return r.height > 0 && getComputedStyle(k).position !== 'absolute';
+    });
+    for (let i = 1; i < kids.length; i++) {
+      const a = kids[i - 1].getBoundingClientRect(), b = kids[i].getBoundingClientRect();
+      const gap = Math.round(b.top - a.bottom);
+      /* 兄弟间 gap(flex gap / margin)为 0 时不算空白:内容是紧挨着的 */
+      const cs = getComputedStyle(col);
+      const declared = parseFloat(cs.rowGap) || 0;
+      const extra = Math.round(gap - declared);
+      if (extra > 24) out.blanks.push({ card: elLabel(card).slice(0, 30), between: elLabel(kids[i - 1]).slice(0, 30) + ' → ' + elLabel(kids[i]).slice(0, 30), extra, gap });
+    }
+  }
+
+  /* ---- 8. hover:穷举可点元素 ---- */
+  const clickables = [];
+  const seen = new Set();
+  for (const el of all) {
+    if (!el.matches?.('button, a[href], summary, [role="button"], [role="tab"], [role="menuitemcheckbox"], [role="menuitemradio"], [data-link]')) continue;
+    if (!vis(el)) continue;
+    const r = el.getBoundingClientRect();
+    /* 只要中心点真的是它自己(不被遮挡),才 hover */
+    const cx = r.left + r.width / 2, cy = r.top + r.height / 2;
+    if (cx < 0 || cy < 0 || cx > innerWidth || cy > innerHeight) continue;
+    const key = elLabel(el) + '@' + Math.round(cx) + ',' + Math.round(cy);
+    if (seen.has(key)) continue; seen.add(key);
+    clickables.push({ el, cx, cy, sig: [getComputedStyle(el).backgroundColor, getComputedStyle(el).borderTopColor, getComputedStyle(el).backgroundImage, getComputedStyle(el).color, getComputedStyle(el).boxShadow, getComputedStyle(el).transform] });
+  }
+  out.clickables = clickables.length;
+  for (const c of clickables) {
+    const before = c.sig.join('|');
+    c.el.dispatchEvent(new PointerEvent('pointerover', { bubbles: true, composed: true }));
+    c.el.dispatchEvent(new PointerEvent('pointerenter', { bubbles: false, composed: true }));
+    c.el.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, composed: true }));
+    /* 等过渡走完(最长 240ms)—— 用两层 rAF + 260ms 超时 */
+    await new Promise((r) => setTimeout(r, 260));
+    const s = getComputedStyle(c.el);
+    const after = [s.backgroundColor, s.borderTopColor, s.backgroundImage, s.color, s.boxShadow, s.transform].join('|');
+    if (after === before) out.hoverFail.push({ tag: elLabel(c.el).slice(0, 40), text: (c.el.textContent || '').trim().slice(0, 12) });
+    c.el.dispatchEvent(new PointerEvent('pointerout', { bubbles: true, composed: true }));
+    c.el.dispatchEvent(new MouseEvent('mouseout', { bubbles: true, composed: true }));
+    await new Promise((r) => setTimeout(r, 30));
+  }
+
+  /* ---- 9. 底部空白 ---- */
+  out.scrollH = Math.round(document.documentElement.scrollHeight);
+  const mainEl = main();
+  let bottom = 0;
+  const scan = (root) => {
+    for (const el of root.querySelectorAll('*')) {
+      if (!vis(el)) continue;
+      if (!hasText(el) && !el.matches('img, svg, kf-glass-card, kf-opportunity-card, kf-empty, canvas')) continue;
+      /* 忽略整块容器的盒,只看「叶子」内容与其卡片 */
+      const r = el.getBoundingClientRect();
+      bottom = Math.max(bottom, r.bottom + scrollY);
+      if (el.shadowRoot) scan(el.shadowRoot);
+    }
+  };
+  scan(mainEl);
+  out.lastContentBottom = Math.round(bottom);
+
+  /* ---- 10. 筛选区(P1)与 11. 工作台两栏(P3) ---- */
+  const q = (sel) => main()?.shadowRoot?.querySelector(sel) || null;
+  if (page === '/pool') {
+    const tb = q('[data-toolbar]');
+    const filters = q('.filters');
+    const seg = q('.seg');
+    const search = q('.frow.toolbar input[type="search"]');
+    const chips = [...(main()?.shadowRoot?.querySelectorAll('.filters .kf-chip') || [])];
+    const chipSizes = chips.map((c) => { const r = c.getBoundingClientRect(); return [Math.round(r.height), getComputedStyle(c).fontSize]; });
+    const segBtns = seg ? [...seg.querySelectorAll('button')] : [];
+    const segGap = seg ? getComputedStyle(seg).gap : '';
+    const segBorders = seg ? segBtns.map((b) => { const s = getComputedStyle(b); return s.borderRightWidth + ' ' + (s.borderRadius || ''); }) : [];
+    out.filterLayout = {
+      container: !!tb, filtersInsideToolbar: tb ? tb.contains(filters) : false,
+      seg: !!seg, segGap, segBtnHeights: segBtns.map((b) => Math.round(b.getBoundingClientRect().height)),
+      chipHeights: chipSizes.map((x) => x[0]), chipFonts: [...new Set(chipSizes.map((x) => x[1]))],
+      searchH: search ? Math.round(search.getBoundingClientRect().height) : null,
+      bottomDelta: search && filters ? Math.round(search.getBoundingClientRect().bottom - filters.getBoundingClientRect().bottom) : null,
+      segBorder: segBorders,
+    };
+  }
+  if (page === '/') {
+    const g = q('.grid2');
+    if (g) {
+      const ks = [...g.children].map((k) => Math.round(k.getBoundingClientRect().height));
+      out.wbCols = { heights: ks, diff: ks.length === 2 ? Math.abs(ks[0] - ks[1]) : null };
+      /* 左卡(或「还没选」空态卡)内的连续空白 */
+      const first = g.children[0];
+      const card = first.shadowRoot?.querySelector('.frame');
+      if (card) {
+        let maxGap = 0;
+        const face = card.querySelector('.face');
+        const inst = face?.querySelector('slot')?.assignedElements()[0];
+        if (inst) {
+          const leaves = [...inst.querySelectorAll('*')].filter((e) => vis(e) && hasText(e));
+          const rs = leaves.map((e) => e.getBoundingClientRect()).sort((a, b) => a.top - b.top);
+          for (let i = 1; i < rs.length; i++) maxGap = Math.max(maxGap, Math.round(rs[i].top - rs[i - 1].bottom));
+        }
+        out.wbCols.leftMaxGap = maxGap;
+      }
+    }
+  }
+  return out;
+})()`;
+
+const results = [];
+for (const p of PAGES) {
+  await gotoView(p);
+  results.push(await page.evaluate(MEASURE));
+}
+
+/* ============ 汇总 ============ */
+const ALLOWED_RADII = new Set([0, 8, 12, 20, 9999]);
+const sum = (k) => results.reduce((n, r) => n + (r.radii[k] || 0), 0);
+
+const radiusKinds = {};
+for (const r of results) for (const [k, n] of Object.entries(r.radii)) radiusKinds[k] = (radiusKinds[k] || 0) + n;
+const badRadii = Object.entries(radiusKinds).filter(([k]) => !ALLOWED_RADII.has(Number(k)) && k !== 'circle');
+
+const controls = results.flatMap((r) => r.controls.map((c) => ({ ...c, page: r.page })));
+const nativeControls = controls.filter((c) => c.reasons.length);
+const thick = results.flatMap((r) => r.thickBorders.map((x) => ({ ...x, page: r.page })));
+/* 焦点环(outline 2px)只在聚焦时出现,还没聚焦时 computed outline 是 none / 宽度 0 */
+const thickReal = thick.filter((x) => x.w > 1);
+const bright = thick.filter((x) => x.ow > 1);
+const blacks = results.flatMap((r) => r.blackText.map((x) => ({ ...x, page: r.page })));
+const fonts = {};
+for (const r of results) for (const [k, n] of Object.entries(r.fontSizes)) fonts[k] = (fonts[k] || 0) + n;
+const fontKinds = Object.keys(fonts).map(Number).sort((a, b) => a - b);
+const rows = results.flatMap((r) => r.rows.map((x) => ({ ...x, page: r.page })));
+const badRows = rows.filter((x) => x.spread > 2);
+const blanks = results.flatMap((r) => r.blanks.map((x) => ({ ...x, page: r.page })));
+const hoverFails = results.flatMap((r) => r.hoverFail.map((x) => ({ ...x, page: r.page })));
+const clickables = results.reduce((n, r) => n + r.clickables, 0);
+const bottomGaps = results.map((r) => ({ page: r.page, gap: Math.max(0, r.scrollH - r.lastContentBottom) }));
+const pool = results.find((r) => r.page === '/pool');
+const wb = results.find((r) => r.page === '/');
+
+const checks = [];
+const check = (name, ok, detail) => { checks.push({ name, ok, detail }); console.log(`\n${JUDGE ? (ok ? '✓' : '✗') : '·'} ${name}\n    ${detail}`); };
+
+console.log(`\n===== v12 视觉验收 · tag=${TAG} · 页面 ${PAGES.join(' ')} =====`);
+
+check('圆角种类 ≤ 3 且 ∈ {8,12,20}(0 只允许分割线/非容器)', badRadii.length === 0 && Object.keys(radiusKinds).length <= 3,
+  `种类 ${Object.keys(radiusKinds).length}:${Object.entries(radiusKinds).map(([k, n]) => `${k}px×${n}`).join('、')}` +
+  (badRadii.length ? `\n    违禁:${badRadii.map(([k, n]) => `${k}px×${n}(如 ${results.flatMap((r) => Object.entries(r.radiiWhere || {}).filter(([kk]) => kk === k).map(([, w]) => w)).slice(0, 3).join(' / ')})`).join(';')}` : ''));
+
+check('原生外观控件 = 0', nativeControls.length === 0,
+  `控件总数 ${controls.length},原生外观 ${nativeControls.length}` +
+  (nativeControls.length ? '\n    ' + nativeControls.slice(0, 12).map((c) => `${c.page} ${c.tag} 「${c.text}」${c.reasons.join(',')}`).join('\n    ') : ''));
+
+check('描边 > 1px = 0', thickReal.length === 0,
+  `> 1px border ${thickReal.length}` + (thickReal.length ? ':' + thickReal.slice(0, 10).map((x) => `${x.page} ${x.tag} ${x.w}px`).join('、') : ''));
+
+check('纯黑 rgb(0,0,0) = 0', blacks.length === 0,
+  `${blacks.length}` + (blacks.length ? ':' + blacks.slice(0, 10).map((x) => `${x.page} ${x.tag}「${x.text}」`).join('、') : ''));
+
+check('字号档 ≤ 5 且无 13.3333px', fontKinds.length <= 5 && !fontKinds.some((f) => Math.abs(f - 13.3333) < 0.01),
+  `${fontKinds.length} 档:${fontKinds.map((f) => `${f}×${fonts[f]}`).join(' / ')}`);
+
+check('同排卡片高度差 ≤ 2px', badRows.length === 0,
+  `测了 ${rows.length} 行,超差 ${badRows.length}` + (badRows.length ? '\n    ' + badRows.slice(0, 8).map((x) => `${x.page} ${x.container} n=${x.n} 极差 ${x.spread}px [${x.heights.join(',')}]`).join('\n    ') : ''));
+
+check('卡内连续空白 ≤ 24px', blanks.length === 0,
+  `超 24px 的位置 ${blanks.length}` + (blanks.length ? '\n    ' + blanks.slice(0, 8).map((x) => `${x.page} ${x.between} +${x.extra}px`).join('\n    ') : ''));
+
+check('可点元素 hover 反馈', hoverFails.length === 0,
+  `可点 ${clickables},无反馈 ${hoverFails.length}` + (hoverFails.length ? '\n    ' + hoverFails.slice(0, 12).map((x) => `${x.page} ${x.tag}「${x.text}」`).join('\n    ') : ''));
+
+check('页面底部空白 ≤ 120px', bottomGaps.every((b) => b.gap <= 120),
+  bottomGaps.map((b) => `${b.page} ${b.gap}px`).join(','));
+
+check('P1 筛选栏:一个容器 + 分段排序 + 与搜索框等高底对齐', (() => {
+  const f = pool?.filterLayout;
+  if (!f) return false;
+  const segOk = f.seg && f.segGap === '0px' && new Set(f.segBtnHeights).size === 1;
+  const chipOk = f.chipHeights.every((h) => h >= 28 && h <= 32) && f.chipFonts.length === 1 && f.chipFonts[0] === '12px';
+  return f.container && f.filtersInsideToolbar && segOk && chipOk && f.searchH !== null && Math.abs(f.bottomDelta) <= 2;
+})(), pool ? `容器 ${pool.filterLayout.container},filters 在内 ${pool.filterLayout.filtersInsideToolbar},seg gap=${pool.filterLayout.segGap} 按钮高[${pool.filterLayout.segBtnHeights}],chip 高[${[...new Set(pool.filterLayout.chipHeights)]}] 字号[${pool.filterLayout.chipFonts}],搜索框高 ${pool.filterLayout.searchH},底边差 ${pool.filterLayout.bottomDelta}px` : '未量 /pool');
+
+check('P3 工作台两栏等高(差 ≤ 2px)且左卡无 > 32px 连续空白', Boolean(wb?.wbCols) && wb.wbCols.diff !== null && wb.wbCols.diff <= 2 && wb.wbCols.leftMaxGap <= 32,
+  wb?.wbCols ? `两栏高 [${wb.wbCols.heights}],差 ${wb.wbCols.diff}px,左卡最大连续空白 ${wb.wbCols.leftMaxGap}px` : '未量 /');
+
+if (errors.length) console.log(`\n页面错误 ${errors.length}:\n    ${errors.slice(0, 10).join('\n    ')}`);
+const fail = checks.filter((c) => !c.ok);
+console.log(`\n${JUDGE ? '判分' : '基线(不判分)'}:${checks.length - fail.length}/${checks.length} 达标${errors.length ? `,页面错误 ${errors.length}` : ''}`);
+
+if (JSON_OUT) {
+  mkdirSync(dirname(join(ROOT, JSON_OUT)), { recursive: true });
+  writeFileSync(join(ROOT, JSON_OUT), JSON.stringify({ tag: TAG, at: new Date().toISOString(), pages: results, checks, errors }, null, 2));
+}
+
+await browser.close();
+srv.kill();
+process.exit(JUDGE && (fail.length || errors.length) ? 1 : 0);

+ 2 - 2
src/components/kf-badge.js

@@ -38,11 +38,11 @@ export class KfBadge extends LitElement {
     /* 徽标:一套尺寸(22px 高 / 6px 圆角 / 11.5px 字);颜色只表达含义,不铺重底 */
     :host { display: inline-flex; vertical-align: middle; }
     /* 手机:标签 11.5px 但要有底色块撑住(任务书 2.4),高度放到 24 */
-    @media (max-width: 767px) { .b { height: 24px; padding: 0 9px; border-radius: 7px; } }
+    @media (max-width: 767px) { .b { height: 24px; padding: 0 9px; border-radius: var(--r-sm); } }
     .b {
       display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 8px;
       text-box-trim: trim-both; text-box-edge: cap alphabetic;
-      border-radius: 6px; font: 600 11px/1 var(--kf-font); letter-spacing: -0.01em;
+      border-radius: var(--r-sm); font: 600 11px/1 var(--kf-font); letter-spacing: -0.01em;
       border: 1px solid var(--kf-line-strong); color: var(--kf-ink-2); background: rgba(255,255,255,0.55);
       white-space: nowrap; font-variant-numeric: tabular-nums;
     }

+ 2 - 2
src/components/kf-drawer.js

@@ -110,12 +110,12 @@ export class KfDrawer extends LitElement {
     .kicker { font-size: 11px; letter-spacing: var(--ls-cn-small); color: var(--kf-ink-3); font-weight: 600; }
     h2 { margin: 4px 0 0; font-size: 20px; line-height: 1.35; color: var(--kf-ink); font-weight: 600; }
     .sub { margin-top: 4px; color: var(--kf-ink-3); font-size: 13px; }
-    .x { width: 32px; height: 32px; flex: none; border-radius: 10px; display: grid; place-items: center;
+    .x { width: 32px; height: 32px; flex: none; border-radius: var(--r-md); display: grid; place-items: center;
       cursor: pointer; color: var(--kf-ink); }
     .body { flex: 1; overflow: auto; padding: 16px 20px 24px; overscroll-behavior: contain; }
     @media (max-width: 767px) {
       /* width 100% + box-sizing: border-box:1px 边框不会再顶出视口右侧(v9 实测右边溢出 24px 的根因) */
-      .panel { width: 100%; box-sizing: border-box; border-radius: 16px 0 0 16px; }
+      .panel { width: 100%; box-sizing: border-box; border-radius: var(--r-md) 0 0 var(--r-md); }
       .head { padding: 18px 14px 14px; padding-top: calc(14px + env(safe-area-inset-top, 0px)); }
       .x { width: 44px; height: 44px; }
       .body { padding: 16px 16px calc(24px + env(safe-area-inset-bottom, 0px)); -webkit-overflow-scrolling: touch; }

+ 1 - 1
src/components/kf-evidence-chain.js

@@ -34,7 +34,7 @@ export class KfEvidenceChain extends LitElement {
     .seg { padding: 12px 0; border-top: 1px solid var(--kf-line); }
     .seg:first-child { border-top: 0; padding-top: 0; }
     .seg h4 { margin: 0 0 8px; font-size: 11px; line-height: 1.4; color: var(--kf-ink-3); font-weight: 600; letter-spacing: var(--ls-cn-small); display: flex; gap: 8px; align-items: center; }
-    .seg h4 .cnt { background: rgba(20,36,70,0.08); border-radius: 6px; padding: 1px 7px; color: var(--kf-ink-2); font-variant-numeric: tabular-nums; }
+    .seg h4 .cnt { background: rgba(20,36,70,0.08); border-radius: var(--r-sm); padding: 1px 7px; color: var(--kf-ink-2); font-variant-numeric: tabular-nums; }
     ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
     li { display: grid; gap: 2px; }
     button.link { all: unset; cursor: pointer; color: var(--kf-ink); font-weight: 600; font-size: 13px; border-bottom: 1px dashed var(--kf-line-strong); align-self: start; }

+ 2 - 2
src/components/kf-glass-card.js

@@ -46,7 +46,7 @@ export class KfGlassCard extends LitElement {
     /* 卡面盒高只由内容决定,与宿主被栅格拉伸的高度无关(block-size: fit-content 让「高度算成拉伸值」的怪行为失效) */
     .frame { width: 100%; height: fit-content; }
     .frame { box-sizing: border-box; isolation: isolate; display: block; overflow: clip; min-height: 0; transition-property: none; }
-    .frame > .face { display: block; position: relative; z-index: 2; box-sizing: border-box; padding: var(--kf-space-card); border-radius: 15px; }
+    .frame > .face { display: block; position: relative; z-index: 2; box-sizing: border-box; padding: var(--kf-space-card); border-radius: var(--r-md); }
     slot { display: block; }
     /* hover 光斑:只亮边框;坐标由 kf-app 的 pointermove 写入 --x / --y */
     :host([lift]) .frame::before {
@@ -64,7 +64,7 @@ export class KfGlassCard extends LitElement {
     /* 手机(v9 实测保留):卡片白面 .62 + blur(24px),圆角 16,内边距 16。
        点按反馈沿用共享表 .kf-card.is-lift:active 的 scale(.985) / 80ms。 */
     @media (max-width: 767px) {
-      .frame { background: linear-gradient(rgba(255, 255, 255, 0.80), rgba(255, 255, 255, 0.80)) padding-box, linear-gradient(180deg, rgba(255, 255, 255, 0.90), rgba(255, 255, 255, 0.12)) border-box; border-radius: 16px; }
+      .frame { background: linear-gradient(rgba(255, 255, 255, 0.80), rgba(255, 255, 255, 0.80)) padding-box, linear-gradient(180deg, rgba(255, 255, 255, 0.90), rgba(255, 255, 255, 0.12)) border-box; border-radius: var(--r-md); }
     }
     /* tone 原来是一条 3px 彩色左边栏(v11 反例 #2 / Vercel「colored side rails」):
        改成 6% 同色染色背景 + 1px 同色半透明描边 —— 同样是「这张卡有状态」,但不是装饰条 */

+ 2 - 2
src/components/kf-opportunity-card.js

@@ -73,14 +73,14 @@ export class KfOpportunityCard extends LitElement {
     .acts .sp { flex: 1; }
     a.report { font-size: 11px; color: var(--kf-accent); text-decoration: none; border-bottom: 1px dashed rgba(91, 91, 214, 0.40); }
     a.report:hover { border-bottom-style: solid; }
-    .st { display: inline-flex; border: 1px solid var(--kf-line-strong); border-radius: 8px; overflow: hidden; background: rgba(255,255,255,0.5); }
+    .st { display: inline-flex; border: 1px solid var(--kf-line-strong); border-radius: var(--r-sm); overflow: hidden; background: rgba(255,255,255,0.5); }
     .st button { border: 0; background: transparent; font: 500 11px/1 var(--kf-font); color: var(--kf-ink-2); padding: 0 10px; height: 26px; cursor: pointer; transition: background var(--kf-dur) var(--kf-ease); }
     .st button:hover { background: rgba(255,255,255,0.6); }
     .st button[aria-pressed="true"]:hover { background: var(--kf-ink); }
     .st button[aria-pressed="true"] { background: var(--kf-ink); color: #fff; }
     .st button[aria-pressed="true"].ok { background: #0f5232; }
     .st button[aria-pressed="true"].no { background: #8a1a14; }
-    .sample { font-size: 11px; line-height: 1; color: #5c4300; background: rgba(255,236,170,0.55); border: 1px solid rgba(170,130,0,0.35); border-radius: 6px; padding: 1px 6px; }
+    .sample { font-size: 11px; line-height: 1; color: #5c4300; background: rgba(255,236,170,0.55); border: 1px solid rgba(170,130,0,0.35); border-radius: var(--r-sm); padding: 1px 6px; }
     :host([compact]) .title { font-size: 14px; }
     :host([compact]) .nums .v { font-size: 16px; }
     /* 手机(任务书 1.3 / 1.5 / 2.4):标题 17/600、一句话 15/1.55、大数字 24/700、按钮 44 触摸高 */

+ 1 - 1
src/components/kf-pipeline.js

@@ -30,7 +30,7 @@ export class KfPipeline extends LitElement {
     .v { font-size: 20px; font-weight: 600; line-height: 1.1; color: var(--kf-ink); font-variant-numeric: tabular-nums; font-family: var(--kf-font-num); }
     .l { font-size: 11px; color: var(--kf-ink-3); }
     .arr { display: inline-flex; color: var(--kf-ink-3); }
-    .rate { margin-left: auto; font-size: 11px; line-height: 1; color: var(--kf-ink-3); border: 1px solid var(--kf-line-strong); border-radius: 6px; padding: 4px 12px; background: rgba(255,255,255,0.5); }
+    .rate { margin-left: auto; font-size: 11px; line-height: 1; color: var(--kf-ink-3); border: 1px solid var(--kf-line-strong); border-radius: var(--r-sm); padding: 4px 12px; background: rgba(255,255,255,0.5); }
     .rate b { color: var(--kf-accent-ink); font-variant-numeric: tabular-nums; font-family: var(--kf-font-num); }
   `;
 

+ 3 - 3
src/components/kf-score-panel.js

@@ -48,7 +48,7 @@ export class KfScorePanel extends LitElement {
     .meta b { color: var(--kf-ink); font-weight: 600; font-variant-numeric: tabular-nums; }
     .none { color: var(--kf-ink-3); font-size: 14px; font-weight: 600; }
     ul { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 6px; }
-    li { display: grid; grid-template-columns: 88px 48px 1fr; gap: 8px; align-items: baseline; padding: 8px 12px; border-radius: 8px; background: rgba(255,255,255,0.4); border: 1px solid var(--kf-line); }
+    li { display: grid; grid-template-columns: 88px 48px 1fr; gap: 8px; align-items: baseline; padding: 8px 12px; border-radius: var(--r-sm); background: rgba(255,255,255,0.4); border: 1px solid var(--kf-line); }
     /* Agent 评分:6% 染色 + 1px 同色半透明描边(不是整块紫底) */
     li.agent { background: color-mix(in srgb, var(--kf-accent) 6%, rgba(255,255,255,0.4)); border-color: color-mix(in srgb, var(--kf-accent) 18%, transparent); }
     .who { color: var(--kf-ink); font-weight: 600; font-size: 13px; }
@@ -56,9 +56,9 @@ export class KfScorePanel extends LitElement {
     /* 行内只用 kf-stat 的数字槽(数字滚动 + 单位分层都复用它),不渲染标签 / 注脚 */
     .s kf-stat { display: inline-block; }
     .c .t { color: var(--kf-ink-3); font-size: 11px; margin-left: 6px; }
-    form { margin-top: 16px; padding: 12px; border-radius: 8px; border: 1px dashed var(--kf-line-strong); display: grid; gap: 8px; }
+    form { margin-top: 16px; padding: 12px; border-radius: var(--r-sm); border: 1px dashed var(--kf-line-strong); display: grid; gap: 8px; }
     .row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
-    input[type="number"], input[type="text"] { height: 32px; border-radius: 8px; border: 1px solid var(--kf-line-strong); background: rgba(255,255,255,0.6); transition: var(--kf-t); }
+    input[type="number"], input[type="text"] { height: 32px; border-radius: var(--r-sm); border: 1px solid var(--kf-line-strong); background: rgba(255,255,255,0.6); transition: var(--kf-t); }
     input:focus { outline: none; border-color: var(--kf-focus); box-shadow: 0 0 0 2px rgba(91, 91, 214, 0.22); background: #fff; }
     input[type="number"] { width: 88px; padding: 0 8px; font: 600 14px var(--kf-font-num); font-variant-numeric: tabular-nums; }
     input[type="text"] { flex: 1; min-width: 160px; padding: 0 12px; font: 13px var(--kf-font); }

+ 1 - 1
src/components/kf-toast.js

@@ -46,7 +46,7 @@ export class KfToast extends LitElement {
     :host { position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 16px); z-index: 60; opacity: 0; pointer-events: none;
       transition: transform 200ms cubic-bezier(0.2, 0, 0, 1), opacity 200ms cubic-bezier(0.2, 0, 0, 1); }
     :host([open]) { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
-    .t { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-radius: 14px;
+    .t { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-radius: var(--r-md);
       background: rgba(20, 32, 60, 0.92); color: #fff; font-size: 13px; box-shadow: var(--shadow-3);
       -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px); }
     .dot { width: 8px; height: 8px; border-radius: 50%; background: #5ee0a0; }

+ 1 - 1
src/components/kf-viz.js

@@ -33,7 +33,7 @@ const VIZ_CSS = css`
   .brow .n { color: var(--kf-ink); }
   .brow { display: grid; align-items: center; gap: 4px 6px; font-variant-numeric: tabular-nums; }
   .bars.stack .brow { grid-template-columns: minmax(0, 72px) minmax(0, 1fr) 32px; grid-template-rows: auto; gap: 8px; }
-  .brow .t { grid-column: 1 / -1; height: 4px; border-radius: 2px; background: rgba(16, 24, 40, 0.07); overflow: hidden; }
+  .brow .t { grid-column: 1 / -1; height: 4px; border-radius: var(--r-sm); background: rgba(16, 24, 40, 0.07); overflow: hidden; }
   .bars.stack .brow .t { grid-column: auto; }
   :host([stack]) .brow .t { order: 2; }
   :host([stack]) .brow .n { order: 3; }

+ 5 - 5
src/layout/kf-app.js

@@ -393,7 +393,7 @@ export class KfApp extends SignalWatcher(LitElement) {
       <div class="kf-skel" style="width:240px;height:28px"></div>
       <div class="kf-skel" style="width:360px;height:14px;margin-top:8px"></div>
       <div class="kpi-row">${[1, 2, 3, 4].map(() => html`<div class="kf-skel kpi-ph"></div>`)}</div>
-      <div class="kf-skel" style="height:88px;margin-top:16px;border-radius:16px"></div>
+      <div class="kf-skel" style="height:88px;margin-top:16px;border-radius:var(--r-md)"></div>
       <div class="skel-row">${[1, 2, 3, 4, 5, 6].map(() => html`<div class="kf-skel card-ph">
         <i class="l w40"></i><i class="l w85"></i><i class="l w70"></i><i class="l w55"></i></div>`)}</div>
     </div>`;
@@ -461,9 +461,9 @@ export class KfApp extends SignalWatcher(LitElement) {
     .view { padding: 16px 28px 48px; width: 100%; box-sizing: border-box; }
     .skel-page { padding-top: 8px; }
     .skel-page .kpi-row { display: flex; gap: 16px; margin-top: 24px; }
-    .skel-page .kpi-ph { flex: 1; height: 64px; border-radius: 16px; }
-    .skel-page .card-ph { height: 236px; border-radius: 16px; padding: 16px 20px; box-sizing: border-box; display: grid; align-content: start; gap: 12px; }
-    .skel-page .card-ph .l { display: block; height: 12px; border-radius: 6px; background: rgba(0, 0, 0, 0.04); }
+    .skel-page .kpi-ph { flex: 1; height: 64px; border-radius: var(--r-md); }
+    .skel-page .card-ph { height: 236px; border-radius: var(--r-md); padding: 16px 20px; box-sizing: border-box; display: grid; align-content: start; gap: 12px; }
+    .skel-page .card-ph .l { display: block; height: 12px; border-radius: var(--r-sm); background: rgba(0, 0, 0, 0.04); }
     .skel-page .card-ph .w40 { width: 40%; height: 16px; }
     .skel-page .card-ph .w85 { width: 85%; margin-top: 8px; }
     .skel-page .card-ph .w70 { width: 70%; }
@@ -496,7 +496,7 @@ export class KfApp extends SignalWatcher(LitElement) {
     .prov { display: flex; flex-wrap: wrap; gap: 4px; align-items: baseline; font-size: 11px; color: var(--kf-ink-3); }
     .prov .plat { color: var(--kf-ink); font-weight: 600; }
     .quotes { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
-    .quotes li { padding: 12px 16px; border-radius: 10px; background: rgba(255,255,255,0.45); border: 1px solid var(--kf-line); }
+    .quotes li { padding: 12px 16px; border-radius: var(--r-md); background: rgba(255,255,255,0.45); border: 1px solid var(--kf-line); }
     .quotes p { margin: 0 0 4px; font-size: 13px; line-height: var(--lh-body); max-width: 48em; color: var(--kf-ink); }
     /* ===== 断点(任务书第 1 节,全站统一) ===== */
     /* 平板:导航收窄,仍然在左侧 */

+ 8 - 8
src/layout/kf-nav.js

@@ -51,22 +51,22 @@ export class KfNav extends LitElement {
       border-radius: 0 var(--kf-radius-lg) var(--kf-radius-lg) 0; border-left: 0; }
     .brand { display: flex; gap: 12px; align-items: center; padding: 4px 8px 18px; }
     /* 品牌块:v10 收成一块实色强调色(过去是四色 conic 渐变 + 彩色投影,过饱和) */
-    .mark { width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center; color: #fff; font-weight: 600; font-size: 20px;
+    .mark { width: 40px; height: 40px; border-radius: var(--r-md); display: grid; place-items: center; color: #fff; font-weight: 600; font-size: 20px;
       background: var(--kf-accent); }
     .name { font-size: 14px; font-weight: 600; color: var(--kf-ink); letter-spacing: -0.01em; }
     .sub { font-size: 11px; color: var(--kf-ink-3); }
     nav { display: grid; gap: 4px; }
-    a { display: flex; align-items: center; gap: 12px; height: 40px; padding: 0 12px; border-radius: 10px; color: var(--kf-ink-2);
+    a { display: flex; align-items: center; gap: 12px; height: 40px; padding: 0 12px; border-radius: var(--r-md); color: var(--kf-ink-2);
       text-decoration: none; font-size: 14px; font-weight: 500; position: relative; }
     a { transition: var(--kf-t); }
     a:hover { background: rgba(255,255,255,0.5); }
     a[aria-current="page"] { background: rgba(255,255,255,0.92); color: var(--kf-ink); box-shadow: var(--elev-1); }
-    a[aria-current="page"]::before { content: ""; position: absolute; left: 0; top: 11px; bottom: 11px; width: 3px; border-radius: 0 3px 3px 0; background: var(--kf-accent); }
+    a[aria-current="page"]::before { content: ""; position: absolute; left: 0; top: 11px; bottom: 11px; width: 3px; border-radius: 0 var(--r-sm) var(--r-sm) 0; background: var(--kf-accent); }
     svg.i { width: 18px; height: 18px; }
     .lbl { flex: 1; min-width: 0; }
     .en { display: block; font-size: 11px; color: var(--kf-ink-3); letter-spacing: 0.03em; font-weight: 500; }
     .short { display: none; }
-    .badge { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 6px; display: grid; place-items: center;
+    .badge { min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--r-sm); display: grid; place-items: center;
       font-size: 11px; font-weight: 500; letter-spacing: 0.02em; background: var(--kf-fill); color: var(--kf-ink-2); font-variant-numeric: tabular-nums; }
     .badge.danger { background-color: var(--kf-s); color: #fff; }
     .foot { margin-top: auto; padding: 12px 10px 0; border-top: 1px solid var(--kf-line); font-size: 11px; color: var(--kf-ink-3); display: flex; align-items: center; gap: 8px; }
@@ -82,7 +82,7 @@ export class KfNav extends LitElement {
       .tabbar {
         display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); align-items: start;
         box-sizing: border-box; padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
-        border-radius: 16px 16px 0 0; border-bottom: 0; border-left: 0; border-right: 0;
+        border-radius: var(--r-lg) var(--r-lg) 0 0; border-bottom: 0; border-left: 0; border-right: 0;
         background:
           linear-gradient(rgba(255, 255, 255, 0.78), rgba(255, 255, 255, 0.78)) padding-box,
           linear-gradient(0deg, rgba(10, 20, 40, 0.10), rgba(255, 255, 255, 0.95)) border-box;
@@ -91,7 +91,7 @@ export class KfNav extends LitElement {
         box-shadow: var(--kf-shadow-tabbar);   /* = elev-3 的上下镜像 */
       }
       .tabbar a { height: 52px; min-width: 0; padding: 0; display: grid; justify-items: center; align-content: center; gap: 4px;
-        position: relative; border-radius: 10px; color: var(--kf-ink-3); background: none; box-shadow: none; }
+        position: relative; border-radius: var(--r-md); color: var(--kf-ink-3); background: none; box-shadow: none; }
       .tabbar a::before { display: none; }
       .tabbar a:active { background: rgba(18, 32, 64, 0.06); transform: scale(0.985); transition: transform 80ms cubic-bezier(0.4, 0, 0.2, 1); }
       .tabbar .ico { position: relative; width: 24px; height: 24px; display: grid; place-items: center; }
@@ -102,12 +102,12 @@ export class KfNav extends LitElement {
       .tabbar .ico .sl { display: none; stroke-width: 2.6; }
       .tabbar a[aria-current="page"] .ico .ln { display: none; }
       .tabbar a[aria-current="page"] .ico .sl { display: block; }
-      .tabbar a[aria-current="page"] .ico::after { content: ""; position: absolute; inset: 4px; border-radius: 7px; z-index: -1;
+      .tabbar a[aria-current="page"] .ico::after { content: ""; position: absolute; inset: 4px; border-radius: var(--r-sm); z-index: -1;
         background: var(--kf-accent-soft); }
       .tabbar a[aria-current="page"]::after { content: ""; position: absolute; top: -6px; left: 50%; width: 20px; height: 2px; margin-left: -10px;
         border-radius: 0 0 2px 2px; background: var(--kf-accent); }
       /* 移动 Tab 角标:不绝对定位出头(v10 实测悬在栏外 20px 处,形成一条悬空的小色块) */
-      .tabbar .badge { position: static; margin: -4px 0 0 20px; min-width: 16px; height: 16px; padding: 0 4px; font-size: 11px; border-radius: 6px; }
+      .tabbar .badge { position: static; margin: -4px 0 0 20px; min-width: 16px; height: 16px; padding: 0 4px; font-size: 11px; border-radius: var(--r-sm); }
     }
     @media (min-width: 768px) { .tabbar { display: none; } }
   `;

+ 4 - 4
src/layout/kf-topbar.js

@@ -49,12 +49,12 @@ export class KfTopbar extends LitElement {
     .sync .dot { width: 7px; height: 7px; border-radius: 50%; background: #2e7d5b; }
     .sync.warn .dot { background: #b27a00; }
     .sync.err .dot { background: var(--kf-s); }
-    .me { display: flex; align-items: center; gap: 8px; padding: 2px 2px 2px 12px; border-radius: 6px; border: 1px solid transparent; background: linear-gradient(var(--kf-glass-chip), var(--kf-glass-chip)) padding-box, var(--kf-edge-chip) border-box; box-shadow: var(--kf-shadow-chip); }
+    .me { display: flex; align-items: center; gap: 8px; padding: 2px 2px 2px 12px; border-radius: var(--r-sm); border: 1px solid transparent; background: linear-gradient(var(--kf-glass-chip), var(--kf-glass-chip)) padding-box, var(--kf-edge-chip) border-box; box-shadow: var(--kf-shadow-chip); }
     .me label { font-size: 11px; color: var(--kf-ink-3); }
-    select { height: 28px; border-radius: 6px; border: 0; background: transparent; font: 600 13px var(--kf-font); color: var(--kf-ink); padding: 0 8px 0 2px; cursor: pointer; }
+    select { height: 28px; border-radius: var(--r-sm); border: 0; background: transparent; font: 600 13px var(--kf-font); color: var(--kf-ink); padding: 0 8px 0 2px; cursor: pointer; }
     .who { width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; font-size: 11px; font-weight: 600; color: #fff;
       background: linear-gradient(135deg, #2457d6, #5a3fd6); }
-    button.refresh { height: 32px; padding: 0 12px; border-radius: 10px; font: 500 13px var(--kf-font); color: var(--kf-ink); cursor: pointer; }
+    button.refresh { height: 32px; padding: 0 12px; border-radius: var(--r-sm); font: 500 13px var(--kf-font); color: var(--kf-ink); cursor: pointer; }
     @media (max-width: 1023px) { .bar { padding: 10px 20px; } .sync { display: none; } }
     /* 手机:状态栏让开(safe-area-top),标题 17/600,一行装下「我是 + 刷新」 */
     @media (max-width: 767px) {
@@ -68,7 +68,7 @@ export class KfTopbar extends LitElement {
       .who { width: 32px; height: 32px; font-size: 13px; margin-left: -8px; }
       select { height: 44px; min-width: 44px; font-size: 14px; font-weight: 600; max-width: 128px; }
       .me:active { background: linear-gradient(var(--kf-glass-chip-hover), var(--kf-glass-chip-hover)) padding-box, var(--kf-edge-chip) border-box; }
-      button.refresh { height: 44px; min-width: 44px; padding: 0 14px; font-size: 14px; border-radius: 12px; }
+      button.refresh { height: 44px; min-width: 44px; padding: 0 14px; font-size: 14px; border-radius: var(--r-sm); }
     }
   `;
 

+ 10 - 10
src/pages/card-toolbar.js

@@ -24,7 +24,7 @@ export const TOOLBAR_CSS = css`
   .tb .kf-chip.on .n { opacity: 0.9; }
   .dd { position: relative; }
   .dd > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; height: 28px; padding: 0 10px;
-    border-radius: 8px; border: 1px solid var(--kf-line-strong); background: var(--kf-glass-chip); font: 500 13px/1 var(--kf-font); color: var(--kf-ink);
+    border-radius: var(--r-sm); border: 1px solid var(--kf-line-strong); background: var(--kf-glass-chip); font: 500 13px/1 var(--kf-font); color: var(--kf-ink);
     transition: background var(--kf-dur) var(--kf-ease), border-color var(--kf-dur) var(--kf-ease); }
   .dd > summary:hover { background: var(--kf-glass-chip-hover); }
   .dd > summary::-webkit-details-marker { display: none; }
@@ -35,7 +35,7 @@ export const TOOLBAR_CSS = css`
     background: linear-gradient(var(--kf-glass-top), var(--kf-glass-top)) padding-box, var(--kf-edge) border-box;
     -webkit-backdrop-filter: blur(var(--kf-blur-top)) saturate(var(--kf-sat-top)); backdrop-filter: blur(var(--kf-blur-top)) saturate(var(--kf-sat-top));
     box-shadow: var(--kf-shadow-pop); }
-  .dd .opt { all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px;
+  .dd .opt { all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: var(--r-sm);
     font: 500 13px var(--kf-font); color: var(--kf-ink); cursor: pointer; }
   .dd .opt:hover { background: rgba(91, 91, 214, 0.10); }
   .dd .opt[aria-checked="true"] { background: rgba(24, 24, 27, 0.06); font-weight: 600; }
@@ -45,11 +45,11 @@ export const TOOLBAR_CSS = css`
   .sw.t-amber { background: var(--kf-s4); } .sw.t-rose { background: var(--kf-s5); }
   .dd .opt .ck { width: 14px; height: 14px; border-radius: 4px; border: 1.5px solid var(--kf-line-strong); flex: none; }
   .dd .opt[aria-checked="true"] .ck { background: var(--gray-12); border-color: var(--gray-12); }
-  .seg2 { display: inline-flex; border: 1px solid var(--kf-line-strong); border-radius: 8px; overflow: hidden; background: rgba(255,255,255,0.5); }
+  .seg2 { display: inline-flex; border: 1px solid var(--kf-line-strong); border-radius: var(--r-sm); overflow: hidden; background: rgba(255,255,255,0.5); }
   .seg2 button { all: unset; cursor: pointer; padding: 0 10px; height: 26px; display: inline-flex; align-items: center; gap: 4px; font: 500 11px/1 var(--kf-font); color: var(--kf-ink-2); }
   .seg2 button[aria-pressed="true"] { background: var(--kf-ink); color: #fff; }
-  .sortb { display: inline-flex; align-items: center; gap: 2px; padding: 2px 2px 2px 8px; border-radius: 8px; border: 1px solid var(--kf-line-strong); background: rgba(255,255,255,0.5); color: var(--kf-ink-3); }
-  .sortb button { all: unset; cursor: pointer; padding: 0 8px; height: 22px; border-radius: 7px; font: 500 11px/1 var(--kf-font); color: var(--kf-ink-2); }
+  .sortb { display: inline-flex; align-items: center; gap: 2px; padding: 2px 2px 2px 8px; border-radius: var(--r-sm); border: 1px solid var(--kf-line-strong); background: rgba(255,255,255,0.5); color: var(--kf-ink-3); }
+  .sortb button { all: unset; cursor: pointer; padding: 0 8px; height: 22px; border-radius: var(--r-sm); font: 500 11px/1 var(--kf-font); color: var(--kf-ink-2); }
   .sortb button[aria-pressed="true"] { background: rgba(24, 24, 27, 0.07); color: var(--kf-ink); font-weight: 600; }
   .tb .cnt { font: 500 11px var(--kf-font-num); color: var(--kf-ink-3); font-variant-numeric: tabular-nums; }
   .tb .cnt b { color: var(--kf-ink); font-weight: 600; }
@@ -57,23 +57,23 @@ export const TOOLBAR_CSS = css`
   /* ===== 手机(任务书 1.2):6 个下拉 + 4 个开关收成一个「筛选」按钮 + 底部弹层 ===== */
   .mbar, .mchips { display: none; }
   @media (max-width: 767px) {
-    .tb { display: block; padding: 8px; border-radius: 16px; margin-bottom: 12px; }
+    .tb { display: block; padding: 8px; border-radius: var(--r-md); margin-bottom: 12px; }
     .tb > .tb-row { display: none; }
     /* 工具条两行:第一行「筛选(N) · 结果数 · 视图」;第二行只放一个可展开的「排序」,展开后才有近 7 天 / 排序 / 清除 */
     .mbar { display: flex; gap: 8px; align-items: center; }
     .mbar .cnt { margin-left: auto; font: 600 14px var(--kf-font-num); color: var(--kf-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
     .mbar .cnt b { font-weight: 600; }
-    .fbtn { all: revert; box-sizing: border-box; display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 14px; border-radius: 12px; cursor: pointer;
+    .fbtn { all: revert; box-sizing: border-box; display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 14px; border-radius: var(--r-md); cursor: pointer;
       font: 600 14px var(--kf-font); color: var(--kf-ink); border: 1px solid transparent; flex: none;
       background: linear-gradient(var(--kf-glass-chip), var(--kf-glass-chip)) padding-box, var(--kf-edge-chip) border-box; box-shadow: var(--kf-shadow-chip);
       -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); transition: transform 90ms var(--kf-ease); }
     .fbtn:active { transform: scale(0.985); background: linear-gradient(rgba(255,255,255,0.75), rgba(255,255,255,0.75)) padding-box, var(--kf-edge-chip) border-box; }
     .fbtn.on { border-color: var(--kf-accent); box-shadow: inset 0 0 0 1px var(--kf-accent); }
-    .fbtn .nb { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; display: grid; place-items: center; font: 500 11px var(--kf-font-num); color: #fff; background: var(--kf-accent); font-variant-numeric: tabular-nums; }
-    .seg2.m { display: inline-flex; margin-left: auto; height: 44px; border-radius: 12px; flex: none; }
+    .fbtn .nb { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; display: grid; place-items: center; font: 500 11px var(--kf-font-num); color: #fff; background: var(--kf-accent); font-variant-numeric: tabular-nums; }
+    .seg2.m { display: inline-flex; margin-left: auto; height: 44px; border-radius: var(--r-md); flex: none; }
     .seg2.m button { height: 44px; min-width: 44px; padding: 0 10px; }
     .seg2.m button svg { width: 18px; height: 18px; }
-    .mor { margin-top: 8px; border-radius: 12px; background: rgba(255, 255, 255, 0.32); }
+    .mor { margin-top: 8px; border-radius: var(--r-md); background: rgba(255, 255, 255, 0.32); }
     .mor > summary { list-style: none; display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 12px; cursor: pointer; font: 600 14px var(--kf-font); color: var(--kf-ink-2); }
     .mor > summary::-webkit-details-marker { display: none; }
     .mor > summary .ch { margin-left: auto; color: var(--kf-ink-3); transition: transform var(--kf-dur) var(--kf-ease); }

+ 8 - 8
src/pages/filter-sheet.js

@@ -134,7 +134,7 @@ export class KfFilterSheet extends LitElement {
     .sheet:focus, .sheet:focus-visible { outline: none; }
     .sheet { position: absolute; left: 0; right: 0; bottom: 0; max-height: 88vh; display: flex; flex-direction: column;
       transform: translateY(var(--sheet-dy, 0px)); box-sizing: border-box;
-      border-radius: 16px 16px 0 0; border: 1px solid transparent; border-bottom: 0;
+      border-radius: var(--r-md) var(--r-md) 0 0; border: 1px solid transparent; border-bottom: 0;
       background: linear-gradient(rgba(255, 255, 255, 0.78), rgba(255, 255, 255, 0.78)) padding-box,
         linear-gradient(135deg, rgba(255,255,255,0.95), rgba(255,255,255,0.2) 40%, rgba(10,20,40,0.08)) border-box;
       -webkit-backdrop-filter: blur(32px) saturate(190%); backdrop-filter: blur(32px) saturate(190%);
@@ -147,25 +147,25 @@ export class KfFilterSheet extends LitElement {
     .handle { display: block; width: 40px; height: 5px; margin: 0 auto; border-radius: 3px; background: rgba(18, 32, 64, 0.28); }
     .hd { display: flex; align-items: center; padding: 0 8px 4px 20px; }
     h2 { margin: 0; flex: 1; font-size: 16px; font-weight: 600; color: var(--kf-ink); line-height: 1.4; }
-    .x { all: unset; width: 44px; height: 44px; display: grid; place-items: center; border-radius: 12px; color: var(--kf-ink); cursor: pointer; }
+    .x { all: unset; width: 44px; height: 44px; display: grid; place-items: center; border-radius: var(--r-md); color: var(--kf-ink); cursor: pointer; }
     .x:active { background: rgba(18, 32, 64, 0.08); }
     .groups { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; padding: 0 12px 8px; }
     .g { border-top: 1px solid var(--kf-line); }
     .g:first-child { border-top: 0; }
-    .grow-row { all: unset; box-sizing: border-box; width: 100%; min-height: 56px; display: flex; align-items: center; gap: 8px; padding: 0 8px; border-radius: 12px; cursor: pointer; color: var(--kf-ink); }
+    .grow-row { all: unset; box-sizing: border-box; width: 100%; min-height: 56px; display: flex; align-items: center; gap: 8px; padding: 0 8px; border-radius: var(--r-md); cursor: pointer; color: var(--kf-ink); }
     .grow-row:active { background: rgba(18, 32, 64, 0.05); }
     .gl { font-size: 14px; font-weight: 600; flex: none; }
     .g.has .gl { color: var(--kf-accent-ink); }
-    .gn { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; display: grid; place-items: center; font: 500 11px var(--kf-font-num); color: #fff; background: var(--kf-accent); font-variant-numeric: tabular-nums; }
+    .gn { min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--r-md); display: grid; place-items: center; font: 500 11px var(--kf-font-num); color: #fff; background: var(--kf-accent); font-variant-numeric: tabular-nums; }
     .gv { flex: 1; min-width: 0; font-size: 13px; color: var(--kf-ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: right; }
     .gc { margin-left: auto; display: grid; place-items: center; color: var(--kf-ink-3); transition: transform var(--kf-dur) var(--kf-ease); }
     .gc.up { transform: rotate(180deg); }
     .opts { display: grid; gap: 2px; padding: 0 0 8px; animation: kf-enter 160ms var(--kf-ease) both; }
-    .opt { all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 0 10px 0 14px; border-radius: 12px; cursor: pointer; color: var(--kf-ink-2); font-size: 14px; }
+    .opt { all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 0 10px 0 14px; border-radius: var(--r-md); cursor: pointer; color: var(--kf-ink-2); font-size: 14px; }
     .opt:active { background: rgba(18, 32, 64, 0.07); transform: scale(0.985); transition: transform 80ms cubic-bezier(0.4, 0, 0.2, 1); }
     .opt .ol { flex: 1; min-width: 0; line-height: 1.3; }
     .opt .on { font: 600 14px var(--kf-font-num); color: var(--kf-ink-3); font-variant-numeric: tabular-nums; }
-    .opt .ck { width: 22px; height: 22px; border-radius: 7px; display: grid; place-items: center; border: 1.5px solid var(--kf-line-strong); color: transparent; flex: none; }
+    .opt .ck { width: 22px; height: 22px; border-radius: var(--r-sm); display: grid; place-items: center; border: 1.5px solid var(--kf-line-strong); color: transparent; flex: none; }
     .opt .ck svg { width: 14px; height: 14px; }
     /* 选中态:灰阶(v10 强调色收敛)—— 浅灰底 + 深字,勾选块实心灰-12 */
     .opt[aria-checked="true"] { background: rgba(24, 24, 27, 0.06); color: var(--kf-ink); font-weight: 600; }
@@ -175,13 +175,13 @@ export class KfFilterSheet extends LitElement {
     .sw.t-blue { background: var(--kf-s1); } .sw.t-violet { background: var(--kf-s2); } .sw.t-teal { background: var(--kf-s3); }
     .sw.t-amber { background: var(--kf-s4); } .sw.t-rose { background: var(--kf-s5); }
     .ft { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 8px; padding: 12px 16px; border-top: 1px solid var(--kf-line); background: rgba(255, 255, 255, 0.4); }
-    .ft .kf-btn { height: 48px; font-size: 14px; font-weight: 600; border-radius: 12px; }
+    .ft .kf-btn { height: 48px; font-size: 14px; font-weight: 600; border-radius: var(--r-md); }
     .ft .kf-btn[disabled] { opacity: 0.45; }
     .ft .go { font-variant-numeric: tabular-nums; }
     /* 内嵌模式:从「筛选」按钮上方的单元格里长出,底部贴住 Tab 栏,顶部留一截可用内容做上下文 */
     :host([mode="panel"]) { display: none; position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 20; }
     :host([mode="panel"][open]) { display: block; }
-    :host([mode="panel"]) .sheet { max-height: none; top: 0; bottom: 0; animation: unfold 200ms var(--kf-ease); border-radius: 16px; border: 1px solid transparent; }
+    :host([mode="panel"]) .sheet { max-height: none; top: 0; bottom: 0; animation: unfold 200ms var(--kf-ease); border-radius: var(--r-md); border: 1px solid transparent; }
     :host([mode="panel"]) .grip { display: none; }
     :host([mode="panel"]) .ft { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
     @keyframes unfold { from { transform: translateY(12px); opacity: 0.4; } }

+ 7 - 7
src/pages/report-card.js

@@ -34,7 +34,7 @@ export const CARD_CSS = css`
   /* 手机:整页「报告中心 · 类型」已写在标题区,卡上不再重复类型 / 全文状态,只留阶段·优先级·品类 */
   @media (max-width: 767px) { .rc .top .badge.type, .rc .top .full { display: none; } }
   .rc .top .fresh:has(~ .full) { order: 9; }
-  .rc .badge { display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 8px; border-radius: 6px;
+  .rc .badge { display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 8px; border-radius: var(--r-sm);
     font: 600 11px/1 var(--kf-font); letter-spacing: -0.01em; white-space: nowrap; border: 1px solid transparent; }
   /* 阶段色 S1–S5:白字压实色,逐色验证过 ≥ 4.5:1 */
   .rc .badge.stage { color: #fff; }
@@ -45,8 +45,8 @@ export const CARD_CSS = css`
   .rc .badge.cat { background: rgba(255,255,255,0.45); border-color: var(--kf-line); color: var(--kf-ink-2); font-weight: 500; }
   /* 优先级:阶段块右上角一枚 14px 小角标(实底 + 白字,颜色仍按 S/A/B) */
   .rc .tagstage { position: relative; display: inline-flex; }
-  .rc .pri { position: absolute; top: -5px; right: -5px; width: 14px; height: 14px; border-radius: 5px; display: grid; place-items: center;
-    font: 500 11px/1 var(--kf-font); color: #fff; letter-spacing: 0; border: 2px solid rgba(255,255,255,0.9); }
+  .rc .pri { position: absolute; top: -5px; right: -5px; width: 14px; height: 14px; border-radius: var(--r-sm); display: grid; place-items: center;
+    font: 500 11px/1 var(--kf-font); color: #fff; letter-spacing: 0; border: 1px solid rgba(255,255,255,0.9); }
   .rc .pri.p-S { background: var(--kf-s); } .rc .pri.p-A { background: var(--kf-a); } .rc .pri.p-B { background: var(--kf-b); }
   .rc .badge.status { background: rgba(255,255,255,0.5); border-color: var(--kf-line-strong); color: var(--kf-ink-2); }
   .rc .badge.status.s-approved { color: var(--kf-ok-text); } .rc .badge.status.s-rejected { color: var(--kf-danger-text); }
@@ -102,14 +102,14 @@ export const CARD_CSS = css`
   .rc .ring { width: 40px; height: 40px; flex: none; }
   .rc .ring text { font: 600 12px var(--kf-font-num); fill: var(--kf-ink); font-variant-numeric: tabular-nums; font-size: 12px; }
   .rc .thumb { display: grid; grid-template-columns: repeat(7, 1fr); grid-template-rows: 1fr auto; gap: 4px 4px; align-items: end; height: 48px; padding: 8px 8px 6px;
-    border-radius: 8px; background: linear-gradient(180deg, rgba(255,255,255,0.5), rgba(255,255,255,0.2)); border: 1px solid var(--kf-line); }
+    border-radius: var(--r-sm); background: linear-gradient(180deg, rgba(255,255,255,0.5), rgba(255,255,255,0.2)); border: 1px solid var(--kf-line); }
   .rc .thumb i { display: block; border-radius: 2px 2px 0 0; background: color-mix(in oklab, var(--kf-ink) 18%, transparent); min-height: 4px; }
   .rc .thumb .cap { grid-column: 1 / -1; display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--kf-ink-3); }
   .rc .thumb .dots { display: flex; gap: 4px; }
   .rc .thumb .dots b { width: 4px; height: 4px; border-radius: 50%; background: var(--kf-s3); }
   .rc .thumb img { grid-column: span 7; width: 100%; height: 100%; object-fit: cover; border-radius: 6px; }
   /* 引文块:不画彩色左边栏(反例 #2),用 4% 染色底 + 1px 描边表达「这是一段原文」 */
-  .rc .q { font-size: 11px; color: var(--kf-ink-2); line-height: 1.6; display: flex; gap: 8px; padding: 8px 10px; border-radius: 8px;
+  .rc .q { font-size: 11px; color: var(--kf-ink-2); line-height: 1.6; display: flex; gap: 8px; padding: 8px 10px; border-radius: var(--r-sm);
     background: color-mix(in srgb, var(--kf-ink) 4%, transparent); border: 1px solid color-mix(in srgb, var(--kf-ink) 8%, transparent); }
   .rc .q span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
     .rc .src { display: flex; align-items: center; gap: 6px; font-size: 11px; line-height: 1.4; color: var(--kf-ink-2); margin-top: auto; padding-top: 12px; border-top: 1px solid var(--kf-line); min-width: 0; flex-wrap: wrap; font-variant-numeric: tabular-nums; }
@@ -136,7 +136,7 @@ export const CARD_CSS = css`
     .rc .m > div.score-cell { grid-template-columns: minmax(0, 1fr); }
     .rc .m > div.score-cell .ring { justify-self: start; }
     .rc .q { font-size: 13px; line-height: 1.55; }
-    .rc .badge { height: 24px; padding: 0 8px; font-size: 11px; border-radius: 7px; }
+    .rc .badge { height: 24px; padding: 0 8px; font-size: 11px; border-radius: var(--r-sm); }
     .rc .src { display: flex; flex-direction: column; align-items: stretch; gap: 4px; font-size: 13px; line-height: 1.4; padding-top: 12px; }
     .rc .src .l1 { display: flex; align-items: center; gap: 6px; min-width: 0; }
     .rc .src .l2 { display: flex; align-items: center; gap: 6px; min-width: 0; color: var(--kf-ink-2); }
@@ -148,7 +148,7 @@ export const CARD_CSS = css`
   }
   /* 紧凑列表:一行一条,数字列等宽对齐 */
   .row { display: grid; grid-template-columns: 48px minmax(0, 1.5fr) 96px 88px minmax(0, 1fr) 80px; gap: 12px; align-items: center;
-    padding: 8px 12px; border-radius: 8px; color: var(--kf-ink-2); font-size: 13px; line-height: 1.5; cursor: pointer;
+    padding: 8px 12px; border-radius: var(--r-sm); color: var(--kf-ink-2); font-size: 13px; line-height: 1.5; cursor: pointer;
     transition: background var(--kf-dur) var(--kf-ease); }
   .row + .row { border-top: 1px solid var(--kf-line); }
   .row:hover { background: rgba(255,255,255,0.5); }

+ 3 - 3
src/pages/view-ledger.js

@@ -111,14 +111,14 @@ export class ViewLedger extends LitElement {
       .ledger-head h2 { font-size: 20px; font-weight: 600; }
       .ledger-head p { font-size: 13px; color: var(--kf-ink-2); }
       .ledger-head .sum { margin-left: 0; width: 100%; font-size: 13px; }
-      .filters { padding: 12px; border-radius: 16px; }
+      .filters { padding: 12px; border-radius: var(--r-md); }
       .frow { gap: 8px; }
       .frow .lbl { width: 44px; font-size: 13px; }
       .chips { gap: 8px; }
       .kf-chip { height: 36px; padding: 0 12px; font-size: 13px; }
       kf-table { display: none; }
       .mledger { display: grid; gap: 8px; }
-      .mledger li { display: grid; gap: 6px; padding: 12px 14px; min-height: 64px; border-radius: 16px; cursor: pointer;
+      .mledger li { display: grid; gap: 6px; padding: 12px 14px; min-height: 64px; border-radius: var(--r-md); cursor: pointer;
         border: 1px solid transparent;
         background: linear-gradient(rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0.62)) padding-box, var(--kf-edge) border-box;
         -webkit-backdrop-filter: blur(24px) saturate(180%); backdrop-filter: blur(24px) saturate(180%); box-shadow: var(--kf-shadow); }
@@ -145,7 +145,7 @@ export class ViewLedger extends LitElement {
     // 加载中:画出和真实台账同形的骨架(表头 + 8 行),数据回来高度不跳
     if (!db) return html`<div data-ledger-skel aria-busy="true" aria-label="正在读取台账">
       <div class="ledger-head"><div><h2>证据台账</h2><p><span class="kf-skel" style="display:inline-block;width:280px;height:13px;vertical-align:-2px"></span></p></div></div>
-      <div class="kf-glass is-panel" style="border-radius:16px;padding:8px 12px">
+      <div class="kf-glass is-panel" style="border-radius: var(--r-md);padding:8px 12px">
         <div class="skel-row head">${[0, 1, 2, 3, 4, 5, 6, 7, 8].map(() => html`<span class="kf-skel" style="height:11px"></span>`)}</div>
         ${[0, 1, 2, 3, 4, 5, 6, 7].map(() => html`<div class="skel-row">${[0, 1, 2, 3, 4, 5, 6, 7, 8].map(() => html`<span class="kf-skel" style="height:13px"></span>`)}</div>`)}
       </div>

+ 2 - 2
src/pages/view-members.js

@@ -37,7 +37,7 @@ export class ViewMembers extends LitElement {
     .gh .n { margin-left: auto; font-size: 11px; color: var(--kf-ink-3); letter-spacing: var(--ls-cn-small); }
     .list { list-style: none; margin: 0; padding: 0; display: grid; }
     .list li { display: grid; grid-template-columns: 40px minmax(96px, 1fr) 180px 80px 72px 72px 112px 80px; gap: 12px; align-items: center;
-      padding: 8px 12px; border-radius: 8px; font-size: 13px; line-height: 1.5; color: var(--kf-ink-2);
+      padding: 8px 12px; border-radius: var(--r-sm); font-size: 13px; line-height: 1.5; color: var(--kf-ink-2);
       font-variant-numeric: tabular-nums; transition: background var(--kf-dur) var(--kf-ease); }
     .list li + li { border-top: 1px solid var(--kf-line); }
     .list li:not(.head):hover { background: rgba(255,255,255,0.45); }
@@ -46,7 +46,7 @@ export class ViewMembers extends LitElement {
     .nm { font-weight: 600; color: var(--kf-ink); }
     .nm a { color: inherit; text-decoration: none; }
     .nm a:hover { color: var(--kf-accent); }
-    .me-tag { display: inline-block; font-size: 11px; line-height: 16px; color: var(--kf-accent-ink); border: 1px solid rgba(91, 91, 214, 0.30); border-radius: 4px; padding: 0 4px; margin-left: 6px; }
+    .me-tag { display: inline-block; font-size: 11px; line-height: 16px; color: var(--kf-accent-ink); border: 1px solid rgba(91, 91, 214, 0.30); border-radius: var(--r-sm); padding: 0 4px; margin-left: 6px; }
     .stuck { display: inline-flex; align-items: center; gap: 4px; color: var(--kf-s); font-weight: 600; }
     .ok { color: var(--kf-ok-text); }
     kf-bars { display: block; width: 100%; color: var(--kf-accent); }

+ 8 - 8
src/pages/view-pool.js

@@ -58,9 +58,9 @@ export class ViewPool extends LitElement {
     /* 筛选卡与卡片流放在同一个块容器里:sticky 才有参照,行盒也不会把块级子元素叠在一起 */
     .pool-body { display: block; }
     .toolbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
-    .toolbar input[type="search"] { height: 32px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--kf-line-strong); font: 13px var(--kf-font); min-width: 240px; background: rgba(255,255,255,0.5); transition: var(--kf-t); }
+    .toolbar input[type="search"] { height: 32px; padding: 0 12px; border-radius: var(--r-sm); border: 1px solid var(--kf-line-strong); font: 13px var(--kf-font); min-width: 240px; background: rgba(255,255,255,0.5); transition: var(--kf-t); }
     .toolbar input[type="search"]:focus { outline: none; border-color: var(--kf-focus); box-shadow: 0 0 0 2px rgba(91, 91, 214, 0.22); background: rgba(255,255,255,0.75); }
-    .seg { display: inline-flex; border: 1px solid var(--kf-line-strong); border-radius: 8px; overflow: hidden; background: rgba(255,255,255,0.5); }
+    .seg { display: inline-flex; border: 1px solid var(--kf-line-strong); border-radius: var(--r-sm); overflow: hidden; background: rgba(255,255,255,0.5); }
     .seg button { border: 0; background: transparent; padding: 0 12px; height: 30px; font: 500 11px var(--kf-font); color: var(--kf-ink-2); cursor: pointer; transition: background var(--kf-dur) var(--kf-ease); }
     .seg button[aria-pressed="true"] { background: var(--kf-ink); color: #fff; }
     .cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); gap: 16px; }
@@ -71,16 +71,16 @@ export class ViewPool extends LitElement {
     /* 手机工具条:桌面隐藏 */
     .pbar { display: none; }
     @media (max-width: 767px) {
-      .pbar { display: grid; grid-template-columns: 96px minmax(0, 1fr); grid-template-areas: "f m" "s s"; gap: 8px; padding: 8px; margin-bottom: 12px; border-radius: 16px; align-items: center; }
-      .pbar-btn { grid-area: f; appearance: none; -webkit-appearance: none; box-sizing: border-box; width: 100%; height: 44px; padding: 0; margin: 0; border: 1px solid transparent; border-radius: 12px; cursor: pointer;
+      .pbar { display: grid; grid-template-columns: 96px minmax(0, 1fr); grid-template-areas: "f m" "s s"; gap: 8px; padding: 8px; margin-bottom: 12px; border-radius: var(--r-md); align-items: center; }
+      .pbar-btn { grid-area: f; appearance: none; -webkit-appearance: none; box-sizing: border-box; width: 100%; height: 44px; padding: 0; margin: 0; border: 1px solid transparent; border-radius: var(--r-md); cursor: pointer;
         background: linear-gradient(rgba(255,255,255,0.72), rgba(255,255,255,0.72)) padding-box, var(--kf-edge-chip) border-box; color: var(--kf-ink);
         display: grid; grid-auto-flow: column; justify-content: center; align-items: center; gap: 4px; font: 600 16px/1 var(--kf-font); letter-spacing: var(--ls-cn-small); }
-      .pbar input[type="search"] { grid-area: m; min-width: 0; width: 100%; height: 44px; padding: 0 12px; border-radius: 12px; border: 1px solid var(--kf-line-strong); font: 400 14px var(--kf-font); background: rgba(255, 255, 255, 0.5); }
-      .pbar-more { grid-area: s; border-radius: 12px; background: rgba(255, 255, 255, 0.32); }
+      .pbar input[type="search"] { grid-area: m; min-width: 0; width: 100%; height: 44px; padding: 0 12px; border-radius: var(--r-md); border: 1px solid var(--kf-line-strong); font: 400 14px var(--kf-font); background: rgba(255, 255, 255, 0.5); }
+      .pbar-more { grid-area: s; border-radius: var(--r-md); background: rgba(255, 255, 255, 0.32); }
       .pbar-more > summary { list-style: none; display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 12px; font: 600 14px var(--kf-font); color: var(--kf-ink-2); cursor: pointer; }
       .pbar-more > summary::-webkit-details-marker { display: none; }
       .pbar-sorts { display: flex; gap: 6px; padding: 0 8px 8px; }
-      .pbar-sorts button { all: unset; box-sizing: border-box; flex: 1; height: 44px; display: grid; place-items: center; border-radius: 10px; font: 500 13px var(--kf-font); color: var(--kf-ink-2); background: rgba(255, 255, 255, 0.45); cursor: pointer; }
+      .pbar-sorts button { all: unset; box-sizing: border-box; flex: 1; height: 44px; display: grid; place-items: center; border-radius: var(--r-md); font: 500 13px var(--kf-font); color: var(--kf-ink-2); background: rgba(255, 255, 255, 0.45); cursor: pointer; }
       .pbar-sorts button[aria-pressed="true"] { background: var(--kf-ink); color: #fff; }
       /* 手机上原生筛选卡收起(桌面档里已隐藏的 .pbar 不在此列) */
       .filters { display: none; }
@@ -88,7 +88,7 @@ export class ViewPool extends LitElement {
     @media (min-width: 768px) and (max-width: 1023px) { .filters { position: static; } .cards { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); } }
     /* 手机:筛选卡不吸顶、搜索框占满一行,卡片单列 */
     @media (max-width: 767px) {
-      .filters { position: static; padding: 12px; border-radius: 16px; gap: 8px; }
+      .filters { position: static; padding: 12px; border-radius: var(--r-md); gap: 8px; }
       .frow .lbl { width: 44px; }
       .chips { gap: 8px; }
       .kf-chip { height: 36px; padding: 0 12px; font-size: 13px; }

+ 7 - 7
src/pages/view-report-type.js

@@ -48,7 +48,7 @@ export class ViewReportType extends LitElement {
     .tabs { display: flex; gap: 6px; flex-wrap: nowrap; margin: 0; max-width: min(52vw, 640px); overflow-x: auto; scrollbar-width: none; }
     .tabs::-webkit-scrollbar { display: none; }
     /* 类型切换 = 点缀层 chip(.55 + blur 12);当前项反白实底 */
-    .tabs a { display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px; border-radius: 6px; text-decoration: none;
+    .tabs a { display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px; border-radius: var(--r-sm); text-decoration: none;
       font-size: 13px; line-height: 1; font-weight: 500; color: var(--kf-ink-2); border: 1px solid transparent;
       background: linear-gradient(var(--kf-glass-chip), var(--kf-glass-chip)) padding-box, var(--kf-edge-chip) border-box;
       box-shadow: var(--kf-shadow-chip); transition: var(--kf-t); }
@@ -58,7 +58,7 @@ export class ViewReportType extends LitElement {
     .tabs a .n { font: 500 11px/1 var(--kf-font-num); color: var(--kf-ink-3); font-variant-numeric: tabular-nums; }
     .tabs a[aria-current="page"] .n { color: rgba(255,255,255,0.8); }
     .head { display: flex; align-items: center; gap: 12px; padding: 0; flex-wrap: wrap; margin-top: var(--kf-space-in); }
-    .head .ico { width: 40px; height: 40px; flex: none; border-radius: 10px; display: grid; place-items: center;
+    .head .ico { width: 40px; height: 40px; flex: none; border-radius: var(--r-md); display: grid; place-items: center;
       background: var(--kf-accent-soft); color: var(--kf-accent-ink); }
     .head .ico svg { stroke: var(--kf-accent-ink); }
     .head h2 { margin: 0; font-size: 20px; line-height: 1.3; font-weight: 600; color: var(--kf-ink); letter-spacing: -0.02em; text-box-trim: trim-both; text-box-edge: cap alphabetic; }
@@ -67,7 +67,7 @@ export class ViewReportType extends LitElement {
     .kpi { min-width: 112px; padding: 8px 12px; border-radius: var(--kf-radius-sm); display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; gap: 6px 10px; align-items: end;
       background: var(--kf-glass-card); -webkit-backdrop-filter: blur(var(--kf-glass-card-blur)); backdrop-filter: blur(var(--kf-glass-card-blur));
       box-shadow: var(--kf-glass-card-shadow); }
-    .kpi .ic { grid-row: span 2; width: 28px; height: 28px; border-radius: 8px; display: grid; place-items: center; color: var(--kf-accent-ink); background: rgba(91, 91, 214, 0.10); }
+    .kpi .ic { grid-row: span 2; width: 28px; height: 28px; border-radius: var(--r-sm); display: grid; place-items: center; color: var(--kf-accent-ink); background: rgba(91, 91, 214, 0.10); }
     .kpi b { font-size: 32px; font-weight: 600; line-height: 1; letter-spacing: var(--ls-cn-display); color: var(--gray-12); font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1;
       display: block; height: max-content; text-box-trim: trim-both; text-box-edge: cap alphabetic; }   /* v11b:flex 容器不修剪,见工作台同处注释 */
     /* 分母(/5、/10)只是说明,放小一号灰色,不和大数字抢;数字用 Inter(拉丁 / 数字字体栈) */
@@ -95,7 +95,7 @@ export class ViewReportType extends LitElement {
     .listhead { display: grid; grid-template-columns: 48px minmax(0, 1.5fr) 96px 88px minmax(0, 1fr) 80px; gap: 12px; padding: 8px 12px;
       font-size: 11px; line-height: 1.3; letter-spacing: var(--ls-cn-small); color: var(--kf-ink-3); font-weight: 500; border-bottom: 1px solid var(--kf-line); }
     .pager { display: flex; align-items: center; justify-content: center; gap: 4px; margin: 24px 0 8px; flex-wrap: wrap; }
-    .pager button { all: unset; cursor: pointer; min-width: 32px; height: 32px; padding: 0 8px; display: grid; place-items: center; border-radius: 8px;
+    .pager button { all: unset; cursor: pointer; min-width: 32px; height: 32px; padding: 0 8px; display: grid; place-items: center; border-radius: var(--r-sm);
       border: 1px solid transparent;
       background: linear-gradient(var(--kf-glass-chip), var(--kf-glass-chip)) padding-box, var(--kf-edge-chip) border-box;
       font: 600 13px var(--kf-font-num); color: var(--kf-ink-2); font-variant-numeric: tabular-nums; transition: var(--kf-t); }
@@ -116,10 +116,10 @@ export class ViewReportType extends LitElement {
 
       /* 标题区:图标 36 + 标题 17/600,四个数据并成一行紧凑条(不再四个 104px 宽卡片各带一个图标) */
       .head { flex-wrap: wrap; gap: 8px 12px; padding: 0 0 16px; }
-      .head .ico { width: 36px; height: 36px; border-radius: 11px; }
+      .head .ico { width: 36px; height: 36px; border-radius: var(--r-md); }
       .head h2 { font-size: 16px; font-weight: 600; }
       .kpis { margin-left: 0; width: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; padding: 8px 0;
-        border-radius: 16px; background: linear-gradient(var(--kf-glass-mid), var(--kf-glass-mid)) padding-box, var(--kf-edge) border-box; border: 1px solid transparent;
+        border-radius: var(--r-md); background: linear-gradient(var(--kf-glass-mid), var(--kf-glass-mid)) padding-box, var(--kf-edge) border-box; border: 1px solid transparent;
         -webkit-backdrop-filter: blur(24px) saturate(180%); backdrop-filter: blur(24px) saturate(180%); box-shadow: none; }
       .kpi { min-width: 0; padding: 0 4px 0 12px; display: grid; grid-template-columns: 1fr; gap: 0; border-left: 1px solid var(--kf-line); border-radius: 0; background: none; border: 0; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
       .kpi:first-child { border-left: 0; }
@@ -136,7 +136,7 @@ export class ViewReportType extends LitElement {
       .cards > kf-glass-card { width: 100%; }
 
       /* 紧凑列表:手机上收成两行(阶段 + 标题 / 引用·分 + 人 + 时间),不横滚 */
-      .listwrap { border-radius: 16px; }
+      .listwrap { border-radius: var(--r-md); }
       .listhead { display: none; }
       .row { grid-template-columns: 40px minmax(0, 1fr) auto; grid-template-areas: "s t x" "s w w"; row-gap: 2px; column-gap: 8px; padding: 12px 14px; min-height: 64px; font-size: 14px; box-sizing: border-box; }
       .row > :nth-child(1) { grid-area: s; align-self: start; }

+ 11 - 11
src/pages/view-report.js

@@ -80,14 +80,14 @@ export class ViewReport extends LitElement {
     .toc { position: sticky; top: 72px; z-index: 6; display: flex; gap: 4px; overflow-x: auto; padding: 6px; margin: 0 0 16px;
       border-radius: var(--kf-radius); }
     .dgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 8px; margin-top: 8px; }
-    a.d { display: grid; grid-template-columns: 32px minmax(0,1fr); gap: 2px 8px; padding: 12px; border-radius: 8px; text-decoration: none;
+    a.d { display: grid; grid-template-columns: 32px minmax(0,1fr); gap: 2px 8px; padding: 12px; border-radius: var(--r-sm); text-decoration: none;
       background: rgba(255,255,255,0.4); border: 1px solid var(--kf-line); color: inherit; transition: var(--kf-t); }
     a.d:hover { background: rgba(255,255,255,0.7); box-shadow: var(--kf-shadow-chip); }
     a.d .dn { font: 600 11px/1.4 var(--kf-font-num); color: var(--kf-accent-ink); grid-row: span 2; padding-top: 2px; font-variant-numeric: tabular-nums; }
     a.d .dt { font-size: 13px; font-weight: 600; color: var(--kf-ink); }
     a.d .ds { font-size: 11px; color: var(--kf-ink-2); grid-column: 2; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
     .toc a.jump, aside.rail a.jump { flex: none; font-size: 13px; line-height: 1; color: var(--kf-ink-2); text-decoration: none;
-      padding: 6px 10px; border-radius: 6px; display: inline-block; transition: background var(--kf-dur) var(--kf-ease); }
+      padding: 6px 10px; border-radius: var(--r-sm); display: inline-block; transition: background var(--kf-dur) var(--kf-ease); }
     .toc a.jump:hover, aside.rail a.jump:hover { background: rgba(255,255,255,0.6); color: var(--kf-ink); }
     .toc a.jump[aria-current="true"] { background: var(--kf-ink); color: #fff; }
     aside.rail ol li + li { margin-top: 2px; }
@@ -99,12 +99,12 @@ export class ViewReport extends LitElement {
     .col, .main-col { display: block; min-width: 0; }
     article.ch { padding: var(--kf-space-card) var(--kf-space-card-gap); margin-bottom: var(--kf-space-card); scroll-margin-top: 144px; }
     .ch-h { display: flex; gap: 12px; align-items: baseline; }
-    .ch-no { font-family: var(--kf-font-num); font-size: 11px; line-height: 20px; color: var(--kf-accent-ink); border: 1px solid rgba(91, 91, 214, 0.30); border-radius: 6px; padding: 0 6px; font-variant-numeric: tabular-nums; }
+    .ch-no { font-family: var(--kf-font-num); font-size: 11px; line-height: 20px; color: var(--kf-accent-ink); border: 1px solid rgba(91, 91, 214, 0.30); border-radius: var(--r-sm); padding: 0 6px; font-variant-numeric: tabular-nums; }
     .ch-h h2 { margin: 0; font-size: 20px; line-height: 1.3; font-weight: 600; color: var(--kf-ink); letter-spacing: -0.01em; }
     .en { font-size: 11px; letter-spacing: var(--ls-cn-small); color: var(--kf-ink-3); font-weight: 600; text-transform: uppercase; }
     /* 摘要块:6% 染色底 + 1px 同色半透明描边(v11 反例 #2:不用 3px 彩色左边栏) */
     .lead { margin: 12px 0 16px; padding: 12px 16px; background: color-mix(in srgb, var(--kf-accent) 6%, transparent); font-size: 13px; color: var(--kf-ink-2);
-      line-height: var(--lh-body); border-radius: 10px; box-shadow: 0 0 0 1px color-mix(in srgb, var(--kf-accent) 16%, transparent); }
+      line-height: var(--lh-body); border-radius: var(--r-md); box-shadow: 0 0 0 1px color-mix(in srgb, var(--kf-accent) 16%, transparent); }
     .lead b { color: var(--kf-accent-ink); font-weight: 600; }
     .sec { padding: 12px 0; border-top: 1px solid var(--kf-line); }
     .sec:first-of-type { border-top: 0; }
@@ -112,7 +112,7 @@ export class ViewReport extends LitElement {
     .sec h4 .no { font-family: var(--kf-font-num); font-size: 11px; color: var(--kf-ink-3); }
     p.para { margin: 0 0 12px; font-size: 14px; line-height: 1.85; color: var(--kf-ink-2); max-width: 72ch; }
     .kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(152px, 1fr)); gap: 12px; }
-    .tbl-wrap { overflow-x: auto; border: 1px solid var(--kf-line); border-radius: 10px; }
+    .tbl-wrap { overflow-x: auto; border: 1px solid var(--kf-line); border-radius: var(--r-md); }
     table.rt { width: 100%; border-collapse: collapse; font-size: 13px; }
     .rt th { background: rgba(240,244,252,0.7); text-align: left; padding: 8px 12px; color: var(--kf-ink-3); font-weight: 600; font-size: 11px; letter-spacing: var(--ls-cn-small); border-bottom: 1px solid var(--kf-line); white-space: nowrap; }
     .rt td { padding: 8px 12px; border-bottom: 1px solid var(--kf-line); vertical-align: middle; color: var(--kf-ink-2); font-variant-numeric: tabular-nums; }
@@ -120,18 +120,18 @@ export class ViewReport extends LitElement {
     .rt .k { color: var(--kf-ink); font-weight: 600; }
     .funnel { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
     .funnel li { display: grid; grid-template-columns: 44px minmax(0, 1fr) 120px; gap: 10px; align-items: center; font-size: 13px; }
-    .bar { height: 8px; border-radius: 999px; background: rgba(20,36,70,0.07); overflow: hidden; }
+    .bar { height: 8px; border-radius: var(--r-sm); background: rgba(20,36,70,0.07); overflow: hidden; }
     .bar i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--kf-s1), var(--kf-s2)); }
-    .finding { padding: 12px 16px; border-radius: 8px; border: 1px solid var(--kf-line); background: rgba(255,255,255,0.45); margin-bottom: 12px; }
+    .finding { padding: 12px 16px; border-radius: var(--r-sm); border: 1px solid var(--kf-line); background: rgba(255,255,255,0.45); margin-bottom: 12px; }
     .finding h5 { margin: 0; font-size: 14px; line-height: 1.5; font-weight: 600; color: var(--kf-ink); }
     .finding p { margin: 4px 0 8px; font-size: 13px; line-height: 1.6; color: var(--kf-ink-2); }
     .ev { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; font-size: 11px; color: var(--kf-ink-3); }
     .ev b { color: var(--kf-ink); font-variant-numeric: tabular-nums; }
-    .anchor { display: inline-flex; gap: 4px; align-items: center; height: 26px; padding: 0 10px; border-radius: 6px; border: 1px solid rgba(91, 91, 214, 0.22);
+    .anchor { display: inline-flex; gap: 4px; align-items: center; height: 26px; padding: 0 10px; border-radius: var(--r-sm); border: 1px solid rgba(91, 91, 214, 0.22);
       background: rgba(91, 91, 214, 0.10); color: var(--kf-accent-ink); font: 600 11px/1 var(--kf-font); cursor: pointer; transition: var(--kf-t); }
     .anchor:hover { background: rgba(91, 91, 214, 0.10); border-color: rgba(91, 91, 214, 0.45); }
     .two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
-    .two > div { padding: 12px; border-radius: 8px; border: 1px solid var(--kf-line); font-size: 13px; line-height: 1.6; }
+    .two > div { padding: 12px; border-radius: var(--r-sm); border: 1px solid var(--kf-line); font-size: 13px; line-height: 1.6; }
     .two .yes { background: rgba(31,107,69,0.06); border-color: rgba(31,107,69,0.25); }
     .two .no { background: rgba(164,36,28,0.05); border-color: rgba(164,36,28,0.22); }
     .two ul { margin: 6px 0 0; padding-left: 18px; }
@@ -143,7 +143,7 @@ export class ViewReport extends LitElement {
     .rail ol a { color: var(--kf-ink); text-decoration: none; border-bottom: 1px dashed var(--kf-line-strong); }
     .rail .stat { display: flex; justify-content: space-between; font-size: 13px; padding: 3px 0; color: var(--kf-ink-2); }
     .chain { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
-    .chain div { display: grid; justify-items: center; gap: 4px; padding: 8px 4px; border-radius: 8px; background: rgba(255,255,255,0.45); border: 1px solid var(--kf-line); }
+    .chain div { display: grid; justify-items: center; gap: 4px; padding: 8px 4px; border-radius: var(--r-sm); background: rgba(255,255,255,0.45); border: 1px solid var(--kf-line); }
     .chain b { font: 600 14px/1.1 var(--kf-font-num); color: var(--kf-ink); font-variant-numeric: tabular-nums; }
     .chain i { font-style: normal; font-size: 11px; line-height: 1.3; color: var(--kf-accent-ink); text-align: center; }
     .rail .stat b { color: var(--kf-ink); font-variant-numeric: tabular-nums; }
@@ -151,7 +151,7 @@ export class ViewReport extends LitElement {
     @media (max-width: 1100px) { .layout { grid-template-columns: 1fr; } aside.rail { position: static; } }
     /* 手机(任务书 1.3 / 2.4):阅读稿单栏;章节导航吸在顶栏下、左右通到屏幕边;封面标题 26→20;来源收成两行 */
     @media (max-width: 767px) {
-      .toc { top: calc(80px + env(safe-area-inset-top, 0px)); margin: 0 -16px 12px; border-radius: 0 0 16px 16px; padding: 6px 12px; scrollbar-width: none; }
+      .toc { top: calc(80px + env(safe-area-inset-top, 0px)); margin: 0 -16px 12px; border-radius: 0 0 var(--r-md) var(--r-md); padding: 6px 12px; scrollbar-width: none; }
       .toc::-webkit-scrollbar { display: none; }
       .toc a.jump { font-size: 13px; padding: 10px 12px; }
       .cover { padding: 16px; }

+ 2 - 2
src/pages/view-reports.js

@@ -68,7 +68,7 @@ export class ViewReports extends LitElement {
     .t .src .who { font-size: 11px; }
     .t .src .tm { margin-left: 0; }
     .t .h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; row-gap: 4px; }
-    .t .ico { width: 32px; height: 32px; border-radius: 10px; display: grid; place-items: center; color: var(--kf-accent-ink);
+    .t .ico { width: 32px; height: 32px; border-radius: var(--r-md); display: grid; place-items: center; color: var(--kf-accent-ink);
       background: var(--kf-accent-soft); flex: none; }
     /* 长标签不截断(5.6):两行折行,不再 nowrap + 省略号 */
     .t h3 { margin: 0; font-size: 14px; line-height: 1.35; font-weight: 600; color: var(--kf-ink); letter-spacing: var(--ls-cn-display);
@@ -95,7 +95,7 @@ export class ViewReports extends LitElement {
     .listhead { display: grid; grid-template-columns: 48px minmax(0, 1.5fr) 96px 88px minmax(0, 1fr) 80px; gap: 12px; padding: 8px 12px;
       font-size: 11px; line-height: 1.3; letter-spacing: var(--ls-cn-small); font-weight: 500; color: var(--kf-ink-3); border-bottom: 1px solid var(--kf-line); }
     .pager { display: flex; align-items: center; justify-content: center; gap: 4px; margin: 24px 0 8px; }
-    .pager button { all: unset; cursor: pointer; min-width: 32px; height: 32px; padding: 0 8px; display: grid; place-items: center; border-radius: 10px;
+    .pager button { all: unset; cursor: pointer; min-width: 32px; height: 32px; padding: 0 8px; display: grid; place-items: center; border-radius: var(--r-md);
       border: 1px solid transparent;
       background: linear-gradient(var(--kf-glass-chip), var(--kf-glass-chip)) padding-box, var(--kf-edge-chip) border-box;
       font-size: 13px; font-weight: 500; color: var(--kf-ink-2); font-variant-numeric: tabular-nums; transition: var(--kf-t); }

+ 4 - 4
src/pages/view-stages.js

@@ -50,7 +50,7 @@ export class ViewStages extends LitElement {
     .ov .b { grid-column: 1; } .ov kf-ring { grid-column: 2; grid-row: 1; }   /* 环与阶段徽标同一行右端 */
     .ov .n, .ov .mix { grid-column: 1 / -1; }
     /* 阶段色 S1–S5:和卡片徽标、筛选色块同一套 */
-    .ov .b { justify-self: start; font: 600 11px/1 var(--kf-font); letter-spacing: 0.02em; color: #fff; padding: 4px 6px; border-radius: 5px; text-box-trim: trim-both; text-box-edge: cap alphabetic; }
+    .ov .b { justify-self: start; font: 600 11px/1 var(--kf-font); letter-spacing: 0.02em; color: #fff; padding: 4px 6px; border-radius: var(--r-sm); text-box-trim: trim-both; text-box-edge: cap alphabetic; }
     .ov .b { justify-self: start; }
     .b.blue { background: var(--kf-s1); } .b.violet { background: var(--kf-s2); } .b.teal { background: var(--kf-s3); } .b.amber { background: var(--kf-s4); } .b.rose { background: var(--kf-s5); }
     /* 份数:大数字 + 小单位(1.2),后面跟「人 / 证据」两个小数字 */
@@ -60,9 +60,9 @@ export class ViewStages extends LitElement {
     .ov .n span { display: inline-flex; align-items: center; gap: 4px; margin-left: var(--kf-space-in); font-size: 11px; font-weight: 500; color: var(--kf-ink-3); font-variant-numeric: tabular-nums; }
     .ov .n .ev { margin-left: var(--kf-space-in); }
     /* 占比条:4px、圆角 = 高度/2、单色(原来是一条蓝→紫的装饰渐变) */
-    .ov .bar { height: 4px; border-radius: 2px; background: rgba(16, 24, 40, 0.07); overflow: hidden; }
-    .ov .bar i { display: block; height: 100%; border-radius: 2px; background: var(--tone, var(--kf-ink-3)); }
-    .ov .mix { display: flex; gap: 2px; height: 3px; border-radius: 2px; overflow: hidden; }
+    .ov .bar { height: 4px; border-radius: 999px; background: rgba(16, 24, 40, 0.07); overflow: hidden; }
+    .ov .bar i { display: block; height: 100%; border-radius: 999px; background: var(--tone, var(--kf-ink-3)); }
+    .ov .mix { display: flex; gap: 2px; height: 3px; border-radius: 999px; overflow: hidden; }
     .ov .mix i { display: block; height: 100%; }
     .overview > .kf-card[aria-current="true"] { box-shadow: var(--kf-shadow-lift); outline: 2px solid var(--kf-focus); outline-offset: 1px; }
     .tool { display: flex; gap: 8px; align-items: center; margin: var(--kf-space-section) 0 var(--kf-space-in); flex-wrap: wrap; }

+ 5 - 5
src/pages/view-workbench.js

@@ -53,7 +53,7 @@ export class ViewWorkbench extends LitElement {
     .who .n div { text-align: right; }
     .who .n b { display: block; font-size: 20px; font-weight: 600; line-height: 1; letter-spacing: var(--ls-cn-display); color: var(--gray-12); font-variant-numeric: tabular-nums; text-box-trim: trim-both; text-box-edge: cap alphabetic; }
     .who .n span { font-size: 11px; font-weight: 500; line-height: 1.4; letter-spacing: var(--ls-cn-small); color: var(--kf-ink-3); }
-    .avatar { width: 44px; height: 44px; border-radius: 10px; display: grid; place-items: center; font-size: 20px; font-weight: 600; color: #fff;
+    .avatar { width: 44px; height: 44px; border-radius: var(--r-md); display: grid; place-items: center; font-size: 20px; font-weight: 600; color: #fff;
       background: var(--kf-accent); flex: none; }
     .hd h3 { font-size: 16px; line-height: var(--lh-title); font-weight: 600; color: var(--kf-ink); letter-spacing: var(--ls-cn-display); }
     .hd .go { margin-left: auto; font-variant-numeric: tabular-nums; }
@@ -71,10 +71,10 @@ export class ViewWorkbench extends LitElement {
     .kpi kf-spark { grid-area: spark; color: var(--kf-accent); align-self: end; margin-bottom: 3px; }
     /* 阶段条:五格一格一句「S1 · 3 份」,徽标 + 数值同行 */
     .stagebar { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--kf-space-in); }
-    .stg { padding: var(--kf-space-in); border-radius: 10px; background: var(--kf-fill); border: 1px solid var(--kf-line);
+    .stg { padding: var(--kf-space-in); border-radius: var(--r-md); background: var(--kf-fill); border: 1px solid var(--kf-line);
       display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 4px 8px; min-width: 0; }
     .stg kf-ring { grid-row: 1 / 3; grid-column: 3; color: var(--tone, var(--kf-accent)); }
-    .stg .b { font: 600 11px/1 var(--kf-font); color: #fff; padding: 4px 6px; border-radius: 5px; letter-spacing: 0.02em; text-box-trim: trim-both; text-box-edge: cap alphabetic; }
+    .stg .b { font: 600 11px/1 var(--kf-font); color: #fff; padding: 4px 6px; border-radius: var(--r-sm); letter-spacing: 0.02em; text-box-trim: trim-both; text-box-edge: cap alphabetic; }
     .stg .b.blue { background: var(--kf-s1); } .stg .b.violet { background: var(--kf-s2); } .stg .b.teal { background: var(--kf-s3); }
     .stg .b.amber { background: var(--kf-s4); } .stg .b.rose { background: var(--kf-s5); }
     .stg .n { justify-self: end; font-size: 16px; font-weight: 600; line-height: 1; letter-spacing: var(--ls-cn-display); color: var(--gray-12);
@@ -110,7 +110,7 @@ export class ViewWorkbench extends LitElement {
     /* 虚线占位(v11b 4.2):高度 = 内容(一行 18px + 上下 10px)≈ 38px,不再撑到 72px / 半张卡;
        卡片本身 align-items: start,内容多高卡就多高,不留「撑高留白」。 */
     .empty { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; padding: 10px 12px; color: var(--kf-ink-3); font-size: 13px; line-height: 18px;
-      border: 1px dashed color-mix(in srgb, var(--kf-ink-3) 24%, transparent); border-radius: 10px; }
+      border: 1px dashed color-mix(in srgb, var(--kf-ink-3) 24%, transparent); border-radius: var(--r-md); }
     .empty .go { margin-left: auto; }
     .stagebar { margin-top: var(--kf-space-in); }
     .latest { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--kf-space-card-gap); align-items: start; margin-top: var(--kf-space-in); }
@@ -131,7 +131,7 @@ export class ViewWorkbench extends LitElement {
       .go { min-width: 44px; justify-content: center; padding: 0 6px; }
       .stalled li { flex-wrap: wrap; }
       .foot-links { display: flex; gap: 8px; margin-top: var(--kf-space-card); }
-      .foot-links a { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px; border-radius: 12px; font-size: 14px; font-weight: 600;
+      .foot-links a { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px; border-radius: var(--r-md); font-size: 14px; font-weight: 600;
         color: var(--kf-accent-ink); text-decoration: none; border: 1px solid transparent;
         background: linear-gradient(var(--kf-glass-chip), var(--kf-glass-chip)) padding-box, var(--kf-edge-chip) border-box; }
     }

+ 42 - 26
src/styles/tokens.js

@@ -186,19 +186,24 @@ export const TOKENS_CSS = `:root, :host {
   /* 间距 4pt 栅格(任务书 2.8) */
   --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-6: 24px; --space-8: 32px;
 
-  /* 圆角纪律(任务书 2.7):卡片 16 / 小部件 10 / badge 6 / 按钮 10;禁 ≥24px */
-  --kf-radius-btn: 10px;
-  --kf-radius: 16px;
-  --kf-radius-sm: 10px;
-  --kf-radius-badge: 6px;
-  --kf-radius-lg: 16px;
+  /* 圆角纪律(v12 P0):全站只允许三档 —— 8 / 12 / 20。0 只留给分割线这类非容器。
+     由 verify-visual-v12 按 computed border-radius 实测(四角全量、跨 shadow),出现第四种就判失败。
+     旧的按钮 10 / badge 6 档已并入 8:6px 在 28px 高的 chip 上肉眼看得出比 8px 方,两档并排就是「不齐」。 */
+  --r-sm: 8px;   /* chip、小按钮、输入框、标签 */
+  --r-md: 12px;  /* 卡片、面板、抽屉内块 */
+  --r-lg: 20px;  /* 浮层、大卡、模态 */
+  --kf-radius-btn: var(--r-sm);
+  --kf-radius: var(--r-md);
+  --kf-radius-sm: var(--r-sm);
+  --kf-radius-badge: var(--r-sm);
+  --kf-radius-lg: var(--r-lg);
   --kf-gap: 16px;
 
 
   @media (max-width: 767px) {
-    --kf-radius: 16px;
-    --kf-radius-sm: 10px;
-    --kf-radius-btn: 10px;
+    --kf-radius: var(--r-md);
+    --kf-radius-sm: var(--r-sm);
+    --kf-radius-btn: var(--r-sm);
     --kf-touch: 44px;
   }
 
@@ -250,6 +255,16 @@ button, a, [role="button"], summary { touch-action: manipulation; }
 
 html.kf-drawer-open, html.kf-drawer-open body { overflow: hidden; }
 
+/* ============ v12 P0:原生控件兜底 ============
+   浏览器默认外观兜底:替换元素(input / select / textarea)不吃继承来的字族,会退回 Times / 灰底 / 2px 浮雕边。
+   这里统一清掉外观与默认字族;**具体的底色 / 边框 / 圆角由各处控件样式显式给**(验收脚本要求显式覆盖)。 */
+input, select, textarea { appearance: none; -webkit-appearance: none; font-family: inherit; font-size: inherit; color: var(--kf-ink); margin: 0; }
+select { background-image: none; }
+input::-webkit-search-cancel-button { -webkit-appearance: none; }
+button { font-family: inherit; }
+summary { list-style: none; }
+summary::-webkit-details-marker { display: none; }
+
 /* ============ 玻璃基元:一层玻璃 ============
    两层背景(浮层):白面(padding-box)+ 135° 发丝边(border-box,只露 1px)。
    v11 板块六:浮层(侧栏 / 顶栏 / Tab / 抽屉 / 弹层)保留玻璃;内容卡(.kf-card)减薄 ——
@@ -357,29 +372,30 @@ summary:focus:not(:focus-visible), [tabindex]:focus:not(:focus-visible) { outlin
 }
 .kf-btn:active { transform: scale(0.985); transition: transform 80ms cubic-bezier(0.4, 0, 0.2, 1); }
 .kf-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
+/* 按钮三形态(v12 P0):
+   primary   实底、无边框、白字
+   secondary 透明底 + 1px 描边(.14 白)+ 次级字色(= .kf-btn 的默认形态,筛选 chip 也用它)
+   ghost     无底无框,只在 hover / active 给背景 */
 .kf-btn.primary { background: var(--kf-accent); border-color: var(--kf-accent); color: #fff; box-shadow: var(--shadow-1); }
 .kf-btn.primary:hover { background: var(--kf-accent-strong); }
-.kf-btn.ghost { background: transparent; border-color: transparent; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
-.kf-btn.ghost:hover { background: var(--kf-fill); }
+.kf-btn.secondary, .kf-btn { background: transparent; border-color: rgba(255, 255, 255, 0.14); box-shadow: none; color: var(--kf-ink-2);
+  -webkit-backdrop-filter: none; backdrop-filter: none; }
+.kf-btn.secondary:hover { background: rgba(255, 255, 255, 0.55); border-color: rgba(255, 255, 255, 0.55); color: var(--kf-ink); }
+.kf-btn.primary { box-shadow: var(--shadow-1); }
+.kf-btn.ghost { background: transparent; border-color: transparent; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; color: var(--kf-ink-2); }
+.kf-btn.ghost:hover { background: rgba(24, 24, 27, 0.06); color: var(--kf-ink); }
 .kf-btn.danger { color: var(--kf-danger); border-color: rgba(154,31,24,0.3); }
 
 .kf-chip {
   display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; height: 28px; padding: 0 10px;
-  border-radius: 6px; border: 1px solid transparent;
-  background:
-    linear-gradient(var(--kf-glass-chip), var(--kf-glass-chip)) padding-box,
-    var(--kf-edge-chip) border-box;
-  box-shadow: var(--kf-shadow-chip);
-  font: 500 13px/1 var(--kf-font); color: var(--kf-ink); cursor: pointer;
+  border-radius: var(--r-sm); border: 1px solid rgba(255, 255, 255, 0.14);
+  background: transparent;
+  font: 500 13px/1 var(--kf-font); color: var(--kf-ink-2); cursor: pointer;
   text-box-trim: trim-both; text-box-edge: cap alphabetic;
   transition: var(--kf-t);
 }
-.kf-chip:hover {
-  background:
-    linear-gradient(var(--kf-glass-chip-hover), var(--kf-glass-chip-hover)) padding-box,
-    var(--kf-edge-chip-hover) border-box;
-}
-.kf-chip[aria-pressed="true"] { background: var(--kf-ink); color: #fff; border-color: var(--kf-ink); }
+.kf-chip:hover { background: rgba(255, 255, 255, 0.55); border-color: rgba(255, 255, 255, 0.55); color: var(--kf-ink); }
+.kf-chip[aria-pressed="true"], .kf-chip[aria-pressed="true"]:hover { background: var(--kf-ink); color: #fff; border-color: var(--kf-ink); }
 .kf-chip .n { font-variant-numeric: tabular-nums; }   /* 数字不降透明度:v8 实测 .8 时部分 11.5px 数字压到 4.5 以下 */
 .kf-chip:active { transform: scale(0.985); transition: transform 80ms cubic-bezier(0.4, 0, 0.2, 1); }
 
@@ -426,7 +442,7 @@ svg.i { flex: none; vertical-align: -0.125em; }
 
 /* 骨架屏(v10 任务书 2.9):灰阶 shimmer,1.4s */
 .kf-skel {
-  position: relative; overflow: hidden; border-radius: 6px;
+  position: relative; overflow: hidden; border-radius: var(--r-sm);
   background: linear-gradient(90deg, rgba(0, 0, 0, 0.05) 25%, rgba(0, 0, 0, 0.03) 37%, rgba(0, 0, 0, 0.05) 63%);
   background-size: 400% 100%;
   animation: shimmer 1.4s ease-in-out infinite;
@@ -473,8 +489,8 @@ svg.i { flex: none; vertical-align: -0.125em; }
 .kv .v { order: 2; font-variant-numeric: tabular-nums; color: var(--kf-ink); }
 /* 空态 / 错误态(v11 板块八):空态保留卡片框,只换内容;错误态 6% 染色 + 1px 同色半透明描边,不用红大块 */
 .empty { display: grid; place-items: center; gap: 8px; min-height: 64px; padding: 10px 12px; box-sizing: border-box; color: var(--kf-ink-3); font-size: 13px;
-  border: 1px dashed color-mix(in srgb, var(--kf-ink-3) 24%, transparent); border-radius: 10px; }
-.alert { border-left: none; background: color-mix(in srgb, #E5484D 6%, rgba(255, 255, 255, 0.72)); border-radius: 10px;
+  border: 1px dashed color-mix(in srgb, var(--kf-ink-3) 24%, transparent); border-radius: var(--r-sm); }
+.alert { border-left: none; background: color-mix(in srgb, #E5484D 6%, rgba(255, 255, 255, 0.72)); border-radius: var(--r-sm);
   padding: 12px 14px; font-size: 13px; line-height: 1.6; box-shadow: var(--elev-1), 0 0 0 1px color-mix(in srgb, #E5484D 16%, transparent); }
 
 @media (prefers-reduced-motion: reduce) {