@mrintel/villain-ui 0.8.2 → 0.9.1

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 (68) hide show
  1. package/README.md +52 -3
  2. package/dist/components/buttons/Button.svelte +1 -1
  3. package/dist/components/buttons/FloatingActionButton.svelte +1 -1
  4. package/dist/components/buttons/IconButton.svelte +2 -2
  5. package/dist/components/buttons/LinkButton.svelte +1 -1
  6. package/dist/components/buttons/buttonClasses.js +7 -7
  7. package/dist/components/cards/Card.svelte +43 -11
  8. package/dist/components/cards/Card.svelte.d.ts +11 -0
  9. package/dist/components/cards/Panel.svelte +44 -5
  10. package/dist/components/cards/Panel.svelte.d.ts +7 -0
  11. package/dist/components/cards/SectionHeader.svelte +2 -2
  12. package/dist/components/data/Avatar.svelte +1 -1
  13. package/dist/components/data/Badge.svelte +3 -3
  14. package/dist/components/data/CalendarGrid.svelte +6 -4
  15. package/dist/components/data/CalendarGrid.svelte.d.ts +3 -0
  16. package/dist/components/data/CodeBlock.svelte +1 -1
  17. package/dist/components/data/List.svelte +1 -1
  18. package/dist/components/data/Pagination.svelte +3 -3
  19. package/dist/components/data/Stat.svelte +3 -5
  20. package/dist/components/data/Table.svelte +12 -14
  21. package/dist/components/data/Tag.svelte +1 -1
  22. package/dist/components/data/WeekHeatmap.svelte +2 -2
  23. package/dist/components/forms/Checkbox.svelte +1 -1
  24. package/dist/components/forms/DatePicker.svelte +3 -1
  25. package/dist/components/forms/DateTimePicker.svelte +3 -1
  26. package/dist/components/forms/FileUpload.svelte +1 -1
  27. package/dist/components/forms/FormSection.svelte +21 -0
  28. package/dist/components/forms/FormSection.svelte.d.ts +14 -0
  29. package/dist/components/forms/InputGroup.svelte +1 -1
  30. package/dist/components/forms/RadioGroup.svelte +0 -1
  31. package/dist/components/forms/RangeSlider.svelte +2 -6
  32. package/dist/components/forms/SelectMenu.svelte +4 -3
  33. package/dist/components/forms/Switch.svelte +1 -1
  34. package/dist/components/forms/TimePicker.svelte +1 -1
  35. package/dist/components/forms/TimePickerGrid.svelte +0 -3
  36. package/dist/components/forms/formClasses.d.ts +2 -2
  37. package/dist/components/forms/formClasses.js +2 -2
  38. package/dist/components/forms/index.d.ts +1 -0
  39. package/dist/components/forms/index.js +1 -0
  40. package/dist/components/navigation/Breadcrumbs.svelte +3 -3
  41. package/dist/components/navigation/ContextMenu.svelte +2 -2
  42. package/dist/components/navigation/DropdownMenu.svelte +2 -2
  43. package/dist/components/navigation/Menu.svelte +2 -2
  44. package/dist/components/navigation/Navbar.svelte +10 -2
  45. package/dist/components/navigation/Sidebar.svelte +6 -9
  46. package/dist/components/navigation/Tabs.svelte +2 -2
  47. package/dist/components/overlays/Alert.svelte +1 -1
  48. package/dist/components/overlays/CommandPalette.svelte +2 -2
  49. package/dist/components/overlays/Drawer.svelte +5 -5
  50. package/dist/components/overlays/Dropdown.svelte +1 -1
  51. package/dist/components/overlays/Modal.svelte +2 -2
  52. package/dist/components/overlays/Popover.svelte +1 -1
  53. package/dist/components/overlays/ProgressBar.svelte +3 -3
  54. package/dist/components/overlays/SkeletonLoader.svelte +2 -2
  55. package/dist/components/overlays/Spinner.svelte +1 -1
  56. package/dist/components/overlays/Toast.svelte +2 -2
  57. package/dist/components/overlays/Tooltip.svelte +1 -1
  58. package/dist/components/typography/Code.svelte +1 -1
  59. package/dist/components/utilities/Carousel.svelte +4 -4
  60. package/dist/components/utilities/Collapse.svelte +1 -1
  61. package/dist/components/utilities/Hero.svelte +3 -2
  62. package/dist/components/utilities/SystemConsole.svelte +1 -1
  63. package/dist/components/utilities/SystemInterface.svelte +1 -2
  64. package/dist/components/wizard/StepForm.svelte +1 -1
  65. package/dist/index.d.ts +2 -2
  66. package/dist/index.js +2 -2
  67. package/dist/theme.css +207 -190
  68. package/package.json +2 -1
@@ -256,7 +256,7 @@ const errorClasses = $derived(hasError ? 'error-state' : '');
256
256
  role="dialog"
257
257
  aria-modal="true"
258
258
  aria-label="Choose date and time"
259
- class="datetime-picker-dropdown {variant === 'glass' ? 'glass-panel' : 'panel-floating'} rounded-lg overflow-hidden"
259
+ class="datetime-picker-dropdown {variant === 'glass' ? 'glass-panel' : 'panel-floating'} rounded-[var(--radius-sm)] overflow-hidden"
260
260
  onclick={(e) => e.stopPropagation()}
261
261
  >
262
262
  <!-- Tab navigation -->
@@ -308,6 +308,8 @@ const errorClasses = $derived(hasError ? 'error-state' : '');
308
308
  selectedDate={selectedDate}
