aegis-desktop 1.0.10 → 1.0.13
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/lib/auto.js +11 -7
- package/lib/fingerprint.js +76 -17
- package/lib/google-connect.js +171 -0
- package/lib/local/claude-pro.js +134 -11
- package/lib/local/engine.js +111 -26
- package/lib/local/prompt.js +67 -37
- package/lib/local/tools.js +49 -13
- package/lib/settings.js +65 -24
- package/main.js +270 -36
- package/package.json +5 -2
- package/preload.js +45 -12
- package/renderer/app.js +691 -22
- package/renderer/budget.js +18 -9
- package/renderer/companion.js +225 -0
- package/renderer/fingerprint.css +16 -0
- package/renderer/fingerprint.js +136 -2
- package/renderer/index.html +302 -121
- package/renderer/provider-toolbar.js +136 -0
- package/renderer/providers.js +261 -0
- package/renderer/style.css +547 -171
- package/vendor/aegis.js +169 -3
- package/vendor/credentials.js +9 -2
- package/vendor/drive-connect.js +87 -0
- package/vendor/drive-upload.js +176 -0
- package/vendor/google-signin.js +127 -0
- package/vendor/record-vault.js +431 -113
- package/vendor/update.js +366 -8
package/renderer/style.css
CHANGED
|
@@ -6,14 +6,26 @@
|
|
|
6
6
|
* corresponding source under this licence (§5/§13) — see LICENSING.md.
|
|
7
7
|
*/
|
|
8
8
|
:root {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
/* Surface ramp: four neutral-cool steps, farthest-back to nearest-front.
|
|
10
|
+
The rule this stylesheet now follows is that no selector picks a grey of
|
|
11
|
+
its own — "a bit lighter than the page" is --surface, never #151a22. That
|
|
12
|
+
is what stops forty near-identical darks accumulating, each one a slightly
|
|
13
|
+
different hue depending on the year it was written, and it is why the
|
|
14
|
+
values below are a ramp rather than five unrelated colours.
|
|
15
|
+
|
|
16
|
+
--bg the page
|
|
17
|
+
--surface a rail resting ON the page: sidebar, topbar
|
|
18
|
+
--surface2 an object ON a rail: composer, lane cards, chips
|
|
19
|
+
--surface3 that object, hovered or pressed */
|
|
20
|
+
--bg: #0b0d11;
|
|
21
|
+
--surface: #10131a;
|
|
22
|
+
--surface2: #171b23;
|
|
23
|
+
--surface3: #1f242e;
|
|
24
|
+
--border: #232934; /* hairline — used once per edge, never doubled */
|
|
25
|
+
--border2: #333b49; /* the same line lifted: hover, focus, emphasis */
|
|
26
|
+
--text: #dbe3ee;
|
|
27
|
+
--text2: #94a2b6;
|
|
28
|
+
--text3: #4c586a;
|
|
17
29
|
--teal: #00e5c0;
|
|
18
30
|
--purple: #6b8fd4;
|
|
19
31
|
--green: #00ff88;
|
|
@@ -27,6 +39,47 @@
|
|
|
27
39
|
--user: var(--purple);
|
|
28
40
|
--assistant: var(--surface2);
|
|
29
41
|
|
|
42
|
+
/* One radius scale, three steps plus pills. 6px is inline (a chip, a key, a
|
|
43
|
+
small button), 10px is a sitting object (a card, a lane card), 14px is a
|
|
44
|
+
large surface (the composer). The ad-hoc 3/4/8/9/12/16/18px values that
|
|
45
|
+
used to be scattered here rounded to the nearest step: one at a time the
|
|
46
|
+
spread was invisible, all together it read as impatient. */
|
|
47
|
+
--r-sm: 6px;
|
|
48
|
+
--r-md: 10px;
|
|
49
|
+
--r-lg: 14px;
|
|
50
|
+
--r-pill: 999px;
|
|
51
|
+
|
|
52
|
+
/* The reading column: ~72 characters of Ubuntu at 15px. One number governs
|
|
53
|
+
the transcript's prose AND the composer's width, so the input sits exactly
|
|
54
|
+
under the column of text it produces — if these drifted apart the window
|
|
55
|
+
would look assembled from two different grids.
|
|
56
|
+
|
|
57
|
+
Deliberately px, not ch. `ch` resolves against the font-size of whichever
|
|
58
|
+
element uses it, and the transcript sets 14px on `.messages` while the
|
|
59
|
+
composer inherits 14px from <body> and 15px inside the textarea — so the
|
|
60
|
+
same `72ch` would have produced three different widths for the two things
|
|
61
|
+
that must line up. A fixed length is the only spelling that agrees with
|
|
62
|
+
itself in both places. */
|
|
63
|
+
--measure: 640px;
|
|
64
|
+
|
|
65
|
+
/* Spacing, in 4px steps. Named only where a value repeats across sections. */
|
|
66
|
+
--s-1: 4px;
|
|
67
|
+
--s-2: 8px;
|
|
68
|
+
--s-3: 12px;
|
|
69
|
+
--s-4: 16px;
|
|
70
|
+
|
|
71
|
+
/* Two shadows: resting, and lifted. A wide translucent blur reads as depth;
|
|
72
|
+
a tight opaque offset reads as a sticker. */
|
|
73
|
+
--shadow-1: 0 1px 2px rgba(0, 0, 0, 0.28);
|
|
74
|
+
--shadow-2: 0 12px 32px -18px rgba(0, 0, 0, 0.9);
|
|
75
|
+
|
|
76
|
+
/* The accent at the three opacities this sheet actually uses. Naming them
|
|
77
|
+
keeps "teal at 0.35" from being retyped as rgba(0,229,192,.35) eight
|
|
78
|
+
times, which is what made a colour tweak a find-and-replace. */
|
|
79
|
+
--accent-soft: var(--accent-soft);
|
|
80
|
+
--accent-mid: var(--accent-mid);
|
|
81
|
+
--accent-edge: var(--accent-edge);
|
|
82
|
+
|
|
30
83
|
/* Deterministic stacks. All three named families are vendored in
|
|
31
84
|
renderer/fonts/ (see fonts/NOTICE.md), so they resolve to the same bytes on
|
|
32
85
|
every platform and with the network down — the desktop counterpart of the
|
|
@@ -148,7 +201,7 @@ body {
|
|
|
148
201
|
max-width: 40ch;
|
|
149
202
|
padding: 2px 8px;
|
|
150
203
|
border: 1px solid var(--border);
|
|
151
|
-
border-radius:
|
|
204
|
+
border-radius: var(--r-pill);
|
|
152
205
|
}
|
|
153
206
|
|
|
154
207
|
.session-meter[hidden] {
|
|
@@ -195,7 +248,7 @@ body {
|
|
|
195
248
|
.slider {
|
|
196
249
|
position: absolute;
|
|
197
250
|
inset: 0;
|
|
198
|
-
border-radius:
|
|
251
|
+
border-radius: var(--r-lg);
|
|
199
252
|
background: var(--border);
|
|
200
253
|
transition: 0.15s;
|
|
201
254
|
cursor: pointer;
|
|
@@ -248,20 +301,45 @@ main {
|
|
|
248
301
|
background: var(--bg);
|
|
249
302
|
}
|
|
250
303
|
|
|
304
|
+
/* NO BOXES.
|
|
305
|
+
A card used to be a filled, bordered, rounded rectangle — nine of them down
|
|
306
|
+
the sidebar, each with its own frame, which made a single scrolling column
|
|
307
|
+
read as a page of unrelated widgets and spent the eye's attention on borders
|
|
308
|
+
that carry no information. The sidebar is one continuous surface now: only a
|
|
309
|
+
hairline between sections, and the heading set as a quiet label rather than
|
|
310
|
+
a panel title.
|
|
311
|
+
|
|
312
|
+
The `.card` class itself stays in the markup, and that is deliberate: it is a
|
|
313
|
+
layout hook, not a decoration. `revealSidebarCard()` in app.js resolves
|
|
314
|
+
`node.closest('section.card')` to find the section it must scroll to when the
|
|
315
|
+
welcome panel sends the user to the key field, and
|
|
316
|
+
desktop/test/renderer-model-key-focus.test.mjs mirrors that selector. Deleting
|
|
317
|
+
the class from the template would silently break that jump; deleting the
|
|
318
|
+
fill, border and radius from the rule does not. */
|
|
251
319
|
.card {
|
|
252
|
-
background:
|
|
253
|
-
border:
|
|
254
|
-
border-radius:
|
|
255
|
-
padding:
|
|
320
|
+
background: none;
|
|
321
|
+
border: 0;
|
|
322
|
+
border-radius: 0;
|
|
323
|
+
padding: 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* The divider replaces the box. It is on the section, not a wrapper, so a
|
|
327
|
+
hidden section (the companion card before it has anything true to say) never
|
|
328
|
+
leaves a floating rule behind. */
|
|
329
|
+
.side .card + .card {
|
|
330
|
+
border-top: 1px solid var(--border);
|
|
331
|
+
padding-top: 12px;
|
|
256
332
|
}
|
|
257
333
|
|
|
258
334
|
.card h2 {
|
|
259
|
-
font-size:
|
|
335
|
+
font-size: 11px;
|
|
260
336
|
text-transform: uppercase;
|
|
261
|
-
letter-spacing: 0.
|
|
337
|
+
letter-spacing: 0.08em;
|
|
262
338
|
color: var(--text2);
|
|
263
339
|
margin: 0 0 8px;
|
|
264
340
|
font-family: var(--font-display);
|
|
341
|
+
font-weight: 600;
|
|
342
|
+
opacity: 0.75;
|
|
265
343
|
}
|
|
266
344
|
|
|
267
345
|
.card dl {
|
|
@@ -288,7 +366,7 @@ select {
|
|
|
288
366
|
background: var(--surface);
|
|
289
367
|
color: var(--text);
|
|
290
368
|
border: 1px solid var(--border);
|
|
291
|
-
border-radius:
|
|
369
|
+
border-radius: var(--r-sm);
|
|
292
370
|
padding: 6px;
|
|
293
371
|
font-family: var(--font-display);
|
|
294
372
|
}
|
|
@@ -321,7 +399,7 @@ select:disabled {
|
|
|
321
399
|
background: var(--surface);
|
|
322
400
|
color: var(--text);
|
|
323
401
|
border: 1px solid var(--border);
|
|
324
|
-
border-radius:
|
|
402
|
+
border-radius: var(--r-sm);
|
|
325
403
|
padding: 5px 8px;
|
|
326
404
|
font: inherit;
|
|
327
405
|
font-size: 12px;
|
|
@@ -352,7 +430,7 @@ select:disabled {
|
|
|
352
430
|
background: var(--surface);
|
|
353
431
|
color: var(--text);
|
|
354
432
|
border: 1px solid var(--border);
|
|
355
|
-
border-radius:
|
|
433
|
+
border-radius: var(--r-sm);
|
|
356
434
|
padding: 4px 6px;
|
|
357
435
|
font: inherit;
|
|
358
436
|
font-size: 12px;
|
|
@@ -380,7 +458,7 @@ select:disabled {
|
|
|
380
458
|
background: var(--surface);
|
|
381
459
|
color: var(--text);
|
|
382
460
|
border: 1px solid var(--border);
|
|
383
|
-
border-radius:
|
|
461
|
+
border-radius: var(--r-sm);
|
|
384
462
|
padding: 6px 8px;
|
|
385
463
|
font: inherit;
|
|
386
464
|
}
|
|
@@ -392,7 +470,7 @@ select:disabled {
|
|
|
392
470
|
|
|
393
471
|
.memory-search button {
|
|
394
472
|
border: none;
|
|
395
|
-
border-radius:
|
|
473
|
+
border-radius: var(--r-sm);
|
|
396
474
|
background: var(--surface2);
|
|
397
475
|
color: var(--text);
|
|
398
476
|
border: 1px solid var(--border);
|
|
@@ -420,7 +498,7 @@ select:disabled {
|
|
|
420
498
|
.memory-results li {
|
|
421
499
|
font-size: 12px;
|
|
422
500
|
border: 1px solid var(--border);
|
|
423
|
-
border-radius:
|
|
501
|
+
border-radius: var(--r-sm);
|
|
424
502
|
padding: 6px 8px;
|
|
425
503
|
word-break: break-word;
|
|
426
504
|
}
|
|
@@ -490,7 +568,7 @@ select:disabled {
|
|
|
490
568
|
.card-title-btn:focus-visible {
|
|
491
569
|
outline: 1px solid var(--teal);
|
|
492
570
|
outline-offset: 2px;
|
|
493
|
-
border-radius:
|
|
571
|
+
border-radius: var(--r-sm);
|
|
494
572
|
}
|
|
495
573
|
|
|
496
574
|
/* ------------------------------------------------------ memory inspector */
|
|
@@ -527,7 +605,7 @@ select:disabled {
|
|
|
527
605
|
min-height: 0;
|
|
528
606
|
background: color-mix(in srgb, var(--surface2) 88%, transparent);
|
|
529
607
|
border: 1px solid var(--border2);
|
|
530
|
-
border-radius:
|
|
608
|
+
border-radius: var(--r-md);
|
|
531
609
|
box-shadow: 0 24px 70px rgba(0, 0, 0, 0.6);
|
|
532
610
|
overflow: hidden;
|
|
533
611
|
}
|
|
@@ -571,7 +649,7 @@ select:disabled {
|
|
|
571
649
|
background: var(--surface);
|
|
572
650
|
color: var(--text);
|
|
573
651
|
border: 1px solid var(--border);
|
|
574
|
-
border-radius:
|
|
652
|
+
border-radius: var(--r-sm);
|
|
575
653
|
padding: 7px 9px;
|
|
576
654
|
font: inherit;
|
|
577
655
|
}
|
|
@@ -583,7 +661,7 @@ select:disabled {
|
|
|
583
661
|
|
|
584
662
|
.memory-filters button {
|
|
585
663
|
border: 1px solid var(--border);
|
|
586
|
-
border-radius:
|
|
664
|
+
border-radius: var(--r-sm);
|
|
587
665
|
background: var(--surface);
|
|
588
666
|
color: var(--text);
|
|
589
667
|
padding: 0 12px;
|
|
@@ -628,7 +706,7 @@ select:disabled {
|
|
|
628
706
|
font-size: 10px;
|
|
629
707
|
line-height: 1.6;
|
|
630
708
|
padding: 1px 7px;
|
|
631
|
-
border-radius:
|
|
709
|
+
border-radius: var(--r-pill);
|
|
632
710
|
border: 1px solid var(--border);
|
|
633
711
|
color: var(--text2);
|
|
634
712
|
background: var(--surface);
|
|
@@ -656,7 +734,7 @@ button.mem-chip.on {
|
|
|
656
734
|
}
|
|
657
735
|
|
|
658
736
|
.mem-chip.src {
|
|
659
|
-
border-color:
|
|
737
|
+
border-color: var(--accent-edge);
|
|
660
738
|
color: var(--teal);
|
|
661
739
|
}
|
|
662
740
|
|
|
@@ -698,7 +776,7 @@ button.mem-chip.on {
|
|
|
698
776
|
|
|
699
777
|
.mem-card {
|
|
700
778
|
border: 1px solid var(--border);
|
|
701
|
-
border-radius:
|
|
779
|
+
border-radius: var(--r-sm);
|
|
702
780
|
background: var(--surface);
|
|
703
781
|
padding: 9px 11px;
|
|
704
782
|
}
|
|
@@ -749,7 +827,7 @@ button.mem-chip.on {
|
|
|
749
827
|
font-size: 12px;
|
|
750
828
|
color: var(--text2);
|
|
751
829
|
border: 1px dashed var(--border);
|
|
752
|
-
border-radius:
|
|
830
|
+
border-radius: var(--r-sm);
|
|
753
831
|
padding: 18px;
|
|
754
832
|
text-align: center;
|
|
755
833
|
}
|
|
@@ -798,7 +876,7 @@ button.mem-chip.on {
|
|
|
798
876
|
background: var(--surface);
|
|
799
877
|
color: var(--text);
|
|
800
878
|
border: 1px solid var(--border);
|
|
801
|
-
border-radius:
|
|
879
|
+
border-radius: var(--r-sm);
|
|
802
880
|
padding: 6px 8px;
|
|
803
881
|
font: inherit;
|
|
804
882
|
}
|
|
@@ -820,7 +898,7 @@ body.memory-open {
|
|
|
820
898
|
background: var(--surface);
|
|
821
899
|
color: var(--text);
|
|
822
900
|
border: 1px solid var(--border);
|
|
823
|
-
border-radius:
|
|
901
|
+
border-radius: var(--r-sm);
|
|
824
902
|
padding: 6px 8px;
|
|
825
903
|
font: inherit;
|
|
826
904
|
}
|
|
@@ -834,7 +912,7 @@ body.memory-open {
|
|
|
834
912
|
width: 100%;
|
|
835
913
|
margin-top: 6px;
|
|
836
914
|
border: none;
|
|
837
|
-
border-radius:
|
|
915
|
+
border-radius: var(--r-sm);
|
|
838
916
|
background: var(--teal);
|
|
839
917
|
color: #04140f;
|
|
840
918
|
padding: 6px 0;
|
|
@@ -844,7 +922,7 @@ body.memory-open {
|
|
|
844
922
|
}
|
|
845
923
|
|
|
846
924
|
.btn-block:hover:not(:disabled) {
|
|
847
|
-
box-shadow: 0 0 12px
|
|
925
|
+
box-shadow: 0 0 12px var(--accent-mid);
|
|
848
926
|
}
|
|
849
927
|
|
|
850
928
|
.btn-block:disabled {
|
|
@@ -852,43 +930,95 @@ body.memory-open {
|
|
|
852
930
|
cursor: default;
|
|
853
931
|
}
|
|
854
932
|
|
|
855
|
-
/* ------------------------------------------------------------- messages
|
|
933
|
+
/* ------------------------------------------------------------- messages
|
|
934
|
+
The transcript is the application. Everything else in this window — the
|
|
935
|
+
rail, the topbar, the composer — is chrome around it, and the layout here
|
|
936
|
+
is what decides whether the window reads as a serious tool or as a chat
|
|
937
|
+
widget.
|
|
938
|
+
|
|
939
|
+
What changed and why (a lift, not a repaint):
|
|
940
|
+
|
|
941
|
+
1. NO BUBBLES. A turn used to be a rounded 76%-wide box, the user's in a
|
|
942
|
+
saturated purple block with white text. That is the geometry of a
|
|
943
|
+
messaging app, and it costs twice: the coloured block is the loudest
|
|
944
|
+
thing on screen even when the *answer* is what the eye came for, and
|
|
945
|
+
the ragged 76% width puts prose at a measure that changes every turn,
|
|
946
|
+
so nothing settles into a column you can read down.
|
|
947
|
+
|
|
948
|
+
2. ONE MEASURE, ONE COLUMN. Every turn is full-width inside a single
|
|
949
|
+
reading column (`--measure`), assistant and user alike. Turns are
|
|
950
|
+
separated by a hairline and by space, never by a frame — the same
|
|
951
|
+
no-boxes rule the sidebar adopted, applied to the transcript. The
|
|
952
|
+
reader's eye then has exactly one left edge to return to.
|
|
953
|
+
|
|
954
|
+
3. AUTHOR LINE, NOT A CHAT HEADER. `.who` was 11px uppercase with 0.7
|
|
955
|
+
opacity sitting *inside* the bubble; it is now a quiet line above the
|
|
956
|
+
prose in the body colour, so it labels the turn without competing
|
|
957
|
+
with it.
|
|
958
|
+
*/
|
|
856
959
|
.messages {
|
|
857
960
|
flex: 1;
|
|
858
961
|
overflow-y: auto;
|
|
859
|
-
padding:
|
|
962
|
+
padding: var(--s-4) var(--s-4) var(--s-2);
|
|
860
963
|
display: flex;
|
|
861
964
|
flex-direction: column;
|
|
862
|
-
gap:
|
|
965
|
+
gap: 0;
|
|
863
966
|
min-height: 0;
|
|
864
967
|
font-family: var(--font-chat);
|
|
968
|
+
/* The reading column is centered in the pane and capped at ~72ch: past
|
|
969
|
+
that a line of prose is a head-turn, under it the column looks stingy.
|
|
970
|
+
The number lives on :root (--measure) so the composer shares it; `auto`
|
|
971
|
+
side margins in a column flex container center each child horizontally,
|
|
972
|
+
and in a narrow window the cap simply stops binding — no media query. */
|
|
865
973
|
}
|
|
866
974
|
|
|
867
975
|
.msg {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
976
|
+
width: 100%;
|
|
977
|
+
max-width: var(--measure);
|
|
978
|
+
margin: 0 auto;
|
|
979
|
+
/* Horizontal padding is the same on every role, including the assistant
|
|
980
|
+
turn that paints no background. That is deliberate: the moment the user's
|
|
981
|
+
plate is inset and the reply is not, the two turns start on different left
|
|
982
|
+
edges and the column this whole section is built around stops existing. */
|
|
983
|
+
padding: 14px var(--s-3) 16px;
|
|
984
|
+
border: 0;
|
|
985
|
+
border-radius: 0;
|
|
986
|
+
background: none;
|
|
987
|
+
/* The hairline that replaces the bubble: a divider between turns, drawn on
|
|
988
|
+
the TOP of every turn including the first, then suppressed on the first
|
|
989
|
+
one below. One line, one place, no double border between neighbours. */
|
|
990
|
+
border-top: 1px solid var(--border);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
.msg:first-child {
|
|
994
|
+
border-top: 0;
|
|
995
|
+
padding-top: 0;
|
|
871
996
|
}
|
|
872
997
|
|
|
998
|
+
/* The user's turn is distinguished by typography and a quiet plate, not by a
|
|
999
|
+
saturated fill. `--surface2` is the "object on the page" step of the ramp,
|
|
1000
|
+
so the band is faintly recessed — enough to find while scrolling back,
|
|
1001
|
+
never enough to outshout the answer under it. */
|
|
873
1002
|
.msg.user {
|
|
874
|
-
align-self:
|
|
875
|
-
background: var(--
|
|
876
|
-
color:
|
|
1003
|
+
align-self: center;
|
|
1004
|
+
background: var(--surface2);
|
|
1005
|
+
color: var(--text);
|
|
1006
|
+
border-radius: var(--r-md);
|
|
1007
|
+
border-top-color: transparent;
|
|
877
1008
|
}
|
|
878
1009
|
|
|
879
1010
|
.msg.assistant {
|
|
880
|
-
align-self:
|
|
881
|
-
background:
|
|
882
|
-
border: 1px solid var(--border);
|
|
1011
|
+
align-self: center;
|
|
1012
|
+
background: none;
|
|
883
1013
|
}
|
|
884
1014
|
|
|
885
1015
|
.msg.system {
|
|
886
1016
|
align-self: center;
|
|
887
|
-
background:
|
|
1017
|
+
background: none;
|
|
888
1018
|
color: var(--text2);
|
|
889
1019
|
font-size: 12px;
|
|
890
|
-
border: 1px dashed var(--border);
|
|
891
|
-
max-width: 92
|
|
1020
|
+
border-top: 1px dashed var(--border);
|
|
1021
|
+
max-width: min(var(--measure), 92%);
|
|
892
1022
|
text-align: center;
|
|
893
1023
|
}
|
|
894
1024
|
|
|
@@ -968,23 +1098,35 @@ body.memory-open {
|
|
|
968
1098
|
display: none;
|
|
969
1099
|
}
|
|
970
1100
|
|
|
1101
|
+
/* The author line. Uppercase micro-type at 600 weight is the one place this
|
|
1102
|
+
sheet uses it, because it is a label and not prose — but it now sits in
|
|
1103
|
+
--text2 on the page background instead of inside a bubble, and the user's
|
|
1104
|
+
is tinted rather than right-aligned: in a single reading column a ragged
|
|
1105
|
+
right edge on one turn's header breaks the column the whole layout exists
|
|
1106
|
+
to establish. */
|
|
971
1107
|
.who {
|
|
972
1108
|
font-size: 11px;
|
|
973
1109
|
font-weight: 600;
|
|
974
1110
|
text-transform: uppercase;
|
|
975
|
-
letter-spacing: 0.
|
|
976
|
-
|
|
977
|
-
margin-bottom:
|
|
1111
|
+
letter-spacing: 0.07em;
|
|
1112
|
+
color: var(--text2);
|
|
1113
|
+
margin-bottom: var(--s-2);
|
|
978
1114
|
font-family: var(--font-display);
|
|
979
1115
|
}
|
|
980
1116
|
|
|
981
1117
|
.msg.user .who {
|
|
982
|
-
|
|
1118
|
+
color: var(--purple);
|
|
983
1119
|
}
|
|
984
1120
|
|
|
1121
|
+
/* Prose. 15px/1.65 is a touch larger than the 14px body default because this
|
|
1122
|
+
is the only long-form text in the window and the measure above is wide
|
|
1123
|
+
enough to carry it; anything smaller at 72ch reads as a log file. */
|
|
985
1124
|
.body {
|
|
986
1125
|
white-space: pre-wrap;
|
|
987
1126
|
word-break: break-word;
|
|
1127
|
+
font-size: 15px;
|
|
1128
|
+
line-height: 1.65;
|
|
1129
|
+
color: var(--text);
|
|
988
1130
|
}
|
|
989
1131
|
|
|
990
1132
|
/* Tool-call log for a turn (desktop/lib/local/engine.js onDelta's `tool`
|
|
@@ -1022,14 +1164,17 @@ body.memory-open {
|
|
|
1022
1164
|
|
|
1023
1165
|
.meta {
|
|
1024
1166
|
font-size: 11px;
|
|
1025
|
-
color: var(--
|
|
1026
|
-
margin-top:
|
|
1167
|
+
color: var(--text3);
|
|
1168
|
+
margin-top: var(--s-2);
|
|
1027
1169
|
font-family: var(--font-mono);
|
|
1028
1170
|
}
|
|
1029
1171
|
|
|
1172
|
+
/* Was `rgba(255, 255, 255, 0.75)`, chosen to survive on the purple bubble.
|
|
1173
|
+
The bubble is gone, so a white wash here would be a faint smudge on the
|
|
1174
|
+
page; the user's meta takes the muted step of the ramp like everyone
|
|
1175
|
+
else's. */
|
|
1030
1176
|
.msg.user .meta {
|
|
1031
|
-
color:
|
|
1032
|
-
text-align: right;
|
|
1177
|
+
color: var(--text3);
|
|
1033
1178
|
}
|
|
1034
1179
|
|
|
1035
1180
|
/* --------------------------------------------------- discovery lane (D2.2)
|
|
@@ -1038,17 +1183,13 @@ body.memory-open {
|
|
|
1038
1183
|
beside the answer instead of being buried under it. */
|
|
1039
1184
|
.chatflow {
|
|
1040
1185
|
align-self: stretch;
|
|
1041
|
-
max-width:
|
|
1042
|
-
margin: 2px
|
|
1043
|
-
padding:
|
|
1186
|
+
max-width: var(--measure);
|
|
1187
|
+
margin: 2px auto var(--s-2);
|
|
1188
|
+
padding: var(--s-2) 10px 10px;
|
|
1044
1189
|
border: 1px solid var(--border);
|
|
1045
1190
|
border-left: 2px solid var(--teal);
|
|
1046
|
-
border-radius:
|
|
1047
|
-
background: linear-gradient(
|
|
1048
|
-
90deg,
|
|
1049
|
-
rgba(0, 229, 192, 0.05),
|
|
1050
|
-
rgba(107, 143, 212, 0.05)
|
|
1051
|
-
);
|
|
1191
|
+
border-radius: var(--r-md);
|
|
1192
|
+
background: linear-gradient(90deg, var(--accent-soft), rgba(107, 143, 212, 0.05));
|
|
1052
1193
|
}
|
|
1053
1194
|
|
|
1054
1195
|
.flow-rail {
|
|
@@ -1095,7 +1236,7 @@ body.memory-open {
|
|
|
1095
1236
|
gap: 6px;
|
|
1096
1237
|
padding: 9px 11px;
|
|
1097
1238
|
border: 1px solid var(--border2);
|
|
1098
|
-
border-radius:
|
|
1239
|
+
border-radius: var(--r-md);
|
|
1099
1240
|
background: var(--surface2);
|
|
1100
1241
|
min-height: 92px;
|
|
1101
1242
|
}
|
|
@@ -1116,7 +1257,7 @@ body.memory-open {
|
|
|
1116
1257
|
}
|
|
1117
1258
|
|
|
1118
1259
|
.flow-card.done {
|
|
1119
|
-
border-color:
|
|
1260
|
+
border-color: var(--accent-edge);
|
|
1120
1261
|
}
|
|
1121
1262
|
|
|
1122
1263
|
.flow-card.stopped {
|
|
@@ -1212,31 +1353,30 @@ body.memory-open {
|
|
|
1212
1353
|
scroll-snap-align: end;
|
|
1213
1354
|
}
|
|
1214
1355
|
|
|
1215
|
-
/* Composer side rail
|
|
1216
|
-
|
|
1217
|
-
.composer-
|
|
1356
|
+
/* Composer side rail. Now the composer's own control row (see .composer-row):
|
|
1357
|
+
the discovery toggle, the mode chip and Send on one line under the input. */
|
|
1358
|
+
.composer-row {
|
|
1218
1359
|
display: flex;
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1360
|
+
align-items: center;
|
|
1361
|
+
gap: var(--s-2);
|
|
1362
|
+
/* The top hairline is what makes the row read as *inside* the composer
|
|
1363
|
+
rather than as a second bar attached to its bottom edge. */
|
|
1364
|
+
border-top: 1px solid var(--border);
|
|
1365
|
+
padding-top: var(--s-2);
|
|
1366
|
+
margin-top: var(--s-1);
|
|
1222
1367
|
}
|
|
1223
1368
|
|
|
1224
|
-
.composer-
|
|
1369
|
+
.composer-spacer {
|
|
1225
1370
|
flex: 1;
|
|
1226
|
-
min-height: 34px;
|
|
1227
1371
|
}
|
|
1228
1372
|
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
.composer-modes {
|
|
1233
|
-
display: flex;
|
|
1234
|
-
align-items: center;
|
|
1235
|
-
gap: 10px;
|
|
1236
|
-
padding: 0 16px 10px;
|
|
1237
|
-
min-height: 22px;
|
|
1373
|
+
.composer-row button[type='submit'] {
|
|
1374
|
+
flex: none;
|
|
1375
|
+
min-height: 30px;
|
|
1238
1376
|
}
|
|
1239
1377
|
|
|
1378
|
+
/* Composer mode chip: the tool-approval mode, inside the composer. Painted
|
|
1379
|
+
only from renderConfirmMode()/renderAutoModeChip() in app.js. */
|
|
1240
1380
|
.mode-chip {
|
|
1241
1381
|
display: inline-flex;
|
|
1242
1382
|
align-items: center;
|
|
@@ -1246,9 +1386,9 @@ body.memory-open {
|
|
|
1246
1386
|
font-size: 10.5px;
|
|
1247
1387
|
line-height: 1.7;
|
|
1248
1388
|
color: var(--text2);
|
|
1249
|
-
background: var(--
|
|
1389
|
+
background: var(--surface);
|
|
1250
1390
|
border: 1px solid var(--border);
|
|
1251
|
-
border-radius:
|
|
1391
|
+
border-radius: var(--r-pill);
|
|
1252
1392
|
cursor: pointer;
|
|
1253
1393
|
user-select: none;
|
|
1254
1394
|
white-space: nowrap;
|
|
@@ -1274,7 +1414,8 @@ body.memory-open {
|
|
|
1274
1414
|
quiet, because the safe state should not look like the exciting one. */
|
|
1275
1415
|
.mode-chip.is-auto {
|
|
1276
1416
|
color: var(--teal);
|
|
1277
|
-
border-color: var(--
|
|
1417
|
+
border-color: var(--accent-edge);
|
|
1418
|
+
background: var(--accent-soft);
|
|
1278
1419
|
}
|
|
1279
1420
|
|
|
1280
1421
|
.mode-chip.is-auto .mode-dot {
|
|
@@ -1282,10 +1423,14 @@ body.memory-open {
|
|
|
1282
1423
|
text-shadow: 0 0 6px var(--teal);
|
|
1283
1424
|
}
|
|
1284
1425
|
|
|
1285
|
-
.composer-
|
|
1426
|
+
.composer-row .hint {
|
|
1286
1427
|
font-size: 10.5px;
|
|
1287
1428
|
color: var(--text3);
|
|
1288
1429
|
margin: 0;
|
|
1430
|
+
min-width: 0;
|
|
1431
|
+
overflow: hidden;
|
|
1432
|
+
text-overflow: ellipsis;
|
|
1433
|
+
white-space: nowrap;
|
|
1289
1434
|
}
|
|
1290
1435
|
|
|
1291
1436
|
|
|
@@ -1372,60 +1517,91 @@ label[hidden] {
|
|
|
1372
1517
|
color: var(--teal);
|
|
1373
1518
|
}
|
|
1374
1519
|
|
|
1375
|
-
/* ------------------------------------------------------------- composer
|
|
1520
|
+
/* ------------------------------------------------------------- composer
|
|
1521
|
+
The one elevated object in the window. Everything else is flat: the rail is
|
|
1522
|
+
a surface, turns are a column with hairlines, and this is the thing that
|
|
1523
|
+
sits ON the page, so it is the only element allowed a shadow and the only
|
|
1524
|
+
one whose focus changes its border. That is the whole hierarchy — if the
|
|
1525
|
+
composer is not the most obviously interactive object on screen, the eye
|
|
1526
|
+
does not land on the place it is supposed to type.
|
|
1527
|
+
|
|
1528
|
+
Flex direction is column now, not row: the textarea is the box and the
|
|
1529
|
+
control row (toggle, mode chip, Send) sits on a hairline inside it. */
|
|
1376
1530
|
.composer {
|
|
1377
1531
|
display: flex;
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
width:
|
|
1532
|
+
flex-direction: column;
|
|
1533
|
+
gap: var(--s-1);
|
|
1534
|
+
align-items: stretch;
|
|
1535
|
+
padding: var(--s-3);
|
|
1536
|
+
margin: 0 auto var(--s-3);
|
|
1537
|
+
max-width: var(--measure);
|
|
1538
|
+
width: calc(100% - 32px);
|
|
1384
1539
|
border: 1px solid var(--border2);
|
|
1385
|
-
border-radius:
|
|
1540
|
+
border-radius: var(--r-lg);
|
|
1386
1541
|
background: var(--surface2);
|
|
1387
|
-
box-shadow:
|
|
1542
|
+
box-shadow: var(--shadow-1);
|
|
1388
1543
|
transition: border-color 0.15s, box-shadow 0.15s;
|
|
1389
|
-
margin-bottom: 12px;
|
|
1390
1544
|
}
|
|
1391
1545
|
|
|
1546
|
+
/* Focus is communicated by the border and a single soft ring — not by a glow
|
|
1547
|
+
in the accent colour at full strength, which turned the whole box teal and
|
|
1548
|
+
made every keystroke feel like an alert. */
|
|
1392
1549
|
.composer:focus-within {
|
|
1393
|
-
border-color: var(--
|
|
1394
|
-
box-shadow: 0 0 0
|
|
1550
|
+
border-color: var(--border2);
|
|
1551
|
+
box-shadow: 0 0 0 3px var(--accent-soft), var(--shadow-2);
|
|
1395
1552
|
}
|
|
1396
1553
|
|
|
1397
1554
|
.composer textarea {
|
|
1398
|
-
flex: 1
|
|
1555
|
+
/* `flex: 1` lives here from the row-era composer, where it let the input eat
|
|
1556
|
+
the leftover WIDTH. The composer is a column now, so a 0 flex-basis would
|
|
1557
|
+
resolve vertically and collapse the field to its padding: basis `auto`
|
|
1558
|
+
keeps the two rows the markup asks for, and the textarea's own
|
|
1559
|
+
`rows="2"` supplies the height. Growth is no longer its job. */
|
|
1560
|
+
flex: 0 0 auto;
|
|
1399
1561
|
resize: none;
|
|
1400
1562
|
background: transparent;
|
|
1401
1563
|
color: var(--text);
|
|
1402
1564
|
border: none;
|
|
1403
|
-
border-radius:
|
|
1404
|
-
padding:
|
|
1565
|
+
border-radius: var(--r-sm);
|
|
1566
|
+
padding: var(--s-1) 2px;
|
|
1405
1567
|
font: inherit;
|
|
1406
1568
|
font-family: var(--font-chat);
|
|
1569
|
+
font-size: 15px;
|
|
1570
|
+
line-height: 1.6;
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
.composer textarea::placeholder {
|
|
1574
|
+
color: var(--text3);
|
|
1407
1575
|
}
|
|
1408
1576
|
|
|
1409
1577
|
.composer textarea:focus {
|
|
1410
1578
|
outline: none;
|
|
1411
1579
|
}
|
|
1412
1580
|
|
|
1413
|
-
|
|
1581
|
+
/* Send is filled accent, not a second grey button: it is the terminal action
|
|
1582
|
+
of the only form in the window. */
|
|
1583
|
+
/* Scoped to [type='submit'] on purpose. The mode chip is a <button> inside
|
|
1584
|
+
this form now (it used to sit outside it), and `.composer button` at
|
|
1585
|
+
(0,1,1) outranks `.mode-chip` at (0,1,0) — so an unscoped rule here would
|
|
1586
|
+
have filled the chip with the send accent. Send is the only submit. */
|
|
1587
|
+
.composer button[type='submit'] {
|
|
1414
1588
|
border: none;
|
|
1415
|
-
border-radius:
|
|
1589
|
+
border-radius: var(--r-sm);
|
|
1416
1590
|
background: var(--teal);
|
|
1417
1591
|
color: #04140f;
|
|
1418
|
-
padding: 0
|
|
1592
|
+
padding: 0 16px;
|
|
1419
1593
|
font: inherit;
|
|
1420
1594
|
font-weight: 700;
|
|
1421
1595
|
cursor: pointer;
|
|
1596
|
+
transition: filter 0.15s, box-shadow 0.15s;
|
|
1422
1597
|
}
|
|
1423
1598
|
|
|
1424
|
-
.composer button:hover:not(:disabled) {
|
|
1425
|
-
|
|
1599
|
+
.composer button[type='submit']:hover:not(:disabled) {
|
|
1600
|
+
filter: brightness(1.08);
|
|
1601
|
+
box-shadow: 0 0 12px var(--accent-mid);
|
|
1426
1602
|
}
|
|
1427
1603
|
|
|
1428
|
-
.composer button:disabled {
|
|
1604
|
+
.composer button[type='submit']:disabled {
|
|
1429
1605
|
opacity: 0.5;
|
|
1430
1606
|
cursor: default;
|
|
1431
1607
|
}
|
|
@@ -1440,7 +1616,7 @@ label {
|
|
|
1440
1616
|
|
|
1441
1617
|
.ghost-btn {
|
|
1442
1618
|
border: 1px solid var(--border);
|
|
1443
|
-
border-radius:
|
|
1619
|
+
border-radius: var(--r-sm);
|
|
1444
1620
|
background: var(--surface2);
|
|
1445
1621
|
color: var(--text);
|
|
1446
1622
|
padding: 4px 10px;
|
|
@@ -1470,7 +1646,7 @@ label {
|
|
|
1470
1646
|
background: var(--surface);
|
|
1471
1647
|
color: var(--text);
|
|
1472
1648
|
border: 1px solid var(--border);
|
|
1473
|
-
border-radius:
|
|
1649
|
+
border-radius: var(--r-sm);
|
|
1474
1650
|
padding: 6px;
|
|
1475
1651
|
font: inherit;
|
|
1476
1652
|
}
|
|
@@ -1483,7 +1659,7 @@ label {
|
|
|
1483
1659
|
.cancel-btn {
|
|
1484
1660
|
margin-top: 8px;
|
|
1485
1661
|
border: 1px solid var(--red);
|
|
1486
|
-
border-radius:
|
|
1662
|
+
border-radius: var(--r-sm);
|
|
1487
1663
|
background: transparent;
|
|
1488
1664
|
color: var(--red);
|
|
1489
1665
|
padding: 2px 10px;
|
|
@@ -1495,7 +1671,7 @@ label {
|
|
|
1495
1671
|
.copy-btn {
|
|
1496
1672
|
margin-top: 8px;
|
|
1497
1673
|
border: 1px solid var(--teal);
|
|
1498
|
-
border-radius:
|
|
1674
|
+
border-radius: var(--r-sm);
|
|
1499
1675
|
background: transparent;
|
|
1500
1676
|
color: var(--teal);
|
|
1501
1677
|
padding: 2px 10px;
|
|
@@ -1522,7 +1698,7 @@ label {
|
|
|
1522
1698
|
|
|
1523
1699
|
.approval-card {
|
|
1524
1700
|
border: 1px solid var(--amber);
|
|
1525
|
-
border-radius:
|
|
1701
|
+
border-radius: var(--r-sm);
|
|
1526
1702
|
background: rgba(255, 145, 0, 0.08);
|
|
1527
1703
|
padding: 8px 10px;
|
|
1528
1704
|
}
|
|
@@ -1596,7 +1772,7 @@ label {
|
|
|
1596
1772
|
white-space: pre;
|
|
1597
1773
|
background: var(--bg);
|
|
1598
1774
|
border: 1px solid var(--border);
|
|
1599
|
-
border-radius:
|
|
1775
|
+
border-radius: var(--r-sm);
|
|
1600
1776
|
padding: 6px 8px;
|
|
1601
1777
|
margin-bottom: 8px;
|
|
1602
1778
|
}
|
|
@@ -1628,7 +1804,7 @@ label {
|
|
|
1628
1804
|
}
|
|
1629
1805
|
|
|
1630
1806
|
.approval-btn {
|
|
1631
|
-
border-radius:
|
|
1807
|
+
border-radius: var(--r-sm);
|
|
1632
1808
|
padding: 4px 10px;
|
|
1633
1809
|
font: inherit;
|
|
1634
1810
|
font-size: 11px;
|
|
@@ -1664,16 +1840,21 @@ label {
|
|
|
1664
1840
|
}
|
|
1665
1841
|
|
|
1666
1842
|
/* ------------------------------------------------------- settings pane */
|
|
1843
|
+
/* NO BOXES, same rule as .card (see that comment above): each key row used
|
|
1844
|
+
to be its own filled, bordered, rounded rectangle, which re-introduced the
|
|
1845
|
+
boxed-widgets look one level down inside a card the Oct-18/19 session had
|
|
1846
|
+
just de-boxed. A hairline between rows replaces the per-row frame. */
|
|
1667
1847
|
.setting-row {
|
|
1668
|
-
|
|
1669
|
-
border-radius: 6px;
|
|
1670
|
-
padding: 8px;
|
|
1671
|
-
margin-bottom: 8px;
|
|
1848
|
+
padding: 8px 0;
|
|
1672
1849
|
display: flex;
|
|
1673
1850
|
flex-direction: column;
|
|
1674
1851
|
gap: 6px;
|
|
1675
1852
|
}
|
|
1676
1853
|
|
|
1854
|
+
.setting-row + .setting-row {
|
|
1855
|
+
border-top: 1px solid var(--border);
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1677
1858
|
.setting-name {
|
|
1678
1859
|
font-size: 12px;
|
|
1679
1860
|
font-weight: 600;
|
|
@@ -1684,7 +1865,7 @@ label {
|
|
|
1684
1865
|
background: var(--surface);
|
|
1685
1866
|
color: var(--text);
|
|
1686
1867
|
border: 1px solid var(--border);
|
|
1687
|
-
border-radius:
|
|
1868
|
+
border-radius: var(--r-sm);
|
|
1688
1869
|
padding: 5px 7px;
|
|
1689
1870
|
font: inherit;
|
|
1690
1871
|
font-size: 12px;
|
|
@@ -1721,7 +1902,7 @@ label {
|
|
|
1721
1902
|
font-size: 12px;
|
|
1722
1903
|
color: var(--text2);
|
|
1723
1904
|
border: 1px dashed var(--border);
|
|
1724
|
-
border-radius:
|
|
1905
|
+
border-radius: var(--r-sm);
|
|
1725
1906
|
padding: 6px 8px;
|
|
1726
1907
|
}
|
|
1727
1908
|
|
|
@@ -1744,18 +1925,23 @@ label {
|
|
|
1744
1925
|
color: var(--teal);
|
|
1745
1926
|
}
|
|
1746
1927
|
|
|
1928
|
+
/* Sessions, same no-boxes rule as .card: a list of past sessions is a list,
|
|
1929
|
+
not a stack of cards. Each row is a full-width hit target separated by a
|
|
1930
|
+
hairline; hover paints the row's own surface instead of outlining it. */
|
|
1747
1931
|
.session-row {
|
|
1748
1932
|
display: flex;
|
|
1749
1933
|
flex-direction: column;
|
|
1750
1934
|
gap: 2px;
|
|
1751
|
-
border:
|
|
1752
|
-
border-
|
|
1753
|
-
|
|
1935
|
+
border: 0;
|
|
1936
|
+
border-left: 2px solid transparent;
|
|
1937
|
+
border-radius: var(--r-sm);
|
|
1938
|
+
padding: 5px 8px;
|
|
1754
1939
|
cursor: pointer;
|
|
1755
1940
|
}
|
|
1756
1941
|
|
|
1757
1942
|
.session-row:hover {
|
|
1758
|
-
|
|
1943
|
+
background: var(--surface2);
|
|
1944
|
+
border-left-color: var(--teal);
|
|
1759
1945
|
}
|
|
1760
1946
|
|
|
1761
1947
|
.session-title {
|
|
@@ -1831,41 +2017,39 @@ label {
|
|
|
1831
2017
|
margin: 0;
|
|
1832
2018
|
}
|
|
1833
2019
|
|
|
1834
|
-
.
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
2020
|
+
/* The one personalized line that replaced the five topic pills. It sits where
|
|
2021
|
+
the "start with one of these" sentence and the pill row used to be, and it
|
|
2022
|
+
carries the same visual weight as .sub so the panel still reads as a greeting
|
|
2023
|
+
with one sentence under it — not a card, not a menu. Wider than .sub because
|
|
2024
|
+
it is a sentence about this install rather than a tagline, and `[hidden]` has
|
|
2025
|
+
to be restated: a class selector outranks the UA `[hidden] { display:none }`,
|
|
2026
|
+
which is the same defect fixed for .welcome-connect below. */
|
|
2027
|
+
.welcome-personal {
|
|
2028
|
+
max-width: 480px;
|
|
1840
2029
|
margin-top: 2px;
|
|
2030
|
+
color: var(--text2);
|
|
1841
2031
|
}
|
|
1842
2032
|
|
|
1843
|
-
.
|
|
1844
|
-
display:
|
|
1845
|
-
align-items: center;
|
|
1846
|
-
gap: 7px;
|
|
1847
|
-
padding: 7px 14px;
|
|
1848
|
-
border-radius: 999px;
|
|
1849
|
-
border: 1px solid var(--border2);
|
|
1850
|
-
background: var(--surface);
|
|
1851
|
-
color: var(--text2);
|
|
1852
|
-
font-size: 12px;
|
|
1853
|
-
font-weight: 500;
|
|
1854
|
-
cursor: pointer;
|
|
1855
|
-
transition: all 0.15s;
|
|
1856
|
-
font-family: var(--font-chat);
|
|
1857
|
-
white-space: nowrap;
|
|
2033
|
+
.welcome-personal[hidden] {
|
|
2034
|
+
display: none;
|
|
1858
2035
|
}
|
|
1859
2036
|
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
2037
|
+
/* An action line (a downloaded update, a key not yet pasted) is a step the user
|
|
2038
|
+
can take now, so it gets the teal edge the pills used to carry on hover. A
|
|
2039
|
+
tip rotation stays quiet — it is information, not a task. */
|
|
2040
|
+
/* The model's own sentence. It is not a task and not a status, so it gets no
|
|
2041
|
+
teal edge and no button-like weight — just the body colour, so it reads as
|
|
2042
|
+
the first thing the assistant said rather than as another app notice. */
|
|
2043
|
+
.welcome-personal[data-kind='ai'] {
|
|
2044
|
+
color: var(--text);
|
|
2045
|
+
text-align: left;
|
|
1864
2046
|
}
|
|
1865
2047
|
|
|
1866
|
-
.
|
|
1867
|
-
|
|
1868
|
-
|
|
2048
|
+
.welcome-personal[data-kind='action'] {
|
|
2049
|
+
color: var(--text2);
|
|
2050
|
+
border-left: 2px solid var(--teal);
|
|
2051
|
+
padding-left: 10px;
|
|
2052
|
+
text-align: left;
|
|
1869
2053
|
}
|
|
1870
2054
|
|
|
1871
2055
|
.chat-welcome .hints {
|
|
@@ -1895,7 +2079,7 @@ label {
|
|
|
1895
2079
|
margin-top: 8px;
|
|
1896
2080
|
padding: 16px 18px;
|
|
1897
2081
|
border: 1px solid var(--border);
|
|
1898
|
-
border-radius:
|
|
2082
|
+
border-radius: var(--r-md);
|
|
1899
2083
|
background: var(--surface);
|
|
1900
2084
|
text-align: left;
|
|
1901
2085
|
animation: wc-in 0.25s ease-out;
|
|
@@ -1991,7 +2175,7 @@ label {
|
|
|
1991
2175
|
text-align: left;
|
|
1992
2176
|
padding: 13px 14px;
|
|
1993
2177
|
border: 1px solid var(--border2);
|
|
1994
|
-
border-radius:
|
|
2178
|
+
border-radius: var(--r-sm);
|
|
1995
2179
|
background: var(--surface2);
|
|
1996
2180
|
color: var(--text2);
|
|
1997
2181
|
font-family: var(--font-chat);
|
|
@@ -2002,7 +2186,7 @@ label {
|
|
|
2002
2186
|
.wc-path:hover,
|
|
2003
2187
|
.wc-path:focus-visible {
|
|
2004
2188
|
border-color: var(--teal);
|
|
2005
|
-
background:
|
|
2189
|
+
background: var(--accent-soft);
|
|
2006
2190
|
outline: none;
|
|
2007
2191
|
}
|
|
2008
2192
|
|
|
@@ -2012,7 +2196,7 @@ label {
|
|
|
2012
2196
|
existing surface, no new colours, no change to the shared .wc-path rules
|
|
2013
2197
|
above. */
|
|
2014
2198
|
.wc-path-primary {
|
|
2015
|
-
border-color:
|
|
2199
|
+
border-color: var(--accent-edge);
|
|
2016
2200
|
background: linear-gradient(180deg, rgba(0, 229, 192, 0.07), rgba(0, 229, 192, 0.02));
|
|
2017
2201
|
}
|
|
2018
2202
|
|
|
@@ -2235,7 +2419,7 @@ label {
|
|
|
2235
2419
|
font-size: 0.92em;
|
|
2236
2420
|
background: rgba(255, 255, 255, 0.06);
|
|
2237
2421
|
border: 1px solid var(--border);
|
|
2238
|
-
border-radius:
|
|
2422
|
+
border-radius: var(--r-sm);
|
|
2239
2423
|
padding: 1px 5px;
|
|
2240
2424
|
}
|
|
2241
2425
|
|
|
@@ -2248,7 +2432,7 @@ label {
|
|
|
2248
2432
|
padding-top: 26px;
|
|
2249
2433
|
background: var(--bg);
|
|
2250
2434
|
border: 1px solid var(--border);
|
|
2251
|
-
border-radius:
|
|
2435
|
+
border-radius: var(--r-sm);
|
|
2252
2436
|
overflow-x: auto;
|
|
2253
2437
|
}
|
|
2254
2438
|
|
|
@@ -2265,7 +2449,7 @@ label {
|
|
|
2265
2449
|
top: 6px;
|
|
2266
2450
|
right: 6px;
|
|
2267
2451
|
border: 1px solid var(--border2);
|
|
2268
|
-
border-radius:
|
|
2452
|
+
border-radius: var(--r-sm);
|
|
2269
2453
|
background: var(--surface);
|
|
2270
2454
|
color: var(--text2);
|
|
2271
2455
|
padding: 1px 8px;
|
|
@@ -2353,15 +2537,15 @@ label {
|
|
|
2353
2537
|
pointer-events: none;
|
|
2354
2538
|
background: linear-gradient(
|
|
2355
2539
|
to bottom,
|
|
2356
|
-
rgba(
|
|
2357
|
-
rgba(
|
|
2540
|
+
rgba(11, 13, 17, 0.6),
|
|
2541
|
+
rgba(11, 13, 17, 0)
|
|
2358
2542
|
);
|
|
2359
2543
|
opacity: 0;
|
|
2360
2544
|
transition: opacity 0.18s ease;
|
|
2361
2545
|
}
|
|
2362
2546
|
|
|
2363
2547
|
body.is-scrolled .topbar {
|
|
2364
|
-
background-color: rgba(
|
|
2548
|
+
background-color: rgba(23, 27, 35, 0.86);
|
|
2365
2549
|
-webkit-backdrop-filter: blur(12px) saturate(140%);
|
|
2366
2550
|
backdrop-filter: blur(12px) saturate(140%);
|
|
2367
2551
|
box-shadow: 0 1px 0 var(--border), 0 14px 34px -22px rgba(0, 0, 0, 0.9);
|
|
@@ -2375,7 +2559,7 @@ body.is-scrolled .topbar::after {
|
|
|
2375
2559
|
`.composer` already transitions box-shadow (see the composer section), so
|
|
2376
2560
|
this animates with no new transition to keep in sync. */
|
|
2377
2561
|
body.is-scrolled .composer {
|
|
2378
|
-
box-shadow:
|
|
2562
|
+
box-shadow: var(--shadow-2);
|
|
2379
2563
|
}
|
|
2380
2564
|
|
|
2381
2565
|
/* Scrollbars: thin, self-effacing, and only really visible while in use —
|
|
@@ -2426,7 +2610,7 @@ body.is-scrolled .composer {
|
|
|
2426
2610
|
background-color: var(--border);
|
|
2427
2611
|
background-clip: padding-box;
|
|
2428
2612
|
border: 3px solid transparent;
|
|
2429
|
-
border-radius:
|
|
2613
|
+
border-radius: var(--r-pill);
|
|
2430
2614
|
}
|
|
2431
2615
|
|
|
2432
2616
|
.messages::-webkit-scrollbar-thumb:hover,
|
|
@@ -2556,14 +2740,22 @@ body.keys-open {
|
|
|
2556
2740
|
padding: 4px 0;
|
|
2557
2741
|
}
|
|
2558
2742
|
|
|
2743
|
+
/* Key rows: a ledger, so rows are separated by a hairline rather than each
|
|
2744
|
+
carrying a frame. `--line` was never defined anywhere in this sheet — the
|
|
2745
|
+
`#2a2f3a` fallback was doing all the work — so it now names the real token. */
|
|
2559
2746
|
.keys-row {
|
|
2560
2747
|
display: grid;
|
|
2561
2748
|
grid-template-columns: 78px 1fr auto;
|
|
2562
2749
|
align-items: center;
|
|
2563
2750
|
gap: 10px;
|
|
2564
|
-
padding: 10px
|
|
2565
|
-
border:
|
|
2566
|
-
border-
|
|
2751
|
+
padding: 10px 2px;
|
|
2752
|
+
border: 0;
|
|
2753
|
+
border-top: 1px solid var(--border);
|
|
2754
|
+
border-radius: 0;
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
.keys-row:first-child {
|
|
2758
|
+
border-top: 0;
|
|
2567
2759
|
}
|
|
2568
2760
|
|
|
2569
2761
|
/* A row whose key is already on the machine reads as done and drops back, so
|
|
@@ -2578,7 +2770,7 @@ body.keys-open {
|
|
|
2578
2770
|
font-size: 12px;
|
|
2579
2771
|
text-align: center;
|
|
2580
2772
|
padding: 2px 6px;
|
|
2581
|
-
border-radius:
|
|
2773
|
+
border-radius: var(--r-sm);
|
|
2582
2774
|
color: #9aa4b2;
|
|
2583
2775
|
}
|
|
2584
2776
|
|
|
@@ -2598,3 +2790,187 @@ body.keys-open {
|
|
|
2598
2790
|
flex-wrap: wrap;
|
|
2599
2791
|
padding-top: 6px;
|
|
2600
2792
|
}
|
|
2793
|
+
|
|
2794
|
+
/* ------------------------------------------------ providers & models card
|
|
2795
|
+
One list, every provider path. The URL line is monospace because it IS an
|
|
2796
|
+
address — proportional text misreads `l`/`1` and `0`/`O` in a hostname. */
|
|
2797
|
+
/* The one bar: provider, model, effort. Laid out as a single row of labelled
|
|
2798
|
+
controls rather than a stack of label-above-select pairs, because these three
|
|
2799
|
+
are read together — the model list is the provider's, the effort applies to
|
|
2800
|
+
whatever is picked. Wraps at narrow widths instead of overflowing; the
|
|
2801
|
+
sidebar is 300px and a fixed row would clip the effort select. */
|
|
2802
|
+
.pt-toolbar {
|
|
2803
|
+
display: flex;
|
|
2804
|
+
flex-wrap: wrap;
|
|
2805
|
+
gap: 6px 8px;
|
|
2806
|
+
align-items: flex-end;
|
|
2807
|
+
margin-bottom: 6px;
|
|
2808
|
+
}
|
|
2809
|
+
.pt-field {
|
|
2810
|
+
display: flex;
|
|
2811
|
+
flex-direction: column;
|
|
2812
|
+
gap: 2px;
|
|
2813
|
+
flex: 1 1 92px;
|
|
2814
|
+
min-width: 0;
|
|
2815
|
+
font-size: 10px;
|
|
2816
|
+
text-transform: uppercase;
|
|
2817
|
+
letter-spacing: 0.08em;
|
|
2818
|
+
color: var(--text2);
|
|
2819
|
+
font-family: var(--font-display);
|
|
2820
|
+
}
|
|
2821
|
+
/* The base `select` rule puts `margin-top: 6px` and `width: 100%` on every
|
|
2822
|
+
select in the app, which inside the bar leaves a floating 6px gap above each
|
|
2823
|
+
control and forces the row to wrap. Reset here only. */
|
|
2824
|
+
.pt-field select {
|
|
2825
|
+
margin-top: 0;
|
|
2826
|
+
padding: 4px 6px;
|
|
2827
|
+
}
|
|
2828
|
+
.pt-toolbar .budget-row {
|
|
2829
|
+
display: flex;
|
|
2830
|
+
flex-direction: column;
|
|
2831
|
+
gap: 2px;
|
|
2832
|
+
flex: 0 0 72px;
|
|
2833
|
+
font-size: 10px;
|
|
2834
|
+
text-transform: uppercase;
|
|
2835
|
+
letter-spacing: 0.08em;
|
|
2836
|
+
color: var(--text2);
|
|
2837
|
+
font-family: var(--font-display);
|
|
2838
|
+
}
|
|
2839
|
+
.pt-toolbar .budget-row select {
|
|
2840
|
+
margin-top: 0;
|
|
2841
|
+
padding: 4px 6px;
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
/* The two cards' split (index.html): the catalog card is key rows, the custom
|
|
2845
|
+
card is an address + key + model id. Its fields are the bar's `.pt-field`
|
|
2846
|
+
stacked one per line — the three go together, so none of them is `flex: 1 1
|
|
2847
|
+
92px` beside another and wrapping mid-decision. */
|
|
2848
|
+
#custom-provider-card .pt-field {
|
|
2849
|
+
flex: 1 1 100%;
|
|
2850
|
+
margin-bottom: 6px;
|
|
2851
|
+
}
|
|
2852
|
+
#custom-provider-card .pt-field input {
|
|
2853
|
+
margin-top: 0;
|
|
2854
|
+
font-family: var(--font-mono);
|
|
2855
|
+
text-transform: none;
|
|
2856
|
+
letter-spacing: normal;
|
|
2857
|
+
}
|
|
2858
|
+
#custom-provider-card .api-key-row {
|
|
2859
|
+
margin-top: 2px;
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
.pt-bar {
|
|
2863
|
+
display: flex;
|
|
2864
|
+
gap: 8px;
|
|
2865
|
+
align-items: center;
|
|
2866
|
+
margin-bottom: 6px;
|
|
2867
|
+
}
|
|
2868
|
+
.pt-bar input {
|
|
2869
|
+
flex: 1 1 auto;
|
|
2870
|
+
min-width: 0;
|
|
2871
|
+
}
|
|
2872
|
+
.pt-list {
|
|
2873
|
+
list-style: none;
|
|
2874
|
+
margin: 4px 0 0;
|
|
2875
|
+
padding: 0;
|
|
2876
|
+
max-height: 340px;
|
|
2877
|
+
overflow-y: auto;
|
|
2878
|
+
}
|
|
2879
|
+
.pt-group {
|
|
2880
|
+
margin-bottom: 8px;
|
|
2881
|
+
}
|
|
2882
|
+
.pt-group-title {
|
|
2883
|
+
font-size: 11px;
|
|
2884
|
+
text-transform: uppercase;
|
|
2885
|
+
letter-spacing: 0.06em;
|
|
2886
|
+
opacity: 0.65;
|
|
2887
|
+
margin: 4px 0 2px;
|
|
2888
|
+
}
|
|
2889
|
+
.pt-rows {
|
|
2890
|
+
list-style: none;
|
|
2891
|
+
margin: 0;
|
|
2892
|
+
padding: 0;
|
|
2893
|
+
}
|
|
2894
|
+
.pt-row {
|
|
2895
|
+
display: flex;
|
|
2896
|
+
flex-direction: column;
|
|
2897
|
+
gap: 1px;
|
|
2898
|
+
padding: 4px 6px;
|
|
2899
|
+
border-radius: var(--r-sm);
|
|
2900
|
+
border-left: 2px solid transparent;
|
|
2901
|
+
}
|
|
2902
|
+
.pt-row:hover {
|
|
2903
|
+
background: rgba(255, 255, 255, 0.04);
|
|
2904
|
+
border-left-color: currentColor;
|
|
2905
|
+
}
|
|
2906
|
+
/* The clickable row fills its <li>; the browser's default button chrome is
|
|
2907
|
+
reset here rather than using a div, so keyboard focus and Enter work. */
|
|
2908
|
+
.pt-pick {
|
|
2909
|
+
display: flex;
|
|
2910
|
+
flex-direction: column;
|
|
2911
|
+
gap: 1px;
|
|
2912
|
+
width: 100%;
|
|
2913
|
+
text-align: left;
|
|
2914
|
+
background: none;
|
|
2915
|
+
border: 0;
|
|
2916
|
+
padding: 0;
|
|
2917
|
+
color: inherit;
|
|
2918
|
+
font: inherit;
|
|
2919
|
+
cursor: pointer;
|
|
2920
|
+
}
|
|
2921
|
+
.pt-pick:focus-visible {
|
|
2922
|
+
outline: 2px solid currentColor;
|
|
2923
|
+
outline-offset: 2px;
|
|
2924
|
+
}
|
|
2925
|
+
.pt-model {
|
|
2926
|
+
font-weight: 600;
|
|
2927
|
+
}
|
|
2928
|
+
.pt-muted {
|
|
2929
|
+
opacity: 0.6;
|
|
2930
|
+
font-weight: 400;
|
|
2931
|
+
}
|
|
2932
|
+
.pt-id,
|
|
2933
|
+
.pt-target {
|
|
2934
|
+
font-family: var(--font-mono);
|
|
2935
|
+
font-size: 11px;
|
|
2936
|
+
opacity: 0.7;
|
|
2937
|
+
overflow-wrap: anywhere;
|
|
2938
|
+
}
|
|
2939
|
+
.pt-billing,
|
|
2940
|
+
.pt-blocked {
|
|
2941
|
+
font-size: 11px;
|
|
2942
|
+
opacity: 0.6;
|
|
2943
|
+
}
|
|
2944
|
+
/* A blocked row states the reason in the warning colour, but stays in the list:
|
|
2945
|
+
hiding it would answer "what can I address" with a shorter list than reality. */
|
|
2946
|
+
.pt-blocked {
|
|
2947
|
+
color: #f5a524;
|
|
2948
|
+
opacity: 0.95;
|
|
2949
|
+
}
|
|
2950
|
+
.pt-empty {
|
|
2951
|
+
opacity: 0.6;
|
|
2952
|
+
font-size: 12px;
|
|
2953
|
+
padding: 4px 6px;
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
/* ------------------------------------------------------------ daily line */
|
|
2957
|
+
.companion-line {
|
|
2958
|
+
margin: 2px 0 6px;
|
|
2959
|
+
line-height: 1.45;
|
|
2960
|
+
}
|
|
2961
|
+
.companion-row {
|
|
2962
|
+
display: flex;
|
|
2963
|
+
gap: 8px;
|
|
2964
|
+
}
|
|
2965
|
+
/* An 'action' message is something to do, so it reads a shade stronger than a
|
|
2966
|
+
tip. Both are plain text — no badge, no colour that implies urgency. */
|
|
2967
|
+
#companion-card[data-kind='action'] .companion-line {
|
|
2968
|
+
font-weight: 600;
|
|
2969
|
+
}
|
|
2970
|
+
/* Same author-stylesheet-beats-UA-stylesheet gotcha as .update-banner above:
|
|
2971
|
+
.card's `display: grid` (or similar) outranks the UA sheet's
|
|
2972
|
+
`[hidden] { display: none }`, so the card's initial `hidden` in index.html
|
|
2973
|
+
would otherwise be a no-op. */
|
|
2974
|
+
#companion-card[hidden] {
|
|
2975
|
+
display: none;
|
|
2976
|
+
}
|