free-coding-models 0.5.28 → 0.5.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/free-coding-models.js +10 -2
- package/changelog/v0.5.29.md +19 -0
- package/changelog/v0.5.30.md +15 -0
- package/package.json +1 -1
- package/sources.js +3 -2
- package/src/core/config.js +1 -14
- package/src/core/endpoint-installer.js +5 -9
- package/src/core/legacy-proxy-cleanup.js +2 -0
- package/src/core/model-merger.js +4 -13
- package/src/core/playground.js +6 -4
- package/src/core/router-daemon.js +101 -43
- package/src/core/router-dashboard.js +63 -25
- package/src/core/shared-helpers.js +117 -0
- package/src/core/sync-set.js +11 -24
- package/src/core/tool-launchers.js +24 -92
- package/src/core/utils.js +26 -100
- package/src/tui/app.js +2 -2
- package/src/tui/command-palette.js +1 -0
- package/src/tui/key-handler.js +77 -20
- package/src/tui/render-table.js +3 -3
- package/web/dist/assets/index-CsFt3qt5.css +1 -0
- package/web/dist/assets/index-I6N91rH7.js +40 -0
- package/web/dist/favicon.ico +0 -0
- package/web/dist/favicons/apple-touch-icon.png +0 -0
- package/web/dist/favicons/favicon-16x16.png +0 -0
- package/web/dist/favicons/favicon-192x192.png +0 -0
- package/web/dist/favicons/favicon-32x32.png +0 -0
- package/web/dist/favicons/favicon-48x48.png +0 -0
- package/web/dist/favicons/favicon-512x512.png +0 -0
- package/web/dist/favicons/favicon-96x96.png +0 -0
- package/web/dist/favicons/favicon.ico +0 -0
- package/web/dist/favicons/mstile-150x150.png +0 -0
- package/web/dist/favicons/mstile-310x150.png +0 -0
- package/web/dist/favicons/mstile-310x310.png +0 -0
- package/web/dist/favicons/mstile-512x512.png +0 -0
- package/web/dist/favicons/mstile-70x70.png +0 -0
- package/web/dist/index.html +2 -2
- package/web/public/favicon.ico +0 -0
- package/web/public/favicons/apple-touch-icon.png +0 -0
- package/web/public/favicons/favicon-16x16.png +0 -0
- package/web/public/favicons/favicon-192x192.png +0 -0
- package/web/public/favicons/favicon-32x32.png +0 -0
- package/web/public/favicons/favicon-48x48.png +0 -0
- package/web/public/favicons/favicon-512x512.png +0 -0
- package/web/public/favicons/favicon-96x96.png +0 -0
- package/web/public/favicons/favicon.ico +0 -0
- package/web/public/favicons/mstile-150x150.png +0 -0
- package/web/public/favicons/mstile-310x150.png +0 -0
- package/web/public/favicons/mstile-310x310.png +0 -0
- package/web/public/favicons/mstile-512x512.png +0 -0
- package/web/public/favicons/mstile-70x70.png +0 -0
- package/web/server.js +34 -4
- package/web/src/components/dashboard/ExpandedDetailRow.jsx +10 -113
- package/web/src/components/dashboard/ExpandedDetailRow.module.css +9 -0
- package/web/src/components/playground/PlaygroundChat.jsx +527 -0
- package/web/src/components/playground/PlaygroundChat.module.css +382 -0
- package/web/src/components/playground/PlaygroundView.jsx +104 -442
- package/web/src/components/playground/PlaygroundView.module.css +10 -0
- package/web/src/components/router/RouterView.jsx +268 -56
- package/web/src/components/router/RouterView.module.css +416 -1
- package/src/core/product-flags.js +0 -9
- package/web/dist/assets/index-BRFowJv5.css +0 -1
- package/web/dist/assets/index-Pr3waI0-.js +0 -41
|
@@ -140,6 +140,13 @@
|
|
|
140
140
|
&:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
/* 📖 Bigger start button for the stopped state — more prominent CTA. */
|
|
144
|
+
.startBtnBig {
|
|
145
|
+
padding: 10px 24px;
|
|
146
|
+
font-size: 15px;
|
|
147
|
+
border-radius: 10px;
|
|
148
|
+
}
|
|
149
|
+
|
|
143
150
|
.stopBtn {
|
|
144
151
|
display: flex;
|
|
145
152
|
align-items: center;
|
|
@@ -175,6 +182,33 @@
|
|
|
175
182
|
margin-bottom: 16px;
|
|
176
183
|
}
|
|
177
184
|
|
|
185
|
+
/* 📖 Hero glow when running — makes the quick setup card visually prominent. */
|
|
186
|
+
.quickSetupHero {
|
|
187
|
+
border: 1px solid rgba(0, 200, 100, 0.25);
|
|
188
|
+
box-shadow: 0 0 16px rgba(0, 200, 100, 0.08);
|
|
189
|
+
border-radius: 10px;
|
|
190
|
+
padding: 12px;
|
|
191
|
+
background: linear-gradient(135deg, rgba(0, 200, 100, 0.05), transparent);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* 📖 "Copy all" button — sits at the right of the Quick Setup title. */
|
|
195
|
+
.copyAllBtn {
|
|
196
|
+
display: inline-flex;
|
|
197
|
+
align-items: center;
|
|
198
|
+
gap: 4px;
|
|
199
|
+
margin-left: auto;
|
|
200
|
+
padding: 3px 10px;
|
|
201
|
+
background: var(--bg-secondary, #14141f);
|
|
202
|
+
border: 1px solid var(--border, #1e1e2e);
|
|
203
|
+
border-radius: 6px;
|
|
204
|
+
color: var(--text-secondary, #aaa);
|
|
205
|
+
font-size: 11px;
|
|
206
|
+
font-weight: 500;
|
|
207
|
+
cursor: pointer;
|
|
208
|
+
font-family: inherit;
|
|
209
|
+
&:hover { color: var(--text-primary, #e0e0e0); border-color: var(--accent, #00c864); }
|
|
210
|
+
}
|
|
211
|
+
|
|
178
212
|
.sectionTitle {
|
|
179
213
|
display: flex;
|
|
180
214
|
align-items: center;
|
|
@@ -351,6 +385,16 @@
|
|
|
351
385
|
text-transform: uppercase;
|
|
352
386
|
}
|
|
353
387
|
|
|
388
|
+
.logEmpty {
|
|
389
|
+
padding: 16px;
|
|
390
|
+
text-align: center;
|
|
391
|
+
color: var(--text-muted, #888);
|
|
392
|
+
font-size: 12px;
|
|
393
|
+
background: var(--bg-secondary, #14141f);
|
|
394
|
+
border: 1px dashed var(--border, #1e1e2e);
|
|
395
|
+
border-radius: 8px;
|
|
396
|
+
}
|
|
397
|
+
|
|
354
398
|
@keyframes fadeIn {
|
|
355
399
|
from { opacity: 0; }
|
|
356
400
|
to { opacity: 1; }
|
|
@@ -421,7 +465,7 @@
|
|
|
421
465
|
}
|
|
422
466
|
|
|
423
467
|
.setEmpty {
|
|
424
|
-
padding: 16px;
|
|
468
|
+
padding: 20px 16px;
|
|
425
469
|
text-align: center;
|
|
426
470
|
color: var(--text-muted, #888);
|
|
427
471
|
font-size: 12px;
|
|
@@ -430,6 +474,23 @@
|
|
|
430
474
|
border-radius: 8px;
|
|
431
475
|
}
|
|
432
476
|
|
|
477
|
+
.setEmptyTitle {
|
|
478
|
+
font-size: 13px;
|
|
479
|
+
font-weight: 600;
|
|
480
|
+
color: var(--text-secondary, #aaa);
|
|
481
|
+
margin-bottom: 4px;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.setEmptyHint {
|
|
485
|
+
font-size: 11px;
|
|
486
|
+
color: var(--text-muted, #888);
|
|
487
|
+
line-height: 1.5;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.setEmptyHint strong {
|
|
491
|
+
color: var(--text-secondary, #aaa);
|
|
492
|
+
}
|
|
493
|
+
|
|
433
494
|
.setRow {
|
|
434
495
|
display: flex;
|
|
435
496
|
align-items: center;
|
|
@@ -510,6 +571,79 @@
|
|
|
510
571
|
text-transform: uppercase;
|
|
511
572
|
}
|
|
512
573
|
|
|
574
|
+
/* 📖 Priority badge variants — make the fallback chain semantics explicit
|
|
575
|
+
(issue #120). Primary gets the accent color so users instantly see which
|
|
576
|
+
model serves every request; fallbacks stay muted. */
|
|
577
|
+
.setPriorityPrimary {
|
|
578
|
+
min-width: 52px;
|
|
579
|
+
padding: 2px 8px;
|
|
580
|
+
border-radius: 4px;
|
|
581
|
+
background: rgba(0, 200, 100, 0.14);
|
|
582
|
+
color: var(--accent, #00c864);
|
|
583
|
+
border: 1px solid rgba(0, 200, 100, 0.3);
|
|
584
|
+
text-transform: uppercase;
|
|
585
|
+
letter-spacing: 0.3px;
|
|
586
|
+
text-align: center;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.setPriorityFallback {
|
|
590
|
+
text-transform: none;
|
|
591
|
+
opacity: 0.85;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/* 📖 Next-to-serve row — subtle accent left border + tint so the user can
|
|
595
|
+
see at a glance which model will handle the next chat completion.
|
|
596
|
+
Only applied when the daemon is running and routingOrder is known. */
|
|
597
|
+
.setRowNext {
|
|
598
|
+
background: linear-gradient(90deg, rgba(0, 200, 100, 0.07), transparent 60%);
|
|
599
|
+
border-left: 2px solid var(--accent, #00c864);
|
|
600
|
+
padding-left: 8px;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/* 📖 Priority legend — one-line explainer above the set list. */
|
|
604
|
+
.priorityLegend {
|
|
605
|
+
display: flex;
|
|
606
|
+
align-items: center;
|
|
607
|
+
gap: 8px;
|
|
608
|
+
flex-wrap: wrap;
|
|
609
|
+
padding: 6px 10px;
|
|
610
|
+
margin-bottom: 8px;
|
|
611
|
+
font-size: 11px;
|
|
612
|
+
color: var(--text-muted, #888);
|
|
613
|
+
background: var(--bg-secondary, #14141f);
|
|
614
|
+
border: 1px solid var(--border, #1e1e2e);
|
|
615
|
+
border-radius: 6px;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.legendPrimary {
|
|
619
|
+
display: inline-flex;
|
|
620
|
+
align-items: center;
|
|
621
|
+
gap: 3px;
|
|
622
|
+
font-weight: 600;
|
|
623
|
+
color: var(--accent, #00c864);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
.legendFallback {
|
|
627
|
+
font-weight: 600;
|
|
628
|
+
color: var(--text-secondary, #aaa);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.legendSeparator {
|
|
632
|
+
color: var(--text-muted, #888);
|
|
633
|
+
opacity: 0.7;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
.legendNext {
|
|
637
|
+
margin-left: auto;
|
|
638
|
+
color: var(--text-secondary, #aaa);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.legendNext code {
|
|
642
|
+
color: var(--accent, #00c864);
|
|
643
|
+
font-family: 'SF Mono', monospace;
|
|
644
|
+
font-size: 10px;
|
|
645
|
+
}
|
|
646
|
+
|
|
513
647
|
.setRowBtns {
|
|
514
648
|
display: flex;
|
|
515
649
|
gap: 2px;
|
|
@@ -710,3 +844,284 @@
|
|
|
710
844
|
flex-shrink: 0;
|
|
711
845
|
}
|
|
712
846
|
|
|
847
|
+
/* ════════════════════════════════════════════════════════════════════════
|
|
848
|
+
📖 Probe-all button + progress bar (AI Latency benchmarks on the set).
|
|
849
|
+
════════════════════════════════════════════════════════════════════════ */
|
|
850
|
+
|
|
851
|
+
/* 📖 Active state for the Probe button while benchmarks run. */
|
|
852
|
+
.probeBtnActive {
|
|
853
|
+
border-color: var(--accent, #00c864);
|
|
854
|
+
color: var(--accent, #00c864);
|
|
855
|
+
cursor: progress;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/* 📖 Progress card shown below the set actions while probing. */
|
|
859
|
+
.probeProgress {
|
|
860
|
+
display: flex;
|
|
861
|
+
flex-direction: column;
|
|
862
|
+
gap: 6px;
|
|
863
|
+
padding: 8px 10px;
|
|
864
|
+
margin-bottom: 8px;
|
|
865
|
+
background: var(--bg-secondary, #14141f);
|
|
866
|
+
border: 1px solid rgba(0, 200, 100, 0.2);
|
|
867
|
+
border-radius: 6px;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
.probeProgressLabel {
|
|
871
|
+
display: flex;
|
|
872
|
+
align-items: center;
|
|
873
|
+
gap: 5px;
|
|
874
|
+
font-size: 11px;
|
|
875
|
+
color: var(--accent, #00c864);
|
|
876
|
+
font-weight: 600;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
.probeProgressCount {
|
|
880
|
+
margin-left: auto;
|
|
881
|
+
color: var(--text-secondary, #aaa);
|
|
882
|
+
font-weight: 500;
|
|
883
|
+
font-family: 'SF Mono', monospace;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.probeProgressBar {
|
|
887
|
+
height: 4px;
|
|
888
|
+
background: var(--bg-primary, #0f0f17);
|
|
889
|
+
border-radius: 2px;
|
|
890
|
+
overflow: hidden;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
.probeProgressFill {
|
|
894
|
+
height: 100%;
|
|
895
|
+
background: linear-gradient(90deg, var(--accent, #00c864), rgba(0, 200, 100, 0.6));
|
|
896
|
+
border-radius: 2px;
|
|
897
|
+
transition: width 0.4s ease;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/* ════════════════════════════════════════════════════════════════════════
|
|
901
|
+
📖 AI Latency cell in each set row — populated by Probe all.
|
|
902
|
+
════════════════════════════════════════════════════════════════════════ */
|
|
903
|
+
|
|
904
|
+
.aiLatencyCell {
|
|
905
|
+
display: inline-flex;
|
|
906
|
+
align-items: center;
|
|
907
|
+
gap: 4px;
|
|
908
|
+
min-width: 78px;
|
|
909
|
+
font-size: 10px;
|
|
910
|
+
font-family: 'SF Mono', monospace;
|
|
911
|
+
justify-content: flex-end;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.aiLatencyMs {
|
|
915
|
+
font-weight: 700;
|
|
916
|
+
color: #b400ff;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
.aiLatencyTps {
|
|
920
|
+
color: var(--text-muted, #888);
|
|
921
|
+
font-size: 9px;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
.aiLatencySpin {
|
|
925
|
+
color: var(--accent, #00c864);
|
|
926
|
+
letter-spacing: 2px;
|
|
927
|
+
animation: probeSpin 0.8s steps(3, end) infinite;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
@keyframes probeSpin {
|
|
931
|
+
0% { opacity: 0.3; }
|
|
932
|
+
50% { opacity: 1; }
|
|
933
|
+
100% { opacity: 0.3; }
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
.aiLatencyErr {
|
|
937
|
+
color: var(--error, #ff5a5a);
|
|
938
|
+
font-size: 10px;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
.aiLatencyNone {
|
|
942
|
+
color: var(--text-muted, #888);
|
|
943
|
+
opacity: 0.4;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/* ════════════════════════════════════════════════════════════════════════
|
|
947
|
+
📖 Mini Playground — live router test inside the Router view.
|
|
948
|
+
════════════════════════════════════════════════════════════════════════ */
|
|
949
|
+
|
|
950
|
+
.miniPgHint {
|
|
951
|
+
margin-left: auto;
|
|
952
|
+
font-size: 10px;
|
|
953
|
+
font-weight: 400;
|
|
954
|
+
color: var(--text-muted, #888);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
.miniPgHint code {
|
|
958
|
+
color: var(--accent, #00c864);
|
|
959
|
+
font-family: 'SF Mono', monospace;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
.miniPg {
|
|
963
|
+
max-height: 220px;
|
|
964
|
+
overflow-y: auto;
|
|
965
|
+
padding: 8px;
|
|
966
|
+
margin-bottom: 8px;
|
|
967
|
+
background: var(--bg-primary, #0f0f17);
|
|
968
|
+
border: 1px solid var(--border, #1e1e2e);
|
|
969
|
+
border-radius: 8px;
|
|
970
|
+
display: flex;
|
|
971
|
+
flex-direction: column;
|
|
972
|
+
gap: 8px;
|
|
973
|
+
scroll-behavior: smooth;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.miniPgEmpty {
|
|
977
|
+
text-align: center;
|
|
978
|
+
color: var(--text-muted, #888);
|
|
979
|
+
font-size: 11px;
|
|
980
|
+
padding: 18px 8px;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
.miniPgMsg {
|
|
984
|
+
display: flex;
|
|
985
|
+
flex-direction: column;
|
|
986
|
+
gap: 3px;
|
|
987
|
+
max-width: 88%;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
.miniPgUser {
|
|
991
|
+
align-self: flex-end;
|
|
992
|
+
align-items: flex-end;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
.miniPgAssistant {
|
|
996
|
+
align-self: flex-start;
|
|
997
|
+
align-items: flex-start;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.miniPgBubble {
|
|
1001
|
+
padding: 7px 11px;
|
|
1002
|
+
border-radius: 12px;
|
|
1003
|
+
font-size: 12px;
|
|
1004
|
+
line-height: 1.5;
|
|
1005
|
+
white-space: pre-wrap;
|
|
1006
|
+
word-break: break-word;
|
|
1007
|
+
color: var(--text-primary, #e0e0e0);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
.miniPgUser .miniPgBubble {
|
|
1011
|
+
background: rgba(0, 200, 100, 0.12);
|
|
1012
|
+
border: 1px solid rgba(0, 200, 100, 0.2);
|
|
1013
|
+
border-bottom-right-radius: 4px;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
.miniPgAssistant .miniPgBubble {
|
|
1017
|
+
background: var(--bg-secondary, #14141f);
|
|
1018
|
+
border: 1px solid var(--border, #1e1e2e);
|
|
1019
|
+
border-bottom-left-radius: 4px;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
.miniPgTyping {
|
|
1023
|
+
color: var(--accent, #00c864);
|
|
1024
|
+
letter-spacing: 3px;
|
|
1025
|
+
animation: probeSpin 0.9s steps(3, end) infinite;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
.miniPgError {
|
|
1029
|
+
display: block;
|
|
1030
|
+
margin-top: 4px;
|
|
1031
|
+
color: var(--error, #ff5a5a);
|
|
1032
|
+
font-size: 11px;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
.miniPgAborted {
|
|
1036
|
+
display: block;
|
|
1037
|
+
margin-top: 4px;
|
|
1038
|
+
color: var(--text-muted, #888);
|
|
1039
|
+
font-size: 10px;
|
|
1040
|
+
font-style: italic;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/* 📖 Target badge under each user bubble — shows the Primary model the
|
|
1044
|
+
router will try first for this message (priority-first routing, #120).
|
|
1045
|
+
If failover kicks in, the reply's .miniPgRouted badge shows a different
|
|
1046
|
+
model, making the fallback chain visible at a glance. */
|
|
1047
|
+
.miniPgTarget {
|
|
1048
|
+
font-size: 10px;
|
|
1049
|
+
color: var(--text-muted, #888);
|
|
1050
|
+
font-family: 'SF Mono', monospace;
|
|
1051
|
+
padding: 0 4px;
|
|
1052
|
+
display: inline-flex;
|
|
1053
|
+
align-items: center;
|
|
1054
|
+
gap: 3px;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
.miniPgTarget svg {
|
|
1058
|
+
color: var(--accent, #00c864);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/* 📖 Routed-via badge under each assistant reply — shows WHICH model the
|
|
1062
|
+
priority-first router actually picked for this message (issue #120). */
|
|
1063
|
+
.miniPgRouted {
|
|
1064
|
+
font-size: 10px;
|
|
1065
|
+
color: var(--text-muted, #888);
|
|
1066
|
+
font-family: 'SF Mono', monospace;
|
|
1067
|
+
padding: 0 4px;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.miniPgRouted span {
|
|
1071
|
+
color: var(--accent, #00c864);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
.miniPgInputRow {
|
|
1075
|
+
display: flex;
|
|
1076
|
+
gap: 6px;
|
|
1077
|
+
align-items: stretch;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
.miniPgInput {
|
|
1081
|
+
flex: 1;
|
|
1082
|
+
padding: 8px 12px;
|
|
1083
|
+
background: var(--bg-primary, #0f0f17);
|
|
1084
|
+
border: 1px solid var(--border, #1e1e2e);
|
|
1085
|
+
border-radius: 8px;
|
|
1086
|
+
color: var(--text-primary, #e0e0e0);
|
|
1087
|
+
font-size: 12px;
|
|
1088
|
+
font-family: inherit;
|
|
1089
|
+
outline: none;
|
|
1090
|
+
transition: border-color 0.15s;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
.miniPgInput:focus {
|
|
1094
|
+
border-color: var(--accent, #00c864);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
.miniPgInput::placeholder {
|
|
1098
|
+
color: var(--text-muted, #888);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
.miniPgSendBtn,
|
|
1102
|
+
.miniPgStopBtn {
|
|
1103
|
+
display: flex;
|
|
1104
|
+
align-items: center;
|
|
1105
|
+
justify-content: center;
|
|
1106
|
+
width: 38px;
|
|
1107
|
+
border: none;
|
|
1108
|
+
border-radius: 8px;
|
|
1109
|
+
cursor: pointer;
|
|
1110
|
+
transition: opacity 0.15s, background 0.15s;
|
|
1111
|
+
flex-shrink: 0;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
.miniPgSendBtn {
|
|
1115
|
+
background: var(--accent, #00c864);
|
|
1116
|
+
color: #000;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
.miniPgSendBtn:disabled {
|
|
1120
|
+
opacity: 0.4;
|
|
1121
|
+
cursor: not-allowed;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
.miniPgStopBtn {
|
|
1125
|
+
background: var(--error, #ff5a5a);
|
|
1126
|
+
color: #fff;
|
|
1127
|
+
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file src/product-flags.js
|
|
3
|
-
* @description Product-level flags and feature gates.
|
|
4
|
-
*
|
|
5
|
-
* @details
|
|
6
|
-
* 📖 Previously held PROXY_DISABLED_NOTICE for the proxy bridge rebuild.
|
|
7
|
-
* 📖 That notice was removed in 0.3.22 after the proxy surface was fully
|
|
8
|
-
* 📖 retired. File kept as a home for future product-level flags.
|
|
9
|
-
*/
|