309
309
  onDateSelect={handleDateSelect}
310
310
  highlightToday={true}
311
+ minDate={minDateStr ? new Date(minDateStr + 'T00:00:00') : undefined}
312
+ maxDate={maxDateStr ? new Date(maxDateStr + 'T00:00:00') : undefined}
311
313
  class="calendar-picker"
312
314
  />
313
315
  {:else}
@@ -67,7 +67,7 @@ const fileList = $derived(files ? Array.from(files) : []);
67
67
  ondrop={handleDrop}
68
68
  onclick={handleClick}
69
69
  onkeydown={(e) => e.key === 'Enter' && handleClick()}
70
- class="panel-raised rounded-[var(--radius-lg)] p-8 text-center cursor-pointer transition-all duration-300 ease-luxe {isDragging ? 'border-2 border-accent accent-glow bg-base-2' : ''} {hasError && !isDragging ? 'border-2 border-error' : ''} {disabled ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''}"
70
+ class="panel-raised rounded-[var(--radius-sm)] p-8 text-center cursor-pointer transition-all duration-300 ease-luxe {isDragging ? 'border-2 border-accent accent-glow bg-base-2' : ''} {hasError && !isDragging ? 'border-2 border-error' : ''} {disabled ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''}"
71
71
  >
72
72
  <div class="flex flex-col items-center gap-2">
