@2lab.ai/ui 0.0.0-stage → 0.2.0

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.
Files changed (60) hide show
  1. package/README.md +55 -2
  2. package/dist/agent-inbox.js +1061 -0
  3. package/dist/agent-inbox.js.map +1 -0
  4. package/dist/agent-queue.js +1610 -0
  5. package/dist/agent-queue.js.map +1 -0
  6. package/dist/agent-run.js +859 -0
  7. package/dist/agent-run.js.map +1 -0
  8. package/dist/ai-answer.js +687 -0
  9. package/dist/ai-answer.js.map +1 -0
  10. package/dist/components/agent-inbox/agent-inbox.d.ts +158 -0
  11. package/dist/components/agent-inbox/index.d.ts +2 -0
  12. package/dist/components/agent-inbox/styles.d.ts +6 -0
  13. package/dist/components/agent-queue/agent-queue.d.ts +41 -0
  14. package/dist/components/agent-queue/index.d.ts +6 -0
  15. package/dist/components/agent-queue/logic.d.ts +261 -0
  16. package/dist/components/agent-queue/strings.d.ts +473 -0
  17. package/dist/components/agent-queue/styles.d.ts +8 -0
  18. package/dist/components/agent-run/agent-run.d.ts +273 -0
  19. package/dist/components/agent-run/index.d.ts +2 -0
  20. package/dist/components/agent-run/styles.d.ts +6 -0
  21. package/dist/components/ai-answer/ai-answer.d.ts +92 -0
  22. package/dist/components/ai-answer/index.d.ts +2 -0
  23. package/dist/components/ai-answer/styles.d.ts +2 -0
  24. package/dist/components/context-window/context-window.d.ts +156 -0
  25. package/dist/components/context-window/index.d.ts +2 -0
  26. package/dist/components/context-window/styles.d.ts +2 -0
  27. package/dist/components/memory-panel/index.d.ts +2 -0
  28. package/dist/components/memory-panel/memory-panel.d.ts +101 -0
  29. package/dist/components/memory-panel/styles.d.ts +2 -0
  30. package/dist/components/model-picker/index.d.ts +2 -0
  31. package/dist/components/model-picker/model-picker.d.ts +136 -0
  32. package/dist/components/model-picker/morph.d.ts +9 -0
  33. package/dist/components/model-picker/styles.d.ts +6 -0
  34. package/dist/components/tool-call-card/index.d.ts +7 -0
  35. package/dist/components/tool-call-card/logic.d.ts +87 -0
  36. package/dist/components/tool-call-card/strings.d.ts +94 -0
  37. package/dist/components/tool-call-card/styles.d.ts +5 -0
  38. package/dist/components/tool-call-card/tool-call-card.d.ts +49 -0
  39. package/dist/components/tool-call-card/tool-call-group.d.ts +32 -0
  40. package/dist/context-window.js +384 -0
  41. package/dist/context-window.js.map +1 -0
  42. package/dist/core/element.d.ts +41 -0
  43. package/dist/core/format.d.ts +14 -0
  44. package/dist/core/html.d.ts +10 -0
  45. package/dist/core/tokens.d.ts +14 -0
  46. package/dist/format-BBGWXPzk.js +51 -0
  47. package/dist/format-BBGWXPzk.js.map +1 -0
  48. package/dist/html-elD6Bb_u.js +175 -0
  49. package/dist/html-elD6Bb_u.js.map +1 -0
  50. package/dist/index.d.ts +16 -0
  51. package/dist/index.js +129 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/memory-panel.js +1255 -0
  54. package/dist/memory-panel.js.map +1 -0
  55. package/dist/model-picker.js +858 -0
  56. package/dist/model-picker.js.map +1 -0
  57. package/dist/tokens.css +4 -0
  58. package/dist/tool-call-card.js +1046 -0
  59. package/dist/tool-call-card.js.map +1 -0
  60. package/package.json +79 -4
