clay-server 3.8.0-beta.1 → 3.8.0-beta.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 (35) hide show
  1. package/lib/builtin-mates.js +14 -14
  2. package/lib/mates.js +2 -6
  3. package/lib/project-mate-interaction.js +7 -7
  4. package/lib/project-sessions.js +1 -1
  5. package/lib/project-user-mention.js +4 -4
  6. package/lib/project.js +4 -3
  7. package/lib/public/css/avatar-imprints.css +46 -0
  8. package/lib/public/css/icon-strip.css +3 -3
  9. package/lib/public/css/profile.css +123 -95
  10. package/lib/public/css/session-actions.css +40 -9
  11. package/lib/public/css/user-settings.css +1 -1
  12. package/lib/public/index.html +2 -2
  13. package/lib/public/modules/app-cursors.js +2 -2
  14. package/lib/public/modules/app-dm.js +1 -8
  15. package/lib/public/modules/app-messages.js +2 -2
  16. package/lib/public/modules/app-projects.js +7 -6
  17. package/lib/public/modules/app-rate-limit.js +0 -1
  18. package/lib/public/modules/app-rendering.js +0 -3
  19. package/lib/public/modules/avatar-imprint.js +134 -0
  20. package/lib/public/modules/avatar.js +25 -19
  21. package/lib/public/modules/debate.js +10 -5
  22. package/lib/public/modules/mate-sidebar.js +2 -2
  23. package/lib/public/modules/mention.js +26 -16
  24. package/lib/public/modules/profile.js +73 -190
  25. package/lib/public/modules/session-actions.js +5 -3
  26. package/lib/public/modules/sidebar-mates.js +5 -4
  27. package/lib/public/modules/sidebar-sessions.js +1 -1
  28. package/lib/public/style.css +1 -0
  29. package/lib/server-auth.js +2 -2
  30. package/lib/server-dm.js +8 -8
  31. package/lib/server-mates.js +3 -3
  32. package/lib/server-settings.js +2 -2
  33. package/lib/server.js +5 -4
  34. package/lib/users.js +4 -4
  35. package/package.json +1 -1
