oat-glassed 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/js/dropdown.js ADDED
@@ -0,0 +1,74 @@
1
+ /**
2
+ * oat - Dropdown Component
3
+ * Provides positioning, keyboard navigation, and ARIA state management.
4
+ *
5
+ * Usage:
6
+ * <ot-dropdown>
7
+ * <button popovertarget="menu-id">Options</button>
8
+ * <menu popover id="menu-id">
9
+ * <button role="menuitem">Item 1</button>
10
+ * <button role="menuitem">Item 2</button>
11
+ * </menu>
12
+ * </ot-dropdown>
13
+ */
14
+
15
+ import { OtBase } from './base.js';
16
+
17
+ class OtDropdown extends OtBase {
18
+ #menu;
19
+ #trigger;
20
+ #position;
21
+ #items;
22
+
23
+ init() {
24
+ this.#menu = this.$('[popover]');
25
+ this.#trigger = this.$('[popovertarget]');
26
+
27
+ if (!this.#menu || !this.#trigger) return;
28
+
29
+ this.#menu.addEventListener('toggle', this);
30
+ this.#menu.addEventListener('keydown', this);
31
+
32
+ this.#position = () => {
33
+ // Position has to be calculated and applied manually because
34
+ // popover positioning is like fixed, relative to the window.
35
+ const r = this.#trigger.getBoundingClientRect();
36
+ const m = this.#menu.getBoundingClientRect();
37
+
38
+ // Flip if menu overflows viewport.
39
+ this.#menu.style.top = `${r.bottom + m.height > window.innerHeight ? r.top - m.height : r.bottom}px`;
40
+ this.#menu.style.left = `${r.left + m.width > window.innerWidth ? r.right - m.width : r.left}px`;
41
+ };
42
+ }
43
+
44
+ ontoggle(e) {
45
+ if (e.newState === 'open') {
46
+ this.#position();
47
+ window.addEventListener('scroll', this.#position, true);
48
+ window.addEventListener('resize', this.#position);
49
+ this.#items = this.$$('[role="menuitem"]');
50
+ this.#items[0]?.focus();
51
+ this.#trigger.ariaExpanded = 'true';
52
+ } else {
53
+ this.cleanup();
54
+ this.#items = null;
55
+ this.#trigger.ariaExpanded = 'false';
56
+ this.#trigger.focus();
57
+ }
58
+ }
59
+
60
+ onkeydown(e) {
61
+ if (!e.target.matches('[role="menuitem"]')) return;
62
+
63
+ const idx = this.#items.indexOf(e.target);
64
+ const next = this.keyNav(e, idx, this.#items.length, 'ArrowUp', 'ArrowDown', true);
65
+ if (next >= 0) this.#items[next].focus();
66
+ }
67
+
68
+ cleanup() {
69
+ window.removeEventListener('scroll', this.#position, true);
70
+ window.removeEventListener('resize', this.#position);
71
+ }
72
+ }
73
+
74
+ customElements.define('ot-dropdown', OtDropdown);
package/js/index.js ADDED
@@ -0,0 +1,13 @@
1
+ import './base.js';
2
+ import './tabs.js';
3
+ import './dropdown.js';
4
+ import './tooltip.js';
5
+ import './sidebar.js';
6
+ import './command.js';
7
+ import { toast, toastEl, toastClear } from './toast.js';
8
+
9
+ // Register the global window.ot.* APIs.
10
+ const ot = window.ot || (window.ot = {});
11
+ ot.toast = toast;
12
+ ot.toast.el = toastEl;
13
+ ot.toast.clear = toastClear;
package/js/sidebar.js ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Sidebar toggle handler
3
+ * Toggles data-sidebar-open on layout when toggle button is clicked
4
+ */
5
+ document.addEventListener('click', (e) => {
6
+ const toggle = e.target.closest('[data-sidebar-toggle]');
7
+ if (toggle) {
8
+ const layout = toggle.closest('[data-sidebar-layout]');
9
+ layout?.toggleAttribute('data-sidebar-open');
10
+ return;
11
+ }
12
+
13
+ // Dismiss sidebar when clicking outside (when sidebar is not an overlay).
14
+ if (!e.target.closest('[data-sidebar]')) {
15
+ const layout = document.querySelector('[data-sidebar-layout][data-sidebar-open]');
16
+ // Hardcode breakpoint (for now) as there's no way to use a CSS variable in
17
+ // the @media{} query which could've been picked up here.
18
+ if (layout && window.matchMedia('(max-width: 768px)').matches) {
19
+ layout.removeAttribute('data-sidebar-open');
20
+ }
21
+ }
22
+ });
package/js/tabs.js ADDED
@@ -0,0 +1,94 @@
1
+ /**
2
+ * oat - Tabs Component
3
+ * Provides keyboard navigation and ARIA state management.
4
+ *
5
+ * Usage:
6
+ * <ot-tabs>
7
+ * <div role="tablist">
8
+ * <button role="tab">Tab 1</button>
9
+ * <button role="tab">Tab 2</button>
10
+ * </div>
11
+ * <div role="tabpanel">Content 1</div>
12
+ * <div role="tabpanel">Content 2</div>
13
+ * </ot-tabs>
14
+ */
15
+
16
+ import { OtBase } from './base.js';
17
+
18
+ class OtTabs extends OtBase {
19
+ #tabs = [];
20
+ #panels = [];
21
+
22
+ init() {
23
+ const tablist = this.$(':scope > [role="tablist"]');
24
+ this.#tabs = tablist ? [...tablist.querySelectorAll('[role="tab"]')] : [];
25
+ this.#panels = this.$$(':scope > [role="tabpanel"]');
26
+
27
+ if (this.#tabs.length === 0 || this.#panels.length === 0) {
28
+ console.warn('ot-tabs: Missing tab or tabpanel elements');
29
+ return;
30
+ }
31
+
32
+ // Generate IDs and set up ARIA.
33
+ this.#tabs.forEach((tab, i) => {
34
+ const panel = this.#panels[i];
35
+ if (!panel) return;
36
+
37
+ const tabId = tab.id || `ot-tab-${this.uid()}`;
38
+ const panelId = panel.id || `ot-panel-${this.uid()}`;
39
+
40
+ tab.id = tabId;
41
+ panel.id = panelId;
42
+ tab.setAttribute('aria-controls', panelId);
43
+ panel.setAttribute('aria-labelledby', tabId);
44
+ });
45
+
46
+ tablist.addEventListener('click', this);
47
+ tablist.addEventListener('keydown', this);
48
+
49
+ // Find initially active tab or default to first.
50
+ const activeTab = this.#tabs.findIndex(t => t.ariaSelected === 'true');
51
+ this.#activate(activeTab >= 0 ? activeTab : 0);
52
+ }
53
+
54
+ onclick(e) {
55
+ const index = this.#tabs.indexOf(e.target.closest('[role="tab"]'));
56
+ if (index >= 0) this.#activate(index);
57
+ }
58
+
59
+ onkeydown(e) {
60
+ if (!e.target.closest('[role="tab"]')) return;
61
+
62
+ const next = this.keyNav(e, this.activeIndex, this.#tabs.length, 'ArrowLeft', 'ArrowRight');
63
+ if (next >= 0) {
64
+ this.#activate(next);
65
+ this.#tabs[next].focus();
66
+ }
67
+ }
68
+
69
+ #activate(idx) {
70
+ this.#tabs.forEach((tab, i) => {
71
+ const isActive = i === idx;
72
+ tab.ariaSelected = String(isActive);
73
+ tab.tabIndex = isActive ? 0 : -1;
74
+ });
75
+
76
+ this.#panels.forEach((panel, i) => {
77
+ panel.hidden = i !== idx;
78
+ });
79
+
80
+ this.emit('ot-tab-change', { index: idx, tab: this.#tabs[idx] });
81
+ }
82
+
83
+ get activeIndex() {
84
+ return this.#tabs.findIndex(t => t.ariaSelected === 'true');
85
+ }
86
+
87
+ set activeIndex(value) {
88
+ if (value >= 0 && value < this.#tabs.length) {
89
+ this.#activate(value);
90
+ }
91
+ }
92
+ }
93
+
94
+ customElements.define('ot-tabs', OtTabs);
package/js/toast.js ADDED
@@ -0,0 +1,144 @@
1
+ /**
2
+ * oat - Toast Notifications
3
+ *
4
+ * Usage:
5
+ * ot.toast('Saved!')
6
+ * ot.toast('Action completed successfully', 'All good')
7
+ * ot.toast('Operation completed.', 'Success', { variant: 'success' })
8
+ * ot.toast('Something went wrong.', 'Error', { variant: 'danger', placement: 'bottom-center' })
9
+ *
10
+ * // Custom markup
11
+ * ot.toast.el(element)
12
+ * ot.toast.el(element, { duration: 4000, placement: 'bottom-center' })
13
+ * ot.toast.el(document.querySelector('#my-template'))
14
+ */
15
+
16
+ const toasts = {};
17
+
18
+ function _get(placement) {
19
+ if (!toasts[placement]) {
20
+ const el = document.createElement('div');
21
+ el.className = 'toast-container';
22
+ el.setAttribute('popover', 'manual');
23
+ el.setAttribute('data-placement', placement);
24
+ document.body.appendChild(el);
25
+ toasts[placement] = el;
26
+ }
27
+
28
+ return toasts[placement];
29
+ }
30
+
31
+ function _show(el, options = {}) {
32
+ const { placement = 'top-right', duration = 4000 } = options;
33
+ const p = _get(placement);
34
+
35
+ el.classList.add('toast');
36
+
37
+ let timeout;
38
+
39
+ // Pause on hover.
40
+ el.onmouseenter = () => clearTimeout(timeout);
41
+ el.onmouseleave = () => {
42
+ if (duration > 0) {
43
+ timeout = setTimeout(() => _remove(el, p), duration);
44
+ }
45
+ };
46
+
47
+ // Show with animation.
48
+ el.setAttribute('data-entering', '');
49
+ p.appendChild(el);
50
+ p.showPopover();
51
+
52
+ // Double RAF to compute styles before transition starts.
53
+ requestAnimationFrame(() => {
54
+ requestAnimationFrame(() => {
55
+ el.removeAttribute('data-entering');
56
+ });
57
+ });
58
+
59
+ if (duration > 0) {
60
+ timeout = setTimeout(() => _remove(el, p), duration);
61
+ }
62
+
63
+ return el;
64
+ }
65
+
66
+ function _remove(el, container) {
67
+ // Ignore if already in the process of exiting.
68
+ if (el.hasAttribute('data-exiting')) {
69
+ return;
70
+ }
71
+ el.setAttribute('data-exiting', '');
72
+
73
+ const cleanup = () => {
74
+ el.remove();
75
+ if (!container.children.length) {
76
+ container.hidePopover();
77
+ }
78
+ };
79
+
80
+ el.addEventListener('transitionend', cleanup, { once: true });
81
+
82
+ // Couldn't confirm what unit this actually returns across browsers, so
83
+ // assume that it could be ms or s. Also, setTimeou() is required because
84
+ // there's no guarantee that the `transitionend` event will always fire,
85
+ // eg: clients that disable animations.
86
+ const t = getComputedStyle(el).getPropertyValue('--transition').trim();
87
+ const val = parseFloat(t);
88
+ const ms = t.endsWith('ms') ? val : val * 1000;
89
+ setTimeout(cleanup, ms);
90
+ }
91
+
92
+ // Show a text toast.
93
+ export function toast(message, title, options = {}) {
94
+ const { variant = 'info', ...rest } = options;
95
+
96
+ const el = document.createElement('output');
97
+ el.setAttribute('data-variant', variant);
98
+
99
+ if (title) {
100
+ const titleEl = document.createElement('h6');
101
+ titleEl.className = 'toast-title';
102
+ titleEl.textContent = title;
103
+ el.appendChild(titleEl);
104
+ }
105
+
106
+ const msgEl = document.createElement('div');
107
+ msgEl.className = 'toast-message';
108
+ msgEl.textContent = message;
109
+ el.appendChild(msgEl);
110
+
111
+ return _show(el, rest);
112
+ }
113
+
114
+ // Element-based toast.
115
+ export function toastEl(el, options = {}) {
116
+ let t;
117
+
118
+ if (el instanceof HTMLTemplateElement) {
119
+ t = el.content.firstElementChild?.cloneNode(true);
120
+ } else if (el) {
121
+ t = el.cloneNode(true);
122
+ }
123
+
124
+ if (!t) {
125
+ return;
126
+ }
127
+
128
+ t.removeAttribute('id');
129
+
130
+ return _show(t, options);
131
+ }
132
+
133
+ // Clear all toasts.
134
+ export function toastClear(placement) {
135
+ if (placement && toasts[placement]) {
136
+ toasts[placement].innerHTML = '';
137
+ toasts[placement].hidePopover();
138
+ } else {
139
+ Object.values(toasts).forEach(c => {
140
+ c.innerHTML = '';
141
+ c.hidePopover();
142
+ });
143
+ }
144
+ }
package/js/tooltip.js ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * oat - Tooltip Enhancement
3
+ * Converts title attributes to data-tooltip for custom styling.
4
+ * Progressive enhancement: native title works without JS.
5
+ */
6
+
7
+ document.addEventListener('DOMContentLoaded', () => {
8
+ const _attrib = 'title', _sel = '[title]';
9
+ const apply = el => {
10
+ const t = el.getAttribute(_attrib);
11
+ if (!t) return;
12
+ el.setAttribute('data-tooltip', t);
13
+ el.hasAttribute('aria-label') || el.setAttribute('aria-label', t);
14
+
15
+ // Kill the original 'title'.
16
+ el.removeAttribute(_attrib);
17
+ };
18
+
19
+ // Apply to all elements on load.
20
+ document.querySelectorAll(_sel).forEach(apply);
21
+
22
+ // Apply to new elements.
23
+ new MutationObserver(muts => {
24
+ for (const m of muts) {
25
+ apply(m.target);
26
+
27
+ for (const n of m.addedNodes)
28
+ if (n.nodeType === 1) {
29
+ apply(n);
30
+ n.querySelectorAll(_sel).forEach(apply);
31
+ }
32
+ }
33
+ }).observe(document.body, {
34
+ childList: true, subtree: true, attributes: true, attributeFilter: [_attrib]
35
+ });
36
+ });
@@ -0,0 +1 @@
1
+ @layer theme,base,components,animations,utilities;@layer base{*,*:before,*:after{box-sizing:border-box;-webkit-tap-highlight-color:transparent}*{margin:0}html{tab-size:4}body,dialog,[popover]{font-family:var(--font-sans);font-size:var(--text-regular);line-height:var(--leading-normal);color:var(--foreground)}body{background-color:var(--background);color:var(--foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}main{padding-block-start:var(--space-8)}img,picture,video,canvas,svg{max-width:100%}p,h1,h2,h3,h4,h5,h6{overflow-wrap:break-word}h1,h2,h3,h4,h5,h6{font-weight:var(--font-semibold);line-height:1.25;&:first-child{margin-block-start:0}}h1{font-size:var(--text-1);margin:var(--space-10) 0 var(--space-6)}h2{font-size:var(--text-2);margin:var(--space-8) 0 var(--space-5)}h3{font-size:var(--text-3);margin:var(--space-6) 0 var(--space-4)}h4{font-size:var(--text-4);margin:var(--space-5) 0 var(--space-3)}h5{font-size:var(--text-5);margin:var(--space-4) 0 var(--space-2)}h6{font-size:var(--text-regular);margin:var(--space-4) 0 var(--space-2)}p{margin-block-end:var(--space-4);&:last-child{margin-block-end:0}}a{color:var(--link);text-decoration:underline;text-underline-offset:2px;transition:color var(--transition-fast);&:hover{color:rgb(from var(--link) r g b / .8)}}strong,b{font-weight:var(--font-semibold)}em,i{font-style:italic}small{font-size:var(--text-7)}code{font-family:var(--font-mono);font-size:.875em;padding:calc(var(--space-1) / 2) var(--space-2);background-color:var(--faint);border:1px solid var(--border);border-radius:var(--radius-small)}pre{font-family:var(--font-mono);padding:var(--space-5);background-color:light-dark(rgb(246 246 250 / .45),rgb(18 18 24 / .45));border:1px solid var(--glass-border);border-radius:var(--radius-medium);overflow-x:auto;margin-block-end:var(--space-4);box-shadow:var(--glass-edge);code{padding:0;background:none;border:none;border-radius:0}}blockquote{border-inline-start:3px solid light-dark(rgb(from var(--primary) r g b / .3),rgb(from var(--primary) r g b / .4));padding:var(--space-3) var(--space-4);margin:var(--space-4) 0;color:var(--muted-foreground);font-style:italic;background-color:var(--faint);border-radius:0 var(--radius-small) var(--radius-small) 0}hr{border:none;border-top:1px solid var(--border);margin:var(--space-2) 0}ul,ol{padding-inline-start:var(--space-6);margin-block-end:var(--space-4)}ul{list-style-type:disc}ol{list-style-type:decimal}li{margin-block-end:var(--space-1)}mark{background-color:rgb(from var(--warning) r g b / .3);padding:calc(var(--space-1) / 2) var(--space-1);border-radius:var(--radius-small)}[hidden]{display:none}:focus-visible{outline:2px solid rgb(from var(--ring) r g b / .6);outline-offset:2px}:disabled{opacity:.5;cursor:not-allowed}}@layer theme{:root{color-scheme:light dark;--background: light-dark(#ffffff, #030712);--foreground: light-dark(#111827, #f9fafb);--card: light-dark(rgb(255 255 255 / .55), rgb(17 24 39 / .48));--card-foreground: light-dark(#111827, #f9fafb);--primary: light-dark(#111827, #f9fafb);--primary-foreground: light-dark(#ffffff, #111827);--secondary: light-dark(rgb(243 244 246 / .55), rgb(31 41 55 / .4));--secondary-foreground: light-dark(#1f2937, #f3f4f6);--muted: light-dark(rgb(243 244 246 / .45), rgb(31 41 55 / .4));--muted-foreground: light-dark(#6b7280, #9ca3af);--faint: light-dark(rgb(249 250 251 / .35), rgb(17 24 39 / .3));--faint-foreground: light-dark(#9ca3af, #6b7280);--accent: light-dark(rgb(243 244 246 / .55), rgb(31 41 55 / .4));--link: light-dark(#0284c7, #7dd3fc);--danger: light-dark(#ef4444, #f87171);--danger-foreground: light-dark(#ffffff, #111827);--success: light-dark(#10b981, #34d399);--success-foreground: light-dark(#ffffff, #111827);--warning: light-dark(#f59e0b, #fbbf24);--warning-foreground: #111827;--border: light-dark(rgb(0 0 0 / .08), rgb(255 255 255 / .08));--input: light-dark(rgb(0 0 0 / .1), rgb(255 255 255 / .1));--ring: light-dark(#111827, #f9fafb);--glass-blur: 12px;--glass-saturate: 120%;--glass-border: light-dark( rgb(255 255 255 / .65), rgb(255 255 255 / .09) );--glass-highlight: light-dark( linear-gradient( 135deg, rgb(255 255 255 / .7) 0%, rgb(255 255 255 / .15) 40%, rgb(255 255 255 / 0) 60% ), linear-gradient( 135deg, rgb(255 255 255 / .1) 0%, rgb(255 255 255 / .03) 40%, rgb(255 255 255 / 0) 60% ) );--glass-edge: light-dark( inset 0 0 0 1px rgb(255 255 255 / .12), inset 0 1px 0 rgb(255 255 255 / .15), 0 8px 32px rgb(0 0 0 / .08), inset 0 0 0 1px rgb(255 255 255 / .08), inset 0 1px 0 rgb(255 255 255 / .1), 0 8px 32px rgb(0 0 0 / .25) );--space-1: .25rem;--space-2: .5rem;--space-3: .75rem;--space-4: 1rem;--space-5: 1.25rem;--space-6: 1.5rem;--space-8: 2rem;--space-10: 2.5rem;--space-12: 3rem;--space-14: 3.5rem;--space-16: 4rem;--space-18: 4.5rem;--radius-small: .25rem;--radius-medium: .5rem;--radius-large: 1.25rem;--radius-full: 9999px;--bar-height: .5rem;--font-sans: system-ui, -apple-system, sans-serif;--font-mono: ui-monospace, "SF Mono", Consolas, monospace;--text-1: clamp(1.75rem, 1.5rem + 1.1vw, 2.25rem);--text-2: clamp(1.5rem, 1.3rem + .8vw, 1.875rem);--text-3: clamp(1.25rem, 1.1rem + .5vw, 1.5rem);--text-4: clamp(1.125rem, 1.05rem + .3vw, 1.25rem);--text-5: 1.125rem;--text-6: 1rem;--text-7: .875rem;--text-8: .75rem;--text-regular: var(--text-6);--leading-normal: 1.6;--font-normal: 400;--font-medium: 500;--font-semibold: 600;--font-bold: 600;--shadow-small: light-dark( 0 1px 4px rgb(0 0 0 / .03), 0 .5px 1px rgb(0 0 0 / .02), 0 1px 4px rgb(0 0 0 / .2), 0 .5px 1px rgb(0 0 0 / .15) );--shadow-medium: light-dark( 0 4px 20px -4px rgb(0 0 0 / .06), 0 1px 4px rgb(0 0 0 / .03), 0 4px 20px -4px rgb(0 0 0 / .35), 0 1px 4px rgb(0 0 0 / .2) );--shadow-large: light-dark( 0 16px 48px -8px rgb(0 0 0 / .07), 0 4px 16px -4px rgb(0 0 0 / .03), 0 16px 48px -8px rgb(0 0 0 / .45), 0 4px 16px -4px rgb(0 0 0 / .2) );--shadow-glow: light-dark( 0 0 0 .5px rgb(0 0 0 / .02), 0 4px 24px -4px rgb(0 0 0 / .05), 0 0 0 .5px rgb(255 255 255 / .05), 0 4px 28px -4px rgb(0 0 0 / .4) );--transition-fast: .12s cubic-bezier(.4, 0, .2, 1);--transition: .2s cubic-bezier(.4, 0, .2, 1);--transition-spring: .5s cubic-bezier(.175, .885, .32, 1.1);--z-dropdown: 50;--z-modal: 200}@media(prefers-reduced-transparency:reduce){:root{--glass-blur: 0px;--glass-saturate: 100%;--card: light-dark(rgb(243 244 246 / .95), rgb(17 24 39 / .95));--secondary: light-dark(rgb(229 231 235 / .95), rgb(31 41 55 / .92));--muted: light-dark(rgb(229 231 235 / .92), rgb(31 41 55 / .88));--faint: light-dark(rgb(243 244 246 / .9), rgb(17 24 39 / .85));--accent: light-dark(rgb(229 231 235 / .95), rgb(31 41 55 / .92));--glass-highlight: none;--glass-edge: none}*,*:before,*:after,*::backdrop{backdrop-filter:none!important;-webkit-backdrop-filter:none!important}}}@layer animations{.animate-pop-in{opacity:1;transform:perspective(1000px) rotateX(0) translateZ(0);will-change:transform,opacity;transition:opacity .25s cubic-bezier(.175,.885,.32,1.075),transform .25s cubic-bezier(.175,.885,.32,1.075),overlay .25s cubic-bezier(.175,.885,.32,1.075) allow-discrete,display .25s cubic-bezier(.175,.885,.32,1.075) allow-discrete;@starting-style{opacity:0;transform:perspective(1000px) rotateX(-12deg) translateZ(-60px)}&[data-state=closing]{opacity:0;transform:perspective(1000px) rotateX(-12deg) translateZ(-60px)}&[data-state=closing]::backdrop{opacity:0}}dialog::backdrop{opacity:1;transition:opacity .25s cubic-bezier(.4,0,.2,1);@starting-style{opacity:0}}.animate-slide-in{opacity:1;transform:translate(0) scale(1);will-change:transform,opacity;transition:opacity .3s cubic-bezier(.175,.885,.32,1.075),transform .3s cubic-bezier(.175,.885,.32,1.075);@starting-style{opacity:0;transform:translate(100%) scale(.95)}&[data-state=closing]{opacity:0;transform:translate(100%) scale(.95)}}}@layer base{:is(button,[type=submit],[type=reset],[type=button],a.button),::file-selector-button{--_hov: color-mix(in srgb, var(--primary), white 20%);display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-2) var(--space-4);font-size:var(--text-7);font-weight:var(--font-medium);line-height:var(--leading-normal);white-space:nowrap;text-decoration:none;background-color:var(--primary);color:var(--primary-foreground);border-radius:var(--radius-medium);border:1px solid rgb(from #fff r g b / .15);box-shadow:inset 0 1px #ffffff1f,0 1px 4px #00000014;transition:background-color var(--transition-fast),opacity var(--transition-fast),transform var(--transition-fast),box-shadow var(--transition-fast);&:not(:disabled){cursor:pointer}&:hover:not(:disabled){background-color:var(--_hov);box-shadow:inset 0 1px #ffffff26,0 2px 8px #0000001f}&:active:not(:disabled){transform:translateY(1px);box-shadow:inset 0 1px 2px #0000001a}&[data-variant=secondary]{--_hov: color-mix(in srgb, var(--secondary), black 5%);background-color:var(--secondary);color:var(--secondary-foreground);border-color:light-dark(rgb(255 255 255 / .08),rgb(255 255 255 / .06));box-shadow:inset 0 1px #ffffff14,var(--shadow-small)}&[data-variant=danger]{--_hov: color-mix(in srgb, var(--danger), black 12%);background-color:var(--danger);color:var(--danger-foreground)}&:is(.outline,.ghost){--_hov: var(--accent);background-color:transparent;color:var(--foreground);box-shadow:none;border-color:transparent;&:hover:not(:disabled){box-shadow:var(--shadow-small)}&[data-variant=danger]{--_hov: color-mix(in srgb, var(--danger), transparent 90%);color:var(--danger)}&[data-variant=secondary]{--_hov: color-mix(in srgb, var(--secondary), transparent 80%);color:var(--secondary-foreground)}}&.outline{border-color:var(--border);&[data-variant=danger]{border-color:var(--danger)}&[data-variant=secondary]{border-color:var(--border)}}&.ghost{border-color:transparent}&.small{padding:var(--space-1) var(--space-3);font-size:var(--text-8)}&.large{height:3rem;padding:0 var(--space-6);font-size:var(--text-regular)}&.icon{width:2.5rem;padding:0;&.small{width:2rem}&.large{width:3rem}}}::file-selector-button{background-color:transparent;color:var(--foreground);border:1px solid var(--border)}::file-selector-button:hover{background-color:var(--accent)}}@layer components{menu.buttons{list-style-type:none;padding-inline-start:0;display:inline-flex;>li{&:first-child>*{border-start-start-radius:var(--radius-medium);border-end-start-radius:var(--radius-medium)}&:last-child>*{border-start-end-radius:var(--radius-medium);border-end-end-radius:var(--radius-medium)}>*{border-radius:0}&:not(:last-child)>*{border-inline-end:1px solid rgb(from var(--primary-foreground) r g b / .15)}}}}@layer base{label{display:block;font-size:var(--text-7);font-weight:var(--font-medium);&:has(input:where([type=checkbox],[type=radio])){display:inline-flex;align-items:center;gap:var(--space-2);font-weight:var(--font-normal)}}:where(input:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color]),textarea,select){width:100%;margin-block-start:var(--space-1);padding:var(--space-2) var(--space-3);font-size:var(--text-7);line-height:var(--leading-normal);background-color:light-dark(rgb(255 255 255 / .45),rgb(255 255 255 / .04));color:var(--foreground);border:1px solid var(--input);border-radius:var(--radius-medium);box-shadow:inset 0 1px 0 light-dark(rgb(255 255 255 / .6),rgb(255 255 255 / .04));transition:border-color var(--transition-fast),box-shadow var(--transition-fast),background-color var(--transition-fast);&::placeholder{color:var(--muted-foreground)}&:focus{outline:none;border-color:var(--ring);background-color:light-dark(rgb(255 255 255 / .6),rgb(255 255 255 / .06));box-shadow:0 0 0 3px rgb(from var(--ring) r g b / .12),inset 0 1px 0 light-dark(rgb(255 255 255 / .5),rgb(255 255 255 / .03));z-index:1}&:disabled{background-color:var(--muted)}&:is([aria-invalid=true],:user-invalid){border-color:var(--danger);&:focus{box-shadow:0 0 0 3px rgb(from var(--danger) r g b / .12),inset 0 1px 0 light-dark(rgb(255 255 255 / .5),rgb(255 255 255 / .03))}}}textarea{height:auto;min-height:5rem;padding:var(--space-3);resize:vertical}select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--space-2) center;padding-inline-end:var(--space-6)}input:where([type=checkbox],[type=radio]){appearance:none;width:1rem;height:1rem;margin:0;position:relative;background-color:var(--background);border:1px solid var(--input);transition:background-color var(--transition-fast),border-color var(--transition-fast);&:checked{background-color:var(--primary);border-color:var(--primary);&:after{content:"";position:absolute;inset:0;background-color:var(--primary-foreground);mask-position:center;mask-repeat:no-repeat;mask-size:100%}}}input[type=checkbox]{border-radius:var(--radius-small);&:checked:after{mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='4'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E")}&[role=switch]{--switch-height: calc(var(--bar-height) * 3);--switch-inset: 2px;--switch-thumb: calc(var(--switch-height) - var(--switch-inset) * 3);width:calc(var(--switch-height) * 2);height:var(--switch-height);border-radius:var(--radius-full);background-color:var(--input);&:before{content:"";position:absolute;top:50%;left:var(--switch-inset);transform:translateY(-50%);width:var(--switch-thumb);height:var(--switch-thumb);background-color:var(--background);border-radius:var(--radius-full);transition:transform var(--transition);box-shadow:var(--shadow-small)}&:checked{background-color:var(--primary);&:after{content:none}&:before{transform:translateY(-50%) translate(var(--switch-height))}}}}input[type=radio]{border-radius:var(--radius-full);&:checked:after{mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='4' fill='currentColor'/%3E%3C/svg%3E")}}:where(input:where([type=checkbox],[type=radio],[type=range]),select):not(:disabled),label:has(input:where([type=checkbox],[type=radio]):not(:disabled)){cursor:pointer}input[type=range]{width:100%;height:var(--bar-height);appearance:none;background:var(--muted);border-radius:var(--radius-full);&::-webkit-slider-thumb{appearance:none;width:1.25rem;height:1.25rem;background:var(--primary);border-radius:var(--radius-full);transition:transform var(--transition-fast);&:hover{transform:scale(1.1)}}&::-moz-range-thumb{width:1.25rem;height:1.25rem;background:var(--primary);border:none;border-radius:var(--radius-full)}}fieldset{border:1px solid var(--border);border-radius:var(--radius-medium);padding:var(--space-4);margin-block-end:var(--space-4);content-visibility:auto}legend{font-size:var(--text-7);font-weight:var(--font-medium);padding:0 var(--space-2)}}@layer components{fieldset.group{display:flex;align-items:stretch;border:none;padding:0;margin:0;>:is(input,textarea,select){flex:1;margin-block-start:0;&:not(:focus):not(:last-child){border-inline-end-color:transparent}}>:is(input,textarea,select,button){border-radius:0;&:first-child{border-radius:var(--radius-medium) 0 0 var(--radius-medium)}&:last-child{border-radius:0 var(--radius-medium) var(--radius-medium) 0}}>legend{float:inline-start;display:inline-flex;align-items:center;padding:0 var(--space-3);line-height:var(--leading-normal);font-weight:var(--font-normal);color:var(--muted-foreground);background-color:var(--muted);border:1px solid var(--input);border-inline-end:none;border-radius:var(--radius-medium) 0 0 var(--radius-medium)}}[data-field]{margin-block-end:var(--space-4);[data-hint],.error{font-size:var(--text-8);font-weight:var(--font-normal);color:var(--muted-foreground);margin-block-start:var(--space-1)}.error{display:none}&[data-field=error] .error{display:block;color:var(--danger)}}}@layer base{.table{min-width:320px;width:100%;overflow-x:auto;border-radius:var(--radius-medium);border:1px solid var(--glass-border);background-color:light-dark(rgb(255 255 255 / .3),rgb(255 255 255 / .02));box-shadow:var(--glass-edge);contain:paint}table{border-collapse:collapse;width:100%;font-size:var(--text-7)}thead{border-bottom:1px solid var(--border);background-color:light-dark(rgb(255 255 255 / .25),rgb(255 255 255 / .03))}th,td{overflow-wrap:break-word}th{padding:var(--space-3) var(--space-3);text-align:start;font-weight:var(--font-medium);color:var(--muted-foreground);font-size:var(--text-8);text-transform:uppercase;letter-spacing:.03em}td{padding:var(--space-3)}tbody tr{border-bottom:1px solid var(--border);transition:background-color var(--transition-fast);&:last-child{border-bottom:none}&:hover{background-color:var(--accent)}}}@layer base{progress{appearance:none;width:100%;height:var(--bar-height);border:none;border-radius:var(--radius-full);overflow:hidden;background-color:var(--muted);&::-webkit-progress-bar{background-color:var(--muted);border-radius:var(--radius-full)}&::-webkit-progress-value{background-color:var(--primary);border-radius:var(--radius-full);transition:width var(--transition)}&::-moz-progress-bar{background-color:var(--primary);border-radius:var(--radius-full)}}meter{appearance:none;width:100%;height:var(--bar-height);border:none;border-radius:var(--radius-full);overflow:hidden;background:var(--muted);&::-webkit-meter-bar{background:var(--muted);border:none;border-radius:var(--radius-full);height:var(--bar-height)}&::-webkit-meter-optimum-value,&::-webkit-meter-suboptimum-value,&::-webkit-meter-even-less-good-value{border-radius:var(--radius-full)}&::-webkit-meter-optimum-value{background:var(--success)}&::-webkit-meter-suboptimum-value{background:var(--warning)}&::-webkit-meter-even-less-good-value{background:var(--danger)}&::-moz-meter-bar{background:var(--success);border-radius:var(--radius-full)}&:-moz-meter-sub-optimum::-moz-meter-bar{background:var(--warning)}&:-moz-meter-sub-sub-optimum::-moz-meter-bar{background:var(--danger)}}}@layer components{[aria-busy=true]{&:before{content:"";display:inline-block;inset:0;margin:auto;width:1.5rem;height:1.5rem;border:2px solid var(--muted);border-top-color:var(--primary);border-radius:var(--radius-full);animation:spin 1s linear infinite;text-align:center}&[data-spinner~=small]:before{width:1rem;height:1rem}&[data-spinner~=large]:before{width:2rem;height:2rem;border-width:3px}&[data-spinner~=overlay]{position:relative;>*{opacity:.3;pointer-events:none}&:before{position:absolute;inset:0;margin:auto;z-index:1}}}@keyframes spin{to{transform:rotate(360deg)}}}@layer components{:root{--grid-cols: 12;--grid-gap: 1.5rem;--container-max: 1280px;--container-pad: 1rem}.container{width:100%;max-width:var(--container-max);margin-inline:auto;padding-inline:var(--container-pad)}.row{display:grid;grid-template-columns:repeat(var(--grid-cols),1fr);gap:var(--grid-gap);width:100%}.col,[class*=col-]{grid-column-end:span var(--span, var(--grid-cols))}.col-1{--span: 1}.col-2{--span: 2}.col-3{--span: 3}.col-4{--span: 4}.col-5{--span: 5}.col-6{--span: 6}.col-7{--span: 7}.col-8{--span: 8}.col-9{--span: 9}.col-10{--span: 10}.col-11{--span: 11}.col-12{--span: 12}.offset-1{grid-column-start:2}.offset-2{grid-column-start:3}.offset-3{grid-column-start:4}.offset-4{grid-column-start:5}.offset-5{grid-column-start:6}.offset-6{grid-column-start:7}.col-end{grid-column-start:span var(--span, 1);grid-column-end:-1}@media(max-width:768px){.row{--grid-cols: 4;--grid-gap: 1rem}.col,[class*=col-]{--span: 4}[class*=offset-]{grid-column-start:auto}}}@layer components{.card{background-color:var(--card);background-image:var(--glass-highlight);color:var(--card-foreground);border:1px solid var(--glass-border);border-radius:var(--radius-large);box-shadow:var(--glass-edge);padding:var(--space-6);overflow:hidden;contain:paint;>*+*{margin-block-start:var(--space-4)}>header>*+*{margin-block-start:var(--space-2)}}}@layer components{[role=alert]{position:relative;display:flex;gap:var(--space-3);padding:var(--space-4) var(--space-6);background-color:light-dark(rgb(255 255 255 / .4),rgb(255 255 255 / .03));background-image:var(--glass-highlight);border:1px solid var(--glass-border);border-radius:var(--radius-medium);font-size:var(--text-7);box-shadow:var(--glass-edge);contain:paint;&[data-variant]{border:none}&[data-variant=error],&[data-variant=danger]{color:var(--danger);background-color:light-dark(color-mix(in srgb,var(--danger) 6%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--danger) 12%,rgb(0 0 0 / .25)));border:1px solid light-dark(rgb(from var(--danger) r g b / .15),rgb(from var(--danger) r g b / .2));& a{color:var(--danger)}}&[data-variant=success]{color:var(--success);background-color:light-dark(color-mix(in srgb,var(--success) 6%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--success) 12%,rgb(0 0 0 / .25)));border:1px solid light-dark(rgb(from var(--success) r g b / .15),rgb(from var(--success) r g b / .2));& a{color:var(--success)}}&[data-variant=warning]{color:var(--warning);background-color:light-dark(color-mix(in srgb,var(--warning) 6%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--warning) 12%,rgb(0 0 0 / .25)));border:1px solid light-dark(rgb(from var(--warning) r g b / .15),rgb(from var(--warning) r g b / .2));& a{color:var(--warning)}}}}@layer components{.badge{display:inline-flex;align-items:center;gap:var(--space-1);padding:var(--space-1) var(--space-4);font-size:var(--text-8);font-weight:var(--font-medium);line-height:var(--leading-normal);background-color:var(--primary);color:var(--primary-foreground);border-radius:var(--radius-full);border:1px solid rgb(from #fff r g b / .12);box-shadow:var(--shadow-small);&.secondary{background-color:var(--secondary);color:var(--secondary-foreground);border-color:light-dark(rgb(255 255 255 / .08),rgb(255 255 255 / .06))}&.outline{background-color:transparent;color:var(--foreground);border:1px solid var(--border);box-shadow:none}&.success{color:var(--success);border-color:light-dark(rgb(from var(--success) r g b / .15),rgb(from var(--success) r g b / .2));background-color:light-dark(color-mix(in srgb,var(--success) 8%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--success) 15%,rgb(0 0 0 / .25)))}&.warning{color:var(--warning);border-color:light-dark(rgb(from var(--warning) r g b / .15),rgb(from var(--warning) r g b / .2));background-color:light-dark(color-mix(in srgb,var(--warning) 8%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--warning) 15%,rgb(0 0 0 / .25)))}&.danger{color:var(--danger);border-color:light-dark(rgb(from var(--danger) r g b / .15),rgb(from var(--danger) r g b / .2));background-color:light-dark(color-mix(in srgb,var(--danger) 8%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--danger) 15%,rgb(0 0 0 / .25)))}}}@layer components{details{border:1px solid var(--glass-border);border-radius:var(--radius-medium);overflow:hidden;background-color:light-dark(rgb(255 255 255 / .35),rgb(255 255 255 / .02));background-image:var(--glass-highlight);box-shadow:var(--glass-edge);contain:paint;content-visibility:auto;+details{margin-top:-1px;border-start-start-radius:0;border-start-end-radius:0}&:has(+details){border-end-start-radius:0;border-end-end-radius:0}&[open] summary{border-bottom:1px solid var(--border)}}summary{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);padding:var(--space-4);font-weight:var(--font-medium);cursor:pointer;user-select:none;transition:background-color var(--transition-fast);&:hover{background-color:var(--accent)}&::-webkit-details-marker,&::marker{display:none}&:after{content:"";width:1em;height:1em;flex-shrink:0;background-color:currentColor;mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");mask-size:contain;mask-repeat:no-repeat;transition:transform var(--transition-fast)}details[open] &:after{transform:rotate(180deg)}}details>*:not(summary){margin:var(--space-4)}}@layer components{[role=tablist]{display:inline-flex;align-items:center;gap:var(--space-1);padding:var(--space-1);background-color:var(--muted);border-radius:var(--radius-medium);border:1px solid var(--glass-border);box-shadow:var(--glass-edge);contain:paint}[role=tab]{display:inline-flex;align-items:center;justify-content:center;padding:var(--space-2) var(--space-3);font-size:var(--text-7);font-weight:var(--font-medium);white-space:nowrap;background-color:transparent;color:var(--muted-foreground);border:none;border-radius:calc(var(--radius-medium) - 2px);box-shadow:none;cursor:pointer;transition:background-color var(--transition-fast),color var(--transition-fast),box-shadow var(--transition-fast);&:hover{color:var(--foreground)}&[aria-selected=true]{background-color:light-dark(rgb(255 255 255 / .75),rgb(255 255 255 / .1));color:var(--foreground);box-shadow:var(--shadow-small)}}[role=tabpanel]{padding:var(--space-4) 0;&:focus-visible{outline:none}}}@layer components{dialog{position:fixed;inset:0;z-index:var(--z-modal);width:min(100% - 2rem,32rem);max-height:85vh;margin:auto;padding:0;background-color:var(--card);background-image:var(--glass-highlight);border:1px solid var(--glass-border);border-radius:var(--radius-large);box-shadow:var(--glass-edge),var(--shadow-large);backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-saturate));-webkit-backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-saturate));will-change:transform,opacity;contain:layout style paint;opacity:0;transform:translateY(8px) scale(.97);transition:opacity .25s cubic-bezier(.175,.885,.32,1.075),transform .25s cubic-bezier(.175,.885,.32,1.075),display .25s allow-discrete,overlay .25s allow-discrete;&[open]{opacity:1;transform:translateY(0) scale(1)}@starting-style{&[open]{opacity:0;transform:translateY(8px) scale(.97)}}&::backdrop{background-color:light-dark(rgb(0 0 0 / .2),rgb(0 0 0 / .45));backdrop-filter:blur(6px) saturate(var(--glass-saturate));-webkit-backdrop-filter:blur(6px) saturate(var(--glass-saturate));opacity:0;transition:opacity .25s ease,display .25s allow-discrete,overlay .25s allow-discrete}&[open]::backdrop{opacity:1}@starting-style{&[open]::backdrop{opacity:0}}>header,>form>header{display:flex;flex-direction:column;gap:var(--space-1);padding:var(--space-6);padding-block-end:0;>h1,>h2,>h3,>h4,>h5,>h6{margin-block-end:0}>p{font-size:var(--text-7);color:var(--muted-foreground);margin-block-end:0}}>p,>div,>section,>form>p,>form>div,>form>section{padding:var(--space-6);overflow-y:auto}>footer,>form>footer{display:flex;justify-content:flex-end;gap:var(--space-2);padding:var(--space-6);padding-block-start:0}}}@layer components{ot-dropdown{[popover]{position:fixed;margin:0;min-width:12rem;background-color:light-dark(rgb(255 255 255 / .72),rgb(17 24 39 / .65));background-image:var(--glass-highlight);backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%);border:1px solid light-dark(rgb(255 255 255 / .7),rgb(255 255 255 / .12));border-radius:var(--radius-medium);box-shadow:var(--glass-edge),var(--shadow-large);will-change:transform,opacity;opacity:0;transform:translateY(-6px) scale(.96);transition:opacity .2s cubic-bezier(.175,.885,.32,1.075),transform .2s cubic-bezier(.175,.885,.32,1.075),display .2s allow-discrete,overlay .2s allow-discrete;&:popover-open{opacity:1;transform:translateY(0) scale(1)}@starting-style{&:popover-open{opacity:0;transform:translateY(-6px) scale(.96)}}}[role=menuitem]{display:flex;align-items:center;justify-content:start;gap:var(--space-2);width:100%;padding:var(--space-2) var(--space-3);font-size:var(--text-7);text-align:start;color:var(--foreground);background:none;border:none;border-radius:var(--radius-small);box-shadow:none;cursor:pointer;transition:background-color var(--transition-fast);&:hover,&:focus{background-color:var(--accent);outline:none}}}}@layer components{.toast-container{position:fixed;display:flex;flex-direction:column;pointer-events:none;margin:0;padding:0;border:none;background:transparent;content-visibility:auto;overflow:visible;&::backdrop{display:none}&[data-placement=top-left]{inset:var(--space-4) auto auto var(--space-4)}&[data-placement=top-center]{inset:var(--space-4) auto auto 50%;transform:translate(-50%)}&[data-placement=top-right]{inset:var(--space-4) var(--space-4) auto auto}&[data-placement=bottom-left]{inset:auto auto var(--space-4) var(--space-4);flex-direction:column-reverse}&[data-placement=bottom-center]{inset:auto auto var(--space-4) 50%;transform:translate(-50%);flex-direction:column-reverse}&[data-placement=bottom-right]{inset:auto var(--space-4) var(--space-4) auto;flex-direction:column-reverse}}.toast{--transition: .3s;--transition-in: calc(var(--transition) - 50ms);padding:var(--space-5) var(--space-4);max-width:28rem;min-width:20rem;pointer-events:auto;background-color:var(--card);background-image:var(--glass-highlight);border:1px solid var(--glass-border);border-inline-start-width:var(--space-1);border-inline-start-style:solid;border-radius:var(--radius-large);box-shadow:var(--glass-edge),var(--shadow-large);will-change:transform,opacity;transition:opacity var(--transition-in),transform var(--transition-in),margin var(--transition-in);line-height:1;.toast-title{font-weight:600;margin:0 0 var(--space-3) 0}.toast-message{color:var(--muted-foreground)}&[data-variant=success]{border-inline-start-color:var(--success);.toast-title{color:var(--success)}}&[data-variant=danger]{border-inline-start-color:var(--danger);.toast-title{color:var(--danger)}}&[data-variant=warning]{border-inline-start-color:var(--warning);.toast-title{color:var(--warning)}}>[data-close]{margin-inline-start:auto;background:none;border:none;padding:0;cursor:pointer;opacity:.5;&:hover{opacity:1}}margin:var(--space-2) 0;&[data-entering]{opacity:0;transform:translateY(-1rem) scale(.95)}&[data-exiting]{opacity:0;margin:0;padding-block:0;max-height:0;overflow:hidden;transition:opacity var(--transition),margin var(--transition),padding var(--transition),max-height var(--transition)}}}@layer components{[data-sidebar-layout]{display:grid;grid-template-columns:14rem 1fr;grid-template-rows:auto 1fr;height:100dvh;>main{grid-row:2;min-width:0;overflow-y:auto}>aside[data-sidebar]{grid-row:2;min-height:0;z-index:1;background-color:light-dark(rgb(248 250 252 / .55),rgb(2 6 23 / .55));backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-saturate));-webkit-backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-saturate));will-change:transform;contain:layout style paint;border-inline-end:1px solid var(--border);display:flex;flex-direction:column;>:is(header,footer){flex-shrink:0;padding:var(--space-3)}>footer{margin-block-start:auto}>nav{flex:1;min-height:0;overflow-y:auto;padding:var(--space-3) var(--space-2);font-size:var(--text-7);ul{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--space-1);li{margin:0}}a{display:flex;gap:var(--space-2);padding:var(--space-1) var(--space-3);color:var(--foreground);text-decoration:none;border-radius:var(--radius-small);transition:background-color var(--transition-fast);&:is(:hover,[aria-current]){background-color:var(--accent)}}details{border:none;overflow:visible;background:none;+details{margin-top:0}&[open] summary{border-bottom:none}>ul{margin-inline-start:var(--space-4);padding:var(--space-1) 0}}summary{justify-content:flex-start;padding:var(--space-2) var(--space-3);border-radius:var(--radius-small);&:after{width:.75rem;height:.75rem;margin-inline-start:auto}}}}>nav[data-topnav]{grid-column:1 / -1}}nav[data-topnav]{position:sticky;top:0;z-index:5;display:flex;align-items:center;gap:var(--space-3);padding:var(--space-2) var(--space-4);background-color:light-dark(rgb(248 250 252 / .55),rgb(2 6 23 / .55));backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-saturate));-webkit-backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-saturate));will-change:transform;contain:layout style paint;border-bottom:1px solid var(--glass-border);a{text-decoration:none}}:is([data-sidebar-toggle],[data-sidebar-header]){display:none}[data-sidebar-toggle]{padding:0 var(--space-1);background:none;border:1px solid var(--border);border-radius:var(--radius-small)}@media(min-width:769px){[data-sidebar-layout=always]{transition:grid-template-columns var(--transition);[data-sidebar-toggle]{display:inline-block}>aside[data-sidebar]{transform:translate(0);opacity:1}&[data-sidebar-open]{grid-template-columns:0px 1fr;gap:0;>aside[data-sidebar]{overflow:hidden;min-width:0;transform:translate(-100%);opacity:0;visibility:hidden;border-inline-end:none}}}}@media(max-width:768px){[data-sidebar-layout]{grid-template-columns:1fr;>main{grid-column:1}>aside[data-sidebar]{grid-column:1;z-index:2;width:16rem;transform:translate(-100%);box-shadow:var(--shadow-large)}&[data-sidebar-open]>aside[data-sidebar]{transform:translate(0)}}[data-sidebar-toggle]{display:inline-block}[data-sidebar-header]{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border)}}}@layer components{[role=status].skeleton{--_c: light-dark( color-mix(in srgb, var(--muted) 30%, white), color-mix(in srgb, var(--muted) 90%, var(--foreground)) );margin-block-end:var(--space-3);background:var(--muted);border-radius:var(--radius-small);animation:anim 2s infinite;background-size:200% 100%;background-image:linear-gradient(90deg,var(--muted) 0%,var(--_c) 50%,var(--muted) 100%);&.box{width:4rem;height:4rem}&.line{height:1rem;width:100%}}[role=status].skeleton:last-child{margin-block-end:0}@keyframes anim{0%{background-position:200% 0}to{background-position:-200% 0}}}@layer components{[data-tooltip]{position:relative}[data-tooltip]:before,[data-tooltip]:after{position:absolute;inset-inline-start:50%;opacity:0;visibility:hidden;transition:opacity var(--transition-fast),transform var(--transition-fast),visibility var(--transition-fast);pointer-events:none;z-index:1000}[data-tooltip]:after{content:attr(data-tooltip);inset-block-end:calc(100% + 10px);transform:translate(-50%) translateY(4px);padding:var(--space-2) var(--space-3);font-size:var(--text-7);line-height:1;white-space:nowrap;background:light-dark(rgb(20 20 30 / .75),rgb(40 40 55 / .8));color:#ececf1;border:1px solid light-dark(rgb(255 255 255 / .08),rgb(255 255 255 / .12));border-radius:var(--radius-medium);box-shadow:var(--shadow-medium)}[data-tooltip]:before{content:"";inset-block-end:calc(100% - 5px);transform:translate(-50%) translateY(4px);border:8px solid transparent;border-top-color:light-dark(rgb(20 20 30 / .75),rgb(40 40 55 / .8))}[data-tooltip]:is(:hover,:focus-visible):before,[data-tooltip]:is(:hover,:focus-visible):after{opacity:1;visibility:visible;transition-delay:.7s;transform:translate(-50%) translateY(0)}}@layer components{[data-nav]{font-size:var(--text-7);display:flex;flex-direction:column;gap:var(--space-1);>small{display:block;padding:var(--space-2) var(--space-3);font-size:var(--text-8);font-weight:var(--font-semibold);color:var(--muted-foreground);text-transform:uppercase;letter-spacing:.05em;&:not(:first-child){margin-block-start:var(--space-3)}}a{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);color:var(--foreground);text-decoration:none;border-radius:var(--radius-small);transition:background-color var(--transition-fast);&:hover{background-color:var(--accent)}&[aria-current]{background-color:var(--accent);font-weight:var(--font-medium)}>.badge{margin-inline-start:auto;font-size:.625rem}}svg,img:not(.avatar img){width:1rem;height:1rem;flex-shrink:0;opacity:.7}details{border:none;background:none;overflow:visible;+details{margin-top:0}&[open] summary{border-bottom:none}>:not(summary){margin:0;padding-inline-start:var(--space-6)}}summary{justify-content:flex-start;padding:var(--space-2) var(--space-3);border-radius:var(--radius-small);font-size:var(--text-7);&:after{width:.75rem;height:.75rem;margin-inline-start:auto}}hr{margin:var(--space-2) var(--space-3);border:none;border-top:1px solid var(--border)}}}@layer components{.tag{display:inline-flex;align-items:center;gap:var(--space-1);padding:var(--space-1) var(--space-3);font-size:var(--text-8);font-weight:var(--font-medium);line-height:var(--leading-normal);background-color:var(--secondary);color:var(--secondary-foreground);border:1px solid light-dark(rgb(255 255 255 / .08),rgb(255 255 255 / .06));border-radius:var(--radius-full);>button{all:unset;display:inline-flex;align-items:center;justify-content:center;width:.875rem;height:.875rem;border-radius:var(--radius-full);cursor:pointer;opacity:.5;transition:opacity var(--transition-fast),background-color var(--transition-fast);&:hover{opacity:1;background-color:rgb(from currentColor r g b / .15)}}&.primary{background-color:var(--primary);color:var(--primary-foreground);border-color:rgb(from #fff r g b / .12)}&.success{color:var(--success);border-color:light-dark(rgb(from var(--success) r g b / .15),rgb(from var(--success) r g b / .2));background-color:light-dark(color-mix(in srgb,var(--success) 8%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--success) 15%,rgb(0 0 0 / .25)))}&.warning{color:var(--warning);border-color:light-dark(rgb(from var(--warning) r g b / .15),rgb(from var(--warning) r g b / .2));background-color:light-dark(color-mix(in srgb,var(--warning) 8%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--warning) 15%,rgb(0 0 0 / .25)))}&.danger{color:var(--danger);border-color:light-dark(rgb(from var(--danger) r g b / .15),rgb(from var(--danger) r g b / .2));background-color:light-dark(color-mix(in srgb,var(--danger) 8%,rgb(255 255 255 / .35)),color-mix(in srgb,var(--danger) 15%,rgb(0 0 0 / .25)))}}}@layer components{.avatar{display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border-radius:var(--radius-full);background-color:var(--secondary);color:var(--secondary-foreground);font-size:var(--text-7);font-weight:var(--font-medium);overflow:hidden;flex-shrink:0;vertical-align:middle;border:1.5px solid light-dark(rgb(255 255 255 / .08),rgb(255 255 255 / .06));box-shadow:var(--shadow-small);>img{width:100%;height:100%;object-fit:cover}&.small{width:1.75rem;height:1.75rem;font-size:var(--text-8)}&.large{width:3.5rem;height:3.5rem;font-size:var(--text-5)}}.avatar-group{display:flex;.avatar{border:2px solid var(--background);&:not(:first-child){margin-inline-start:-.5rem}}}}@layer components{[data-empty]{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-3);padding:var(--space-12) var(--space-6);text-align:center;color:var(--muted-foreground);background-color:light-dark(rgb(255 255 255 / .2),rgb(255 255 255 / .01));border:1px solid var(--glass-border);border-radius:var(--radius-large);box-shadow:var(--glass-edge);contain:paint;>svg,>img{width:3rem;height:3rem;opacity:.4}>:is(h1,h2,h3,h4,h5,h6){margin:0;color:var(--foreground)}>p{max-width:28rem;margin:0;font-size:var(--text-7)}>:is(button,a.button){margin-block-start:var(--space-2)}}}@layer components{ot-command{display:contents}ot-command dialog{width:min(100% - 2rem,28rem);max-height:min(60vh,24rem);margin-block-start:15vh;margin-inline:auto;margin-block-end:auto;padding:0;flex-direction:column;overflow:hidden;&[open]{display:flex}}ot-command input[type=search]{margin:0;padding:var(--space-3) var(--space-4);font-size:var(--text-6);background:transparent;border:none;border-bottom:1px solid var(--border);border-radius:0;box-shadow:none;&:focus{outline:none;border-color:var(--border);background:transparent;box-shadow:none}&::-webkit-search-cancel-button{display:none}}ot-command [role=listbox]{flex:1;overflow-y:auto;padding:var(--space-2);>:not([role=option]){display:block;padding:var(--space-2) var(--space-3);padding-block-start:var(--space-3);font-size:var(--text-8);font-weight:var(--font-semibold);color:var(--muted-foreground);&:first-child{padding-block-start:var(--space-1)}}}ot-command [role=option]{display:flex;align-items:center;justify-content:flex-start;gap:var(--space-2);width:100%;padding:var(--space-2) var(--space-3);font-size:var(--text-7);text-align:start;background:none;color:var(--foreground);border:none;border-radius:var(--radius-small);box-shadow:none;cursor:pointer;transition:background-color var(--transition-fast);&:hover,&[aria-selected=true]{background-color:var(--accent);box-shadow:none}&:active{transform:none;box-shadow:none}>kbd{margin-inline-start:auto;padding:var(--space-1) var(--space-2);font-family:var(--font-mono);font-size:var(--text-8);color:var(--muted-foreground);background-color:var(--muted);border:1px solid var(--glass-border);border-radius:var(--radius-small)}>svg{width:1rem;height:1rem;flex-shrink:0;opacity:.7}}}@layer utilities{.align-left{text-align:start}.align-center{text-align:center}.align-right{text-align:end}.text-light{color:var(--muted-foreground)}.text-lighter{color:var(--faint-foreground)}.flex{display:flex}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-end{justify-content:flex-end}.hstack{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;align-content:flex-start;height:auto;*{margin:0}}.vstack{display:flex;flex-direction:column;gap:var(--space-3)}.gap-1{gap:var(--space-1)}.gap-2{gap:var(--space-2)}.gap-4{gap:var(--space-4)}.mt-2{margin-block-start:var(--space-2)}.mt-4{margin-block-start:var(--space-4)}.mt-6{margin-block-start:var(--space-6)}.mb-2{margin-block-end:var(--space-2)}.mb-4{margin-block-end:var(--space-4)}.mb-6{margin-block-end:var(--space-6)}.p-4{padding:var(--space-4)}.w-100{width:100%}:is(ul,ol,a).unstyled{list-style:none;text-decoration:none;padding:0}}
@@ -0,0 +1 @@
1
+ (()=>{var d=class extends HTMLElement{#t=!1;connectedCallback(){this.#t||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.#e(),{once:!0}):this.#e())}#e(){this.#t||(this.#t=!0,this.init())}disconnectedCallback(){this.cleanup()}cleanup(){}handleEvent(t){let e=this[`on${t.type}`];e&&e.call(this,t)}keyNav(t,e,s,o,n,a=!1){let{key:r}=t,c=-1;return r===n?c=(e+1)%s:r===o?c=(e-1+s)%s:a&&(r==="Home"?c=0:r==="End"&&(c=s-1)),c>=0&&t.preventDefault(),c}emit(t,e=null){return this.dispatchEvent(new CustomEvent(t,{bubbles:!0,composed:!0,cancelable:!0,detail:e}))}$(t){return this.querySelector(t)}$$(t){return Array.from(this.querySelectorAll(t))}uid(){return Math.random().toString(36).slice(2,10)}};"commandForElement"in HTMLButtonElement.prototype||document.addEventListener("click",i=>{let t=i.target.closest("button[commandfor]");if(!t)return;let e=document.getElementById(t.getAttribute("commandfor"));if(!e)return;let s=t.getAttribute("command")||"toggle";e instanceof HTMLDialogElement&&(s==="show-modal"?e.showModal():s==="close"||e.open?e.close():e.showModal())});var h=class extends d{#t=[];#e=[];init(){let t=this.$(':scope > [role="tablist"]');if(this.#t=t?[...t.querySelectorAll('[role="tab"]')]:[],this.#e=this.$$(':scope > [role="tabpanel"]'),this.#t.length===0||this.#e.length===0){console.warn("ot-tabs: Missing tab or tabpanel elements");return}this.#t.forEach((s,o)=>{let n=this.#e[o];if(!n)return;let a=s.id||`ot-tab-${this.uid()}`,r=n.id||`ot-panel-${this.uid()}`;s.id=a,n.id=r,s.setAttribute("aria-controls",r),n.setAttribute("aria-labelledby",a)}),t.addEventListener("click",this),t.addEventListener("keydown",this);let e=this.#t.findIndex(s=>s.ariaSelected==="true");this.#i(e>=0?e:0)}onclick(t){let e=this.#t.indexOf(t.target.closest('[role="tab"]'));e>=0&&this.#i(e)}onkeydown(t){if(!t.target.closest('[role="tab"]'))return;let e=this.keyNav(t,this.activeIndex,this.#t.length,"ArrowLeft","ArrowRight");e>=0&&(this.#i(e),this.#t[e].focus())}#i(t){this.#t.forEach((e,s)=>{let o=s===t;e.ariaSelected=String(o),e.tabIndex=o?0:-1}),this.#e.forEach((e,s)=>{e.hidden=s!==t}),this.emit("ot-tab-change",{index:t,tab:this.#t[t]})}get activeIndex(){return this.#t.findIndex(t=>t.ariaSelected==="true")}set activeIndex(t){t>=0&&t<this.#t.length&&this.#i(t)}};customElements.define("ot-tabs",h);var u=class extends d{#t;#e;#i;#s;init(){this.#t=this.$("[popover]"),this.#e=this.$("[popovertarget]"),!(!this.#t||!this.#e)&&(this.#t.addEventListener("toggle",this),this.#t.addEventListener("keydown",this),this.#i=()=>{let t=this.#e.getBoundingClientRect(),e=this.#t.getBoundingClientRect();this.#t.style.top=`${t.bottom+e.height>window.innerHeight?t.top-e.height:t.bottom}px`,this.#t.style.left=`${t.left+e.width>window.innerWidth?t.right-e.width:t.left}px`})}ontoggle(t){t.newState==="open"?(this.#i(),window.addEventListener("scroll",this.#i,!0),window.addEventListener("resize",this.#i),this.#s=this.$$('[role="menuitem"]'),this.#s[0]?.focus(),this.#e.ariaExpanded="true"):(this.cleanup(),this.#s=null,this.#e.ariaExpanded="false",this.#e.focus())}onkeydown(t){if(!t.target.matches('[role="menuitem"]'))return;let e=this.#s.indexOf(t.target),s=this.keyNav(t,e,this.#s.length,"ArrowUp","ArrowDown",!0);s>=0&&this.#s[s].focus()}cleanup(){window.removeEventListener("scroll",this.#i,!0),window.removeEventListener("resize",this.#i)}};customElements.define("ot-dropdown",u);document.addEventListener("DOMContentLoaded",()=>{let i="title",t="[title]",e=s=>{let o=s.getAttribute(i);o&&(s.setAttribute("data-tooltip",o),s.hasAttribute("aria-label")||s.setAttribute("aria-label",o),s.removeAttribute(i))};document.querySelectorAll(t).forEach(e),new MutationObserver(s=>{for(let o of s){e(o.target);for(let n of o.addedNodes)n.nodeType===1&&(e(n),n.querySelectorAll(t).forEach(e))}}).observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[i]})});document.addEventListener("click",i=>{let t=i.target.closest("[data-sidebar-toggle]");if(t){t.closest("[data-sidebar-layout]")?.toggleAttribute("data-sidebar-open");return}if(!i.target.closest("[data-sidebar]")){let e=document.querySelector("[data-sidebar-layout][data-sidebar-open]");e&&window.matchMedia("(max-width: 768px)").matches&&e.removeAttribute("data-sidebar-open")}});var f=class extends d{#t;#e;#i;#s=-1;init(){this.#t=this.$("dialog")||this.#o(),this.#e=this.$('input[type="search"]'),document.addEventListener("keydown",this),this.#t.addEventListener("keydown",this),this.#e&&this.#e.addEventListener("input",this),this.#t.addEventListener("click",this)}#o(){let t=document.createElement("dialog");for(t.setAttribute("closedby","any");this.firstChild;)t.appendChild(this.firstChild);return this.appendChild(t),t}open(){this.#t.showModal(),this.#e&&(this.#e.value="",this.#e.focus()),this.#n()}#n(){this.#s=-1,this.$$('[role="listbox"] > *').forEach(t=>t.hidden=!1),this.$$('[role="option"]').forEach(t=>t.removeAttribute("aria-selected"))}onkeydown(t){if((t.metaKey||t.ctrlKey)&&t.key==="k"){t.preventDefault(),this.#t.open?this.#t.close():this.open();return}if(!this.#t.open)return;if(t.key==="Escape"){t.preventDefault(),this.#t.close();return}if(this.#i=this.$$('[role="option"]:not([hidden])'),!this.#i.length)return;let e=this.keyNav(t,this.#s,this.#i.length,"ArrowUp","ArrowDown",!0);e>=0&&(this.#s=e,this.#i.forEach((s,o)=>s.setAttribute("aria-selected",String(o===e))),this.#i[e].scrollIntoView({block:"nearest"})),t.key==="Enter"&&this.#s>=0&&(t.preventDefault(),this.#i[this.#s].click(),this.#t.close())}oninput(){let t=this.#e.value.toLowerCase(),e=null,s=!1;for(let o of this.$$('[role="listbox"] > *'))if(o.matches('[role="option"]')){let n=!t||o.textContent.toLowerCase().includes(t);o.hidden=!n,n&&(s=!0)}else e&&(e.hidden=!s),e=o,s=!1;e&&(e.hidden=!s),this.#s=-1,this.$$('[role="option"]').forEach(o=>o.removeAttribute("aria-selected"))}onclick(t){if(t.target===this.#t){this.#t.close();return}if(t.target.closest('[role="option"]')){this.#t.close();return}this.#e&&!t.target.closest("input")&&this.#e.focus()}cleanup(){document.removeEventListener("keydown",this)}};customElements.define("ot-command",f);var l={};function w(i){if(!l[i]){let t=document.createElement("div");t.className="toast-container",t.setAttribute("popover","manual"),t.setAttribute("data-placement",i),document.body.appendChild(t),l[i]=t}return l[i]}function b(i,t={}){let{placement:e="top-right",duration:s=4e3}=t,o=w(e);i.classList.add("toast");let n;return i.onmouseenter=()=>clearTimeout(n),i.onmouseleave=()=>{s>0&&(n=setTimeout(()=>p(i,o),s))},i.setAttribute("data-entering",""),o.appendChild(i),o.showPopover(),requestAnimationFrame(()=>{requestAnimationFrame(()=>{i.removeAttribute("data-entering")})}),s>0&&(n=setTimeout(()=>p(i,o),s)),i}function p(i,t){if(i.hasAttribute("data-exiting"))return;i.setAttribute("data-exiting","");let e=()=>{i.remove(),t.children.length||t.hidePopover()};i.addEventListener("transitionend",e,{once:!0});let s=getComputedStyle(i).getPropertyValue("--transition").trim(),o=parseFloat(s),n=s.endsWith("ms")?o:o*1e3;setTimeout(e,n)}function g(i,t,e={}){let{variant:s="info",...o}=e,n=document.createElement("output");if(n.setAttribute("data-variant",s),t){let r=document.createElement("h6");r.className="toast-title",r.textContent=t,n.appendChild(r)}let a=document.createElement("div");return a.className="toast-message",a.textContent=i,n.appendChild(a),b(n,o)}function v(i,t={}){let e;if(i instanceof HTMLTemplateElement?e=i.content.firstElementChild?.cloneNode(!0):i&&(e=i.cloneNode(!0)),!!e)return e.removeAttribute("id"),b(e,t)}function E(i){i&&l[i]?(l[i].innerHTML="",l[i].hidePopover()):Object.values(l).forEach(t=>{t.innerHTML="",t.hidePopover()})}var m=window.ot||(window.ot={});m.toast=g;m.toast.el=v;m.toast.clear=E;})();
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "oat-glassed",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "author": "good-lly | Originally created by Kailash Nadh @kailashnadh",
6
+ "homepage": "https://github.com/good-lly/oat-glassed",
7
+ "description": " Ultra-lightweight, zero dependency, semantic HTML/CSS/JS UI library",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/good-lly/oat-glassed.git"
11
+ },
12
+ "keywords": [
13
+ "ui",
14
+ "components",
15
+ "component-library"
16
+ ],
17
+ "files": [
18
+ "oat-glassed.min.css",
19
+ "oat-glassed.min.js",
20
+ "css",
21
+ "js"
22
+ ],
23
+ "main": "oat-glassed.min.js",
24
+ "style": "oat-glassed.min.css",
25
+ "unpkg": "oat-glassed.min.js",
26
+ "jsdelivr": "oat-glassed.min.js"
27
+ }