@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,614 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
MOBILE OPTIMIZATIONS
|
|
3
|
+
Responsive design and touch-friendly UI
|
|
4
|
+
============================================ */
|
|
5
|
+
|
|
6
|
+
/* ==========================================
|
|
7
|
+
RESPONSIVE BREAKPOINTS REFERENCE
|
|
8
|
+
--breakpoint-sm: 480px (Small phones)
|
|
9
|
+
--breakpoint-md: 768px (Tablets)
|
|
10
|
+
--breakpoint-lg: 1024px (Desktop)
|
|
11
|
+
--breakpoint-xl: 1440px (Wide desktop)
|
|
12
|
+
--breakpoint-2xl: 1920px (Ultra-wide)
|
|
13
|
+
========================================== */
|
|
14
|
+
|
|
15
|
+
/* ============================================
|
|
16
|
+
UNIFIED PANEL - Mobile/Tablet Full-Page Slide-In
|
|
17
|
+
Below split-view breakpoint (1024px), panels slide in full-page
|
|
18
|
+
============================================ */
|
|
19
|
+
@media (max-width: 1023px) {
|
|
20
|
+
.panel,
|
|
21
|
+
.dev-panel,
|
|
22
|
+
.satellite-navigator {
|
|
23
|
+
position: fixed !important;
|
|
24
|
+
inset: 0 !important;
|
|
25
|
+
width: 100% !important;
|
|
26
|
+
height: 100% !important;
|
|
27
|
+
max-width: 100% !important;
|
|
28
|
+
max-height: 100% !important;
|
|
29
|
+
border-radius: 0 !important;
|
|
30
|
+
transform: translateX(100%);
|
|
31
|
+
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
32
|
+
background: var(--bg) !important;
|
|
33
|
+
z-index: var(--z-sticky) !important;
|
|
34
|
+
overflow-y: auto;
|
|
35
|
+
-webkit-overflow-scrolling: touch;
|
|
36
|
+
overscroll-behavior: contain;
|
|
37
|
+
padding: 0 !important;
|
|
38
|
+
box-shadow: none !important;
|
|
39
|
+
top: 0 !important;
|
|
40
|
+
right: 0 !important;
|
|
41
|
+
left: 0 !important;
|
|
42
|
+
bottom: 0 !important;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.panel.visible,
|
|
46
|
+
.dev-panel.visible,
|
|
47
|
+
.satellite-navigator.visible {
|
|
48
|
+
display: flex !important;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
transform: translateX(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.panel-header,
|
|
54
|
+
.settings-panel-header,
|
|
55
|
+
.dev-panel-header,
|
|
56
|
+
.satellite-nav-header {
|
|
57
|
+
position: sticky;
|
|
58
|
+
top: 0;
|
|
59
|
+
background: var(--bg);
|
|
60
|
+
padding: var(--space-4) var(--space-5) !important;
|
|
61
|
+
border-bottom: 1px solid var(--border);
|
|
62
|
+
z-index: var(--z-base);
|
|
63
|
+
flex-shrink: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.panel-content,
|
|
67
|
+
.settings-panel-content {
|
|
68
|
+
flex: 1;
|
|
69
|
+
overflow-y: auto;
|
|
70
|
+
-webkit-overflow-scrolling: touch;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Remove scroll mask-image on full-screen mobile panels - cuts off content */
|
|
74
|
+
.settings-panel-content {
|
|
75
|
+
mask-image: none !important;
|
|
76
|
+
-webkit-mask-image: none !important;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Panel rows - larger touch targets on mobile */
|
|
80
|
+
.panel-row,
|
|
81
|
+
.setting-row {
|
|
82
|
+
padding: var(--space-4) var(--space-5) !important;
|
|
83
|
+
min-height: 60px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.panel-row-label,
|
|
87
|
+
.setting-label {
|
|
88
|
+
font-size: var(--text-base) !important;
|
|
89
|
+
font-weight: 500;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.panel-row-desc,
|
|
93
|
+
.setting-desc {
|
|
94
|
+
font-size: var(--text-sm) !important;
|
|
95
|
+
margin-top: var(--space-1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Larger toggle on mobile/tablet */
|
|
99
|
+
.toggle {
|
|
100
|
+
width: 52px !important;
|
|
101
|
+
height: 30px !important;
|
|
102
|
+
border-radius: var(--radius-xl) !important;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.toggle::after {
|
|
106
|
+
width: 26px !important;
|
|
107
|
+
height: 26px !important;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.toggle.on::after {
|
|
111
|
+
transform: translateX(22px) !important;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* Mobile breakpoint (--breakpoint-md: 768px) */
|
|
116
|
+
@media (max-width: 768px) {
|
|
117
|
+
/* App container - constrain to viewport */
|
|
118
|
+
.app {
|
|
119
|
+
max-width: 100% !important;
|
|
120
|
+
width: 100% !important;
|
|
121
|
+
overflow-x: hidden;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Container adjustments */
|
|
125
|
+
.container {
|
|
126
|
+
padding: 0 !important;
|
|
127
|
+
border-radius: 0 !important;
|
|
128
|
+
height: 100vh !important;
|
|
129
|
+
max-width: 100% !important;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Header - tighter on mobile, prevent right-side cutoff */
|
|
133
|
+
header,
|
|
134
|
+
.header {
|
|
135
|
+
padding: var(--space-2) var(--space-3);
|
|
136
|
+
position: sticky;
|
|
137
|
+
top: 0;
|
|
138
|
+
gap: var(--space-2);
|
|
139
|
+
overflow: hidden;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.header-left {
|
|
143
|
+
min-width: 0;
|
|
144
|
+
overflow: hidden;
|
|
145
|
+
flex: 1 1 0;
|
|
146
|
+
gap: var(--space-1);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.header-right {
|
|
150
|
+
flex-shrink: 0;
|
|
151
|
+
gap: var(--space-1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Hide less critical badges on mobile to save space */
|
|
155
|
+
.encryption-badge,
|
|
156
|
+
.connection-mode-badge {
|
|
157
|
+
display: none !important;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* Tighter status badge on mobile — pull dot close to logo */
|
|
161
|
+
.status-badge {
|
|
162
|
+
gap: 2px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.status-dot {
|
|
166
|
+
margin-right: 0;
|
|
167
|
+
z-index: var(--z-dropdown);
|
|
168
|
+
background: var(--bg);
|
|
169
|
+
border-bottom: 1px solid var(--border);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
header h1 {
|
|
173
|
+
font-size: var(--text-base);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.header-buttons {
|
|
177
|
+
gap: var(--space-1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.header-buttons button,
|
|
181
|
+
.header-btn {
|
|
182
|
+
padding: var(--space-1) var(--space-2);
|
|
183
|
+
min-width: 44px;
|
|
184
|
+
min-height: 44px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Context tracker - compact on mobile */
|
|
188
|
+
.context-badge {
|
|
189
|
+
gap: 4px;
|
|
190
|
+
}
|
|
191
|
+
.context-bar {
|
|
192
|
+
width: 36px;
|
|
193
|
+
}
|
|
194
|
+
.context-text {
|
|
195
|
+
font-size: 9px;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* Messages area */
|
|
199
|
+
#messages {
|
|
200
|
+
padding: var(--space-3);
|
|
201
|
+
padding-bottom: 140px; /* Space for input area */
|
|
202
|
+
overflow-x: hidden; /* Prevent horizontal scroll */
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.message {
|
|
206
|
+
max-width: 85% !important;
|
|
207
|
+
min-width: 80px; /* padding (28px) + min content (~50px) */
|
|
208
|
+
padding: 10px 14px !important;
|
|
209
|
+
font-size: var(--text-base);
|
|
210
|
+
word-break: normal; /* Don't break words aggressively */
|
|
211
|
+
overflow-wrap: break-word; /* Only break long words on overflow */
|
|
212
|
+
overflow: visible; /* Don't make bubbles scrollable */
|
|
213
|
+
box-sizing: border-box;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* Edit button - always visible on mobile (no hover on touch) */
|
|
217
|
+
.message.user .message-edit-btn {
|
|
218
|
+
opacity: 0.6;
|
|
219
|
+
position: absolute;
|
|
220
|
+
left: -44px;
|
|
221
|
+
top: 50%;
|
|
222
|
+
transform: translateY(-50%);
|
|
223
|
+
min-width: 44px;
|
|
224
|
+
min-height: 44px;
|
|
225
|
+
display: flex;
|
|
226
|
+
align-items: center;
|
|
227
|
+
justify-content: center;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.message.user {
|
|
231
|
+
position: relative;
|
|
232
|
+
/* Remove display:flex - it breaks text wrapping */
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Message wrapper mobile fixes */
|
|
236
|
+
.message-wrapper {
|
|
237
|
+
max-width: 85% !important;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.message-wrapper .message {
|
|
241
|
+
min-width: 80px; /* padding (28px) + min content (~50px) */
|
|
242
|
+
word-break: normal; /* Override break-word for wrapped messages */
|
|
243
|
+
overflow-wrap: break-word; /* Only break on overflow, not every char */
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Hide message actions by default on mobile - too cramped */
|
|
247
|
+
.message .message-actions {
|
|
248
|
+
display: none;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/* Show on tap/focus */
|
|
252
|
+
.message:focus .message-actions,
|
|
253
|
+
.message:active .message-actions {
|
|
254
|
+
display: flex;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/* Bottom dock - wraps input + mode tabs as single fixed unit */
|
|
258
|
+
.bottom-dock {
|
|
259
|
+
position: fixed;
|
|
260
|
+
bottom: 0;
|
|
261
|
+
left: 0;
|
|
262
|
+
right: 0;
|
|
263
|
+
z-index: var(--z-dropdown);
|
|
264
|
+
background: var(--bg);
|
|
265
|
+
display: flex;
|
|
266
|
+
flex-direction: column;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/* Input area - flows naturally inside bottom-dock */
|
|
270
|
+
.bottom-dock .input-area {
|
|
271
|
+
position: static !important;
|
|
272
|
+
padding: var(--space-3);
|
|
273
|
+
background: var(--bg);
|
|
274
|
+
border-top: none;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/* Mode tabs - flows naturally below input inside bottom-dock */
|
|
278
|
+
.bottom-dock .mode-tabs {
|
|
279
|
+
position: static;
|
|
280
|
+
padding: 0;
|
|
281
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
282
|
+
background: var(--bg);
|
|
283
|
+
border-top: 1px solid var(--border);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
#textInput {
|
|
287
|
+
font-size: 16px !important; /* Prevent zoom on iOS */
|
|
288
|
+
padding: var(--space-3) var(--space-4);
|
|
289
|
+
min-height: 44px; /* Touch target */
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
#sendBtn {
|
|
293
|
+
width: 44px;
|
|
294
|
+
height: 44px;
|
|
295
|
+
min-width: 44px;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.mode-tab {
|
|
299
|
+
padding: var(--space-2) var(--space-4);
|
|
300
|
+
font-size: var(--text-base);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/* Settings panel - Mobile specifics (unified .panel handles full-page slide-in) */
|
|
304
|
+
/* Buttons on mobile - touch-friendly sizing */
|
|
305
|
+
.setting-btn {
|
|
306
|
+
min-height: 44px;
|
|
307
|
+
padding: var(--space-3) var(--space-5);
|
|
308
|
+
font-size: var(--text-base);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* Inputs on mobile - touch-friendly sizing */
|
|
312
|
+
.setting-input,
|
|
313
|
+
.setting-select {
|
|
314
|
+
min-height: 44px;
|
|
315
|
+
font-size: var(--text-base) !important;
|
|
316
|
+
padding: var(--space-3) !important;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* Input groups - stack if needed on very small screens */
|
|
320
|
+
.setting-input-group {
|
|
321
|
+
flex-wrap: wrap;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/* Wide inputs - allow full width on mobile */
|
|
325
|
+
.setting-input-wide {
|
|
326
|
+
max-width: 100%;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/* Developer/Activity panel - uses unified .panel styles from developer.css */
|
|
330
|
+
/* Mobile full-page slide-in handled by .panel.dev-panel rules */
|
|
331
|
+
|
|
332
|
+
/* Satellites panel - Mobile full page slide-in (uses unified .panel class) */
|
|
333
|
+
.panel.satellite-navigator {
|
|
334
|
+
position: fixed !important;
|
|
335
|
+
inset: 0 !important;
|
|
336
|
+
width: 100% !important;
|
|
337
|
+
max-width: 100% !important;
|
|
338
|
+
height: 100% !important;
|
|
339
|
+
max-height: 100% !important;
|
|
340
|
+
border-radius: 0 !important;
|
|
341
|
+
transform: translateX(100%);
|
|
342
|
+
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
343
|
+
background: var(--bg) !important;
|
|
344
|
+
z-index: var(--z-sticky) !important;
|
|
345
|
+
overflow-y: auto;
|
|
346
|
+
-webkit-overflow-scrolling: touch;
|
|
347
|
+
overscroll-behavior: contain;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.panel.satellite-navigator.visible {
|
|
351
|
+
display: flex !important;
|
|
352
|
+
transform: translateX(0);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* Shortcuts panel */
|
|
356
|
+
.shortcuts-panel-inner {
|
|
357
|
+
max-width: 100% !important;
|
|
358
|
+
margin: 0;
|
|
359
|
+
border-radius: 0;
|
|
360
|
+
height: 100%;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* Voice mode */
|
|
364
|
+
#voiceMode {
|
|
365
|
+
padding: var(--space-5);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.voice-btn {
|
|
369
|
+
width: 80px;
|
|
370
|
+
height: 80px;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/* Avatars - smaller on mobile */
|
|
374
|
+
.message-avatar {
|
|
375
|
+
width: var(--space-6);
|
|
376
|
+
height: var(--space-6);
|
|
377
|
+
min-width: var(--space-6);
|
|
378
|
+
font-size: var(--text-sm);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* Toggle sizing handled by ≤1023px breakpoint (52×30px, 26px thumb) */
|
|
382
|
+
|
|
383
|
+
/* File attachment */
|
|
384
|
+
#attachBtn {
|
|
385
|
+
width: 44px;
|
|
386
|
+
height: 44px;
|
|
387
|
+
min-width: 44px;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* Image/file preview */
|
|
391
|
+
#imagePreview {
|
|
392
|
+
max-width: calc(100% - var(--space-6));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/* M2: Preview remove button — 44px touch target */
|
|
396
|
+
.preview-remove {
|
|
397
|
+
width: 44px;
|
|
398
|
+
height: 44px;
|
|
399
|
+
top: -14px;
|
|
400
|
+
right: -14px;
|
|
401
|
+
font-size: var(--text-base);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* M6: Mode tab — 44px min touch target */
|
|
405
|
+
.mode-tab {
|
|
406
|
+
min-height: 44px;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/* M7: Setting description — readable on mobile */
|
|
410
|
+
.setting-desc {
|
|
411
|
+
font-size: var(--text-sm);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/* Small phones (below --breakpoint-sm) */
|
|
416
|
+
@media (max-width: 375px) {
|
|
417
|
+
/* Hide context badge text on small phones — bar only */
|
|
418
|
+
.context-text {
|
|
419
|
+
display: none;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
header h1 {
|
|
423
|
+
font-size: var(--text-base);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.message {
|
|
427
|
+
font-size: var(--text-base);
|
|
428
|
+
padding: var(--space-2) var(--space-3) !important;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.mode-tab {
|
|
432
|
+
padding: var(--space-2) var(--space-3);
|
|
433
|
+
font-size: var(--text-sm);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.voice-btn {
|
|
437
|
+
width: 70px;
|
|
438
|
+
height: 70px;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/* Landscape mode */
|
|
443
|
+
@media (max-height: 500px) and (orientation: landscape) {
|
|
444
|
+
/* Ensure header stays visible */
|
|
445
|
+
header {
|
|
446
|
+
position: sticky;
|
|
447
|
+
top: 0;
|
|
448
|
+
z-index: var(--z-dropdown);
|
|
449
|
+
background: var(--bg);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/* Compact input area */
|
|
453
|
+
.input-area {
|
|
454
|
+
padding: var(--space-2) var(--space-3);
|
|
455
|
+
/* bottom set by JS syncInputBottom() */
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/* Compact mode tabs */
|
|
459
|
+
.mode-tabs {
|
|
460
|
+
bottom: 0;
|
|
461
|
+
padding: var(--space-1) var(--space-3);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.mode-tab {
|
|
465
|
+
padding: var(--space-2) var(--space-3);
|
|
466
|
+
font-size: var(--text-sm);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/* Messages area with proper spacing */
|
|
470
|
+
#messages, main.messages {
|
|
471
|
+
padding-bottom: 90px;
|
|
472
|
+
padding-top: var(--space-2);
|
|
473
|
+
overflow-y: auto;
|
|
474
|
+
-webkit-overflow-scrolling: touch;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/* Compact messages */
|
|
478
|
+
.message {
|
|
479
|
+
padding: var(--space-2) var(--space-3) !important;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/* Smaller voice button */
|
|
483
|
+
.voice-btn {
|
|
484
|
+
width: 60px;
|
|
485
|
+
height: 60px;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/* Panels in landscape - still fullscreen */
|
|
489
|
+
.panel.dev-panel,
|
|
490
|
+
.panel.satellite-navigator {
|
|
491
|
+
max-height: 100% !important;
|
|
492
|
+
height: 100% !important;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/* Safe area insets for notched phones and large screens */
|
|
497
|
+
@supports (padding-bottom: env(safe-area-inset-bottom)) {
|
|
498
|
+
.mode-tabs {
|
|
499
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
#messages {
|
|
503
|
+
padding-bottom: calc(160px + env(safe-area-inset-bottom));
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/* Input area bottom is set dynamically by JS syncInputBottom() */
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/* Fix for tall phones like S25 Ultra where browser chrome eats space */
|
|
510
|
+
@media (max-width: 768px) and (min-height: 800px) {
|
|
511
|
+
#messages {
|
|
512
|
+
padding-bottom: 180px;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/* Input area bottom is set dynamically by JS syncInputBottom() */
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/* Touch feedback */
|
|
519
|
+
@media (hover: none) {
|
|
520
|
+
button:active,
|
|
521
|
+
.mode-tab:active,
|
|
522
|
+
.setting-row:active {
|
|
523
|
+
opacity: 0.7;
|
|
524
|
+
transform: scale(0.98);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/* Disable hover effects on touch */
|
|
528
|
+
button:hover,
|
|
529
|
+
.mode-tab:hover {
|
|
530
|
+
background: inherit;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/* Touch optimization for mobile - prevent double-tap zoom and improve responsiveness */
|
|
535
|
+
@media (max-width: 768px) {
|
|
536
|
+
button,
|
|
537
|
+
a,
|
|
538
|
+
input,
|
|
539
|
+
textarea,
|
|
540
|
+
select,
|
|
541
|
+
.toggle,
|
|
542
|
+
.mode-tab,
|
|
543
|
+
.header-btn,
|
|
544
|
+
.send-btn,
|
|
545
|
+
.voice-btn,
|
|
546
|
+
.input-btn,
|
|
547
|
+
.message-edit-btn,
|
|
548
|
+
.setting-row,
|
|
549
|
+
.satellite-item,
|
|
550
|
+
.satellite-action,
|
|
551
|
+
.dev-tab,
|
|
552
|
+
[role="button"],
|
|
553
|
+
[role="tab"],
|
|
554
|
+
[role="switch"],
|
|
555
|
+
[role="option"] {
|
|
556
|
+
touch-action: manipulation;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/* Ensure scrollable areas allow vertical scrolling */
|
|
560
|
+
.messages,
|
|
561
|
+
.settings-panel,
|
|
562
|
+
.dev-panel-content,
|
|
563
|
+
.satellite-list {
|
|
564
|
+
touch-action: pan-y;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/* Hide scrollbar on mobile but keep functionality */
|
|
569
|
+
@media (max-width: 768px) {
|
|
570
|
+
#messages::-webkit-scrollbar {
|
|
571
|
+
width: 0;
|
|
572
|
+
display: none;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
#messages {
|
|
576
|
+
-ms-overflow-style: none;
|
|
577
|
+
scrollbar-width: none;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/* Prevent pull-to-refresh on chat */
|
|
582
|
+
body {
|
|
583
|
+
overscroll-behavior-y: contain;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/* Overlay/Onboarding screens - ensure scrollable on mobile */
|
|
587
|
+
@media (max-width: 480px) {
|
|
588
|
+
/* Compact context on small screens — already stacked from 768px rule */
|
|
589
|
+
.context-bar {
|
|
590
|
+
width: 28px;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
@media (max-width: 480px) {
|
|
595
|
+
.overlay-screen {
|
|
596
|
+
align-items: flex-start;
|
|
597
|
+
padding: var(--space-4);
|
|
598
|
+
padding-top: env(safe-area-inset-top, var(--space-4));
|
|
599
|
+
padding-bottom: env(safe-area-inset-bottom, var(--space-4));
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.overlay-card {
|
|
603
|
+
margin: var(--space-4) 0;
|
|
604
|
+
max-width: 100%;
|
|
605
|
+
padding: var(--space-5);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/* PWA standalone mode adjustments */
|
|
610
|
+
@media (display-mode: standalone) {
|
|
611
|
+
header {
|
|
612
|
+
padding-top: env(safe-area-inset-top, 12px);
|
|
613
|
+
}
|
|
614
|
+
}
|