@@ -18,8 +18,8 @@ var BUILTIN_MATES = [
18
18
  key: "clay",
19
19
  displayName: "Clay",
20
20
  bio: "Your workspace memory. Searches every session, project, and decision you've made and answers from the receipts. The chat surface for the home screen.",
21
- avatarColor: "#7c3aed",
22
- avatarStyle: "bottts",
21
+ avatarColor: "#5857fc",
22
+ avatarStyle: "imprint",
23
23
  avatarCustom: "/clay-studio-symbol.png", // Clay is the app — use the app symbol
24
24
  avatarLocked: true,
25
25
  primary: true, // code-managed, auto-updated on startup
@@ -48,8 +48,8 @@ var BUILTIN_MATES = [
48
48
  key: "ally",
49
49
  displayName: "Ally",
50
50
  bio: "Chief of staff. Quiet, sharp, sees across every mate. Knows what Arch decided yesterday, what Buzz pitched last week, and what you said three weeks ago.",
51
- avatarColor: "#00b894",
52
- avatarStyle: "bottts",
51
+ avatarColor: "#5857fc",
52
+ avatarStyle: "imprint",
53
53
  avatarCustom: "/mates/ally.png",
54
54
  avatarLocked: true,
55
55
  archived: true, // skip seeding for new users; demote on existing
@@ -69,8 +69,8 @@ var BUILTIN_MATES = [
69
69
  key: "arch",
70
70
  displayName: "Arch",
71
71
  bio: "Architect. Stubborn about structure, patient about everything else. Draws boxes and arrows before anyone writes code, and is annoyingly right about which ones will break.",
72
- avatarColor: "#0984e3",
73
- avatarStyle: "bottts",
72
+ avatarColor: "#5857fc",
73
+ avatarStyle: "imprint",
74
74
  seedData: {
75
75
  relationship: "colleague",
76
76
  activity: ["planning", "reviewing"],
@@ -87,8 +87,8 @@ var BUILTIN_MATES = [
87
87
  key: "rush",
88
88
  displayName: "Rush",
89
89
  bio: "Shipper. Impatient in the best way. Cuts your scope in half, ships it before lunch, and somehow it's better than the original plan.",
90
- avatarColor: "#e17055",
91
- avatarStyle: "bottts",
90
+ avatarColor: "#5857fc",
91
+ avatarStyle: "imprint",
92
92
  seedData: {
93
93
  relationship: "colleague",
94
94
  activity: ["coding", "planning"],
@@ -105,8 +105,8 @@ var BUILTIN_MATES = [
105
105
  key: "ward",
106
106
  displayName: "Ward",
107
107
  bio: "Guardian. Quietly anxious in a productive way. Reads error logs for fun and asks \"what happens when the input is null?\" before anyone else thinks of it.",
108
- avatarColor: "#00b894",
109
- avatarStyle: "bottts",
108
+ avatarColor: "#5857fc",
109
+ avatarStyle: "imprint",
110
110
  seedData: {
111
111
  relationship: "reviewer",
112
112
  activity: ["reviewing", "testing"],
@@ -123,8 +123,8 @@ var BUILTIN_MATES = [
123
123
  key: "pixel",
124
124
  displayName: "Pixel",
125
125
  bio: "Designer. Obsessed with the details nobody else notices. Sees the 2px misalignment, the confusing label, the flow that makes sense to the builder but not the user.",
126
- avatarColor: "#e84393",
127
- avatarStyle: "bottts",
126
+ avatarColor: "#5857fc",
127
+ avatarStyle: "imprint",
128
128
  seedData: {
129
129
  relationship: "colleague",
130
130
  activity: ["designing", "reviewing"],
@@ -141,8 +141,8 @@ var BUILTIN_MATES = [
141
141
  key: "buzz",
142
142
  displayName: "Buzz",
143
143
  bio: "Marketer. Competitive, trend-obsessed, always watching what others are doing. Researches your market, tracks what people search for, and turns \"we built a thing\" into a story people care about.",
144
- avatarColor: "#fdcb6e",
145
- avatarStyle: "bottts",
144
+ avatarColor: "#5857fc",
145
+ avatarStyle: "imprint",
146
146
  seedData: {
147
147
  relationship: "colleague",
148
148
  activity: ["writing", "marketing"],
package/lib/mates.js CHANGED
@@ -121,10 +121,6 @@ function createMate(ctx, seedData) {
121
121
  var id = generateMateId();
122
122
  var userId = ctx ? ctx.userId : null;
123
123
 
124
- // Pick a random avatar color from a pleasant palette
125
- var colors = ["#6c5ce7", "#00b894", "#e17055", "#0984e3", "#fdcb6e", "#e84393", "#00cec9", "#ff7675"];
126
- var colorIdx = crypto.randomBytes(1)[0] % colors.length;
127
-
128
124
  var mate = {
129
125
  id: id,
130
126
  name: null,
@@ -134,8 +130,8 @@ function createMate(ctx, seedData) {
134
130
  vendor: (seedData && seedData.vendor) || "claude",
135
131
  profile: {
136
132
  displayName: null,
137
- avatarColor: colors[colorIdx],
138
- avatarStyle: "bottts",
133
+ avatarColor: "#5857fc",
134
+ avatarStyle: "imprint",
139
135
  avatarSeed: crypto.randomBytes(4).toString("hex"),
140
136
  },
141
137
  bio: null,
@@ -39,14 +39,14 @@ function attachMateInteraction(ctx) {
39
39
  vendor: "claude",
40
40
  name: "Claude Code",
41
41
  avatarColor: "#cc785c",
42
- avatarStyle: "bottts",
42
+ avatarStyle: "imprint",
43
43
  avatarSeed: "plain-claude",
44
44
  },
45
45
  "plain:codex": {
46
46
  vendor: "codex",
47
47
  name: "Codex",
48
48
  avatarColor: "#10a37f",
49
- avatarStyle: "bottts",
49
+ avatarStyle: "imprint",
50
50
  avatarSeed: "plain-codex",
51
51
  },
52
52
  };
@@ -554,8 +554,8 @@ function attachMateInteraction(ctx) {
554
554
  }
555
555
 
556
556
  var mateName = (mate.profile && mate.profile.displayName) || mate.name || "Mate";
557
- var avatarColor = (mate.profile && mate.profile.avatarColor) || "#6c5ce7";
558
- var avatarStyle = (mate.profile && mate.profile.avatarStyle) || "bottts";
557
+ var avatarColor = (mate.profile && mate.profile.avatarColor) || "#5857fc";
558
+ var avatarStyle = (mate.profile && mate.profile.avatarStyle) || "imprint";
559
559
  var avatarSeed = (mate.profile && mate.profile.avatarSeed) || mate.id;
560
560
 
561
561
  // Build full mention text (include pasted content)
@@ -800,11 +800,11 @@ function attachMateInteraction(ctx) {
800
800
 
801
801
  function getMateProfile(mateCtx, mateId) {
802
802
  var mate = matesModule.getMate(mateCtx, mateId);
803
- if (!mate) return { name: "Mate", avatarColor: "#6c5ce7", avatarStyle: "bottts", avatarSeed: mateId };
803
+ if (!mate) return { name: "Mate", avatarColor: "#5857fc", avatarStyle: "imprint", avatarSeed: mateId };
804
804
  return {
805
805
  name: (mate.profile && mate.profile.displayName) || mate.name || "Mate",
806
- avatarColor: (mate.profile && mate.profile.avatarColor) || "#6c5ce7",
807
- avatarStyle: (mate.profile && mate.profile.avatarStyle) || "bottts",
806
+ avatarColor: (mate.profile && mate.profile.avatarColor) || "#5857fc",
807
+ avatarStyle: (mate.profile && mate.profile.avatarStyle) || "imprint",
808
808
  avatarSeed: (mate.profile && mate.profile.avatarSeed) || mateId,
809
809
  };
810
810
  }
@@ -1391,7 +1391,7 @@ function attachSessions(ctx) {
1391
1391
  type: msg.type,
1392
1392
  userId: u.id,
1393
1393
  displayName: p.name || u.displayName || u.username,
1394
- avatarStyle: p.avatarStyle || "thumbs",
1394
+ avatarStyle: p.avatarStyle || "imprint",
1395
1395
  avatarSeed: p.avatarSeed || u.username,
1396
1396
  avatarCustom: p.avatarCustom || "",
1397
1397
  };
@@ -47,9 +47,9 @@ function attachUserMention(ctx) {
47
47
  var u = ws._clayUser;
48
48
  var p = u.profile || {};
49
49
  return {
50
- style: p.avatarStyle || "thumbs",
50
+ style: p.avatarStyle || "imprint",
51
51
  seed: p.avatarSeed || u.username || u.id,
52
- color: p.avatarColor || "#7c3aed",
52
+ color: p.avatarColor || "#5857fc",
53
53
  custom: p.avatarCustom || "",
54
54
  };
55
55
  }
@@ -63,9 +63,9 @@ function attachUserMention(ctx) {
63
63
  id: u.id,
64
64
  name: p.name || u.displayName || u.username || "User",
65
65
  username: u.username,
66
- avatarStyle: p.avatarStyle || "thumbs",
66
+ avatarStyle: p.avatarStyle || "imprint",
67
67
  avatarSeed: p.avatarSeed || u.username,
68
- avatarColor: p.avatarColor || "#7c3aed",
68
+ avatarColor: p.avatarColor || "#5857fc",
69
69
  };
70
70
  }
71
71
 
package/lib/project.js CHANGED
@@ -344,7 +344,7 @@ function createProjectContext(opts) {
344
344
  id: u.id,
345
345
  displayName: p.name || u.displayName || u.username,
346
346
  username: u.username,
347
- avatarStyle: p.avatarStyle || "thumbs",
347
+ avatarStyle: p.avatarStyle || "imprint",
348
348
  avatarSeed: p.avatarSeed || u.username,
349
349
  avatarCustom: p.avatarCustom || "",
350
350
  });
@@ -1277,8 +1277,9 @@ function createProjectContext(opts) {
1277
1277
  id: u.id,
1278
1278
  displayName: p.name || u.displayName || u.username,
1279
1279
  username: u.username,
1280
- avatarStyle: p.avatarStyle || "thumbs",
1280
+ avatarStyle: p.avatarStyle || "imprint",
1281
1281
  avatarSeed: p.avatarSeed || u.username,
1282
+ avatarColor: p.avatarColor || "#5857fc",
1282
1283
  avatarCustom: p.avatarCustom || "",
1283
1284
  });
1284
1285
  }
@@ -1827,7 +1828,7 @@ function createProjectContext(opts) {
1827
1828
  id: u.id,
1828
1829
  displayName: p.name || u.displayName || u.username,
1829
1830
  username: u.username,
1830
- avatarStyle: p.avatarStyle || "thumbs",
1831
+ avatarStyle: p.avatarStyle || "imprint",
1831
1832
  avatarSeed: p.avatarSeed || u.username,
1832
1833
  avatarCustom: p.avatarCustom || "",
1833
1834
  });
@@ -0,0 +1,46 @@
1
+ /* Clay Imprints use one consistent, pressed-square silhouette everywhere. */
2
+ .activity-inline-avatar,
3
+ .ask-mate-avatar,
4
+ .client-avatar,
5
+ .debate-info-avatar,
6
+ .debate-panel-item-avatar,
7
+ .debate-panelist-avatar,
8
+ .debate-speaker-avatar,
9
+ .delegated-card-avatar,
10
+ .dm-bubble-avatar,
11
+ .dm-header-avatar,
12
+ .dm-msg-avatar,
13
+ .dm-picker-mates-marquee-avatar,
14
+ .dm-user-picker-avatar,
15
+ .home-chat-avatar,
16
+ .home-hub-mate-avatar,
17
+ .icon-strip-me-avatar,
18
+ .icon-strip-user-avatar,
19
+ .input-mention-chip-avatar,
20
+ .mate-collapsed-avatar,
21
+ .mate-mobile-avatar,
22
+ .mate-profile-avatar,
23
+ .mate-sidebar-avatar,
24
+ .mention-avatar,
25
+ .mention-item-avatar,
26
+ .mobile-chat-chip-avatar,
27
+ .notif-banner-avatar,
28
+ .profile-avatar-custom-preview,
29
+ .profile-popover-avatar-img,
30
+ .project-switcher-avatar,
31
+ .remote-cursor-avatar,
32
+ .rewind-avatar,
33
+ .session-presence-avatar,
34
+ .sidebar-presence-avatar,
35
+ .us-account-avatar,
36
+ .us-account-avatar-img,
37
+ .user-island-avatar,
38
+ .user-island-avatar img {
39
+ border-radius: 26% !important;
40
+ }
41
+
42
+ .session-presence-avatar,
43
+ .sidebar-presence-avatar,
44
+ .client-avatar {
45
+ box-shadow: 0 0 0 1px rgba(var(--overlay-rgb), 0.12);
46
+ }
@@ -206,10 +206,10 @@
206
206
  }
207
207
 
208
208
  .icon-strip-item.active::before {
209
- background: var(--bg);
209
+ background: color-mix(in srgb, var(--brand-indigo) 6%, var(--bg));
210
210
  box-shadow:
211
- 0 0 0 1px color-mix(in srgb, var(--link) 62%, var(--border)),
212
- 0 1px 3px rgba(var(--shadow-rgb), 0.16);
211
+ 0 5px 14px color-mix(in srgb, var(--brand-indigo) 28%, transparent),
212
+ 0 1px 3px rgba(var(--shadow-rgb), 0.14);
213
213
  }
214
214
 
215
215
  .icon-strip-item.active {
@@ -18,13 +18,16 @@
18
18
  to { opacity: 1; transform: translateY(0); }
19
19
  }
20
20
 
21
- /* Banner */
21
+ /* Identity header */
22
22
  .profile-banner {
23
23
  height: 52px;
24
24
  position: relative;
25
25
  transition: background 0.2s ease;
26
26
  border-radius: 14px 14px 0 0;
27
27
  z-index: 1;
28
+ background: var(--bg);
29
+ border-top: 3px solid var(--profile-accent, #5857fc);
30
+ border-bottom: 1px solid var(--border);
28
31
  }
29
32
 
30
33
  .profile-close-btn {
@@ -34,8 +37,8 @@
34
37
  width: 24px;
35
38
  height: 24px;
36
39
  border: none;
37
- background: rgba(0, 0, 0, 0.3);
38
- color: #fff;
40
+ background: var(--bg-alt);
41
+ color: var(--text-muted);
39
42
  border-radius: 50%;
40
43
  font-size: 16px;
41
44
  line-height: 1;
@@ -47,7 +50,8 @@
47
50
  }
48
51
 
49
52
  .profile-close-btn:hover {
50
- background: rgba(0, 0, 0, 0.5);
53
+ background: var(--bg-hover, var(--bg-alt));
54
+ color: var(--text);
51
55
  }
52
56
 
53
57
  /* Avatar row (overlaps banner) */
@@ -65,7 +69,7 @@
65
69
  .profile-popover-avatar {
66
70
  width: 60px;
67
71
  height: 60px;
68
- border-radius: 50%;
72
+ border-radius: 17px;
69
73
  display: flex;
70
74
  align-items: center;
71
75
  justify-content: center;
@@ -79,30 +83,7 @@
79
83
  width: 100%;
80
84
  height: 100%;
81
85
  object-fit: cover;
82
- border-radius: 50%;
83
- }
84
-
85
- /* Shuffle button next to Avatar label */
86
- .profile-shuffle-btn {
87
- background: none;
88
- border: none;
89
- padding: 0;
90
- margin-left: 4px;
91
- cursor: pointer;
92
- color: var(--text-muted);
93
- vertical-align: middle;
94
- transition: color 0.15s;
95
- display: inline-flex;
96
- align-items: center;
97
- }
98
-
99
- .profile-shuffle-btn .lucide {
100
- width: 12px;
101
- height: 12px;
102
- }
103
-
104
- .profile-shuffle-btn:hover {
105
- color: var(--text);
86
+ border-radius: 14px;
106
87
  }
107
88
 
108
89
  .profile-name-display {
@@ -202,66 +183,140 @@
202
183
  border-color: var(--accent);
203
184
  }
204
185
 
205
- /* Avatar style grid */
206
- .profile-avatar-grid {
207
- display: grid;
208
- grid-template-columns: repeat(4, 1fr);
209
- gap: 6px;
186
+ /* Clay Imprint identity control */
187
+ .profile-imprint-panel {
188
+ border: 1px solid var(--border);
189
+ border-radius: 12px;
190
+ background: var(--bg);
191
+ padding: 9px;
210
192
  }
211
193
 
212
- .profile-avatar-option {
213
- width: 100%;
214
- aspect-ratio: 1;
215
- border-radius: 10px;
216
- border: 2px solid var(--border);
217
- background: var(--bg);
218
- cursor: pointer;
219
- padding: 3px;
220
- overflow: hidden;
194
+ .profile-imprint-preview {
221
195
  display: flex;
222
196
  align-items: center;
223
- justify-content: center;
224
- transition: border-color 0.15s, transform 0.1s;
197
+ gap: 10px;
198
+ min-height: 54px;
225
199
  }
226
200
 
227
- .profile-avatar-option img {
228
- width: 100%;
229
- height: 100%;
230
- object-fit: contain;
231
- border-radius: 6px;
201
+ .profile-imprint-preview img {
202
+ width: 50px;
203
+ height: 50px;
204
+ border-radius: 13px;
205
+ flex: 0 0 auto;
232
206
  }
233
207
 
234
- .profile-avatar-option:hover {
235
- border-color: var(--text-muted);
236
- transform: scale(1.05);
208
+ .profile-imprint-preview span {
209
+ display: flex;
210
+ flex-direction: column;
211
+ gap: 2px;
212
+ min-width: 0;
237
213
  }
238
214
 
239
- .profile-avatar-option.profile-avatar-option-active {
240
- border-color: var(--accent);
241
- box-shadow: 0 0 0 1px var(--accent);
215
+ .profile-imprint-preview strong {
216
+ color: var(--text);
217
+ font-size: 12px;
218
+ font-weight: 650;
219
+ }
220
+
221
+ .profile-imprint-preview small {
222
+ color: var(--text-dimmer);
223
+ font-size: 10px;
224
+ }
225
+
226
+ .profile-imprint-actions {
227
+ display: grid;
228
+ grid-template-columns: 1fr 1fr;
229
+ gap: 5px;
230
+ margin-top: 8px;
242
231
  }
243
232
 
244
- /* Avatar upload button */
245
- .profile-avatar-upload .profile-avatar-upload-icon {
233
+ .profile-imprint-actions button {
234
+ min-width: 0;
235
+ height: 28px;
236
+ padding: 0 8px;
237
+ border: 1px solid var(--border);
238
+ border-radius: 7px;
239
+ background: var(--bg-alt);
240
+ color: var(--text-muted);
241
+ cursor: pointer;
242
+ font-size: 10px;
243
+ font-weight: 600;
244
+ white-space: nowrap;
246
245
  display: flex;
247
246
  align-items: center;
248
247
  justify-content: center;
249
- width: 100%;
250
- height: 100%;
251
- color: var(--text-muted);
248
+ gap: 4px;
249
+ transition: border-color 0.15s, color 0.15s, background 0.15s;
252
250
  }
253
- .profile-avatar-upload .profile-avatar-upload-icon svg {
254
- width: 24px;
255
- height: 24px;
251
+
252
+ .profile-imprint-actions button:hover {
253
+ color: var(--text);
254
+ border-color: var(--text-muted);
256
255
  }
257
- .profile-avatar-upload:hover .profile-avatar-upload-icon {
256
+
257
+ .profile-imprint-actions button.is-active {
258
258
  color: var(--text);
259
+ border-color: var(--accent);
260
+ box-shadow: inset 0 0 0 1px var(--accent);
261
+ }
262
+
263
+ .profile-imprint-actions button .lucide {
264
+ width: 11px;
265
+ height: 11px;
266
+ }
267
+
268
+ .profile-avatar-upload {
269
+ grid-column: 1 / -1;
270
+ }
271
+
272
+ .profile-mate-mark-actions .profile-avatar-upload {
273
+ grid-column: auto;
274
+ }
275
+
276
+ .profile-avatar-upload.is-active::before {
277
+ content: "";
278
+ width: 5px;
279
+ height: 5px;
280
+ border-radius: 50%;
281
+ background: var(--accent);
259
282
  }
283
+
260
284
  .profile-avatar-custom-preview {
261
285
  width: 100%;
262
286
  height: 100%;
263
287
  object-fit: cover;
264
- border-radius: 6px;
288
+ border-radius: 12px;
289
+ }
290
+
291
+ .profile-use-imprint.is-active::before {
292
+ content: "";
293
+ width: 5px;
294
+ height: 5px;
295
+ border-radius: 50%;
296
+ background: var(--accent);
297
+ }
298
+
299
+ .profile-imprint-actions button:focus-visible {
300
+ outline: 2px solid var(--accent);
301
+ outline-offset: 2px;
302
+ }
303
+
304
+ .profile-imprint-actions button:active {
305
+ transform: translateY(1px);
306
+ }
307
+
308
+ .profile-imprint-actions button:disabled {
309
+ opacity: 0.45;
310
+ cursor: default;
311
+ }
312
+
313
+ .profile-imprint-actions button:disabled:hover {
314
+ border-color: var(--border);
315
+ color: var(--text-muted);
316
+ }
317
+
318
+ .profile-imprint-actions button.is-active:hover {
319
+ color: var(--text);
265
320
  }
266
321
 
267
322
  /* Avatar positioner overlay */
@@ -297,7 +352,7 @@
297
352
  color: var(--text-muted);
298
353
  font-size: 20px;
299
354
  cursor: pointer;
300
- border-radius: 50%;
355
+ border-radius: 28px;
301
356
  display: flex;
302
357
  align-items: center;
303
358
  justify-content: center;
@@ -313,7 +368,7 @@
313
368
  color: var(--text);
314
369
  }
315
370
  .avatar-positioner-viewport {
316
- border-radius: 50%;
371
+ border-radius: 26%;
317
372
  overflow: hidden;
318
373
  position: relative;
319
374
  cursor: grab;
@@ -368,30 +423,3 @@
368
423
  .avatar-positioner-btn-done:hover {
369
424
  filter: brightness(1.1);
370
425
  }
371
-
372
- /* Color swatch grid */
373
- .profile-color-grid {
374
- display: flex;
375
- flex-wrap: wrap;
376
- gap: 6px;
377
- }
378
-
379
- .profile-color-swatch {
380
- width: 22px;
381
- height: 22px;
382
- border-radius: 50%;
383
- border: 2px solid transparent;
384
- cursor: pointer;
385
- transition: transform 0.15s, border-color 0.15s;
386
- padding: 0;
387
- }
388
-
389
- .profile-color-swatch:hover {
390
- transform: scale(1.15);
391
- }
392
-
393
- .profile-color-swatch.profile-color-active {
394
- border-color: #fff;
395
- box-shadow: 0 0 0 2px var(--accent);
396
- }
397
-
@@ -2,23 +2,29 @@
2
2
  display: inline-flex;
3
3
  align-items: center;
4
4
  justify-content: center;
5
- width: 28px;
5
+ gap: 6px;
6
+ width: auto;
6
7
  height: 28px;
7
- padding: 0;
8
- border: 1px solid transparent;
8
+ margin: 0;
9
+ padding: 0 9px;
10
+ border: 1px solid var(--border-subtle);
9
11
  border-radius: 8px;
10
- background: transparent;
11
- color: var(--text-dimmer);
12
+ background: color-mix(in srgb, var(--brand-indigo) 5%, var(--bg));
13
+ color: var(--text-secondary);
12
14
  cursor: pointer;
13
15
  flex-shrink: 0;
16
+ font: inherit;
17
+ font-size: 11px;
18
+ font-weight: 650;
19
+ white-space: nowrap;
14
20
  transition: color 0.15s, background 0.15s, border-color 0.15s;
15
21
  }
16
22
 
17
23
  #header-session-actions-btn:hover,
18
24
  #header-session-actions-btn[aria-expanded="true"] {
19
25
  color: var(--text);
20
- background: rgba(var(--overlay-rgb), 0.05);
21
- border-color: var(--border);
26
+ background: color-mix(in srgb, var(--brand-indigo) 9%, var(--bg));
27
+ border-color: color-mix(in srgb, var(--brand-indigo) 32%, var(--border));
22
28
  }
23
29
 
24
30
  #header-session-actions-btn:focus { outline: none; }
@@ -28,12 +34,26 @@
28
34
  }
29
35
 
30
36
  #header-session-actions-btn.hidden { display: none; }
31
- #header-session-actions-btn .lucide { width: 16px; height: 16px; }
37
+ #header-session-actions-btn .lucide:first-child {
38
+ width: 14px;
39
+ height: 14px;
40
+ color: color-mix(in srgb, var(--brand-indigo) 78%, var(--text));
41
+ }
42
+
43
+ #header-session-actions-btn .session-actions-trigger-chevron {
44
+ width: 13px;
45
+ height: 13px;
46
+ transition: transform 0.16s ease;
47
+ }
48
+
49
+ #header-session-actions-btn[aria-expanded="true"] .session-actions-trigger-chevron {
50
+ transform: rotate(180deg);
51
+ }
32
52
 
33
53
  .session-actions-menu {
34
54
  position: fixed;
35
55
  z-index: 10020;
36
- width: 286px;
56
+ width: min(300px, calc(100vw - 16px));
37
57
  padding: 6px;
38
58
  border: 1px solid var(--border);
39
59
  border-radius: 12px;
@@ -63,6 +83,17 @@
63
83
  }
64
84
 
65
85
  .session-actions-row:hover { background: var(--bg-alt); }
86
+ .session-actions-row.is-primary {
87
+ background: color-mix(in srgb, var(--brand-indigo) 6%, transparent);
88
+ }
89
+ .session-actions-row.is-primary:hover {
90
+ background: color-mix(in srgb, var(--brand-indigo) 10%, transparent);
91
+ }
92
+ .session-actions-row.is-primary .session-actions-row-icon {
93
+ border-color: transparent;
94
+ background: var(--brand-indigo);
95
+ color: var(--brand-paper);
96
+ }
66
97
  .session-actions-row:disabled { cursor: default; opacity: 0.42; }
67
98
  .session-actions-row:disabled:hover { background: transparent; }
68
99
 
@@ -342,7 +342,7 @@
342
342
  flex-shrink: 0;
343
343
  width: 56px;
344
344
  height: 56px;
345
- border-radius: 50%;
345
+ border-radius: 26%;
346
346
  overflow: hidden;
347
347
  border: 1px solid rgba(var(--overlay-rgb), 0.1);
348
348
  background: var(--bg);
@@ -388,8 +388,8 @@
388
388
  <div id="ralph-sticky" class="hidden"></div>
389
389
  <div id="debate-sticky" class="hidden"></div>
390
390
  <div class="status">
391
- <button id="header-session-actions-btn" type="button" aria-label="Session actions" title="Session actions" aria-haspopup="menu" aria-expanded="false">
392
- <i data-lucide="ellipsis"></i>
391
+ <button id="header-session-actions-btn" type="button" aria-label="Session actions" aria-haspopup="menu" aria-expanded="false">
392
+ <i data-lucide="bot"></i><span>Add AI worker</span><i class="session-actions-trigger-chevron" data-lucide="chevron-down"></i>
393
393
  </button>
394
394
  <button type="button" id="header-tui-font-btn" class="header-tui-font-btn hidden" title="Terminal font" aria-label="Terminal font">
395
395
  <i data-lucide="type"></i>