@@ -0,0 +1,473 @@
1
+ /** Live time phrases. `at` is the epoch the phrase counts to (or from, for `since` / `fetched`). */
2
+ export type TimeKind = 'left' | 'in' | 'back' | 'runs' | 'since' | 'fetched';
3
+ declare const en: {
4
+ /** Time left, floored: 1d 5h · 1h 20m · 24m · 42s. */
5
+ dur: (s: number) => string;
6
+ soon: string;
7
+ in: (x: string) => string;
8
+ back: (x: string) => string;
9
+ backSoon: string;
10
+ runs: (x: string) => string;
11
+ runsSoon: string;
12
+ since: (x: string) => string;
13
+ fetched: (s: number) => string;
14
+ /** Age of a measurement, first unit only: 12m · 4h · 6d. */
15
+ age: (s: number) => string;
16
+ capTitle: string;
17
+ capError: (r: string) => string;
18
+ capNone: string;
19
+ capAria: (n: string) => string;
20
+ source: (src: string, n: number) => string;
21
+ pill: {
22
+ unknown: string;
23
+ allLimited: string;
24
+ empty: string;
25
+ limited: (n: number) => string;
26
+ low: string;
27
+ ok: string;
28
+ };
29
+ disc: {
30
+ reflected: (c: number, n: number) => string;
31
+ blocked: (b: number) => string;
32
+ excluded: (n: number, why: string) => string;
33
+ held: string;
34
+ unknownTier: string;
35
+ noMeasure: string;
36
+ assumed: (n: number, tier: string) => string;
37
+ estimated: (n: number) => string;
38
+ unmeasured: (n: number) => string;
39
+ measured: (a: string) => string;
40
+ };
41
+ bar: {
42
+ fiveHour: string;
43
+ fiveHourSub: string;
44
+ weekly: string;
45
+ weeklySub: string;
46
+ of: (total: string) => string;
47
+ said: (label: string, v: string, total: string, pct: string) => string;
48
+ low: (p: number) => string;
49
+ next: (gain: string) => string;
50
+ heldByWeekly: string;
51
+ backWithin: (g: string) => string;
52
+ nothing: string;
53
+ unknown: string;
54
+ };
55
+ gain: (x: number, f: (n: number) => string) => string;
56
+ cause: Record<string, string>;
57
+ workers: string;
58
+ workersAria: (name: string, r: number, n: number) => string;
59
+ reason: Record<string, string>;
60
+ stateWord: Record<string, string>;
61
+ noReturn: string;
62
+ okFold: (n: number) => string;
63
+ okFoldAria: (n: number) => string;
64
+ tierAssumed: (t: string) => string;
65
+ noTier: string;
66
+ card: {
67
+ aria: (n: string) => string;
68
+ close: string;
69
+ now: string;
70
+ week: string;
71
+ binds: string;
72
+ h5: string;
73
+ wk: string;
74
+ state: string;
75
+ returns: string;
76
+ estimated: string;
77
+ estimatedSay: string;
78
+ okTitle: string;
79
+ okAria: string;
80
+ okKind: (p: string, n: number) => string;
81
+ okRow: (now: string, wk: string) => string;
82
+ };
83
+ tl: {
84
+ h5: string;
85
+ wk: string;
86
+ note: string;
87
+ none5: string;
88
+ small5: (g: string) => string;
89
+ aria: string;
90
+ axis: string[];
91
+ mark: (w: string, gain: string, when: string, names: string) => string;
92
+ lim: (until: string) => string;
93
+ limNone: string;
94
+ };
95
+ news: {
96
+ allLimited: (n: string, back: string) => string;
97
+ empty: (n: string, back: string) => string;
98
+ again: (n: string, r: number, total: number) => string;
99
+ low: (n: string, wk: boolean, p: number, v: string, t: string) => string;
100
+ fail: (n: string, err: string) => string;
101
+ wait: (n: string) => string;
102
+ };
103
+ laneAria: (t: string) => string;
104
+ running: (n: number) => string;
105
+ waiting: (n: number) => string;
106
+ stat: {
107
+ next: string;
108
+ running: string;
109
+ runs: string;
110
+ fails: string;
111
+ nextTitle: (name: string, at: string) => string;
112
+ none: string;
113
+ runningTitle: (r: number, n: number) => string;
114
+ unknown: (u: number) => string;
115
+ runsTitle: (n: number, ok: number, f: number, run: number) => string;
116
+ unknownTitle: (u: number) => string;
117
+ failsTitle: string;
118
+ cut: (name: string, cap: number, from: string) => string;
119
+ };
120
+ queue: {
121
+ head: string;
122
+ headTitle: string;
123
+ aria: string;
124
+ empty: string;
125
+ said: (name: string, when: string, i: number, n: number) => string;
126
+ };
127
+ job: {
128
+ past: (n: number) => string;
129
+ next: (clock: string) => string;
130
+ exprTitle: (e: string) => string;
131
+ strip: (name: string, k: number, sum: string) => string;
132
+ noRuns: string;
133
+ noRecords: string;
134
+ running: string;
135
+ waiting: string;
136
+ };
137
+ run: Record<string, string>;
138
+ runCount: Record<string, string>;
139
+ runSum: (n: number, word: string) => string;
140
+ chart: {
141
+ title: string;
142
+ ok: string;
143
+ run: string;
144
+ fail: string;
145
+ okTitle: string;
146
+ runTitle: string;
147
+ failTitle: string;
148
+ axis: string[];
149
+ col: (at: string, ok: number, f: number, r: number) => string;
150
+ said: (n: number, ok: number, f: number, r: number) => string;
151
+ peak: (at: string, n: number) => string;
152
+ cut: (at: string) => string;
153
+ unknown: (u: number) => string;
154
+ hatch: (names: string) => string;
155
+ };
156
+ };
157
+ export type Strings = typeof en;
158
+ export declare const STRINGS: {
159
+ en: {
160
+ /** Time left, floored: 1d 5h · 1h 20m · 24m · 42s. */
161
+ dur: (s: number) => string;
162
+ soon: string;
163
+ in: (x: string) => string;
164
+ back: (x: string) => string;
165
+ backSoon: string;
166
+ runs: (x: string) => string;
167
+ runsSoon: string;
168
+ since: (x: string) => string;
169
+ fetched: (s: number) => string;
170
+ /** Age of a measurement, first unit only: 12m · 4h · 6d. */
171
+ age: (s: number) => string;
172
+ capTitle: string;
173
+ capError: (r: string) => string;
174
+ capNone: string;
175
+ capAria: (n: string) => string;
176
+ source: (src: string, n: number) => string;
177
+ pill: {
178
+ unknown: string;
179
+ allLimited: string;
180
+ empty: string;
181
+ limited: (n: number) => string;
182
+ low: string;
183
+ ok: string;
184
+ };
185
+ disc: {
186
+ reflected: (c: number, n: number) => string;
187
+ blocked: (b: number) => string;
188
+ excluded: (n: number, why: string) => string;
189
+ held: string;
190
+ unknownTier: string;
191
+ noMeasure: string;
192
+ assumed: (n: number, tier: string) => string;
193
+ estimated: (n: number) => string;
194
+ unmeasured: (n: number) => string;
195
+ measured: (a: string) => string;
196
+ };
197
+ bar: {
198
+ fiveHour: string;
199
+ fiveHourSub: string;
200
+ weekly: string;
201
+ weeklySub: string;
202
+ of: (total: string) => string;
203
+ said: (label: string, v: string, total: string, pct: string) => string;
204
+ low: (p: number) => string;
205
+ next: (gain: string) => string;
206
+ heldByWeekly: string;
207
+ backWithin: (g: string) => string;
208
+ nothing: string;
209
+ unknown: string;
210
+ };
211
+ gain: (x: number, f: (n: number) => string) => string;
212
+ cause: Record<string, string>;
213
+ workers: string;
214
+ workersAria: (name: string, r: number, n: number) => string;
215
+ reason: Record<string, string>;
216
+ stateWord: Record<string, string>;
217
+ noReturn: string;
218
+ okFold: (n: number) => string;
219
+ okFoldAria: (n: number) => string;
220
+ tierAssumed: (t: string) => string;
221
+ noTier: string;
222
+ card: {
223
+ aria: (n: string) => string;
224
+ close: string;
225
+ now: string;
226
+ week: string;
227
+ binds: string;
228
+ h5: string;
229
+ wk: string;
230
+ state: string;
231
+ returns: string;
232
+ estimated: string;
233
+ estimatedSay: string;
234
+ okTitle: string;
235
+ okAria: string;
236
+ okKind: (p: string, n: number) => string;
237
+ okRow: (now: string, wk: string) => string;
238
+ };
239
+ tl: {
240
+ h5: string;
241
+ wk: string;
242
+ note: string;
243
+ none5: string;
244
+ small5: (g: string) => string;
245
+ aria: string;
246
+ axis: string[];
247
+ mark: (w: string, gain: string, when: string, names: string) => string;
248
+ lim: (until: string) => string;
249
+ limNone: string;
250
+ };
251
+ news: {
252
+ allLimited: (n: string, back: string) => string;
253
+ empty: (n: string, back: string) => string;
254
+ again: (n: string, r: number, total: number) => string;
255
+ low: (n: string, wk: boolean, p: number, v: string, t: string) => string;
256
+ fail: (n: string, err: string) => string;
257
+ wait: (n: string) => string;
258
+ };
259
+ laneAria: (t: string) => string;
260
+ running: (n: number) => string;
261
+ waiting: (n: number) => string;
262
+ stat: {
263
+ next: string;
264
+ running: string;
265
+ runs: string;
266
+ fails: string;
267
+ nextTitle: (name: string, at: string) => string;
268
+ none: string;
269
+ runningTitle: (r: number, n: number) => string;
270
+ unknown: (u: number) => string;
271
+ runsTitle: (n: number, ok: number, f: number, run: number) => string;
272
+ unknownTitle: (u: number) => string;
273
+ failsTitle: string;
274
+ cut: (name: string, cap: number, from: string) => string;
275
+ };
276
+ queue: {
277
+ head: string;
278
+ headTitle: string;
279
+ aria: string;
280
+ empty: string;
281
+ said: (name: string, when: string, i: number, n: number) => string;
282
+ };
283
+ job: {
284
+ past: (n: number) => string;
285
+ next: (clock: string) => string;
286
+ exprTitle: (e: string) => string;
287
+ strip: (name: string, k: number, sum: string) => string;
288
+ noRuns: string;
289
+ noRecords: string;
290
+ running: string;
291
+ waiting: string;
292
+ };
293
+ run: Record<string, string>;
294
+ runCount: Record<string, string>;
295
+ runSum: (n: number, word: string) => string;
296
+ chart: {
297
+ title: string;
298
+ ok: string;
299
+ run: string;
300
+ fail: string;
301
+ okTitle: string;
302
+ runTitle: string;
303
+ failTitle: string;
304
+ axis: string[];
305
+ col: (at: string, ok: number, f: number, r: number) => string;
306
+ said: (n: number, ok: number, f: number, r: number) => string;
307
+ peak: (at: string, n: number) => string;
308
+ cut: (at: string) => string;
309
+ unknown: (u: number) => string;
310
+ hatch: (names: string) => string;
311
+ };
312
+ };
313
+ ko: {
314
+ /** Time left, floored: 1d 5h · 1h 20m · 24m · 42s. */
315
+ dur: (s: number) => string;
316
+ soon: string;
317
+ in: (x: string) => string;
318
+ back: (x: string) => string;
319
+ backSoon: string;
320
+ runs: (x: string) => string;
321
+ runsSoon: string;
322
+ since: (x: string) => string;
323
+ fetched: (s: number) => string;
324
+ /** Age of a measurement, first unit only: 12m · 4h · 6d. */
325
+ age: (s: number) => string;
326
+ capTitle: string;
327
+ capError: (r: string) => string;
328
+ capNone: string;
329
+ capAria: (n: string) => string;
330
+ source: (src: string, n: number) => string;
331
+ pill: {
332
+ unknown: string;
333
+ allLimited: string;
334
+ empty: string;
335
+ limited: (n: number) => string;
336
+ low: string;
337
+ ok: string;
338
+ };
339
+ disc: {
340
+ reflected: (c: number, n: number) => string;
341
+ blocked: (b: number) => string;
342
+ excluded: (n: number, why: string) => string;
343
+ held: string;
344
+ unknownTier: string;
345
+ noMeasure: string;
346
+ assumed: (n: number, tier: string) => string;
347
+ estimated: (n: number) => string;
348
+ unmeasured: (n: number) => string;
349
+ measured: (a: string) => string;
350
+ };
351
+ bar: {
352
+ fiveHour: string;
353
+ fiveHourSub: string;
354
+ weekly: string;
355
+ weeklySub: string;
356
+ of: (total: string) => string;
357
+ said: (label: string, v: string, total: string, pct: string) => string;
358
+ low: (p: number) => string;
359
+ next: (gain: string) => string;
360
+ heldByWeekly: string;
361
+ backWithin: (g: string) => string;
362
+ nothing: string;
363
+ unknown: string;
364
+ };
365
+ gain: (x: number, f: (n: number) => string) => string;
366
+ cause: Record<string, string>;
367
+ workers: string;
368
+ workersAria: (name: string, r: number, n: number) => string;
369
+ reason: Record<string, string>;
370
+ stateWord: Record<string, string>;
371
+ noReturn: string;
372
+ okFold: (n: number) => string;
373
+ okFoldAria: (n: number) => string;
374
+ tierAssumed: (t: string) => string;
375
+ noTier: string;
376
+ card: {
377
+ aria: (n: string) => string;
378
+ close: string;
379
+ now: string;
380
+ week: string;
381
+ binds: string;
382
+ h5: string;
383
+ wk: string;
384
+ state: string;
385
+ returns: string;
386
+ estimated: string;
387
+ estimatedSay: string;
388
+ okTitle: string;
389
+ okAria: string;
390
+ okKind: (p: string, n: number) => string;
391
+ okRow: (now: string, wk: string) => string;
392
+ };
393
+ tl: {
394
+ h5: string;
395
+ wk: string;
396
+ note: string;
397
+ none5: string;
398
+ small5: (g: string) => string;
399
+ aria: string;
400
+ axis: string[];
401
+ mark: (w: string, gain: string, when: string, names: string) => string;
402
+ lim: (until: string) => string;
403
+ limNone: string;
404
+ };
405
+ news: {
406
+ allLimited: (n: string, back: string) => string;
407
+ empty: (n: string, back: string) => string;
408
+ again: (n: string, r: number, total: number) => string;
409
+ low: (n: string, wk: boolean, p: number, v: string, t: string) => string;
410
+ fail: (n: string, err: string) => string;
411
+ wait: (n: string) => string;
412
+ };
413
+ laneAria: (t: string) => string;
414
+ running: (n: number) => string;
415
+ waiting: (n: number) => string;
416
+ stat: {
417
+ next: string;
418
+ running: string;
419
+ runs: string;
420
+ fails: string;
421
+ nextTitle: (name: string, at: string) => string;
422
+ none: string;
423
+ runningTitle: (r: number, n: number) => string;
424
+ unknown: (u: number) => string;
425
+ runsTitle: (n: number, ok: number, f: number, run: number) => string;
426
+ unknownTitle: (u: number) => string;
427
+ failsTitle: string;
428
+ cut: (name: string, cap: number, from: string) => string;
429
+ };
430
+ queue: {
431
+ head: string;
432
+ headTitle: string;
433
+ aria: string;
434
+ empty: string;
435
+ said: (name: string, when: string, i: number, n: number) => string;
436
+ };
437
+ job: {
438
+ past: (n: number) => string;
439
+ next: (clock: string) => string;
440
+ exprTitle: (e: string) => string;
441
+ strip: (name: string, k: number, sum: string) => string;
442
+ noRuns: string;
443
+ noRecords: string;
444
+ running: string;
445
+ waiting: string;
446
+ };
447
+ run: Record<string, string>;
448
+ runCount: Record<string, string>;
449
+ runSum: (n: number, word: string) => string;
450
+ chart: {
451
+ title: string;
452
+ ok: string;
453
+ run: string;
454
+ fail: string;
455
+ okTitle: string;
456
+ runTitle: string;
457
+ failTitle: string;
458
+ axis: string[];
459
+ col: (at: string, ok: number, f: number, r: number) => string;
460
+ said: (n: number, ok: number, f: number, r: number) => string;
461
+ peak: (at: string, n: number) => string;
462
+ cut: (at: string) => string;
463
+ unknown: (u: number) => string;
464
+ hatch: (names: string) => string;
465
+ };
466
+ };
467
+ };
468
+ /**
469
+ * The text of a live time element. Future kinds count down (floored; `soon` at zero — never “in soon”);
470
+ * `since` / `fetched` count up from a past epoch.
471
+ */
472
+ export declare function timeText(kind: TimeKind, atMs: number, nowMs: number, t: Strings): string;
473
+ export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Ported from the soma-work dashboard: "CRON badge · lane", "LLM capacity v2" and "Agent Queue grammar"
3
+ * (.prd/affectui/re-agent-queue.md D2·D5–D7·D9–D11·D16–D19). The dashboard's dark-first hexes with a light override
4
+ * are folded into tokens: the 5-hour teal is mixed from --green and --accent, the weekly violet is --purple, and
5
+ * warning text is --st-wait pulled toward --text so it holds 4.5:1 in light (light --st-wait alone is 3.5:1 on white).
6
+ * Override with --ui-aq-now / --ui-aq-wk on the page.
7
+ */
8
+ export declare const styles = "\n:host {\n --aq-now: var(--ui-aq-now, color-mix(in oklch, var(--green) 55%, var(--accent)));\n --aq-wk: var(--ui-aq-wk, var(--purple));\n --aq-warn: var(--st-wait);\n --aq-warn-text: color-mix(in srgb, var(--st-wait) 75%, var(--text));\n}\n.aq { display: grid; gap: 12px; min-width: 0; }\n\n/* \u2500\u2500 Shared grammar: pill, countdown, column head \u2500\u2500 */\n.aq-head { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; min-width: 0; }\n.aq-name { font-size: 12px; color: var(--ib-muted); white-space: nowrap; }\n.aq-pill { display: inline-flex; align-items: center; gap: 4px; min-height: 22px; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; line-height: 1.3; white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--aq-pc, var(--ib-text-2)); background: color-mix(in srgb, var(--aq-pc, var(--ib-muted)) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--aq-pc, var(--ib-muted)) 45%, transparent); }\n.aq-pill.is-ok { --aq-pc: var(--st-done); }\n.aq-pill.is-run { --aq-pc: var(--st-run); }\n.aq-pill.is-paused, .aq-pill.is-low, .aq-pill.is-wait { --aq-pc: var(--aq-warn); color: var(--aq-warn-text); }\n.aq-pill.is-empty { --aq-pc: var(--st-fail); color: var(--st-fail-text); }\n.aq-pill.is-unknown { --aq-pc: var(--ib-muted); }\n.aq-left, .aq-ago { font-variant-numeric: tabular-nums; }\n.aq-col-head { display: flex; align-items: baseline; gap: 6px; font-size: 12px; color: var(--ib-muted); }\n.aq-col-head b { color: var(--ib-text); font-weight: 600; font-variant-numeric: tabular-nums; }\n\n/* \u2500\u2500 LLM capacity: colour is the window (teal = now \u00B7 5h, violet = this week \u00B7 7d) \u2500\u2500 */\n.capacity { background: var(--ib-col); border-radius: 14px; padding: 12px 14px 10px; color: var(--ib-text); min-width: 0; }\n.cap-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 12px; margin-bottom: 4px; }\n.cap-title { margin: 0; font-size: 12px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ib-muted); }\n.cap-sub { font-size: 12px; color: var(--ib-text-2); }\n.cap-off { font-size: 13px; color: var(--ib-text-2); padding: 8px 0 10px; }\n.cap-prov { container: aqprov / inline-size; position: relative; background: var(--ib-card); border-radius: 12px; padding: 14px 18px 12px; margin-top: 10px; box-shadow: inset 0 0 0 1px var(--ib-card-border); min-width: 0; }\n.cap-prov.is-empty { box-shadow: inset 0 0 0 1px var(--st-fail); }\n.cap-prov.is-low { box-shadow: inset 0 0 0 1px var(--st-wait); }\n.cap-pname { margin: 0; font-size: 16px; font-weight: 700; color: var(--ib-text); }\n.cap-disc { font-size: 12px; color: var(--ib-muted); margin: 2px 0 8px; }\n.cap-disc .cap-stale { color: var(--aq-warn-text); font-weight: 600; }\n/* One bar per window \u2014 label | bar | \"x / total accounts %\" \u2014 and a \"next \u2026\" line. */\n.cap-bar-row { display: grid; grid-template-columns: 92px minmax(0, 1fr) 200px; align-items: center; gap: 4px 12px; margin: 8px 0; }\n.cap-bar-lbl { font-size: 14px; font-weight: 700; line-height: 1.2; }\n.cap-bar-lbl i { display: block; font-style: normal; font-weight: 400; font-size: 11px; color: var(--ib-muted); }\n.cap-bar-row.is-h5 .cap-bar-lbl { color: var(--aq-now); }\n.cap-bar-row.is-wk .cap-bar-lbl { color: var(--aq-wk); }\n.cap-bar { position: relative; height: 26px; border-radius: 7px; background: var(--ib-pill); overflow: hidden; }\n.cap-bar > span { display: block; height: 100%; border-radius: 7px; transition: width var(--dur-move) var(--ease-out); }\n.cap-bar-row.is-h5 .cap-bar > span { background: var(--aq-now); }\n.cap-bar-row.is-wk .cap-bar > span { background: var(--aq-wk); }\n/* The dashed line is where the pool turns low (the reference's backpressure line). */\n.cap-low { position: absolute; top: 0; bottom: 0; width: 0; border-left: 1px dashed var(--ib-text-2); opacity: 0.7; }\n.cap-bar-val { font-size: 14px; color: var(--ib-text-2); white-space: nowrap; font-variant-numeric: tabular-nums; }\n.cap-bar-val b { font-size: 19px; color: var(--ib-text); }\n.cap-bar-val em { font-style: normal; font-weight: 600; margin-left: 4px; }\n.cap-bar-next { grid-column: 2 / 4; font-size: 12px; color: var(--ib-text-2); }\n.cap-prov.is-empty .cap-bar-row.is-h5 .cap-bar-next { color: var(--st-fail-text); font-weight: 600; }\n.cap-tl-wrap { margin-top: 10px; border-top: 1px solid var(--ib-card-border); padding-top: 8px; }\n.cap-tl-h { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12px; color: var(--ib-text-2); }\n.cap-tl-h i { font-style: normal; }\n.cap-tl-h .is-h5 { color: var(--aq-now); }\n.cap-tl-h .is-wk { color: var(--aq-wk); }\n.cap-tl { display: block; max-width: 100%; height: auto; overflow: visible; }\n.cap-tl text { font-family: inherit; }\n.cap-tl-axis { stroke: var(--ib-muted); stroke-opacity: 0.5; stroke-width: 2; }\n.cap-tl-tick { stroke: var(--ib-card-border); }\n.cap-tl-ax { fill: var(--ib-muted); font-size: 11px; }\n.cap-tl-mk.is-h5 { fill: var(--aq-now); stroke: var(--aq-now); }\n.cap-tl-mk.is-wk { fill: var(--aq-wk); stroke: var(--aq-wk); }\n.cap-tl-mk circle, .cap-tl-mk rect { stroke: var(--ib-card); stroke-width: 1.5; }\n.cap-tl-span { stroke-width: 5; stroke-linecap: round; }\n.cap-tl-mk text { stroke: none; font-size: 12.5px; font-weight: 700; }\n.cap-tl-lim { fill: var(--st-fail); fill-opacity: 0.12; }\n.cap-tl-hatch { stroke: var(--st-fail); stroke-opacity: 0.4; stroke-width: 1.5; }\n/* Narrow card: label and value share the first line, the bar takes the full width, the next line under it. */\n@container aqprov (max-width: 599.98px) {\n .cap-bar-row { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 8px; margin: 10px 0; }\n .cap-bar-lbl { grid-row: 1; grid-column: 1; align-self: baseline; }\n .cap-bar-lbl i { display: inline; margin-left: 6px; }\n .cap-bar-val { grid-row: 1; grid-column: 2; align-self: baseline; }\n .cap-bar { grid-row: 2; grid-column: 1 / -1; height: 20px; }\n .cap-bar-next { grid-row: 3; grid-column: 1 / -1; }\n .cap-bar-val b { font-size: 16px; }\n .cap-tl-h-note { display: none; }\n}\n\n/* \u2500\u2500 Accounts as workers: state marks + the pinned account card \u2500\u2500 */\n.aq-workers { position: relative; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--ib-card-border); }\n.aq-marks { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }\n.aq-mark { display: inline-flex; align-items: center; gap: 5px; min-height: 28px; max-width: 100%; padding: 0 9px; border-radius: 8px; border: 1px solid var(--ib-card-border); background: var(--ib-card); color: var(--ib-text); font: inherit; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; transition: background-color var(--dur-fade) var(--ease-out), color var(--dur-fade) var(--ease-out), border-color var(--dur-fade) var(--ease-out); }\n.aq-mark b { font-weight: 600; }\n.aq-mark .aq-g { font-size: 10px; }\n.aq-mark.is-limited { color: var(--aq-warn-text); background: color-mix(in srgb, var(--aq-warn) 12%, var(--ib-card)); border-color: color-mix(in srgb, var(--aq-warn) 50%, transparent); }\n.aq-mark.is-spent, .aq-mark.is-unmeasured, .aq-mark.is-paused { color: var(--ib-text-2); background: var(--ib-pill); }\n.aq-mark.is-excluded { color: var(--ib-muted); background: transparent; border-style: dashed; }\n.aq-mark[aria-expanded=\"true\"] { border-color: var(--ib-text-2); }\n.aq-mark:focus-visible, .aq-q:focus-visible, .aq-pop-close:focus-visible, .cron-history-btn:focus-visible, .cron-strip:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }\n@media (hover: hover) and (pointer: fine) { .aq-mark:hover, .aq-q:hover { border-color: var(--ib-muted); } }\n.aq-wdot { flex: none; width: 7px; height: 7px; border-radius: 50%; }\n.aq-wdot.is-h5 { background: var(--aq-now); }\n.aq-wdot.is-wk { background: var(--aq-wk); }\n.aq-pop { position: absolute; z-index: 6; top: 100%; left: 8px; width: min(280px, calc(100% - 16px)); display: grid; gap: 10px; padding: 12px; border-radius: 12px; background: var(--ib-card); color: var(--ib-text); box-shadow: 0 0 0 1px var(--ib-card-border), var(--ib-shadow-raised); animation: aq-open var(--dur-fade) var(--ease-out); }\n.cap-prov.is-narrow .aq-pop { width: calc(100% - 24px); }\n@keyframes aq-open { from { opacity: 0; transform: translateY(-4px) scale(0.97); } to { opacity: 1; transform: none; } }\n.aq-pop-head { display: flex; align-items: center; gap: 8px; min-width: 0; }\n.aq-pop-name { font-size: 14px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.aq-pop-kind { flex: 1 1 auto; min-width: 0; font-size: 12px; color: var(--ib-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.aq-pop-close { flex: none; width: 28px; height: 28px; border-radius: 8px; border: 1px solid var(--ib-card-border); background: none; color: var(--ib-text-2); font: inherit; font-size: 16px; line-height: 1; cursor: pointer; }\n.aq-pop-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; margin: 0; padding: 10px 12px; border-radius: 10px; background: var(--ib-col); }\n.aq-pop-stats dt { font-size: 11px; color: var(--ib-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.aq-pop-stats dd { margin: 0; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; }\n.aq-pop-stats .is-wide { grid-column: 1 / -1; }\n\n/* \u2500\u2500 CRON lane = the queue \u2500\u2500 */\n.aq-lane { container: aqlane / inline-size; background: var(--ib-col); border-radius: 14px; padding: 2px 4px 10px; color: var(--ib-text); min-width: 0; }\n.aq-lane-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; padding: 10px 8px 8px 10px; min-height: 40px; }\n.aq-lane-ic { display: inline-flex; color: var(--ib-muted); }\n.aq-lane-ic svg { width: 14px; height: 14px; }\n.aq-lane-title { margin: 0; font-size: 12px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ib-muted); }\n.aq-count { background: var(--ib-pill); color: var(--ib-text-2); border-radius: 6px; padding: 1px 7px; font-size: 12px; font-weight: 500; min-width: 22px; text-align: center; font-variant-numeric: tabular-nums; }\n.aq-lane-top { padding: 0 4px 10px; }\n.aq-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0; padding: 12px 0; border-radius: 12px; background: var(--ib-card); box-shadow: inset 0 0 0 1px var(--ib-card-border); }\n.aq-stat { display: grid; gap: 2px; min-width: 0; padding: 0 16px; }\n.aq-stat + .aq-stat { border-left: 1px solid var(--ib-card-border); }\n.aq-stat dt { font-size: 12px; color: var(--ib-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.aq-stat dd { margin: 0; font-size: 16px; font-weight: 600; color: var(--ib-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }\n.aq-stat[data-kind=\"failed\"] dd { color: var(--st-fail-text); }\n.aq-of { margin-left: 4px; font-size: 13px; font-weight: 500; color: var(--ib-muted); }\n.aq-of.is-n { margin-left: 1px; }\n.aq-lane-body { display: grid; grid-template-columns: clamp(188px, 26%, 236px) minmax(0, 1fr); gap: 10px; align-items: start; padding: 0 4px; }\n.aq-queue { display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 10px; border-radius: 12px; border: 1px solid var(--ib-card-border); background: color-mix(in srgb, var(--ib-card) 45%, transparent); }\n.aq-q { display: flex; align-items: center; gap: 6px; min-height: 28px; padding: 0 8px; border-radius: 8px; border: 1px solid var(--ib-card-border); background: var(--ib-card); color: var(--ib-text); font: inherit; font-size: 12.5px; text-align: left; cursor: pointer; }\n.aq-q.is-new { animation: aq-in var(--dur-fade) var(--ease-out); }\n.aq-q svg { flex: none; width: 12px; height: 12px; color: var(--ib-muted); }\n.aq-q-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.aq-q .aq-left { flex: none; font-size: 11.5px; color: var(--ib-muted); }\n.aq-more { align-self: flex-start; padding: 1px 8px; border-radius: 6px; background: var(--ib-pill); color: var(--ib-text-2); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }\n.aq-empty { padding: 4px 2px; font-size: 12px; color: var(--ib-muted); }\n@keyframes aq-in { from { opacity: 0; } to { opacity: 1; } }\n\n/* Job cards (CRON tiles) */\n.cron-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); gap: 10px; align-items: start; min-width: 0; }\n.cron-group { position: relative; display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 10px; border-radius: 12px; border: 1px dashed var(--ib-card-border); background: color-mix(in srgb, var(--ib-card) 45%, transparent); transition: border-color 150ms ease; }\n.cron-group.is-running { border-style: solid; border-color: color-mix(in srgb, var(--st-run) 55%, transparent); }\n.cron-group.is-waiting { border-style: solid; border-color: var(--st-wait); }\n.cron-tile { display: flex; flex-direction: column; gap: 6px; min-width: 0; --st-color: var(--ib-text-2); }\n.cron-group.is-running .cron-tile { --st-color: var(--st-run); }\n.cron-group.is-waiting .cron-tile { --st-color: var(--aq-warn-text); }\n.cron-tile-head { display: flex; align-items: center; gap: 8px; min-width: 0; }\n.cron-badge { flex-shrink: 0; display: inline-flex; align-items: center; gap: 4px; padding: 1px 7px 1px 5px; border-radius: 999px; font-size: 11px; font-weight: 700; letter-spacing: 0.06em; line-height: 1.5; color: var(--st-color, var(--ib-text-2)); background: color-mix(in srgb, var(--st-color, var(--ib-muted)) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st-color, var(--ib-muted)) 45%, transparent); }\n.cron-badge svg { width: 12px; height: 12px; }\n.cron-name { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 600; color: var(--ib-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.cron-history-btn { flex-shrink: 0; margin-left: auto; min-height: 28px; padding: 2px 10px; border-radius: 8px; border: 1px solid var(--ib-card-border); background: var(--ib-card); color: var(--ib-text-2); font: inherit; font-size: 12px; cursor: pointer; transition: transform var(--dur-press) var(--ease-out), border-color 150ms ease; }\n.cron-history-btn:active:not(:focus-visible) { transform: scale(0.97); }\n@media (hover: hover) and (pointer: fine) { .cron-history-btn:hover { border-color: var(--ib-muted); color: var(--ib-text); } }\n.cron-sched { display: flex; flex-wrap: wrap; gap: 2px 10px; font-size: 12px; color: var(--ib-text-2); font-variant-numeric: tabular-nums; }\n.cron-expr { color: var(--ib-text); }\n.cron-strip { display: flex; align-items: flex-end; gap: 3px; height: 22px; padding: 2px 0; border: 0; border-radius: 4px; background: none; cursor: pointer; width: max-content; max-width: 100%; }\n.cron-strip.is-empty { cursor: default; font-size: 12px; color: var(--ib-muted); height: auto; }\n.cr-tick { display: block; flex: none; width: 8px; height: 16px; border-radius: 2px; background: var(--st-done); }\n.cr-tick.is-fail { background: var(--st-fail); height: 18px; }\n.cr-tick.is-none { background: transparent; box-shadow: inset 0 0 0 1.5px var(--ib-muted); }\n.cr-tick.is-run { background: var(--st-run); }\n.cr-tick.is-wait { background: var(--st-wait); }\n@keyframes cr-pulse { 50% { opacity: 0.45; } }\n@media (prefers-reduced-motion: no-preference) { .cr-tick.is-run { animation: cr-pulse 1.6s ease-in-out infinite; } }\n.cron-status { font-size: 12px; color: var(--ib-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.cron-status.is-run { color: var(--st-run); font-weight: 600; }\n.cron-status.is-wait { color: var(--aq-warn-text); font-weight: 600; }\n.cron-status.is-fail { color: var(--st-fail-text); }\n\n/* 24 hours of runs */\n.aq-chart { margin: 10px 4px 0; padding: 12px 14px 10px; border-radius: 12px; background: var(--ib-card); box-shadow: inset 0 0 0 1px var(--ib-card-border); }\n.aq-chart-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; margin-bottom: 10px; font-size: 12px; }\n.aq-chart-title { font-weight: 500; color: var(--ib-text); }\n.aq-chart-title + .aq-ch-key { margin-left: auto; }\n.aq-ch-key { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--ib-text-2); }\n.aq-ch-key i { width: 8px; height: 8px; border-radius: 2px; }\n.aq-ch-key i.is-ok { background: var(--st-done); }\n.aq-ch-key i.is-run { background: var(--st-run); }\n.aq-ch-key i.is-fail { background: var(--st-fail); }\n.aq-plot { position: relative; height: 112px; margin-left: 26px; display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ib-card-border); }\n.aq-ch-grid { position: absolute; left: -26px; right: 0; top: 0; height: 0; border-top: 1px dashed var(--ib-pill); pointer-events: none; }\n.aq-ch-grid.is-zero { top: 100%; border-top: 0; }\n.aq-ch-grid span { position: absolute; left: 0; top: -7px; width: 20px; text-align: right; font-size: 11px; line-height: 14px; color: var(--ib-muted); font-variant-numeric: tabular-nums; }\n.aq-ch-cut { position: absolute; top: 0; bottom: 0; background: repeating-linear-gradient(-45deg, transparent 0 5px, color-mix(in srgb, var(--ib-muted) 22%, transparent) 5px 6px); }\n.aq-ch-col { position: relative; z-index: 1; flex: 1 1 0; min-width: 0; display: flex; flex-direction: column-reverse; }\n.aq-ch-ok, .aq-ch-run, .aq-ch-fail { display: block; transition: height var(--dur-expand) var(--ease-out); }\n.aq-ch-ok { background: var(--st-done); }\n.aq-ch-run { background: var(--st-run); }\n.aq-ch-fail { background: var(--st-fail); border-radius: 2px 2px 0 0; }\n.aq-ch-axis { display: flex; justify-content: space-between; margin: 6px 0 0 26px; font-size: 11px; color: var(--ib-muted); }\n\n@container aqlane (max-width: 599.98px) {\n .aq-lane-body { grid-template-columns: minmax(0, 1fr); }\n .aq-plot { height: 88px; }\n}\n@container aqlane (max-width: 560px) {\n .aq-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 12px; }\n .aq-stat { padding: 0 12px; }\n .aq-stat:nth-child(odd) { border-left: 0; }\n .aq-stat dd { font-size: 15px; }\n}\n@media (pointer: coarse) {\n .aq-mark, .aq-q, .cron-history-btn, .cron-strip { min-height: 44px; }\n .aq-pop-close { width: 44px; height: 44px; }\n}\n@media (prefers-reduced-motion: reduce) {\n .aq-mark, .aq-q, .aq-pop, .cap-bar > span, .aq-ch-ok, .aq-ch-run, .aq-ch-fail, .cr-tick { animation: none; transition: none; }\n}\n";