@mrintel/villain-ui 0.2.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +3490 -1296
  3. package/dist/components/buttons/Button.svelte +27 -0
  4. package/dist/components/buttons/Button.svelte.d.ts +14 -0
  5. package/dist/components/buttons/ButtonGroup.svelte +17 -0
  6. package/dist/components/buttons/ButtonGroup.svelte.d.ts +8 -0
  7. package/dist/components/buttons/FloatingActionButton.svelte +20 -0
  8. package/dist/components/buttons/FloatingActionButton.svelte.d.ts +12 -0
  9. package/dist/components/buttons/IconButton.svelte +23 -0
  10. package/dist/components/buttons/IconButton.svelte.d.ts +14 -0
  11. package/dist/components/buttons/LinkButton.svelte +24 -0
  12. package/dist/components/buttons/LinkButton.svelte.d.ts +15 -0
  13. package/dist/components/buttons/buttonClasses.d.ts +15 -0
  14. package/dist/components/buttons/buttonClasses.js +15 -0
  15. package/dist/components/buttons/index.d.ts +5 -0
  16. package/dist/components/buttons/index.js +5 -0
  17. package/dist/components/cards/Card.svelte +60 -0
  18. package/dist/components/cards/Card.svelte.d.ts +15 -0
  19. package/dist/components/cards/Container.svelte +17 -0
  20. package/dist/components/cards/Container.svelte.d.ts +10 -0
  21. package/dist/components/cards/Divider.svelte +36 -0
  22. package/dist/components/cards/Divider.svelte.d.ts +11 -0
  23. package/dist/components/cards/Grid.svelte +55 -0
  24. package/dist/components/cards/Grid.svelte.d.ts +10 -0
  25. package/dist/components/cards/Panel.svelte +18 -0
  26. package/dist/components/cards/Panel.svelte.d.ts +11 -0
  27. package/dist/components/cards/SectionHeader.svelte +24 -0
  28. package/dist/components/cards/SectionHeader.svelte.d.ts +12 -0
  29. package/dist/components/cards/index.d.ts +6 -0
  30. package/dist/components/cards/index.js +6 -0
  31. package/dist/components/data/Avatar.svelte +48 -0
  32. package/dist/components/data/Avatar.svelte.d.ts +10 -0
  33. package/dist/components/data/Badge.svelte +45 -0
  34. package/dist/components/data/Badge.svelte.d.ts +14 -0
  35. package/dist/components/data/CalendarGrid.svelte +433 -0
  36. package/dist/components/data/CalendarGrid.svelte.d.ts +25 -0
  37. package/dist/components/data/CalendarGrid.types.d.ts +7 -0
  38. package/dist/components/data/CalendarGrid.types.js +1 -0
  39. package/dist/components/data/CodeBlock.svelte +119 -0
  40. package/dist/components/data/CodeBlock.svelte.d.ts +40 -0
  41. package/dist/components/data/List.svelte +87 -0
  42. package/dist/components/data/List.svelte.d.ts +15 -0
  43. package/dist/components/data/Pagination.svelte +121 -0
  44. package/dist/components/data/Pagination.svelte.d.ts +14 -0
  45. package/dist/components/data/Sparkline.svelte +117 -0
  46. package/dist/components/data/Sparkline.svelte.d.ts +43 -0
  47. package/dist/components/data/Stat.svelte +92 -0
  48. package/dist/components/data/Stat.svelte.d.ts +11 -0
  49. package/dist/components/data/Table.svelte +443 -0
  50. package/dist/components/data/Table.svelte.d.ts +30 -0
  51. package/dist/components/data/Table.types.d.ts +14 -0
  52. package/dist/components/data/Table.types.js +1 -0
  53. package/dist/components/data/Tag.svelte +51 -0
  54. package/dist/components/data/Tag.svelte.d.ts +13 -0
  55. package/dist/components/data/index.d.ts +12 -0
  56. package/dist/components/data/index.js +10 -0
  57. package/dist/components/forms/Checkbox.svelte +39 -0
  58. package/dist/components/forms/Checkbox.svelte.d.ts +12 -0
  59. package/dist/components/forms/DatePicker.svelte +61 -0
  60. package/dist/components/forms/DatePicker.svelte.d.ts +15 -0
  61. package/dist/components/forms/DateTimePicker.svelte +63 -0
  62. package/dist/components/forms/DateTimePicker.svelte.d.ts +16 -0
  63. package/dist/components/forms/FileUpload.svelte +136 -0
  64. package/dist/components/forms/FileUpload.svelte.d.ts +23 -0
  65. package/dist/components/forms/Input.svelte +282 -0
  66. package/dist/components/forms/Input.svelte.d.ts +19 -0
  67. package/dist/components/forms/InputGroup.svelte +7 -0
  68. package/dist/components/forms/InputGroup.svelte.d.ts +20 -0
  69. package/dist/components/forms/RadioGroup.svelte +77 -0
  70. package/dist/components/forms/RadioGroup.svelte.d.ts +17 -0
  71. package/dist/components/forms/RangeSlider.svelte +90 -0
  72. package/dist/components/forms/RangeSlider.svelte.d.ts +14 -0
  73. package/dist/components/forms/Select.svelte +106 -0
  74. package/dist/components/forms/Select.svelte.d.ts +18 -0
  75. package/dist/components/forms/Switch.svelte +44 -0
  76. package/dist/components/forms/Switch.svelte.d.ts +12 -0
  77. package/dist/components/forms/Textarea.svelte +52 -0
  78. package/dist/components/forms/Textarea.svelte.d.ts +15 -0
  79. package/dist/components/forms/TimePicker.svelte +63 -0
  80. package/dist/components/forms/TimePicker.svelte.d.ts +16 -0
  81. package/dist/components/forms/formClasses.d.ts +3 -0
  82. package/dist/components/forms/formClasses.js +3 -0
  83. package/dist/components/forms/index.d.ts +12 -0
  84. package/dist/components/forms/index.js +12 -0
  85. package/dist/components/navigation/Breadcrumbs.svelte +56 -0
  86. package/dist/components/navigation/Breadcrumbs.svelte.d.ts +15 -0
  87. package/dist/components/navigation/ContextMenu.svelte +133 -0
  88. package/dist/components/navigation/ContextMenu.svelte.d.ts +18 -0
  89. package/dist/components/navigation/DropdownMenu.svelte +139 -0
  90. package/dist/components/navigation/DropdownMenu.svelte.d.ts +17 -0
  91. package/dist/components/navigation/Menu.svelte +72 -0
  92. package/dist/components/navigation/Menu.svelte.d.ts +15 -0
  93. package/dist/components/navigation/Navbar.svelte +111 -0
  94. package/dist/components/navigation/Navbar.svelte.d.ts +15 -0
  95. package/dist/components/navigation/Sidebar.svelte +236 -0
  96. package/dist/components/navigation/Sidebar.svelte.d.ts +12 -0
  97. package/dist/components/navigation/Tabs.svelte +86 -0
  98. package/dist/components/navigation/Tabs.svelte.d.ts +19 -0
  99. package/dist/components/navigation/index.d.ts +7 -0
  100. package/dist/components/navigation/index.js +7 -0
  101. package/dist/components/overlays/Alert.svelte +81 -0
  102. package/dist/components/overlays/Alert.svelte.d.ts +15 -0
  103. package/dist/components/overlays/CommandPalette.svelte +182 -0
  104. package/dist/components/overlays/CommandPalette.svelte.d.ts +16 -0
  105. package/dist/components/overlays/Drawer.svelte +158 -0
  106. package/dist/components/overlays/Drawer.svelte.d.ts +16 -0
  107. package/dist/components/overlays/Dropdown.svelte +62 -0
  108. package/dist/components/overlays/Dropdown.svelte.d.ts +11 -0
  109. package/dist/components/overlays/Modal.svelte +125 -0
  110. package/dist/components/overlays/Modal.svelte.d.ts +15 -0
  111. package/dist/components/overlays/Popover.svelte +106 -0
  112. package/dist/components/overlays/Popover.svelte.d.ts +11 -0
  113. package/dist/components/overlays/ProgressBar.svelte +29 -0
  114. package/dist/components/overlays/ProgressBar.svelte.d.ts +10 -0
  115. package/dist/components/overlays/SkeletonLoader.svelte +66 -0
  116. package/dist/components/overlays/SkeletonLoader.svelte.d.ts +9 -0
  117. package/dist/components/overlays/Spinner.svelte +33 -0
  118. package/dist/components/overlays/Spinner.svelte.d.ts +7 -0
  119. package/dist/components/overlays/Toast.svelte +111 -0
  120. package/dist/components/overlays/Toast.svelte.d.ts +16 -0
  121. package/dist/components/overlays/Tooltip.svelte +94 -0
  122. package/dist/components/overlays/Tooltip.svelte.d.ts +12 -0
  123. package/dist/components/overlays/index.d.ts +11 -0
  124. package/dist/components/overlays/index.js +11 -0
  125. package/dist/components/typography/Code.svelte +10 -0
  126. package/dist/components/typography/Code.svelte.d.ts +6 -0
  127. package/dist/components/typography/Heading.svelte +15 -0
  128. package/dist/components/typography/Heading.svelte.d.ts +10 -0
  129. package/dist/components/typography/Text.svelte +21 -0
  130. package/dist/components/typography/Text.svelte.d.ts +10 -0
  131. package/dist/components/typography/index.d.ts +3 -0
  132. package/dist/components/typography/index.js +3 -0
  133. package/dist/components/utilities/Accordion.svelte +54 -0
  134. package/dist/components/utilities/Accordion.svelte.d.ts +17 -0
  135. package/dist/components/utilities/Carousel.svelte +124 -0
  136. package/dist/components/utilities/Carousel.svelte.d.ts +16 -0
  137. package/dist/components/utilities/Collapse.svelte +46 -0
  138. package/dist/components/utilities/Collapse.svelte.d.ts +10 -0
  139. package/dist/components/utilities/Hero.svelte +42 -0
  140. package/dist/components/utilities/Hero.svelte.d.ts +10 -0
  141. package/dist/components/utilities/Portal.svelte +47 -0
  142. package/dist/components/utilities/Portal.svelte.d.ts +21 -0
  143. package/dist/components/utilities/ScrollArea.svelte +33 -0
  144. package/dist/components/utilities/ScrollArea.svelte.d.ts +8 -0
  145. package/dist/components/utilities/SystemConsole.svelte +310 -0
  146. package/dist/components/utilities/SystemConsole.svelte.d.ts +20 -0
  147. package/dist/components/utilities/SystemInterface.svelte +726 -0
  148. package/dist/components/utilities/SystemInterface.svelte.d.ts +19 -0
  149. package/dist/components/utilities/index.d.ts +9 -0
  150. package/dist/components/utilities/index.js +8 -0
  151. package/dist/components/utilities/utilities.types.d.ts +46 -0
  152. package/dist/components/utilities/utilities.types.js +4 -0
  153. package/dist/index.d.ts +60 -175
  154. package/dist/index.js +24 -4560
  155. package/dist/lib/internal/id.d.ts +12 -0
  156. package/dist/lib/internal/id.js +15 -0
  157. package/dist/theme.css +2821 -0
  158. package/package.json +83 -75
  159. package/dist/index.css +0 -1
