wezard 2.1.4 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -24
- package/dist/daemon/cc-session.js +14 -1
- package/dist/daemon/cc-session.js.map +1 -1
- package/dist/daemon/danger.js +48 -7
- package/dist/daemon/danger.js.map +1 -1
- package/dist/daemon/detail.js +28 -7
- package/dist/daemon/detail.js.map +1 -1
- package/dist/daemon/handoff.js +132 -0
- package/dist/daemon/handoff.js.map +1 -0
- package/dist/daemon/inbound.js +2 -1
- package/dist/daemon/inbound.js.map +1 -1
- package/dist/daemon/index.js +191 -99
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/mirror-bridge.js +136 -12
- package/dist/daemon/mirror-bridge.js.map +1 -1
- package/dist/daemon/peers.js +114 -34
- package/dist/daemon/peers.js.map +1 -1
- package/dist/daemon/receipts.js +190 -0
- package/dist/daemon/receipts.js.map +1 -0
- package/dist/daemon/route.js +92 -0
- package/dist/daemon/route.js.map +1 -0
- package/dist/daemon/wizard.js +38 -19
- package/dist/daemon/wizard.js.map +1 -1
- package/dist/mcp/server.js +60 -25
- package/dist/mcp/server.js.map +1 -1
- package/dist/shared/chat-http.js +101 -21
- package/dist/shared/chat-http.js.map +1 -1
- package/dist/shared/chat-render.js +0 -1
- package/dist/shared/chat-render.js.map +1 -1
- package/dist/shared/chat-view.js +2 -9
- package/dist/shared/chat-view.js.map +1 -1
- package/dist/shared/config.js +6 -0
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/detail-render.js +3 -2
- package/dist/shared/detail-render.js.map +1 -1
- package/dist/shared/detail-store.js +1 -1
- package/dist/shared/detail-store.js.map +1 -1
- package/dist/shared/keepalive.js +46 -0
- package/dist/shared/keepalive.js.map +1 -0
- package/dist/shared/reminder.js +13 -0
- package/dist/shared/reminder.js.map +1 -1
- package/dist/shared/role-render.js +2 -1
- package/dist/shared/role-render.js.map +1 -1
- package/dist/shared/role-search.js +100 -0
- package/dist/shared/role-search.js.map +1 -0
- package/dist/shared/role-view.js +85 -26
- package/dist/shared/role-view.js.map +1 -1
- package/dist/shared/world.js +38 -8
- package/dist/shared/world.js.map +1 -1
- package/dist/svr/index.js +1 -1
- package/dist/svr/index.js.map +1 -1
- package/package.json +1 -1
- package/web/chat.css +415 -333
- package/web/chat.js +899 -741
package/web/chat.css
CHANGED
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
--mine-line: #c9d7f3;
|
|
19
19
|
--accent: #2f55c9; /* 视角色: 名字的点、选中态、自己的气泡描边 */
|
|
20
20
|
--priv: #9a5b10; /* 私聊 */
|
|
21
|
+
/* 头像底: 不透明, 且由 card/accent 推出 —— 叠在选中/高亮/关系图任何底色上都不变色, 换主题时随 token 走。 */
|
|
22
|
+
--av-bg: var(--card);
|
|
23
|
+
--av-line: var(--line);
|
|
24
|
+
--av-hot: color-mix(in srgb, var(--accent) 14%, var(--card));
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
html { height: 100% }
|
|
@@ -47,59 +51,75 @@ button { font: inherit; color: inherit }
|
|
|
47
51
|
|
|
48
52
|
/* ── 左栏顶: 当前 role 的名片 (身份); 关系/日程入口是名片下、会话列表上的一排 ──── */
|
|
49
53
|
.rolebar {
|
|
50
|
-
|
|
54
|
+
/* margin 归零: 通用 header 规则带着 8px 下边距, 会把下面的入口条顶得上宽下窄。 */
|
|
55
|
+
position: relative; flex: none; margin: 0; padding: 16px 16px 14px; border-bottom: 1px solid var(--line);
|
|
51
56
|
display: flex; flex-direction: column; gap: 8px; background: var(--card);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
/* 通用 header 规则带着 flex-wrap:wrap + align-items:baseline —— 竖轴上那会让名片按内容撑宽 (max-content),
|
|
58
|
+
长名字 / 长路径就冲出侧栏。 */
|
|
59
|
+
flex-wrap: nowrap; align-items: stretch;
|
|
60
|
+
}
|
|
61
|
+
.rolebar > .who { min-width: 0 }
|
|
62
|
+
.rolebar .id { display: flex; gap: 12px; align-items: center; min-width: 0 }
|
|
63
|
+
/* 与会话项头像同一套不透明底, 放大到名片尺寸。 */
|
|
64
|
+
.rolebar .id .av {
|
|
65
|
+
flex: none; display: grid; place-items: center; width: 48px; height: 48px; border-radius: 14px;
|
|
66
|
+
background: var(--av-bg); box-shadow: inset 0 0 0 1px var(--av-line); font-size: 28px; line-height: 1;
|
|
67
|
+
}
|
|
68
|
+
.rolebar .id .l { min-width: 0; display: flex; flex-direction: column; gap: 3px }
|
|
56
69
|
.rolebar .id .nm { font-size: 18px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.rolebar .
|
|
66
|
-
.rolebar .st.off { color: var(--faint) }
|
|
67
|
-
.rolebar .st.off::before { background: transparent; box-shadow: inset 0 0 0 1.5px #b1bac4 }
|
|
68
|
-
.rolebar .job { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink); opacity: .8 }
|
|
69
|
-
.rolebar .facts { display: flex; gap: 6px 12px; flex-wrap: wrap; font-size: 11.5px; color: var(--mute) }
|
|
70
|
-
.rolebar .facts span { white-space: nowrap }
|
|
70
|
+
/* 职责是一句话, 至多两行; 截掉的悬停看全文 (chat.js 的截断提示)。 */
|
|
71
|
+
.rolebar .job {
|
|
72
|
+
margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink); opacity: .8; word-break: break-word;
|
|
73
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
|
|
74
|
+
}
|
|
75
|
+
/* 名字下的描述: 📁 cwd · 🏠 home · 🐣 出生, 一段低调的灰字, 排不下就整项落到下一行。 */
|
|
76
|
+
.rolebar .facts { display: flex; flex-wrap: wrap; gap: 0 10px; font-size: 11.5px; line-height: 1.45; color: var(--faint); min-width: 0 }
|
|
77
|
+
/* 每条自身不折行; 独占一行仍超宽 (长路径 / 长群名) 才省略。 */
|
|
78
|
+
.rolebar .facts span { white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis }
|
|
71
79
|
.rolebar .go { cursor: pointer; color: var(--accent) }
|
|
72
80
|
.rolebar .go:hover { text-decoration: underline }
|
|
73
|
-
|
|
81
|
+
/* 分隔线两端收进来, 与上面搜索框的左右边距对齐, 不顶满侧栏。 */
|
|
82
|
+
.acts { flex: none; display: flex; justify-content: center; align-items: center; gap: 2px; margin: 0 10px; padding: 4px 0 8px; border-bottom: 1px solid var(--line) }
|
|
74
83
|
.acts:empty { display: none }
|
|
75
84
|
/* 旧外壳 (daemon 未重启) 里它还在名片内 —— 那里不需要自己的内边距与分隔线。 */
|
|
76
|
-
.rolebar .acts { padding: 0; border: 0 }
|
|
77
|
-
/*
|
|
85
|
+
.rolebar .acts { margin: 0; padding: 0; border: 0 }
|
|
86
|
+
/* 入口: 图标 + 名字 + 淡色副标题, 无框无底; hover 才浮出一层浅底, 打开着的染视角色。 */
|
|
78
87
|
.bd {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
.bd
|
|
83
|
-
.bd
|
|
84
|
-
.bd
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
flex: none; padding: 1px 4px; border: 0; border-radius: 4px; background: none; cursor: pointer; white-space: nowrap;
|
|
89
|
+
font-size: 12px; color: var(--mute); transition: color .12s;
|
|
90
|
+
}
|
|
91
|
+
.bd:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px }
|
|
92
|
+
.bd.on { color: var(--accent); font-weight: 600 }
|
|
93
|
+
.bd.bad { color: #cf222e }
|
|
94
|
+
.acts .sep { color: var(--line); font-size: 12px; user-select: none }
|
|
95
|
+
/* session 切换: name 右边一个小号文字触发器 + 浮层列表。name 先省略, 触发器不让位。 */
|
|
96
|
+
.rolebar .id .l { flex: 1 }
|
|
97
|
+
.rolebar .nl { display: flex; align-items: center; gap: 8px; min-width: 0 }
|
|
98
|
+
#rb-st { flex: none; display: inline-flex }
|
|
99
|
+
.rolebar .nl .nm { min-width: 0; flex: 0 1 auto }
|
|
100
|
+
.rolebar .nl .cp { min-width: 0; flex: 0 1 auto; display: inline-flex; cursor: copy }
|
|
101
|
+
.rolebar .nl .cp:hover .nm { text-decoration: underline dotted var(--faint); text-underline-offset: 3px }
|
|
102
|
+
.toast {
|
|
103
|
+
position: fixed; left: 50%; bottom: 28px; z-index: 1000; transform: translate(-50%, 8px);
|
|
104
|
+
padding: 6px 12px; border-radius: 8px; font-size: 12.5px; color: #fff; background: rgba(28, 36, 48, .88);
|
|
105
|
+
opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s;
|
|
106
|
+
}
|
|
107
|
+
.toast.on { opacity: 1; transform: translate(-50%, 0) }
|
|
108
|
+
#rb-sp { flex: none; display: inline-flex }
|
|
109
|
+
.sp { position: relative; display: inline-flex }
|
|
87
110
|
.sp-btn {
|
|
88
|
-
|
|
89
|
-
font-size:
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
.sp-btn:hover, .sp.open .sp-btn {
|
|
93
|
-
|
|
94
|
-
.sp-btn .
|
|
95
|
-
.sp-btn .
|
|
96
|
-
.sp-btn .car {
|
|
97
|
-
flex: none; width: 6px; height: 6px; margin: -3px 2px 0 0; border: solid var(--mute); border-width: 0 1.5px 1.5px 0;
|
|
98
|
-
transform: rotate(45deg); transition: transform .15s;
|
|
99
|
-
}
|
|
100
|
-
.sp.open .sp-btn .car { transform: rotate(-135deg); margin-top: 3px }
|
|
111
|
+
display: inline-flex; align-items: center; gap: 2px; cursor: pointer; white-space: nowrap;
|
|
112
|
+
font-size: 11.5px; color: var(--mute); background: none; border: 0; border-radius: 5px; padding: 1px 4px;
|
|
113
|
+
font-variant-numeric: tabular-nums; transition: background .12s, color .12s;
|
|
114
|
+
}
|
|
115
|
+
.sp-btn:hover, .sp.open .sp-btn { background: var(--paper); color: var(--ink) }
|
|
116
|
+
/* 箭头用边框画, 不用 ▾ 字形 —— 字形贴着基线, 放大后总是偏下。 */
|
|
117
|
+
.sp-btn .car { flex: none; display: grid; place-items: center; width: 18px; height: 18px; transition: transform .15s }
|
|
118
|
+
.sp-btn .car::before { content: ""; border: 5px solid transparent; border-top: 6px solid var(--faint); border-bottom: 0 }
|
|
119
|
+
.sp.open .sp-btn .car { transform: rotate(180deg) }
|
|
101
120
|
.sp-list {
|
|
102
|
-
|
|
121
|
+
/* 以触发器左下角为锚向右下展开 —— 触发器贴着 name 右边, 朝左开会被侧栏左沿裁掉。 */
|
|
122
|
+
position: absolute; z-index: 20; left: 0; top: calc(100% + 4px); width: 196px; max-width: calc(100vw - 24px);
|
|
103
123
|
max-height: 280px; overflow-y: auto; overscroll-behavior: contain;
|
|
104
124
|
background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 4px;
|
|
105
125
|
box-shadow: 0 8px 24px #1c24301f, 0 2px 6px #1c24300f;
|
|
@@ -107,45 +127,46 @@ button { font: inherit; color: inherit }
|
|
|
107
127
|
}
|
|
108
128
|
.sp.open .sp-list { opacity: 1; transform: none; pointer-events: auto }
|
|
109
129
|
.sp-it {
|
|
110
|
-
width: 100%; display:
|
|
130
|
+
width: 100%; display: flex; gap: 10px; align-items: baseline;
|
|
111
131
|
background: none; border: 0; border-radius: 6px; padding: 6px 8px; cursor: pointer; text-align: left; font-size: 12px;
|
|
112
132
|
}
|
|
113
133
|
.sp-it:hover { background: var(--paper) }
|
|
114
134
|
.sp-it.on { background: var(--mine); color: var(--accent) }
|
|
115
|
-
.sp-it .id {
|
|
116
|
-
.sp-it .
|
|
117
|
-
.sp-it .n { color: var(--faint); font-variant-numeric: tabular-nums; grid-column: 3 }
|
|
135
|
+
.sp-it .id { flex: 1; min-width: 0; font-variant-numeric: tabular-nums }
|
|
136
|
+
.sp-it .n { flex: none; color: var(--faint); font-variant-numeric: tabular-nums }
|
|
118
137
|
.sp-it.all { border-bottom: 1px solid var(--line); border-radius: 6px 6px 0 0; margin-bottom: 3px }
|
|
119
|
-
.sp-it.all .id { font-family: inherit }
|
|
120
|
-
|
|
121
|
-
/* 左栏底: session 切换 —— 轮次的事, 与顶上的身份分开, 钉在会话列表下面。 */
|
|
122
|
-
.sidefoot { flex: none; border-top: 1px solid var(--line); padding: 10px 12px; background: var(--paper) }
|
|
123
|
-
/* 在底部, 浮层往上开。 */
|
|
124
|
-
.sidefoot .sp-list { top: auto; bottom: calc(100% + 4px); transform: translateY(4px) }
|
|
125
|
-
.sidefoot .sp.open .sp-list { transform: none }
|
|
126
138
|
|
|
127
139
|
/* ── 用量条: 一组轮次的总账 ─────────────────────────────────────────
|
|
128
140
|
一个组件两处挂: 整页页脚 (wizard 的总账) / 聊天窗口底 (人与某个 wizard 这段往来的账)。
|
|
129
|
-
|
|
130
|
-
|
|
141
|
+
永远单行: 主人 · 模型 · 指标 · 图例, I/O 分布是贴底的色带。排不下时 chat.js 的 fitUsage
|
|
142
|
+
按容器宽度一级级加 f-* 藏掉次要的 (分布文字 → 名字 → 耗时), 不按视口断点。 */
|
|
131
143
|
.usage {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
144
|
+
/* 整条只有一个字号、一个间隔: 指标、模型名、主人、图例都用它。 */
|
|
145
|
+
--u-gap: 14px;
|
|
146
|
+
flex: none; display: flex; align-items: center; flex-wrap: nowrap; gap: var(--u-gap); overflow: hidden; white-space: nowrap;
|
|
147
|
+
position: relative; padding: 7px 20px 9px; border-top: 1px solid var(--line); background: var(--paper);
|
|
148
|
+
font-family: ui-monospace, Menlo, monospace; font-size: 11.5px; color: var(--mute);
|
|
135
149
|
font-variant-numeric: tabular-nums;
|
|
136
150
|
}
|
|
137
|
-
.usage b { font-weight:
|
|
138
|
-
.usage
|
|
139
|
-
.usage .u-
|
|
140
|
-
.usage .
|
|
141
|
-
.usage .
|
|
142
|
-
.usage .u-
|
|
143
|
-
.usage .
|
|
144
|
-
.usage .
|
|
145
|
-
|
|
151
|
+
.usage b { font-weight: 400; color: var(--ink) }
|
|
152
|
+
.usage > * { flex: none }
|
|
153
|
+
.usage .u-who { display: flex; align-items: center; gap: 4px; max-width: 200px }
|
|
154
|
+
.usage .u-nm { overflow: hidden; text-overflow: ellipsis; color: var(--faint) }
|
|
155
|
+
.usage .u-lb { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; color: var(--accent) }
|
|
156
|
+
.usage .u-ic { font-style: normal; margin-right: 4px }
|
|
157
|
+
.usage .u-kvs, .usage .leg { display: flex; gap: var(--u-gap) }
|
|
158
|
+
.usage .kv { white-space: nowrap }
|
|
159
|
+
/* I/O 分布 = bar 的底边: 横跨整宽的细色带, 不占行; 悬停加粗一点好瞄准某一段。 */
|
|
160
|
+
.usage .bar {
|
|
161
|
+
position: absolute; left: 0; right: 0; bottom: 0; height: 3px; display: flex;
|
|
162
|
+
background: var(--line); transition: height .12s;
|
|
163
|
+
}
|
|
164
|
+
.usage .bar:hover { height: 6px }
|
|
165
|
+
.usage .bar .seg { flex: 1 1 0; min-width: 2px; height: 100% }
|
|
166
|
+
.usage .leg { margin-left: auto }
|
|
146
167
|
.usage .lg { display: flex; align-items: center; gap: 4px; white-space: nowrap }
|
|
147
|
-
.usage .lg i { width:
|
|
148
|
-
.usage .
|
|
168
|
+
.usage .lg i { width: 7px; height: 7px; border-radius: 50%; flex: none }
|
|
169
|
+
.usage.f-leg .leg, .usage.f-nm .u-nm, .usage.f-time .kv-time { display: none }
|
|
149
170
|
|
|
150
171
|
/* 群聊头像 = 参与者头像拼图: 1 格居中, 2 格左右, 3/4 格田字。 */
|
|
151
172
|
.mosaic {
|
|
@@ -153,7 +174,7 @@ button { font: inherit; color: inherit }
|
|
|
153
174
|
background: #eef1f6; border: 1px solid var(--line); gap: 1px; padding: 1px;
|
|
154
175
|
font-size: 13px !important; line-height: 1 !important;
|
|
155
176
|
}
|
|
156
|
-
.mosaic i { font-style: normal; display: grid; place-items: center; background:
|
|
177
|
+
.mosaic i { font-style: normal; display: grid; place-items: center; background: var(--av-bg); min-width: 0; min-height: 0 }
|
|
157
178
|
.mosaic.n1 { grid-template: 1fr / 1fr; font-size: 20px !important }
|
|
158
179
|
.mosaic.n2 { grid-template: 1fr / 1fr 1fr; font-size: 14px !important }
|
|
159
180
|
.mosaic.n3, .mosaic.n4 { grid-template: 1fr 1fr / 1fr 1fr }
|
|
@@ -167,50 +188,42 @@ button { font: inherit; color: inherit }
|
|
|
167
188
|
.convs h2:first-child { margin-top: 6px }
|
|
168
189
|
.convs h2 span { font-weight: 400; color: var(--faint); font-variant-numeric: tabular-nums }
|
|
169
190
|
|
|
170
|
-
.ci
|
|
171
|
-
|
|
191
|
+
/* 群下的子项 (.si) 与私聊项 (.ci) 同一套尺寸 —— 只有一份。 */
|
|
192
|
+
.ci, .si {
|
|
193
|
+
display: flex; gap: 10px; align-items: center; width: 100%; text-align: left; overflow: hidden;
|
|
172
194
|
padding: 8px 10px; border: 0; border-radius: 9px; background: transparent; cursor: pointer;
|
|
173
195
|
}
|
|
174
|
-
.ci
|
|
175
|
-
|
|
176
|
-
.ci {
|
|
177
|
-
.ci
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
.ci .
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
.ci .
|
|
196
|
+
.ci.on, .si.on { background: #eaf0fc }
|
|
197
|
+
/* 下分割线: 每一项自己的下边线 (侧栏项、群下子项、关系图卡片一律), 两端收到内容边距。 */
|
|
198
|
+
.ci, .si { position: relative }
|
|
199
|
+
.ci::after, .si::after {
|
|
200
|
+
content: ""; position: absolute; left: 10px; right: 10px; bottom: 0; height: 1px;
|
|
201
|
+
background: var(--line); opacity: .6; pointer-events: none;
|
|
202
|
+
}
|
|
203
|
+
.ci > .av, .si > .av {
|
|
204
|
+
flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px;
|
|
205
|
+
background: var(--av-bg); box-shadow: inset 0 0 0 1px var(--av-line); font-size: 20px; line-height: 1;
|
|
206
|
+
}
|
|
207
|
+
.ci .b, .si .b { min-width: 0; flex: 1; overflow: hidden }
|
|
208
|
+
.ci .l1, .si .l1 { display: flex; align-items: baseline; gap: 6px; overflow: hidden; white-space: nowrap }
|
|
209
|
+
.ci .t, .si .t { font-size: 13.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
210
|
+
.ci .ts, .si .ts { margin-left: auto; flex: none; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums }
|
|
211
|
+
.ci .pv, .si .pv { display: block; font-size: 12px; color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
212
|
+
.ci .pv:empty, .si .pv:empty { display: none }
|
|
186
213
|
.ci .tag { font-size: 10.5px; border-radius: 4px; padding: 0 4px; flex: none }
|
|
187
214
|
/* 头像与名字是进入那个 role 视角的入口 —— 侧栏项、会话头、消息行同一种读法。
|
|
188
|
-
|
|
189
|
-
让位 (:has), 否则读起来像是要选中这一行。z-index 保证没有兄弟盖住命中区。 */
|
|
215
|
+
它们嵌在整行那颗按钮里; 行本身悬停不变底色, 只有入口自己亮起。z-index 保证没有兄弟盖住命中区。 */
|
|
190
216
|
.nm.go, .av.go { position: relative; z-index: 1; cursor: pointer }
|
|
191
217
|
.nm.go:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 2px }
|
|
192
218
|
span.av.go { border-radius: 8px; transition: background .12s, box-shadow .12s }
|
|
193
|
-
span.av.go:hover { background:
|
|
194
|
-
.ci:not(.on):has(.go:hover), .si:not(.on):has(.go:hover) { background: transparent }
|
|
219
|
+
span.av.go:hover { background: var(--av-hot); box-shadow: 0 0 0 3px var(--av-hot) }
|
|
195
220
|
.ci .tag.priv { color: var(--priv); background: #9a5b1014 }
|
|
196
221
|
|
|
197
|
-
/* 群里的其他 role —— 挂在群下,
|
|
222
|
+
/* 群里的其他 role —— 挂在群下, 与会话项同一种读法、同一套尺寸 (名字 · 时刻 / 最近一句), 只靠缩进分层级。
|
|
198
223
|
点开是「我与它在这个群里」的往来。 */
|
|
199
|
-
|
|
200
|
-
.
|
|
201
|
-
|
|
202
|
-
padding: 5px 8px; border: 0; border-radius: 8px; background: transparent; cursor: pointer; color: var(--ink);
|
|
203
|
-
}
|
|
204
|
-
.si:hover { background: #f4f6f9 }
|
|
205
|
-
.si.on { background: #eaf0fc }
|
|
206
|
-
.si > .av { font-size: 17px; line-height: 1; flex: none; width: 24px; text-align: center }
|
|
207
|
-
.si .b { min-width: 0; flex: 1; overflow: hidden }
|
|
208
|
-
.si .l1 { display: flex; align-items: baseline; gap: 6px }
|
|
209
|
-
.si .t { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
210
|
-
.si.on .t { color: var(--accent) }
|
|
211
|
-
.si .ts { margin-left: auto; flex: none; font-size: 10.5px; color: var(--faint); font-variant-numeric: tabular-nums }
|
|
212
|
-
.si .pv { display: block; font-size: 11.5px; color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
213
|
-
.si .pv:empty { display: none }
|
|
224
|
+
/* 竖线的 x 与关系图里的竖向连线对齐: 都在项左缘 +10px (关系树 ul 缩进 20 - 线距 li 10)。 */
|
|
225
|
+
.subs { margin: 0 0 6px 10px; border-left: 1px solid var(--line); padding-left: 2px }
|
|
226
|
+
.si { color: var(--ink) }
|
|
214
227
|
.si-more {
|
|
215
228
|
display: block; width: 100%; text-align: center; padding: 4px 8px; border: 0;
|
|
216
229
|
background: transparent; cursor: pointer; font-size: 11.5px; color: var(--mute);
|
|
@@ -226,16 +239,11 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
226
239
|
font-variant-numeric: tabular-nums;
|
|
227
240
|
}
|
|
228
241
|
|
|
229
|
-
/* 执行中的 wizard: 名字右边一盏呼吸灯, 会话与子项同一位置, 与回复头上的 .tg-dot 同大。 */
|
|
230
|
-
.ci .l1 .live, .si .l1 .live {
|
|
231
|
-
flex: none; align-self: center; width: 7px; height: 7px;
|
|
232
|
-
border-radius: 50%; background: #1a7f37; animation: pulse 1.4s infinite;
|
|
233
|
-
}
|
|
234
242
|
|
|
235
243
|
/* ── 右栏头: 这个群聊 / 私聊是什么 ───────────────────────────────── */
|
|
236
244
|
.main { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; background: var(--card) }
|
|
237
245
|
.chathead {
|
|
238
|
-
flex: none; display: flex; align-items: center; gap: 12px; padding: 10px 20px; min-height: 58px;
|
|
246
|
+
flex: none; display: flex; align-items: center; gap: 12px; margin: 0; padding: 10px 20px; min-height: 58px;
|
|
239
247
|
background: var(--card); border-bottom: 1px solid var(--line);
|
|
240
248
|
}
|
|
241
249
|
.chathead .back { display: none; border: 0; background: none; font-size: 22px; color: var(--mute); cursor: pointer; padding: 0 4px }
|
|
@@ -249,10 +257,13 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
249
257
|
.ch-who .pair .av + .av { margin-left: -8px; box-shadow: -2px 0 0 var(--card) }
|
|
250
258
|
.ch-who .pair .av.go { cursor: pointer }
|
|
251
259
|
.ch-who .pair .av.go:hover { border-color: var(--accent) }
|
|
252
|
-
|
|
253
|
-
.ch-who
|
|
254
|
-
.ch-who
|
|
255
|
-
.ch-
|
|
260
|
+
/* 标题先让位 (min-width:0), 两端头像与右侧按钮不让。 */
|
|
261
|
+
.ch-who .t { min-width: 0; font-size: 16px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
262
|
+
.ch-who > .t:not(:only-child) { flex: 0 1 auto }
|
|
263
|
+
.ch-who .sub { min-width: 0; font-size: 11.5px; color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
264
|
+
.ch-acts { display: flex; gap: 8px; align-items: center; flex: 0 1 auto; min-width: 0; font-size: 12px; color: var(--mute) }
|
|
265
|
+
.ch-acts .with { min-width: 0; max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
266
|
+
.ch-acts .vb { flex: none }
|
|
256
267
|
.vb {
|
|
257
268
|
font-size: 12.5px; background: var(--card); border: 1px solid var(--line); border-radius: 7px;
|
|
258
269
|
padding: 4px 11px; cursor: pointer; white-space: nowrap;
|
|
@@ -287,7 +298,8 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
287
298
|
.mrow.mine { flex-direction: row-reverse }
|
|
288
299
|
.mrow.mine .mcol { align-items: flex-end }
|
|
289
300
|
.mwho { font-size: 11.5px; color: var(--mute); display: flex; gap: 6px; align-items: center; flex-wrap: wrap }
|
|
290
|
-
.mwho .to { color: var(--faint); display: inline-flex; gap: 6px; align-items: center }
|
|
301
|
+
.mwho .to { color: var(--faint); display: inline-flex; gap: 6px; align-items: center; min-width: 0; max-width: 100% }
|
|
302
|
+
.mwho .nm { min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
291
303
|
.mwho .ch { font-size: 10.5px; border-radius: 4px; padding: 0 4px }
|
|
292
304
|
.mwho .ch.priv { color: var(--priv); background: #9a5b1014 }
|
|
293
305
|
/* 时刻只此一处 —— 气泡外, 跟着名字走。等宽数字让一列时间对得齐。 */
|
|
@@ -352,8 +364,40 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
352
364
|
.mrow.mine .flip .fi { flex-direction: row-reverse }
|
|
353
365
|
.mrow.mine .flip .fc { transform: scaleX(-1) }
|
|
354
366
|
.flip .fc { flex: none }
|
|
367
|
+
.flip .fi { min-width: 0; max-width: 100%; box-sizing: border-box; padding: 4px 8px; gap: 6px }
|
|
368
|
+
/* 要去谁那里: 名字可以折行, 不撑出门外。 */
|
|
369
|
+
.flip .fn { min-width: 0; overflow-wrap: anywhere }
|
|
355
370
|
.flip:hover, .flip:focus-visible { background: #2f55c90d; color: var(--accent) }
|
|
356
371
|
.flip[disabled] { cursor: default; background: transparent !important; color: transparent !important }
|
|
372
|
+
/* 说给谁: 贴着气泡写在门里, 与气泡首行对齐。不吃点击 —— 点到它就是点门。
|
|
373
|
+
门竖排: 描述在上、换视角箭头在下, 描述折几行箭头就跟着往下让, 两者不叠。
|
|
374
|
+
contain: size —— 门的内容不参与这一行的高度, 描述再长也不撑高一行。 */
|
|
375
|
+
.flip:has(.dest) {
|
|
376
|
+
flex-direction: column; justify-content: flex-start; gap: 6px; contain: size;
|
|
377
|
+
padding: calc(var(--av) + 12px) 4px 0;
|
|
378
|
+
}
|
|
379
|
+
/* 只留向下的吸附: 原先的 bottom 吸附会把箭头往上拽到视窗中线, 越过上面的描述。 */
|
|
380
|
+
.flip:has(.dest) .fi { bottom: auto; flex: none }
|
|
381
|
+
/* 门比描述矮 (一行短气泡) 时不许把描述压扁, 宁可溢到行外。 */
|
|
382
|
+
.flip:has(.dest) .dest { flex: none }
|
|
383
|
+
/* 压过 .mrow.mine .flip 的 flex-end: 竖排后那条是纵轴, 会把描述推到行底。 */
|
|
384
|
+
.mrow .flip:has(.dest) { justify-content: flex-start }
|
|
385
|
+
.mrow.them .flip:has(.dest) { align-items: flex-start }
|
|
386
|
+
.mrow.mine .flip:has(.dest) { align-items: flex-end }
|
|
387
|
+
.flip .dest {
|
|
388
|
+
max-width: 100%; font-size: 11px; line-height: 1.45; color: var(--faint); pointer-events: none;
|
|
389
|
+
display: flex; align-items: center; gap: 4px; max-height: calc(3 * 1.45em); overflow: hidden;
|
|
390
|
+
}
|
|
391
|
+
.flip .dest .arr { font-style: normal; flex: none }
|
|
392
|
+
.flip .dest .dav {
|
|
393
|
+
flex: none; width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--line); background: var(--card);
|
|
394
|
+
display: grid; place-items: center; font-size: 11px; line-height: 1;
|
|
395
|
+
}
|
|
396
|
+
.flip .dest .dn { min-width: 0; overflow-wrap: anywhere }
|
|
397
|
+
.mrow.them .flip .dest { text-align: left }
|
|
398
|
+
.mrow.mine .flip .dest { text-align: right; justify-content: flex-end }
|
|
399
|
+
.flip[disabled] .dest { color: var(--faint) }
|
|
400
|
+
.mwho .to { display: none }
|
|
357
401
|
.mwho .av.go { cursor: pointer }
|
|
358
402
|
.mwho .av.go:hover { border-color: var(--accent); background: #2f55c914 }
|
|
359
403
|
|
|
@@ -392,6 +436,8 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
392
436
|
保温 ping 不是对话, 但它是真花销 —— 所以留在时间轴上, 只是收成一行虚线。 */
|
|
393
437
|
/* summary 的灰底 / 底线是 SHARED_CSS 里通用 details 的 —— 圆角得自己裁, 底线只在展开时才是分割线。 */
|
|
394
438
|
.ping-fold { border: 1px dashed #d8dee4; border-radius: 10px; background: #fff; overflow: hidden }
|
|
439
|
+
/* 暂时整条藏起来 —— 行仍折在 details 里, 折叠 / FLIP 逻辑照旧, 删掉这行即恢复。 */
|
|
440
|
+
.ping-fold { display: none }
|
|
395
441
|
.ping-fold:not([open]) > .ping-sum { border-bottom: 0 }
|
|
396
442
|
.ping-fold > .ping-sum {
|
|
397
443
|
display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: #fff;
|
|
@@ -414,6 +460,7 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
414
460
|
}
|
|
415
461
|
.ping-fold .mcol { max-width: 100% }
|
|
416
462
|
.ping-fold .flip { display: none }
|
|
463
|
+
.ping-fold .mwho .to { display: inline-flex }
|
|
417
464
|
/* 折叠里的气泡同是白底 —— 描一圈虚线跟对话气泡分开, 与外框一个语气。 */
|
|
418
465
|
.ping-fold .mb :is(.bubble.mq, .say > .bubble) { border: 1px dashed var(--bub-line) }
|
|
419
466
|
|
|
@@ -428,11 +475,10 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
428
475
|
.thread { padding: 12px }
|
|
429
476
|
.mcol { max-width: calc(86% + var(--av)) }
|
|
430
477
|
.flip { min-width: 16px; padding: 0 4px; font-size: 0 }
|
|
478
|
+
.flip .dest { display: none }
|
|
479
|
+
.mwho .to { display: inline-flex }
|
|
431
480
|
.thread { padding-bottom: calc(12px + env(safe-area-inset-bottom)) }
|
|
432
|
-
.usage { padding: 8px 12px
|
|
433
|
-
.usage .u-kvs, .usage .leg { flex-wrap: wrap }
|
|
434
|
-
.usage .u-io { flex: 1 1 100%; flex-wrap: wrap; gap: 6px 12px }
|
|
435
|
-
.usage .bar { flex: 1 1 100%; width: auto }
|
|
481
|
+
.usage { padding: 8px 12px }
|
|
436
482
|
.usage.page { padding-bottom: calc(8px + env(safe-area-inset-bottom)) }
|
|
437
483
|
}
|
|
438
484
|
|
|
@@ -448,139 +494,12 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
448
494
|
padding: 8px 20px; background: #fff; border-bottom: 1px solid #d0d7de;
|
|
449
495
|
font-size: 11.5px; color: #57606a;
|
|
450
496
|
}
|
|
451
|
-
.
|
|
452
|
-
|
|
453
|
-
只会让人在两处之间对照颜色。 */
|
|
454
|
-
.wtools .chip {
|
|
455
|
-
display: flex; align-items: center; gap: 5px; font: inherit; cursor: pointer;
|
|
456
|
-
background: #fff; border: 1px solid #d0d7de; border-radius: 13px; padding: 2px 10px;
|
|
457
|
-
color: #8c959f;
|
|
458
|
-
}
|
|
459
|
-
.wtools .chip i { width: 14px; height: 0; border-top: 2px solid var(--c); opacity: .35 }
|
|
460
|
-
.wtools .chip b { font-variant-numeric: tabular-nums; font-weight: 700 }
|
|
461
|
-
.wtools .chip.on { color: #1f2328; border-color: var(--c) }
|
|
462
|
-
.wtools .chip.on i { opacity: 1 }
|
|
463
|
-
.wtools .chip.clear, .wtools .chip.only { border-color: #d0d7de; color: #57606a }
|
|
464
|
-
.wtools .chip.only.on { border-color: #0969da; color: #0550ae; background: #ddf4ff }
|
|
465
|
-
.wtools .wstat { margin-left: auto; color: #8c959f; font-variant-numeric: tabular-nums }
|
|
466
|
-
.wtools .wstat b { color: #0969da }
|
|
497
|
+
.wtools .wstat { flex: 1; display: flex; gap: 6px; align-items: baseline; color: #8c959f }
|
|
498
|
+
.wtools .rng { color: var(--ink) }
|
|
467
499
|
.wtools .warn { color: #9a6700 }
|
|
468
|
-
.wtools .hint { margin-left:
|
|
469
|
-
|
|
470
|
-
/* position 不是装饰: 力导向的画布是 `position:absolute; inset:0`, 没有这一行它
|
|
471
|
-
就贴到更外层的定位祖先上去 —— 坐标原点跑到顶栏, 节点飘到工具条上面, 而
|
|
472
|
-
overflow:hidden 也拦不住一个容器块在自己之外的绝对定位子元素。 */
|
|
500
|
+
.wtools .hint { margin-left: auto; color: #b1bac4 }
|
|
473
501
|
.wscroll { position: relative; flex: 1; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch }
|
|
474
502
|
.wmap { position: relative; padding: 18px 20px 28px; min-width: min-content }
|
|
475
|
-
/* 有关系的节点带一道左侧色条 —— 76 个会话里哪几个真的在协作, 不点开也看得见。 */
|
|
476
|
-
.wnode.rel::before {
|
|
477
|
-
content: ""; position: absolute; left: 1px; top: 8px; bottom: 8px;
|
|
478
|
-
width: 2px; border-radius: 1px; background: #0969da66;
|
|
479
|
-
}
|
|
480
|
-
/* 连线层铺满整张图并且不吃事件 —— 节点的点击/双击必须照常穿过去。
|
|
481
|
-
z-index 把它抬到卡片之上: 卡片是不透明的, 压在下面时一条跨卡片的边会被中途
|
|
482
|
-
吃掉半截, 读出来像是断的。.wgrid 不设 z-index (保持 auto) 才不会自成一个层叠
|
|
483
|
-
上下文 —— 那样悬停/聚焦的节点就再也抬不过这条线了。 */
|
|
484
|
-
.wedges { position: absolute; inset: 0; pointer-events: none; overflow: visible; z-index: 2 }
|
|
485
|
-
/* 反过来: 正在看的那个节点要压过连线, 否则文字被线划着读。只抬这两种 —— 一直
|
|
486
|
-
抬着某个节点等于把"线被卡片吃掉"这个毛病在它身上留一份。 */
|
|
487
|
-
.wnode:hover, .wnode.sel { z-index: 3 }
|
|
488
|
-
/* 多列流式而不是 grid: 聊天卡片的高度天差地别 (一个群 2 个 wizard, 另一个 20 个),
|
|
489
|
-
grid 的行高按本行最高的那张对齐, 于是矮卡片下面全是空白 —— 图看着比实际稀疏
|
|
490
|
-
一倍。CSS columns 是砌砖式的: 卡片顺着列往下码, 码满了换列, 没有行的概念。
|
|
491
|
-
列宽钉在 320 附近也顺带收住了"两张卡片各占半个屏"的过度拉伸。 */
|
|
492
|
-
.wgrid { position: relative; columns: 320px; column-gap: 16px }
|
|
493
|
-
|
|
494
|
-
.wchat {
|
|
495
|
-
background: #fff; border: 1px solid #d0d7de; border-radius: 12px; overflow: hidden;
|
|
496
|
-
/* 一张卡片不能被切成两列 —— 断在半截的家谱读不出父子关系。 */
|
|
497
|
-
break-inside: avoid; -webkit-column-break-inside: avoid; page-break-inside: avoid;
|
|
498
|
-
margin-bottom: 16px;
|
|
499
|
-
}
|
|
500
|
-
/* 卡片头可点 = 进那个群 (见 chat.js 的 openNode)。 */
|
|
501
|
-
.wch.go { cursor: pointer }
|
|
502
|
-
.wch.go:hover .nm { color: #0969da; text-decoration: underline }
|
|
503
|
-
/* 当前聊天是读图的锚点, 给它一道明确的边 —— 其余的群一律等价, 不再分轻重。 */
|
|
504
|
-
.wchat.self { border-color: #0969da66; box-shadow: 0 0 0 3px #0969da10 }
|
|
505
|
-
.wch {
|
|
506
|
-
display: flex; align-items: baseline; gap: 8px; padding: 9px 13px;
|
|
507
|
-
border-bottom: 1px solid #eaeef2; background: #f6f8fa;
|
|
508
|
-
}
|
|
509
|
-
.wchat.self .wch { background: #f0f6ff }
|
|
510
|
-
.wch .nm {
|
|
511
|
-
font-size: 13px; font-weight: 700; min-width: 0; overflow: hidden;
|
|
512
|
-
text-overflow: ellipsis; white-space: nowrap;
|
|
513
|
-
}
|
|
514
|
-
.wch .here {
|
|
515
|
-
font-size: 10px; color: #0969da; background: #0969da14; border-radius: 4px; padding: 1px 5px;
|
|
516
|
-
}
|
|
517
|
-
.wch .ct {
|
|
518
|
-
margin-left: auto; font-size: 11px; color: #8c959f; flex: none;
|
|
519
|
-
font-family: ui-monospace, Menlo, monospace;
|
|
520
|
-
}
|
|
521
|
-
.wch .ct em { color: #1a7f37; font-style: normal; font-weight: 700 }
|
|
522
|
-
/* 左内边距是同卡片内连线的车道 —— 一条 `#a → #b` 的派活边从这里绕过去, 不必
|
|
523
|
-
拐出卡片 (拐出去就会被滚动容器裁掉)。 */
|
|
524
|
-
.wrows { padding: 7px 10px 10px 22px; display: flex; flex-direction: column; gap: 3px }
|
|
525
|
-
|
|
526
|
-
.wnode {
|
|
527
|
-
position: relative; display: flex; gap: 8px; align-items: flex-start;
|
|
528
|
-
padding: 6px 8px; border-radius: 8px; cursor: pointer;
|
|
529
|
-
border: 1px solid transparent; transition: opacity .15s, background .12s;
|
|
530
|
-
}
|
|
531
|
-
.wnode:hover { background: #f6f8fa }
|
|
532
|
-
.wnode.self { background: #fffbe8 }
|
|
533
|
-
.wnode.sel { background: #eef4fc; border-color: #0969da55 }
|
|
534
|
-
/* 聚焦时无关节点压暗而不是移除 —— 位置不动, 连点几个节点版面也不跳。 */
|
|
535
|
-
.wnode.dim { opacity: .3 }
|
|
536
|
-
/* 双击能走进去的那些 —— 外聊天的节点现在也算 (整页跳过去)。 */
|
|
537
|
-
.wnode.go { cursor: pointer }
|
|
538
|
-
.wnode.cold .wav { filter: grayscale(1); opacity: .55 }
|
|
539
|
-
/* 缩进本身就是家谱; 这道折线只是把"缩给谁看"指实。 */
|
|
540
|
-
.wnode .lin {
|
|
541
|
-
position: absolute; left: -9px; top: 0; bottom: 50%; width: 9px;
|
|
542
|
-
border-left: 1.5px solid #d8cdf0; border-bottom: 1.5px solid #d8cdf0;
|
|
543
|
-
border-bottom-left-radius: 6px;
|
|
544
|
-
}
|
|
545
|
-
/* 子 wizard 不是 fork: 折线换成虚线、换色, 与分身一眼分开 (同关系图的 spawn 边)。 */
|
|
546
|
-
.wnode .lin.sp { border-style: dashed; border-color: #f0d2bd }
|
|
547
|
-
.wav {
|
|
548
|
-
position: relative; width: 26px; height: 26px; flex: none; border-radius: 8px;
|
|
549
|
-
background: #f1f3f6; border: 1px solid #eaeef2;
|
|
550
|
-
display: flex; align-items: center; justify-content: center; font-size: 14px;
|
|
551
|
-
}
|
|
552
|
-
.wav .live {
|
|
553
|
-
position: absolute; right: -3px; bottom: -3px; width: 9px; height: 9px;
|
|
554
|
-
border-radius: 50%; background: #1a7f37; border: 2px solid #fff;
|
|
555
|
-
animation: pulse 1.4s infinite;
|
|
556
|
-
}
|
|
557
|
-
.wbody { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px }
|
|
558
|
-
.wl1 { display: flex; align-items: baseline; gap: 6px; min-width: 0 }
|
|
559
|
-
.wname {
|
|
560
|
-
font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden;
|
|
561
|
-
text-overflow: ellipsis; white-space: nowrap;
|
|
562
|
-
}
|
|
563
|
-
.wnode.run .wname { color: #1a7f37 }
|
|
564
|
-
.wtag {
|
|
565
|
-
flex: none; font-size: 10.5px; color: #57606a; background: #f1f3f6;
|
|
566
|
-
border-radius: 4px; padding: 0 5px; font-family: ui-monospace, Menlo, monospace;
|
|
567
|
-
}
|
|
568
|
-
.wtag.def { color: #8c959f }
|
|
569
|
-
.wih { flex: none; font-size: 11px; color: #6639ba }
|
|
570
|
-
.wts {
|
|
571
|
-
margin-left: auto; flex: none; font-size: 10.5px; color: #8c959f;
|
|
572
|
-
font-family: ui-monospace, Menlo, monospace;
|
|
573
|
-
}
|
|
574
|
-
.wjob { font-size: 11.5px; color: #0550ae; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
575
|
-
.wprev {
|
|
576
|
-
font-size: 11.5px; color: #656d76; overflow: hidden; line-height: 1.4;
|
|
577
|
-
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
578
|
-
}
|
|
579
|
-
.wmeta {
|
|
580
|
-
font-size: 10.5px; color: #8c959f; font-family: ui-monospace, Menlo, monospace;
|
|
581
|
-
display: flex; gap: 4px; flex-wrap: wrap; margin-top: 1px;
|
|
582
|
-
}
|
|
583
|
-
.wmeta .sep { opacity: .45 }
|
|
584
503
|
|
|
585
504
|
/* ══ 日程 ═══════════════════════════════════════════════════════════ */
|
|
586
505
|
.plan-in { flex: 1; min-height: 0; overflow-y: auto; padding: 18px 20px 28px }
|
|
@@ -615,32 +534,18 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
615
534
|
position: relative; height: 8px; border-radius: 4px; background: #eaeef2; margin: 3px 0 7px;
|
|
616
535
|
}
|
|
617
536
|
.strip .pin {
|
|
618
|
-
position: absolute; top: -
|
|
619
|
-
border-radius: 3px; background: #9a6700; box-shadow: 0 0 0 2px #fff;
|
|
620
|
-
}
|
|
621
|
-
.strip .cap { font-size: 11px; color: #8c959f }
|
|
622
|
-
|
|
623
|
-
.prow {
|
|
624
|
-
display: flex; gap: 16px; background: #fff; border: 1px solid #d0d7de;
|
|
625
|
-
border-radius: 10px; padding: 12px 16px; margin-bottom: 10px;
|
|
626
|
-
}
|
|
627
|
-
.prow .pl { flex: none; width: 152px; border-right: 1px dashed #eaeef2; padding-right: 14px }
|
|
628
|
-
.pwhen { font-size: 11.5px; color: #9a6700; font-weight: 600 }
|
|
629
|
-
.pnext {
|
|
630
|
-
display: flex; align-items: baseline; gap: 6px; margin-top: 5px;
|
|
631
|
-
font-family: ui-monospace, Menlo, monospace;
|
|
537
|
+
position: absolute; top: -4px; width: 10px; height: 16px; margin-left: -5px; padding: 0; cursor: pointer;
|
|
538
|
+
border: 0; border-radius: 3px; background: #9a6700; box-shadow: 0 0 0 2px #fff;
|
|
632
539
|
}
|
|
633
|
-
.
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
.ph { display: flex; align-items: center; gap: 7px; flex-wrap: wrap }
|
|
637
|
-
.ph .note { font-size: 11px; color: #57606a }
|
|
638
|
-
.ph .pid {
|
|
639
|
-
margin-left: auto; font-size: 10px; color: #b1bac4;
|
|
640
|
-
font-family: ui-monospace, Menlo, monospace;
|
|
540
|
+
.strip .pin span {
|
|
541
|
+
position: absolute; bottom: 19px; left: 50%; transform: translateX(-50%); white-space: nowrap;
|
|
542
|
+
font: 600 9.5px ui-monospace, Menlo, monospace; color: #9a6700; opacity: 0; transition: opacity .12s; pointer-events: none;
|
|
641
543
|
}
|
|
642
|
-
.
|
|
643
|
-
.
|
|
544
|
+
.strip .pin:hover span, .strip .pin:focus-visible span { opacity: 1 }
|
|
545
|
+
.strip .pin:hover { transform: scaleY(1.15) }
|
|
546
|
+
.strip .pin.bad { background: #cf222e }
|
|
547
|
+
.strip .pin.bad span { color: #cf222e }
|
|
548
|
+
.strip .cap { font-size: 11px; color: #8c959f }
|
|
644
549
|
|
|
645
550
|
/* wizard 徽标 —— 日程/工单里凡是提到一个 wizard 都用它, 同聊天的可点进线程。 */
|
|
646
551
|
.wchip {
|
|
@@ -684,69 +589,15 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
684
589
|
@media (max-width: 760px) {
|
|
685
590
|
.chathead .vb { padding: 3px 8px }
|
|
686
591
|
.wmap { padding: 12px }
|
|
687
|
-
.wgrid { columns: 1 }
|
|
688
592
|
.plan-in { padding: 12px }
|
|
689
|
-
.
|
|
690
|
-
.
|
|
691
|
-
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
/* 相关性筛掉的那些 —— 说一声它们还在, 但不占图的位置 (见 shared/world 的说明)。 */
|
|
695
|
-
.wmore {
|
|
696
|
-
padding: 5px 13px 9px; font-size: 10.5px; color: #b1bac4;
|
|
697
|
-
border-top: 1px dashed #eaeef2; margin-top: 2px;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
/* ══ 关系视图 · 力导向布局 ═════════════════════════════════════════
|
|
701
|
-
卡片布局之外的另一种读法: 节点只画 wizard, 聊天不再是容器而是节点身上的一
|
|
702
|
-
道色条 + 一行群名。见 web/chat.js 的说明。 */
|
|
703
|
-
.wscroll.fx { overflow: hidden }
|
|
704
|
-
.wmap.force { position: absolute; inset: 0; padding: 0; min-width: 0 }
|
|
705
|
-
.fxn {
|
|
706
|
-
position: absolute; left: 0; top: 0; z-index: 2;
|
|
707
|
-
display: flex; align-items: center; gap: 7px; max-width: 210px;
|
|
708
|
-
padding: 5px 10px 5px 7px; border-radius: 10px;
|
|
709
|
-
background: #fff; border: 1px solid #d0d7de; border-left: 3px solid var(--c);
|
|
710
|
-
box-shadow: 0 1px 3px #1b1f2412; cursor: grab; touch-action: none;
|
|
711
|
-
user-select: none; -webkit-user-select: none;
|
|
712
|
-
transition: opacity .15s, box-shadow .12s;
|
|
713
|
-
will-change: transform;
|
|
714
|
-
}
|
|
715
|
-
.fxn .wav { width: 22px; height: 22px; border-radius: 7px; font-size: 12px }
|
|
716
|
-
.fxn .wav .live { width: 8px; height: 8px; right: -2px; bottom: -2px }
|
|
717
|
-
.fxb { min-width: 0; display: flex; flex-direction: column; gap: 0 }
|
|
718
|
-
.fxn .wname { font-size: 12px }
|
|
719
|
-
/* 群名压得比名字轻 —— 它是节点的属性, 不是节点本身。 */
|
|
720
|
-
.fxc {
|
|
721
|
-
font-size: 9.5px; color: var(--c); opacity: .85; overflow: hidden;
|
|
722
|
-
text-overflow: ellipsis; white-space: nowrap;
|
|
723
|
-
}
|
|
724
|
-
.fxn.self { background: #fffbe8 }
|
|
725
|
-
.fxn.cold { opacity: .72 }
|
|
726
|
-
.fxn.cold .wav { filter: grayscale(1); opacity: .55 }
|
|
727
|
-
.fxn.run .wname { color: #1a7f37 }
|
|
728
|
-
.fxn.dim { opacity: .22 }
|
|
729
|
-
.fxn.sel { box-shadow: 0 0 0 3px var(--c), 0 1px 3px #1b1f2412; }
|
|
730
|
-
.fxn.sel .fxc { opacity: 1 }
|
|
731
|
-
.fxn.drag { cursor: grabbing; box-shadow: 0 6px 16px #1b1f2426 }
|
|
732
|
-
/* 钉住 = 这个位置是人摆的, 力不再动它。 */
|
|
733
|
-
.fxn.pin::after {
|
|
734
|
-
content: "📌"; position: absolute; right: -5px; top: -7px; font-size: 9px;
|
|
735
|
-
opacity: .8; pointer-events: none;
|
|
736
|
-
}
|
|
737
|
-
/* 布局开关 —— 两种读法并列, 不是复选。 */
|
|
738
|
-
.wtools .wlay { display: inline-flex; border: 1px solid #d0d7de; border-radius: 7px; overflow: hidden }
|
|
739
|
-
.wtools .lb {
|
|
740
|
-
border: 0; background: #fff; cursor: pointer; padding: 3px 9px;
|
|
741
|
-
font-size: 11.5px; color: #57606a; font-family: inherit;
|
|
742
|
-
}
|
|
743
|
-
.wtools .lb + .lb { border-left: 1px solid #d0d7de }
|
|
744
|
-
.wtools .lb.on { background: #ddf4ff; color: #0550ae; font-weight: 600 }
|
|
593
|
+
.tcard { flex-direction: column; gap: 8px }
|
|
594
|
+
.tc-time { width: auto; flex-direction: row; align-items: baseline; gap: 8px; border-right: 0; padding: 0 }
|
|
595
|
+
}
|
|
745
596
|
|
|
746
597
|
/* ══ 关系 / 日程 ═══════════════════════════════════════════════════ */
|
|
747
598
|
/* 都是当前 role 的另一面, 侧栏 (它的会话) 留着 —— 点一个会话就回到对话。
|
|
748
599
|
会话标题条与页脚总账只属于对话视图。 */
|
|
749
|
-
.pane { flex: 1; min-height: 0; display: flex; flex-direction: column; background: #fafbfc }
|
|
600
|
+
.pane { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; background: #fafbfc }
|
|
750
601
|
|
|
751
602
|
/* 过程框里的工具行是 nowrap 的 —— 不裁一刀会把整列撑出横向滚动。 */
|
|
752
603
|
.mb > .turn-group { overflow: hidden }
|
|
@@ -759,3 +610,234 @@ span.av.go:hover { background: #2f55c924; box-shadow: 0 0 0 3px #2f55c924 }
|
|
|
759
610
|
.rem.raw { flex-basis: 100% }
|
|
760
611
|
.rem.raw .rem-raw { display: block }
|
|
761
612
|
.rem.raw .rem-tag { display: none }
|
|
613
|
+
|
|
614
|
+
/* ══ 忙闲: 名字右边唯一的状态位 (名片 · 关系树 · 侧栏共用 stTag) ══
|
|
615
|
+
只有执行中带颜色与呼吸; 空字 (侧栏) 就只剩那盏灯。 */
|
|
616
|
+
.wst {
|
|
617
|
+
flex: none; align-self: center; display: inline-flex; align-items: center; gap: 4px; font-size: 10px; line-height: 16px;
|
|
618
|
+
padding: 0 6px; border-radius: 8px; background: #eef0f3; color: var(--mute); white-space: nowrap; font-weight: 500;
|
|
619
|
+
}
|
|
620
|
+
.wst::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #b1bac4 }
|
|
621
|
+
.wst.run { background: #dafbe1; color: #1a7f37 }
|
|
622
|
+
.wst.run::before { background: #1a7f37; animation: pulse 1.4s infinite }
|
|
623
|
+
.wst.off { background: transparent; color: var(--faint); box-shadow: inset 0 0 0 1px var(--line) }
|
|
624
|
+
.wst.off::before { background: transparent; box-shadow: inset 0 0 0 1.5px #b1bac4 }
|
|
625
|
+
.wst:empty { padding: 0; background: none; box-shadow: none }
|
|
626
|
+
.wst:empty::before { width: 7px; height: 7px }
|
|
627
|
+
/* ══ 关系图 · 关系树 (家谱与派活合成一棵, 以当前 role 为中心) ══════════
|
|
628
|
+
它替换的是侧栏的会话列表: 标题、图例与会话列表的分组标题同一种读法, 卡片就是会话项 (.ci)。 */
|
|
629
|
+
.tview .tall {
|
|
630
|
+
margin-left: auto; border: 0; background: none; padding: 0 2px; cursor: pointer; font-size: 11px; color: var(--faint);
|
|
631
|
+
text-decoration: underline dotted; text-underline-offset: 3px;
|
|
632
|
+
}
|
|
633
|
+
.tview .tall:hover { color: var(--accent) }
|
|
634
|
+
.tview h2 .warn { color: #9a6700; font-weight: 400 }
|
|
635
|
+
.tree.all > li + li { margin-top: 10px; padding-top: 10px; border-top: 1px dashed #eaeef2 }
|
|
636
|
+
.tfold { flex: none; font-size: 10px; font-weight: 400; color: var(--faint); border: 1px dashed var(--line); border-radius: 8px; padding: 0 5px; line-height: 14px }
|
|
637
|
+
.tsolo { font-size: 11.5px; color: var(--faint); margin: 0 8px 10px }
|
|
638
|
+
.tview .pempty { padding: 18px 8px }
|
|
639
|
+
|
|
640
|
+
/* 树: 每条入边是一道实线, 从父卡片底下一路落到自己卡片的头像旁, 末端一枚箭头, 颜色 = 关系种类。
|
|
641
|
+
兄弟共用的那段竖干上, 后画的 (更下方的节点) 盖住先画的; 竖线往上伸到 ul 顶为止 (clip-path 只裁上边)。 */
|
|
642
|
+
.tree, .tree ul { list-style: none; margin: 0; padding: 0 }
|
|
643
|
+
.tree ul { padding-left: 20px; clip-path: inset(0 -100vw -100vh -100vw) }
|
|
644
|
+
.tree li { position: relative; padding-top: 14px }
|
|
645
|
+
.tree > li { padding-top: 0 }
|
|
646
|
+
.tree ul > li::before {
|
|
647
|
+
content: ""; position: absolute; left: -10px; top: -9999px; height: calc(9999px + 39px); width: 10px;
|
|
648
|
+
border-left: 1.5px solid var(--lc); border-bottom: 1.5px solid var(--lc); border-bottom-left-radius: 7px;
|
|
649
|
+
}
|
|
650
|
+
.tree ul > li::after {
|
|
651
|
+
content: ""; position: absolute; left: -6px; top: 34px; border: 4.5px solid transparent; border-right: 0;
|
|
652
|
+
border-left: 7px solid var(--lc);
|
|
653
|
+
}
|
|
654
|
+
.tree li.spawn { --lc: #d4700f }
|
|
655
|
+
.tree li.clone { --lc: #8250df }
|
|
656
|
+
.tree li.peer { --lc: #0969da }
|
|
657
|
+
.tree li.job { --lc: #bf8700 }
|
|
658
|
+
.tree li.graph { --lc: #0a7d6b }
|
|
659
|
+
/* 卡片 = 会话项; label 骑在它左上角, 紧挨箭头。 */
|
|
660
|
+
.tci { position: relative; overflow: visible }
|
|
661
|
+
.tci.me .t .nm { color: var(--accent) }
|
|
662
|
+
/* 连接用的祖先: 没和视角对过话, 只为把对过话的后代挂回家谱 —— 淡一档。 */
|
|
663
|
+
.tci.via { opacity: .55 }
|
|
664
|
+
.tci.via:hover { opacity: 1 }
|
|
665
|
+
.tlab { position: absolute; left: 4px; top: -8px; display: flex; gap: 3px; z-index: 2 }
|
|
666
|
+
.tlab .ek { box-shadow: 0 0 0 2px var(--card) }
|
|
667
|
+
|
|
668
|
+
/* 边的 label: 辅助信息, 淡色; 一条边可能同时带几种 (既是子 wizard 又被派过活), 各一枚。 */
|
|
669
|
+
.ek {
|
|
670
|
+
flex: none; font-size: 10px; line-height: 15px; padding: 0 5px; border-radius: 4px; white-space: nowrap;
|
|
671
|
+
font-weight: 500; color: var(--mute); background: #f1f3f6;
|
|
672
|
+
}
|
|
673
|
+
.ek.spawn { color: #a8642a; background: #d4700f12 }
|
|
674
|
+
.ek.clone { color: #7a5bb8; background: #8250df12 }
|
|
675
|
+
.ek.peer { color: #4a74b0; background: #0969da10 }
|
|
676
|
+
.ek.job { color: #94741f; background: #bf870014 }
|
|
677
|
+
.ek.graph { color: #3d8577; background: #0a7d6b12 }
|
|
678
|
+
.ek.cross { font-weight: 400; background: #fff; box-shadow: inset 0 0 0 1px var(--line) }
|
|
679
|
+
|
|
680
|
+
/* ══ 日程 · 总览 / 任务卡 ════════════════════════════════════════════ */
|
|
681
|
+
.pstats {
|
|
682
|
+
max-width: 900px; margin: 0 auto 18px; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px;
|
|
683
|
+
}
|
|
684
|
+
.pst {
|
|
685
|
+
background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 10px 14px;
|
|
686
|
+
display: flex; flex-direction: column; gap: 2px; min-width: 0;
|
|
687
|
+
}
|
|
688
|
+
.pst .k { font-size: 11px; color: var(--mute) }
|
|
689
|
+
.pst b { font-size: 20px; line-height: 26px; font-variant-numeric: tabular-nums; font-family: ui-monospace, Menlo, monospace }
|
|
690
|
+
.pst b small { font-size: 12px; color: var(--faint); font-weight: 400 }
|
|
691
|
+
.pst .s { font-size: 11px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
692
|
+
.pst.bad { border-color: #cf222e66; background: #fff6f6 }
|
|
693
|
+
.pst.bad b, .pst.bad .k { color: #cf222e }
|
|
694
|
+
|
|
695
|
+
.tcard {
|
|
696
|
+
display: flex; gap: 16px; background: #fff; border: 1px solid var(--line); border-radius: 12px;
|
|
697
|
+
padding: 12px 16px; margin-bottom: 10px; transition: box-shadow .2s, border-color .2s;
|
|
698
|
+
}
|
|
699
|
+
.tcard:hover { border-color: #b9c3d3 }
|
|
700
|
+
.tcard.bad { border-color: #cf222e55; border-left: 3px solid #cf222e }
|
|
701
|
+
.tcard.flash { animation: flash 1.2s ease-out }
|
|
702
|
+
@keyframes flash { 0% { box-shadow: 0 0 0 4px #9a670055 } 100% { box-shadow: 0 0 0 4px #9a670000 } }
|
|
703
|
+
.tc-time {
|
|
704
|
+
flex: none; width: 92px; display: flex; flex-direction: column; gap: 1px;
|
|
705
|
+
border-right: 1px dashed #eaeef2; padding-right: 14px;
|
|
706
|
+
}
|
|
707
|
+
.tc-time b { font: 700 22px/28px ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; color: var(--ink) }
|
|
708
|
+
.tc-time span { font-size: 11px; color: var(--mute) }
|
|
709
|
+
.tc-time em { font-style: normal; font-size: 11px; color: #9a6700; font-weight: 600 }
|
|
710
|
+
.tc-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 7px }
|
|
711
|
+
.perr {
|
|
712
|
+
font-size: 11.5px; color: #82071e; background: #ffebe9; border: 1px solid #ff818266; border-radius: 8px;
|
|
713
|
+
padding: 6px 10px; line-height: 1.5;
|
|
714
|
+
}
|
|
715
|
+
.perr b { font-weight: 700 }
|
|
716
|
+
.perr code {
|
|
717
|
+
display: block; margin-top: 3px; font: 11px/1.5 ui-monospace, Menlo, monospace; color: #a40e26;
|
|
718
|
+
white-space: pre-wrap; word-break: break-word;
|
|
719
|
+
}
|
|
720
|
+
.prule { display: flex; gap: 5px; flex-wrap: wrap }
|
|
721
|
+
.rl { font-size: 11px; line-height: 18px; padding: 0 7px; border-radius: 9px; white-space: nowrap }
|
|
722
|
+
.rl.clock { color: #7d4e00; background: #fff8c5; border: 1px solid #d4a72c66; font-weight: 600 }
|
|
723
|
+
.rl.guard { color: var(--mute); background: #f1f3f6; border: 1px solid #e4e8ee }
|
|
724
|
+
.ptitle { font-size: 13px; font-weight: 600; line-height: 1.45; word-break: break-word }
|
|
725
|
+
.pflow { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; font-size: 11.5px }
|
|
726
|
+
.pflow .fl { color: var(--faint) }
|
|
727
|
+
.pflow .ar { color: var(--faint) }
|
|
728
|
+
.pflow .fresh { color: #6639ba; background: #8250df12; border-radius: 10px; padding: 0 7px; line-height: 18px }
|
|
729
|
+
.pprompt { font-size: 11.5px; border-radius: 8px; background: #f6f8fa; border: 1px solid #eaeef2 }
|
|
730
|
+
.pprompt summary {
|
|
731
|
+
text-transform: none; letter-spacing: 0; font-weight: 400; cursor: pointer; padding: 5px 10px; color: var(--mute); display: flex; gap: 8px; min-width: 0; list-style: none;
|
|
732
|
+
}
|
|
733
|
+
.pprompt summary::-webkit-details-marker { display: none }
|
|
734
|
+
.pprompt summary::before { content: "▸"; color: var(--faint); transition: transform .12s }
|
|
735
|
+
.pprompt[open] summary::before { transform: rotate(90deg) }
|
|
736
|
+
.pprompt summary span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); opacity: .75 }
|
|
737
|
+
.pprompt pre {
|
|
738
|
+
margin: 0; padding: 8px 12px 10px; border-top: 1px solid #eaeef2; max-height: 280px; overflow: auto;
|
|
739
|
+
font: 11.5px/1.55 ui-monospace, Menlo, monospace; white-space: pre-wrap; word-break: break-word;
|
|
740
|
+
}
|
|
741
|
+
.pfoot { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 10.5px; color: var(--faint) }
|
|
742
|
+
.pfoot .pid { margin-left: auto; font-family: ui-monospace, Menlo, monospace; color: #b1bac4 }
|
|
743
|
+
.gt { border-radius: 4px; padding: 0 6px; line-height: 16px; font-weight: 600 }
|
|
744
|
+
.gt.none { color: var(--faint); background: #f1f3f6; font-weight: 400 }
|
|
745
|
+
.gt.go { color: #1a7f37; background: #dafbe1 }
|
|
746
|
+
.gt.skip { color: #57606a; background: #eaeef2 }
|
|
747
|
+
.gt.err { color: #fff; background: #cf222e }
|
|
748
|
+
.jh .jst { border-radius: 4px; padding: 0 6px; background: #eaeef2 }
|
|
749
|
+
.jrow.open .jh .jst { background: #dafbe1 }
|
|
750
|
+
.jmm .wst { font-size: 9.5px }
|
|
751
|
+
.jmm .tmp, .jmm .wchip { flex: none; white-space: nowrap }
|
|
752
|
+
|
|
753
|
+
/* ── 搜索 (⌘K): 名片下、关系/日程入口上的搜索框 + 居中浮层 ──────────────
|
|
754
|
+
入口与会话项同圆角, 安静的浅灰底; 浮层的结果行沿用会话项的两行读法。 */
|
|
755
|
+
.sbox {
|
|
756
|
+
flex: none; display: flex; align-items: center; gap: 8px; margin: 10px 10px 4px; padding: 7px 10px;
|
|
757
|
+
border: 1px solid var(--line); border-radius: 9px; background: var(--paper); color: var(--faint);
|
|
758
|
+
cursor: pointer; text-align: left; transition: border-color .12s, background .12s, color .12s;
|
|
759
|
+
}
|
|
760
|
+
.sbox:hover { border-color: #c4cbd6; background: var(--card); color: var(--mute) }
|
|
761
|
+
.sbox .ic, .sk-in .ic { flex: none; display: inline-flex }
|
|
762
|
+
.sbox .ic svg, .sk-in .ic svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round }
|
|
763
|
+
.sbox .lb { flex: 1; min-width: 0; font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
764
|
+
.sbox kbd, .sk kbd {
|
|
765
|
+
flex: none; font: 500 10.5px/1 ui-sans-serif, system-ui, -apple-system, sans-serif; color: var(--mute);
|
|
766
|
+
padding: 3px 5px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; background: var(--card);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
.sk {
|
|
770
|
+
position: fixed; inset: 0; z-index: 900; display: flex; justify-content: center; align-items: flex-start;
|
|
771
|
+
padding: 12vh 16px 16px; background: #1c243038; animation: sk-in .12s ease-out;
|
|
772
|
+
}
|
|
773
|
+
.sk[hidden] { display: none }
|
|
774
|
+
@keyframes sk-in { from { opacity: 0 } }
|
|
775
|
+
.sk-panel {
|
|
776
|
+
width: 600px; max-width: 100%; max-height: 70vh; display: flex; flex-direction: column; overflow: hidden;
|
|
777
|
+
background: var(--card); border: 1px solid var(--line); border-radius: 14px;
|
|
778
|
+
box-shadow: 0 24px 64px #1c243033, 0 4px 14px #1c24301a;
|
|
779
|
+
}
|
|
780
|
+
.sk-in { flex: none; display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--line); color: var(--faint) }
|
|
781
|
+
.sk-in .ic svg { width: 17px; height: 17px }
|
|
782
|
+
.sk-in input {
|
|
783
|
+
flex: 1; min-width: 0; border: 0; outline: 0; background: none; font: inherit; font-size: 15px; color: var(--ink);
|
|
784
|
+
}
|
|
785
|
+
.sk-in input::-webkit-search-cancel-button { display: none }
|
|
786
|
+
.sk-list { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px 8px 8px }
|
|
787
|
+
.sk-list h3 {
|
|
788
|
+
margin: 10px 8px 4px; font-size: 11.5px; font-weight: 600; color: var(--mute);
|
|
789
|
+
display: flex; align-items: baseline; gap: 6px;
|
|
790
|
+
}
|
|
791
|
+
.sk-list h3 span { font-weight: 400; color: var(--faint); font-variant-numeric: tabular-nums }
|
|
792
|
+
.sk-it {
|
|
793
|
+
display: flex; gap: 10px; align-items: center; width: 100%; text-align: left; overflow: hidden;
|
|
794
|
+
padding: 7px 10px; border: 0; border-radius: 9px; background: transparent; cursor: pointer;
|
|
795
|
+
}
|
|
796
|
+
.sk-it.on { background: #eaf0fc }
|
|
797
|
+
.sk-it.msg { align-items: flex-start }
|
|
798
|
+
.sk-it.msg > .av { margin-top: 1px }
|
|
799
|
+
.sk-it > .av {
|
|
800
|
+
flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 9px;
|
|
801
|
+
background: #f1f3f6; font-size: 17px; line-height: 1;
|
|
802
|
+
}
|
|
803
|
+
.sk-it .b { min-width: 0; flex: 1; overflow: hidden }
|
|
804
|
+
.sk-it .l1 { display: flex; align-items: baseline; gap: 8px; overflow: hidden; white-space: nowrap }
|
|
805
|
+
.sk-it .nm { font-size: 13.5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
806
|
+
.sk-it .k { margin-left: auto; flex: none; font-size: 11px; color: var(--faint); opacity: 0 }
|
|
807
|
+
.sk-it.on .k { opacity: 1; color: var(--accent) }
|
|
808
|
+
.sk-it .ts { margin-left: auto; flex: none; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums }
|
|
809
|
+
.sk-it .pv { display: block; font-size: 12px; color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
|
|
810
|
+
.sk-it .l1 .nm + .nm, .sk-it .arr + .nm { font-weight: 500; color: var(--mute) }
|
|
811
|
+
.sk-it .arr { flex: none; color: var(--faint); font-size: 11.5px }
|
|
812
|
+
.sk-it .tag { flex: none; font-size: 10.5px; color: var(--mute); background: var(--paper); border-radius: 4px; padding: 1px 5px }
|
|
813
|
+
/* 命中的那一截: 正文色, 最多两行; 命中词是这一页的视角色淡底 —— 与选中态一个色系。 */
|
|
814
|
+
.sk-it .sn {
|
|
815
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
|
|
816
|
+
margin-top: 2px; font-size: 12.5px; line-height: 1.5; color: var(--ink); word-break: break-word;
|
|
817
|
+
}
|
|
818
|
+
.sk-it mark { background: #2f55c91f; color: var(--accent); font-weight: 600; border-radius: 3px; padding: 0 1px }
|
|
819
|
+
.sk-it.on mark { background: #2f55c92e }
|
|
820
|
+
.sk-it .l3 { display: flex; align-items: center; gap: 8px; margin-top: 3px; min-width: 0 }
|
|
821
|
+
.sk-it .where {
|
|
822
|
+
display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 70%;
|
|
823
|
+
font-size: 11px; color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
824
|
+
}
|
|
825
|
+
.sk-it .where i { font-style: normal; font-size: 12px; line-height: 1 }
|
|
826
|
+
.sk-it .where.priv { color: var(--priv) }
|
|
827
|
+
.sk-it .cnt { flex: none; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums }
|
|
828
|
+
.sk-empty { padding: 18px 10px; text-align: center; font-size: 12.5px; color: var(--faint) }
|
|
829
|
+
.sk-foot {
|
|
830
|
+
flex: none; display: flex; gap: 16px; padding: 8px 16px; border-top: 1px solid var(--line);
|
|
831
|
+
font-size: 11px; color: var(--faint); background: #fafbfc;
|
|
832
|
+
}
|
|
833
|
+
.sk-foot span { display: inline-flex; align-items: center; gap: 4px }
|
|
834
|
+
.sk-foot kbd { padding: 2px 4px }
|
|
835
|
+
@media (max-width: 760px) {
|
|
836
|
+
.sk { padding-top: 8px }
|
|
837
|
+
.sk-panel { max-height: calc(100dvh - 16px) }
|
|
838
|
+
.sk-foot { display: none }
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/* 搜索跳到的那一句: 气泡闪一圈视角色。 */
|
|
842
|
+
.mrow.hit .mb > * { animation: hit 1.6s ease-out }
|
|
843
|
+
@keyframes hit { 0%, 30% { box-shadow: 0 0 0 3px #2f55c955 } 100% { box-shadow: 0 0 0 3px #2f55c900 } }
|