@mooncompany/uplink-chat 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @mooncompany/uplink-chat might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/bin/uplink.js +279 -0
- package/middleware/error-handler.js +69 -0
- package/package.json +93 -0
- package/public/css/agents.36b98c0f.css +1469 -0
- package/public/css/agents.css +1469 -0
- package/public/css/app.a6a7f8f5.css +2731 -0
- package/public/css/app.css +2731 -0
- package/public/css/artifacts.css +444 -0
- package/public/css/commands.css +55 -0
- package/public/css/connection.css +131 -0
- package/public/css/dashboard.css +233 -0
- package/public/css/developer.css +328 -0
- package/public/css/files.css +123 -0
- package/public/css/markdown.css +156 -0
- package/public/css/message-actions.css +278 -0
- package/public/css/mobile.css +614 -0
- package/public/css/panels-unified.css +483 -0
- package/public/css/premium.css +415 -0
- package/public/css/realtime.css +189 -0
- package/public/css/satellites.css +401 -0
- package/public/css/shortcuts.css +185 -0
- package/public/css/split-view.4def0262.css +673 -0
- package/public/css/split-view.css +673 -0
- package/public/css/theme-generator.css +391 -0
- package/public/css/themes.css +387 -0
- package/public/css/timestamps.css +54 -0
- package/public/css/variables.css +78 -0
- package/public/dist/bundle.b55050c4.js +15757 -0
- package/public/favicon.svg +24 -0
- package/public/img/agents/ada.png +0 -0
- package/public/img/agents/clarice.png +0 -0
- package/public/img/agents/dennis-nedry.png +0 -0
- package/public/img/agents/elliot-alderson.png +0 -0
- package/public/img/agents/main.png +0 -0
- package/public/img/agents/scotty.png +0 -0
- package/public/img/agents/top-flight-security.png +0 -0
- package/public/index.html +1083 -0
- package/public/js/agents-data.js +234 -0
- package/public/js/agents-ui.js +72 -0
- package/public/js/agents.js +1525 -0
- package/public/js/app.js +79 -0
- package/public/js/appearance-settings.js +111 -0
- package/public/js/artifacts.js +432 -0
- package/public/js/audio-queue.js +168 -0
- package/public/js/bootstrap.js +54 -0
- package/public/js/chat.js +1211 -0
- package/public/js/commands.js +581 -0
- package/public/js/connection-api.js +121 -0
- package/public/js/connection.js +1231 -0
- package/public/js/context-tracker.js +271 -0
- package/public/js/core.js +172 -0
- package/public/js/dashboard.js +452 -0
- package/public/js/developer.js +432 -0
- package/public/js/encryption.js +124 -0
- package/public/js/errors.js +122 -0
- package/public/js/event-bus.js +77 -0
- package/public/js/fetch-utils.js +171 -0
- package/public/js/file-handler.js +229 -0
- package/public/js/files.js +352 -0
- package/public/js/gateway-chat.js +538 -0
- package/public/js/logger.js +112 -0
- package/public/js/markdown.js +190 -0
- package/public/js/message-actions.js +431 -0
- package/public/js/message-renderer.js +288 -0
- package/public/js/missed-messages.js +235 -0
- package/public/js/mobile-debug.js +95 -0
- package/public/js/notifications.js +367 -0
- package/public/js/offline-queue.js +178 -0
- package/public/js/onboarding.js +543 -0
- package/public/js/panels.js +156 -0
- package/public/js/premium.js +412 -0
- package/public/js/realtime-voice.js +844 -0
- package/public/js/satellite-sync.js +256 -0
- package/public/js/satellite-ui.js +175 -0
- package/public/js/satellites.js +1516 -0
- package/public/js/settings.js +1087 -0
- package/public/js/shortcuts.js +381 -0
- package/public/js/split-chat.js +1234 -0
- package/public/js/split-resize.js +211 -0
- package/public/js/splitview.js +340 -0
- package/public/js/storage.js +408 -0
- package/public/js/streaming-handler.js +324 -0
- package/public/js/stt-settings.js +316 -0
- package/public/js/theme-generator.js +661 -0
- package/public/js/themes.js +164 -0
- package/public/js/timestamps.js +198 -0
- package/public/js/tts-settings.js +575 -0
- package/public/js/ui.js +267 -0
- package/public/js/update-notifier.js +143 -0
- package/public/js/utils/constants.js +165 -0
- package/public/js/utils/sanitize.js +93 -0
- package/public/js/utils/sse-parser.js +195 -0
- package/public/js/voice.js +883 -0
- package/public/manifest.json +58 -0
- package/public/moon_texture.jpg +0 -0
- package/public/sw.js +221 -0
- package/public/three.min.js +6 -0
- package/server/channel.js +529 -0
- package/server/chat.js +270 -0
- package/server/config-store.js +362 -0
- package/server/config.js +159 -0
- package/server/context.js +131 -0
- package/server/gateway-commands.js +211 -0
- package/server/gateway-proxy.js +318 -0
- package/server/index.js +22 -0
- package/server/logger.js +89 -0
- package/server/middleware/auth.js +188 -0
- package/server/middleware.js +218 -0
- package/server/openclaw-discover.js +308 -0
- package/server/premium/index.js +156 -0
- package/server/premium/license.js +140 -0
- package/server/realtime/bridge.js +837 -0
- package/server/realtime/index.js +349 -0
- package/server/realtime/tts-stream.js +446 -0
- package/server/routes/agents.js +564 -0
- package/server/routes/artifacts.js +174 -0
- package/server/routes/chat.js +311 -0
- package/server/routes/config-settings.js +345 -0
- package/server/routes/config.js +603 -0
- package/server/routes/files.js +307 -0
- package/server/routes/index.js +18 -0
- package/server/routes/media.js +451 -0
- package/server/routes/missed-messages.js +107 -0
- package/server/routes/premium.js +75 -0
- package/server/routes/push.js +156 -0
- package/server/routes/satellite.js +406 -0
- package/server/routes/status.js +251 -0
- package/server/routes/stt.js +35 -0
- package/server/routes/voice.js +260 -0
- package/server/routes/webhooks.js +203 -0
- package/server/routes.js +206 -0
- package/server/runtime-config.js +336 -0
- package/server/share.js +305 -0
- package/server/stt/faster-whisper.js +72 -0
- package/server/stt/groq.js +51 -0
- package/server/stt/index.js +196 -0
- package/server/stt/openai.js +49 -0
- package/server/sync.js +244 -0
- package/server/tailscale-https.js +175 -0
- package/server/tts.js +646 -0
- package/server/update-checker.js +172 -0
- package/server/utils/filename.js +129 -0
- package/server/utils.js +147 -0
- package/server/watchdog.js +318 -0
- package/server/websocket/broadcast.js +359 -0
- package/server/websocket/connections.js +339 -0
- package/server/websocket/index.js +215 -0
- package/server/websocket/routing.js +277 -0
- package/server/websocket/sync.js +102 -0
- package/server.js +404 -0
- package/utils/detect-tool-usage.js +93 -0
- package/utils/errors.js +158 -0
- package/utils/html-escape.js +84 -0
- package/utils/id-sanitize.js +94 -0
- package/utils/response.js +130 -0
- package/utils/with-retry.js +105 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
THEME SYSTEM
|
|
3
|
+
|
|
4
|
+
How it works:
|
|
5
|
+
- :root in app.css defines the default theme (Midnight)
|
|
6
|
+
- Each [data-theme] block overrides ONLY the color variables
|
|
7
|
+
- Starfield bg stays black (#000), stars stay white across all dark themes
|
|
8
|
+
- Daylight (light mode) hides starfield entirely
|
|
9
|
+
- JS sets data-theme on <html> and saves to localStorage
|
|
10
|
+
============================================ */
|
|
11
|
+
|
|
12
|
+
/* ── Midnight (Default) ──
|
|
13
|
+
Values live in :root in app.css. This block is a reference only. */
|
|
14
|
+
:root[data-theme="midnight"] {
|
|
15
|
+
/* All defaults — no overrides needed */
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* ── Daylight (Light Mode) ──
|
|
19
|
+
Warm light theme — soft white, washed red accent */
|
|
20
|
+
:root[data-theme="daylight"] {
|
|
21
|
+
--bg: #f8f5f1;
|
|
22
|
+
--bg-secondary: rgba(252, 249, 244, 0.95);
|
|
23
|
+
--bg-input: rgba(0, 0, 0, 0.03);
|
|
24
|
+
--accent: #c84b4b;
|
|
25
|
+
--accent-hover: #a93d3d;
|
|
26
|
+
--accent-secondary: #e06060;
|
|
27
|
+
--text: #1a1a1a;
|
|
28
|
+
--text-muted: #737373;
|
|
29
|
+
--text-dim: #a3a3a3;
|
|
30
|
+
--text-inverse: #f8f5f1;
|
|
31
|
+
--border: rgba(0, 0, 0, 0.08);
|
|
32
|
+
|
|
33
|
+
--accent-05: rgba(200, 75, 75, 0.05);
|
|
34
|
+
--accent-10: rgba(200, 75, 75, 0.1);
|
|
35
|
+
--accent-15: rgba(200, 75, 75, 0.15);
|
|
36
|
+
--accent-20: rgba(200, 75, 75, 0.2);
|
|
37
|
+
--accent-30: rgba(200, 75, 75, 0.3);
|
|
38
|
+
--accent-40: rgba(200, 75, 75, 0.4);
|
|
39
|
+
--accent-50: rgba(200, 75, 75, 0.5);
|
|
40
|
+
|
|
41
|
+
--error-10: rgba(220, 38, 38, 0.08);
|
|
42
|
+
--error-20: rgba(220, 38, 38, 0.12);
|
|
43
|
+
--error-30: rgba(220, 38, 38, 0.2);
|
|
44
|
+
--success-20: rgba(22, 163, 74, 0.1);
|
|
45
|
+
|
|
46
|
+
--user-bubble: rgba(200, 75, 75, 0.33);
|
|
47
|
+
--user-accent: rgba(200, 75, 75, 0.38);
|
|
48
|
+
--user-accent-hover: rgba(200, 75, 75, 0.25);
|
|
49
|
+
--assistant-bubble: rgba(0, 0, 0, 0.11);
|
|
50
|
+
|
|
51
|
+
--success: #16a34a;
|
|
52
|
+
--warning: #d97706;
|
|
53
|
+
--info: #2563eb;
|
|
54
|
+
--recording: #dc2626;
|
|
55
|
+
--error: #dc2626;
|
|
56
|
+
--neutral: #737373;
|
|
57
|
+
|
|
58
|
+
--star-color: #fff;
|
|
59
|
+
|
|
60
|
+
--syntax-keyword: #7c3aed;
|
|
61
|
+
--syntax-string: #16a34a;
|
|
62
|
+
--syntax-comment: #a3a3a3;
|
|
63
|
+
--syntax-number: #c84b4b;
|
|
64
|
+
|
|
65
|
+
--black-20: rgba(0, 0, 0, 0.06);
|
|
66
|
+
--black-40: rgba(0, 0, 0, 0.1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* ── Ember ──
|
|
70
|
+
Deep fire theme — dark navy base, crimson surfaces, amber/yellow accents
|
|
71
|
+
Palette: #03071e #370617 #6a040f #9d0208 #d00000 #dc2f02 #e85d04 #f48c06 #faa307 #ffba08 */
|
|
72
|
+
:root[data-theme="ember"] {
|
|
73
|
+
--bg: #03071e;
|
|
74
|
+
--bg-secondary: rgba(55, 6, 23, 0.95);
|
|
75
|
+
--bg-input: rgba(106, 4, 15, 0.3);
|
|
76
|
+
--accent: #f48c06;
|
|
77
|
+
--accent-hover: #faa307;
|
|
78
|
+
--accent-secondary: #ffba08;
|
|
79
|
+
--text: #fce8d0;
|
|
80
|
+
--text-muted: #c8906a;
|
|
81
|
+
--text-dim: #8a5a3a;
|
|
82
|
+
--text-inverse: #03071e;
|
|
83
|
+
--border: rgba(244, 140, 6, 0.15);
|
|
84
|
+
|
|
85
|
+
--accent-05: rgba(244, 140, 6, 0.05);
|
|
86
|
+
--accent-10: rgba(244, 140, 6, 0.1);
|
|
87
|
+
--accent-15: rgba(244, 140, 6, 0.15);
|
|
88
|
+
--accent-20: rgba(244, 140, 6, 0.2);
|
|
89
|
+
--accent-30: rgba(244, 140, 6, 0.3);
|
|
90
|
+
--accent-40: rgba(244, 140, 6, 0.4);
|
|
91
|
+
--accent-50: rgba(244, 140, 6, 0.5);
|
|
92
|
+
|
|
93
|
+
--error-10: rgba(208, 0, 0, 0.15);
|
|
94
|
+
--error-20: rgba(208, 0, 0, 0.25);
|
|
95
|
+
--error-30: rgba(208, 0, 0, 0.35);
|
|
96
|
+
--success-20: rgba(74, 222, 128, 0.2);
|
|
97
|
+
|
|
98
|
+
--user-bubble: rgba(157, 2, 8, 0.3);
|
|
99
|
+
--user-accent: #9d0208;
|
|
100
|
+
--user-accent-hover: #6a040f;
|
|
101
|
+
--assistant-bubble: rgba(46, 33, 33, 0.98);
|
|
102
|
+
|
|
103
|
+
--success: #4ade80;
|
|
104
|
+
--warning: #ffba08;
|
|
105
|
+
--info: #60a5fa;
|
|
106
|
+
--recording: #d00000;
|
|
107
|
+
--error: #d00000;
|
|
108
|
+
--neutral: #8a5a3a;
|
|
109
|
+
|
|
110
|
+
--star-color: #f48c06;
|
|
111
|
+
|
|
112
|
+
--syntax-keyword: #faa307;
|
|
113
|
+
--syntax-string: #ffba08;
|
|
114
|
+
--syntax-comment: #6a040f;
|
|
115
|
+
--syntax-number: #e85d04;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* ── Forest ──
|
|
119
|
+
Deep earthy dark theme — dark woodland greens, muted sage accents
|
|
120
|
+
Palette: #dad7cd #a3b18a #588157 #3a5a40 #344e41 */
|
|
121
|
+
:root[data-theme="forest"] {
|
|
122
|
+
--bg: #131813;
|
|
123
|
+
--bg-secondary: rgba(34, 44, 34, 0.95);
|
|
124
|
+
--bg-input: rgba(52, 78, 65, 0.25);
|
|
125
|
+
--accent: #a3b18a;
|
|
126
|
+
--accent-hover: #dad7cd;
|
|
127
|
+
--accent-secondary: #588157;
|
|
128
|
+
--text: #dad7cd;
|
|
129
|
+
--text-muted: #8a9a7a;
|
|
130
|
+
--text-dim: #5a6e4a;
|
|
131
|
+
--text-inverse: #1a1f1a;
|
|
132
|
+
--border: rgba(163, 177, 138, 0.15);
|
|
133
|
+
|
|
134
|
+
--accent-05: rgba(163, 177, 138, 0.05);
|
|
135
|
+
--accent-10: rgba(163, 177, 138, 0.1);
|
|
136
|
+
--accent-15: rgba(163, 177, 138, 0.15);
|
|
137
|
+
--accent-20: rgba(163, 177, 138, 0.2);
|
|
138
|
+
--accent-30: rgba(163, 177, 138, 0.3);
|
|
139
|
+
--accent-40: rgba(163, 177, 138, 0.4);
|
|
140
|
+
--accent-50: rgba(163, 177, 138, 0.5);
|
|
141
|
+
|
|
142
|
+
--error-10: rgba(239, 68, 68, 0.1);
|
|
143
|
+
--error-20: rgba(239, 68, 68, 0.2);
|
|
144
|
+
--error-30: rgba(239, 68, 68, 0.3);
|
|
145
|
+
--success-20: rgba(88, 129, 87, 0.25);
|
|
146
|
+
|
|
147
|
+
--user-bubble: rgba(58, 90, 64, 0.3);
|
|
148
|
+
--user-accent: #3a5a40;
|
|
149
|
+
--user-accent-hover: #344e41;
|
|
150
|
+
--assistant-bubble: rgba(46, 43, 35, 0.63);
|
|
151
|
+
|
|
152
|
+
--success: #a3b18a;
|
|
153
|
+
--warning: #d4a746;
|
|
154
|
+
--info: #60a5fa;
|
|
155
|
+
--recording: #ff3366;
|
|
156
|
+
--error: #ef4444;
|
|
157
|
+
--neutral: #6b7280;
|
|
158
|
+
|
|
159
|
+
--star-color: #a3b18a;
|
|
160
|
+
|
|
161
|
+
--syntax-keyword: #dad7cd;
|
|
162
|
+
--syntax-string: #a3b18a;
|
|
163
|
+
--syntax-comment: #3a5a40;
|
|
164
|
+
--syntax-number: #588157;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* ── Phantom ──
|
|
168
|
+
Monochrome grayscale — no color accent */
|
|
169
|
+
:root[data-theme="phantom"] {
|
|
170
|
+
--bg: #000;
|
|
171
|
+
--bg-secondary: rgba(20, 20, 20, 0.95);
|
|
172
|
+
--bg-input: rgba(30, 30, 30, 0.8);
|
|
173
|
+
--accent: #a0a0a0;
|
|
174
|
+
--accent-hover: #c0c0c0;
|
|
175
|
+
--accent-secondary: #808080;
|
|
176
|
+
--text: #e8e8e8;
|
|
177
|
+
--text-muted: #909090;
|
|
178
|
+
--text-dim: #707070;
|
|
179
|
+
--text-inverse: #0a0a0a;
|
|
180
|
+
--border: var(--accent-15);
|
|
181
|
+
|
|
182
|
+
--accent-05: rgba(160, 160, 160, 0.05);
|
|
183
|
+
--accent-10: rgba(160, 160, 160, 0.1);
|
|
184
|
+
--accent-15: rgba(160, 160, 160, 0.15);
|
|
185
|
+
--accent-20: rgba(160, 160, 160, 0.2);
|
|
186
|
+
--accent-30: rgba(160, 160, 160, 0.3);
|
|
187
|
+
--accent-40: rgba(160, 160, 160, 0.4);
|
|
188
|
+
--accent-50: rgba(160, 160, 160, 0.5);
|
|
189
|
+
|
|
190
|
+
--error-10: rgba(239, 68, 68, 0.1);
|
|
191
|
+
--error-20: rgba(239, 68, 68, 0.2);
|
|
192
|
+
--error-30: rgba(239, 68, 68, 0.3);
|
|
193
|
+
--success-20: rgba(74, 222, 128, 0.2);
|
|
194
|
+
|
|
195
|
+
--user-bubble: rgba(60, 60, 60, 0.4);
|
|
196
|
+
--user-accent: #404040;
|
|
197
|
+
--user-accent-hover: #333333;
|
|
198
|
+
--assistant-bubble: #161f25;
|
|
199
|
+
|
|
200
|
+
--success: #4ade80;
|
|
201
|
+
--warning: #fbbf24;
|
|
202
|
+
--info: #60a5fa;
|
|
203
|
+
--recording: #ff3366;
|
|
204
|
+
--error: #ef4444;
|
|
205
|
+
--neutral: #6b7280;
|
|
206
|
+
|
|
207
|
+
--star-color: #fff;
|
|
208
|
+
|
|
209
|
+
--syntax-keyword: #b0b0b0;
|
|
210
|
+
--syntax-string: #909090;
|
|
211
|
+
--syntax-comment: #505050;
|
|
212
|
+
--syntax-number: #c0c0c0;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* ============================================
|
|
216
|
+
DAYLIGHT (LIGHT MODE) OVERRIDES
|
|
217
|
+
These need component-level selectors since
|
|
218
|
+
light mode changes more than just colors.
|
|
219
|
+
============================================ */
|
|
220
|
+
|
|
221
|
+
/* Hide starfield in light themes */
|
|
222
|
+
:root[data-theme="daylight"] #stars,
|
|
223
|
+
:root[data-theme="forest"] #stars {
|
|
224
|
+
display: none;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* Light mode needs opaque .app background */
|
|
228
|
+
:root[data-theme="daylight"] .app {
|
|
229
|
+
background: var(--bg);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* Message bubbles need subtle borders in light mode */
|
|
233
|
+
:root[data-theme="daylight"] .assistant-message .message-content {
|
|
234
|
+
border: 1px solid var(--border);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
:root[data-theme="daylight"] .user-message .message-content {
|
|
238
|
+
border: 1px solid rgba(200, 75, 75, 0.1);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* Override the hardcoded purple border on user bubbles */
|
|
242
|
+
:root[data-theme="daylight"] .message.user {
|
|
243
|
+
border-color: rgba(200, 75, 75, 0.12);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Panels need subtle shadow instead of glow */
|
|
247
|
+
:root[data-theme="daylight"] .settings-panel,
|
|
248
|
+
:root[data-theme="daylight"] .panel,
|
|
249
|
+
:root[data-theme="daylight"] .dev-panel {
|
|
250
|
+
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
|
|
251
|
+
border-color: rgba(0, 0, 0, 0.1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Input fields need visible borders */
|
|
255
|
+
:root[data-theme="daylight"] .setting-input,
|
|
256
|
+
:root[data-theme="daylight"] .setting-select,
|
|
257
|
+
:root[data-theme="daylight"] #messageInput {
|
|
258
|
+
border-color: rgba(0, 0, 0, 0.1);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* Header — barely-there warm tint */
|
|
262
|
+
:root[data-theme="daylight"] .main-header {
|
|
263
|
+
background: rgba(0, 0, 0, 0.02);
|
|
264
|
+
border-bottom: 1px solid var(--border);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Code blocks — subtle warm gray */
|
|
268
|
+
:root[data-theme="daylight"] pre,
|
|
269
|
+
:root[data-theme="daylight"] code {
|
|
270
|
+
background: rgba(0, 0, 0, 0.035);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
:root[data-theme="daylight"] pre {
|
|
274
|
+
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/* ============================================
|
|
278
|
+
EMBER OVERRIDES — Rising ember sparks
|
|
279
|
+
============================================ */
|
|
280
|
+
:root[data-theme="ember"] .star {
|
|
281
|
+
animation: ember-rise var(--duration) linear infinite !important;
|
|
282
|
+
animation-duration: calc(var(--duration) * 4) !important;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
@keyframes ember-rise {
|
|
286
|
+
0% {
|
|
287
|
+
opacity: 0;
|
|
288
|
+
transform: translateY(0) translateX(0) scale(0.8);
|
|
289
|
+
}
|
|
290
|
+
5% {
|
|
291
|
+
opacity: var(--opacity);
|
|
292
|
+
transform: translateY(-10px) translateX(2px) scale(1);
|
|
293
|
+
}
|
|
294
|
+
25% {
|
|
295
|
+
opacity: var(--opacity);
|
|
296
|
+
transform: translateY(-50px) translateX(8px) scale(0.9);
|
|
297
|
+
}
|
|
298
|
+
50% {
|
|
299
|
+
opacity: calc(var(--opacity) * 0.7);
|
|
300
|
+
transform: translateY(-100px) translateX(-3px) scale(0.7);
|
|
301
|
+
}
|
|
302
|
+
75% {
|
|
303
|
+
opacity: calc(var(--opacity) * 0.3);
|
|
304
|
+
transform: translateY(-150px) translateX(10px) scale(0.4);
|
|
305
|
+
}
|
|
306
|
+
95% {
|
|
307
|
+
opacity: 0;
|
|
308
|
+
transform: translateY(-180px) translateX(5px) scale(0.2);
|
|
309
|
+
}
|
|
310
|
+
100% {
|
|
311
|
+
opacity: 0;
|
|
312
|
+
transform: translateY(0) translateX(0) scale(0.8);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/* ============================================
|
|
317
|
+
EMBER (DARK MODE) OVERRIDES
|
|
318
|
+
Ember uses a non-black bg, so starfield stars
|
|
319
|
+
need to be amber-tinted (handled via --star-color)
|
|
320
|
+
============================================ */
|
|
321
|
+
|
|
322
|
+
/* ============================================
|
|
323
|
+
THEME PICKER — Visual theme selector
|
|
324
|
+
Replaces the plain <select> dropdown
|
|
325
|
+
============================================ */
|
|
326
|
+
|
|
327
|
+
.theme-picker {
|
|
328
|
+
display: flex;
|
|
329
|
+
flex-wrap: wrap;
|
|
330
|
+
gap: 6px;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.theme-picker-item {
|
|
334
|
+
display: flex;
|
|
335
|
+
align-items: center;
|
|
336
|
+
gap: 7px;
|
|
337
|
+
padding: 5px 10px 5px 6px;
|
|
338
|
+
border-radius: 8px;
|
|
339
|
+
border: 1.5px solid transparent;
|
|
340
|
+
background: rgba(255, 255, 255, 0.04);
|
|
341
|
+
cursor: pointer;
|
|
342
|
+
transition: background 0.15s, border-color 0.15s, transform 0.1s;
|
|
343
|
+
user-select: none;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.theme-picker-item:hover {
|
|
347
|
+
background: rgba(255, 255, 255, 0.08);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.theme-picker-item.active {
|
|
351
|
+
border-color: var(--accent);
|
|
352
|
+
background: var(--accent-10);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.theme-picker-item[data-premium-locked="true"] {
|
|
356
|
+
opacity: 0.45;
|
|
357
|
+
cursor: default;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.theme-picker-item[data-premium-locked="true"]:hover {
|
|
361
|
+
background: rgba(255, 255, 255, 0.04);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.theme-picker-swatch {
|
|
365
|
+
width: 18px;
|
|
366
|
+
height: 18px;
|
|
367
|
+
border-radius: 5px;
|
|
368
|
+
flex-shrink: 0;
|
|
369
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.theme-picker-name {
|
|
373
|
+
font-size: 0.72rem;
|
|
374
|
+
font-weight: 500;
|
|
375
|
+
color: var(--text-muted);
|
|
376
|
+
white-space: nowrap;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.theme-picker-item.active .theme-picker-name {
|
|
380
|
+
color: var(--text);
|
|
381
|
+
font-weight: 600;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.theme-picker-lock {
|
|
385
|
+
font-size: 0.6rem;
|
|
386
|
+
opacity: 0.6;
|
|
387
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
TIMESTAMPS STYLES
|
|
3
|
+
Inline with bottom of bubble, outside
|
|
4
|
+
============================================ */
|
|
5
|
+
|
|
6
|
+
/* Message needs relative positioning for timestamp */
|
|
7
|
+
.message.show-timestamp {
|
|
8
|
+
position: relative;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* Timestamp element — hidden by default */
|
|
12
|
+
.message-timestamp {
|
|
13
|
+
display: none;
|
|
14
|
+
font-size: 0.6rem;
|
|
15
|
+
font-family: 'Space Mono', monospace;
|
|
16
|
+
color: var(--text-muted);
|
|
17
|
+
opacity: 0.6;
|
|
18
|
+
user-select: none;
|
|
19
|
+
line-height: 1;
|
|
20
|
+
white-space: nowrap;
|
|
21
|
+
position: absolute;
|
|
22
|
+
bottom: 4px;
|
|
23
|
+
pointer-events: none;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Show when enabled */
|
|
27
|
+
.message.show-timestamp .message-timestamp {
|
|
28
|
+
display: block;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Slightly brighter on hover */
|
|
32
|
+
.message:hover .message-timestamp {
|
|
33
|
+
opacity: 0.85;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* User messages: timestamp to the left of the bubble */
|
|
37
|
+
.message.user .message-timestamp {
|
|
38
|
+
right: calc(100% + 8px);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Assistant messages: timestamp to the right of the bubble */
|
|
42
|
+
.message.assistant .message-timestamp {
|
|
43
|
+
left: calc(100% + 8px);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Mobile: tighter spacing */
|
|
47
|
+
@media (max-width: 480px) {
|
|
48
|
+
.message.user .message-timestamp {
|
|
49
|
+
right: calc(100% + 4px);
|
|
50
|
+
}
|
|
51
|
+
.message.assistant .message-timestamp {
|
|
52
|
+
left: calc(100% + 4px);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
CSS CUSTOM PROPERTIES (DESIGN TOKENS)
|
|
3
|
+
Consolidated design system variables
|
|
4
|
+
============================================ */
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
/* ==========================================
|
|
8
|
+
Z-INDEX SCALE
|
|
9
|
+
Use these instead of hardcoded z-index values
|
|
10
|
+
==========================================
|
|
11
|
+
|
|
12
|
+
Layer hierarchy (from bottom to top):
|
|
13
|
+
- base (1): Default positioned elements
|
|
14
|
+
- dropdown (100): Dropdowns, autocompletes, tooltips in context
|
|
15
|
+
- sticky (200): Sticky headers, fixed input areas
|
|
16
|
+
- modal (500): Panels, side drawers, activity panels
|
|
17
|
+
- overlay (1000): Full-screen overlays, modals, dialogs
|
|
18
|
+
- toast (9000): Notifications, toasts, alerts
|
|
19
|
+
- tooltip (10000): Tooltips that must appear above everything
|
|
20
|
+
========================================== */
|
|
21
|
+
--z-base: 1;
|
|
22
|
+
--z-dropdown: 100;
|
|
23
|
+
--z-sticky: 200;
|
|
24
|
+
--z-modal: 500;
|
|
25
|
+
--z-overlay: 1000;
|
|
26
|
+
--z-toast: 9000;
|
|
27
|
+
--z-tooltip: 10000;
|
|
28
|
+
|
|
29
|
+
/* ==========================================
|
|
30
|
+
RESPONSIVE BREAKPOINTS
|
|
31
|
+
Use with @media (max-width: var(--breakpoint-*))
|
|
32
|
+
Note: CSS custom properties don't work in media queries,
|
|
33
|
+
so use these as reference values:
|
|
34
|
+
|
|
35
|
+
--breakpoint-sm: 480px (Small phones, below this is "mobile")
|
|
36
|
+
--breakpoint-md: 768px (Tablets, below this is "small screens")
|
|
37
|
+
--breakpoint-lg: 1024px (Desktop, below this is "tablet")
|
|
38
|
+
--breakpoint-xl: 1440px (Wide desktop)
|
|
39
|
+
--breakpoint-2xl: 1920px (Ultra-wide)
|
|
40
|
+
========================================== */
|
|
41
|
+
|
|
42
|
+
/* ==========================================
|
|
43
|
+
SPACING SCALE (4px base)
|
|
44
|
+
Consolidated from app.css
|
|
45
|
+
========================================== */
|
|
46
|
+
--space-1: 4px;
|
|
47
|
+
--space-2: 8px;
|
|
48
|
+
--space-3: 12px;
|
|
49
|
+
--space-4: 16px;
|
|
50
|
+
--space-5: 20px;
|
|
51
|
+
--space-6: 24px;
|
|
52
|
+
--space-8: 32px;
|
|
53
|
+
--space-10: 40px;
|
|
54
|
+
--space-12: 48px;
|
|
55
|
+
|
|
56
|
+
/* ==========================================
|
|
57
|
+
TYPOGRAPHY SCALE
|
|
58
|
+
Consolidated from app.css
|
|
59
|
+
========================================== */
|
|
60
|
+
--text-xs: 0.75rem; /* 12px */
|
|
61
|
+
--text-sm: 0.875rem; /* 14px */
|
|
62
|
+
--text-base: 1rem; /* 16px */
|
|
63
|
+
--text-lg: 1.125rem; /* 18px */
|
|
64
|
+
--text-xl: 1.25rem; /* 20px */
|
|
65
|
+
--text-2xl: 1.5rem; /* 24px */
|
|
66
|
+
--text-3xl: 2rem; /* 32px */
|
|
67
|
+
|
|
68
|
+
/* ==========================================
|
|
69
|
+
BORDER RADIUS SCALE
|
|
70
|
+
Use these instead of hardcoded border-radius
|
|
71
|
+
========================================== */
|
|
72
|
+
--radius-sm: 4px;
|
|
73
|
+
--radius-md: 8px;
|
|
74
|
+
--radius-lg: 12px;
|
|
75
|
+
--radius-xl: 16px;
|
|
76
|
+
--radius-2xl: 24px;
|
|
77
|
+
--radius-full: 9999px;
|
|
78
|
+
}
|