@@ -0,0 +1,726 @@
1
+ <script lang="ts">let { messages = [], onSubmit, processing = false, placeholder = 'ENTER DIRECTIVE', height = '600px', autoScroll = true, stagingDelay = 150, leftPanel, rightPanel, topPanel, bottomPanel, class: className = '', ...restProps } = $props();
2
+ let inputValue = $state('');
3
+ let outputContainer = $state();
4
+ let inputElement = $state();
5
+ let visibleMessages = $state(new Set());
6
+ let processingDots = $state(0);
7
+ // Auto-scroll when messages change
8
+ $effect(() => {
9
+ if (autoScroll && outputContainer && messages.length > 0) {
10
+ requestAnimationFrame(() => {
11
+ if (outputContainer) {
12
+ outputContainer.scrollTop = outputContainer.scrollHeight;
13
+ }
14
+ });
15
+ }
16
+ });
17
+ // Staged message revelation
18
+ $effect(() => {
19
+ const newMessages = messages.filter((m) => !visibleMessages.has(m.id));
20
+ if (newMessages.length === 0)
21
+ return;
22
+ // Stage messages with delay
23
+ newMessages.forEach((msg, index) => {
24
+ setTimeout(() => {
25
+ visibleMessages.add(msg.id);
26
+ visibleMessages = new Set(visibleMessages);
27
+ }, index * stagingDelay);
28
+ });
29
+ });
30
+ // Processing animation
31
+ $effect(() => {
32
+ if (!processing) {
33
+ processingDots = 0;
34
+ return;
35
+ }
36
+ const interval = setInterval(() => {
37
+ processingDots = (processingDots + 1) % 4;
38
+ }, 400);
39
+ return () => clearInterval(interval);
40
+ });
41
+ function handleSubmit(e) {
42
+ e.preventDefault();
43
+ const trimmed = inputValue.trim();
44
+ if (!trimmed || !onSubmit || processing)
45
+ return;
46
+ onSubmit(trimmed);
47
+ inputValue = '';
48
+ }
49
+ function handleKeyDown(e) {
50
+ if (e.key === 'Enter' && !e.shiftKey && !processing) {
51
+ e.preventDefault();
52
+ handleSubmit(e);
53
+ }
54
+ }
55
+ function getTierStyles(tier) {
56
+ const tiers = {
57
+ informational: 'text-[var(--color-accent-soft)] border-l-[var(--color-accent-overlay-30)]',
58
+ analysis: 'text-[#60a5fa] border-l-[rgba(96,165,250,0.3)]',
59
+ directive: 'text-[var(--color-accent)] border-l-[var(--color-accent-overlay-50)]',
60
+ warning: 'text-[var(--color-warning)] border-l-[rgba(251,191,36,0.3)]',
61
+ critical: 'text-[var(--color-error)] border-l-[var(--color-error-overlay-50)]'
62
+ };
63
+ return tier ? tiers[tier] : tiers.informational;
64
+ }
65
+ function formatTimestamp(ts) {
66
+ if (!ts)
67
+ return '';
68
+ const date = new Date(ts);
69
+ const hours = date.getHours().toString().padStart(2, '0');
70
+ const minutes = date.getMinutes().toString().padStart(2, '0');
71
+ const seconds = date.getSeconds().toString().padStart(2, '0');
72
+ const ms = date.getMilliseconds().toString().padStart(3, '0');
73
+ return `${hours}:${minutes}:${seconds}.${ms}`;
74
+ }
75
+ function getContent(content) {
76
+ if (typeof content === 'string') {
77
+ return { type: 'text', value: content };
78
+ }
79
+ return content;
80
+ }
81
+ function getStatusColor(status) {
82
+ const colors = {
83
+ ok: 'var(--color-success)',
84
+ warning: 'var(--color-warning)',
85
+ error: 'var(--color-error)',
86
+ info: 'var(--color-accent)'
87
+ };
88
+ return colors[status];
89
+ }
90
+ const containerStyle = $derived(`height: ${height}`);
91
+ const hasPanel = $derived(!!leftPanel || !!rightPanel || !!topPanel || !!bottomPanel);
92
+ export {};
93
+ </script>
94
+
95
+ <div
96
+ class="system-interface {className}"
97
+ class:has-panels={hasPanel}
98
+ style={containerStyle}
99
+ {...restProps}
100
+ role="log"
101
+ aria-live="polite"
102
+ aria-atomic="false"
103
+ >
104
+ <!-- Header -->
105
+ <div class="interface-header">
106
+ <div class="header-line"></div>
107
+ <div class="header-title">
108
+ <span class="title-text">SYSTEM INTERFACE</span>
109
+ {#if processing}
110
+ <span class="processing-indicator">
111
+ PROCESSING{'.'.repeat(processingDots)}
112
+ </span>
113
+ {/if}
114
+ </div>
115
+ <div class="header-line"></div>
116
+ </div>
117
+
118
+ <!-- Top Panel (optional persistent area) -->
119
+ {#if topPanel}
120
+ <div class="top-panel">
121
+ {@render topPanel()}
122
+ </div>
123
+ {/if}
124
+
125
+ <!-- Main Content Area -->
126
+ <div class="interface-content">
127
+ <!-- Left Panel (optional) -->
128
+ {#if leftPanel}
129
+ <div class="side-panel left-panel">
130
+ {@render leftPanel()}
131
+ </div>
132
+ {/if}
133
+
134
+ <!-- Message Stream -->
135
+ <div class="message-stream" bind:this={outputContainer}>
136
+ {#each messages as message (message.id)}
137
+ {@const isVisible = visibleMessages.has(message.id)}
138
+ {@const contentData = getContent(message.content)}
139
+ <div
140
+ class="message-wrapper"
141
+ class:visible={isVisible}
142
+ class:updateable={message.updateable}
143
+ data-role={message.role}
144
+ data-tier={message.tier}
145
+ data-type={contentData.type}
146
+ >
147
+ {#if message.role === 'user'}
148
+ <!-- User Input -->
149
+ <div class="user-message">
150
+ <div class="message-meta">
151
+ <span class="message-role">USER</span>
152
+ {#if message.timestamp}
153
+ <span class="message-timestamp">{formatTimestamp(message.timestamp)}</span>
154
+ {/if}
155
+ </div>
156
+ <div class="message-content user-content">
157
+ {#if contentData.type === 'text'}
158
+ {contentData.value}
159
+ {:else if typeof message.content === 'string'}
160
+ {message.content}
161
+ {/if}
162
+ </div>
163
+ </div>
164
+ {:else}
165
+ <!-- System Output -->
166
+ <div class="system-message {getTierStyles(message.tier)}">
167
+ <div class="message-meta">
168
+ <span class="message-role">SYSTEM</span>
169
+ {#if message.tier}
170
+ <span class="tier-indicator">{message.tier.toUpperCase()}</span>
171
+ {/if}
172
+ <span class="content-type">{contentData.type.toUpperCase()}</span>
173
+ {#if message.timestamp}
174
+ <span class="message-timestamp">{formatTimestamp(message.timestamp)}</span>
175
+ {/if}
176
+ </div>
177
+ <div class="message-content system-content">
178
+ {#if contentData.type === 'text'}
179
+ <div class="text-content">{contentData.value}</div>
180
+ {:else if contentData.type === 'stats'}
181
+ <div class="stats-content" class:grid-layout={contentData.layout === 'grid'}>
182
+ {#each Object.entries(contentData.value) as [key, value]}
183
+ <div class="stat-item">
184
+ <span class="stat-label">{key}</span>
185
+ <span class="stat-value">{value}</span>
186
+ </div>
187
+ {/each}
188
+ </div>
189
+ {:else if contentData.type === 'status'}
190
+ <div class="status-content">
191
+ {#each Object.entries(contentData.value) as [key, { value, status }]}
192
+ <div class="status-item">
193
+ <span class="status-indicator" style="background: {getStatusColor(status)}"></span>
194
+ <span class="status-label">{key}</span>
195
+ <span class="status-value">{value}</span>
196
+ </div>
197
+ {/each}
198
+ </div>
199
+ {:else if contentData.type === 'table'}
200
+ <div class="table-content">
201
+ <table>
202
+ <thead>
203
+ <tr>
204
+ {#each contentData.value.headers as header}
205
+ <th>{header}</th>
206
+ {/each}
207
+ </tr>
208
+ </thead>
209
+ <tbody>
210
+ {#each contentData.value.rows as row}
211
+ <tr>
212
+ {#each row as cell}
213
+ <td>{cell}</td>
214
+ {/each}
215
+ </tr>
216
+ {/each}
217
+ </tbody>
218
+ </table>
219
+ </div>
220
+ {:else if contentData.type === 'keyvalue'}
221
+ <div class="keyvalue-content" style="grid-template-columns: repeat({contentData.columns || 2}, 1fr)">
222
+ {#each Object.entries(contentData.value) as [key, value]}
223
+ <div class="kv-item">
224
+ <span class="kv-key">{key}:</span>
225
+ <span class="kv-value">{value}</span>
226
+ </div>
227
+ {/each}
228
+ </div>
229
+ {:else if contentData.type === 'custom'}
230
+ <div class="custom-content {contentData.class || ''}">
231
+ {contentData.value}
232
+ </div>
233
+ {/if}
234
+ </div>
235
+ </div>
236
+ {/if}
237
+ </div>
238
+ {/each}
239
+ </div>
240
+
241
+ <!-- Right Panel (optional) -->
242
+ {#if rightPanel}
243
+ <div class="side-panel right-panel">
244
+ {@render rightPanel()}
245
+ </div>
246
+ {/if}
247
+ </div>
248
+
249
+ <!-- Bottom Panel (optional) -->
250
+ {#if bottomPanel}
251
+ <div class="bottom-panel">
252
+ {@render bottomPanel()}
253
+ </div>
254
+ {/if}
255
+
256
+ <!-- Input Area -->
257
+ <form class="input-area" onsubmit={handleSubmit}>
258
+ <div class="input-wrapper">
259
+ <span class="input-prompt">›</span>
260
+ <input
261
+ bind:this={inputElement}
262
+ bind:value={inputValue}
263
+ type="text"
264
+ class="system-input"
265
+ placeholder={processing ? 'AWAITING SYSTEM RESPONSE' : placeholder}
266
+ disabled={processing}
267
+ onkeydown={handleKeyDown}
268
+ autocomplete="off"
269
+ spellcheck="false"
270
+ />
271
+ <button
272
+ type="submit"
273
+ class="submit-indicator"
274
+ disabled={!inputValue.trim() || processing}
275
+ aria-label="Submit"
276
+ >
277
+ <span class="submit-icon">→</span>
278
+ </button>
279
+ </div>
280
+ </form>
281
+ </div>
282
+
283
+ <style>
284
+ .system-interface {
285
+ display: flex;
286
+ flex-direction: column;
287
+ background: linear-gradient(
288
+ 180deg,
289
+ rgba(10, 10, 12, 0.98) 0%,
290
+ rgba(5, 5, 8, 0.98) 100%
291
+ );
292
+ border: 1px solid var(--color-border);
293
+ border-radius: var(--radius-lg);
294
+ overflow: hidden;
295
+ font-family: var(--font-mono);
296
+ box-shadow:
297
+ 0 0 0 1px rgba(255, 255, 255, 0.02),
298
+ 0 20px 60px rgba(0, 0, 0, 0.9),
299
+ inset 0 1px 0 rgba(255, 255, 255, 0.03);
300
+ position: relative;
301
+ backdrop-filter: blur(20px);
302
+ }
303
+
304
+ /* Header */
305
+ .interface-header {
306
+ display: flex;
307
+ align-items: center;
308
+ gap: 1rem;
309
+ padding: 1rem 1.5rem;
310
+ background: linear-gradient(
311
+ 180deg,
312
+ rgba(15, 15, 20, 0.8) 0%,
313
+ rgba(10, 10, 15, 0.6) 100%
314
+ );
315
+ border-bottom: 1px solid var(--color-border);
316
+ position: relative;
317
+ }
318
+
319
+ .header-line {
320
+ flex: 1;
321
+ height: 1px;
322
+ background: linear-gradient(
323
+ 90deg,
324
+ transparent 0%,
325
+ var(--color-accent-overlay-20) 50%,
326
+ transparent 100%
327
+ );
328
+ }
329
+
330
+ .header-title {
331
+ display: flex;
332
+ align-items: center;
333
+ gap: 1rem;
334
+ font-size: 0.75rem;
335
+ letter-spacing: 0.15em;
336
+ font-weight: 600;
337
+ }
338
+
339
+ .title-text {
340
+ color: var(--color-accent-soft);
341
+ text-shadow: 0 0 20px var(--color-accent-overlay-30);
342
+ }
343
+
344
+ .processing-indicator {
345
+ color: var(--color-accent);
346
+ font-size: 0.625rem;
347
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
348
+ min-width: 5rem;
349
+ text-align: left;
350
+ }
351
+
352
+ @keyframes pulse {
353
+ 0%,
354
+ 100% {
355
+ opacity: 0.5;
356
+ }
357
+ 50% {
358
+ opacity: 1;
359
+ }
360
+ }
361
+
362
+ /* Top Panel */
363
+ .top-panel {
364
+ padding: 1rem 1.5rem;
365
+ background: rgba(0, 0, 0, 0.2);
366
+ border-bottom: 1px solid var(--color-border);
367
+ }
368
+
369
+ /* Content Area with optional side panels */
370
+ .interface-content {
371
+ flex: 1;
372
+ display: flex;
373
+ overflow: hidden;
374
+ }
375
+
376
+ .side-panel {
377
+ width: 250px;
378
+ padding: 1rem;
379
+ background: rgba(0, 0, 0, 0.3);
380
+ overflow-y: auto;
381
+ overflow-x: hidden;
382
+ }
383
+
384
+ .left-panel {
385
+ border-right: 1px solid var(--color-border);
386
+ }
387
+
388
+ .right-panel {
389
+ border-left: 1px solid var(--color-border);
390
+ }
391
+
392
+ /* Bottom Panel */
393
+ .bottom-panel {
394
+ padding: 1rem 1.5rem;
395
+ background: rgba(0, 0, 0, 0.2);
396
+ border-top: 1px solid var(--color-border);
397
+ }
398
+
399
+ /* Message Stream */
400
+ .message-stream {
401
+ flex: 1;
402
+ overflow-y: auto;
403
+ overflow-x: hidden;
404
+ padding: 1.5rem;
405
+ background: rgba(0, 0, 0, 0.3);
406
+ position: relative;
407
+ }
408
+
409
+ .message-wrapper {
410
+ margin-bottom: 1.5rem;
411
+ opacity: 0;
412
+ transform: translateY(8px);
413
+ transition:
414
+ opacity 0.4s var(--ease-luxe),
415
+ transform 0.4s var(--ease-luxe);
416
+ }
417
+
418
+ .message-wrapper.visible {
419
+ opacity: 1;
420
+ transform: translateY(0);
421
+ }
422
+
423
+ .message-wrapper.updateable {
424
+ /* Messages that can be updated in place might have different styling */
425
+ position: relative;
426
+ }
427
+
428
+ /* Message Meta */
429
+ .message-meta {
430
+ display: flex;
431
+ align-items: center;
432
+ gap: 0.75rem;
433
+ margin-bottom: 0.5rem;
434
+ font-size: 0.625rem;
435
+ letter-spacing: 0.1em;
436
+ }
437
+
438
+ .message-role {
439
+ color: var(--color-text-muted);
440
+ font-weight: 600;
441
+ }
442
+
443
+ .tier-indicator,
444
+ .content-type {
445
+ color: var(--color-accent-soft);
446
+ opacity: 0.6;
447
+ font-size: 0.55rem;
448
+ }
449
+
450
+ .message-timestamp {
451
+ color: var(--color-text-muted);
452
+ opacity: 0.4;
453
+ margin-left: auto;
454
+ }
455
+
456
+ /* User Messages */
457
+ .user-message {
458
+ max-width: 80%;
459
+ }
460
+
461
+ .user-content {
462
+ background: rgba(255, 255, 255, 0.02);
463
+ border: 1px solid var(--color-border);
464
+ border-radius: var(--radius-md);
465
+ padding: 0.75rem 1rem;
466
+ color: var(--color-text);
467
+ line-height: 1.6;
468
+ font-size: var(--text-sm);
469
+ }
470
+
471
+ /* System Messages */
472
+ .system-message {
473
+ border-left: 2px solid;
474
+ padding-left: 1rem;
475
+ transition: all 0.3s var(--ease-luxe);
476
+ }
477
+
478
+ .system-content {
479
+ color: inherit;
480
+ line-height: 1.7;
481
+ font-size: var(--text-sm);
482
+ }
483
+
484
+ /* Content Type Renderers */
485
+ .text-content {
486
+ white-space: pre-wrap;
487
+ word-wrap: break-word;
488
+ }
489
+
490
+ .stats-content {
491
+ display: flex;
492
+ flex-direction: column;
493
+ gap: 0.75rem;
494
+ }
495
+
496
+ .stats-content.grid-layout {
497
+ display: grid;
498
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
499
+ gap: 1rem;
500
+ }
501
+
502
+ .stat-item {
503
+ display: flex;
504
+ flex-direction: column;
505
+ gap: 0.25rem;
506
+ padding: 0.75rem;
507
+ background: rgba(0, 0, 0, 0.3);
508
+ border: 1px solid var(--color-border);
509
+ border-radius: var(--radius-sm);
510
+ }
511
+
512
+ .stat-label {
513
+ font-size: 0.625rem;
514
+ text-transform: uppercase;
515
+ letter-spacing: 0.1em;
516
+ opacity: 0.6;
517
+ }
518
+
519
+ .stat-value {
520
+ font-size: 1.5rem;
521
+ font-weight: 700;
522
+ text-shadow: 0 0 20px currentColor;
523
+ }
524
+
525
+ .status-content {
526
+ display: flex;
527
+ flex-direction: column;
528
+ gap: 0.5rem;
529
+ }
530
+
531
+ .status-item {
532
+ display: flex;
533
+ align-items: center;
534
+ gap: 0.75rem;
535
+ padding: 0.5rem 0.75rem;
536
+ background: rgba(0, 0, 0, 0.2);
537
+ border-radius: var(--radius-sm);
538
+ }
539
+
540
+ .status-indicator {
541
+ width: 8px;
542
+ height: 8px;
543
+ border-radius: 50%;
544
+ box-shadow: 0 0 10px currentColor;
545
+ flex-shrink: 0;
546
+ }
547
+
548
+ .status-label {
549
+ flex: 1;
550
+ font-size: 0.75rem;
551
+ opacity: 0.8;
552
+ }
553
+
554
+ .status-value {
555
+ font-size: 0.875rem;
556
+ font-weight: 600;
557
+ }
558
+
559
+ .table-content {
560
+ overflow-x: auto;
561
+ }
562
+
563
+ .table-content table {
564
+ width: 100%;
565
+ border-collapse: collapse;
566
+ font-size: 0.75rem;
567
+ }
568
+
569
+ .table-content th {
570
+ text-align: left;
571
+ padding: 0.5rem 0.75rem;
572
+ border-bottom: 1px solid var(--color-border);
573
+ font-weight: 600;
574
+ text-transform: uppercase;
575
+ letter-spacing: 0.05em;
576
+ font-size: 0.625rem;
577
+ opacity: 0.8;
578
+ }
579
+
580
+ .table-content td {
581
+ padding: 0.5rem 0.75rem;
582
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
583
+ }
584
+
585
+ .keyvalue-content {
586
+ display: grid;
587
+ gap: 0.5rem;
588
+ }
589
+
590
+ .kv-item {
591
+ display: flex;
592
+ gap: 0.5rem;
593
+ padding: 0.375rem 0.5rem;
594
+ background: rgba(0, 0, 0, 0.2);
595
+ border-radius: var(--radius-sm);
596
+ font-size: 0.75rem;
597
+ }
598
+
599
+ .kv-key {
600
+ opacity: 0.7;
601
+ font-weight: 600;
602
+ }
603
+
604
+ .kv-value {
605
+ flex: 1;
606
+ }
607
+
608
+ .custom-content {
609
+ /* Allow custom styling via class */
610
+ }
611
+
612
+ /* Input Area */
613
+ .input-area {
614
+ background: linear-gradient(
615
+ 180deg,
616
+ rgba(10, 10, 15, 0.6) 0%,
617
+ rgba(15, 15, 20, 0.8) 100%
618
+ );
619
+ border-top: 1px solid var(--color-border);
620
+ padding: 1rem 1.5rem;
621
+ position: relative;
622
+ }
623
+
624
+ .input-wrapper {
625
+ display: flex;
626
+ align-items: center;
627
+ gap: 0.75rem;
628
+ background: rgba(0, 0, 0, 0.4);
629
+ border: 1px solid var(--color-border);
630
+ border-radius: var(--radius-md);
631
+ padding: 0.75rem 1rem;
632
+ transition: all 0.3s var(--ease-luxe);
633
+ }
634
+
635
+ .input-wrapper:focus-within {
636
+ border-color: var(--color-accent-overlay-50);
637
+ box-shadow: 0 0 20px var(--color-accent-overlay-20);
638
+ }
639
+
640
+ .input-prompt {
641
+ color: var(--color-accent);
642
+ font-size: 1rem;
643
+ font-weight: 700;
644
+ user-select: none;
645
+ text-shadow: 0 0 10px currentColor;
646
+ flex-shrink: 0;
647
+ }
648
+
649
+ .system-input {
650
+ flex: 1;
651
+ background: transparent;
652
+ border: none;
653
+ color: var(--color-text);
654
+ font-family: var(--font-mono);
655
+ font-size: var(--text-sm);
656
+ outline: none;
657
+ letter-spacing: 0.02em;
658
+ caret-color: var(--color-accent);
659
+ }
660
+
661
+ .system-input::placeholder {
662
+ color: var(--color-text-muted);
663
+ opacity: 0.3;
664
+ letter-spacing: 0.05em;
665
+ font-size: 0.75rem;
666
+ }
667
+
668
+ .system-input:disabled {
669
+ opacity: 0.4;
670
+ cursor: not-allowed;
671
+ }
672
+
673
+ .submit-indicator {
674
+ background: transparent;
675
+ border: none;
676
+ color: var(--color-accent-soft);
677
+ font-size: 1.25rem;
678
+ cursor: pointer;
679
+ padding: 0;
680
+ transition: all 0.3s var(--ease-luxe);
681
+ opacity: 0.3;
682
+ flex-shrink: 0;
683
+ }
684
+
685
+ .submit-indicator:not(:disabled) {
686
+ opacity: 1;
687
+ }
688
+
689
+ .submit-indicator:not(:disabled):hover {
690
+ color: var(--color-accent);
691
+ text-shadow: 0 0 12px currentColor;
692
+ transform: translateX(2px);
693
+ }
694
+
695
+ .submit-indicator:disabled {
696
+ cursor: not-allowed;
697
+ opacity: 0.2;
698
+ }
699
+
700
+ .submit-icon {
701
+ display: block;
702
+ line-height: 1;
703
+ }
704
+
705
+ /* Scrollbar */
706
+ .message-stream::-webkit-scrollbar,
707
+ .side-panel::-webkit-scrollbar {
708
+ width: 0.375rem;
709
+ }
710
+
711
+ .message-stream::-webkit-scrollbar-track,
712
+ .side-panel::-webkit-scrollbar-track {
713
+ background: rgba(0, 0, 0, 0.4);
714
+ }
715
+
716
+ .message-stream::-webkit-scrollbar-thumb,
717
+ .side-panel::-webkit-scrollbar-thumb {
718
+ background: var(--color-accent-overlay-20);
719
+ border-radius: var(--radius-sm);
720
+ transition: background 0.3s var(--ease-luxe);
721
+ }
722
+
723
+ .message-stream::-webkit-scrollbar-thumb:hover,
724
+ .side-panel::-webkit-scrollbar-thumb:hover {
725
+ background: var(--color-accent-overlay-40);
726
+ }</style>