@kolbo/mcp 1.87.11 → 1.87.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/apps/index.js +6 -5
- package/src/apps/theme.js +444 -446
- package/src/apps/widgets/plans.js +164 -113
package/src/apps/theme.js
CHANGED
|
@@ -1,446 +1,444 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Kolbo Liquid Glass design system for MCP App widgets.
|
|
5
|
-
* Tokens extracted from kolbo-map (tailwind.config + index.css + liquid-glass.css):
|
|
6
|
-
* dark bg #0F0F0F, card #262626/90 + blur, brand #3b82f6, text #F5F5F2, Inter,
|
|
7
|
-
* specular top-edge highlight, spring easing cubic-bezier(.34,1.56,.64,1),
|
|
8
|
-
* skeleton-sweep shimmer, liquid-press buttons.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const KOLBO_CSS = `
|
|
12
|
-
:root {
|
|
13
|
-
--bg: #0f0f0f;
|
|
14
|
-
--card: rgba(38, 38, 38, 0.90);
|
|
15
|
-
--card-solid: #262626;
|
|
16
|
-
--surface: rgba(255, 255, 255, 0.03);
|
|
17
|
-
--surface-2: rgba(255, 255, 255, 0.06);
|
|
18
|
-
--border: rgba(255, 255, 255, 0.08);
|
|
19
|
-
--border-strong: rgba(255, 255, 255, 0.14);
|
|
20
|
-
--text: #f5f5f2;
|
|
21
|
-
--text-muted: rgba(245, 245, 242, 0.62);
|
|
22
|
-
--text-faint: rgba(245, 245, 242, 0.40);
|
|
23
|
-
--brand: #3b82f6;
|
|
24
|
-
--brand-soft: rgba(59, 130, 246, 0.16);
|
|
25
|
-
--success: #22c55e;
|
|
26
|
-
--error: #ef4444;
|
|
27
|
-
--warning: #f59e0b;
|
|
28
|
-
--radius-card: 16px;
|
|
29
|
-
--radius-btn: 8px;
|
|
30
|
-
--spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
31
|
-
--smooth: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
32
|
-
--specular: inset 0 1px 0 rgba(255, 255, 255, 0.18);
|
|
33
|
-
color-scheme: dark;
|
|
34
|
-
}
|
|
35
|
-
[data-theme="light"] {
|
|
36
|
-
--bg: #f5f5f2;
|
|
37
|
-
--card: rgba(255, 255, 255, 0.85);
|
|
38
|
-
--card-solid: #ffffff;
|
|
39
|
-
--surface: rgba(0, 0, 0, 0.02);
|
|
40
|
-
--surface-2: rgba(0, 0, 0, 0.04);
|
|
41
|
-
--border: rgba(0, 0, 0, 0.08);
|
|
42
|
-
--border-strong: rgba(0, 0, 0, 0.14);
|
|
43
|
-
--text: #0a0a0c;
|
|
44
|
-
--text-muted: rgba(10, 10, 12, 0.62);
|
|
45
|
-
--text-faint: rgba(10, 10, 12, 0.40);
|
|
46
|
-
--brand-soft: rgba(59, 130, 246, 0.10);
|
|
47
|
-
--specular: inset 0 1px 0 rgba(255, 255, 255, 0.65);
|
|
48
|
-
color-scheme: light;
|
|
49
|
-
}
|
|
50
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
51
|
-
html, body { background: transparent; }
|
|
52
|
-
body {
|
|
53
|
-
font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
|
|
54
|
-
color: var(--text);
|
|
55
|
-
font-size: 14px;
|
|
56
|
-
line-height: 1.5;
|
|
57
|
-
-webkit-font-smoothing: antialiased;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/* ---- Card shell ---- */
|
|
61
|
-
.k-card {
|
|
62
|
-
position: relative;
|
|
63
|
-
background: var(--card);
|
|
64
|
-
backdrop-filter: blur(20px) saturate(180%);
|
|
65
|
-
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
66
|
-
border: 1px solid var(--border);
|
|
67
|
-
border-radius: var(--radius-card);
|
|
68
|
-
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.25), var(--specular);
|
|
69
|
-
overflow: hidden;
|
|
70
|
-
animation: k-in 400ms var(--spring);
|
|
71
|
-
}
|
|
72
|
-
@keyframes k-in { from { opacity: 0; transform: translateY(6px) scale(0.985); } to { opacity: 1; transform: none; } }
|
|
73
|
-
|
|
74
|
-
.k-head {
|
|
75
|
-
display: flex; align-items: center; gap: 10px;
|
|
76
|
-
padding: 12px 16px;
|
|
77
|
-
border-bottom: 1px solid var(--border);
|
|
78
|
-
}
|
|
79
|
-
.k-logo { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13px; letter-spacing: -0.01em; }
|
|
80
|
-
.k-logo svg { display: block; }
|
|
81
|
-
.k-head .k-title { color: var(--text-muted); font-size: 12.5px; font-weight: 500; }
|
|
82
|
-
.k-head .k-spacer { flex: 1; }
|
|
83
|
-
|
|
84
|
-
.k-body { padding: 14px 16px; }
|
|
85
|
-
.k-prompt { color: var(--text-muted); font-size: 12.5px; margin-bottom: 4px; word-break: break-word;
|
|
86
|
-
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
|
|
87
|
-
user-select: text; -webkit-user-select: text; cursor: text; }
|
|
88
|
-
.k-prompt.expanded { -webkit-line-clamp: unset; }
|
|
89
|
-
.k-text-tools { display: flex; gap: 2px; justify-content: flex-end; margin: 0 0 10px; }
|
|
90
|
-
.k-text-btn {
|
|
91
|
-
display: inline-flex; align-items: center; gap: 4px;
|
|
92
|
-
padding: 3px 8px; border: 0; border-radius: 6px;
|
|
93
|
-
background: transparent; color: var(--text-faint);
|
|
94
|
-
font-size: 11px; font-weight: 600; font-family: inherit;
|
|
95
|
-
cursor: pointer;
|
|
96
|
-
}
|
|
97
|
-
.k-text-btn:hover { color: var(--text); background: var(--surface-2); }
|
|
98
|
-
.k-text-btn svg { width: 12px; height: 12px; }
|
|
99
|
-
/* @VisualDNA / #Moodboard mentions are load-bearing prompt syntax, not prose —
|
|
100
|
-
the server resolves them to the actual asset. Mark them so a glance at the
|
|
101
|
-
prompt shows which references it pulls in. */
|
|
102
|
-
.k-mention {
|
|
103
|
-
display: inline; padding: 1px 5px; border-radius: 5px;
|
|
104
|
-
background: var(--brand-soft); color: var(--brand);
|
|
105
|
-
font-family: 'JetBrains Mono', ui-monospace, monospace;
|
|
106
|
-
font-size: 0.94em; font-weight: 500;
|
|
107
|
-
}
|
|
108
|
-
/* Single-line media caption (scene / batch prompt under the viewer) */
|
|
109
|
-
.k-caption { font-size: 11px; color: var(--text-faint); margin: 2px 2px 0;
|
|
110
|
-
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
111
|
-
user-select: text; -webkit-user-select: text; cursor: text; }
|
|
112
|
-
.k-caption.expanded { white-space: normal; word-break: break-word; }
|
|
113
|
-
.k-caption + .k-text-tools { margin: 0 2px 6px; justify-content: flex-start; }
|
|
114
|
-
|
|
115
|
-
/* ---- Chips ---- */
|
|
116
|
-
.k-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 12px; }
|
|
117
|
-
.k-chip {
|
|
118
|
-
display: inline-flex; align-items: center; gap: 5px;
|
|
119
|
-
padding: 3px 9px; border-radius: 999px;
|
|
120
|
-
background: var(--surface-2); border: 1px solid var(--border);
|
|
121
|
-
box-shadow: var(--specular);
|
|
122
|
-
font-size: 11px; font-weight: 500; color: var(--text-muted);
|
|
123
|
-
white-space: nowrap;
|
|
124
|
-
font-family: 'JetBrains Mono', ui-monospace, monospace;
|
|
125
|
-
letter-spacing: 0.01em;
|
|
126
|
-
animation: k-chip-in 200ms var(--spring);
|
|
127
|
-
}
|
|
128
|
-
@keyframes k-chip-in { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: none; } }
|
|
129
|
-
.k-chip.brand { background: var(--brand-soft); border-color: rgba(59, 130, 246, 0.3); color: var(--brand); }
|
|
130
|
-
.k-chip img { width: 14px; height: 14px; border-radius: 4px; object-fit: cover; }
|
|
131
|
-
.k-chip .k-mono-icon {
|
|
132
|
-
width: 14px; height: 14px; border-radius: 4px; background: var(--brand);
|
|
133
|
-
color: #fff; font-size: 9px; font-weight: 700; display: inline-flex;
|
|
134
|
-
align-items: center; justify-content: center; font-family: 'Inter', sans-serif;
|
|
135
|
-
}
|
|
136
|
-
.k-chip img.k-voice-thumb { width: 18px; height: 18px; border-radius: 999px; margin-left: -3px; }
|
|
137
|
-
.k-ref-thumb { width: 26px; height: 26px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border-strong); }
|
|
138
|
-
.k-peek-hit { cursor: zoom-in; }
|
|
139
|
-
.k-peek {
|
|
140
|
-
position: absolute; inset: 0; z-index: 20;
|
|
141
|
-
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
142
|
-
gap: 10px; padding: 28px 16px 16px;
|
|
143
|
-
background: rgba(8, 10, 16, 0.92);
|
|
144
|
-
}
|
|
145
|
-
.k-peek[hidden] { display: none !important; }
|
|
146
|
-
.k-peek img, .k-peek video {
|
|
147
|
-
display: none; max-width: 100%; max-height: min(360px, 70vh);
|
|
148
|
-
border-radius: 10px; object-fit: contain; background: #000;
|
|
149
|
-
}
|
|
150
|
-
.k-peek img[src], .k-peek video[src] { display: block; }
|
|
151
|
-
.k-peek-close {
|
|
152
|
-
position: absolute; top: 8px; right: 8px;
|
|
153
|
-
width: 28px; height: 28px; border: 0; border-radius: 999px;
|
|
154
|
-
background: var(--surface-2); color: var(--text); cursor: pointer;
|
|
155
|
-
display: inline-flex; align-items: center; justify-content: center;
|
|
156
|
-
}
|
|
157
|
-
.k-peek-cap { font-size: 12px; color: var(--text-muted); text-align: center; max-width: 100%; word-break: break-word; }
|
|
158
|
-
/* Peek granted host fullscreen: the overlay owns the whole viewport, not the card. */
|
|
159
|
-
html.k-peek-fs, html.k-peek-fs body { height: 100%; overflow: hidden; }
|
|
160
|
-
html.k-peek-fs .k-peek { position: fixed; inset: 0; z-index: 50; }
|
|
161
|
-
html.k-peek-fs .k-peek img, html.k-peek-fs .k-peek video { max-height: calc(100vh - 72px); }
|
|
162
|
-
/* ---- Plans / upgrade card ---- */
|
|
163
|
-
.k-plan-toggle { display: inline-flex; gap: 2px; padding: 3px; margin-bottom: 12px;
|
|
164
|
-
background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px; }
|
|
165
|
-
.k-toggle-btn { border: 0; border-radius: 999px; padding: 5px 14px; cursor: pointer;
|
|
166
|
-
background: transparent; color: var(--text-muted); font-family: inherit; font-size: 12px; font-weight: 600; }
|
|
167
|
-
.k-toggle-btn.active { background: var(--brand); color: #fff; }
|
|
168
|
-
.k-plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; }
|
|
169
|
-
.k-plan { display: flex; flex-direction: column; gap: 7px; padding: 14px;
|
|
170
|
-
background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--specular); }
|
|
171
|
-
.k-plan.current { border-color: var(--brand); }
|
|
172
|
-
.k-plan-top { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
173
|
-
.k-plan-name { font-size: 15px; font-weight: 700; letter-spacing: -0.01em; }
|
|
174
|
-
.k-plan-badge { padding: 2px 7px; border-radius: 999px; background: var(--brand-soft); color: var(--brand);
|
|
175
|
-
font-size: 10px; font-weight: 700; }
|
|
176
|
-
.k-plan-badge.current { background: var(--surface-2); color: var(--text-faint); }
|
|
177
|
-
.k-plan-credits { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-muted); }
|
|
178
|
-
.k-plan-pricing { display: flex; align-items: baseline; gap: 6px; margin-top: 2px; }
|
|
179
|
-
.k-plan-price { font-size: 22px; font-weight: 700; letter-spacing: -0.02em; }
|
|
180
|
-
.k-plan-was { font-size: 13px; color: var(--text-faint); text-decoration: line-through; }
|
|
181
|
-
.k-plan-note { font-size: 11px; color: var(--text-faint); }
|
|
182
|
-
.k-plan .k-btn { margin-top: auto; justify-content: center; }
|
|
183
|
-
.k-pack-head { margin: 14px 0 6px; font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
|
|
184
|
-
text-transform: uppercase; color: var(--text-faint); }
|
|
185
|
-
.k-pack-row { margin-bottom: 6px; }
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
.k-dna-
|
|
190
|
-
.k-dna-stack .k-dna-
|
|
191
|
-
.k-dna-stack
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
.k-gen-grid {
|
|
197
|
-
.k-gen-grid.
|
|
198
|
-
.k-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
.k-skel.
|
|
214
|
-
.k-skel
|
|
215
|
-
|
|
216
|
-
.k-skel
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
.k-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
.
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
.k-progress { position:
|
|
259
|
-
background: var(--
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
.k-media {
|
|
268
|
-
|
|
269
|
-
.k-media
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
.k-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
html.k-fullscreen
|
|
302
|
-
html.k-fullscreen .k-
|
|
303
|
-
html.k-fullscreen
|
|
304
|
-
html.k-fullscreen .k-
|
|
305
|
-
html.k-fullscreen
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
html.k-fullscreen .k-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
.k-
|
|
314
|
-
|
|
315
|
-
.k-thumbs .k-thumb {
|
|
316
|
-
|
|
317
|
-
.k-thumbs .k-thumb
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
.k-btn
|
|
333
|
-
|
|
334
|
-
.k-btn.primary { background:
|
|
335
|
-
|
|
336
|
-
.k-btn.
|
|
337
|
-
|
|
338
|
-
.k-btn.danger { background:
|
|
339
|
-
|
|
340
|
-
.k-btn.
|
|
341
|
-
.k-
|
|
342
|
-
|
|
343
|
-
.k-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
.k-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
.k-cell {
|
|
362
|
-
|
|
363
|
-
.k-cell
|
|
364
|
-
.k-cell
|
|
365
|
-
.k-cell .k-cell-
|
|
366
|
-
|
|
367
|
-
.k-cell .k-cell-
|
|
368
|
-
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
.k-audio-
|
|
383
|
-
|
|
384
|
-
.k-audio-
|
|
385
|
-
|
|
386
|
-
.k-audio
|
|
387
|
-
display:
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
395
|
-
.k-generated-audio .k-audio-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
.k-generated-audio { grid-
|
|
402
|
-
.k-generated-audio .k-audio-
|
|
403
|
-
|
|
404
|
-
.k-
|
|
405
|
-
|
|
406
|
-
.k-
|
|
407
|
-
.k-
|
|
408
|
-
.k-
|
|
409
|
-
.k-
|
|
410
|
-
.k-
|
|
411
|
-
.k-
|
|
412
|
-
.k-
|
|
413
|
-
.k-
|
|
414
|
-
.k-prompt-row { flex
|
|
415
|
-
.k-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
.
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
.k-footer {
|
|
433
|
-
|
|
434
|
-
.k-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
module.exports = { KOLBO_CSS, KOLBO_LOGO_SVG, KOLBO_LOGO_IMG };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Kolbo Liquid Glass design system for MCP App widgets.
|
|
5
|
+
* Tokens extracted from kolbo-map (tailwind.config + index.css + liquid-glass.css):
|
|
6
|
+
* dark bg #0F0F0F, card #262626/90 + blur, brand #3b82f6, text #F5F5F2, Inter,
|
|
7
|
+
* specular top-edge highlight, spring easing cubic-bezier(.34,1.56,.64,1),
|
|
8
|
+
* skeleton-sweep shimmer, liquid-press buttons.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const KOLBO_CSS = `
|
|
12
|
+
:root {
|
|
13
|
+
--bg: #0f0f0f;
|
|
14
|
+
--card: rgba(38, 38, 38, 0.90);
|
|
15
|
+
--card-solid: #262626;
|
|
16
|
+
--surface: rgba(255, 255, 255, 0.03);
|
|
17
|
+
--surface-2: rgba(255, 255, 255, 0.06);
|
|
18
|
+
--border: rgba(255, 255, 255, 0.08);
|
|
19
|
+
--border-strong: rgba(255, 255, 255, 0.14);
|
|
20
|
+
--text: #f5f5f2;
|
|
21
|
+
--text-muted: rgba(245, 245, 242, 0.62);
|
|
22
|
+
--text-faint: rgba(245, 245, 242, 0.40);
|
|
23
|
+
--brand: #3b82f6;
|
|
24
|
+
--brand-soft: rgba(59, 130, 246, 0.16);
|
|
25
|
+
--success: #22c55e;
|
|
26
|
+
--error: #ef4444;
|
|
27
|
+
--warning: #f59e0b;
|
|
28
|
+
--radius-card: 16px;
|
|
29
|
+
--radius-btn: 8px;
|
|
30
|
+
--spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
31
|
+
--smooth: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
32
|
+
--specular: inset 0 1px 0 rgba(255, 255, 255, 0.18);
|
|
33
|
+
color-scheme: dark;
|
|
34
|
+
}
|
|
35
|
+
[data-theme="light"] {
|
|
36
|
+
--bg: #f5f5f2;
|
|
37
|
+
--card: rgba(255, 255, 255, 0.85);
|
|
38
|
+
--card-solid: #ffffff;
|
|
39
|
+
--surface: rgba(0, 0, 0, 0.02);
|
|
40
|
+
--surface-2: rgba(0, 0, 0, 0.04);
|
|
41
|
+
--border: rgba(0, 0, 0, 0.08);
|
|
42
|
+
--border-strong: rgba(0, 0, 0, 0.14);
|
|
43
|
+
--text: #0a0a0c;
|
|
44
|
+
--text-muted: rgba(10, 10, 12, 0.62);
|
|
45
|
+
--text-faint: rgba(10, 10, 12, 0.40);
|
|
46
|
+
--brand-soft: rgba(59, 130, 246, 0.10);
|
|
47
|
+
--specular: inset 0 1px 0 rgba(255, 255, 255, 0.65);
|
|
48
|
+
color-scheme: light;
|
|
49
|
+
}
|
|
50
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
51
|
+
html, body { background: transparent; }
|
|
52
|
+
body {
|
|
53
|
+
font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
|
|
54
|
+
color: var(--text);
|
|
55
|
+
font-size: 14px;
|
|
56
|
+
line-height: 1.5;
|
|
57
|
+
-webkit-font-smoothing: antialiased;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* ---- Card shell ---- */
|
|
61
|
+
.k-card {
|
|
62
|
+
position: relative;
|
|
63
|
+
background: var(--card);
|
|
64
|
+
backdrop-filter: blur(20px) saturate(180%);
|
|
65
|
+
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
66
|
+
border: 1px solid var(--border);
|
|
67
|
+
border-radius: var(--radius-card);
|
|
68
|
+
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.25), var(--specular);
|
|
69
|
+
overflow: hidden;
|
|
70
|
+
animation: k-in 400ms var(--spring);
|
|
71
|
+
}
|
|
72
|
+
@keyframes k-in { from { opacity: 0; transform: translateY(6px) scale(0.985); } to { opacity: 1; transform: none; } }
|
|
73
|
+
|
|
74
|
+
.k-head {
|
|
75
|
+
display: flex; align-items: center; gap: 10px;
|
|
76
|
+
padding: 12px 16px;
|
|
77
|
+
border-bottom: 1px solid var(--border);
|
|
78
|
+
}
|
|
79
|
+
.k-logo { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13px; letter-spacing: -0.01em; }
|
|
80
|
+
.k-logo svg { display: block; }
|
|
81
|
+
.k-head .k-title { color: var(--text-muted); font-size: 12.5px; font-weight: 500; }
|
|
82
|
+
.k-head .k-spacer { flex: 1; }
|
|
83
|
+
|
|
84
|
+
.k-body { padding: 14px 16px; }
|
|
85
|
+
.k-prompt { color: var(--text-muted); font-size: 12.5px; margin-bottom: 4px; word-break: break-word;
|
|
86
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
|
|
87
|
+
user-select: text; -webkit-user-select: text; cursor: text; }
|
|
88
|
+
.k-prompt.expanded { -webkit-line-clamp: unset; }
|
|
89
|
+
.k-text-tools { display: flex; gap: 2px; justify-content: flex-end; margin: 0 0 10px; }
|
|
90
|
+
.k-text-btn {
|
|
91
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
92
|
+
padding: 3px 8px; border: 0; border-radius: 6px;
|
|
93
|
+
background: transparent; color: var(--text-faint);
|
|
94
|
+
font-size: 11px; font-weight: 600; font-family: inherit;
|
|
95
|
+
cursor: pointer;
|
|
96
|
+
}
|
|
97
|
+
.k-text-btn:hover { color: var(--text); background: var(--surface-2); }
|
|
98
|
+
.k-text-btn svg { width: 12px; height: 12px; }
|
|
99
|
+
/* @VisualDNA / #Moodboard mentions are load-bearing prompt syntax, not prose —
|
|
100
|
+
the server resolves them to the actual asset. Mark them so a glance at the
|
|
101
|
+
prompt shows which references it pulls in. */
|
|
102
|
+
.k-mention {
|
|
103
|
+
display: inline; padding: 1px 5px; border-radius: 5px;
|
|
104
|
+
background: var(--brand-soft); color: var(--brand);
|
|
105
|
+
font-family: 'JetBrains Mono', ui-monospace, monospace;
|
|
106
|
+
font-size: 0.94em; font-weight: 500;
|
|
107
|
+
}
|
|
108
|
+
/* Single-line media caption (scene / batch prompt under the viewer) */
|
|
109
|
+
.k-caption { font-size: 11px; color: var(--text-faint); margin: 2px 2px 0;
|
|
110
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
111
|
+
user-select: text; -webkit-user-select: text; cursor: text; }
|
|
112
|
+
.k-caption.expanded { white-space: normal; word-break: break-word; }
|
|
113
|
+
.k-caption + .k-text-tools { margin: 0 2px 6px; justify-content: flex-start; }
|
|
114
|
+
|
|
115
|
+
/* ---- Chips ---- */
|
|
116
|
+
.k-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 12px; }
|
|
117
|
+
.k-chip {
|
|
118
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
119
|
+
padding: 3px 9px; border-radius: 999px;
|
|
120
|
+
background: var(--surface-2); border: 1px solid var(--border);
|
|
121
|
+
box-shadow: var(--specular);
|
|
122
|
+
font-size: 11px; font-weight: 500; color: var(--text-muted);
|
|
123
|
+
white-space: nowrap;
|
|
124
|
+
font-family: 'JetBrains Mono', ui-monospace, monospace;
|
|
125
|
+
letter-spacing: 0.01em;
|
|
126
|
+
animation: k-chip-in 200ms var(--spring);
|
|
127
|
+
}
|
|
128
|
+
@keyframes k-chip-in { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: none; } }
|
|
129
|
+
.k-chip.brand { background: var(--brand-soft); border-color: rgba(59, 130, 246, 0.3); color: var(--brand); }
|
|
130
|
+
.k-chip img { width: 14px; height: 14px; border-radius: 4px; object-fit: cover; }
|
|
131
|
+
.k-chip .k-mono-icon {
|
|
132
|
+
width: 14px; height: 14px; border-radius: 4px; background: var(--brand);
|
|
133
|
+
color: #fff; font-size: 9px; font-weight: 700; display: inline-flex;
|
|
134
|
+
align-items: center; justify-content: center; font-family: 'Inter', sans-serif;
|
|
135
|
+
}
|
|
136
|
+
.k-chip img.k-voice-thumb { width: 18px; height: 18px; border-radius: 999px; margin-left: -3px; }
|
|
137
|
+
.k-ref-thumb { width: 26px; height: 26px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border-strong); }
|
|
138
|
+
.k-peek-hit { cursor: zoom-in; }
|
|
139
|
+
.k-peek {
|
|
140
|
+
position: absolute; inset: 0; z-index: 20;
|
|
141
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
142
|
+
gap: 10px; padding: 28px 16px 16px;
|
|
143
|
+
background: rgba(8, 10, 16, 0.92);
|
|
144
|
+
}
|
|
145
|
+
.k-peek[hidden] { display: none !important; }
|
|
146
|
+
.k-peek img, .k-peek video {
|
|
147
|
+
display: none; max-width: 100%; max-height: min(360px, 70vh);
|
|
148
|
+
border-radius: 10px; object-fit: contain; background: #000;
|
|
149
|
+
}
|
|
150
|
+
.k-peek img[src], .k-peek video[src] { display: block; }
|
|
151
|
+
.k-peek-close {
|
|
152
|
+
position: absolute; top: 8px; right: 8px;
|
|
153
|
+
width: 28px; height: 28px; border: 0; border-radius: 999px;
|
|
154
|
+
background: var(--surface-2); color: var(--text); cursor: pointer;
|
|
155
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
156
|
+
}
|
|
157
|
+
.k-peek-cap { font-size: 12px; color: var(--text-muted); text-align: center; max-width: 100%; word-break: break-word; }
|
|
158
|
+
/* Peek granted host fullscreen: the overlay owns the whole viewport, not the card. */
|
|
159
|
+
html.k-peek-fs, html.k-peek-fs body { height: 100%; overflow: hidden; }
|
|
160
|
+
html.k-peek-fs .k-peek { position: fixed; inset: 0; z-index: 50; }
|
|
161
|
+
html.k-peek-fs .k-peek img, html.k-peek-fs .k-peek video { max-height: calc(100vh - 72px); }
|
|
162
|
+
/* ---- Plans / upgrade card ---- */
|
|
163
|
+
.k-plan-toggle { display: inline-flex; gap: 2px; padding: 3px; margin-bottom: 12px;
|
|
164
|
+
background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px; }
|
|
165
|
+
.k-toggle-btn { border: 0; border-radius: 999px; padding: 5px 14px; cursor: pointer;
|
|
166
|
+
background: transparent; color: var(--text-muted); font-family: inherit; font-size: 12px; font-weight: 600; }
|
|
167
|
+
.k-toggle-btn.active { background: var(--brand); color: #fff; }
|
|
168
|
+
.k-plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; }
|
|
169
|
+
.k-plan { display: flex; flex-direction: column; gap: 7px; padding: 14px;
|
|
170
|
+
background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--specular); }
|
|
171
|
+
.k-plan.current { border-color: var(--brand); }
|
|
172
|
+
.k-plan-top { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
173
|
+
.k-plan-name { font-size: 15px; font-weight: 700; letter-spacing: -0.01em; }
|
|
174
|
+
.k-plan-badge { padding: 2px 7px; border-radius: 999px; background: var(--brand-soft); color: var(--brand);
|
|
175
|
+
font-size: 10px; font-weight: 700; }
|
|
176
|
+
.k-plan-badge.current { background: var(--surface-2); color: var(--text-faint); }
|
|
177
|
+
.k-plan-credits { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-muted); }
|
|
178
|
+
.k-plan-pricing { display: flex; align-items: baseline; gap: 6px; margin-top: 2px; }
|
|
179
|
+
.k-plan-price { font-size: 22px; font-weight: 700; letter-spacing: -0.02em; }
|
|
180
|
+
.k-plan-was { font-size: 13px; color: var(--text-faint); text-decoration: line-through; }
|
|
181
|
+
.k-plan-note { font-size: 11px; color: var(--text-faint); }
|
|
182
|
+
.k-plan .k-btn { margin-top: auto; justify-content: center; }
|
|
183
|
+
.k-pack-head { margin: 14px 0 6px; font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
|
|
184
|
+
text-transform: uppercase; color: var(--text-faint); }
|
|
185
|
+
.k-pack-row { margin-bottom: 6px; }
|
|
186
|
+
/* Visual DNA chips: the character's face, so you can see WHICH DNA is locked in. */
|
|
187
|
+
.k-dna-face { width: 18px; height: 18px; border-radius: 999px; object-fit: cover; margin-left: -3px; background: var(--border-strong); }
|
|
188
|
+
.k-dna-stack .k-dna-stack-item { display: inline-flex; }
|
|
189
|
+
.k-dna-stack .k-dna-stack-item + .k-dna-stack-item .k-dna-face { margin-left: -9px; }
|
|
190
|
+
.k-dna-stack .k-dna-face { box-shadow: 0 0 0 1.5px var(--card-solid); }
|
|
191
|
+
.k-dna-stack { cursor: default; }
|
|
192
|
+
|
|
193
|
+
/* ---- Generating state ---- */
|
|
194
|
+
.k-gen-grid { display: grid; gap: 8px; }
|
|
195
|
+
.k-gen-grid.n1 { grid-template-columns: 1fr; }
|
|
196
|
+
.k-gen-grid.n2 { grid-template-columns: 1fr 1fr; }
|
|
197
|
+
.k-gen-grid.n3, .k-gen-grid.n4 { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
|
|
198
|
+
.k-skel {
|
|
199
|
+
position: relative; border-radius: 10px; overflow: hidden;
|
|
200
|
+
background: var(--surface-2); border: 1px solid var(--border);
|
|
201
|
+
min-height: 120px; max-height: 300px;
|
|
202
|
+
/* width:100% is load-bearing, not cosmetic. Without a definite width the
|
|
203
|
+
aspect-ratio transfers the OTHER way: a 16/9 cell in a 196px auto-fill
|
|
204
|
+
column wants 110px of height, min-height:120px clamps it up, and the ratio
|
|
205
|
+
then back-computes the WIDTH as 120*16/9 = 213px. The item overflows its
|
|
206
|
+
196px track and lands on top of the next tile — which is exactly what a
|
|
207
|
+
3-up video grid looked like. Pinning the width makes the ratio size the
|
|
208
|
+
height only, and min-height just letterboxes a slightly tall cell. */
|
|
209
|
+
width: 100%;
|
|
210
|
+
}
|
|
211
|
+
.k-skel.video { aspect-ratio: 16 / 9; }
|
|
212
|
+
.k-skel.square { aspect-ratio: 1; }
|
|
213
|
+
.k-skel.portrait { aspect-ratio: 3 / 4; }
|
|
214
|
+
.k-skel::after {
|
|
215
|
+
content: ''; position: absolute; inset: 0;
|
|
216
|
+
/* The shimmer covers the WHOLE cell and outlives the skeleton — .k-skel.done
|
|
217
|
+
only clears its paint, not its box. A pseudo-element hit-tests as its
|
|
218
|
+
originating element, so every click on a finished cell landed on the cell
|
|
219
|
+
instead of the media inside it: image cells still worked (their handler is
|
|
220
|
+
ON the cell), but a <video>'s native controls never saw a single event —
|
|
221
|
+
play, scrub, volume and fullscreen were all dead. It is decoration; it must
|
|
222
|
+
never take a click. */
|
|
223
|
+
pointer-events: none;
|
|
224
|
+
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.06) 40%, rgba(255,255,255,0.10) 50%, rgba(255,255,255,0.06) 60%, transparent 100%);
|
|
225
|
+
background-size: 200% 100%;
|
|
226
|
+
animation: k-sweep 1.6s ease-in-out infinite;
|
|
227
|
+
}
|
|
228
|
+
@keyframes k-sweep { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
|
|
229
|
+
/* Batch grid: per-cell prompt caption + a cell that already finished */
|
|
230
|
+
/* bottom: 0 puts this exactly where a <video> draws its control bar, so it has
|
|
231
|
+
to be click-through too — the caption is a label, not a target. The full text
|
|
232
|
+
stays reachable: the title tooltip moved onto the cell. */
|
|
233
|
+
.k-skel-cap { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; pointer-events: none;
|
|
234
|
+
padding: 12px 8px 6px; font-size: 10.5px; color: #fff;
|
|
235
|
+
background: linear-gradient(transparent, rgba(0, 0, 0, 0.65));
|
|
236
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
237
|
+
.k-skel.done::after { animation: none; background: none; }
|
|
238
|
+
.k-cell-fill { width: 100%; height: 100%; object-fit: contain; display: block; background: #000; }
|
|
239
|
+
.k-gen-badge {
|
|
240
|
+
position: absolute; top: 10px; left: 10px; z-index: 2; pointer-events: none;
|
|
241
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
242
|
+
padding: 4px 10px; border-radius: 999px;
|
|
243
|
+
background: rgba(0, 0, 0, 0.65); /* no backdrop-filter: nested blur over the
|
|
244
|
+
animating k-sweep skeleton forced per-frame backdrop re-sampling on phones;
|
|
245
|
+
0.65 black over the shimmer reads identically without it */
|
|
246
|
+
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
247
|
+
font-size: 11px; font-weight: 600; color: #fff;
|
|
248
|
+
}
|
|
249
|
+
.k-spin {
|
|
250
|
+
width: 12px; height: 12px; border-radius: 50%;
|
|
251
|
+
border: 2px solid rgba(255,255,255,0.25); border-top-color: var(--brand);
|
|
252
|
+
animation: k-rot 0.8s linear infinite;
|
|
253
|
+
}
|
|
254
|
+
@keyframes k-rot { to { transform: rotate(360deg); } }
|
|
255
|
+
|
|
256
|
+
.k-progress { position: relative; height: 3px; border-radius: 2px; overflow: hidden;
|
|
257
|
+
background: var(--surface-2); margin-top: 12px; }
|
|
258
|
+
.k-progress > i { position: absolute; inset: 0 auto 0 0; width: 0%; border-radius: 2px;
|
|
259
|
+
background: linear-gradient(90deg, var(--brand), #60a5fa);
|
|
260
|
+
transition: width 600ms var(--smooth); }
|
|
261
|
+
.k-status-line { display: flex; align-items: center; justify-content: space-between;
|
|
262
|
+
margin-top: 8px; font-size: 11px; color: var(--text-faint); }
|
|
263
|
+
|
|
264
|
+
/* ---- Results ---- */
|
|
265
|
+
.k-media { position: relative; border-radius: 10px; overflow: hidden; border: 1px solid var(--border);
|
|
266
|
+
background: #000; cursor: pointer; transition: transform 300ms var(--spring), box-shadow 300ms var(--smooth); }
|
|
267
|
+
.k-media:hover { transform: scale(1.015); box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45); }
|
|
268
|
+
.k-media img, .k-media video { display: block; width: 100%; height: 100%; object-fit: contain; }
|
|
269
|
+
.k-media.selected { outline: 2px solid var(--brand); outline-offset: 1px; }
|
|
270
|
+
|
|
271
|
+
/* ---- Per-item hover download button (multi-image grids, CD scenes, viewer) ---- */
|
|
272
|
+
.k-dl {
|
|
273
|
+
position: absolute; top: 8px; right: 8px; z-index: 3;
|
|
274
|
+
width: 30px; height: 30px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.18);
|
|
275
|
+
background: rgba(0, 0, 0, 0.62); color: #fff; font-size: 14px; line-height: 1;
|
|
276
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
277
|
+
cursor: pointer; opacity: 0; transition: opacity 150ms var(--smooth), background 150ms var(--smooth);
|
|
278
|
+
}
|
|
279
|
+
.k-media:hover .k-dl, .k-viewer:hover .k-dl, .k-skel:hover .k-dl { opacity: 1; }
|
|
280
|
+
.k-dl:hover { background: var(--brand); border-color: var(--brand); }
|
|
281
|
+
/* Attach-to-prompt sits immediately left of Download (30px button + 8px gap). */
|
|
282
|
+
.k-attach { right: 46px; }
|
|
283
|
+
.k-viewer { position: relative; }
|
|
284
|
+
|
|
285
|
+
/* Keep the whole completed card under the host's iframe height cap (~800px):
|
|
286
|
+
header + prompt + chips + viewer + thumbs + actions + footer must all fit,
|
|
287
|
+
or claude.ai adds an inner scrollbar. Click the image to expand in-Claude. */
|
|
288
|
+
.k-viewer { margin-bottom: 10px; }
|
|
289
|
+
.k-viewer img, .k-viewer video { display: block; width: 100%;
|
|
290
|
+
/* Fixed px, no vh: vh inside an iframe is the height the host granted, so a
|
|
291
|
+
vh-based cap grew as the iframe grew and the card chased its own tail. */
|
|
292
|
+
max-height: 320px; object-fit: contain;
|
|
293
|
+
border-radius: 12px; background: #000; border: 1px solid var(--border); cursor: zoom-in; }
|
|
294
|
+
.k-viewer video { cursor: default; }
|
|
295
|
+
|
|
296
|
+
/* ---- Fullscreen (ui/request-display-mode granted) ----
|
|
297
|
+
position:fixed pins the card to the iframe viewport regardless of document
|
|
298
|
+
flow/host sizing quirks — the media physically cannot exceed the screen. */
|
|
299
|
+
html.k-fullscreen, html.k-fullscreen body { height: 100%; overflow: hidden; }
|
|
300
|
+
html.k-fullscreen .k-card { position: fixed; inset: 0; display: flex; flex-direction: column; border-radius: 0; }
|
|
301
|
+
html.k-fullscreen .k-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
|
|
302
|
+
html.k-fullscreen .k-prompt, html.k-fullscreen .k-chips { flex: none; }
|
|
303
|
+
html.k-fullscreen #stage { flex: 1; min-height: 0; display: flex; flex-direction: column; }
|
|
304
|
+
html.k-fullscreen .k-viewer { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; margin-bottom: 6px; }
|
|
305
|
+
html.k-fullscreen .k-viewer img, html.k-fullscreen .k-viewer video {
|
|
306
|
+
max-height: 100%; max-width: 100%; height: auto;
|
|
307
|
+
width: auto; margin: 0 auto; cursor: zoom-out; object-fit: contain; }
|
|
308
|
+
html.k-fullscreen .k-thumbs { flex: none; }
|
|
309
|
+
html.k-fullscreen .k-thumbs .k-thumb { width: 56px; height: 56px; }
|
|
310
|
+
html.k-fullscreen .k-actions { flex: none; padding-top: 8px; }
|
|
311
|
+
.k-expand-hint { display: none; }
|
|
312
|
+
.k-thumbs { display: flex; gap: 6px; margin: 10px 0 2px; }
|
|
313
|
+
.k-thumbs .k-thumb { width: 48px; height: 48px; border-radius: 8px; overflow: hidden; cursor: pointer;
|
|
314
|
+
border: 2px solid transparent; opacity: 0.75; transition: all 150ms var(--smooth); flex: none; }
|
|
315
|
+
.k-thumbs .k-thumb:hover { opacity: 1; }
|
|
316
|
+
.k-thumbs .k-thumb.active { border-color: var(--brand); opacity: 1; }
|
|
317
|
+
.k-thumbs .k-thumb img { width: 100%; height: 100%; object-fit: cover; }
|
|
318
|
+
|
|
319
|
+
/* ---- Buttons ---- */
|
|
320
|
+
.k-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding-top: 12px; }
|
|
321
|
+
.k-btn {
|
|
322
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
323
|
+
padding: 7px 14px; border-radius: var(--radius-btn);
|
|
324
|
+
border: 1px solid var(--border); background: var(--surface-2);
|
|
325
|
+
box-shadow: var(--specular);
|
|
326
|
+
color: var(--text); font-size: 12px; font-weight: 600; font-family: inherit;
|
|
327
|
+
cursor: pointer; transition: all 150ms var(--smooth);
|
|
328
|
+
text-decoration: none; user-select: none;
|
|
329
|
+
}
|
|
330
|
+
.k-btn:hover { background: var(--border-strong); }
|
|
331
|
+
.k-btn:active { transform: scale(0.97); }
|
|
332
|
+
.k-btn.primary { background: var(--brand); border-color: var(--brand); color: #fff;
|
|
333
|
+
box-shadow: 0 2px 12px rgba(59, 130, 246, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.25); }
|
|
334
|
+
.k-btn.primary:hover { background: #2f74e8; }
|
|
335
|
+
.k-btn.ghost { background: transparent; box-shadow: none; border-color: transparent; color: var(--text-muted); }
|
|
336
|
+
.k-btn.danger { background: var(--error); border-color: var(--error); color: #fff;
|
|
337
|
+
box-shadow: 0 2px 12px rgba(239, 68, 68, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.25); }
|
|
338
|
+
.k-btn.danger:hover { background: #dc2626; }
|
|
339
|
+
.k-stop-ask { color: var(--text-muted); font-size: 12px; font-weight: 500; margin-right: 4px; }
|
|
340
|
+
.k-btn.ghost:hover { color: var(--text); background: var(--surface-2); }
|
|
341
|
+
.k-btn svg { width: 13px; height: 13px; }
|
|
342
|
+
/* Inline SVG icons (replace emoji) — align with text, inherit color, never shrink. */
|
|
343
|
+
.k-ic { width: 1em; height: 1em; vertical-align: -0.14em; flex: none; }
|
|
344
|
+
.k-btn:disabled { opacity: 0.5; cursor: default; }
|
|
345
|
+
|
|
346
|
+
/* ---- Inline prompt input (Animate / Edit flows) ---- */
|
|
347
|
+
.k-prompt-row { display: none; gap: 8px; margin-top: 10px; }
|
|
348
|
+
.k-prompt-row.open { display: flex; animation: k-in 250ms var(--spring); }
|
|
349
|
+
.k-input {
|
|
350
|
+
flex: 1; padding: 8px 12px; border-radius: var(--radius-btn);
|
|
351
|
+
border: 1px solid var(--border-strong); background: var(--surface);
|
|
352
|
+
color: var(--text); font-size: 12.5px; font-family: inherit; outline: none;
|
|
353
|
+
}
|
|
354
|
+
.k-input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
|
|
355
|
+
.k-input::placeholder { color: var(--text-faint); }
|
|
356
|
+
|
|
357
|
+
/* ---- Grid widget (media / stock / presets) ---- */
|
|
358
|
+
.k-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
|
|
359
|
+
.k-cell { position: relative; border-radius: 10px; overflow: hidden; border: 1px solid var(--border);
|
|
360
|
+
background: var(--surface); cursor: pointer; transition: transform 250ms var(--spring); }
|
|
361
|
+
.k-cell:hover { transform: translateY(-2px) scale(1.01); }
|
|
362
|
+
.k-cell .k-cell-media { position: relative; aspect-ratio: 1; background: #000; }
|
|
363
|
+
.k-cell .k-cell-media img { width: 100%; height: 100%; object-fit: contain; display: block; }
|
|
364
|
+
.k-cell-play { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
|
365
|
+
.k-cell .k-cell-label { padding: 6px 8px; font-size: 11px; color: var(--text-muted);
|
|
366
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
367
|
+
.k-cell .k-cell-sub { padding: 0 8px 7px; font-size: 10px; color: var(--text-faint);
|
|
368
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
369
|
+
|
|
370
|
+
/* ---- Audio rows ---- */
|
|
371
|
+
.k-audio-row { display: flex; align-items: center; gap: 10px; padding: 9px 10px;
|
|
372
|
+
border-radius: 10px; border: 1px solid var(--border); background: var(--surface);
|
|
373
|
+
margin-bottom: 6px; transition: background 150ms var(--smooth); }
|
|
374
|
+
.k-audio-row:hover { background: var(--surface-2); }
|
|
375
|
+
.k-audio-art { width: 40px; height: 40px; border-radius: 8px; object-fit: cover; flex: none;
|
|
376
|
+
background: var(--brand-soft); }
|
|
377
|
+
/* Stand-in when a voice/track has no artwork, or has one the host refuses to
|
|
378
|
+
load — a blank tile and the browser's broken-image glyph both read as "this
|
|
379
|
+
row is broken" rather than "this one has no picture". */
|
|
380
|
+
.k-audio-art-fallback { display: flex; align-items: center; justify-content: center;
|
|
381
|
+
color: var(--brand); font-size: 18px; }
|
|
382
|
+
.k-audio-meta { flex: 1; min-width: 0; }
|
|
383
|
+
.k-audio-title { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
384
|
+
.k-audio-sub { font-size: 11px; color: var(--text-faint);
|
|
385
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
386
|
+
.k-generated-audio {
|
|
387
|
+
display: grid; grid-template-columns: 40px minmax(0, 1fr) auto;
|
|
388
|
+
align-items: center; gap: 7px 10px;
|
|
389
|
+
}
|
|
390
|
+
.k-generated-audio .k-audio-placeholder {
|
|
391
|
+
display: flex; align-items: center; justify-content: center; color: var(--brand);
|
|
392
|
+
}
|
|
393
|
+
.k-generated-audio .k-audio-placeholder svg { width: 19px; height: 19px; }
|
|
394
|
+
.k-generated-audio .k-audio-download { white-space: nowrap; }
|
|
395
|
+
.k-generated-audio .k-audio-player {
|
|
396
|
+
grid-column: 2 / -1; display: block; width: 100%; min-width: 0; height: 34px;
|
|
397
|
+
}
|
|
398
|
+
@media (max-width: 520px) {
|
|
399
|
+
.k-generated-audio { grid-template-columns: 36px minmax(0, 1fr); }
|
|
400
|
+
.k-generated-audio .k-audio-art { width: 36px; height: 36px; }
|
|
401
|
+
.k-generated-audio .k-btn { grid-column: 2; justify-self: start; }
|
|
402
|
+
.k-generated-audio .k-audio-player { grid-column: 1 / -1; }
|
|
403
|
+
/* Touch-friendly MCP App layout (Claude iOS/Android iframe). */
|
|
404
|
+
.k-head { padding: 10px 12px; gap: 8px; }
|
|
405
|
+
.k-body { padding: 10px 12px 12px; }
|
|
406
|
+
.k-footer { padding: 8px 12px 12px; }
|
|
407
|
+
.k-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
|
|
408
|
+
.k-actions { flex-direction: column; align-items: stretch; }
|
|
409
|
+
.k-actions .k-btn { width: 100%; min-height: 44px; justify-content: center; }
|
|
410
|
+
.k-btn { min-height: 40px; padding: 10px 14px; }
|
|
411
|
+
.k-title { font-size: 13.5px; }
|
|
412
|
+
.k-prompt-row { flex-wrap: wrap; }
|
|
413
|
+
.k-prompt-row .k-input { min-width: 0; flex: 1 1 100%; }
|
|
414
|
+
.k-prompt-row .k-btn { flex: 1 1 auto; }
|
|
415
|
+
.k-text-btn { min-height: 32px; padding: 6px 10px; }
|
|
416
|
+
}
|
|
417
|
+
.k-play {
|
|
418
|
+
width: 32px; height: 32px; border-radius: 50%; flex: none; border: 1px solid rgba(255,255,255,0.18);
|
|
419
|
+
background: rgba(0,0,0,0.5); color: #fff; cursor: pointer;
|
|
420
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
421
|
+
transition: all 150ms var(--smooth);
|
|
422
|
+
}
|
|
423
|
+
.k-play:hover { background: var(--brand); border-color: var(--brand); }
|
|
424
|
+
|
|
425
|
+
/* ---- Misc ---- */
|
|
426
|
+
.k-error { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-radius: 10px;
|
|
427
|
+
background: rgba(239, 68, 68, 0.08); border: 1px solid rgba(239, 68, 68, 0.25);
|
|
428
|
+
color: #fca5a5; font-size: 12.5px; }
|
|
429
|
+
.k-empty { padding: 22px; text-align: center; color: var(--text-faint); font-size: 12.5px; }
|
|
430
|
+
.k-footer { display: flex; align-items: center; gap: 6px; padding: 8px 16px 12px;
|
|
431
|
+
font-size: 10.5px; color: var(--text-faint); }
|
|
432
|
+
.k-footer a { color: var(--text-faint); text-decoration: none; }
|
|
433
|
+
.k-footer a:hover { color: var(--brand); }
|
|
434
|
+
.k-credits { margin-left: auto; font-family: 'JetBrains Mono', monospace; }
|
|
435
|
+
`;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Kolbo mark — the real app icon from the CDN (the host CSP allows it), with
|
|
439
|
+
* the simplified inline SVG only as the onerror fallback.
|
|
440
|
+
*/
|
|
441
|
+
const KOLBO_LOGO_SVG = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="24" height="24" rx="6" fill="#3b82f6"/><path d="M7 5.5v13M7 12l6.5-6.5M7 12l7 6.5" stroke="#fff" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
442
|
+
const KOLBO_LOGO_IMG = `<img src="https://kolbo-general-media.fra1.cdn.digitaloceanspaces.com/models_icons/kolbo-ai.png" alt="Kolbo" style="width:18px;height:18px;border-radius:5px;display:block" onerror="this.outerHTML=KOLBO_LOGO_FALLBACK">`;
|
|
443
|
+
|
|
444
|
+
module.exports = { KOLBO_CSS, KOLBO_LOGO_SVG, KOLBO_LOGO_IMG };
|