73
73
  {#if icon}
@@ -0,0 +1,21 @@
1
+ <script lang="ts">let { legend, description, columns = 1, class: className = '', children, ...restProps } = $props();
2
+ export {};
3
+ </script>
4
+
5
+ <fieldset class="border-0 p-0 m-0 min-w-0 {className}" {...restProps}>
6
+ {#if legend}
7
+ <legend
8
+ class="font-[var(--font-mono)] text-xs uppercase tracking-[0.08em] text-[var(--color-text-soft)] p-0 mb-2 w-full border-b border-[var(--color-border-subtle)] pb-3"
9
+ >
10
+ {legend}
11
+ </legend>
12
+ {/if}
13
+ {#if description}
14
+ <p class="text-sm text-[var(--color-text-soft)] mt-3 mb-6">{description}</p>
15
+ {:else if legend}
16
+ <div class="mt-6"></div>
17
+ {/if}
18
+ <div class="grid gap-5 {columns === 2 ? 'md:grid-cols-2' : ''}">
19
+ {@render children?.()}
20
+ </div>
21
+ </fieldset>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ /** Mono uppercase section label (e.g. "01 / IDENTITY"). */
4
+ legend?: string;
5
+ /** Supporting copy under the legend. */
6
+ description?: string;
7
+ /** Field layout: single column (default) or two columns on md+. */
8
+ columns?: 1 | 2;
9
+ class?: string;
10
+ children?: Snippet;
11
+ }
12
+ declare const FormSection: import("svelte").Component<Props, {}, "">;
13
+ type FormSection = ReturnType<typeof FormSection>;
14
+ export default FormSection;
@@ -2,6 +2,6 @@
2
2
  // No props needed for standard slot usage
3
3
  </script>
4
4
 
5
- <div class="flex items-stretch rounded-[var(--radius-lg)] overflow-hidden panel-raised [&>*:not(:first-child)]:ml-[-1px] [&>*:not(:first-child):not(:last-child)]:rounded-none [&>*:first-child]:rounded-r-none [&>*:last-child]:rounded-l-none">
5
+ <div class="flex items-stretch rounded-[var(--radius-sm)] overflow-hidden panel-raised [&>*:not(:first-child)]:ml-[-1px] [&>*:not(:first-child):not(:last-child)]:rounded-none [&>*:first-child]:rounded-r-none [&>*:last-child]:rounded-l-none">
6
6
  <slot />
7
7
  </div>
@@ -83,5 +83,4 @@ export {};
83
83
  height: 0.75rem;
84
84
  border-radius: var(--radius-pill);
85
85
  background: var(--color-accent);
86
- box-shadow: var(--shadow-accent-glow);
87
86
  }</style>
@@ -47,7 +47,6 @@ const percentage = $derived(max === min ? 0 : ((value - min) / (max - min)) * 10
47
47
  height: 1.25rem;
48
48
  border-radius: var(--radius-pill);
49
49
  background: var(--color-accent);
50
- box-shadow: var(--shadow-accent-glow);
51
50
  cursor: pointer;
52
51
  transition: transform 0.2s var(--ease-luxe);
53
52
  }
@@ -62,7 +61,6 @@ const percentage = $derived(max === min ? 0 : ((value - min) / (max - min)) * 10
62
61
  height: 1.25rem;
63
62
  border-radius: var(--radius-pill);
64
63
  background: var(--color-accent);
65
- box-shadow: var(--shadow-accent-glow);
66
64
  cursor: pointer;
67
65
  transition: transform 0.2s var(--ease-luxe);
68
66
  border: none;
@@ -73,15 +71,13 @@ const percentage = $derived(max === min ? 0 : ((value - min) / (max - min)) * 10
73
71
  }
74
72
 
75
73
  input[type="range"]:focus::-webkit-slider-thumb {
76
- box-shadow:
77
- var(--shadow-accent-glow),
74
+ box-shadow:
78
75
  0 0 0 3px var(--color-base-1),
79
76
  0 0 0 5px var(--color-accent);
80
77
  }
81
78
 
82
79
  input[type="range"]:focus::-moz-range-thumb {
83
- box-shadow:
84
- var(--shadow-accent-glow),
80
+ box-shadow:
85
81
  0 0 0 3px var(--color-base-1),
86
82
  0 0 0 5px var(--color-accent);
87
83
  }
@@ -86,16 +86,17 @@ function handleListboxKeyDown(event) {
86
86
  break;
87
87
  }
88
88
  }
89
- function scrollOptionIntoView(index) {
89
+ function scrollOptionIntoView(index, block = 'nearest') {
90
90
  requestAnimationFrame(() => {
91
91
  const optionEl = listboxElement?.querySelector(`[data-index="${index}"]`);
92
- optionEl?.scrollIntoView({ block: 'nearest' });
92
+ optionEl?.scrollIntoView({ block });
93
93
  });
94
94
  }
95
- // Set highlighted index and focus listbox when dropdown opens
95
+ // Set highlighted index, scroll it into view, and focus listbox when dropdown opens
96
96
  $effect(() => {
97
97
  if (open) {
98
98
  highlightedIndex = selectedIndex >= 0 ? selectedIndex : 0;
99
+ scrollOptionIntoView(highlightedIndex, 'center');
99
100
  if (listboxElement) {
100
101
  requestAnimationFrame(() => listboxElement?.focus());
101
102
  }
@@ -14,7 +14,7 @@ const hasError = $derived(error || !!validationMessage);
14
14
  {disabled}
15
15
  bind:checked
16
16
  onchange={onchange}
17
- class="w-14 h-7 rounded-pill bg-base-3 border appearance-none transition-all duration-300 ease-luxe cursor-pointer checked:bg-accent checked:accent-glow focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 focus:ring-offset-base-1 relative {hasError ? 'border-error' : 'border-border'} {disabled ? 'cursor-not-allowed' : ''}"
17
+ class="w-14 h-7 rounded-pill bg-base-3 border appearance-none transition-all duration-300 ease-luxe cursor-pointer checked:bg-accent focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 focus:ring-offset-base-1 relative {hasError ? 'border-error' : 'border-border'} {disabled ? 'cursor-not-allowed' : ''}"
18
18
  />
19
19
  {#if iconBefore}
20
20
  <span class="inline-flex items-center justify-center text-text-soft">
@@ -169,7 +169,7 @@ const errorClasses = $derived(hasError ? 'error-state' : '');
169
169
  role="dialog"
170
170
  aria-modal="true"
171
171
  aria-label="Choose time"
172
- class="time-picker-dropdown {variant === 'glass' ? 'glass-panel' : 'panel-floating'} rounded-lg overflow-hidden"
172
+ class="time-picker-dropdown {variant === 'glass' ? 'glass-panel' : 'panel-floating'} rounded-[var(--radius-sm)] overflow-hidden"
173
173
  >
174
174
  <TimePickerGrid
175
175
  bind:hours={selectedHours}
@@ -445,7 +445,6 @@ $effect(() => {
445
445
  border-color: var(--color-accent);
446
446
  color: var(--color-base-0);
447
447
  font-weight: 700;
448
- box-shadow: 0 0 12px var(--color-accent-glow);
449
448
  }
450
449
 
451
450
  .time-option.disabled,
@@ -482,8 +481,6 @@ $effect(() => {
482
481
 
483
482
  .confirm-button:hover:not(:disabled) {
484
483
  background: var(--color-accent-hover);
485
- box-shadow: 0 0 20px var(--color-accent-glow);
486
- transform: translateY(-1px);
487
484
  }
488
485
 
489
486
  .confirm-button:active:not(:disabled) {
@@ -1,3 +1,3 @@
1
- export declare const baseInputClasses = "glass-panel rounded-[var(--radius-lg)] px-5 py-3.5 font-body text-text placeholder:text-text-muted transition-all duration-300 ease-luxe w-full";
2
- export declare const focusClasses = "focus:outline-none focus:border-accent focus:accent-glow";
1
+ export declare const baseInputClasses = "input-well rounded-[var(--radius-sm)] px-5 py-3.5 font-body text-text placeholder:text-text-muted transition-all duration-150 ease-luxe w-full";
2
+ export declare const focusClasses = "focus:outline-none focus:border-[var(--color-accent)]";
3
3
  export declare const disabledClasses = "opacity-50 cursor-not-allowed";
@@ -1,3 +1,3 @@
1
- export const baseInputClasses = 'glass-panel rounded-[var(--radius-lg)] px-5 py-3.5 font-body text-text placeholder:text-text-muted transition-all duration-300 ease-luxe w-full';
2
- export const focusClasses = 'focus:outline-none focus:border-accent focus:accent-glow';
1
+ export const baseInputClasses = 'input-well rounded-[var(--radius-sm)] px-5 py-3.5 font-body text-text placeholder:text-text-muted transition-all duration-150 ease-luxe w-full';
2
+ export const focusClasses = 'focus:outline-none focus:border-[var(--color-accent)]';
3
3
  export const disabledClasses = 'opacity-50 cursor-not-allowed';
@@ -11,3 +11,4 @@ export { default as DatePicker } from './DatePicker.svelte';
11
11
  export { default as TimePicker } from './TimePicker.svelte';
12
12
  export { default as DateTimePicker } from './DateTimePicker.svelte';
13
13
  export { default as SelectMenu } from './SelectMenu.svelte';
14
+ export { default as FormSection } from './FormSection.svelte';
@@ -11,3 +11,4 @@ export { default as DatePicker } from './DatePicker.svelte';
11
11
  export { default as TimePicker } from './TimePicker.svelte';
12
12
  export { default as DateTimePicker } from './DateTimePicker.svelte';
13
13
  export { default as SelectMenu } from './SelectMenu.svelte';
14
+ export { default as FormSection } from './FormSection.svelte';
@@ -9,7 +9,7 @@ export {};
9
9
  {#if item.href}
10
10
  <a
11
11
  href={item.href}
12
- class="flex items-center gap-2 text-sm font-[var(--font-body)] text-[var(--color-text-soft)] hover:text-[var(--color-accent)] hover:underline transition-colors duration-200 ease-[var(--ease-luxe)]"
12
+ class="flex items-center gap-2 text-xs font-[var(--font-mono)] uppercase tracking-[0.08em] text-[var(--color-text-soft)] hover:text-[var(--color-accent)] hover:underline transition-colors duration-200 ease-[var(--ease-luxe)]"
13
13
  >
14
14
  {#if item.icon}
15
15
  <span class="inline-flex items-center justify-center">
@@ -21,7 +21,7 @@ export {};
21
21
  {:else if item.onclick}
22
22
  <button
23
23
  onclick={item.onclick}
24
- class="flex items-center gap-2 text-sm font-[var(--font-body)] text-[var(--color-text-soft)] hover:text-[var(--color-accent)] hover:underline transition-colors duration-200 ease-[var(--ease-luxe)] cursor-pointer"
24
+ class="flex items-center gap-2 text-xs font-[var(--font-mono)] uppercase tracking-[0.08em] text-[var(--color-text-soft)] hover:text-[var(--color-accent)] hover:underline transition-colors duration-200 ease-[var(--ease-luxe)] cursor-pointer"
25
25
  >
26
26
  {#if item.icon}
27
27
  <span class="inline-flex items-center justify-center">
@@ -31,7 +31,7 @@ export {};
31
31
  {item.label}
32
32
  </button>
33
33
  {:else}
34
- <span class="flex items-center gap-2 text-sm font-[var(--font-body)] {index === items.length - 1 ? 'text-[var(--color-text)]' : 'text-[var(--color-text-soft)]'}">
34
+ <span class="flex items-center gap-2 text-xs font-[var(--font-mono)] uppercase tracking-[0.08em] {index === items.length - 1 ? 'text-[var(--color-text)]' : 'text-[var(--color-text-soft)]'}">
35
35
  {#if item.icon}
36
36
  <span class="inline-flex items-center justify-center">
37
37
  {@render item.icon()}
@@ -111,7 +111,7 @@ $effect(() => {
111
111
  role="menu"
112
112
  tabindex="-1"
113
113
  onkeydown={handleMenuKeyDown}
114
- class="fixed z-[var(--z-50)] glass-panel rounded-[var(--radius-lg)] shadow-[var(--shadow-deep)] min-w-[12rem] animate-[fade-in_0.15s_var(--ease-luxe)]"
114
+ class="fixed z-[var(--z-50)] glass-panel rounded-[var(--radius-sm)] shadow-[var(--shadow-deep)] min-w-[12rem] animate-[fade-in_0.15s_var(--ease-luxe)]"
115
115
  style="left: {x}px; top: {y}px;"
116
116
  >
117
117
  {#each items as item, index}
@@ -121,7 +121,7 @@ $effect(() => {
121
121
  tabindex={index === selectedIndex ? 0 : -1}
122
122
  onclick={() => handleItemClick(item)}
123
123
  disabled={item.disabled}
124
- class="w-full text-left px-4 py-2 text-sm text-text hover:bg-base-3 transition-colors duration-200 flex items-center gap-2 {item.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}"
124
+ class="w-full text-left px-4 py-2 font-[var(--font-mono)] text-xs uppercase tracking-[0.08em] text-text hover:bg-base-3 transition-colors duration-200 flex items-center gap-2 {item.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}"
125
125
  >
126
126
  {#if item.icon}
127
127
  {@render item.icon()}
@@ -117,7 +117,7 @@ $effect(() => {
117
117
  role="menu"
118
118
  tabindex="-1"
119
119
  onkeydown={handleMenuKeyDown}
120
- class="absolute {placementClasses[placement]} z-[var(--z-50)] glass-panel rounded-[var(--radius-lg)] shadow-[var(--shadow-deep)] min-w-[12rem] animate-[fade-up_0.2s_var(--ease-luxe)]"
120
+ class="absolute {placementClasses[placement]} z-[var(--z-50)] glass-panel rounded-[var(--radius-sm)] shadow-[var(--shadow-deep)] min-w-[12rem] animate-[scale-in_0.15s_var(--ease-sharp)]"
121
121
  >
122
122
  {#each items as item, index}
123
123
  <button
@@ -126,7 +126,7 @@ $effect(() => {
126
126
  tabindex={index === selectedIndex ? 0 : -1}
127
127
  onclick={() => handleItemClick(item)}
128
128
  disabled={item.disabled}
129
- class="w-full text-left px-4 py-2 text-sm text-text hover:bg-base-3 transition-colors duration-200 flex items-center gap-2 {item.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}"
129
+ class="w-full text-left px-4 py-2 font-[var(--font-mono)] text-xs uppercase tracking-[0.08em] text-text hover:bg-base-3 transition-colors duration-200 flex items-center gap-2 {item.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}"
130
130
  >
131
131
  {#if item.icon}
132
132
  {@render item.icon()}
@@ -49,7 +49,7 @@ $effect(() => {
49
49
  export {};
50
50
  </script>
51
51
 
52
- <div bind:this={menuContainer} role="menu" tabindex="-1" onkeydown={handleMenuKeyDown} class="glass-panel rounded-[var(--radius-lg)] p-3 shadow-[var(--shadow-deep)]">
52
+ <div bind:this={menuContainer} role="menu" tabindex="-1" onkeydown={handleMenuKeyDown} class="glass-panel rounded-[var(--radius-sm)] p-3 shadow-[var(--shadow-deep)]">
53
53
  {#if children}
54
54
  {@render children()}
55
55
  {:else if items}
@@ -60,7 +60,7 @@ export {};
60
60
  tabindex={index === selectedIndex ? 0 : -1}
61
61
  onclick={() => handleItemClick(item)}
62
62
  disabled={item.disabled}
63
- class="flex items-center gap-2 w-full px-4 py-3 rounded-[var(--radius-md)] text-[var(--color-text)] text-sm font-[var(--font-body)] hover:bg-[var(--color-base-3)] hover-lift transition-all duration-200 ease-[var(--ease-luxe)] {item.disabled ? 'opacity-50 pointer-events-none' : 'cursor-pointer'}"
63
+ class="flex items-center gap-2 w-full px-4 py-3 rounded-[var(--radius-sm)] text-[var(--color-text)] text-xs font-[var(--font-mono)] uppercase tracking-[0.08em] hover:bg-[var(--color-base-3)] hover-lift transition-all duration-200 ease-[var(--ease-luxe)] {item.disabled ? 'opacity-50 pointer-events-none' : 'cursor-pointer'}"
64
64
  >
65
65
  {#if item.icon}
66
66
  {@render item.icon()}
@@ -80,9 +80,18 @@ export {};
80
80
  </nav>
81
81
 
82
82
  <style>
83
+ /* System text: navigation is mono, uppercase, tracked */
84
+ nav :global(a),
85
+ nav :global(button) {
86
+ font-family: var(--font-mono);
87
+ font-size: var(--text-xs);
88
+ text-transform: uppercase;
89
+ letter-spacing: 0.08em;
90
+ }
91
+
83
92
  nav :global(.navbar-logo) {
84
93
  color: var(--color-accent);
85
- font-weight: 600;
94
+ font-weight: 700;
86
95
  font-size: var(--text-lg);
87
96
  }
88
97
 
@@ -102,7 +111,6 @@ export {};
102
111
  right: 0;
103
112
  height: 2px;
104
113
  background: var(--color-accent);
105
- box-shadow: var(--shadow-accent-glow);
106
114
  }
107
115
 
108
116
  nav :global(a:not(.active):hover),
@@ -171,7 +171,7 @@ export {};
171
171
  justify-content: center;
172
172
  width: 2.5rem;
173
173
  height: 2.5rem;
174
- border-radius: var(--radius-pill);
174
+ border-radius: var(--radius-sm);
175
175
  background: var(--color-accent-overlay-20);
176
176
  color: var(--color-accent);
177
177
  font-weight: 600;
@@ -204,11 +204,6 @@ export {};
204
204
  font-weight: 600;
205
205
  }
206
206
 
207
- aside :global(a.active),
208
- aside :global(button.active) {
209
- box-shadow: var(--shadow-accent-glow);
210
- }
211
-
212
207
  aside :global(a:not(.active):hover),
213
208
  aside :global(button:not(.active):hover) {
214
209
  background: var(--color-base-3);
@@ -222,7 +217,7 @@ export {};
222
217
  gap: 0.75rem;
223
218
  padding: 0.75rem 1rem;
224
219
  margin: 0.25rem 0.5rem;
225
- border-radius: var(--radius-md);
220
+ border-radius: 0;
226
221
  color: var(--color-text-soft);
227
222
  text-decoration: none;
228
223
  transition: all 0.2s var(--ease-luxe);
@@ -231,6 +226,8 @@ export {};
231
226
  background: transparent;
232
227
  width: calc(100% - 1rem);
233
228
  text-align: left;
234
- font-family: var(--font-body);
235
- font-size: 0.875rem;
229
+ font-family: var(--font-mono);
230
+ font-size: var(--text-xs);
231
+ text-transform: uppercase;
232
+ letter-spacing: 0.08em;
236
233
  }</style>
@@ -59,7 +59,7 @@ const orientationClasses = {
59
59
  horizontal: 'flex flex-row',
60
60
  vertical: 'flex flex-col'
61
61
  };
62
- const radiusClass = variant === 'pills' ? 'rounded-pill' : 'rounded-[var(--radius-md)]';
62
+ const radiusClass = variant === 'pills' ? 'rounded-pill' : 'rounded-none';
63
63
  export {};
64
64
  </script>
65
65
 
@@ -73,7 +73,7 @@ export {};
73
73
  onclick={() => handleTabClick(tab.id, tab.disabled)}
74
74
  onkeydown={(e) => handleKeyDown(e, tab.id)}
75
75
  disabled={tab.disabled}
76
- class="flex items-center gap-2 px-6 py-3 {radiusClass} font-body text-sm transition-all duration-300 ease-luxe {activeTab === tab.id ? 'bg-accent text-text accent-glow' : 'text-text-soft hover:bg-base-3'} {tab.disabled ? 'opacity-50 pointer-events-none' : 'cursor-pointer'}"
76
+ class="flex items-center gap-2 px-6 py-3 {radiusClass} font-mono text-xs uppercase tracking-[0.08em] transition-all duration-150 ease-luxe {activeTab === tab.id ? 'bg-accent text-text' : 'text-text-soft hover:bg-base-3'} {tab.disabled ? 'opacity-50 pointer-events-none' : 'cursor-pointer'}"
77
77
  >
78
78
  {#if tab.iconBefore}
79
79
  <span class="inline-flex items-center justify-center">
@@ -40,7 +40,7 @@ export {};
40
40
 
41
41
  {#if visible}
42
42
  <div
43
- class="glass-panel rounded-[var(--radius-lg)] p-4 flex gap-3 {variantClasses[variant]} {className} animate-[fade-in_0.2s_var(--ease-sharp)]"
43
+ class="glass-panel rounded-[var(--radius-sm)] p-4 flex gap-3 {variantClasses[variant]} {className} animate-[fade-in_0.2s_var(--ease-sharp)]"
44
44
  role={roleMap[variant]}
45
45
  aria-live={ariaLiveMap[variant]}
46
46
  >
@@ -103,12 +103,12 @@ $effect(() => {
103
103
 
104
104
  {#if open}
105
105
  <div
106
- class="fixed inset-0 z-[var(--z-50)] flex items-start justify-center pt-[20vh] p-4 bg-overlay backdrop-blur-md animate-[fade-in_0.2s_var(--ease-luxe)]"
106
+ class="fixed inset-0 z-[var(--z-50)] flex items-start justify-center pt-[20vh] p-4 bg-overlay animate-[fade-in_0.2s_var(--ease-luxe)]"
107
107
  onclick={handleBackdropClick}
108
108
  role="presentation"
109
109
  >
110
110
  <div
111
- class="panel-floating rounded-xl shadow-deep w-full max-w-[36rem] animate-[fade-up_0.3s_var(--ease-luxe)]"
111
+ class="panel-floating rounded-[var(--radius-md)] shadow-deep w-full max-w-[36rem] animate-[scale-in_0.2s_var(--ease-sharp)]"
112
112
  role="combobox"
113
113
  aria-expanded="true"
114
114
  aria-haspopup="listbox"
@@ -34,10 +34,10 @@ const positionClasses = {
34
34
  bottom: 'bottom-0 left-0 w-full'
35
35
  };
36
36
  const animationClasses = {
37
- left: 'animate-[slide-in-left_0.3s_var(--ease-luxe)]',
38
- right: 'animate-[slide-in-right_0.3s_var(--ease-luxe)]',
39
- top: 'animate-[slide-in-top_0.3s_var(--ease-luxe)]',
40
- bottom: 'animate-[slide-in-bottom_0.3s_var(--ease-luxe)]'
37
+ left: 'animate-[slide-in-left_0.2s_var(--ease-sharp)]',
38
+ right: 'animate-[slide-in-right_0.2s_var(--ease-sharp)]',
39
+ top: 'animate-[slide-in-top_0.2s_var(--ease-sharp)]',
40
+ bottom: 'animate-[slide-in-bottom_0.2s_var(--ease-sharp)]'
41
41
  };
42
42
  function handleClose() {
43
43
  open = false;
@@ -106,7 +106,7 @@ $effect(() => {
106
106
 
107
107
  {#if open}
108
108
  <div
109
- class="fixed inset-0 z-[var(--z-50)] bg-overlay backdrop-blur-md animate-[fade-in_0.2s_var(--ease-luxe)]"
109
+ class="fixed inset-0 z-[var(--z-50)] bg-overlay animate-[fade-in_0.2s_var(--ease-luxe)]"
110
110
  onclick={handleBackdropClick}
111
111
  role="presentation"
112
112
  >
@@ -76,7 +76,7 @@ $effect(() => {
76
76
  <div
77
77
  bind:this={dropdownElement}
78
78
  id={dropdownId}
79
- class="absolute {placementClasses[placement]} z-[var(--z-50)] panel-floating rounded-[var(--radius-lg)] shadow-[var(--shadow-deep)] min-w-[12rem] animate-[fade-up_0.2s_var(--ease-luxe)]"
79
+ class="absolute {placementClasses[placement]} z-[var(--z-50)] panel-floating rounded-[var(--radius-sm)] shadow-[var(--shadow-deep)] min-w-[12rem] animate-[scale-in_0.15s_var(--ease-sharp)]"
80
80
  style={fullWidth && triggerWidth > 0 ? `width: ${triggerWidth}px` : ''}
81
81
  role="menu"
82
82
  >
@@ -77,13 +77,13 @@ $effect(() => {
77
77
 
78
78
  {#if open}
79
79
  <div
80
- class="fixed inset-0 z-[var(--z-50)] flex items-center justify-center p-4 bg-overlay backdrop-blur-md animate-[fade-in_0.2s_var(--ease-luxe)]"
80
+ class="fixed inset-0 z-[var(--z-50)] flex items-center justify-center p-4 bg-overlay animate-[fade-in_0.2s_var(--ease-luxe)]"
81
81
  onclick={handleBackdropClick}
82
82
  role="presentation"
83
83
  >
84
84
  <div
85
85
  bind:this={modalElement}
86
- class="panel-floating rounded-[var(--radius-lg)] shadow-deep w-full {sizeClasses[size]} {className} animate-[fade-up_0.3s_var(--ease-luxe)] flex flex-col max-h-[90vh]"
86
+ class="panel-floating rounded-[var(--radius-md)] shadow-deep w-full {sizeClasses[size]} {className} animate-[scale-in_0.2s_var(--ease-sharp)] flex flex-col max-h-[90vh]"
87
87
  role="dialog"
88
88
  aria-modal="true"
89
89
  aria-labelledby={title ? titleId : undefined}
@@ -97,7 +97,7 @@ $effect(() => {
97
97
  <div
98
98
  bind:this={popoverElement}
99
99
  id={popoverId}
100
- class="absolute {placementClasses[actualPlacement]} z-[var(--z-50)] panel-floating rounded-[var(--radius-lg)] shadow-deep p-4 animate-[fade-up_0.2s_var(--ease-luxe)]"
100
+ class="absolute {placementClasses[actualPlacement]} z-[var(--z-50)] panel-floating rounded-[var(--radius-sm)] shadow-deep p-4 animate-[scale-in_0.15s_var(--ease-sharp)]"
101
101
  role="dialog"
102
102
  >
103
103
  {@render children?.()}
@@ -9,7 +9,7 @@ const heightClasses = {
9
9
  </script>
10
10
 
11
11
  <div
12
- class="relative bg-[var(--color-base-3)] border border-[var(--color-border)] rounded-[var(--radius-pill)] overflow-hidden shadow-[var(--shadow-deep)] {heightClasses[size]}"
12
+ class="relative bg-[var(--color-base-3)] border border-[var(--color-border)] rounded-none overflow-hidden shadow-[var(--shadow-deep)] {heightClasses[size]}"
13
13
  role="progressbar"
14
14
  aria-valuenow={value}
15
15
  aria-valuemin="0"
@@ -17,12 +17,12 @@ const heightClasses = {
17
17
  aria-label={label || `${percentage.toFixed(0)}% complete`}
18
18
  >
19
19
  <div
20
- class="h-full bg-[var(--color-accent)] accent-glow transition-all duration-500 ease-[var(--ease-luxe)]"
20
+ class="h-full bg-[var(--color-accent)] transition-all duration-500 ease-[var(--ease-luxe)]"
21
21
  style="width: {percentage}%"
22
22
  ></div>
23
23
 
24
24
  {#if showLabel}
25
- <div class="absolute inset-0 flex items-center justify-center text-xs font-semibold text-[var(--color-text)] text-glow">
25
+ <div class="absolute inset-0 flex items-center justify-center text-xs font-semibold text-[var(--color-text)]">
26
26
  {label || `${percentage.toFixed(0)}%`}
27
27
  </div>
28
28
  {/if}
@@ -8,7 +8,7 @@ const defaultDimensions = {
8
8
  const roundingClasses = {
9
9
  text: 'rounded-[var(--radius-sm)]',
10
10
  circular: 'rounded-[var(--radius-pill)]',
11
- rectangular: 'rounded-[var(--radius-lg)]'
11
+ rectangular: 'rounded-[var(--radius-sm)]'
12
12
  };
13
13
  const finalWidth = width || defaultDimensions[variant].width;
14
14
  const finalHeight = height || defaultDimensions[variant].height;
@@ -53,7 +53,7 @@ const finalHeight = height || defaultDimensions[variant].height;
53
53
  var(--color-accent-overlay-10),
54
54
  transparent
55
55
  );
56
- animation: shimmer 1.5s ease-in-out infinite;
56
+ animation: shimmer 2.8s ease-in-out infinite;
57
57
  }
58
58
 
59
59
  @keyframes shimmer {
@@ -14,7 +14,7 @@ const sizeClasses = {
14
14
  aria-label={label || 'Loading'}
15
15
  >
16
16
  <div
17
- class="{sizeClasses[size]} border-[var(--color-base-3)] border-t-[var(--color-accent)] rounded-[var(--radius-pill)] accent-glow animate-spin"
17
+ class="{sizeClasses[size]} border-[var(--color-base-3)] border-t-[var(--color-accent)] rounded-[var(--radius-pill)] animate-spin"
18
18
  ></div>
19
19
  <span class="sr-only">{label || 'Loading'}</span>
20
20
  </div>
@@ -42,7 +42,7 @@ const ariaLiveMap = {
42
42
  error: 'assertive'
43
43
  };
44
44
  const animationClasses = $derived(position.startsWith('bottom')
45
- ? 'animate-[fade-up_0.3s_var(--ease-luxe)]'
45
+ ? 'animate-[scale-in_0.2s_var(--ease-sharp)]'
46
46
  : 'animate-[fade-in_0.3s_var(--ease-luxe)]');
47
47
  const stackOffset = $derived(position.startsWith('bottom')
48
48
  ? `translateY(-${index * 5}rem)`
@@ -75,7 +75,7 @@ $effect(() => {
75
75
  style="transform: {stackOffset}"
76
76
  >
77
77
  <div
78
- class="panel-floating rounded-[var(--radius-lg)] p-4 min-w-[20rem] max-w-md flex gap-3 items-start {variantBorderClasses[variant]}"
78
+ class="panel-floating rounded-[var(--radius-sm)] p-4 min-w-[20rem] max-w-md flex gap-3 items-start {variantBorderClasses[variant]}"
79
79
  role={roleMap[variant]}
80
80
  aria-live={ariaLiveMap[variant]}
81
81
  aria-atomic="true"
@@ -87,7 +87,7 @@ $effect(() => {
87
87
  id={tooltipId}
88
88
  role="tooltip"
89
89
  aria-hidden={visible ? 'false' : 'true'}
90
- class="absolute {placementClasses[actualPlacement]} z-[var(--z-50)] panel-floating rounded-[var(--radius-md)] px-4 py-2.5 text-sm text-text whitespace-nowrap pointer-events-none {className} {visible ? 'animate-[fade-in_0.15s_var(--ease-luxe)] opacity-100' : 'opacity-0 invisible'}"
90
+ class="absolute {placementClasses[actualPlacement]} z-[var(--z-50)] panel-floating rounded-[var(--radius-sm)] px-4 py-2.5 text-sm text-text whitespace-nowrap pointer-events-none {className} {visible ? 'animate-[fade-in_0.15s_var(--ease-luxe)] opacity-100' : 'opacity-0 invisible'}"
91
91
  >
92
92
  {content}
93
93
  </div>
@@ -3,7 +3,7 @@ let { children } = $props();
3
3
  </script>
4
4
 
5
5
  <code
6
- class="inline-flex items-center transition-all duration-300 hover:shadow-[0_0_12px_var(--color-accent-overlay-30)]"
6
+ class="inline-flex items-center"
7
7
  style="background: var(--color-accent-overlay-10); border: 1px solid var(--color-border); padding: 0.125rem 0.375rem; border-radius: var(--radius-sm); font-family: var(--font-mono); color: var(--color-accent-soft); font-size: 0.9em;"
8
8
  >
9
9
  {@render children?.()}
@@ -64,7 +64,7 @@ export {};
64
64
  </script>
65
65
 
66
66
  <div class="relative">
67
- <div class="panel-raised rounded-[var(--radius-lg)] overflow-hidden">
67
+ <div class="panel-raised rounded-none overflow-hidden">
68
68
  <div
69
69
  class="flex transition-transform duration-300 ease-luxe"
70
70
  style="transform: translateX(-{currentIndex * 100}%);"
@@ -88,7 +88,7 @@ export {};
88
88
  <button
89
89
  type="button"
90
90
  onclick={goToPrev}
91
- class="absolute left-2 top-1/2 -translate-y-1/2 obsidian-surface metal-edge rounded-full p-2 text-text hover:accent-glow transition-all"
91
+ class="absolute left-2 top-1/2 -translate-y-1/2 obsidian-surface metal-edge rounded-[var(--radius-sm)] p-2 text-text hover:border-[var(--color-border-strong)] transition-all"
92
92
  aria-label="Previous item"
93
93
  >
94
94
  <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -99,7 +99,7 @@ export {};
99
99
  <button
100
100
  type="button"
101
101
  onclick={goToNext}
102
- class="absolute right-2 top-1/2 -translate-y-1/2 obsidian-surface metal-edge rounded-full p-2 text-text hover:accent-glow transition-all"
102
+ class="absolute right-2 top-1/2 -translate-y-1/2 obsidian-surface metal-edge rounded-[var(--radius-sm)] p-2 text-text hover:border-[var(--color-border-strong)] transition-all"
103
103
  aria-label="Next item"
104
104
  >
105
105
  <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -114,7 +114,7 @@ export {};
114
114
  <button
115
115
  type="button"
116
116
  onclick={() => goToIndex(index)}
117
- class="w-2 h-2 rounded-full transition-all {index === currentIndex ? 'accent-glow bg-accent w-8' : 'bg-text-muted'}"
117
+ class="w-2 h-2 rounded-full transition-all {index === currentIndex ? 'bg-accent w-8' : 'bg-text-muted'}"
118
118
  aria-label="Go to item {index + 1}"
119
119
  >
120
120
  </button>
@@ -11,7 +11,7 @@ let effectiveOpen = $derived(onToggle ? open : openLocal);
11
11
  let maxHeight = $derived(effectiveOpen && contentElement ? `${contentElement.scrollHeight}px` : '0px');
12
12
  </script>
13
13
 
14
- <div class="border border-border rounded-md overflow-hidden {effectiveOpen ? 'panel-raised' : ''}">
14
+ <div class="border border-border rounded-[var(--radius-sm)] overflow-hidden {effectiveOpen ? 'panel-raised' : ''}">
15
15
  <button
16
16
  id={headerId}
17
17
  type="button"
@@ -37,6 +37,7 @@ let { title, text, features, children, class: className = '', ...restProps } = $
37
37
 
38
38
  .hero-section {
39
39
  text-align: center;
40
- padding-bottom: 3rem;
41
- margin-bottom: 3rem;
40
+ padding-top: 2rem;
41
+ padding-bottom: 4rem;
42
+ margin-bottom: 4rem;
42
43
  }</style>
@@ -1,4 +1,4 @@
1
- <script lang="ts">let { messages = [], prompt = '>', placeholder = 'Enter command...', height = '500px', maxHeight = '80vh', showTimestamps = false, autoScroll = true, typewriterEffect = false, typewriterSpeed = 50, showScanlines = true, glowEffect = true, onSubmit, disabled = false, class: className = '', ...restProps } = $props();
1
+ <script lang="ts">let { messages = [], prompt = '>', placeholder = 'Enter command...', height = '500px', maxHeight = '80vh', showTimestamps = false, autoScroll = true, typewriterEffect = false, typewriterSpeed = 50, showScanlines = true, glowEffect = false, onSubmit, disabled = false, class: className = '', ...restProps } = $props();
2
2
  let inputValue = $state('');
3
3
  let consoleContainer = $state();
4
4
  let inputElement = $state();