@jungherz-de/glasskit-elements 1.14.0 → 1.15.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.
- package/README.md +12 -6
- package/dist/components/base.js +1 -21
- package/dist/components/glk-accordion-item.js +1 -0
- package/dist/components/glk-accordion.js +1 -0
- package/dist/components/glk-avatar.js +1 -0
- package/dist/components/glk-badge.js +1 -0
- package/dist/components/glk-button.js +1 -0
- package/dist/components/glk-card.js +1 -0
- package/dist/components/glk-checkbox.js +1 -0
- package/dist/components/glk-divider.js +1 -0
- package/dist/components/glk-empty.js +53 -0
- package/dist/components/glk-input.js +1 -0
- package/dist/components/glk-list-item.js +1 -0
- package/dist/components/glk-list.js +1 -0
- package/dist/components/glk-modal.js +1 -0
- package/dist/components/glk-nav.js +1 -0
- package/dist/components/glk-pill.js +1 -0
- package/dist/components/glk-popover.js +1 -0
- package/dist/components/glk-progress.js +1 -0
- package/dist/components/glk-radio.js +1 -0
- package/dist/components/glk-range.js +1 -0
- package/dist/components/glk-search.js +1 -0
- package/dist/components/glk-segmented.js +124 -0
- package/dist/components/glk-select.js +1 -0
- package/dist/components/glk-sheet.js +141 -0
- package/dist/components/glk-status.js +1 -0
- package/dist/components/glk-steps.js +75 -0
- package/dist/components/glk-tab-accessory.js +1 -0
- package/dist/components/glk-tab-bar.js +1 -0
- package/dist/components/glk-tab-dock.js +1 -0
- package/dist/components/glk-tab-item.js +1 -0
- package/dist/components/glk-textarea.js +1 -0
- package/dist/components/glk-title.js +1 -0
- package/dist/components/glk-toast.js +1 -0
- package/dist/components/glk-toggle.js +1 -0
- package/dist/glasskit-elements.esm.js +380 -3
- package/dist/glasskit-elements.js +383 -2
- package/dist/glasskit-elements.min.js +1 -1
- package/package.json +3 -3
- package/src/components/content/glk-empty.js +51 -0
- package/src/components/feedback/glk-sheet.js +139 -0
- package/src/components/forms/glk-segmented.js +122 -0
- package/src/components/navigation/glk-steps.js +73 -0
- package/src/index.js +4 -0
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<a href="https://www.npmjs.com/package/@jungherz-de/glasskit-elements"><img src="https://img.shields.io/npm/v/@jungherz-de/glasskit-elements?style=flat-square&color=f5a623&label=version" alt="Version"></a>
|
|
5
5
|
<a href="#"><img src="https://img.shields.io/badge/vanilla_JS-no_dependencies-44cc11?style=flat-square" alt="Vanilla JS"></a>
|
|
6
|
-
<a href="#"><img src="https://img.shields.io/badge/components-
|
|
6
|
+
<a href="#"><img src="https://img.shields.io/badge/components-33-7ec8e3?style=flat-square" alt="33 Components"></a>
|
|
7
7
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT License"></a>
|
|
8
|
-
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-v1.
|
|
8
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-v1.15.1-lightgrey?style=flat-square" alt="Changelog"></a>
|
|
9
9
|
<a href="https://www.npmjs.com/package/@jungherz-de/glasskit-elements"><img src="https://img.shields.io/badge/npm-%40jungherz--de%2Fglasskit--elements-cb3837?style=flat-square&logo=npm" alt="npm"></a>
|
|
10
10
|
</p>
|
|
11
11
|
|
|
@@ -51,7 +51,7 @@ It is the **app layer** of the GlassKit family — three layers, one design lang
|
|
|
51
51
|
| Feature | Details |
|
|
52
52
|
|---|---|
|
|
53
53
|
| 🔌 **Shadow DOM** | Style encapsulation via `adoptedStyleSheets` — no CSS leaking |
|
|
54
|
-
| 🧩 **
|
|
54
|
+
| 🧩 **33 Components** | Buttons, cards, toggles, modals, accordions, lists, popovers, tab bars (incl. floating + accessory), and more |
|
|
55
55
|
| 🪶 **Lightweight** | 117 KB raw / 92 KB minified / 15 KB gzipped (IIFE bundle), no external dependencies |
|
|
56
56
|
| 📦 **Three bundle formats** | IIFE for `<script>`, minified IIFE for production, ESM for bundlers & tree-shaking |
|
|
57
57
|
| 🎛️ **Form Participation** | Input, toggle, checkbox, radio, select — all work natively with `<form>` via `ElementInternals` |
|
|
@@ -66,7 +66,7 @@ It is the **app layer** of the GlassKit family — three layers, one design lang
|
|
|
66
66
|
|
|
67
67
|
```html
|
|
68
68
|
<!-- 1. GlassKit CSS -->
|
|
69
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.
|
|
69
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.15/glasskit.min.css">
|
|
70
70
|
|
|
71
71
|
<!-- 2. GlassKit Elements -->
|
|
72
72
|
<script src="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit-elements/dist/glasskit-elements.min.js"></script>
|
|
@@ -94,6 +94,8 @@ import '@jungherz-de/glasskit-elements/components/glk-toggle.js';
|
|
|
94
94
|
import { GlkElement, GlkFormElement } from '@jungherz-de/glasskit-elements/base.js';
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
The per-component files leave `@jungherz-de/glasskit/glasskit-styles.js` as an external import, so the GlassKit stylesheet exists once — a bundler resolves it from `node_modules`; a build-free project adds it to its import map next to the elements entries. Do not mix the `<script>` bundle with `base.js`: the bundle carries its own copy of the classes, so `instanceof` would fail across the two. With the bundle, take the class from it — `GlassKitElements.GlkElement`, or `import { GlkElement } from '@jungherz-de/glasskit-elements'` for the ESM bundle.
|
|
98
|
+
|
|
97
99
|
---
|
|
98
100
|
|
|
99
101
|
## 🚀 Quick Start
|
|
@@ -102,7 +104,7 @@ import { GlkElement, GlkFormElement } from '@jungherz-de/glasskit-elements/base.
|
|
|
102
104
|
<!DOCTYPE html>
|
|
103
105
|
<html data-theme="dark">
|
|
104
106
|
<head>
|
|
105
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.
|
|
107
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.15/glasskit.min.css">
|
|
106
108
|
<script src="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit-elements/dist/glasskit-elements.min.js"></script>
|
|
107
109
|
</head>
|
|
108
110
|
<body>
|
|
@@ -127,6 +129,7 @@ import { GlkElement, GlkFormElement } from '@jungherz-de/glasskit-elements/base.
|
|
|
127
129
|
| `<glk-tab-item>` | Tab bar item | `label`, `active`, `badge` |
|
|
128
130
|
| `<glk-tab-dock>` | Wrapper for floating tab bar + optional accessory | `accessory-left` |
|
|
129
131
|
| `<glk-tab-accessory>` | Standalone glass capsule (search, compose…) | `label`, `variant` (accent, success, error), `disabled` |
|
|
132
|
+
| `<glk-steps>` | Progress through a short flow | `steps`, `current`, `label` |
|
|
130
133
|
|
|
131
134
|
### Content
|
|
132
135
|
|
|
@@ -138,6 +141,7 @@ import { GlkElement, GlkFormElement } from '@jungherz-de/glasskit-elements/base.
|
|
|
138
141
|
| `<glk-title>` | Styled heading | — |
|
|
139
142
|
| `<glk-divider>` | Horizontal divider | — |
|
|
140
143
|
| `<glk-status>` | Status notice | `message` |
|
|
144
|
+
| `<glk-empty>` | Empty state: icon, title, text, one action | `title`, `text` |
|
|
141
145
|
|
|
142
146
|
### Buttons
|
|
143
147
|
|
|
@@ -159,6 +163,7 @@ All form components support `name`, `value`, `disabled` and participate in nativ
|
|
|
159
163
|
| `<glk-checkbox>` | Checkbox | `label`, `checked`, `disabled` |
|
|
160
164
|
| `<glk-radio>` | Radio button | `label`, `name`, `value`, `checked` |
|
|
161
165
|
| `<glk-range>` | Range slider | `label`, `min`, `max`, `value`, `step` |
|
|
166
|
+
| `<glk-segmented>` | Small exclusive choice as one control; form-associated | `options` (JSON), `value`, `full`, `label`, `name` |
|
|
162
167
|
|
|
163
168
|
### Feedback & Notifications
|
|
164
169
|
|
|
@@ -168,6 +173,7 @@ All form components support `name`, `value`, `disabled` and participate in nativ
|
|
|
168
173
|
| `<glk-modal>` | Modal dialog | `open`, `title` |
|
|
169
174
|
| `<glk-toast>` | Auto-dismissing notification | `message`, `variant` (success, error, warning), `duration` |
|
|
170
175
|
| `<glk-popover>` | Anchored dropdown / menu | `open`, `placement` (top, bottom, start, end) |
|
|
176
|
+
| `<glk-sheet>` | Bottom sheet, the mobile sibling of the modal | `open`, `inline`, `title` |
|
|
171
177
|
|
|
172
178
|
### Containers
|
|
173
179
|
|
|
@@ -311,7 +317,7 @@ Requires `adoptedStyleSheets`, `ElementInternals`, and `customElements` v1.
|
|
|
311
317
|
|
|
312
318
|
## 🤖 AI / LLM Reference
|
|
313
319
|
|
|
314
|
-
[`SKILL.md`](SKILL.md) is a tag-based, machine-readable reference for LLMs and AI copilots. It contains copy-paste-ready HTML for all
|
|
320
|
+
[`SKILL.md`](SKILL.md) is a tag-based, machine-readable reference for LLMs and AI copilots. It contains copy-paste-ready HTML for all 33 elements, attribute / slot / event tables, composition patterns, and a common-mistakes section. It is the companion to the class-based `SKILL.md` in [GlassKit CSS](https://github.com/JUNGHERZ/GlassKit) — use both together for complete coverage of the glass stack.
|
|
315
321
|
|
|
316
322
|
---
|
|
317
323
|
|
package/dist/components/base.js
CHANGED
|
@@ -1,24 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// Auto-generated by build-styles-js.mjs – do not edit manually.
|
|
3
|
-
|
|
4
|
-
// The [data-theme] blocks that declare --gl-* …
|
|
5
|
-
const tokensCss = ":root,[data-theme=dark]{color-scheme:dark;--gl-color-primary:#f5a623;--gl-color-primary-dark:#d4692a;--gl-color-primary-mid:color-mix(in srgb, var(--gl-color-primary) 32%, var(--gl-color-primary-dark));--gl-color-bg-dark:#0e2530;--gl-color-bg-mid:#1a3d4e;--gl-color-bg-light:#1b3e50;--gl-color-text:#ffffff;--gl-color-text-muted:rgba(255, 255, 255, 0.60);--gl-color-text-on-light:#1a3a4a;--gl-color-text-heading:#ffffff;--gl-color-success:#34c759;--gl-color-error:#ff3b30;--gl-color-warning:#ffcc00;--gl-color-success-dark:#2da44e;--gl-color-error-dark:#d63027;--gl-color-on-primary:#ffffff;--gl-color-on-success:#ffffff;--gl-color-on-error:#ffffff;--gl-color-primary-on-surface:color-mix(in srgb, var(--gl-color-primary) 50%, #ffffff);--gl-color-success-on-surface:color-mix(in srgb, var(--gl-color-success) 62%, #ffffff);--gl-color-error-on-surface:color-mix(in srgb, var(--gl-color-error) 50%, #ffffff);--gl-state-scrim:rgba(0, 0, 0, 0.30);--gl-color-primary-surface:color-mix(in srgb, var(--gl-color-primary) 25%, transparent);--gl-color-primary-border:var(--gl-border-warm);--gl-color-success-surface:color-mix(in srgb, var(--gl-color-success) 15%, transparent);--gl-color-success-border:color-mix(in srgb, var(--gl-color-success) 30%, transparent);--gl-color-error-surface:color-mix(in srgb, var(--gl-color-error) 15%, transparent);--gl-color-error-border:color-mix(in srgb, var(--gl-color-error) 30%, transparent);--gl-surface-1:rgba(255, 255, 255, 0.08);--gl-surface-2:rgba(255, 255, 255, 0.10);--gl-surface-3:rgba(255, 255, 255, 0.14);--gl-surface-4:rgba(255, 255, 255, 0.16);--gl-surface-5:rgba(255, 255, 255, 0.22);--gl-surface-milk:rgba(255, 255, 255, 0.55);--gl-surface-milk-strong:rgba(255, 255, 255, 0.75);--gl-surface-overlay:rgba(0, 0, 0, 0.50);--gl-card-glow-top:rgba(255, 255, 255, 0.32);--gl-card-glow-mid:rgba(255, 255, 255, 0.22);--gl-card-glow-low:rgba(255, 255, 255, 0.14);--gl-card-glow-bottom:rgba(255, 255, 255, 0.08);--gl-card-icon-color:rgba(255, 255, 255, 0.8);--gl-card-text-color:rgba(255, 255, 255, 0.7);--gl-border-subtle:rgba(255, 255, 255, 0.18);--gl-border-medium:rgba(255, 255, 255, 0.30);--gl-border-strong:rgba(255, 255, 255, 0.40);--gl-border-milk:rgba(255, 255, 255, 0.60);--gl-border-warm:color-mix(in srgb, color-mix(in srgb, var(--gl-color-primary) 68%, #ffffff) 35%, transparent);--gl-border-focus:color-mix(in srgb, var(--gl-color-primary) 60%, transparent);--gl-icon-default:rgba(255, 255, 255, 0.6);--gl-icon-muted:rgba(255, 255, 255, 0.45);--gl-icon-strong:rgba(255, 255, 255, 0.8);--gl-icon-on-primary:var(--gl-color-on-primary, #ffffff);--gl-icon-on-secondary:#1a3a4a;--gl-icon-on-tertiary:rgba(255, 255, 255, 0.6);--gl-blur:24px;--gl-blur-light:16px;--gl-blur-soft:12px;--gl-blur-heavy:40px;--gl-radius-pill:50%;--gl-radius-full:9999px;--gl-radius-card:24px;--gl-radius-btn:16px;--gl-radius-input:14px;--gl-radius-sm:12px;--gl-radius-xs:8px;--gl-shadow-card:0 8px 32px rgba(0, 0, 0, 0.18);--gl-shadow-btn:0 4px 16px rgba(0, 0, 0, 0.12);--gl-shadow-btn-primary:0 6px 24px color-mix(in srgb, var(--gl-color-primary-mid) 35%, transparent),0 2px 8px rgba(0, 0, 0, 0.15);--gl-shadow-glow:0 2px 12px rgba(255, 255, 255, 0.08),0 4px 16px rgba(0, 0, 0, 0.15);--gl-shadow-modal:0 24px 80px rgba(0, 0, 0, 0.4),0 8px 32px rgba(0, 0, 0, 0.2);--gl-shadow-toast:0 8px 32px rgba(0, 0, 0, 0.25);--gl-shadow-focus:0 0 0 3px color-mix(in srgb, var(--gl-color-primary) 30%, transparent);--gl-inset-subtle:inset 0 1px 1px rgba(255, 255, 255, 0.10);--gl-inset-medium:inset 0 1px 1px rgba(255, 255, 255, 0.15);--gl-inset-strong:inset 0 1px 2px rgba(255, 255, 255, 0.25);--gl-inset-milk:inset 0 1px 2px rgba(255, 255, 255, 0.40);--gl-bg-aurora-1:rgba(60, 160, 160, 0.25);--gl-bg-aurora-2:rgba(200, 140, 60, 0.12);--gl-bg-aurora-3:rgba(80, 180, 200, 0.18);--gl-bg-light-streak-1:rgba(90, 210, 200, 0.14);--gl-bg-light-streak-2:rgba(110, 200, 190, 0.10);--gl-bg-warm-glow:rgba(220, 160, 70, 0.10);--gl-space-2xs:4px;--gl-space-xs:8px;--gl-space-sm:12px;--gl-space-md:16px;--gl-space-lg:20px;--gl-space-xl:24px;--gl-space-2xl:32px;--gl-space-3xl:40px;--gl-space-4xl:56px;--gl-font-family:-apple-system,BlinkMacSystemFont,'SF Pro Display','Segoe UI',Roboto,Helvetica,Arial,sans-serif;--gl-font-size-xs:13px;--gl-font-size-sm:14px;--gl-font-size-base:15px;--gl-font-size-btn:16px;--gl-font-size-lg:18px;--gl-font-size-title:24px;--gl-font-size-modal:20px;--gl-font-weight-normal:400;--gl-font-weight-medium:500;--gl-font-weight-semibold:600;--gl-transition:all 0.25s ease;--gl-transition-fast:all 0.15s ease;--gl-transition-modal:all 0.3s cubic-bezier(0.4, 0, 0.2, 1);--gl-tab-bar-height:82px;--gl-tab-bar-floating-bottom:16px;--gl-tab-bar-floating-gap:var(--gl-space-sm);--gl-tab-bar-floating-padding:6px 10px;--gl-tab-bar-floating-radius:var(--gl-radius-full);--gl-tab-bar-accessory-size:56px;--gl-tab-bar-spotlight-color:var(--gl-color-primary);--gl-placeholder:rgba(255, 255, 255, 0.35);--gl-accordion-body-color:var(--gl-color-text-muted);--gl-toggle-thumb-bg:linear-gradient(to bottom,\n rgba(255,255,255,0.9) 0%,\n rgba(255,255,255,0.7) 100%);--gl-range-track-bg:var(--gl-surface-2);--gl-range-track-border:var(--gl-border-subtle)}[data-theme=light]{color-scheme:light;--gl-color-primary:#e8852d;--gl-color-primary-dark:#c96a1e;--gl-color-primary-mid:color-mix(in srgb, var(--gl-color-primary) 52%, var(--gl-color-primary-dark));--gl-color-bg-dark:#e8ecf1;--gl-color-bg-mid:#f0f4f8;--gl-color-bg-light:#f5f7fa;--gl-color-text:#1a2a36;--gl-color-text-muted:rgba(26, 42, 54, 0.55);--gl-color-text-on-light:#1a3a4a;--gl-color-text-heading:#0f1f2a;--gl-color-success:#28a745;--gl-color-error:#dc3545;--gl-color-warning:#e6a800;--gl-color-success-dark:#1e7e34;--gl-color-error-dark:#b02a37;--gl-color-on-primary:#ffffff;--gl-color-on-success:#ffffff;--gl-color-on-error:#ffffff;--gl-color-primary-on-surface:color-mix(in srgb, var(--gl-color-primary) 60%, #000000);--gl-color-success-on-surface:color-mix(in srgb, var(--gl-color-success) 68%, #000000);--gl-color-error-on-surface:color-mix(in srgb, var(--gl-color-error) 82%, #000000);--gl-state-scrim:rgba(255, 255, 255, 0.30);--gl-color-primary-surface:color-mix(in srgb, var(--gl-color-primary) 25%, transparent);--gl-color-primary-border:var(--gl-border-warm);--gl-color-success-surface:color-mix(in srgb, var(--gl-color-success) 15%, transparent);--gl-color-success-border:color-mix(in srgb, var(--gl-color-success) 30%, transparent);--gl-color-error-surface:color-mix(in srgb, var(--gl-color-error) 15%, transparent);--gl-color-error-border:color-mix(in srgb, var(--gl-color-error) 30%, transparent);--gl-surface-1:rgba(255, 255, 255, 0.50);--gl-surface-2:rgba(255, 255, 255, 0.60);--gl-surface-3:rgba(255, 255, 255, 0.70);--gl-surface-4:rgba(255, 255, 255, 0.75);--gl-surface-5:rgba(255, 255, 255, 0.85);--gl-surface-milk:rgba(255, 255, 255, 0.85);--gl-surface-milk-strong:rgba(255, 255, 255, 0.92);--gl-surface-overlay:rgba(0, 0, 0, 0.25);--gl-card-glow-top:rgba(255, 255, 255, 0.90);--gl-card-glow-mid:rgba(255, 255, 255, 0.78);--gl-card-glow-low:rgba(255, 255, 255, 0.65);--gl-card-glow-bottom:rgba(255, 255, 255, 0.50);--gl-card-icon-color:rgba(26, 42, 54, 0.5);--gl-card-text-color:rgba(26, 42, 54, 0.6);--gl-border-subtle:rgba(0, 0, 0, 0.08);--gl-border-medium:rgba(0, 0, 0, 0.12);--gl-border-strong:rgba(0, 0, 0, 0.15);--gl-border-milk:rgba(0, 0, 0, 0.10);--gl-border-warm:color-mix(in srgb, var(--gl-color-primary) 30%, transparent);--gl-border-focus:color-mix(in srgb, var(--gl-color-primary) 50%, transparent);--gl-icon-default:rgba(26, 42, 54, 0.50);--gl-icon-muted:rgba(26, 42, 54, 0.35);--gl-icon-strong:rgba(26, 42, 54, 0.70);--gl-icon-on-primary:var(--gl-color-on-primary, #ffffff);--gl-icon-on-secondary:#1a3a4a;--gl-icon-on-tertiary:rgba(26, 42, 54, 0.50);--gl-shadow-card:0 4px 20px rgba(0, 0, 0, 0.06);--gl-shadow-btn:0 2px 10px rgba(0, 0, 0, 0.06);--gl-shadow-btn-primary:0 4px 16px color-mix(in srgb, var(--gl-color-primary) 25%, transparent),0 2px 6px rgba(0, 0, 0, 0.08);--gl-shadow-glow:0 2px 8px rgba(0, 0, 0, 0.05),0 4px 12px rgba(0, 0, 0, 0.04);--gl-shadow-modal:0 16px 48px rgba(0, 0, 0, 0.12),0 4px 16px rgba(0, 0, 0, 0.08);--gl-shadow-toast:0 4px 20px rgba(0, 0, 0, 0.10);--gl-shadow-focus:0 0 0 3px color-mix(in srgb, var(--gl-color-primary) 25%, transparent);--gl-inset-subtle:inset 0 1px 1px rgba(255, 255, 255, 0.60);--gl-inset-medium:inset 0 1px 1px rgba(255, 255, 255, 0.70);--gl-inset-strong:inset 0 1px 2px rgba(255, 255, 255, 0.80);--gl-inset-milk:inset 0 1px 2px rgba(255, 255, 255, 0.90);--gl-bg-aurora-1:rgba(100, 200, 220, 0.15);--gl-bg-aurora-2:rgba(240, 180, 100, 0.10);--gl-bg-aurora-3:rgba(120, 200, 230, 0.12);--gl-bg-light-streak-1:rgba(140, 230, 220, 0.10);--gl-bg-light-streak-2:rgba(160, 220, 210, 0.08);--gl-bg-warm-glow:rgba(240, 180, 100, 0.08);--gl-placeholder:rgba(26, 42, 54, 0.30);--gl-accordion-body-color:var(--gl-color-text-muted);--gl-toggle-thumb-bg:linear-gradient(to bottom, #ffffff 0%, #f0f0f0 100%);--gl-range-track-bg:var(--gl-surface-2);--gl-range-track-border:var(--gl-border-subtle)}";
|
|
6
|
-
|
|
7
|
-
// … and everything else, in two pieces around where they were.
|
|
8
|
-
const componentsHead = "[class*=gl-],[class*=glass-],[class*=glass-]::after,[class*=glass-]::before{box-sizing:border-box}";
|
|
9
|
-
const componentsTail = ".glass-bg{background:radial-gradient(ellipse at 20% 40%,var(--gl-bg-aurora-1) 0,transparent 55%),radial-gradient(ellipse at 80% 65%,var(--gl-bg-aurora-2) 0,transparent 50%),radial-gradient(ellipse at 50% 20%,var(--gl-bg-aurora-3) 0,transparent 50%),linear-gradient(170deg,var(--gl-color-bg-light) 0,var(--gl-color-bg-mid) 50%,var(--gl-color-bg-dark) 100%);position:relative;min-height:100vh;overflow-x:hidden;font-family:var(--gl-font-family);color:var(--gl-color-text);-webkit-font-smoothing:antialiased;transition:background .4s,color .3s}.glass-bg::before{content:'';position:absolute;top:20%;left:-30%;width:160%;height:55%;background:radial-gradient(ellipse at 35% 45%,var(--gl-bg-light-streak-1) 0,transparent 50%),radial-gradient(ellipse at 65% 55%,var(--gl-bg-light-streak-2) 0,transparent 45%);transform:rotate(-8deg);pointer-events:none;z-index:0}.glass-bg::after{content:'';position:absolute;top:40%;right:-20%;width:70%;height:50%;background:radial-gradient(ellipse at center,var(--gl-bg-warm-glow) 0,transparent 65%);pointer-events:none;z-index:0}.glass-bg>*{position:relative;z-index:1}.glass-bg--has-tab-bar{padding-bottom:var(--gl-tab-bar-height)}.glass-bg--has-tab-bar-floating{padding-bottom:calc(var(--gl-tab-bar-accessory-size) + var(--gl-tab-bar-floating-bottom) + var(--gl-space-md))}.glass-nav{display:flex;justify-content:space-between;align-items:center;padding:0 var(--gl-space-xs)}.glass-pill{width:46px;height:46px;border-radius:var(--gl-radius-pill);background:var(--gl-surface-3);backdrop-filter:blur(var(--gl-blur));-webkit-backdrop-filter:blur(var(--gl-blur));border:1.5px solid var(--gl-border-strong);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:var(--gl-transition);color:var(--gl-color-text);box-shadow:var(--gl-shadow-glow),var(--gl-inset-medium);outline:0;-webkit-tap-highlight-color:transparent}.glass-pill:hover{background:var(--gl-surface-5);transform:scale(1.05)}.glass-pill:active{transform:scale(.95)}.glass-pill ::slotted(svg),.glass-pill svg{width:20px;height:20px;fill:none;stroke:var(--gl-color-text);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}.glass-title{text-align:center;color:var(--gl-color-text-heading);font-size:var(--gl-font-size-title);font-weight:var(--gl-font-weight-semibold);line-height:1.3;text-shadow:0 2px 12px rgba(0,0,0,.15);letter-spacing:-.3px}.glass-card{background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur));-webkit-backdrop-filter:blur(var(--gl-blur));border:1.5px solid var(--gl-border-medium);border-radius:var(--gl-radius-card);padding:var(--gl-space-3xl) var(--gl-space-xl) var(--gl-space-2xl);box-shadow:var(--gl-shadow-card),var(--gl-inset-strong)}.glass-card--glow{position:relative;overflow:hidden;background:linear-gradient(to bottom,var(--gl-card-glow-top) 0,var(--gl-card-glow-mid) 25%,var(--gl-card-glow-low) 55%,var(--gl-card-glow-bottom) 100%)}.glass-card--glow::before{content:'';position:absolute;top:0;left:10%;right:10%;height:1px;background:linear-gradient(90deg,transparent 0,rgba(255,255,255,.5) 30%,rgba(255,255,255,.6) 50%,rgba(255,255,255,.5) 70%,transparent 100%);z-index:1}.glass-card__icon{display:flex;align-items:center;justify-content:center;margin:0 auto var(--gl-space-lg)}.glass-card__icon svg{width:64px;height:64px;stroke:var(--gl-card-icon-color);stroke-width:1.2;fill:none}.glass-card__text{color:var(--gl-card-text-color);font-size:var(--gl-font-size-base);font-weight:var(--gl-font-weight-normal);line-height:1.55;text-align:center}.glass-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;height:56px;border:none;border-radius:var(--gl-radius-btn);font-family:var(--gl-font-family);font-size:var(--gl-font-size-btn);font-weight:var(--gl-font-weight-semibold);cursor:pointer;transition:var(--gl-transition);outline:0;-webkit-tap-highlight-color:transparent}a.glass-btn{display:inline-flex;text-decoration:none}.glass-btn ::slotted(svg),.glass-btn svg{width:20px;height:20px;flex-shrink:0;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.glass-btn--primary{background:linear-gradient(135deg,var(--gl-color-primary) 0,var(--gl-color-primary-mid) 50%,var(--gl-color-primary-dark) 100%);color:var(--gl-color-on-primary,#fff);border:1px solid var(--gl-border-warm);box-shadow:var(--gl-shadow-btn-primary),var(--gl-inset-strong)}.glass-btn--primary ::slotted(svg),.glass-btn--primary svg{fill:var(--gl-icon-on-primary);stroke:var(--gl-icon-on-primary);stroke-width:0}.glass-btn--primary:hover{transform:translateY(-1px)}.glass-btn--primary:active{transform:translateY(1px)}.glass-btn--secondary{background:linear-gradient(to bottom,var(--gl-surface-milk-strong) 0,var(--gl-surface-milk) 100%);backdrop-filter:blur(var(--gl-blur));-webkit-backdrop-filter:blur(var(--gl-blur));border:1.5px solid var(--gl-border-milk);color:var(--gl-color-text-on-light);box-shadow:var(--gl-shadow-btn),var(--gl-inset-milk)}.glass-btn--secondary ::slotted(svg),.glass-btn--secondary svg{fill:none;stroke:var(--gl-icon-on-secondary);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.glass-btn--secondary:hover{transform:translateY(-1px)}.glass-btn--secondary:active{transform:translateY(1px)}.glass-btn--tertiary{background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur-light));-webkit-backdrop-filter:blur(var(--gl-blur-light));border:1px solid var(--gl-border-subtle);color:var(--gl-color-text-muted);box-shadow:0 4px 12px rgba(0,0,0,.1),var(--gl-inset-subtle)}.glass-btn--tertiary ::slotted(svg),.glass-btn--tertiary svg{fill:none;stroke:var(--gl-icon-on-tertiary);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.glass-btn--tertiary:hover{background:var(--gl-surface-4);color:var(--gl-color-text);transform:translateY(-1px)}.glass-btn--tertiary:active{transform:translateY(1px)}.glass-btn--sm{height:44px;font-size:var(--gl-font-size-sm);border-radius:var(--gl-radius-sm)}.glass-btn--lg{height:64px;font-size:var(--gl-font-size-lg)}.glass-btn--auto{width:auto;padding:0 var(--gl-space-xl)}.glass-status{background:var(--gl-surface-1);backdrop-filter:blur(var(--gl-blur-light));-webkit-backdrop-filter:blur(var(--gl-blur-light));border:1px solid var(--gl-border-subtle);border-radius:var(--gl-radius-btn);padding:var(--gl-space-md) var(--gl-space-lg);display:flex;align-items:center;gap:var(--gl-space-sm);box-shadow:0 4px 12px rgba(0,0,0,.08),var(--gl-inset-subtle)}.glass-status ::slotted(svg),.glass-status svg{width:20px;height:20px;flex-shrink:0;stroke:var(--gl-icon-muted);stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}.glass-status p{color:var(--gl-color-text-muted);font-size:var(--gl-font-size-sm);font-weight:var(--gl-font-weight-normal);line-height:1.45}.glass-input-group{display:flex;flex-direction:column;gap:var(--gl-space-xs)}.glass-label{font-size:var(--gl-font-size-sm);font-weight:var(--gl-font-weight-medium);color:var(--gl-icon-strong);padding-left:var(--gl-space-2xs)}.glass-input{width:100%;height:52px;padding:0 var(--gl-space-md);background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur-light));-webkit-backdrop-filter:blur(var(--gl-blur-light));border:1.5px solid var(--gl-border-medium);border-radius:var(--gl-radius-input);color:var(--gl-color-text);font-family:var(--gl-font-family);font-size:var(--gl-font-size-base);transition:var(--gl-transition);outline:0;box-shadow:var(--gl-inset-subtle);-webkit-tap-highlight-color:transparent}.glass-input::placeholder{color:var(--gl-placeholder)}.glass-input:focus{border-color:var(--gl-border-focus);background:var(--gl-surface-3);box-shadow:var(--gl-shadow-focus),var(--gl-inset-medium)}.glass-input:disabled{opacity:.4;cursor:not-allowed}.glass-input--error{border-color:var(--gl-color-error)}.glass-input--error:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--gl-color-error) 25%,transparent),var(--gl-inset-medium)}.glass-hint{font-size:var(--gl-font-size-xs);color:var(--gl-color-text-muted);padding-left:var(--gl-space-2xs)}.glass-hint--error{color:var(--gl-color-error)}.glass-textarea{width:100%;min-height:120px;padding:var(--gl-space-md);background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur-light));-webkit-backdrop-filter:blur(var(--gl-blur-light));border:1.5px solid var(--gl-border-medium);border-radius:var(--gl-radius-input);color:var(--gl-color-text);font-family:var(--gl-font-family);font-size:var(--gl-font-size-base);line-height:1.5;resize:vertical;transition:var(--gl-transition);outline:0;box-shadow:var(--gl-inset-subtle)}.glass-textarea::placeholder{color:var(--gl-placeholder)}.glass-textarea:focus{border-color:var(--gl-border-focus);background:var(--gl-surface-3);box-shadow:var(--gl-shadow-focus),var(--gl-inset-medium)}.glass-select{width:100%;height:52px;padding:0 var(--gl-space-3xl) 0 var(--gl-space-md);background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur-light));-webkit-backdrop-filter:blur(var(--gl-blur-light));border:1.5px solid var(--gl-border-medium);border-radius:var(--gl-radius-input);color:var(--gl-color-text);font-family:var(--gl-font-family);font-size:var(--gl-font-size-base);transition:var(--gl-transition);outline:0;box-shadow:var(--gl-inset-subtle);cursor:pointer;appearance:none;-webkit-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='rgba(255,255,255,0.6)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 16px center}.glass-select:focus{border-color:var(--gl-border-focus);box-shadow:var(--gl-shadow-focus),var(--gl-inset-medium)}.glass-select option{background:var(--gl-color-bg-mid);color:var(--gl-color-text)}.glass-search{position:relative;display:flex;align-items:center}.glass-search__icon{position:absolute;left:var(--gl-space-md);width:18px;height:18px;stroke:var(--gl-icon-muted)!important;stroke-width:2!important;stroke-linecap:round!important;stroke-linejoin:round!important;fill:none!important;pointer-events:none;z-index:2}.glass-search .glass-input{padding-left:44px;border-radius:var(--gl-radius-full)}.glass-toggle{display:inline-flex;align-items:flex-start;gap:var(--gl-space-sm);cursor:pointer;-webkit-tap-highlight-color:transparent}.glass-toggle__input{position:absolute;opacity:0;margin:0;width:52px;height:30px;pointer-events:none}.glass-toggle__track{position:relative;width:52px;height:30px;background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur-soft));-webkit-backdrop-filter:blur(var(--gl-blur-soft));border:1.5px solid var(--gl-border-medium);border-radius:var(--gl-radius-full);transition:var(--gl-transition);box-shadow:var(--gl-inset-subtle);flex-shrink:0;margin-top:max(0px,calc((1lh - 30px)/ 2))}.glass-toggle__thumb{position:absolute;top:3px;left:3px;width:22px;height:22px;border-radius:var(--gl-radius-pill);background:var(--gl-toggle-thumb-bg);box-shadow:0 2px 6px rgba(0,0,0,.2),var(--gl-inset-milk);transition:var(--gl-transition)}.glass-toggle__input:checked+.glass-toggle__track{background:linear-gradient(135deg,var(--gl-color-primary) 0,var(--gl-color-primary-dark) 100%);border-color:var(--gl-border-warm)}.glass-toggle__input:checked+.glass-toggle__track .glass-toggle__thumb{transform:translateX(22px)}.glass-toggle__input:focus-visible+.glass-toggle__track{box-shadow:var(--gl-shadow-focus)}.glass-toggle__label{font-size:var(--gl-font-size-base);color:var(--gl-color-text);user-select:none;margin-top:max(0px,calc((30px - 1lh)/ 2))}.glass-checkbox{display:inline-flex;align-items:flex-start;gap:var(--gl-space-sm);cursor:pointer;-webkit-tap-highlight-color:transparent}.glass-checkbox__input{position:absolute;opacity:0;margin:0;width:24px;height:24px;pointer-events:none}.glass-checkbox__box{width:24px;height:24px;border-radius:var(--gl-radius-xs);background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur-soft));-webkit-backdrop-filter:blur(var(--gl-blur-soft));border:1.5px solid var(--gl-border-medium);display:flex;align-items:center;justify-content:center;transition:var(--gl-transition);box-shadow:var(--gl-inset-subtle);flex-shrink:0;margin-top:max(0px,calc((1lh - 24px)/ 2))}.glass-checkbox__box svg{width:14px;height:14px;stroke:var(--gl-color-on-primary,#ffffff);stroke-width:3;fill:none;stroke-linecap:round;stroke-linejoin:round;opacity:0;transform:scale(.5);transition:var(--gl-transition-fast)}.glass-checkbox__input:checked+.glass-checkbox__box{background:linear-gradient(135deg,var(--gl-color-primary) 0,var(--gl-color-primary-dark) 100%);border-color:var(--gl-border-warm)}.glass-checkbox__input:checked+.glass-checkbox__box svg{opacity:1;transform:scale(1)}.glass-checkbox__input:focus-visible+.glass-checkbox__box{box-shadow:var(--gl-shadow-focus)}.glass-checkbox__label{font-size:var(--gl-font-size-base);color:var(--gl-color-text);user-select:none;margin-top:max(0px,calc((24px - 1lh)/ 2))}.glass-radio{display:inline-flex;align-items:flex-start;gap:var(--gl-space-sm);cursor:pointer;-webkit-tap-highlight-color:transparent}.glass-radio__input{position:absolute;opacity:0;margin:0;width:24px;height:24px;pointer-events:none}.glass-radio__circle{width:24px;height:24px;border-radius:var(--gl-radius-pill);background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur-soft));border:1.5px solid var(--gl-border-medium);display:flex;align-items:center;justify-content:center;transition:var(--gl-transition);box-shadow:var(--gl-inset-subtle);flex-shrink:0;margin-top:max(0px,calc((1lh - 24px)/ 2))}.glass-radio__dot{width:10px;height:10px;border-radius:var(--gl-radius-pill);background:#fff;opacity:0;transform:scale(0);transition:var(--gl-transition-fast)}.glass-radio__input:checked+.glass-radio__circle{background:linear-gradient(135deg,var(--gl-color-primary) 0,var(--gl-color-primary-dark) 100%);border-color:var(--gl-border-warm)}.glass-radio__input:checked+.glass-radio__circle .glass-radio__dot{opacity:1;transform:scale(1)}.glass-radio__input:focus-visible+.glass-radio__circle{box-shadow:var(--gl-shadow-focus)}.glass-radio__label{font-size:var(--gl-font-size-base);color:var(--gl-color-text);user-select:none;margin-top:max(0px,calc((24px - 1lh)/ 2))}.glass-range-group{display:flex;flex-direction:column;gap:var(--gl-space-xs)}.glass-range-header{display:flex;justify-content:space-between;align-items:baseline}.glass-range-value{font-size:var(--gl-font-size-sm);font-weight:var(--gl-font-weight-semibold);color:var(--gl-color-primary);font-variant-numeric:tabular-nums}.glass-range{-webkit-appearance:none;appearance:none;width:100%;height:6px;border-radius:var(--gl-radius-full);background:var(--gl-range-track-bg);border:1px solid var(--gl-range-track-border);outline:0;cursor:pointer}.glass-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;box-sizing:border-box;width:26px;height:26px;border-radius:var(--gl-radius-pill);background:linear-gradient(135deg,var(--gl-color-primary) 0,var(--gl-color-primary-dark) 100%);border:2px solid rgba(255,255,255,.5);box-shadow:0 2px 8px color-mix(in srgb,var(--gl-color-primary-mid) 35%,transparent),var(--gl-inset-strong);margin-top:-2px;cursor:pointer;transition:var(--gl-transition)}.glass-range::-webkit-slider-thumb:hover{transform:scale(1.1)}.glass-range::-moz-range-thumb{width:26px;height:26px;border-radius:var(--gl-radius-pill);background:linear-gradient(135deg,var(--gl-color-primary) 0,var(--gl-color-primary-dark) 100%);border:2px solid rgba(255,255,255,.5);box-shadow:0 2px 8px color-mix(in srgb,var(--gl-color-primary-mid) 35%,transparent);cursor:pointer}.glass-range::-moz-range-track{height:6px;border-radius:var(--gl-radius-full);background:var(--gl-range-track-bg);border:1px solid var(--gl-range-track-border)}.glass-range:focus-visible{box-shadow:var(--gl-shadow-focus)}.glass-progress{width:100%;display:flex;flex-direction:column;gap:var(--gl-space-xs)}.glass-progress__header{display:flex;justify-content:space-between;align-items:baseline}.glass-progress__label{font-size:var(--gl-font-size-sm);font-weight:var(--gl-font-weight-medium);color:var(--gl-icon-strong)}.glass-progress__value{font-size:var(--gl-font-size-xs);font-weight:var(--gl-font-weight-semibold);color:var(--gl-color-text-muted);font-variant-numeric:tabular-nums}.glass-progress__track{width:100%;height:8px;border-radius:var(--gl-radius-full);background:var(--gl-surface-2);border:1px solid var(--gl-border-subtle);overflow:hidden;box-shadow:var(--gl-inset-subtle)}.glass-progress__fill{height:100%;border-radius:var(--gl-radius-full);background:linear-gradient(90deg,var(--gl-color-primary) 0,var(--gl-color-primary-dark) 100%);box-shadow:0 0 8px color-mix(in srgb,var(--gl-color-primary) 30%,transparent),var(--gl-inset-strong);transition:width .5s cubic-bezier(.4, 0, .2, 1);position:relative}.glass-progress__fill::after{content:'';position:absolute;top:0;left:0;right:0;height:50%;border-radius:var(--gl-radius-full);background:linear-gradient(to bottom,rgba(255,255,255,.3) 0,transparent 100%)}.glass-progress--sm .glass-progress__track{height:4px}.glass-progress--lg .glass-progress__track{height:12px}.glass-progress--success .glass-progress__fill{background:linear-gradient(90deg,var(--gl-color-success) 0,var(--gl-color-success-dark,#2da44e) 100%);box-shadow:0 0 8px color-mix(in srgb,var(--gl-color-success) 30%,transparent),var(--gl-inset-strong)}.glass-progress--error .glass-progress__fill{background:linear-gradient(90deg,var(--gl-color-error) 0,var(--gl-color-error-dark,#d63027) 100%);box-shadow:0 0 8px color-mix(in srgb,var(--gl-color-error) 30%,transparent),var(--gl-inset-strong)}.glass-modal-overlay{position:fixed;inset:0;background:var(--gl-surface-overlay);backdrop-filter:blur(var(--gl-blur-soft));-webkit-backdrop-filter:blur(var(--gl-blur-soft));display:flex;align-items:center;justify-content:center;padding:var(--gl-space-lg);z-index:1000;opacity:0;pointer-events:none;transition:var(--gl-transition-modal);font-family:var(--gl-font-family);-webkit-font-smoothing:antialiased}.glass-modal-overlay.is-active{opacity:1;pointer-events:auto}.glass-modal{width:100%;max-width:340px;background:linear-gradient(to bottom,var(--gl-card-glow-top) 0,var(--gl-card-glow-bottom) 100%);backdrop-filter:blur(var(--gl-blur-heavy));-webkit-backdrop-filter:blur(var(--gl-blur-heavy));border:1.5px solid var(--gl-border-medium);border-radius:var(--gl-radius-card);overflow:hidden;box-shadow:var(--gl-shadow-modal);transform:scale(.9) translateY(20px);transition:var(--gl-transition-modal);position:relative}.glass-modal-overlay.is-active .glass-modal{transform:scale(1) translateY(0)}.glass-modal::before{content:'';position:absolute;top:0;left:10%;right:10%;height:1px;background:linear-gradient(90deg,transparent 0,rgba(255,255,255,.4) 30%,rgba(255,255,255,.5) 50%,rgba(255,255,255,.4) 70%,transparent 100%)}.glass-modal__header{padding:var(--gl-space-xl) var(--gl-space-xl) var(--gl-space-sm);text-align:center}.glass-modal__title{font-size:var(--gl-font-size-modal);font-weight:var(--gl-font-weight-semibold);color:var(--gl-color-text)}.glass-modal__body{padding:var(--gl-space-sm) var(--gl-space-xl) var(--gl-space-xl);text-align:center}.glass-modal__body p{color:var(--gl-color-text-muted);font-size:var(--gl-font-size-base);line-height:1.55}.glass-modal__footer{display:flex;border-top:1px solid var(--gl-border-subtle)}.glass-modal__action{flex:1;height:52px;background:0 0;border:none;font-family:var(--gl-font-family);font-size:var(--gl-font-size-btn);font-weight:var(--gl-font-weight-medium);color:var(--gl-color-text-muted);cursor:pointer;transition:var(--gl-transition-fast);outline:0}.glass-modal__action:hover{background:var(--gl-surface-1)}.glass-modal__action+.glass-modal__action{border-left:1px solid var(--gl-border-subtle)}.glass-modal__action--primary{color:var(--gl-color-primary);font-weight:var(--gl-font-weight-semibold)}.glass-modal__action--danger{color:var(--gl-color-error);font-weight:var(--gl-font-weight-semibold)}.glass-toast{position:fixed;top:var(--gl-space-4xl);left:50%;transform:translateX(-50%) translateY(-20px);min-width:280px;max-width:340px;padding:var(--gl-space-md) var(--gl-space-lg);background:linear-gradient(to bottom,var(--gl-surface-4) 0,var(--gl-surface-2) 100%);backdrop-filter:blur(var(--gl-blur));-webkit-backdrop-filter:blur(var(--gl-blur));border:1px solid var(--gl-border-medium);border-radius:var(--gl-radius-btn);display:flex;align-items:center;gap:var(--gl-space-sm);box-shadow:var(--gl-shadow-toast),var(--gl-inset-medium);z-index:1100;opacity:0;pointer-events:none;transition:var(--gl-transition-modal);font-family:var(--gl-font-family);-webkit-font-smoothing:antialiased}.glass-toast.is-visible{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}.glass-toast__icon{width:22px;height:22px;flex-shrink:0;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}.glass-toast--success .glass-toast__icon{stroke:var(--gl-color-success)}.glass-toast--error .glass-toast__icon{stroke:var(--gl-color-error)}.glass-toast--warning .glass-toast__icon{stroke:var(--gl-color-warning)}.glass-toast__text{font-size:var(--gl-font-size-sm);font-weight:var(--gl-font-weight-medium);color:var(--gl-color-text);line-height:1.4}.glass-tab-bar{position:fixed;bottom:0;left:0;right:0;height:var(--gl-tab-bar-height);background:linear-gradient(to bottom,var(--gl-surface-3) 0,var(--gl-surface-1) 100%);backdrop-filter:blur(var(--gl-blur));-webkit-backdrop-filter:blur(var(--gl-blur));border-top:1px solid var(--gl-border-subtle);display:flex;justify-content:space-around;align-items:flex-start;padding-top:var(--gl-space-xs);padding-bottom:env(safe-area-inset-bottom,8px);z-index:900;box-shadow:0 -4px 20px rgba(0,0,0,.08),var(--gl-inset-subtle)}.glass-tab-bar__item{display:flex;flex-direction:column;align-items:center;gap:var(--gl-space-2xs);padding:var(--gl-space-2xs) var(--gl-space-sm);background:0 0;border:none;cursor:pointer;transition:var(--gl-transition);outline:0;-webkit-tap-highlight-color:transparent;min-width:60px}.glass-tab-bar__icon{width:24px;height:24px;display:flex;align-items:center;justify-content:center;position:relative}.glass-tab-bar__icon svg{width:24px;height:24px;fill:none;stroke:var(--gl-icon-muted);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;transition:var(--gl-transition)}.glass-tab-bar__label{font-size:10px;font-weight:var(--gl-font-weight-medium);color:var(--gl-icon-muted);transition:var(--gl-transition);letter-spacing:.2px}.glass-tab-bar__item.is-active .glass-tab-bar__icon svg{stroke:var(--gl-color-primary);filter:drop-shadow(0 0 6px color-mix(in srgb, var(--gl-color-primary) 35%, transparent))}.glass-tab-bar__item.is-active .glass-tab-bar__label{color:var(--gl-color-primary)}.glass-tab-bar__item.is-active .glass-tab-bar__icon::after{content:'';position:absolute;bottom:-6px;left:50%;transform:translateX(-50%);width:4px;height:4px;border-radius:var(--gl-radius-pill);background:var(--gl-color-primary);box-shadow:0 0 6px color-mix(in srgb,var(--gl-color-primary) 50%,transparent)}.glass-tab-bar__item:not(.is-active):hover .glass-tab-bar__icon svg{stroke:var(--gl-icon-default)}.glass-tab-bar__item:not(.is-active):hover .glass-tab-bar__label{color:var(--gl-icon-default)}.glass-tab-bar__badge{position:absolute;top:-4px;right:-8px;min-width:16px;height:16px;padding:0 4px;border-radius:var(--gl-radius-full);background:var(--gl-color-error-dark,#d63027);color:#fff;font-size:10px;font-weight:var(--gl-font-weight-semibold);display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px color-mix(in srgb,var(--gl-color-error) 40%,transparent)}.glass-tab-bar-dock{position:fixed;left:50%;bottom:calc(var(--gl-tab-bar-floating-bottom) + env(safe-area-inset-bottom,0px));transform:translateX(-50%);display:flex;align-items:center;gap:var(--gl-tab-bar-floating-gap);z-index:900;max-width:calc(100vw - 2 * var(--gl-space-md))}.glass-tab-bar-dock--accessory-left{flex-direction:row-reverse}.glass-tab-bar.glass-tab-bar--floating{position:static;left:auto;right:auto;bottom:auto;height:auto;width:max-content;padding:var(--gl-tab-bar-floating-padding);border-radius:var(--gl-tab-bar-floating-radius);border:1px solid var(--gl-border-subtle);background:linear-gradient(to bottom,var(--gl-surface-3) 0,var(--gl-surface-1) 100%);box-shadow:0 8px 32px rgba(0,0,0,.18),0 2px 8px rgba(0,0,0,.08),var(--gl-inset-subtle);display:flex;justify-content:flex-start;align-items:center;gap:var(--gl-space-2xs)}.glass-tab-bar--floating .glass-tab-bar__item{position:relative;border-radius:var(--gl-radius-full);padding:var(--gl-space-2xs) var(--gl-space-sm);min-width:auto;align-items:center}.glass-tab-bar--floating .glass-tab-bar__item>*{position:relative;z-index:1}.glass-tab-bar--floating .glass-tab-bar__item.is-active::before{content:'';position:absolute;inset:0;border-radius:inherit;background:radial-gradient(circle at center,color-mix(in srgb,var(--gl-tab-bar-spotlight-color) 28%,transparent) 0,color-mix(in srgb,var(--gl-tab-bar-spotlight-color) 10%,transparent) 55%,transparent 100%);pointer-events:none;z-index:0}.glass-tab-bar--floating .glass-tab-bar__item.is-active .glass-tab-bar__icon::after{display:none}.glass-tab-bar__accessory{width:var(--gl-tab-bar-accessory-size);height:var(--gl-tab-bar-accessory-size);border-radius:var(--gl-radius-pill);background:linear-gradient(to bottom,var(--gl-surface-3) 0,var(--gl-surface-1) 100%);backdrop-filter:blur(var(--gl-blur));-webkit-backdrop-filter:blur(var(--gl-blur));border:1px solid var(--gl-border-subtle);box-shadow:0 8px 32px rgba(0,0,0,.18),0 2px 8px rgba(0,0,0,.08),var(--gl-inset-subtle);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:var(--gl-transition);outline:0;padding:0;-webkit-tap-highlight-color:transparent;flex-shrink:0}.glass-tab-bar__accessory ::slotted(svg),.glass-tab-bar__accessory svg{width:22px;height:22px;fill:none;stroke:var(--gl-icon-default);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;transition:var(--gl-transition)}.glass-tab-bar__accessory:hover{transform:translateY(-1px)}.glass-tab-bar__accessory:hover ::slotted(svg),.glass-tab-bar__accessory:hover svg{stroke:var(--gl-icon-strong)}.glass-tab-bar__accessory:focus-visible{box-shadow:0 8px 32px rgba(0,0,0,.18),var(--gl-shadow-focus),var(--gl-inset-subtle)}.glass-tab-bar__accessory--accent{background:linear-gradient(135deg,var(--gl-color-primary) 0,color-mix(in srgb,var(--gl-color-primary) 70%,transparent) 100%);border-color:color-mix(in srgb,var(--gl-color-primary) 50%,transparent);box-shadow:0 8px 32px color-mix(in srgb,var(--gl-color-primary) 35%,transparent),var(--gl-inset-medium)}.glass-tab-bar__accessory--accent ::slotted(svg),.glass-tab-bar__accessory--accent svg{stroke:var(--gl-color-on-primary,#ffffff)}.glass-tab-bar__accessory--accent:hover ::slotted(svg),.glass-tab-bar__accessory--accent:hover svg{stroke:var(--gl-color-on-primary,#ffffff)}.glass-tab-bar__accessory--success{background:linear-gradient(135deg,var(--gl-color-success) 0,color-mix(in srgb,var(--gl-color-success) 70%,transparent) 100%);border-color:color-mix(in srgb,var(--gl-color-success) 50%,transparent);box-shadow:0 8px 32px color-mix(in srgb,var(--gl-color-success) 35%,transparent),var(--gl-inset-medium)}.glass-tab-bar__accessory--success ::slotted(svg),.glass-tab-bar__accessory--success svg{stroke:var(--gl-color-on-success,#ffffff)}.glass-tab-bar__accessory--error{background:linear-gradient(135deg,var(--gl-color-error) 0,color-mix(in srgb,var(--gl-color-error) 70%,transparent) 100%);border-color:color-mix(in srgb,var(--gl-color-error) 50%,transparent);box-shadow:0 8px 32px color-mix(in srgb,var(--gl-color-error) 35%,transparent),var(--gl-inset-medium)}.glass-tab-bar__accessory--error ::slotted(svg),.glass-tab-bar__accessory--error svg{stroke:var(--gl-color-on-error,#ffffff)}.glass-accordion{display:flex;flex-direction:column;gap:var(--gl-space-xs)}.glass-accordion__item{background:var(--gl-surface-2);backdrop-filter:blur(var(--gl-blur-light));-webkit-backdrop-filter:blur(var(--gl-blur-light));border:1px solid var(--gl-border-subtle);border-radius:var(--gl-radius-btn);overflow:hidden;transition:var(--gl-transition);box-shadow:var(--gl-inset-subtle)}.glass-accordion__item.is-open{background:var(--gl-surface-3);border-color:var(--gl-border-medium);box-shadow:0 4px 16px rgba(0,0,0,.1),var(--gl-inset-medium)}.glass-accordion__trigger{width:100%;display:flex;align-items:center;justify-content:space-between;gap:var(--gl-space-sm);padding:var(--gl-space-md) var(--gl-space-lg);background:0 0;border:none;cursor:pointer;font-family:var(--gl-font-family);font-size:var(--gl-font-size-base);font-weight:var(--gl-font-weight-semibold);color:var(--gl-color-text);text-align:left;outline:0;transition:var(--gl-transition);-webkit-tap-highlight-color:transparent}.glass-accordion__trigger:hover{color:var(--gl-color-primary)}.glass-accordion__trigger-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0}.glass-accordion__trigger-icon svg{width:18px;height:18px;fill:none;stroke:var(--gl-icon-default);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .3s cubic-bezier(.4, 0, .2, 1)}.glass-accordion__item.is-open .glass-accordion__trigger-icon svg{transform:rotate(180deg);stroke:var(--gl-color-primary)}.glass-accordion__content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4, 0, .2, 1)}.glass-accordion__item.is-open .glass-accordion__content{max-height:500px}.glass-accordion__body{padding:0 var(--gl-space-lg) var(--gl-space-lg);color:var(--gl-accordion-body-color);font-size:var(--gl-font-size-sm);line-height:1.6}.glass-badge{--gl-badge-accent:var(--gl-color-primary);--gl-badge-accent-text:var(--gl-color-primary-on-surface, var(--gl-color-primary));display:inline-flex;align-items:center;gap:var(--gl-space-2xs);padding:var(--gl-space-2xs) var(--gl-space-sm);background:var(--gl-surface-3);backdrop-filter:blur(var(--gl-blur-soft));-webkit-backdrop-filter:blur(var(--gl-blur-soft));border:1px solid var(--gl-border-subtle);border-radius:var(--gl-radius-full);font-size:var(--gl-font-size-xs);font-weight:var(--gl-font-weight-medium);color:var(--gl-color-text);box-shadow:var(--gl-inset-subtle)}.glass-badge--primary{--gl-badge-accent:var(--gl-color-primary);--gl-badge-accent-text:var(--gl-color-primary-on-surface, var(--gl-color-primary));background:linear-gradient(135deg,var(--gl-color-primary-surface,rgba(245,166,35,.25)) 0,color-mix(in srgb,var(--gl-color-primary-dark) 20%,transparent) 100%),var(--gl-state-scrim,transparent);border-color:var(--gl-color-primary-border,var(--gl-border-warm));color:var(--gl-color-primary-on-surface,var(--gl-color-primary))}.glass-badge--success{--gl-badge-accent:var(--gl-color-success);--gl-badge-accent-text:var(--gl-color-success-on-surface, var(--gl-color-success));background:linear-gradient(var(--gl-color-success-surface,rgba(52,199,89,.15)) 0,var(--gl-color-success-surface,rgba(52,199,89,.15)) 100%),var(--gl-state-scrim,transparent);border-color:var(--gl-color-success-border,rgba(52,199,89,.3));color:var(--gl-color-success-on-surface,var(--gl-color-success))}.glass-badge--error{--gl-badge-accent:var(--gl-color-error);--gl-badge-accent-text:var(--gl-color-error-on-surface, var(--gl-color-error));background:linear-gradient(var(--gl-color-error-surface,rgba(255,59,48,.15)) 0,var(--gl-color-error-surface,rgba(255,59,48,.15)) 100%),var(--gl-state-scrim,transparent);border-color:var(--gl-color-error-border,rgba(255,59,48,.3));color:var(--gl-color-error-on-surface,var(--gl-color-error))}.glass-badge--interactive{font-family:inherit;-webkit-appearance:none;appearance:none;cursor:pointer;transition:var(--gl-transition-fast);outline:0;-webkit-tap-highlight-color:transparent}.glass-badge--interactive:hover{border-color:color-mix(in srgb,var(--gl-badge-accent) 45%,var(--gl-border-subtle));box-shadow:var(--gl-inset-subtle),inset 0 0 0 100px color-mix(in srgb,var(--gl-badge-accent) 12%,transparent)}.glass-badge--interactive:active{transform:scale(.96)}.glass-badge--interactive:focus-visible{box-shadow:var(--gl-shadow-focus),var(--gl-inset-subtle)}.glass-badge--selected{border-color:color-mix(in srgb,var(--gl-badge-accent) 55%,transparent);color:var(--gl-badge-accent-text);box-shadow:var(--gl-inset-subtle),inset 0 0 0 100px color-mix(in srgb,var(--gl-badge-accent) 22%,transparent)}.glass-badge--interactive.glass-badge--selected:hover{box-shadow:var(--gl-inset-subtle),inset 0 0 0 100px color-mix(in srgb,var(--gl-badge-accent) 30%,transparent)}.glass-badge--interactive.glass-badge--selected:focus-visible{box-shadow:var(--gl-shadow-focus),var(--gl-inset-subtle),inset 0 0 0 100px color-mix(in srgb,var(--gl-badge-accent) 22%,transparent)}.glass-divider{height:1px;border:none;background:linear-gradient(90deg,transparent 0,var(--gl-border-subtle) 20%,var(--gl-border-medium) 50%,var(--gl-border-subtle) 80%,transparent 100%)}.glass-avatar{width:44px;height:44px;border-radius:var(--gl-radius-pill);background:var(--gl-surface-3);backdrop-filter:blur(var(--gl-blur-soft));-webkit-backdrop-filter:blur(var(--gl-blur-soft));border:1.5px solid var(--gl-border-strong);display:flex;align-items:center;justify-content:center;overflow:hidden;box-shadow:var(--gl-shadow-glow),var(--gl-inset-medium);flex-shrink:0;font-size:var(--gl-font-size-btn);font-weight:var(--gl-font-weight-semibold);color:var(--gl-color-text)}.glass-avatar ::slotted(img),.glass-avatar img{width:100%;height:100%;object-fit:cover}.glass-avatar--sm{width:32px;height:32px;font-size:var(--gl-font-size-xs)}.glass-avatar--lg{width:56px;height:56px;font-size:var(--gl-font-size-lg)}.glass-theme-toggle{width:46px;height:46px;border-radius:var(--gl-radius-pill);background:var(--gl-surface-3);backdrop-filter:blur(var(--gl-blur));-webkit-backdrop-filter:blur(var(--gl-blur));border:1.5px solid var(--gl-border-strong);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:var(--gl-transition);box-shadow:var(--gl-shadow-glow),var(--gl-inset-medium);outline:0;-webkit-tap-highlight-color:transparent}.glass-theme-toggle:hover{background:var(--gl-surface-5);transform:scale(1.05)}.glass-theme-toggle:active{transform:scale(.95)}.glass-theme-toggle svg{width:20px;height:20px;fill:none;stroke:var(--gl-color-text);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.glass-theme-toggle .icon-sun{display:none}.glass-theme-toggle .icon-moon,[data-theme=light] .glass-theme-toggle .icon-sun{display:block}[data-theme=light] .glass-theme-toggle .icon-moon{display:none}.glass-popover-anchor{position:relative;display:inline-block}.glass-popover{position:absolute;top:calc(100% + var(--gl-space-xs));left:50%;transform:translateX(-50%) translateY(-4px) scale(.96);transform-origin:top center;min-width:220px;padding:var(--gl-space-sm);background:var(--gl-surface-3);backdrop-filter:blur(var(--gl-blur));-webkit-backdrop-filter:blur(var(--gl-blur));border:1px solid var(--gl-border-medium);border-radius:var(--gl-radius-card);box-shadow:var(--gl-shadow-card),var(--gl-inset-strong);opacity:0;visibility:hidden;pointer-events:none;transition:opacity .18s,transform .18s cubic-bezier(.2,.8,.2,1),visibility 0s linear .18s;z-index:50}.glass-popover.is-open{opacity:1;visibility:visible;pointer-events:auto;transform:translateX(-50%) translateY(0) scale(1);transition:opacity .18s,transform .22s cubic-bezier(.2,.8,.2,1),visibility linear}.glass-popover--top{top:auto;bottom:calc(100% + var(--gl-space-xs));transform-origin:bottom center}.glass-popover--start{left:0;transform:translateY(-4px) scale(.96);transform-origin:top left}.glass-popover--start.is-open{transform:translateY(0) scale(1)}.glass-popover--end{left:auto;right:0;transform:translateY(-4px) scale(.96);transform-origin:top right}.glass-popover--end.is-open{transform:translateY(0) scale(1)}.glass-list{background:var(--gl-surface-1);backdrop-filter:blur(var(--gl-blur-light));-webkit-backdrop-filter:blur(var(--gl-blur-light));border:1px solid var(--gl-border-subtle);border-radius:var(--gl-radius-btn);box-shadow:0 4px 12px rgba(0,0,0,.08),var(--gl-inset-subtle);overflow:hidden;display:flex;flex-direction:column;width:100%;margin:0;padding:0;list-style:none}.glass-list--flush{border-radius:0;border-left:none;border-right:none;margin-left:calc(var(--gl-space-lg) * -1);margin-right:calc(var(--gl-space-lg) * -1)}.glass-list--bare{background:0 0;backdrop-filter:none;-webkit-backdrop-filter:none;border:none;border-radius:0;box-shadow:none}.glass-list__section-header{padding:var(--gl-space-xs) var(--gl-space-lg) var(--gl-space-2xs);font-size:var(--gl-font-size-xs);font-weight:var(--gl-font-weight-semibold);color:var(--gl-color-text-muted);text-transform:uppercase;letter-spacing:.3px}.glass-list__item{position:relative;display:flex;align-items:center;gap:var(--gl-space-sm);padding:var(--gl-space-md) var(--gl-space-lg);min-height:56px;color:var(--gl-color-text);font-size:var(--gl-font-size-base);text-decoration:none;background:0 0;border:none;width:100%;text-align:left;font-family:inherit;list-style:none}.glass-list__item:not(:last-child)::after{content:'';position:absolute;left:calc(var(--gl-space-lg) + 28px + var(--gl-space-sm));right:var(--gl-space-lg);bottom:0;height:1px;background:var(--gl-border-subtle);pointer-events:none}.glass-list__item:not(:has(.glass-list__leading)):not(:last-child)::after{left:var(--gl-space-lg)}.glass-list__item:has(.glass-list__leading--lg):not(:last-child)::after{left:calc(var(--gl-space-lg) + 40px + var(--gl-space-sm))}.glass-list__item--center{justify-content:center;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.glass-list__item--center>.glass-list__title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.glass-list__item--interactive{cursor:pointer;transition:background .15s}.glass-list__item--interactive:focus-visible,.glass-list__item--interactive:hover{background:var(--gl-surface-2);outline:0}.glass-list__item--interactive:active{background:var(--gl-surface-3)}.glass-list__item--danger{color:var(--gl-color-error)}.glass-list__item--danger .glass-list__leading,.glass-list__item--danger .glass-list__title{color:inherit}.glass-list__item--accent{color:var(--gl-color-primary)}.glass-list__item--accent .glass-list__leading,.glass-list__item--accent .glass-list__title{color:inherit}.glass-list__leading{flex-shrink:0;width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:var(--gl-icon-strong)}.glass-list__leading ::slotted(svg),.glass-list__leading svg{width:24px;height:24px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}.glass-list__leading--lg{width:40px;height:40px;border-radius:var(--gl-radius-xs);overflow:hidden}.glass-list__leading--lg ::slotted(svg),.glass-list__leading--lg svg{width:32px;height:32px}.glass-list__leading--lg ::slotted(img),.glass-list__leading--lg img{width:100%;height:100%;object-fit:cover;display:block}.glass-list__content{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:2px;overflow:hidden}.glass-list__title{font-size:var(--gl-font-size-base);font-weight:var(--gl-font-weight-medium);color:var(--gl-color-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.glass-list__subtitle{font-size:var(--gl-font-size-sm);color:var(--gl-color-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.glass-list__subtitle--wrap{white-space:normal;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.glass-list__trailing{flex-shrink:0;display:flex;align-items:center;gap:var(--gl-space-xs);color:var(--gl-color-text-muted);font-size:var(--gl-font-size-sm)}.glass-list__trailing ::slotted(svg),.glass-list__trailing svg{width:18px;height:18px;stroke:var(--gl-icon-muted);stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}.glass-list__value{color:var(--gl-color-text-muted);font-size:var(--gl-font-size-sm);white-space:nowrap}.glass-skeleton{display:flex;flex-direction:column;gap:10px}.glass-skeleton__line{height:12px;border-radius:6px;background:linear-gradient(90deg,var(--gl-surface-1) 0,var(--gl-surface-4) 50%,var(--gl-surface-1) 100%);background-size:200% 100%;animation:1.4s ease-in-out infinite glass-skeleton}.glass-skeleton__line--title{height:18px}@keyframes glass-skeleton{from{background-position:200% 0}to{background-position:-200% 0}}@media (prefers-reduced-motion:reduce){.glass-skeleton__line{animation:none}}.glass-table-wrap{overflow-x:auto;border-radius:var(--gl-radius-sm)}.glass-table{width:100%;border-collapse:collapse;font-size:var(--gl-font-size-sm);color:var(--gl-color-text)}.glass-table th{text-align:left;padding:8px 10px;white-space:nowrap;font-weight:var(--gl-font-weight-medium);color:var(--gl-color-text-muted);border-bottom:1px solid var(--gl-border-medium)}.glass-table td{padding:9px 10px;vertical-align:top;border-bottom:1px solid var(--gl-border-subtle)}.glass-table tbody tr:last-child td{border-bottom:0}.glass-table tbody tr:hover td{background:var(--gl-surface-1)}.glass-table__num{text-align:right;font-variant-numeric:tabular-nums}.glass-table__muted{color:var(--gl-color-text-muted)}.glass-prose{font-size:var(--gl-font-size-base);line-height:1.6;color:var(--gl-color-text)}.glass-prose>:first-child{margin-top:0}.glass-prose>:last-child{margin-bottom:0}.glass-prose h1,.glass-prose h2,.glass-prose h3{color:var(--gl-color-text-heading);line-height:1.25;margin:1.2em 0 .4em}.glass-prose h1{font-size:var(--gl-font-size-title)}.glass-prose h2{font-size:var(--gl-font-size-modal)}.glass-prose h3{font-size:var(--gl-font-size-lg)}.glass-prose blockquote,.glass-prose ol,.glass-prose p,.glass-prose pre,.glass-prose table,.glass-prose ul{margin:0 0 .9em}.glass-prose ol,.glass-prose ul{padding-left:1.3em}.glass-prose strong{color:var(--gl-color-text-heading)}.glass-prose a{color:var(--gl-color-primary);text-decoration:underline;text-underline-offset:2px}.glass-prose code{font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:.9em;background:var(--gl-surface-2);padding:1px 5px;border-radius:4px}.glass-prose pre{padding:12px 14px;overflow-x:auto;background:var(--gl-surface-1);border-radius:var(--gl-radius-sm)}.glass-prose pre code{background:0 0;padding:0}.glass-prose blockquote{padding:8px 14px;border-left:3px solid var(--gl-color-primary);background:var(--gl-surface-1);border-radius:0 var(--gl-radius-xs) var(--gl-radius-xs) 0}.glass-prose img{max-width:100%;height:auto;border-radius:var(--gl-radius-sm)}.glass-prose hr{height:1px;border:0;margin:1.2em 0;background:var(--gl-border-subtle)}.glass-prose table{width:100%;border-collapse:collapse}.glass-prose td,.glass-prose th{padding:6px 8px;text-align:left;border-bottom:1px solid var(--gl-border-subtle)}.gl-stack{display:flex;flex-direction:column}.gl-row{display:flex;flex-direction:row;align-items:center}.gl-stack--2xs{gap:var(--gl-space-2xs)}.gl-stack--xs{gap:var(--gl-space-xs)}.gl-stack--sm{gap:var(--gl-space-sm)}.gl-stack--md{gap:var(--gl-space-md)}.gl-stack--lg{gap:var(--gl-space-lg)}.gl-stack--xl{gap:var(--gl-space-xl)}.gl-row--xs{gap:var(--gl-space-xs)}.gl-row--sm{gap:var(--gl-space-sm)}.gl-row--md{gap:var(--gl-space-md)}.gl-text-center{text-align:center}.gl-text-muted{color:var(--gl-color-text-muted)}.gl-text-sm{font-size:var(--gl-font-size-sm)}.gl-mt-sm{margin-top:var(--gl-space-sm)}.gl-mt-md{margin-top:var(--gl-space-md)}.gl-mt-lg{margin-top:var(--gl-space-lg)}.gl-mt-xl{margin-top:var(--gl-space-xl)}.gl-mb-sm{margin-bottom:var(--gl-space-sm)}.gl-mb-md{margin-bottom:var(--gl-space-md)}.gl-mb-lg{margin-bottom:var(--gl-space-lg)}.gl-mb-xl{margin-bottom:var(--gl-space-xl)}.gl-px{padding-left:var(--gl-space-lg);padding-right:var(--gl-space-lg)}.gl-w-full{width:100%}.gl-flex-1{flex:1}svg.glass-icon--fill{fill:currentColor;stroke:none}\n/*# sourceMappingURL=glasskit.min.css.map */";
|
|
10
|
-
|
|
11
|
-
const componentsCss = componentsHead + componentsTail;
|
|
12
|
-
const css = componentsHead + tokensCss + componentsTail;
|
|
13
|
-
|
|
14
|
-
const glassSheet = new CSSStyleSheet();
|
|
15
|
-
glassSheet.replaceSync(css);
|
|
16
|
-
|
|
17
|
-
const tokensSheet = new CSSStyleSheet();
|
|
18
|
-
tokensSheet.replaceSync(tokensCss);
|
|
19
|
-
|
|
20
|
-
const componentsSheet = new CSSStyleSheet();
|
|
21
|
-
componentsSheet.replaceSync(componentsCss);
|
|
1
|
+
import { tokensCss, componentsSheet } from '@jungherz-de/glasskit/glasskit-styles.js';
|
|
22
2
|
|
|
23
3
|
// ── Design Tokens ──
|
|
24
4
|
// The shadow roots deliberately adopt the *components* sheet only. Adopting
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GlkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/glasskit/glasskit-styles.js';
|
|
2
3
|
|
|
3
4
|
const CHEVRON_SVG = `<span class="glass-accordion__trigger-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg></span>`;
|
|
4
5
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GlkFormElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/glasskit/glasskit-styles.js';
|
|
2
3
|
|
|
3
4
|
const CHECKMARK_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>`;
|
|
4
5
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { GlkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/glasskit/glasskit-styles.js';
|
|
3
|
+
|
|
4
|
+
// Empty state for lists and result pages. Came back from EhrenPfoten in 1.15.0.
|
|
5
|
+
//
|
|
6
|
+
// Attributes: title, text — an empty one hides its element instead of
|
|
7
|
+
// leaving an empty paragraph
|
|
8
|
+
// Slots: default (icon, with a plain circle as slot fallback), action
|
|
9
|
+
// Parts: empty, icon, title, text, action
|
|
10
|
+
|
|
11
|
+
const FALLBACK_ICON = '<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M8 12h8"/></svg>';
|
|
12
|
+
|
|
13
|
+
class GlkEmpty extends GlkElement {
|
|
14
|
+
static get observedAttributes() { return ['title', 'text']; }
|
|
15
|
+
|
|
16
|
+
render() {
|
|
17
|
+
const root = this.createElement('div', ['glass-empty'], { part: 'empty' });
|
|
18
|
+
const icon = this.createElement('span', ['glass-empty__icon'], { part: 'icon' });
|
|
19
|
+
const iconSlot = document.createElement('slot');
|
|
20
|
+
iconSlot.innerHTML = FALLBACK_ICON;
|
|
21
|
+
icon.appendChild(iconSlot);
|
|
22
|
+
this._titleEl = this.createElement('p', ['glass-empty__title'], { part: 'title' });
|
|
23
|
+
this._textEl = this.createElement('p', ['glass-empty__text'], { part: 'text' });
|
|
24
|
+
const action = this.createElement('div', ['glass-empty__action'], { part: 'action' });
|
|
25
|
+
action.appendChild(this.createElement('slot', [], { name: 'action' }));
|
|
26
|
+
root.append(icon, this._titleEl, this._textEl, action);
|
|
27
|
+
this._wrapper.appendChild(root);
|
|
28
|
+
this._update();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_update() {
|
|
32
|
+
const title = this.getAttribute('title') || '';
|
|
33
|
+
const text = this.getAttribute('text') || '';
|
|
34
|
+
this._titleEl.textContent = title;
|
|
35
|
+
this._titleEl.hidden = !title;
|
|
36
|
+
this._textEl.textContent = text;
|
|
37
|
+
this._textEl.hidden = !text;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
onAttributeChanged() {
|
|
41
|
+
if (this._titleEl) this._update();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get text() { return this.getAttribute('text') || ''; }
|
|
45
|
+
set text(v) {
|
|
46
|
+
if (v) this.setAttribute('text', v);
|
|
47
|
+
else this.removeAttribute('text');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
customElements.define('glk-empty', GlkEmpty);
|
|
52
|
+
|
|
53
|
+
export { GlkEmpty };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GlkFormElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/glasskit/glasskit-styles.js';
|
|
2
3
|
|
|
3
4
|
const SEARCH_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>`;
|
|
4
5
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { GlkFormElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/glasskit/glasskit-styles.js';
|
|
3
|
+
|
|
4
|
+
// One button per option, the chosen one marked aria-pressed="true" — GlassKit
|
|
5
|
+
// styles exactly that attribute. Came back from EhrenPfoten in 1.15.0.
|
|
6
|
+
//
|
|
7
|
+
// Attributes: options (JSON [{value,label,tone?,disabled?}]), value, full,
|
|
8
|
+
// label (aria-label of the group), name (form field name)
|
|
9
|
+
// Properties: value, options (array or JSON text), full, label
|
|
10
|
+
// Event: glk-change { value } — only on a change made by the user
|
|
11
|
+
// Part: group
|
|
12
|
+
//
|
|
13
|
+
// Form-associated: a surrounding <form> receives name=value, reset restores
|
|
14
|
+
// the initial value. A value change only re-sets aria-pressed, never rebuilds,
|
|
15
|
+
// so focus stays on the button that was pressed.
|
|
16
|
+
|
|
17
|
+
const TONES = ['success', 'warning', 'error'];
|
|
18
|
+
|
|
19
|
+
function parseList(json) {
|
|
20
|
+
try {
|
|
21
|
+
const list = JSON.parse(json || '[]');
|
|
22
|
+
return Array.isArray(list) ? list : [];
|
|
23
|
+
} catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class GlkSegmented extends GlkFormElement {
|
|
29
|
+
static get observedAttributes() { return ['options', 'value', 'full', 'label']; }
|
|
30
|
+
|
|
31
|
+
render() {
|
|
32
|
+
this._group = this.createElement('div', ['glass-segmented'], { role: 'group', part: 'group' });
|
|
33
|
+
this._wrapper.appendChild(this._group);
|
|
34
|
+
this._initialValue = this.value;
|
|
35
|
+
this._build();
|
|
36
|
+
this._applyFull();
|
|
37
|
+
this._applyLabel();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_build() {
|
|
41
|
+
this._group.replaceChildren();
|
|
42
|
+
for (const option of parseList(this.getAttribute('options'))) {
|
|
43
|
+
const value = String(option.value ?? '');
|
|
44
|
+
const button = this.createElement('button', ['glass-segmented__item'], { type: 'button', 'data-value': value });
|
|
45
|
+
if (TONES.includes(option.tone)) {
|
|
46
|
+
button.classList.add(`glass-segmented__item--${option.tone}`);
|
|
47
|
+
button.appendChild(this.createElement('span', ['glass-segmented__dot']));
|
|
48
|
+
}
|
|
49
|
+
if (option.disabled) button.disabled = true;
|
|
50
|
+
button.appendChild(document.createTextNode(option.label ?? value));
|
|
51
|
+
this._group.appendChild(button);
|
|
52
|
+
}
|
|
53
|
+
this._syncValue();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_syncValue() {
|
|
57
|
+
const value = this.value;
|
|
58
|
+
for (const button of this._group.querySelectorAll('button[data-value]')) {
|
|
59
|
+
button.setAttribute('aria-pressed', String(button.dataset.value === value));
|
|
60
|
+
}
|
|
61
|
+
this.setFormValue(value);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_applyFull() {
|
|
65
|
+
this._group.classList.toggle('glass-segmented--full', this.getBoolAttr('full'));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_applyLabel() {
|
|
69
|
+
const label = this.getAttribute('label');
|
|
70
|
+
if (label) this._group.setAttribute('aria-label', label);
|
|
71
|
+
else this._group.removeAttribute('aria-label');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
setupEvents() {
|
|
75
|
+
this._onClick = (event) => {
|
|
76
|
+
const button = event.target.closest('button[data-value]');
|
|
77
|
+
if (!button || button.disabled) return;
|
|
78
|
+
const { value } = button.dataset;
|
|
79
|
+
if (value === this.value) return;
|
|
80
|
+
this.value = value;
|
|
81
|
+
this.emit('glk-change', { value });
|
|
82
|
+
};
|
|
83
|
+
this._group.addEventListener('click', this._onClick);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
teardownEvents() {
|
|
87
|
+
this._group?.removeEventListener('click', this._onClick);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
onAttributeChanged(name) {
|
|
91
|
+
if (!this._group) return;
|
|
92
|
+
switch (name) {
|
|
93
|
+
case 'value': this._syncValue(); break;
|
|
94
|
+
case 'options': this._build(); break;
|
|
95
|
+
case 'full': this._applyFull(); break;
|
|
96
|
+
case 'label': this._applyLabel(); break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
resetValue() { this.value = this._initialValue; }
|
|
101
|
+
restoreValue(state) { if (typeof state === 'string') this.value = state; }
|
|
102
|
+
|
|
103
|
+
get value() { return this.getAttribute('value') ?? ''; }
|
|
104
|
+
set value(v) {
|
|
105
|
+
if (v == null) this.removeAttribute('value');
|
|
106
|
+
else this.setAttribute('value', String(v));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get options() { return parseList(this.getAttribute('options')); }
|
|
110
|
+
set options(v) { this.setAttribute('options', typeof v === 'string' ? v : JSON.stringify(v ?? [])); }
|
|
111
|
+
|
|
112
|
+
get full() { return this.getBoolAttr('full'); }
|
|
113
|
+
set full(v) { this.setBoolAttr('full', v); }
|
|
114
|
+
|
|
115
|
+
get label() { return this.getAttribute('label') || ''; }
|
|
116
|
+
set label(v) {
|
|
117
|
+
if (v) this.setAttribute('label', v);
|
|
118
|
+
else this.removeAttribute('label');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
customElements.define('glk-segmented', GlkSegmented);
|
|
123
|
+
|
|
124
|
+
export { GlkSegmented };
|