codebee 0.1.53 → 0.1.55

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.
@@ -0,0 +1,390 @@
1
+ /* CodeBee Mission Control
2
+ 方向:工业感任务指挥中心。深海底色承载信息,琥珀色代表蜂群,冰蓝色代表实时数据。 */
3
+
4
+ :root {
5
+ --bg: #06101c;
6
+ --bg-deep: #040a12;
7
+ --panel: #0c1a2c;
8
+ --panel-hi: #12253c;
9
+ --panel-soft: #0f2035;
10
+ --line: #294763;
11
+ --line-soft: #1d3853;
12
+ --text: #eef5ff;
13
+ --muted: #7f9bb7;
14
+ --muted-2: #526f8d;
15
+ --amber: #f5b84e;
16
+ --amber-hot: #ffd26a;
17
+ --cyan: #54d7ff;
18
+ --blue: #6f9dff;
19
+ --violet: #a58bff;
20
+ --green: #50dfa8;
21
+ --red: #ff7078;
22
+ --mono: "Cascadia Mono", "SFMono-Regular", Consolas, ui-monospace, monospace;
23
+ --display: "Bahnschrift", "DIN Alternate", "Segoe UI", "Microsoft YaHei", sans-serif;
24
+ }
25
+
26
+ * { margin: 0; padding: 0; box-sizing: border-box; }
27
+ html, body { min-height: 100%; }
28
+ body {
29
+ min-height: 100vh;
30
+ background:
31
+ radial-gradient(900px 430px at 66% -12%, #17436a55, transparent 70%),
32
+ radial-gradient(720px 480px at -12% 105%, #173b5844, transparent 72%),
33
+ linear-gradient(135deg, #071321 0%, var(--bg) 50%, #071120 100%);
34
+ color: var(--text);
35
+ font: 14px/1.45 var(--display);
36
+ overflow: hidden;
37
+ position: relative;
38
+ }
39
+ body::before {
40
+ content: "";
41
+ position: fixed;
42
+ inset: 0;
43
+ pointer-events: none;
44
+ opacity: .25;
45
+ background-image:
46
+ linear-gradient(#2d5a7d1c 1px, transparent 1px),
47
+ linear-gradient(90deg, #2d5a7d1c 1px, transparent 1px);
48
+ background-size: 44px 44px;
49
+ mask-image: linear-gradient(180deg, #000, transparent 92%);
50
+ }
51
+ body::after {
52
+ content: "";
53
+ position: fixed;
54
+ inset: 0;
55
+ pointer-events: none;
56
+ box-shadow: inset 0 0 140px #02070dcc;
57
+ }
58
+
59
+ button, input { font: inherit; }
60
+ .hidden { display: none !important; }
61
+ .panel {
62
+ background:
63
+ linear-gradient(145deg, #142b4512, transparent 45%),
64
+ linear-gradient(180deg, var(--panel-hi), var(--panel));
65
+ border: 1px solid #2c4b6877;
66
+ box-shadow: 0 18px 45px #02070d38, inset 0 1px #ffffff08;
67
+ position: relative;
68
+ }
69
+ .panel::after {
70
+ content: "";
71
+ position: absolute;
72
+ right: 0;
73
+ top: 0;
74
+ width: 34px;
75
+ height: 1px;
76
+ background: linear-gradient(90deg, transparent, #64d7ff99);
77
+ pointer-events: none;
78
+ }
79
+
80
+ /* ---------------------------------------------------------------- 顶栏 */
81
+ #hd {
82
+ height: 66px;
83
+ flex: none;
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: space-between;
87
+ padding: 0 30px;
88
+ border-bottom: 1px solid #27445e99;
89
+ background: #071321d9;
90
+ position: relative;
91
+ z-index: 2;
92
+ }
93
+ #hd::after {
94
+ content: "";
95
+ position: absolute;
96
+ left: 30px;
97
+ right: 30px;
98
+ bottom: -1px;
99
+ height: 1px;
100
+ background: linear-gradient(90deg, var(--amber), #4ddcffaa 44%, transparent 82%);
101
+ opacity: .65;
102
+ }
103
+ .hd-brand { display: flex; align-items: center; gap: 12px; min-width: 250px; }
104
+ .brand-mark {
105
+ width: 32px;
106
+ height: 32px;
107
+ position: relative;
108
+ filter: drop-shadow(0 0 9px #f5b84e55);
109
+ }
110
+ .brand-mark::before,
111
+ .brand-mark::after {
112
+ content: "";
113
+ position: absolute;
114
+ top: 4px;
115
+ width: 14px;
116
+ height: 12px;
117
+ border: 1px solid #f5b84e99;
118
+ border-radius: 10px 10px 3px 10px;
119
+ background: #f5b84e17;
120
+ }
121
+ .brand-mark::before { left: 0; transform: rotate(-24deg); }
122
+ .brand-mark::after { right: 0; transform: scaleX(-1) rotate(-24deg); }
123
+ .brand-mark i {
124
+ position: absolute;
125
+ z-index: 1;
126
+ left: 9px;
127
+ width: 14px;
128
+ height: 19px;
129
+ border-radius: 9px;
130
+ background: linear-gradient(90deg, #f5b84e 0 28%, #18253a 28% 44%, #f5b84e 44% 70%, #18253a 70% 86%, #f5b84e 86%);
131
+ transform: rotate(3deg);
132
+ }
133
+ .brand-mark i:nth-child(2) { left: 6px; top: 15px; width: 5px; height: 5px; border-radius: 50%; background: var(--amber-hot); box-shadow: 15px 0 var(--amber-hot); }
134
+ .brand-mark i:nth-child(3) { display: none; }
135
+ .brand-mark b { position: absolute; z-index: 2; left: 13px; top: 5px; width: 2px; height: 2px; border-radius: 50%; background: #071321; box-shadow: 6px 0 #071321; }
136
+ .brand-copy { display: flex; flex-direction: column; gap: 0; }
137
+ .brand-kicker { color: var(--amber); font: 600 9px/1 var(--mono); letter-spacing: 2px; opacity: .9; }
138
+ .hd-name { font-size: 19px; font-weight: 700; letter-spacing: 1px; margin-top: 5px; }
139
+ .hd-center { display: flex; align-items: center; gap: 9px; color: var(--muted); font: 11px var(--mono); letter-spacing: 1px; text-transform: uppercase; }
140
+ .live-pip { width: 7px; height: 7px; border-radius: 50%; background: var(--green); box-shadow: 0 0 0 4px #50dfa81c, 0 0 13px #50dfa8; animation: breathe 2s ease-in-out infinite; }
141
+ .hd-sep { color: var(--muted-2); }
142
+ .hd-updated { color: var(--cyan); }
143
+ .hd-right { display: flex; align-items: center; gap: 10px; min-width: 390px; justify-content: flex-end; }
144
+ .hd-pill { color: var(--muted); border: 1px solid #2d4a6577; border-radius: 999px; padding: 5px 11px; background: #ffffff05; font: 11px var(--mono); white-space: nowrap; }
145
+ .hd-pill.warn { color: #ffd0d0; border-color: #ff707888; background: #ff707812; }
146
+ .hd-pill.off { color: var(--red); border-color: #ff707888; }
147
+ .hd-clock { color: var(--cyan); font: 600 23px var(--mono); letter-spacing: 1px; text-shadow: 0 0 18px #54d7ff55; }
148
+ @keyframes breathe { 50% { opacity: .48; transform: scale(.75); } }
149
+
150
+ /* ---------------------------------------------------------------- 页面骨架 */
151
+ #board {
152
+ height: calc(100vh - 66px);
153
+ min-height: 0;
154
+ max-width: 1920px;
155
+ margin: 0 auto;
156
+ padding: 20px 30px 24px;
157
+ display: grid;
158
+ grid-template-rows: 150px 88px minmax(0, 1fr);
159
+ gap: 14px;
160
+ position: relative;
161
+ z-index: 1;
162
+ }
163
+ .eyebrow { display: flex; align-items: center; gap: 8px; color: var(--muted); font: 600 10px var(--mono); letter-spacing: 2px; text-transform: uppercase; }
164
+ .eyebrow > span:first-child { display: block; width: 6px; height: 6px; background: var(--amber); box-shadow: 0 0 9px #f5b84e88; }
165
+
166
+ /* ---------------------------------------------------------------- 总态势 */
167
+ .overview {
168
+ min-height: 0;
169
+ border-radius: 16px;
170
+ display: grid;
171
+ grid-template-columns: minmax(0, 1fr) 260px 240px;
172
+ overflow: hidden;
173
+ }
174
+ .overview::before {
175
+ content: "01 / HIVE STATUS";
176
+ position: absolute;
177
+ right: 22px;
178
+ top: 15px;
179
+ color: #7f9bb733;
180
+ font: 10px var(--mono);
181
+ letter-spacing: 1.8px;
182
+ }
183
+ .overview-copy { padding: 22px 24px 18px; display: flex; flex-direction: column; justify-content: space-between; min-width: 0; }
184
+ .overview-line { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; min-width: 0; }
185
+ .overview-line h1 { font-size: clamp(25px, 2.4vw, 38px); line-height: 1; letter-spacing: -1px; font-weight: 700; }
186
+ .overview-line p { color: var(--muted); font-size: 12px; margin-top: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 560px; }
187
+ .hero-count { flex: none; padding-right: 6px; text-align: right; }
188
+ .hero-count strong { display: block; color: var(--amber-hot); font: 700 42px/.9 var(--mono); text-shadow: 0 0 25px #f5b84e44; }
189
+ .hero-count span { display: block; color: var(--muted); font: 10px var(--mono); letter-spacing: 1px; margin-top: 7px; }
190
+ .overview-foot { display: flex; align-items: center; gap: 18px; }
191
+ .signal-chip { display: inline-flex; align-items: center; gap: 7px; color: var(--green); font-size: 11px; }
192
+ .signal-chip i { width: 6px; height: 6px; border-radius: 50%; background: var(--green); box-shadow: 0 0 9px var(--green); }
193
+ .overview.has-alert .signal-chip { color: var(--red); }
194
+ .overview.has-alert .signal-chip i { background: var(--red); box-shadow: 0 0 9px var(--red); }
195
+ .overview-note { color: var(--muted-2); font: 10px var(--mono); }
196
+ .overview-visual { position: relative; overflow: hidden; border-left: 1px solid #2b496344; border-right: 1px solid #2b496344; background: radial-gradient(circle at center, #1c4d6a33, transparent 58%); }
197
+ .overview-visual::before { content: ""; position: absolute; inset: 15px; background: repeating-linear-gradient(0deg, transparent 0 17px, #61d9ff0a 18px), repeating-linear-gradient(90deg, transparent 0 17px, #61d9ff0a 18px); transform: perspective(500px) rotateX(58deg) scale(1.6); transform-origin: center bottom; opacity: .7; }
198
+ .orbit { position: absolute; border: 1px solid #59d7ff55; border-radius: 50%; left: 50%; top: 50%; transform: translate(-50%, -50%); }
199
+ .orbit-a { width: 140px; height: 64px; rotate: -14deg; animation: orbit-rotate 9s linear infinite; }
200
+ .orbit-b { width: 182px; height: 88px; rotate: 22deg; border-color: #f5b84e44; animation: orbit-rotate 13s linear infinite reverse; }
201
+ .orbit-dot { position: absolute; width: 6px; height: 6px; border-radius: 50%; background: var(--cyan); box-shadow: 0 0 12px var(--cyan); }
202
+ .dot-a { left: 27%; top: 28%; }
203
+ .dot-b { right: 21%; top: 62%; background: var(--amber); box-shadow: 0 0 12px var(--amber); }
204
+ .dot-c { left: 67%; top: 24%; width: 4px; height: 4px; background: var(--violet); box-shadow: 0 0 10px var(--violet); }
205
+ .core-glow { position: absolute; width: 92px; height: 92px; border-radius: 50%; left: 50%; top: 50%; transform: translate(-50%, -50%); background: #54d7ff15; filter: blur(10px); }
206
+ .overview-core { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 76px; height: 76px; border: 1px solid #54d7ff99; border-radius: 50%; background: #071827e8; display: flex; flex-direction: column; align-items: center; justify-content: center; box-shadow: inset 0 0 20px #54d7ff18, 0 0 20px #54d7ff22; }
207
+ .overview-core strong { color: var(--cyan); font: 700 27px/.9 var(--mono); }
208
+ .overview-core span { color: var(--muted); font: 8px var(--mono); letter-spacing: 1px; margin-top: 6px; }
209
+ @keyframes orbit-rotate { to { rotate: 382deg; } }
210
+ .overview-aside { padding: 25px 20px 18px; display: flex; flex-direction: column; justify-content: center; background: #07132140; }
211
+ .aside-label { color: var(--muted); font: 10px var(--mono); letter-spacing: 2px; text-transform: uppercase; }
212
+ .pool-meter { height: 5px; background: #25415b; border-radius: 99px; overflow: hidden; margin-top: 11px; }
213
+ .pool-meter i { display: block; height: 100%; width: 0; border-radius: inherit; background: linear-gradient(90deg, var(--cyan), var(--violet)); box-shadow: 0 0 12px #54d7ff88; transition: width .5s ease; }
214
+ .pool-readout { display: flex; align-items: baseline; gap: 6px; margin-top: 9px; color: var(--muted); font: 12px var(--mono); }
215
+ .pool-readout strong { color: var(--text); font-size: 23px; }
216
+ .pool-readout em { font: 10px var(--display); color: var(--muted-2); margin-left: auto; font-style: normal; }
217
+ .aside-divider { height: 1px; background: #2a486333; margin: 14px 0 9px; }
218
+ .aside-row { display: flex; justify-content: space-between; align-items: center; color: var(--muted); font-size: 11px; padding: 3px 0; }
219
+ .aside-row b { color: var(--text); font: 600 12px var(--mono); }
220
+
221
+ /* ---------------------------------------------------------------- KPI */
222
+ #kpis { min-height: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }
223
+ .kpi { --kc: var(--cyan); min-width: 0; padding: 12px 16px 10px; border: 1px solid #2c4b6877; border-radius: 12px; background: linear-gradient(145deg, #142b4512, transparent 50%), linear-gradient(180deg, #11243a, #0b182a); position: relative; overflow: hidden; box-shadow: inset 0 1px #ffffff07; }
224
+ .kpi::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--kc); box-shadow: 0 0 16px color-mix(in srgb, var(--kc) 60%, transparent); }
225
+ .k-run { --kc: var(--amber); } .k-queue { --kc: var(--cyan); } .k-done { --kc: var(--green); } .k-fail { --kc: var(--red); } .k-tok { --kc: var(--violet); } .k-cost { --kc: #64c9ff; }
226
+ .kpi-head { display: flex; align-items: center; justify-content: space-between; color: var(--muted); font: 10px var(--mono); letter-spacing: 1px; text-transform: uppercase; }
227
+ .kpi-icon { display: block; width: 7px; height: 7px; border: 1px solid var(--kc); transform: rotate(45deg); opacity: .9; }
228
+ .k-num { margin-top: 6px; color: var(--text); font: 700 25px/1 var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
229
+ .k-run .k-num { color: var(--amber-hot); } .k-fail .k-num { color: var(--red); } .k-tok .k-num { color: #c6b9ff; }
230
+ .kpi-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 7px; color: var(--muted-2); font-size: 10px; }
231
+ .kpi-foot b { color: var(--kc); font: 9px var(--mono); letter-spacing: 1px; }
232
+
233
+ /* ---------------------------------------------------------------- 主工作区 */
234
+ #main { min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) 404px; gap: 14px; }
235
+ #wall { min-height: 0; display: flex; flex-direction: column; border-radius: 16px; overflow: hidden; }
236
+ .panel-head { flex: none; display: flex; align-items: flex-end; justify-content: space-between; padding: 19px 22px 16px; border-bottom: 1px solid #29476355; }
237
+ .panel-head h2, .rail-head h3 { margin-top: 5px; font-size: 16px; font-weight: 650; letter-spacing: .3px; }
238
+ .panel-head-right { display: flex; align-items: center; gap: 12px; }
239
+ .live-count { color: var(--amber); border: 1px solid #f5b84e66; background: #f5b84e12; border-radius: 999px; padding: 5px 9px; font: 10px var(--mono); letter-spacing: 1px; }
240
+ .mode-label { color: var(--muted-2); font: 10px var(--mono); letter-spacing: 1px; }
241
+ #wall-cards { flex: 1; min-height: 0; overflow-y: auto; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: start; gap: 12px; padding: 16px 17px 14px; }
242
+ #wall-cards::-webkit-scrollbar, #recent::-webkit-scrollbar { width: 5px; }
243
+ #wall-cards::-webkit-scrollbar-thumb, #recent::-webkit-scrollbar-thumb { background: #39608188; border-radius: 99px; }
244
+
245
+ /* 运行任务卡 */
246
+ .card { min-width: 0; background: linear-gradient(145deg, #18324e33, transparent 46%), #0a1728; border: 1px solid #31536e99; border-radius: 12px; padding: 14px 15px 13px 18px; position: relative; overflow: hidden; box-shadow: 0 10px 24px #02070d2b; }
247
+ .card::before { content: ""; position: absolute; left: 0; top: 14px; bottom: 14px; width: 3px; border-radius: 0 3px 3px 0; background: var(--amber); box-shadow: 0 0 13px #f5b84e99; animation: breathe 2.2s ease-in-out infinite; }
248
+ .card::after { content: "LIVE"; position: absolute; right: 13px; top: 12px; color: #f5b84e77; font: 9px var(--mono); letter-spacing: 1px; }
249
+ .card-top { display: flex; align-items: baseline; gap: 8px; padding-right: 36px; }
250
+ .c-type { flex: none; color: var(--amber); border: 1px solid #f5b84e55; border-radius: 3px; padding: 2px 6px; background: #f5b84e12; font: 10px var(--mono); }
251
+ .c-title { min-width: 0; color: var(--text); font-size: 14px; font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
252
+ .c-elapsed { flex: none; margin-left: auto; color: var(--cyan); font: 600 12px var(--mono); }
253
+ .c-steps { display: flex; align-items: center; gap: 4px; margin-top: 13px; }
254
+ .c-steps i { flex: 1; min-width: 5px; height: 4px; border-radius: 99px; background: #23405a; }
255
+ .c-steps i.d { background: var(--green); box-shadow: 0 0 7px #50dfa866; }
256
+ .c-steps i.r { background: var(--amber); box-shadow: 0 0 8px #f5b84e77; animation: breathe 1.2s ease-in-out infinite; }
257
+ .c-stepinfo { min-width: 0; display: flex; align-items: baseline; gap: 8px; margin-top: 8px; white-space: nowrap; overflow: hidden; }
258
+ .c-stepinfo .no { color: var(--amber); font: 600 11px var(--mono); flex: none; }
259
+ .c-stepinfo .ag { color: var(--muted); font: 11px var(--mono); flex: none; }
260
+ .c-stepinfo .sm { min-width: 0; overflow: hidden; color: #b7c9dc; font-size: 11px; text-overflow: ellipsis; }
261
+ .c-meta { display: flex; align-items: center; gap: 5px; min-width: 0; margin-top: 11px; overflow: hidden; }
262
+ .b { flex: none; max-width: 155px; padding: 3px 6px; overflow: hidden; color: var(--muted); border: 1px solid #42627d77; border-radius: 3px; background: #ffffff05; font: 10px var(--mono); white-space: nowrap; text-overflow: ellipsis; }
263
+ .b-model { color: #9fd8ff; border-color: #54d7ff55; background: #54d7ff0d; }
264
+ .b-prov { color: #c5baff; border-color: #a58bff55; background: #a58bff0d; }
265
+ .b-agent { color: #b8c8d9; }
266
+ .b.dim { color: var(--muted-2); border-style: dashed; }
267
+ .c-run-tok { min-width: 0; margin-left: auto; color: #69c99e; font: 10px var(--mono); white-space: nowrap; }
268
+ .c-live { position: relative; margin-top: 11px; padding: 8px 10px; border: 1px solid #284a6577; border-radius: 6px; background: #06101ddd; }
269
+ .c-live-tag { position: absolute; right: 8px; top: 6px; color: var(--cyan); font: 9px var(--mono); letter-spacing: 1px; }
270
+ .c-live-text { max-height: 4.6em; overflow: hidden; color: #8fb9d7; font: 10px/1.55 var(--mono); white-space: pre; }
271
+ .c-pct { margin-top: 9px; color: var(--muted-2); font: 10px var(--mono); }
272
+
273
+ /* 空态 / 排队 */
274
+ .wall-empty { flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; position: relative; overflow: hidden; }
275
+ .wall-empty::before { content: "NO ACTIVE RUNS"; position: absolute; top: 14%; color: #7f9bb71a; font: 10px var(--mono); letter-spacing: 3px; }
276
+ .empty-orbit { width: 136px; height: 86px; position: relative; margin-bottom: 2px; }
277
+ .empty-orbit::before, .empty-orbit::after { content: ""; position: absolute; left: 50%; top: 50%; border: 1px solid #54d7ff44; border-radius: 50%; transform: translate(-50%, -50%) rotate(-16deg); }
278
+ .empty-orbit::before { width: 130px; height: 54px; }
279
+ .empty-orbit::after { width: 92px; height: 38px; border-color: #f5b84e44; transform: translate(-50%, -50%) rotate(24deg); }
280
+ .empty-orbit i { position: absolute; width: 6px; height: 6px; border-radius: 50%; background: var(--cyan); box-shadow: 0 0 10px var(--cyan); }
281
+ .empty-orbit i:nth-child(1) { left: 10px; top: 38px; }
282
+ .empty-orbit i:nth-child(2) { right: 12px; top: 19px; background: var(--amber); box-shadow: 0 0 10px var(--amber); }
283
+ .empty-orbit i:nth-child(3) { left: 64px; bottom: 3px; background: var(--violet); box-shadow: 0 0 10px var(--violet); }
284
+ .empty-orbit b { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); color: var(--cyan); font: 700 30px var(--mono); }
285
+ .idle-t1 { color: var(--text); font-size: 20px; font-weight: 650; letter-spacing: 1px; }
286
+ .idle-t2 { color: var(--muted); font-size: 12px; }
287
+ .empty-meta { display: flex; gap: 15px; margin-top: 12px; color: var(--muted-2); font: 10px var(--mono); }
288
+ .empty-meta span { display: inline-flex; align-items: center; gap: 6px; }
289
+ .empty-meta i { width: 5px; height: 5px; border-radius: 50%; background: var(--green); box-shadow: 0 0 8px var(--green); }
290
+ .queue-row { flex: none; display: flex; align-items: center; gap: 15px; min-height: 49px; padding: 0 18px; border-top: 1px solid #29476355; background: #07132155; }
291
+ .q-label { flex: none; display: inline-flex; align-items: center; gap: 7px; color: var(--cyan); font: 11px var(--mono); }
292
+ .q-label b { display: inline-flex; align-items: center; justify-content: center; min-width: 19px; height: 19px; padding: 0 5px; border: 1px solid #54d7ff55; border-radius: 99px; background: #54d7ff12; font-size: 10px; }
293
+ .q-mark { width: 6px; height: 6px; border: 1px solid var(--cyan); transform: rotate(45deg); }
294
+ #queue-chips { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; overflow-x: auto; padding: 3px 2px; }
295
+ #queue-chips::-webkit-scrollbar { height: 4px; }
296
+ #queue-chips .chip { flex: none; max-width: 250px; padding: 5px 10px; overflow: hidden; border: 1px solid #3c648388; border-radius: 4px; background: #54d7ff0b; color: #b9d8ed; font-size: 11px; white-space: nowrap; text-overflow: ellipsis; }
297
+
298
+ /* ---------------------------------------------------------------- 右侧监控轨 */
299
+ #rail { min-height: 0; display: flex; flex-direction: column; gap: 14px; }
300
+ .rail-card { min-height: 0; border-radius: 14px; padding: 15px 17px; }
301
+ .rail-trend { flex: 0 0 166px; }
302
+ .rail-models { flex: 0 0 178px; }
303
+ .rail-recent { flex: 1; display: flex; flex-direction: column; }
304
+ .rail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
305
+ .rail-head h3 { font-size: 14px; }
306
+ .rail-badge { flex: none; padding: 4px 7px; border: 1px solid #41627b66; border-radius: 3px; color: var(--muted); font: 9px var(--mono); letter-spacing: 1px; }
307
+ .trend { display: flex; align-items: flex-end; gap: 8px; height: 94px; padding-top: 16px; }
308
+ .trend .bar { flex: 1; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 7px; }
309
+ .trend .bar i { width: 100%; min-height: 3px; border-radius: 3px 3px 1px 1px; background: linear-gradient(180deg, var(--cyan), var(--blue) 55%, #a58bffcc); box-shadow: 0 0 12px #54d7ff22; transition: height .45s ease; }
310
+ .trend .bar.zero i { background: #27425c; box-shadow: none; }
311
+ .trend .bar b { color: var(--muted-2); font: 9px var(--mono); font-weight: 400; }
312
+ .models { display: flex; flex-direction: column; gap: 9px; margin-top: 16px; }
313
+ .model-row { display: grid; grid-template-columns: 116px minmax(0, 1fr) 51px; gap: 8px; align-items: center; }
314
+ .model-row .nm { min-width: 0; color: #cbd9e8; font-size: 10.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
315
+ .model-row .tk { height: 6px; overflow: hidden; border-radius: 99px; background: #223c57; }
316
+ .model-row .tk i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--cyan), var(--violet)); box-shadow: 0 0 8px #54d7ff55; }
317
+ .model-row .vl { color: var(--muted); font: 9px var(--mono); text-align: right; }
318
+ .models .empty, .recent .empty { color: var(--muted-2); font-size: 11px; padding: 12px 0; }
319
+ #recent { flex: 1; min-height: 0; margin-top: 14px; overflow-y: auto; }
320
+ .r-row { display: flex; align-items: baseline; gap: 8px; min-width: 0; padding: 8px 0; border-bottom: 1px solid #29476333; }
321
+ .r-row:last-child { border-bottom: none; }
322
+ .r-dot { flex: none; width: 6px; height: 6px; border-radius: 50%; margin-top: 3px; }
323
+ .r-dot.done { background: var(--green); box-shadow: 0 0 7px #50dfa8aa; }
324
+ .r-dot.failed { background: var(--red); box-shadow: 0 0 7px #ff7078aa; }
325
+ .r-dot.cancelled { background: var(--muted-2); }
326
+ .r-t { min-width: 0; flex: 1; overflow: hidden; color: #c8d8e9; font-size: 11px; white-space: nowrap; text-overflow: ellipsis; }
327
+ .r-t.failed { color: #ffb7bb; }
328
+ .r-d { flex: none; color: var(--muted-2); font: 9px var(--mono); }
329
+
330
+ /* ---------------------------------------------------------------- 令牌门 */
331
+ .gate { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; background: #040b14ed; backdrop-filter: blur(10px); }
332
+ .gate-box { width: min(360px, calc(100vw - 40px)); padding: 35px 30px 30px; border: 1px solid #31556f99; border-radius: 18px; background: linear-gradient(145deg, #17324d, #0b1728); box-shadow: 0 24px 80px #0009; text-align: center; }
333
+ .gate-mark { display: flex; align-items: center; justify-content: center; gap: 5px; margin-bottom: 18px; }
334
+ .gate-mark span { width: 10px; height: 10px; border-radius: 50%; background: var(--amber); box-shadow: 0 0 12px #f5b84e88; }
335
+ .gate-mark span:nth-child(2) { width: 16px; height: 16px; background: var(--cyan); box-shadow: 0 0 15px #54d7ff88; }
336
+ .gate-title { font-size: 21px; font-weight: 700; }
337
+ .gate-sub { color: var(--muted); font-size: 12px; margin: 7px 0 18px; }
338
+ #gate-token { display: block; width: 100%; padding: 11px 13px; border: 1px solid #3c607b; border-radius: 8px; outline: none; background: #06101c; color: var(--text); text-align: center; }
339
+ #gate-token:focus { border-color: var(--cyan); box-shadow: 0 0 0 3px #54d7ff17; }
340
+ #gate-ok { margin-top: 12px; padding: 10px 26px; border: 1px solid #f5b84e66; border-radius: 7px; background: var(--amber); color: #0a1420; font-weight: 700; cursor: pointer; }
341
+ #gate-ok:hover { background: var(--amber-hot); }
342
+ .gate-err { min-height: 18px; margin-top: 11px; color: var(--red); font-size: 12px; }
343
+
344
+ /* ---------------------------------------------------------------- 响应式 */
345
+ @media (max-width: 1280px) {
346
+ #board { padding-left: 20px; padding-right: 20px; }
347
+ #hd { padding-left: 20px; padding-right: 20px; }
348
+ #hd::after { left: 20px; right: 20px; }
349
+ .overview { grid-template-columns: minmax(0, 1fr) 220px 205px; }
350
+ #main { grid-template-columns: minmax(0, 1fr) 350px; }
351
+ .hd-brand { min-width: 220px; }
352
+ .hd-right { min-width: 330px; }
353
+ }
354
+ @media (max-width: 1050px) {
355
+ body { overflow: auto; }
356
+ #board { height: auto; min-height: calc(100vh - 66px); grid-template-rows: 150px auto auto; }
357
+ #main { grid-template-columns: minmax(0, 1fr); }
358
+ #rail { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
359
+ .rail-recent { grid-column: 1 / -1; min-height: 280px; }
360
+ .hd-center { display: none; }
361
+ }
362
+ @media (max-width: 720px) {
363
+ #hd { height: 60px; padding: 0 14px; }
364
+ #hd::after { left: 14px; right: 14px; }
365
+ #board { height: auto; min-height: calc(100vh - 60px); padding: 14px; grid-template-rows: 260px auto auto; gap: 12px; }
366
+ .brand-kicker { display: none; }
367
+ .hd-name { font-size: 16px; }
368
+ .hd-right { min-width: 0; gap: 6px; }
369
+ #hd-pool, #hd-health { display: none; }
370
+ .hd-clock { font-size: 17px; }
371
+ .overview-note { display: none; }
372
+ .signal-chip { white-space: nowrap; }
373
+ .overview { grid-template-columns: 1fr 130px; grid-template-rows: 1fr 86px; }
374
+ .overview-copy { grid-row: 1 / 3; padding: 20px 17px; }
375
+ .overview-line { display: block; }
376
+ .hero-count { text-align: left; margin-top: 22px; }
377
+ .overview-visual { border-right: none; }
378
+ .overview-aside { grid-column: 2; grid-row: 2; padding: 14px; }
379
+ .overview-aside .aside-divider, .overview-aside .aside-row:nth-last-child(-n+2) { display: none; }
380
+ #kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
381
+ #main { display: block; }
382
+ #wall { min-height: 560px; }
383
+ #wall-cards { grid-template-columns: 1fr; }
384
+ #rail { margin-top: 12px; display: flex; }
385
+ .rail-trend, .rail-models { flex-basis: auto; min-height: 166px; }
386
+ .rail-recent { min-height: 300px; }
387
+ }
388
+ @media (prefers-reduced-motion: reduce) {
389
+ *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
390
+ }
@@ -0,0 +1,162 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN" data-lang="zh">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
6
+ <title>CodeBee · 任务驾驶舱</title>
7
+ <link rel="icon" href="/icons/icon-192.png">
8
+ <link rel="stylesheet" href="/board.css">
9
+ </head>
10
+ <body>
11
+
12
+ <!-- 远程访问令牌门(本机免输;与主界面共用 orch.token) -->
13
+ <div id="gate" class="gate hidden">
14
+ <div class="gate-box">
15
+ <div class="gate-mark" aria-hidden="true"><span></span><span></span><span></span></div>
16
+ <div class="gate-title" data-i18n="需要访问令牌">需要访问令牌</div>
17
+ <div class="gate-sub" data-i18n="启动 CodeBee 时控制台会显示">启动 CodeBee 时控制台会显示</div>
18
+ <input id="gate-token" type="password" data-i18n-ph="访问令牌" placeholder="访问令牌" autocomplete="off">
19
+ <button id="gate-ok" type="button" data-i18n="进入大屏">进入大屏</button>
20
+ <div id="gate-err" class="gate-err"></div>
21
+ </div>
22
+ </div>
23
+
24
+ <header id="hd">
25
+ <div class="hd-brand">
26
+ <div class="brand-mark" aria-hidden="true"><i></i><i></i><i></i><b></b></div>
27
+ <div class="brand-copy">
28
+ <div class="brand-kicker">CODEBEE / OPERATIONS</div>
29
+ <div class="hd-name" data-i18n="任务驾驶舱">任务驾驶舱</div>
30
+ </div>
31
+ </div>
32
+ <div class="hd-center">
33
+ <span class="live-pip"></span>
34
+ <span data-i18n="实时监控">实时监控</span>
35
+ <span class="hd-sep">/</span>
36
+ <span id="hd-updated" class="hd-updated" data-i18n="同步中">同步中</span>
37
+ </div>
38
+ <div class="hd-right">
39
+ <div id="hd-pool" class="hd-pill" title="执行池占用" data-i18n-title="执行池占用">—</div>
40
+ <div id="hd-health" class="hd-pill warn hidden" title=""></div>
41
+ <div id="hd-conn" class="hd-pill off hidden" data-i18n="连接断开">连接断开</div>
42
+ <div id="hd-clock" class="hd-clock">--:--:--</div>
43
+ </div>
44
+ </header>
45
+
46
+ <main id="board">
47
+ <section id="overview" class="overview panel">
48
+ <div class="overview-copy">
49
+ <div class="eyebrow"><span></span><span data-i18n="蜂群状态">蜂群状态</span></div>
50
+ <div class="overview-line">
51
+ <div>
52
+ <h1 id="hero-state" data-i18n="蜂群待命">蜂群待命</h1>
53
+ <p id="hero-copy" data-i18n="没有正在运行的任务,新任务在主界面创建后会实时出现在这里">没有正在运行的任务,新任务在主界面创建后会实时出现在这里</p>
54
+ </div>
55
+ <div class="hero-count">
56
+ <strong id="hero-live-count">0</strong>
57
+ <span data-i18n="个活动单元">个活动单元</span>
58
+ </div>
59
+ </div>
60
+ <div class="overview-foot">
61
+ <span class="signal-chip"><i></i><span id="hero-signal" data-i18n="系统状态良好">系统状态良好</span></span>
62
+ <span class="overview-note" data-i18n="实时聚合 · 每 4 秒刷新">实时聚合 · 每 4 秒刷新</span>
63
+ </div>
64
+ </div>
65
+ <div class="overview-visual" aria-hidden="true">
66
+ <div class="orbit orbit-a"></div>
67
+ <div class="orbit orbit-b"></div>
68
+ <div class="orbit-dot dot-a"></div>
69
+ <div class="orbit-dot dot-b"></div>
70
+ <div class="orbit-dot dot-c"></div>
71
+ <div class="core-glow"></div>
72
+ <div class="overview-core"><strong id="orb-number">0</strong><span>ACTIVE</span></div>
73
+ </div>
74
+ <div class="overview-aside">
75
+ <div class="aside-label" data-i18n="执行池">执行池</div>
76
+ <div class="pool-meter"><i id="pool-meter-fill"></i></div>
77
+ <div class="pool-readout"><strong id="pool-alive">0</strong><span>/</span><span id="pool-target">0</span><em data-i18n="在线槽位">在线槽位</em></div>
78
+ <div class="aside-divider"></div>
79
+ <div class="aside-row"><span data-i18n="队列等待">队列等待</span><b id="overview-queued">0</b></div>
80
+ <div class="aside-row"><span data-i18n="今日成功率">今日成功率</span><b id="overview-success">—</b></div>
81
+ </div>
82
+ </section>
83
+
84
+ <section id="kpis" aria-label="核心指标" data-i18n-aria="核心指标">
85
+ <div class="kpi k-run">
86
+ <div class="kpi-head"><span data-i18n="运行中">运行中</span><i class="kpi-icon"></i></div>
87
+ <div class="k-num" id="k-running">0</div>
88
+ <div class="kpi-foot"><span data-i18n="当前活动">当前活动</span><b>LIVE</b></div>
89
+ </div>
90
+ <div class="kpi k-queue">
91
+ <div class="kpi-head"><span data-i18n="排队中">排队中</span><i class="kpi-icon"></i></div>
92
+ <div class="k-num" id="k-queued">0</div>
93
+ <div class="kpi-foot"><span data-i18n="等待调度">等待调度</span><b>QUEUE</b></div>
94
+ </div>
95
+ <div class="kpi k-done">
96
+ <div class="kpi-head"><span data-i18n="今日完成">今日完成</span><i class="kpi-icon"></i></div>
97
+ <div class="k-num" id="k-done">0</div>
98
+ <div class="kpi-foot"><span data-i18n="完成运行">完成运行</span><b>DONE</b></div>
99
+ </div>
100
+ <div class="kpi k-fail">
101
+ <div class="kpi-head"><span data-i18n="今日失败">今日失败</span><i class="kpi-icon"></i></div>
102
+ <div class="k-num" id="k-failed">0</div>
103
+ <div class="kpi-foot"><span data-i18n="需要关注">需要关注</span><b>ALERT</b></div>
104
+ </div>
105
+ <div class="kpi k-tok">
106
+ <div class="kpi-head"><span data-i18n="今日 tokens">今日 tokens</span><i class="kpi-icon"></i></div>
107
+ <div class="k-num" id="k-tokens">0</div>
108
+ <div class="kpi-foot"><span data-i18n="模型消耗">模型消耗</span><b>USAGE</b></div>
109
+ </div>
110
+ <div class="kpi k-cost">
111
+ <div class="kpi-head"><span data-i18n="今日成本">今日成本</span><i class="kpi-icon"></i></div>
112
+ <div class="k-num" id="k-cost">$0.00</div>
113
+ <div class="kpi-foot"><span data-i18n="运行成本">运行成本</span><b>COST</b></div>
114
+ </div>
115
+ </section>
116
+
117
+ <section id="main">
118
+ <section id="wall" class="panel live-panel">
119
+ <header class="panel-head">
120
+ <div>
121
+ <div class="eyebrow"><span></span><span data-i18n="实时任务流">实时任务流</span></div>
122
+ <h2 data-i18n="运行中任务">运行中任务</h2>
123
+ </div>
124
+ <div class="panel-head-right">
125
+ <span id="wall-count" class="live-count">0 ACTIVE</span>
126
+ <span id="wall-mode" class="mode-label" data-i18n="监控中">监控中</span>
127
+ </div>
128
+ </header>
129
+ <div id="wall-cards"></div>
130
+ <div id="wall-empty" class="wall-empty hidden">
131
+ <div class="empty-orbit" aria-hidden="true"><i></i><i></i><i></i><b>0</b></div>
132
+ <div class="idle-t1" data-i18n="队列已清空">队列已清空</div>
133
+ <div class="idle-t2" data-i18n="等待新的任务接入蜂巢">等待新的任务接入蜂巢</div>
134
+ <div class="empty-meta"><span><i></i><b data-i18n="工作池就绪">工作池就绪</b></span><span><i></i><b data-i18n="监控在线">监控在线</b></span></div>
135
+ </div>
136
+ <div id="queue-row" class="queue-row hidden">
137
+ <div class="q-label"><span class="q-mark"></span><span data-i18n="排队等待">排队等待</span><b id="queue-count">0</b></div>
138
+ <span id="queue-chips"></span>
139
+ </div>
140
+ </section>
141
+
142
+ <aside id="rail">
143
+ <section class="rail-card rail-trend panel">
144
+ <div class="rail-head"><div><div class="eyebrow"><span></span><span data-i18n="资源脉冲">资源脉冲</span></div><h3 data-i18n="近 7 日 tokens">近 7 日 tokens</h3></div><span class="rail-badge">7 DAYS</span></div>
145
+ <div id="trend" class="trend"></div>
146
+ </section>
147
+ <section class="rail-card rail-models panel">
148
+ <div class="rail-head"><div><div class="eyebrow"><span></span><span data-i18n="模型分布">模型分布</span></div><h3 data-i18n="近 7 日模型 TOP5">近 7 日模型 TOP5</h3></div><span class="rail-badge">TOP 5</span></div>
149
+ <div id="models" class="models"></div>
150
+ </section>
151
+ <section class="rail-card rail-recent panel grow">
152
+ <div class="rail-head"><div><div class="eyebrow"><span></span><span data-i18n="事件日志">事件日志</span></div><h3 data-i18n="最近动态">最近动态</h3></div><span id="recent-count" class="rail-badge">—</span></div>
153
+ <div id="recent" class="recent"></div>
154
+ </section>
155
+ </aside>
156
+ </section>
157
+ </main>
158
+
159
+ <script src="/i18n.js"></script>
160
+ <script src="/board.js"></script>
161
+ </body>
162
+ </html>