@pikoloo/codex-proxy 1.0.7 → 1.2.2

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 (42) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +28 -11
  3. package/bin/cli.js +15 -15
  4. package/docs/ACCOUNT.md +104 -0
  5. package/docs/API.md +21 -29
  6. package/docs/ARCHITECTURE.md +9 -9
  7. package/docs/CLAUDE_INTEGRATION.md +3 -3
  8. package/docs/OAUTH.md +13 -13
  9. package/docs/OPENCLAW.md +1 -1
  10. package/docs/legal.md +6 -0
  11. package/images/dashboard-screenshot.png +0 -0
  12. package/images/readme-cover.png +0 -0
  13. package/images/settings-screenshot.png +0 -0
  14. package/package.json +19 -10
  15. package/public/css/style.css +802 -22
  16. package/public/index.html +236 -338
  17. package/public/js/app.js +140 -118
  18. package/src/account-manager.js +210 -292
  19. package/src/cli/account.js +236 -0
  20. package/src/direct-api.js +7 -9
  21. package/src/index.js +7 -7
  22. package/src/middleware/credentials.js +6 -47
  23. package/src/oauth.js +2 -1
  24. package/src/routes/{accounts-route.js → account-route.js} +25 -109
  25. package/src/routes/api-routes.js +18 -30
  26. package/src/routes/chat-route.js +3 -3
  27. package/src/routes/messages-route.js +37 -199
  28. package/src/routes/models-route.js +11 -21
  29. package/src/routes/settings-route.js +1 -41
  30. package/src/security.js +1 -1
  31. package/src/server-settings.js +30 -38
  32. package/src/utils/logger.js +14 -1
  33. package/docs/ACCOUNTS.md +0 -202
  34. package/images/demo-screenshot.png +0 -0
  35. package/images/f757093f-507b-4453-994e-f8275f8b07a9.png +0 -0
  36. package/src/account-rotation/index.js +0 -93
  37. package/src/account-rotation/rate-limits.js +0 -293
  38. package/src/account-rotation/strategies/base-strategy.js +0 -48
  39. package/src/account-rotation/strategies/index.js +0 -31
  40. package/src/account-rotation/strategies/round-robin-strategy.js +0 -42
  41. package/src/account-rotation/strategies/sticky-strategy.js +0 -97
  42. package/src/cli/accounts.js +0 -557
@@ -13,6 +13,12 @@
13
13
  --color-neon-yellow: #eab308;
14
14
  --color-text-dim: #9ca3af;
15
15
  --color-surface-glow: rgba(34, 211, 238, 0.06);
16
+ --app-header-height: 48px;
17
+ --surface-nav: rgba(15, 15, 26, 0.88);
18
+ --surface-nav-border: rgba(255, 255, 255, 0.12);
19
+ --surface-nav-active: rgba(255, 255, 255, 0.1);
20
+ --surface-nav-glow: 0 18px 38px rgba(0, 0, 0, 0.32);
21
+ --surface-nav-accent: var(--color-neon-cyan);
16
22
  }
17
23
 
18
24
  * { margin: 0; padding: 0; box-sizing: border-box; }
@@ -83,6 +89,489 @@ body::before {
83
89
  color: white;
84
90
  }
85
91
 
