@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.

Files changed (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/bin/uplink.js +279 -0
  4. package/middleware/error-handler.js +69 -0
  5. package/package.json +93 -0
  6. package/public/css/agents.36b98c0f.css +1469 -0
  7. package/public/css/agents.css +1469 -0
  8. package/public/css/app.a6a7f8f5.css +2731 -0
  9. package/public/css/app.css +2731 -0
  10. package/public/css/artifacts.css +444 -0
  11. package/public/css/commands.css +55 -0
  12. package/public/css/connection.css +131 -0
  13. package/public/css/dashboard.css +233 -0
  14. package/public/css/developer.css +328 -0
  15. package/public/css/files.css +123 -0
  16. package/public/css/markdown.css +156 -0
  17. package/public/css/message-actions.css +278 -0
  18. package/public/css/mobile.css +614 -0
  19. package/public/css/panels-unified.css +483 -0
  20. package/public/css/premium.css +415 -0
  21. package/public/css/realtime.css +189 -0
  22. package/public/css/satellites.css +401 -0
  23. package/public/css/shortcuts.css +185 -0
  24. package/public/css/split-view.4def0262.css +673 -0
  25. package/public/css/split-view.css +673 -0
  26. package/public/css/theme-generator.css +391 -0
  27. package/public/css/themes.css +387 -0
  28. package/public/css/timestamps.css +54 -0
  29. package/public/css/variables.css +78 -0
  30. package/public/dist/bundle.b55050c4.js +15757 -0
  31. package/public/favicon.svg +24 -0
  32. package/public/img/agents/ada.png +0 -0
  33. package/public/img/agents/clarice.png +0 -0
  34. package/public/img/agents/dennis-nedry.png +0 -0
  35. package/public/img/agents/elliot-alderson.png +0 -0
  36. package/public/img/agents/main.png +0 -0
  37. package/public/img/agents/scotty.png +0 -0
  38. package/public/img/agents/top-flight-security.png +0 -0
  39. package/public/index.html +1083 -0
  40. package/public/js/agents-data.js +234 -0
  41. package/public/js/agents-ui.js +72 -0
  42. package/public/js/agents.js +1525 -0
  43. package/public/js/app.js +79 -0
  44. package/public/js/appearance-settings.js +111 -0
  45. package/public/js/artifacts.js +432 -0
  46. package/public/js/audio-queue.js +168 -0
  47. package/public/js/bootstrap.js +54 -0
  48. package/public/js/chat.js +1211 -0
  49. package/public/js/commands.js +581 -0
  50. package/public/js/connection-api.js +121 -0
  51. package/public/js/connection.js +1231 -0
  52. package/public/js/context-tracker.js +271 -0
  53. package/public/js/core.js +172 -0
  54. package/public/js/dashboard.js +452 -0
  55. package/public/js/developer.js +432 -0
  56. package/public/js/encryption.js +124 -0
  57. package/public/js/errors.js +122 -0
  58. package/public/js/event-bus.js +77 -0
  59. package/public/js/fetch-utils.js +171 -0
  60. package/public/js/file-handler.js +229 -0
  61. package/public/js/files.js +352 -0
  62. package/public/js/gateway-chat.js +538 -0
  63. package/public/js/logger.js +112 -0
  64. package/public/js/markdown.js +190 -0
  65. package/public/js/message-actions.js +431 -0
  66. package/public/js/message-renderer.js +288 -0
  67. package/public/js/missed-messages.js +235 -0
  68. package/public/js/mobile-debug.js +95 -0
  69. package/public/js/notifications.js +367 -0
  70. package/public/js/offline-queue.js +178 -0
  71. package/public/js/onboarding.js +543 -0
  72. package/public/js/panels.js +156 -0
  73. package/public/js/premium.js +412 -0
  74. package/public/js/realtime-voice.js +844 -0
  75. package/public/js/satellite-sync.js +256 -0
  76. package/public/js/satellite-ui.js +175 -0
  77. package/public/js/satellites.js +1516 -0
  78. package/public/js/settings.js +1087 -0
  79. package/public/js/shortcuts.js +381 -0
  80. package/public/js/split-chat.js +1234 -0
  81. package/public/js/split-resize.js +211 -0
  82. package/public/js/splitview.js +340 -0
  83. package/public/js/storage.js +408 -0
  84. package/public/js/streaming-handler.js +324 -0
  85. package/public/js/stt-settings.js +316 -0
  86. package/public/js/theme-generator.js +661 -0
  87. package/public/js/themes.js +164 -0
  88. package/public/js/timestamps.js +198 -0
  89. package/public/js/tts-settings.js +575 -0
  90. package/public/js/ui.js +267 -0
  91. package/public/js/update-notifier.js +143 -0
  92. package/public/js/utils/constants.js +165 -0
  93. package/public/js/utils/sanitize.js +93 -0
  94. package/public/js/utils/sse-parser.js +195 -0
  95. package/public/js/voice.js +883 -0
  96. package/public/manifest.json +58 -0
  97. package/public/moon_texture.jpg +0 -0
  98. package/public/sw.js +221 -0
  99. package/public/three.min.js +6 -0
  100. package/server/channel.js +529 -0
  101. package/server/chat.js +270 -0
  102. package/server/config-store.js +362 -0
  103. package/server/config.js +159 -0
  104. package/server/context.js +131 -0
  105. package/server/gateway-commands.js +211 -0
  106. package/server/gateway-proxy.js +318 -0
  107. package/server/index.js +22 -0
  108. package/server/logger.js +89 -0
  109. package/server/middleware/auth.js +188 -0
  110. package/server/middleware.js +218 -0
  111. package/server/openclaw-discover.js +308 -0
  112. package/server/premium/index.js +156 -0
  113. package/server/premium/license.js +140 -0
  114. package/server/realtime/bridge.js +837 -0
  115. package/server/realtime/index.js +349 -0
  116. package/server/realtime/tts-stream.js +446 -0
  117. package/server/routes/agents.js +564 -0
  118. package/server/routes/artifacts.js +174 -0
  119. package/server/routes/chat.js +311 -0
  120. package/server/routes/config-settings.js +345 -0
  121. package/server/routes/config.js +603 -0
  122. package/server/routes/files.js +307 -0
  123. package/server/routes/index.js +18 -0
  124. package/server/routes/media.js +451 -0
  125. package/server/routes/missed-messages.js +107 -0
  126. package/server/routes/premium.js +75 -0
  127. package/server/routes/push.js +156 -0
  128. package/server/routes/satellite.js +406 -0
  129. package/server/routes/status.js +251 -0
  130. package/server/routes/stt.js +35 -0
  131. package/server/routes/voice.js +260 -0
  132. package/server/routes/webhooks.js +203 -0
  133. package/server/routes.js +206 -0
  134. package/server/runtime-config.js +336 -0
  135. package/server/share.js +305 -0
  136. package/server/stt/faster-whisper.js +72 -0
  137. package/server/stt/groq.js +51 -0
  138. package/server/stt/index.js +196 -0
  139. package/server/stt/openai.js +49 -0
  140. package/server/sync.js +244 -0
  141. package/server/tailscale-https.js +175 -0
  142. package/server/tts.js +646 -0
  143. package/server/update-checker.js +172 -0
  144. package/server/utils/filename.js +129 -0
  145. package/server/utils.js +147 -0
  146. package/server/watchdog.js +318 -0
  147. package/server/websocket/broadcast.js +359 -0
  148. package/server/websocket/connections.js +339 -0
  149. package/server/websocket/index.js +215 -0
  150. package/server/websocket/routing.js +277 -0
  151. package/server/websocket/sync.js +102 -0
  152. package/server.js +404 -0
  153. package/utils/detect-tool-usage.js +93 -0
  154. package/utils/errors.js +158 -0
  155. package/utils/html-escape.js +84 -0
  156. package/utils/id-sanitize.js +94 -0
  157. package/utils/response.js +130 -0
  158. package/utils/with-retry.js +105 -0
@@ -0,0 +1,401 @@
1
+ /* ============================================
2
+ SATELLITES MODULE STYLES
3
+ EXACT match to Activity panel (.dev-panel)
4
+ ============================================ */
5
+
6
+ /* Panel Container - matches dev-panel exactly */
7
+ .satellite-navigator {
8
+ position: fixed;
9
+ bottom: 160px;
10
+ right: var(--space-4);
11
+ width: 360px;
12
+ max-width: calc(100vw - var(--space-8));
13
+ max-height: 400px;
14
+ background: var(--bg-secondary);
15
+ border: 1px solid var(--border);
16
+ border-radius: var(--radius-xl);
17
+ z-index: var(--z-modal);
18
+ display: none;
19
+ flex-direction: column;
20
+ overflow: hidden;
21
+ box-shadow: 0 10px 40px var(--black-40);
22
+ }
23
+
24
+ .satellite-navigator.visible {
25
+ display: flex;
26
+ }
27
+
28
+ /* Header - matches dev-panel-header exactly */
29
+ .satellite-nav-header {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: space-between;
33
+ padding: var(--space-3) var(--space-4);
34
+ border-bottom: 1px solid var(--border);
35
+ background: var(--black-20);
36
+ }
37
+
38
+ .satellite-nav-title {
39
+ font-family: 'Space Mono', monospace;
40
+ font-size: var(--text-sm);
41
+ color: var(--accent);
42
+ letter-spacing: 1px;
43
+ text-transform: uppercase;
44
+ }
45
+
46
+ .satellite-nav-close {
47
+ background: none;
48
+ border: none;
49
+ color: var(--text-muted);
50
+ font-size: var(--text-2xl);
51
+ cursor: pointer;
52
+ min-width: 44px;
53
+ min-height: 44px;
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: center;
57
+ line-height: 1;
58
+ border-radius: var(--radius-md);
59
+ }
60
+
61
+ .satellite-nav-close:hover {
62
+ color: var(--text);
63
+ }
64
+
65
+ /* Session Status Row */
66
+ .satellite-session-status {
67
+ display: flex;
68
+ align-items: center;
69
+ gap: var(--space-2);
70
+ padding: var(--space-2) var(--space-4);
71
+ font-size: var(--text-xs);
72
+ color: var(--text-muted);
73
+ border-bottom: 1px solid var(--border);
74
+ background: rgba(0, 0, 0, 0.1);
75
+ }
76
+
77
+ .session-indicator {
78
+ font-size: 8px;
79
+ transition: color 0.3s;
80
+ }
81
+
82
+ .session-indicator.connected {
83
+ color: var(--success);
84
+ animation: pulse 2s infinite;
85
+ }
86
+
87
+ .session-indicator.disconnected {
88
+ color: var(--error);
89
+ }
90
+
91
+ .session-indicator.loading {
92
+ color: var(--warning);
93
+ animation: blink 1s infinite;
94
+ }
95
+
96
+ .session-key {
97
+ font-family: var(--font-mono, monospace);
98
+ font-size: 10px;
99
+ opacity: 0.7;
100
+ cursor: pointer;
101
+ transition: opacity 0.2s;
102
+ overflow: hidden;
103
+ text-overflow: ellipsis;
104
+ white-space: nowrap;
105
+ max-width: 200px;
106
+ }
107
+
108
+ .session-key:hover {
109
+ opacity: 1;
110
+ }
111
+
112
+ /* Satellite List - content area */
113
+ .satellite-list {
114
+ flex: 1;
115
+ overflow-y: auto;
116
+ padding: var(--space-2);
117
+ }
118
+
119
+ /* Satellite Item */
120
+ .satellite-item {
121
+ display: flex;
122
+ align-items: center;
123
+ gap: var(--space-3);
124
+ padding: var(--space-3) var(--space-4);
125
+ margin: var(--space-1) 0;
126
+ border-radius: var(--radius-md);
127
+ cursor: pointer;
128
+ transition: background 0.2s;
129
+ border: 1px solid transparent;
130
+ }
131
+
132
+ .satellite-item:hover {
133
+ background: var(--white-05);
134
+ }
135
+
136
+ .satellite-item.current {
137
+ background: rgba(99, 102, 241, 0.15);
138
+ border-color: var(--accent);
139
+ }
140
+
141
+ .satellite-item-avatar {
142
+ width: 32px;
143
+ height: 32px;
144
+ border-radius: 50%;
145
+ object-fit: cover;
146
+ flex-shrink: 0;
147
+ }
148
+
149
+ .satellite-item-icon {
150
+ font-size: var(--text-lg);
151
+ flex-shrink: 0;
152
+ }
153
+
154
+ .satellite-item-name {
155
+ flex: 1;
156
+ min-width: 0;
157
+ font-size: var(--text-sm);
158
+ font-weight: 500;
159
+ color: var(--text);
160
+ white-space: nowrap;
161
+ overflow: hidden;
162
+ text-overflow: ellipsis;
163
+ }
164
+
165
+ /* Item Actions (edit, delete buttons) */
166
+ .satellite-item-actions {
167
+ display: flex;
168
+ gap: var(--space-1);
169
+ opacity: 0;
170
+ transition: opacity 0.2s;
171
+ margin-left: auto;
172
+ flex-shrink: 0;
173
+ }
174
+
175
+ .satellite-item:hover .satellite-item-actions {
176
+ opacity: 1;
177
+ }
178
+
179
+ /* Show actions on touch devices */
180
+ @media (hover: none), (pointer: coarse) {
181
+ .satellite-item-actions {
182
+ opacity: 1;
183
+ }
184
+ }
185
+
186
+ .satellite-item-btn {
187
+ background: none;
188
+ border: none;
189
+ min-width: 44px;
190
+ min-height: 44px;
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ font-size: var(--text-sm);
195
+ border-radius: var(--radius-md);
196
+ cursor: pointer;
197
+ transition: background 0.2s;
198
+ touch-action: manipulation;
199
+ }
200
+
201
+ .satellite-item-btn:hover {
202
+ background: var(--white-10);
203
+ }
204
+
205
+ /* Bottom Actions */
206
+ .satellite-nav-actions {
207
+ padding: var(--space-3) var(--space-4);
208
+ border-top: 1px solid var(--border);
209
+ }
210
+
211
+ .satellite-nav-btn {
212
+ width: 100%;
213
+ padding: var(--space-2) var(--space-4);
214
+ background: var(--accent);
215
+ color: var(--text-inverse);
216
+ border: none;
217
+ border-radius: var(--radius-md);
218
+ font-size: var(--text-sm);
219
+ font-weight: 500;
220
+ cursor: pointer;
221
+ transition: background 0.2s, transform 0.1s;
222
+ }
223
+
224
+ .satellite-nav-btn:hover {
225
+ background: var(--accent-hover);
226
+ transform: translateY(-1px);
227
+ }
228
+
229
+ .satellite-nav-btn:active {
230
+ transform: translateY(0);
231
+ }
232
+
233
+ /* ============================================
234
+ NAME PROMPT (for new satellite)
235
+ ============================================ */
236
+
237
+ .satellite-name-prompt {
238
+ padding: var(--space-3);
239
+ border-bottom: 1px solid var(--border);
240
+ background: var(--black-20);
241
+ }
242
+
243
+ .satellite-name-input {
244
+ width: 100%;
245
+ padding: var(--space-2) var(--space-3);
246
+ border: 1px solid var(--border);
247
+ border-radius: var(--radius-md);
248
+ background: var(--bg-input);
249
+ color: var(--text);
250
+ font-size: var(--text-base);
251
+ margin-bottom: var(--space-2);
252
+ }
253
+
254
+ .satellite-name-input:focus {
255
+ outline: none;
256
+ border-color: var(--accent);
257
+ }
258
+
259
+ .satellite-prompt-buttons {
260
+ display: flex;
261
+ gap: var(--space-2);
262
+ justify-content: flex-end;
263
+ }
264
+
265
+ .satellite-prompt-cancel,
266
+ .satellite-prompt-create {
267
+ padding: var(--space-2) var(--space-4);
268
+ border-radius: var(--radius-md);
269
+ font-size: var(--text-sm);
270
+ cursor: pointer;
271
+ border: none;
272
+ }
273
+
274
+ .satellite-prompt-cancel {
275
+ background: transparent;
276
+ color: var(--text-muted);
277
+ border: 1px solid var(--border);
278
+ }
279
+
280
+ .satellite-prompt-cancel:hover {
281
+ background: var(--white-05);
282
+ }
283
+
284
+ .satellite-prompt-create {
285
+ background: var(--accent);
286
+ color: var(--text-inverse);
287
+ }
288
+
289
+ .satellite-prompt-create:hover {
290
+ background: var(--accent-hover);
291
+ }
292
+
293
+ /* ============================================
294
+ SWITCH OVERLAY
295
+ ============================================ */
296
+
297
+ .satellite-switch-overlay {
298
+ position: absolute;
299
+ top: 0;
300
+ left: 0;
301
+ right: 0;
302
+ bottom: 0;
303
+ background: var(--black-80);
304
+ display: flex;
305
+ align-items: center;
306
+ justify-content: center;
307
+ z-index: 100;
308
+ animation: fadeIn 0.15s ease;
309
+ backdrop-filter: blur(2px);
310
+ }
311
+
312
+ .satellite-switch-spinner {
313
+ display: flex;
314
+ flex-direction: column;
315
+ align-items: center;
316
+ gap: 8px;
317
+ color: var(--text);
318
+ font-size: 14px;
319
+ }
320
+
321
+ .satellite-switch-spinner span:first-child {
322
+ font-size: 32px;
323
+ animation: satellitePulse 1s ease-in-out infinite;
324
+ }
325
+
326
+ @keyframes satellitePulse {
327
+ 0%, 100% { transform: scale(1); opacity: 1; }
328
+ 50% { transform: scale(1.1); opacity: 0.7; }
329
+ }
330
+
331
+ /* Input area disabled state during switch */
332
+ .input-area.switching-satellite,
333
+ .chat-input.switching-satellite {
334
+ pointer-events: none;
335
+ opacity: 0.5;
336
+ transition: opacity 0.15s ease;
337
+ }
338
+
339
+ /* ============================================
340
+ PENDING DELETE STATE
341
+ ============================================ */
342
+
343
+ .satellite-item.pending-delete {
344
+ background: rgba(239, 68, 68, 0.15) !important;
345
+ border-color: var(--error) !important;
346
+ animation: pendingPulse 1s ease-in-out infinite;
347
+ }
348
+
349
+ .satellite-item.pending-delete .satellite-item-delete {
350
+ background: var(--error);
351
+ color: white;
352
+ border-radius: var(--radius-md);
353
+ }
354
+
355
+ @keyframes pendingPulse {
356
+ 0%, 100% { opacity: 1; }
357
+ 50% { opacity: 0.7; }
358
+ }
359
+
360
+ /* ============================================
361
+ ANIMATIONS
362
+ ============================================ */
363
+
364
+ @keyframes fadeIn {
365
+ from { opacity: 0; }
366
+ to { opacity: 1; }
367
+ }
368
+
369
+ @keyframes pulse {
370
+ 0%, 100% { opacity: 1; }
371
+ 50% { opacity: 0.5; }
372
+ }
373
+
374
+ @keyframes blink {
375
+ 0%, 100% { opacity: 1; }
376
+ 50% { opacity: 0.3; }
377
+ }
378
+
379
+ /* ============================================
380
+ MOBILE (< 480px)
381
+ ============================================ */
382
+
383
+ @media (max-width: 480px) {
384
+ .satellite-navigator {
385
+ bottom: 140px;
386
+ left: var(--space-4);
387
+ right: var(--space-4);
388
+ width: auto;
389
+ }
390
+ }
391
+
392
+ /* Accessibility: Respect reduced motion preference (M-09) */
393
+ @media (prefers-reduced-motion: reduce) {
394
+ *,
395
+ *::before,
396
+ *::after {
397
+ animation-duration: 0.01ms !important;
398
+ animation-iteration-count: 1 !important;
399
+ transition-duration: 0.01ms !important;
400
+ }
401
+ }
@@ -0,0 +1,185 @@
1
+ /* ============================================
2
+ KEYBOARD SHORTCUTS PANEL STYLES
3
+ ============================================ */
4
+
5
+ .shortcuts-panel {
6
+ position: fixed;
7
+ top: 0;
8
+ left: 0;
9
+ right: 0;
10
+ bottom: 0;
11
+ background: rgba(0, 0, 0, 0.85);
12
+ display: none;
13
+ align-items: center;
14
+ justify-content: center;
15
+ z-index: var(--z-overlay);
16
+ padding: var(--space-5);
17
+ }
18
+
19
+ .shortcuts-panel.visible {
20
+ display: flex;
21
+ }
22
+
23
+ .shortcuts-panel-header {
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: space-between;
27
+ padding: var(--space-5) var(--space-6);
28
+ border-bottom: 1px solid var(--border);
29
+ }
30
+
31
+ .shortcuts-panel-header h3 {
32
+ font-size: var(--text-lg);
33
+ font-weight: 500;
34
+ color: var(--text);
35
+ margin: 0;
36
+ }
37
+
38
+ .shortcuts-close {
39
+ background: none;
40
+ border: none;
41
+ color: var(--text-muted);
42
+ font-size: var(--text-2xl);
43
+ cursor: pointer;
44
+ min-width: 44px;
45
+ min-height: 44px;
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ line-height: 1;
50
+ border-radius: var(--radius-md);
51
+ }
52
+
53
+ .shortcuts-close:hover {
54
+ color: var(--text);
55
+ }
56
+
57
+ .shortcuts-panel > .shortcuts-panel-header,
58
+ .shortcuts-panel > .shortcuts-list,
59
+ .shortcuts-panel > .shortcuts-footer {
60
+ /* Direct children styling */
61
+ }
62
+
63
+ .shortcuts-panel-inner {
64
+ background: var(--bg-secondary);
65
+ border: 1px solid var(--border);
66
+ border-radius: var(--radius-xl);
67
+ width: 100%;
68
+ max-width: 450px;
69
+ max-height: 80vh;
70
+ overflow: hidden;
71
+ display: flex;
72
+ flex-direction: column;
73
+ }
74
+
75
+ .shortcuts-list {
76
+ flex: 1;
77
+ overflow-y: auto;
78
+ padding: var(--space-3) 0;
79
+ }
80
+
81
+ .shortcut-row {
82
+ display: flex;
83
+ align-items: center;
84
+ justify-content: space-between;
85
+ padding: var(--space-3) var(--space-6);
86
+ transition: background 0.15s;
87
+ }
88
+
89
+ .shortcut-row:hover {
90
+ background: rgba(0, 240, 255, 0.05);
91
+ }
92
+
93
+ .shortcut-desc {
94
+ font-size: var(--text-base);
95
+ color: var(--text);
96
+ }
97
+
98
+ .shortcut-key {
99
+ font-family: 'Space Mono', monospace;
100
+ font-size: var(--text-sm);
101
+ background: var(--bg-input);
102
+ border: 1px solid var(--border);
103
+ border-radius: var(--radius-md);
104
+ padding: var(--space-1) var(--space-2);
105
+ color: var(--accent);
106
+ min-width: 60px;
107
+ text-align: center;
108
+ cursor: pointer;
109
+ transition: all 0.15s ease;
110
+ }
111
+
112
+ .shortcut-key:hover {
113
+ border-color: var(--accent);
114
+ background: rgba(0, 240, 255, 0.1);
115
+ }
116
+
117
+ .shortcut-key.editing {
118
+ border-color: var(--accent);
119
+ background: rgba(0, 240, 255, 0.2);
120
+ animation: pulse-border 1s infinite;
121
+ color: var(--text);
122
+ }
123
+
124
+ @keyframes pulse-border {
125
+ 0%, 100% { border-color: var(--accent); }
126
+ 50% { border-color: transparent; }
127
+ }
128
+
129
+ .shortcuts-hint {
130
+ padding: 0 var(--space-6);
131
+ margin: 0 0 var(--space-2) 0;
132
+ font-size: var(--text-xs);
133
+ color: var(--text-muted);
134
+ }
135
+
136
+ .shortcuts-footer {
137
+ padding: var(--space-4) var(--space-6);
138
+ border-top: 1px solid var(--border);
139
+ display: flex;
140
+ justify-content: flex-end;
141
+ }
142
+
143
+ .shortcuts-reset {
144
+ background: transparent;
145
+ border: 1px solid var(--border);
146
+ border-radius: var(--radius-md);
147
+ padding: var(--space-2) var(--space-4);
148
+ color: var(--text-muted);
149
+ font-size: var(--text-sm);
150
+ cursor: pointer;
151
+ transition: all 0.15s;
152
+ }
153
+
154
+ .shortcuts-reset:hover {
155
+ border-color: var(--text-muted);
156
+ color: var(--text);
157
+ }
158
+
159
+ /* Settings button style */
160
+ .setting-btn {
161
+ background: var(--bg-input);
162
+ border: 1px solid var(--border);
163
+ border-radius: var(--radius-md);
164
+ padding: var(--space-2) var(--space-4);
165
+ color: var(--text-muted);
166
+ font-size: var(--text-sm);
167
+ cursor: pointer;
168
+ transition: all 0.15s;
169
+ }
170
+
171
+ .setting-btn:hover {
172
+ border-color: var(--accent);
173
+ color: var(--accent);
174
+ }
175
+
176
+ /* Accessibility: Respect reduced motion preference (M-09) */
177
+ @media (prefers-reduced-motion: reduce) {
178
+ *,
179
+ *::before,
180
+ *::after {
181
+ animation-duration: 0.01ms !important;
182
+ animation-iteration-count: 1 !important;
183
+ transition-duration: 0.01ms !important;
184
+ }
185
+ }