Browse Source

feat(v12-P1): 机会卡池筛选栏整块化(分组竖线 + 排序分段 + 搜索框同行等高)

FmodeCode 5 ngày trước cách đây
mục cha
commit
e94becea8e
4 tập tin đã thay đổi với 1240 bổ sung và 67 xóa
  1. 1143 0
      docs/v12-after-p1.json
  2. 42 24
      scripts/verify-visual-v12.mjs
  3. 4 4
      src/pages/card-toolbar.js
  4. 51 39
      src/pages/view-pool.js

+ 1143 - 0
docs/v12-after-p1.json

@@ -0,0 +1,1143 @@
+{
+  "tag": "before",
+  "at": "2026-10-30T06:01:04.167Z",
+  "pages": [
+    {
+      "page": "/pool",
+      "radii": {
+        "0": 1624,
+        "8": 372,
+        "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.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "候选4"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 71,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "已立项3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 71,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "已否决2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 57,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "S 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 58,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "A 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 57,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "B 级3"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 48,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "S11"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "S21"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 51,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "S34"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 51,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "S42"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 50,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "S51"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "拌面5"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "汤面2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "杯面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "炒面1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "陈静2"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "李娜1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "刘洋1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "孙悦1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "王芳1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "张伟1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "赵磊1"
+        },
+        {
+          "tag": "button.kf-chip",
+          "w": 59,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "reasons": [],
+          "text": "周涛1"
+        },
+        {
+          "tag": "button",
+          "w": 111,
+          "h": 28,
+          "bg": "rgb(24, 24, 27)",
+          "bw": 0,
+          "r": "0px",
+          "font": "12px",
+          "reasons": [],
+          "text": "优先级 S→A→B"
+        },
+        {
+          "tag": "button",
+          "w": 112,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "12px",
+          "reasons": [],
+          "text": "综合评分 高→低"
+        },
+        {
+          "tag": "button",
+          "w": 112,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "12px",
+          "reasons": [],
+          "text": "证据强度 高→低"
+        },
+        {
+          "tag": "button",
+          "w": 73,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "12px",
+          "reasons": [],
+          "text": "最新上传"
+        },
+        {
+          "tag": "button",
+          "w": 73,
+          "h": 28,
+          "bg": "rgba(0, 0, 0, 0)",
+          "bw": 0,
+          "r": "0px",
+          "font": "12px",
+          "reasons": [],
+          "text": "分歧最大"
+        },
+        {
+          "tag": "input",
+          "w": 240,
+          "h": 28,
+          "bg": "rgba(255, 255, 255, 0.5)",
+          "bw": 1,
+          "r": "8px",
+          "font": "12px",
+          "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": 185,
+        "12": 34,
+        "13": 54,
+        "14": 7,
+        "16": 11,
+        "20": 29
+      },
+      "rows": [
+        {
+          "container": "div.shell",
+          "top": 0,
+          "n": 2,
+          "spread": 876,
+          "heights": [
+            900,
+            1776
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 508,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            368,
+            368,
+            368
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 892,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            410,
+            410,
+            410
+          ]
+        },
+        {
+          "container": "div.cards.kf-enter",
+          "top": 1320,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            410,
+            410,
+            410
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 668,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 688,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 1072,
+          "n": 3,
+          "spread": 0,
+          "heights": [
+            42,
+            42,
+            42
+          ]
+        },
+        {
+          "container": "div.nums",
+          "top": 1500,
+          "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": 1776,
+      "lastContentBottom": 0,
+      "filterLayout": {
+        "container": false,
+        "filtersInsideToolbar": false,
+        "seg": false,
+        "segGap": "",
+        "segBtnHeights": [],
+        "chipHeights": [],
+        "chipFonts": [],
+        "searchH": null,
+        "bottomDelta": null,
+        "chipBottomDelta": null,
+        "segBorder": []
+      },
+      "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": "容器圆角(≤6px 的量条/色点不计)4:0px×1624、8px×372、12px×112、circlepx×4"
+    },
+    {
+      "name": "原生外观控件 = 0",
+      "ok": true,
+      "detail": "控件总数 67,原生外观 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": "6 档:11×185 / 12×34 / 13×54 / 14×7 / 16×11 / 20×29"
+    },
+    {
+      "name": "同排卡片高度差 ≤ 2px",
+      "ok": false,
+      "detail": "测了 8 行,超差 1\n    /pool div.shell n=2 极差 876px [900,1776]"
+    },
+    {
+      "name": "卡内连续空白 ≤ 24px",
+      "ok": true,
+      "detail": "超 24px 的位置 0"
+    },
+    {
+      "name": "可点元素 hover 反馈",
+      "ok": false,
+      "detail": "可点 50,无反馈 50\n    /pool a「工作台Workbench」\n    /pool a「机会卡池Opportun」\n    /pool a「五阶段产出Stages 」\n    /pool a「分析报告Reports」\n    /pool a「证据台账Ledger」\n    /pool a「成员Members\n  」\n    /pool button.refresh.kf-btn「刷新」\n    /pool button.kf-chip「候选4」\n    /pool button.kf-chip「已立项3」\n    /pool button.kf-chip「已否决2」\n    /pool button.kf-chip「S 级3」\n    /pool button.kf-chip「A 级3」"
+    },
+    {
+      "name": "页面底部空白 ≤ 120px",
+      "ok": false,
+      "detail": "/pool 1776px"
+    },
+    {
+      "name": "P1 筛选栏:一个容器 + 分段排序 + 与搜索框等高底对齐",
+      "ok": false,
+      "detail": "容器 false,filters 在内 false,seg gap= 按钮高[],chip 高[] 字号[],搜索框高 null,与 chip 行底边差 nullpx,与容器底边差 nullpx"
+    },
+    {
+      "name": "P3 工作台两栏等高(差 ≤ 2px)且左卡无 > 32px 连续空白",
+      "ok": false,
+      "detail": "未量 /"
+    }
+  ],
+  "errors": []
+}

+ 42 - 24
scripts/verify-visual-v12.mjs

@@ -24,7 +24,7 @@
  * 注意(验收脚本的老坑,见 memory kf-verify-browser-quirks):
  *   - 视图异步挂载:goto 后等 kf-app → view-* 的 shadowRoot 有子节点,再等 300ms;
  *   - 跨 shadow 的可见性要沿 parentElement → getRootNode().host 一路走;
- *   - hover 用 elementFromPoint 在已知坐标上派发,不用 mouse.move 后的轮询。
+ *   - hover 必须用真实指针(page.mouse.move):合成 pointerover / mouseover 事件不会让 :hover 命中。
  */
 import { mkdirSync, writeFileSync } from 'node:fs';
 import { join, dirname } from 'node:path';
@@ -233,20 +233,10 @@ const MEASURE = `(async () => {
     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));
-  }
+  /* 悬停必须用「真实指针」:合成 pointerover 事件不会让 :hover 命中(v11 实测 :hover 规则对合成事件无效),
+     所以逐个别移动鼠标,并在移动后把命中的元素收集回来由外圈逐一核对。 */
+  /* clickables 本身不进返回值(元素引用不可序列化):坐标 + 签名 + 标签即可 */
+  out.pendingHover = clickables.map((c) => ({ x: c.cx, y: c.cy, sig: c.sig.join('|'), tag: elLabel(c.el).slice(0, 40), text: (c.el.textContent || '').trim().slice(0, 12) }));
 
   /* ---- 9. 底部空白 ---- */
   out.scrollH = Math.round(document.documentElement.scrollHeight);
@@ -266,13 +256,13 @@ const MEASURE = `(async () => {
   out.lastContentBottom = Math.round(bottom);
 
   /* ---- 10. 筛选区(P1)与 11. 工作台两栏(P3) ---- */
-  const q = (sel) => main()?.shadowRoot?.querySelector(sel) || null;
+  const q = (sel) => appR().querySelector('main#view')?.firstElementChild?.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 tb = q('.filters[data-toolbar]');
+    const seg = filters ? filters.querySelector('.seg') : null;
+    const search = filters ? filters.querySelector('.frow.toolbar input[type="search"]') : null;
+    const chips = [...(q('.filters')?.querySelectorAll('.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 : '';
@@ -283,6 +273,15 @@ const MEASURE = `(async () => {
       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,
+      /* 底边对齐:搜索框底边 vs 它所在那一行(.frow.toolbar)里排序段与 chip 的底边 —— 三者差 ≤ 2px 即「同一底边」 */
+      rowBottomDelta: (() => {
+        if (!search) return null;
+        const row = search.closest('.frow');
+        const segEl = row?.querySelector('.seg');
+        const sb = search.getBoundingClientRect().bottom;
+        const others = [segEl, ...(row ? row.querySelectorAll('.kf-chip') : [])].filter(Boolean).map((e) => e.getBoundingClientRect().bottom);
+        return others.length ? Math.round(Math.max(...others.map((o) => Math.abs(o - sb))) * 10) / 10 : null;
+      })(),
       segBorder: segBorders,
     };
   }
@@ -313,7 +312,25 @@ const MEASURE = `(async () => {
 const results = [];
 for (const p of PAGES) {
   await gotoView(p);
-  results.push(await page.evaluate(MEASURE));
+  const r = await page.evaluate(MEASURE);
+  /* 悬停:逐个用真实鼠标移到元素中心;鼠标离开后等过渡回落 */
+  await page.mouse.move(2, 2);
+  await page.waitForTimeout(60);
+  for (const c of r.pendingHover || []) {
+    await page.mouse.move(c.x, c.y, { steps: 1 });
+    await page.waitForTimeout(240);          /* 等过渡(最长 240ms)走完 */
+    const after = await page.evaluate(([x, y]) => {
+      const el = document.elementFromPoint(x, y);
+      if (!el) return null;
+      const s = getComputedStyle(el);
+      return [s.backgroundColor, s.borderTopColor, s.backgroundImage, s.color, s.boxShadow, s.transform, s.cursor].join('|');
+    }, [c.x, c.y]);
+    if (after === c.sig) r.hoverFail.push({ tag: c.tag, text: c.text });
+    await page.mouse.move(2, 2);
+    await page.waitForTimeout(40);
+  }
+  delete r.pendingHover;
+  results.push(r);
 }
 
 /* ============ 汇总 ============ */
@@ -349,7 +366,7 @@ const check = (name, ok, detail) => { checks.push({ name, ok, detail }); console
 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('、')}` +
+  `容器圆角(≤6px 的量条/色点不计)${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,
@@ -382,8 +399,9 @@ check('P1 筛选栏:一个容器 + 分段排序 + 与搜索框等高底对齐'
   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');
+  /* 底边对齐:搜索框与筛选容器里最后一个 chip 行的底边(不是容器 padding 底) */
+  return f.container && f.filtersInsideToolbar && segOk && chipOk && f.searchH !== null && f.rowBottomDelta !== null && f.rowBottomDelta <= 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.rowBottomDelta}px,与容器底边差 ${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` : '未量 /');

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

@@ -23,10 +23,10 @@ export const TOOLBAR_CSS = css`
   .tb .kf-chip .n { opacity: 0.7; margin-left: 2px; }
   .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: 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 { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; box-sizing: border-box; height: 28px; padding: 0 10px;
+    border-radius: var(--r-sm); border: 1px solid rgba(255, 255, 255, 0.14); background: transparent; font: 500 12px/1 var(--kf-font); color: var(--kf-ink-2);
+    transition: background var(--kf-dur) var(--kf-ease), border-color var(--kf-dur) var(--kf-ease), color var(--kf-dur) var(--kf-ease); }
+  .dd > summary:hover { background: rgba(255, 255, 255, 0.55); border-color: rgba(255, 255, 255, 0.55); color: var(--kf-ink); }
   .dd > summary::-webkit-details-marker { display: none; }
   .dd[open] > summary, .dd.has > summary { border-color: var(--kf-accent); box-shadow: inset 0 0 0 1px var(--kf-accent); }
   /* 下拉面板 = 上层玻璃(.72 + blur 32),和卡片拉开层次 */

+ 51 - 39
src/pages/view-pool.js

@@ -50,51 +50,62 @@ export class ViewPool extends LitElement {
 
 
   static styles = [VIEW_CSS, css`
-    .filters { padding: 12px 16px 16px; display: grid; gap: 8px; align-content: start; position: sticky; top: 72px; z-index: 3; }
-    .frow { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
-    .frow .lbl { width: 56px; font-size: 11px; color: var(--kf-ink-3); flex: none; }
-    .chips { display: flex; gap: 6px; flex-wrap: wrap; flex: 1; }
-    .kf-chip[data-zero="1"] { opacity: 0.42; }
-    /* 筛选卡与卡片流放在同一个块容器里:sticky 才有参照,行盒也不会把块级子元素叠在一起 */
+    /* 筛选栏(v12 P1):一个容器,内部分组「状态 | 优先级 | 阶段 | 品类 | 上传人 | 排序」。
+       分组之间 1px 竖线(::before),组内 chip 8px 间隔;最后一行「排序 + 搜索」与上面的 chip 行之间 1px 横线。
+       容器不是玻璃卡嵌套:它就是筛选区本身,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: 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: 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; }
+    .filters { padding: 0; position: sticky; top: 72px; z-index: 3; display: grid; gap: 0; }
+    .frow { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; padding: 8px 16px; }
+    .frow + .frow { border-top: 1px solid var(--kf-line); }
+    .frow .lbl { width: 48px; font-size: 12px; line-height: 1; color: var(--kf-ink-3); flex: none; }
+    .chips { display: flex; gap: 6px; flex-wrap: wrap; flex: 1; align-items: center; }
+    /* 筛选 chip:28px / 12px 字 / r-sm;未选中透明底 + 1px 描边 + 次级字色;选中实底白字(共享表 .kf-chip[aria-pressed]) */
+    .filters .kf-chip { height: 28px; padding: 0 10px; font-size: 12px; font-weight: 500; gap: 6px; }
+    .filters .kf-chip .n { font-size: 11px; color: var(--kf-ink-3); }
+    .filters .kf-chip[aria-pressed="true"] .n { color: rgba(255, 255, 255, 0.72); }
+    .kf-chip[data-zero="1"] { opacity: 0.42; }
+    /* 排序 = 单选段:一整块被 1px 分隔线切开,不是五个独立按钮 */
+    .seg { display: inline-flex; align-items: stretch; height: 28px; border: 1px solid rgba(255, 255, 255, 0.14); border-radius: var(--r-sm); overflow: hidden; background: transparent; }
+    .seg button { appearance: none; -webkit-appearance: none; border: 0; border-left: 1px solid rgba(255, 255, 255, 0.14); border-radius: 0; margin: 0;
+      background: transparent; padding: 0 12px; height: 100%; font: 500 12px/1 var(--kf-font); color: var(--kf-ink-2); cursor: pointer;
+      white-space: nowrap; transition: background var(--kf-dur) var(--kf-ease), color var(--kf-dur) var(--kf-ease); }
+    .seg button:first-child { border-left: 0; }
+    .seg button:hover { background: rgba(255, 255, 255, 0.55); color: var(--kf-ink); }
+    .seg button[aria-pressed="true"], .seg button[aria-pressed="true"]:hover { background: var(--kf-ink); color: #fff; }
+    /* 搜索框:与排序段同高(28px)、同圆角;聚焦时 2px 焦点环由共享表给 */
+    .frow.toolbar input[type="search"] { appearance: none; -webkit-appearance: none; height: 28px; box-sizing: border-box; padding: 0 10px;
+      border-radius: var(--r-sm); border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(255, 255, 255, 0.5); color: var(--kf-ink);
+      font: 400 12px/1 var(--kf-font); min-width: 240px; margin-left: auto; transition: background var(--kf-dur) var(--kf-ease), border-color var(--kf-dur) var(--kf-ease); }
+    .frow.toolbar input[type="search"]:hover { background: rgba(255, 255, 255, 0.66); }
+    .frow.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.85); }
+    .sfield { margin-left: auto; display: flex; }
+    .sfield input[type="search"] { margin-left: 0; }
     .cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); gap: 16px; }
-    .cards kf-opportunity-card.is-focus { outline: 2px solid var(--kf-accent); outline-offset: 3px; border-radius: var(--kf-radius); }
-    .count { font-size: 13px; color: var(--kf-ink-3); }
+    .cards kf-opportunity-card.is-focus { outline: 2px solid var(--kf-accent); outline-offset: 3px; border-radius: var(--r-md); }
+    .count { font-size: 13px; color: var(--kf-ink-3); font-variant-numeric: tabular-nums; }
     .count b { color: var(--kf-ink); font-variant-numeric: tabular-nums; }
-    .reset { border: 0; background: transparent; color: var(--kf-accent-ink); cursor: pointer; font: 500 11px var(--kf-font); text-decoration: underline; text-underline-offset: 3px; }
+    .reset { border: 0; background: transparent; color: var(--kf-accent-ink); cursor: pointer; font: 500 12px var(--kf-font); text-decoration: underline; text-underline-offset: 3px; padding: 4px 2px; border-radius: var(--r-sm); }
+    .reset:hover { background: rgba(91, 91, 214, 0.08); text-decoration-color: transparent; }
     /* 手机工具条:桌面隐藏 */
     .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: 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);
+      .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 rgba(255, 255, 255, 0.14); border-radius: var(--r-sm); cursor: pointer;
+        background: rgba(255, 255, 255, 0.72); 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: 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: 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 不在此列) */
+      .pbar input[type="search"] { grid-area: m; appearance: none; -webkit-appearance: none; min-width: 0; width: 100%; height: 44px; padding: 0 12px; border-radius: var(--r-sm); border: 1px solid rgba(255, 255, 255, 0.14); font: 400 14px var(--kf-font); background: rgba(255, 255, 255, 0.5); }
+      .pbar-more { grid-area: s; border-radius: var(--r-sm); background: rgba(255, 255, 255, 0.32); }
+      .pbar-more > summary { 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-sorts { display: flex; gap: 0; padding: 0 8px 8px; }
+      .pbar-sorts button { appearance: none; -webkit-appearance: none; border: 1px solid rgba(255, 255, 255, 0.14); border-left-width: 0; margin: 0; box-sizing: border-box; flex: 1; height: 44px; display: grid; place-items: center; border-radius: 0; font: 500 13px var(--kf-font); color: var(--kf-ink-2); background: rgba(255, 255, 255, 0.45); cursor: pointer; }
+      .pbar-sorts button:first-child { border-left-width: 1px; border-top-left-radius: var(--r-sm); border-bottom-left-radius: var(--r-sm); }
+      .pbar-sorts button:last-child { border-top-right-radius: var(--r-sm); border-bottom-right-radius: var(--r-sm); }
+      .pbar-sorts button[aria-pressed="true"] { background: var(--kf-ink); color: #fff; border-color: var(--kf-ink); }
+      /* 手机上原生筛选卡收起(桌面档里已隐藏 .pbar 不在此列) */
       .filters { display: none; }
     }
     @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: var(--r-md); gap: 8px; }
-      .frow .lbl { width: 44px; }
-      .chips { gap: 8px; }
-      .kf-chip { height: 36px; padding: 0 12px; font-size: 13px; }
-      .toolbar input[type="search"] { min-width: 0; width: 100%; height: 44px; font-size: 14px; }
-      .seg { height: 44px; overflow-x: auto; }
-      .seg button { height: 44px; padding: 0 14px; font-size: 13px; }
       .cards { grid-template-columns: minmax(0, 1fr); gap: 12px; }
     }
   `];
@@ -171,7 +182,7 @@ export class ViewPool extends LitElement {
 
       <div class="pool-body">
       <!-- 手机工具条:与类型页同一套(筛选按钮带已选数 / 结果数 / 排序收起 / 搜索),筛选面板 ⤢ 按钮锚定到这里 -->
-      <div class="pbar tb kf-glass is-panel" data-toolbar ${ref((el) => { this._pbar = el; })}>
+      <div class="pbar tb kf-glass is-panel" data-toolbar-m ${ref((el) => { this._pbar = el; })}>
         <button class="pbar-btn ${active ? 'on' : ''}" data-open-sheet @click=${this.#openSheet} aria-label=${`筛选${cnt ? `(已选 ${cnt} 项)` : ''}`}>
           ${icon('filter', 18)}筛选${cnt ? html`<span class="pbar-nb">${cnt}</span>` : ''}
         </button>
@@ -182,11 +193,12 @@ export class ViewPool extends LitElement {
         </details>
       </div>
       ${this.#mobileSheet(c, rows, filtered.length)}
-      <kf-glass-card surface="1" class="filters" data-no-activate>
-        ${DIMS.map((d) => {
+      <!-- 桌面筛选栏(v12 P1):一整块容器,组内 chip、组间竖线,最后一行排序段 + 搜索 -->
+      <div class="filters kf-glass is-panel" data-toolbar data-no-activate>
+        ${DIMS.map((d, di) => {
           const counts = facetCounts(rows, c, d.key);
           const vals = d.values(rows);
-          return html`<div class="frow">
+          return html`<div class="frow ${di ? 'sep' : ''}">
             <span class="lbl">${d.label}</span>
             <div class="chips" role="group" aria-label=${`按${d.label}筛选`}>
               ${vals.map((v) => {
@@ -203,9 +215,9 @@ export class ViewPool extends LitElement {
           <div class="seg" role="group" aria-label="排序方式">
             ${SORTS.map((s) => html`<button aria-pressed=${(c.sort || 'priority') === s.key ? 'true' : 'false'} @click=${() => this.#setSort(s.key)}>${s.label}</button>`)}
           </div>
-          <input type="search" placeholder="搜索卡片标题 / 一句话 / 上传人" .value=${c.q || ''} @input=${this.#search} aria-label="搜索机会卡" />
+          <span class="sfield"><input type="search" placeholder="搜索卡片标题 / 一句话 / 上传人" .value=${c.q || ''} @input=${this.#search} aria-label="搜索机会卡" /></span>
         </div>
-      </kf-glass-card>
+      </div>
 
       ${section('池子', active ? '符合条件的卡片' : '全部卡片', html`<span>${SORTS.find((s) => s.key === (c.sort || 'priority')).label}</span>`)}