92
+ .app-header {
93
+ height: var(--app-header-height);
94
+ min-height: var(--app-header-height);
95
+ }
96
+
97
+ .app-brand {
98
+ min-width: 0;
99
+ }
100
+
101
+ .app-brand-mark {
102
+ width: 1.75rem;
103
+ height: 1.75rem;
104
+ border-radius: 8px;
105
+ font-size: 0.72rem;
106
+ letter-spacing: 0;
107
+ }
108
+
109
+ .app-brand-title {
110
+ white-space: nowrap;
111
+ font-size: 0.75rem;
112
+ letter-spacing: 0;
113
+ }
114
+
115
+ .app-brand-meta {
116
+ height: 1.15rem;
117
+ padding: 0 0.38rem;
118
+ font-size: 0.62rem;
119
+ }
120
+
121
+ .app-toolbar {
122
+ gap: 0.5rem;
123
+ }
124
+
125
+ .app-connection-status {
126
+ min-height: 1.55rem;
127
+ padding: 0.18rem 0.55rem;
128
+ font-size: 0.68rem;
129
+ }
130
+
131
+ .app-header-action {
132
+ width: 1.8rem;
133
+ min-height: 1.8rem;
134
+ padding: 0;
135
+ }
136
+
137
+ .app-toolbar-divider {
138
+ height: 1rem;
139
+ }
140
+
141
+ .section-header,
142
+ .section-heading,
143
+ .section-actions {
144
+ min-width: 0;
145
+ }
146
+
147
+ .section-heading {
148
+ flex: 1 1 auto;
149
+ }
150
+
151
+ .section-actions {
152
+ flex: 0 1 auto;
153
+ max-width: 100%;
154
+ }
155
+
156
+ .account-actions,
157
+ .logs-count-strip,
158
+ .metrics-range-controls {
159
+ flex-wrap: nowrap;
160
+ }
161
+
162
+ .quota-reset-summary {
163
+ display: inline-flex;
164
+ white-space: nowrap;
165
+ line-height: 1.2;
166
+ }
167
+
168
+ .action-label {
169
+ white-space: nowrap;
170
+ }
171
+
172
+ .app-shell {
173
+ height: calc(100vh - var(--app-header-height));
174
+ position: relative;
175
+ }
176
+
177
+ .app-main {
178
+ height: 100%;
179
+ padding-bottom: 5.8rem;
180
+ }
181
+
182
+ .bottom-nav {
183
+ position: fixed;
184
+ left: 50%;
185
+ bottom: max(0.85rem, env(safe-area-inset-bottom));
186
+ z-index: 45;
187
+ display: flex;
188
+ align-items: center;
189
+ justify-content: center;
190
+ gap: 0.18rem;
191
+ width: min(700px, calc(100vw - 1.5rem));
192
+ min-height: 52px;
193
+ padding: 0.28rem;
194
+ border: 1px solid var(--surface-nav-border);
195
+ border-radius: 16px;
196
+ background: var(--surface-nav);
197
+ box-shadow: var(--surface-nav-glow);
198
+ backdrop-filter: blur(22px) saturate(150%);
199
+ -webkit-backdrop-filter: blur(22px) saturate(150%);
200
+ transform: translateX(-50%);
201
+ }
202
+
203
+ .bottom-nav::before {
204
+ content: "";
205
+ position: absolute;
206
+ inset: 0;
207
+ z-index: -1;
208
+ border-radius: inherit;
209
+ background: rgba(255, 255, 255, 0.035);
210
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
211
+ }
212
+
213
+ .bottom-nav-item {
214
+ position: relative;
215
+ display: inline-flex;
216
+ align-items: center;
217
+ justify-content: center;
218
+ gap: 0.38rem;
219
+ min-width: 44px;
220
+ min-height: 42px;
221
+ padding: 0 0.68rem;
222
+ border: 1px solid transparent;
223
+ border-radius: 12px;
224
+ color: #9ca3af;
225
+ font-size: 0.78rem;
226
+ font-weight: 650;
227
+ transition: background 0.18s ease, color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
228
+ }
229
+
230
+ .bottom-nav-item::after {
231
+ content: "";
232
+ position: absolute;
233
+ left: 50%;
234
+ bottom: 0.32rem;
235
+ width: 1.15rem;
236
+ height: 2px;
237
+ border-radius: 999px;
238
+ background: var(--surface-nav-accent);
239
+ opacity: 0;
240
+ transform: translateX(-50%) scaleX(0.65);
241
+ transition: opacity 0.18s ease, transform 0.18s ease;
242
+ }
243
+
244
+ .bottom-nav-item:hover {
245
+ color: #f8fafc;
246
+ background: rgba(255, 255, 255, 0.07);
247
+ }
248
+
249
+ .bottom-nav-item.active {
250
+ color: white;
251
+ background: var(--surface-nav-active);
252
+ border-color: rgba(255, 255, 255, 0.12);
253
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.13), 0 8px 20px rgba(0, 0, 0, 0.14);
254
+ }
255
+
256
+ .bottom-nav-item.active::after {
257
+ opacity: 1;
258
+ transform: translateX(-50%) scaleX(1);
259
+ }
260
+
261
+ .bottom-nav-icon {
262
+ display: inline-flex;
263
+ align-items: center;
264
+ justify-content: center;
265
+ flex: 0 0 auto;
266
+ }
267
+
268
+ .bottom-nav-label {
269
+ display: none;
270
+ white-space: nowrap;
271
+ }
272
+
273
+ .bottom-nav-badge {
274
+ min-width: 1.4rem;
275
+ max-width: 3.4rem;
276
+ overflow: hidden;
277
+ text-overflow: ellipsis;
278
+ padding: 0.1rem 0.35rem;
279
+ border-radius: 999px;
280
+ border: 1px solid rgba(255, 255, 255, 0.08);
281
+ background: rgba(255, 255, 255, 0.08);
282
+ color: currentColor;
283
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
284
+ font-size: 0.65rem;
285
+ line-height: 1.1;
286
+ text-align: center;
287
+ }
288
+
289
+ .quick-test-meta {
290
+ display: flex;
291
+ flex-wrap: wrap;
292
+ align-items: center;
293
+ gap: 0.45rem;
294
+ min-height: 1.65rem;
295
+ margin-top: 0.75rem;
296
+ color: #9ca3af;
297
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
298
+ font-size: 0.72rem;
299
+ }
300
+
301
+ .quick-test-meta span:not(.quick-test-dot) {
302
+ display: inline-flex;
303
+ align-items: center;
304
+ min-height: 1.25rem;
305
+ padding: 0.12rem 0.45rem;
306
+ border-radius: 999px;
307
+ background: rgba(255, 255, 255, 0.04);
308
+ border: 1px solid rgba(255, 255, 255, 0.06);
309
+ }
310
+
311
+ .quick-test-dot {
312
+ width: 0.55rem;
313
+ height: 0.55rem;
314
+ border-radius: 999px;
315
+ background: #71717a;
316
+ }
317
+
318
+ .quick-test-dot.is-running {
319
+ background: var(--color-neon-cyan);
320
+ animation: pulse 1.15s ease-in-out infinite;
321
+ }
322
+
323
+ .quick-test-dot.is-success { background: var(--color-neon-green); }
324
+ .quick-test-dot.is-error { background: #ef4444; }
325
+
326
+ .logs-view {
327
+ height: 100%;
328
+ }
329
+
330
+ .logs-count-strip {
331
+ display: flex;
332
+ align-items: center;
333
+ gap: 0.5rem;
334
+ color: #9ca3af;
335
+ font-size: 0.72rem;
336
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
337
+ }
338
+
339
+ .logs-count-strip span,
340
+ .log-stream-status {
341
+ display: inline-flex;
342
+ align-items: center;
343
+ gap: 0.35rem;
344
+ min-height: 1.55rem;
345
+ padding: 0.15rem 0.55rem;
346
+ border: 1px solid rgba(255, 255, 255, 0.08);
347
+ border-radius: 999px;
348
+ background: rgba(255, 255, 255, 0.05);
349
+ }
350
+
351
+ .log-stream-status {
352
+ color: var(--color-neon-cyan);
353
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
354
+ font-size: 0.72rem;
355
+ font-weight: 650;
356
+ }
357
+
358
+ .log-stream-dot {
359
+ width: 0.45rem;
360
+ height: 0.45rem;
361
+ border-radius: 999px;
362
+ background: currentColor;
363
+ }
364
+
365
+ .log-stream-status.is-connected .log-stream-dot {
366
+ animation: pulse 1.4s ease-in-out infinite;
367
+ }
368
+
369
+ .log-stream-status.is-disconnected {
370
+ color: #eab308;
371
+ }
372
+
373
+ .logs-shell {
374
+ flex: 1 1 auto;
375
+ overflow: hidden;
376
+ }
377
+
378
+ .logs-toolbar {
379
+ display: grid;
380
+ grid-template-columns: minmax(220px, 1fr) auto auto;
381
+ align-items: center;
382
+ gap: 0.75rem;
383
+ padding: 0.85rem;
384
+ border-bottom: 1px solid rgba(42, 42, 62, 0.55);
385
+ background: rgba(15, 15, 26, 0.72);
386
+ }
387
+
388
+ .logs-search {
389
+ display: flex;
390
+ align-items: center;
391
+ gap: 0.45rem;
392
+ min-width: 0;
393
+ height: 34px;
394
+ padding: 0 0.65rem;
395
+ border: 1px solid var(--color-space-border);
396
+ border-radius: 8px;
397
+ color: #9ca3af;
398
+ background: rgba(10, 10, 15, 0.58);
399
+ }
400
+
401
+ .logs-search-input {
402
+ width: 100%;
403
+ min-width: 0;
404
+ border: 0;
405
+ outline: 0;
406
+ background: transparent;
407
+ color: #e5e7eb;
408
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
409
+ font-size: 0.76rem;
410
+ }
411
+
412
+ .logs-filter-row {
413
+ display: flex;
414
+ align-items: center;
415
+ gap: 0.35rem;
416
+ min-width: 0;
417
+ overflow-x: auto;
418
+ }
419
+
420
+ .logs-filter-chip {
421
+ display: inline-flex;
422
+ align-items: center;
423
+ gap: 0.35rem;
424
+ height: 30px;
425
+ padding: 0 0.55rem;
426
+ border: 1px solid rgba(255, 255, 255, 0.08);
427
+ border-radius: 999px;
428
+ color: #9ca3af;
429
+ cursor: pointer;
430
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
431
+ font-size: 0.68rem;
432
+ font-weight: 700;
433
+ opacity: 0.72;
434
+ user-select: none;
435
+ white-space: nowrap;
436
+ }
437
+
438
+ .logs-filter-chip input {
439
+ width: 0;
440
+ height: 0;
441
+ opacity: 0;
442
+ position: absolute;
443
+ }
444
+
445
+ .logs-filter-chip.active {
446
+ opacity: 1;
447
+ background: rgba(255, 255, 255, 0.07);
448
+ }
449
+
450
+ .logs-filter-chip.is-info.active { color: #60a5fa; border-color: rgba(96, 165, 250, 0.35); }
451
+ .logs-filter-chip.is-success.active { color: #34d399; border-color: rgba(52, 211, 153, 0.35); }
452
+ .logs-filter-chip.is-warn.active { color: #f59e0b; border-color: rgba(245, 158, 11, 0.35); }
453
+ .logs-filter-chip.is-error.active { color: #f87171; border-color: rgba(248, 113, 113, 0.35); }
454
+ .logs-filter-chip.is-debug.active { color: #c084fc; border-color: rgba(192, 132, 252, 0.35); }
455
+
456
+ .logs-filter-count {
457
+ min-width: 1.05rem;
458
+ text-align: center;
459
+ color: currentColor;
460
+ opacity: 0.72;
461
+ }
462
+
463
+ .logs-clear-button {
464
+ white-space: nowrap;
465
+ }
466
+
467
+ .logs-grid {
468
+ flex: 1 1 auto;
469
+ overflow: auto;
470
+ background: rgba(10, 10, 15, 0.9);
471
+ color: #d4d4d8;
472
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
473
+ font-size: 0.72rem;
474
+ }
475
+
476
+ .logs-grid-head,
477
+ .logs-row {
478
+ display: grid;
479
+ grid-template-columns: 6.5rem 5.6rem minmax(14rem, 1fr) minmax(13rem, 0.7fr);
480
+ gap: 0.75rem;
481
+ align-items: start;
482
+ }
483
+
484
+ .logs-grid-head {
485
+ position: sticky;
486
+ top: 0;
487
+ z-index: 1;
488
+ padding: 0.6rem 0.85rem;
489
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
490
+ background: rgba(15, 15, 26, 0.96);
491
+ color: #71717a;
492
+ font-size: 0.65rem;
493
+ font-weight: 800;
494
+ text-transform: uppercase;
495
+ }
496
+
497
+ .logs-row {
498
+ min-height: 34px;
499
+ padding: 0.48rem 0.85rem;
500
+ border-bottom: 1px solid rgba(255, 255, 255, 0.055);
501
+ }
502
+
503
+ .logs-row:hover {
504
+ background: rgba(255, 255, 255, 0.04);
505
+ }
506
+
507
+ .logs-time {
508
+ color: #71717a;
509
+ white-space: nowrap;
510
+ }
511
+
512
+ .logs-level {
513
+ display: inline-flex;
514
+ align-items: center;
515
+ justify-content: center;
516
+ width: max-content;
517
+ min-width: 4.6rem;
518
+ height: 1.35rem;
519
+ padding: 0 0.4rem;
520
+ border-radius: 5px;
521
+ border: 1px solid currentColor;
522
+ font-size: 0.64rem;
523
+ font-weight: 800;
524
+ line-height: 1;
525
+ }
526
+
527
+ .logs-row.is-info .logs-level { color: #60a5fa; background: rgba(96, 165, 250, 0.1); }
528
+ .logs-row.is-success .logs-level { color: #34d399; background: rgba(52, 211, 153, 0.1); }
529
+ .logs-row.is-warn .logs-level { color: #f59e0b; background: rgba(245, 158, 11, 0.1); }
530
+ .logs-row.is-error .logs-level { color: #f87171; background: rgba(248, 113, 113, 0.1); }
531
+ .logs-row.is-debug .logs-level { color: #c084fc; background: rgba(192, 132, 252, 0.1); }
532
+
533
+ .logs-message {
534
+ min-width: 0;
535
+ overflow-wrap: anywhere;
536
+ color: #e5e7eb;
537
+ }
538
+
539
+ .logs-details {
540
+ min-width: 0;
541
+ }
542
+
543
+ .logs-detail-list {
544
+ display: flex;
545
+ flex-wrap: wrap;
546
+ gap: 0.3rem;
547
+ }
548
+
549
+ .logs-detail-pill {
550
+ display: inline-flex;
551
+ align-items: center;
552
+ gap: 0.2rem;
553
+ max-width: 100%;
554
+ overflow: hidden;
555
+ text-overflow: ellipsis;
556
+ padding: 0.1rem 0.38rem;
557
+ border: 1px solid rgba(255, 255, 255, 0.08);
558
+ border-radius: 5px;
559
+ color: #a1a1aa;
560
+ background: rgba(255, 255, 255, 0.045);
561
+ white-space: nowrap;
562
+ }
563
+
564
+ .logs-detail-pill strong {
565
+ color: #d4d4d8;
566
+ font-weight: 700;
567
+ }
568
+
569
+ .logs-empty {
570
+ padding: 2rem;
571
+ color: #71717a;
572
+ text-align: center;
573
+ }
574
+
86
575
  .view-container {
87
576
  padding: 1.5rem;
88
577
  max-width: 1400px;
@@ -878,6 +1367,12 @@ table .btn-outline:hover {
878
1367
  --success: #1f8f4d;
879
1368
  --warning: #a56800;
880
1369
  --danger: #d70015;
1370
+ --app-header-height: 48px;
1371
+ --surface-nav: rgba(248, 249, 251, 0.86);
1372
+ --surface-nav-border: rgba(36, 41, 47, 0.12);
1373
+ --surface-nav-active: rgba(255, 255, 255, 0.9);
1374
+ --surface-nav-glow: 0 14px 32px rgba(31, 35, 40, 0.12);
1375
+ --surface-nav-accent: var(--accent);
881
1376
  }
882
1377
 
883
1378
  body {
@@ -969,21 +1464,24 @@ body::after {
969
1464
  }
970
1465
 
971
1466
  .h-14.border-b {
972
- height: 60px;
1467
+ height: var(--app-header-height);
1468
+ min-height: var(--app-header-height);
973
1469
  margin: 0;
974
1470
  border: 0;
975
1471
  border-bottom: 1px solid var(--glass-line);
976
1472
  border-radius: 0;
977
- background-color: var(--glass-toolbar);
978
- box-shadow: 0 1px 0 rgba(255, 255, 255, 0.72);
979
- backdrop-filter: blur(24px) saturate(160%);
980
- -webkit-backdrop-filter: blur(24px) saturate(160%);
1473
+ background-color: rgba(249, 250, 252, 0.9);
1474
+ box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7), 0 8px 24px rgba(31, 35, 40, 0.035);
1475
+ backdrop-filter: blur(20px) saturate(155%);
1476
+ -webkit-backdrop-filter: blur(20px) saturate(155%);
981
1477
  }
982
1478
 
983
- .h-14.border-b .w-8.h-8 {
1479
+ .h-14.border-b .app-brand-mark {
1480
+ width: 1.65rem;
1481
+ height: 1.65rem;
984
1482
  background-color: #1f2328;
985
1483
  background-image: none;
986
- border-radius: 8px;
1484
+ border-radius: 7px;
987
1485
  box-shadow: none;
988
1486
  color: white;
989
1487
  }
@@ -999,29 +1497,44 @@ body::after {
999
1497
 
1000
1498
  .app-brand-title {
1001
1499
  white-space: nowrap;
1500
+ font-size: 0.72rem;
1501
+ font-weight: 750;
1002
1502
  }
1003
1503
 
1004
1504
  .app-brand-meta {
1005
1505
  display: inline-flex;
1006
1506
  align-items: center;
1007
- height: 22px;
1008
- padding: 0 0.55rem;
1507
+ height: 18px;
1508
+ padding: 0 0.42rem;
1009
1509
  border: 1px solid var(--glass-line);
1010
- border-radius: 999px;
1011
- background-color: rgba(255, 255, 255, 0.64);
1510
+ border-radius: 6px;
1511
+ background-color: rgba(255, 255, 255, 0.58);
1012
1512
  color: var(--text-muted);
1513
+ font-size: 0.62rem;
1013
1514
  }
1014
1515
 
1015
1516
  .app-toolbar {
1016
- gap: 0.7rem;
1517
+ gap: 0.5rem;
1017
1518
  }
1018
1519
 
1019
1520
  .app-toolbar .btn-square {
1020
- width: 32px;
1021
- min-height: 32px;
1521
+ width: 28px;
1522
+ min-height: 28px;
1022
1523
  padding: 0;
1023
1524
  }
1024
1525
 
1526
+ .app-connection-status {
1527
+ min-height: 26px;
1528
+ padding: 0.18rem 0.55rem;
1529
+ border-radius: 7px;
1530
+ font-size: 0.68rem;
1531
+ }
1532
+
1533
+ .app-toolbar-divider {
1534
+ height: 14px;
1535
+ opacity: 0.72;
1536
+ }
1537
+
1025
1538
  .h-14.border-b a {
1026
1539
  color: var(--text-muted);
1027
1540
  }
@@ -1031,7 +1544,62 @@ body::after {
1031
1544
  }
1032
1545
 
1033
1546
  .h-\[calc\(100vh-56px\)\] {
1034
- height: calc(100vh - 60px);
1547
+ height: calc(100vh - var(--app-header-height));
1548
+ }
1549
+
1550
+ .app-shell {
1551
+ height: calc(100vh - var(--app-header-height));
1552
+ }
1553
+
1554
+ .bottom-nav {
1555
+ color: var(--text-body);
1556
+ box-shadow: var(--surface-nav-glow), inset 0 1px 0 rgba(255, 255, 255, 0.75);
1557
+ }
1558
+
1559
+ .bottom-nav::before {
1560
+ background: rgba(255, 255, 255, 0.36);
1561
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.62);
1562
+ }
1563
+
1564
+ .bottom-nav-item {
1565
+ color: var(--text-muted);
1566
+ }
1567
+
1568
+ .bottom-nav-item:hover {
1569
+ color: var(--text-strong);
1570
+ background: rgba(36, 41, 47, 0.045);
1571
+ }
1572
+
1573
+ .bottom-nav-item.active {
1574
+ color: var(--text-strong);
1575
+ border-color: rgba(36, 41, 47, 0.1);
1576
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.96), 0 3px 10px rgba(31, 35, 40, 0.08);
1577
+ }
1578
+
1579
+ .bottom-nav-item.active svg {
1580
+ color: var(--accent);
1581
+ }
1582
+
1583
+ .bottom-nav-badge,
1584
+ .quick-test-meta span:not(.quick-test-dot),
1585
+ .logs-count-strip span,
1586
+ .log-stream-status {
1587
+ border-color: var(--glass-line);
1588
+ background: rgba(255, 255, 255, 0.66);
1589
+ }
1590
+
1591
+ .bottom-nav-badge {
1592
+ color: var(--text-muted);
1593
+ }
1594
+
1595
+ .bottom-nav-item.active .bottom-nav-badge {
1596
+ color: var(--accent);
1597
+ border-color: rgba(10, 132, 255, 0.14);
1598
+ background: rgba(10, 132, 255, 0.06);
1599
+ }
1600
+
1601
+ .quick-test-meta {
1602
+ color: var(--text-muted);
1035
1603
  }
1036
1604
 
1037
1605
  .fixed.top-14.bottom-0.left-0 {
@@ -1246,6 +1814,11 @@ select:focus {
1246
1814
  transform: none;
1247
1815
  }
1248
1816
 
1817
+ .hover\:text-white:hover,
1818
+ .group:hover .group-hover\:text-white {
1819
+ color: var(--text-strong);
1820
+ }
1821
+
1249
1822
  .btn-outline,
1250
1823
  table .btn-outline {
1251
1824
  background-color: rgba(255, 255, 255, 0.58);
@@ -1402,6 +1975,72 @@ table .bg-gray-700,
1402
1975
  border: 1px solid var(--glass-line);
1403
1976
  }
1404
1977
 
1978
+ .logs-toolbar {
1979
+ background-color: rgba(255, 255, 255, 0.58);
1980
+ border-color: var(--glass-line);
1981
+ }
1982
+
1983
+ .logs-search {
1984
+ background-color: rgba(255, 255, 255, 0.78);
1985
+ border-color: var(--glass-line);
1986
+ color: var(--text-muted);
1987
+ }
1988
+
1989
+ .logs-search-input {
1990
+ color: var(--text-strong);
1991
+ }
1992
+
1993
+ .logs-filter-chip {
1994
+ border-color: var(--glass-line);
1995
+ color: var(--text-muted);
1996
+ background-color: rgba(255, 255, 255, 0.38);
1997
+ }
1998
+
1999
+ .logs-filter-chip.active {
2000
+ background-color: rgba(255, 255, 255, 0.72);
2001
+ }
2002
+
2003
+ .logs-grid {
2004
+ background-color: rgba(255, 255, 255, 0.5);
2005
+ color: var(--text-body);
2006
+ }
2007
+
2008
+ .logs-grid-head {
2009
+ background-color: rgba(248, 249, 251, 0.94);
2010
+ border-color: var(--glass-line);
2011
+ color: var(--text-faint);
2012
+ }
2013
+
2014
+ .logs-row {
2015
+ border-color: var(--glass-line);
2016
+ }
2017
+
2018
+ .logs-row:hover {
2019
+ background-color: rgba(36, 41, 47, 0.04);
2020
+ }
2021
+
2022
+ .logs-time {
2023
+ color: var(--text-faint);
2024
+ }
2025
+
2026
+ .logs-message {
2027
+ color: var(--text-body);
2028
+ }
2029
+
2030
+ .logs-detail-pill {
2031
+ background-color: rgba(255, 255, 255, 0.7);
2032
+ border-color: var(--glass-line);
2033
+ color: var(--text-muted);
2034
+ }
2035
+
2036
+ .logs-detail-pill strong {
2037
+ color: var(--text-strong);
2038
+ }
2039
+
2040
+ .logs-empty {
2041
+ color: var(--text-faint);
2042
+ }
2043
+
1405
2044
  .view-card .bg-space-800\/50.border {
1406
2045
  background-color: rgba(248, 249, 251, 0.78);
1407
2046
  }
@@ -1639,6 +2278,16 @@ dialog::backdrop,
1639
2278
  -webkit-backdrop-filter: blur(18px);
1640
2279
  }
1641
2280
 
2281
+ @media (min-width: 768px) {
2282
+ .bottom-nav-label {
2283
+ display: inline;
2284
+ }
2285
+
2286
+ .bottom-nav-item {
2287
+ flex: 1 1 0;
2288
+ }
2289
+ }
2290
+
1642
2291
  @media (min-width: 1024px) {
1643
2292
  .fixed.top-14.bottom-0.left-0 {
1644
2293
  position: static;
@@ -1665,9 +2314,84 @@ dialog::backdrop,
1665
2314
  .view-container {
1666
2315
  padding: 1.25rem;
1667
2316
  }
2317
+
2318
+ .section-header {
2319
+ gap: 0.75rem;
2320
+ }
2321
+
2322
+ .logs-toolbar {
2323
+ grid-template-columns: 1fr;
2324
+ }
2325
+
2326
+ .logs-filter-row {
2327
+ width: 100%;
2328
+ }
2329
+
2330
+ .logs-clear-button {
2331
+ width: max-content;
2332
+ }
2333
+
2334
+ .logs-grid-head,
2335
+ .logs-row {
2336
+ grid-template-columns: 5.5rem 5.2rem minmax(13rem, 1fr);
2337
+ }
2338
+
2339
+ .logs-grid-head span:nth-child(4),
2340
+ .logs-details {
2341
+ grid-column: 3;
2342
+ }
2343
+
2344
+ .logs-grid-head span:nth-child(4) {
2345
+ display: none;
2346
+ }
1668
2347
  }
1669
2348
 
1670
2349
  @media (max-width: 900px) {
2350
+ .section-header {
2351
+ flex-direction: column;
2352
+ align-items: stretch;
2353
+ }
2354
+
2355
+ .section-heading {
2356
+ gap: 0.65rem;
2357
+ }
2358
+
2359
+ .section-actions {
2360
+ width: 100%;
2361
+ }
2362
+
2363
+ .account-actions {
2364
+ display: flex;
2365
+ flex-wrap: nowrap;
2366
+ justify-content: flex-start;
2367
+ gap: 0.45rem;
2368
+ overflow: hidden;
2369
+ }
2370
+
2371
+ .account-actions .btn {
2372
+ flex: 0 0 32px;
2373
+ width: 32px;
2374
+ min-width: 32px;
2375
+ height: 32px;
2376
+ min-height: 32px;
2377
+ padding: 0;
2378
+ gap: 0;
2379
+ }
2380
+
2381
+ .account-actions .action-label {
2382
+ display: none;
2383
+ }
2384
+
2385
+ .metrics-range-controls {
2386
+ justify-content: flex-start;
2387
+ overflow-x: auto;
2388
+ }
2389
+
2390
+ .logs-count-strip {
2391
+ flex-wrap: nowrap;
2392
+ overflow-x: auto;
2393
+ }
2394
+
1671
2395
  .dashboard-test-grid {
1672
2396
  grid-template-columns: 1fr;
1673
2397
  }
@@ -1675,7 +2399,8 @@ dialog::backdrop,
1675
2399
 
1676
2400
  @media (max-width: 640px) {
1677
2401
  .h-14.border-b {
1678
- height: 58px;
2402
+ height: var(--app-header-height);
2403
+ min-height: var(--app-header-height);
1679
2404
  padding-left: 0.75rem;
1680
2405
  padding-right: 0.75rem;
1681
2406
  }
@@ -1685,9 +2410,9 @@ dialog::backdrop,
1685
2410
  gap: 0.55rem;
1686
2411
  }
1687
2412
 
1688
- .h-14.border-b .w-8.h-8 {
1689
- width: 1.75rem;
1690
- height: 1.75rem;
2413
+ .h-14.border-b .app-brand-mark {
2414
+ width: 1.55rem;
2415
+ height: 1.55rem;
1691
2416
  flex-shrink: 0;
1692
2417
  }
1693
2418
 
@@ -1715,15 +2440,52 @@ dialog::backdrop,
1715
2440
  display: none;
1716
2441
  }
1717
2442
 
1718
- .h-14.border-b .rounded-full.text-xs {
1719
- padding: 0.3rem 0.55rem;
1720
- font-size: 0.68rem;
2443
+ .h-14.border-b .app-connection-status {
2444
+ min-height: 24px;
2445
+ padding: 0.14rem 0.48rem;
2446
+ font-size: 0.66rem;
1721
2447
  }
1722
2448
 
1723
2449
  .view-container {
1724
2450
  padding: 1rem;
1725
2451
  }
1726
2452
 
2453
+ .section-heading > .rounded-full {
2454
+ display: none;
2455
+ }
2456
+
2457
+ .app-main {
2458
+ padding-bottom: 5.25rem;
2459
+ }
2460
+
2461
+ .bottom-nav {
2462
+ width: min(27rem, calc(100vw - 1rem));
2463
+ min-height: 52px;
2464
+ padding: 0.3rem;
2465
+ border-radius: 15px;
2466
+ }
2467
+
2468
+ .bottom-nav::before {
2469
+ border-radius: 16px;
2470
+ }
2471
+
2472
+ .bottom-nav-item {
2473
+ min-width: 0;
2474
+ flex: 1 1 0;
2475
+ padding: 0;
2476
+ border-radius: 10px;
2477
+ }
2478
+
2479
+ .bottom-nav-badge {
2480
+ position: absolute;
2481
+ top: 0.22rem;
2482
+ right: 0.18rem;
2483
+ min-width: 1rem;
2484
+ max-width: 1.55rem;
2485
+ padding: 0.05rem 0.18rem;
2486
+ font-size: 0.56rem;
2487
+ }
2488
+
1727
2489
  .view-container > .flex.items-center.justify-between.gap-4.mb-6 {
1728
2490
  flex-direction: column;
1729
2491
  }
@@ -1737,6 +2499,24 @@ dialog::backdrop,
1737
2499
  .view-card > .flex.gap-3 .btn {
1738
2500
  width: 100%;
1739
2501
  }
2502
+
2503
+ .logs-grid {
2504
+ font-size: 0.68rem;
2505
+ }
2506
+
2507
+ .logs-grid-head {
2508
+ display: none;
2509
+ }
2510
+
2511
+ .logs-row {
2512
+ grid-template-columns: 4.8rem 4.8rem minmax(0, 1fr);
2513
+ gap: 0.5rem;
2514
+ padding: 0.55rem 0.65rem;
2515
+ }
2516
+
2517
+ .logs-details {
2518
+ grid-column: 1 / -1;
2519
+ }
1740
2520
  }
1741
2521
 
1742
2522
  @media (prefers-reduced-motion: reduce) {