rizzo-css 0.0.2 → 0.0.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # rizzo-css
2
2
 
3
- A modern CSS design system with semantic theming, 14 built-in themes, and accessible components (BEM). Framework-agnostic: use with Astro, Svelte, React, Vue, or plain HTML.
3
+ A modern CSS design system with semantic theming, 14 built-in themes, and accessible components (BEM). **The same CSS and component styles** ship for every option: **Vanilla JS**, Astro, and Svelte. Framework-agnostic: use with any stack or plain HTML.
4
4
 
5
5
  ## Install
6
6
 
@@ -12,7 +12,14 @@ pnpm add rizzo-css
12
12
  yarn add rizzo-css
13
13
  ```
14
14
 
15
- **Quick start (no install):** `npx rizzo-css init` scaffolds a project (prompts for framework and optional Astro/Svelte components). `npx rizzo-css add` copies the CSS into the current project. `npx rizzo-css theme` lists themes.
15
+ **Quick start (no install):** `npx rizzo-css init` scaffolds a project. Choose **Vanilla JS** (yellow in the CLI), **Astro** (orange), or **Svelte** (orange-red). All options get the **same CSS and component styles**. Vanilla JS gets an example page with theme switcher and sample components; Astro/Svelte can optionally add component files. To use the **official Svelte or Astro scaffold** plus Rizzo CSS, create the app with their CLI first, then add our CSS:
16
+
17
+ ```bash
18
+ npm create svelte@latest my-app && cd my-app && npx rizzo-css add
19
+ npm create astro@latest my-app && cd my-app && npx rizzo-css add
20
+ ```
21
+
22
+ `add` auto-detects Svelte/Astro and copies CSS to the right place (`static/css` or `public/css`). `npx rizzo-css theme` lists themes.
16
23
 
17
24
  ## Use
18
25
 
@@ -34,7 +41,7 @@ import 'rizzo-css';
34
41
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rizzo-css@latest" />
35
42
  ```
36
43
 
37
- Use the same class names and HTML structure as in the [component docs](https://rizzo-css.vercel.app/docs/components). For Astro or Svelte, reference components and examples are in the [documentation](https://rizzo-css.vercel.app/docs/getting-started).
44
+ Use the same class names and HTML structure as in the [component docs](https://rizzo-css.vercel.app/docs/components). **Vanilla JS**, Astro, and Svelte all use the same CSS and BEM markup; Astro/Svelte add framework component files for convenience.
38
45
 
39
46
  ## Themes
40
47
 
package/bin/rizzo-css.js CHANGED
@@ -36,6 +36,19 @@ const ASTRO_COMPONENTS = [
36
36
  'Modal', 'Toast', 'Table',
37
37
  ];
38
38
 
39
+ // ANSI colors for CLI (framework logo colors)
40
+ const C = {
41
+ reset: '\u001b[0m',
42
+ dim: '\u001b[90m',
43
+ cyan: '\u001b[36m',
44
+ vanilla: '\u001b[38;5;226m', // Vanilla JS yellow
45
+ astro: '\u001b[38;5;208m', // Astro orange #ff5d01
46
+ svelte: '\u001b[38;5;202m', // Svelte orange #ff3e00
47
+ };
48
+
49
+ const CIRCLE_EMPTY = '\u25CB '; // ○
50
+ const CIRCLE_FILLED = '\u25CF '; // ●
51
+
39
52
  // Resolve path to this package (works when run via npx or from repo)
40
53
  function getPackageRoot() {
41
54
  return dirname(require.resolve('../package.json'));
@@ -55,6 +68,189 @@ function question(prompt) {
55
68
  });
56
69
  }
57
70
 
71
+ /** Format label with optional ANSI color (item.color). */
72
+ function formatLabel(item) {
73
+ const text = item.label || item.value;
74
+ return item.color ? item.color + text + C.reset : text;
75
+ }
76
+
77
+ /** Single-select menu with circles. options: array of { value, label, color? }. Returns selected value. */
78
+ function selectMenu(options, title) {
79
+ const items = options.map((o) => (typeof o === 'string' ? { value: o, label: o } : o));
80
+ const isTty = process.stdin.isTTY && process.stdout.isTTY;
81
+
82
+ if (!isTty) {
83
+ console.log('\n' + (title || 'Choose one') + ':');
84
+ items.forEach((item, i) => console.log(' ' + (i + 1) + '. ' + (item.label || item.value)));
85
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
86
+ return new Promise((resolve) => {
87
+ rl.question('\nEnter number [1]: ', (answer) => {
88
+ rl.close();
89
+ const n = parseInt((answer || '1').trim(), 10);
90
+ const idx = n >= 1 && n <= items.length ? n - 1 : 0;
91
+ resolve(items[idx].value);
92
+ });
93
+ });
94
+ }
95
+
96
+ return new Promise((resolve) => {
97
+ let index = 0;
98
+ const lineCount = (title ? 1 : 0) + items.length + 1;
99
+
100
+ const render = (first) => {
101
+ const lines = (title ? [title] : []).concat(
102
+ items.map((item, i) => {
103
+ const circle = i === index ? CIRCLE_FILLED : CIRCLE_EMPTY;
104
+ const prefix = i === index ? C.cyan + '>' + C.reset + ' ' : ' ';
105
+ return prefix + circle + formatLabel(item);
106
+ })
107
+ );
108
+ if (!first) {
109
+ process.stdout.write('\u001b[' + lineCount + 'A');
110
+ }
111
+ process.stdout.write('\u001b[?25l');
112
+ process.stdout.write(lines.join('\n') + '\n\n');
113
+ process.stdout.write('\u001b[?25h');
114
+ };
115
+
116
+ process.stdin.setRawMode(true);
117
+ process.stdin.resume();
118
+ process.stdin.setEncoding('utf8');
119
+
120
+ render(true);
121
+
122
+ let buf = '';
123
+ const onData = (ch) => {
124
+ if (ch === '\u0003') {
125
+ process.stdin.setRawMode(false);
126
+ process.stdin.removeListener('data', onData);
127
+ process.stdout.write('\n');
128
+ process.exit(130);
129
+ }
130
+ if (ch === '\r' || ch === '\n') {
131
+ process.stdin.setRawMode(false);
132
+ process.stdin.removeListener('data', onData);
133
+ process.stdin.pause();
134
+ process.stdout.write('\n');
135
+ resolve(items[index].value);
136
+ return;
137
+ }
138
+ buf += ch;
139
+ const isUp = buf === '\u001b[A' || buf === '\u001bOA' || (buf.length >= 2 && buf.endsWith('A') && buf.startsWith('\u001b'));
140
+ const isDown = buf === '\u001b[B' || buf === '\u001bOB' || (buf.length >= 2 && buf.endsWith('B') && buf.startsWith('\u001b'));
141
+ if (isUp) {
142
+ buf = '';
143
+ index = index <= 0 ? items.length - 1 : index - 1;
144
+ render(false);
145
+ } else if (isDown) {
146
+ buf = '';
147
+ index = index >= items.length - 1 ? 0 : index + 1;
148
+ render(false);
149
+ } else if (buf.length > 12 || (buf.length === 1 && ch !== '\u001b')) {
150
+ buf = '';
151
+ }
152
+ };
153
+ process.stdin.on('data', onData);
154
+ });
155
+ }
156
+
157
+ /** Multi-select menu: circles ○/●, Space toggles, Enter confirms. Returns array of selected values. */
158
+ function multiSelectMenu(options, title) {
159
+ const items = options.map((o) => (typeof o === 'string' ? { value: o, label: o } : o));
160
+ const isTty = process.stdin.isTTY && process.stdout.isTTY;
161
+
162
+ if (!isTty) {
163
+ console.log('\n' + (title || 'Choose (space to toggle, enter when done') + ':');
164
+ items.forEach((item, i) => console.log(' ' + (i + 1) + '. ' + (item.label || item.value)));
165
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
166
+ return new Promise((resolve) => {
167
+ rl.question('\nEnter numbers to include (e.g. 1 3 5 or all): ', (answer) => {
168
+ rl.close();
169
+ const s = (answer || '').trim().toLowerCase();
170
+ if (s === 'all' || s === 'a') {
171
+ resolve(items.map((i) => i.value));
172
+ return;
173
+ }
174
+ const parts = s.split(/[\s,]+/).filter(Boolean);
175
+ const indices = new Set();
176
+ for (const p of parts) {
177
+ const n = parseInt(p, 10);
178
+ if (n >= 1 && n <= items.length) indices.add(n - 1);
179
+ }
180
+ resolve(Array.from(indices).sort((a, b) => a - b).map((i) => items[i].value));
181
+ });
182
+ });
183
+ }
184
+
185
+ return new Promise((resolve) => {
186
+ let index = 0;
187
+ const selected = new Set();
188
+ const lineCount = (title ? 1 : 0) + items.length + 1;
189
+
190
+ const render = (first) => {
191
+ const lines = (title ? [title] : []).concat(
192
+ items.map((item, i) => {
193
+ const circle = selected.has(i) ? CIRCLE_FILLED : CIRCLE_EMPTY;
194
+ const prefix = i === index ? C.cyan + '>' + C.reset + ' ' : ' ';
195
+ return prefix + circle + formatLabel(item);
196
+ })
197
+ );
198
+ if (!first) {
199
+ process.stdout.write('\u001b[' + lineCount + 'A');
200
+ }
201
+ process.stdout.write('\u001b[?25l');
202
+ process.stdout.write(lines.join('\n') + '\n\n');
203
+ process.stdout.write('\u001b[?25h');
204
+ };
205
+
206
+ process.stdin.setRawMode(true);
207
+ process.stdin.resume();
208
+ process.stdin.setEncoding('utf8');
209
+
210
+ render(true);
211
+
212
+ let buf = '';
213
+ const onData = (ch) => {
214
+ if (ch === '\u0003') {
215
+ process.stdin.setRawMode(false);
216
+ process.stdin.removeListener('data', onData);
217
+ process.stdout.write('\n');
218
+ process.exit(130);
219
+ }
220
+ if (ch === '\r' || ch === '\n') {
221
+ process.stdin.setRawMode(false);
222
+ process.stdin.removeListener('data', onData);
223
+ process.stdin.pause();
224
+ process.stdout.write('\n');
225
+ resolve(Array.from(selected).sort((a, b) => a - b).map((i) => items[i].value));
226
+ return;
227
+ }
228
+ if (ch === ' ') {
229
+ buf = '';
230
+ if (selected.has(index)) selected.delete(index);
231
+ else selected.add(index);
232
+ render(false);
233
+ return;
234
+ }
235
+ buf += ch;
236
+ const isUp = buf === '\u001b[A' || buf === '\u001bOA' || (buf.length >= 2 && buf.endsWith('A') && buf.startsWith('\u001b'));
237
+ const isDown = buf === '\u001b[B' || buf === '\u001bOB' || (buf.length >= 2 && buf.endsWith('B') && buf.startsWith('\u001b'));
238
+ if (isUp) {
239
+ buf = '';
240
+ index = index <= 0 ? items.length - 1 : index - 1;
241
+ render(false);
242
+ } else if (isDown) {
243
+ buf = '';
244
+ index = index >= items.length - 1 ? 0 : index + 1;
245
+ render(false);
246
+ } else if (buf.length > 12 || (buf.length === 1 && ch !== '\u001b')) {
247
+ buf = '';
248
+ }
249
+ };
250
+ process.stdin.on('data', onData);
251
+ });
252
+ }
253
+
58
254
  function printHelp() {
59
255
  console.log(`
60
256
  rizzo-css CLI — Add Rizzo CSS to your project
@@ -63,15 +259,23 @@ Usage:
63
259
  npx rizzo-css <command> [options]
64
260
 
65
261
  Commands:
66
- init Scaffold a new project (prompts: name, framework, theme; Astro/Svelte: optional component picker)
67
- add Copy Rizzo CSS into the current project
68
- theme List available themes
262
+ init Scaffold a minimal project (menus: location, framework, themes, components)
263
+ add Copy Rizzo CSS into the current project (auto-detects Svelte/Astro)
264
+ theme List all available themes (use in init or set data-theme on <html>)
69
265
  help Show this help
70
266
 
267
+ Use framework CLI first, then add Rizzo CSS:
268
+ npm create svelte@latest my-app
269
+ cd my-app && npx rizzo-css add
270
+
271
+ npm create astro@latest my-app
272
+ cd my-app && npx rizzo-css add
273
+
71
274
  Examples:
72
275
  npx rizzo-css init
73
276
  npx rizzo-css add
74
277
  npx rizzo-css add --path public/css
278
+ npx rizzo-css add --framework svelte
75
279
  npx rizzo-css theme
76
280
 
77
281
  Docs: https://rizzo-css.vercel.app
@@ -79,16 +283,44 @@ Docs: https://rizzo-css.vercel.app
79
283
  }
80
284
 
81
285
  function cmdTheme() {
82
- console.log('\nAvailable themes (set data-theme on <html>):\n');
83
- THEMES.forEach((t) => console.log(' ' + t));
84
- console.log('\nExample: <html lang="en" data-theme="github-dark-classic">\n');
286
+ process.stdout.write('\nAvailable themes (set data-theme on <html>):\n\n');
287
+ THEMES.forEach((t) => process.stdout.write(' ' + t + '\n'));
288
+ process.stdout.write('\nExample: <html lang="en" data-theme="github-dark-classic">\n\n');
289
+ }
290
+
291
+ /** Detect framework from cwd: "svelte" | "astro" | null. */
292
+ function detectFramework(cwd) {
293
+ if (existsSync(join(cwd, 'svelte.config.js')) || existsSync(join(cwd, 'svelte.config.ts'))) return 'svelte';
294
+ if (existsSync(join(cwd, 'astro.config.mjs')) || existsSync(join(cwd, 'astro.config.mts')) || existsSync(join(cwd, 'astro.config.js'))) return 'astro';
295
+ try {
296
+ const pkg = readFileSync(join(cwd, 'package.json'), 'utf8');
297
+ const json = JSON.parse(pkg);
298
+ const deps = { ...json.dependencies, ...(json.devDependencies || {}) };
299
+ if (deps['@sveltejs/kit'] || deps['svelte']) return 'svelte';
300
+ if (deps['astro']) return 'astro';
301
+ } catch (_) { /* ignore */ }
302
+ return null;
303
+ }
304
+
305
+ /** Default CSS directory and link href for a framework (for add command). */
306
+ function getFrameworkCssPaths(framework) {
307
+ if (framework === 'svelte') return { targetDir: 'static/css', linkHref: '/css/rizzo.min.css' };
308
+ if (framework === 'astro') return { targetDir: 'public/css', linkHref: '/css/rizzo.min.css' };
309
+ return { targetDir: 'css', linkHref: 'css/rizzo.min.css' };
85
310
  }
86
311
 
87
312
  function cmdAdd(argv) {
88
313
  const pathIdx = argv.indexOf('--path');
89
314
  const customPath = pathIdx !== -1 && argv[pathIdx + 1] ? argv[pathIdx + 1] : null;
90
- const targetDir = customPath || 'css';
91
- const targetFile = join(process.cwd(), targetDir, 'rizzo.min.css');
315
+ const frameworkIdx = argv.indexOf('--framework');
316
+ const explicitFramework = frameworkIdx !== -1 && argv[frameworkIdx + 1] ? argv[frameworkIdx + 1].toLowerCase() : null;
317
+ const cwd = process.cwd();
318
+ const framework = explicitFramework && FRAMEWORKS.includes(explicitFramework)
319
+ ? explicitFramework
320
+ : (explicitFramework === null ? detectFramework(cwd) : null);
321
+ const paths = getFrameworkCssPaths(framework);
322
+ const targetDir = customPath || paths.targetDir;
323
+ const targetFile = join(cwd, targetDir, 'rizzo.min.css');
92
324
  const cssSource = getCssPath();
93
325
 
94
326
  if (!existsSync(cssSource)) {
@@ -96,26 +328,27 @@ function cmdAdd(argv) {
96
328
  process.exit(1);
97
329
  }
98
330
 
99
- mkdirSync(join(process.cwd(), targetDir), { recursive: true });
331
+ mkdirSync(join(cwd, targetDir), { recursive: true });
100
332
  copyFileSync(cssSource, targetFile);
101
- const linkPath = targetDir + '/rizzo.min.css';
333
+ const linkHref = customPath ? customPath + '/rizzo.min.css' : paths.linkHref;
102
334
  console.log('\n✓ Rizzo CSS copied to ' + targetFile);
103
- console.log('\nAdd to your HTML or layout:\n');
104
- console.log(' <link rel="stylesheet" href="' + linkPath + '" />');
105
- console.log('\nSet a theme on <html>: data-theme="github-dark-classic" (see: npx rizzo-css theme)\n');
106
- }
107
-
108
- function parseComponentSelection(input, componentList, maxNum) {
109
- const s = (input || '').trim().toLowerCase();
110
- if (s === 'none' || s === 'n') return [];
111
- if (s === 'all' || s === 'a') return componentList.slice();
112
- const parts = s.split(/[\s,]+/).filter(Boolean);
113
- const indices = new Set();
114
- for (const p of parts) {
115
- const n = parseInt(p, 10);
116
- if (n >= 1 && n <= maxNum) indices.add(n - 1);
335
+ if (framework === 'svelte') {
336
+ console.log('\nDetected Svelte/SvelteKit. Add to your root layout (e.g. src/app.html):\n');
337
+ console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
338
+ console.log('\nSet a theme on <html>: data-theme="github-dark-classic" (see: npx rizzo-css theme)');
339
+ console.log('\nTo add Rizzo Svelte components later: copy from this package\'s scaffold or run npx rizzo-css init and pick Svelte + components in an empty folder, then copy the generated files.\n');
340
+ } else if (framework === 'astro') {
341
+ console.log('\nDetected Astro. Add to your layout (e.g. src/layouts/Layout.astro):\n');
342
+ console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
343
+ console.log('\nSet a theme on <html>: data-theme="github-dark-classic" (see: npx rizzo-css theme)\n');
344
+ } else {
345
+ console.log('\nAdd to your HTML or layout:\n');
346
+ console.log(' <link rel="stylesheet" href="' + linkHref + '" />');
347
+ if (framework === 'vanilla') {
348
+ console.log('\nVanilla JS: same CSS and component classes as Astro/Svelte. Use the same BEM markup from the docs.');
349
+ }
350
+ console.log('\nSet a theme on <html>: data-theme="github-dark-classic" (see: npx rizzo-css theme)\n');
117
351
  }
118
- return indices.size === 0 ? [] : Array.from(indices).sort((a, b) => a - b).map((i) => componentList[i]);
119
352
  }
120
353
 
121
354
  function getScaffoldSvelteDir() {
@@ -126,6 +359,10 @@ function getScaffoldAstroDir() {
126
359
  return join(getPackageRoot(), 'scaffold', 'astro');
127
360
  }
128
361
 
362
+ function getScaffoldVanillaIndex() {
363
+ return join(getPackageRoot(), 'scaffold', 'vanilla', 'index.html');
364
+ }
365
+
129
366
  function copyDirRecursive(src, dest) {
130
367
  mkdirSync(dest, { recursive: true });
131
368
  const entries = readdirSync(src, { withFileTypes: true });
@@ -205,23 +442,47 @@ function copyAstroComponents(projectDir, selectedNames) {
205
442
  }
206
443
 
207
444
  async function cmdInit() {
208
- const name = await question('Project name (folder name, or leave blank for current directory): ');
209
- let framework = await question('Framework: vanilla, astro, svelte (default: vanilla): ') || 'vanilla';
210
- framework = framework.toLowerCase();
211
- if (!FRAMEWORKS.includes(framework)) framework = 'vanilla';
212
-
213
- const theme = await question('Theme (default: github-dark-classic, or run "npx rizzo-css theme" for list): ') || 'github-dark-classic';
445
+ const projectChoice = await selectMenu(
446
+ [
447
+ { value: 'cwd', label: 'Current directory' },
448
+ { value: 'name', label: 'Enter project name (new folder)' },
449
+ ],
450
+ '? Project location'
451
+ );
452
+ const name = projectChoice === 'name' ? await question('Project name (folder name): ') : '';
453
+
454
+ const framework = await selectMenu(
455
+ [
456
+ { value: 'vanilla', label: 'Vanilla JS (HTML + CSS + same styles & components)', color: C.vanilla },
457
+ { value: 'astro', label: 'Astro', color: C.astro },
458
+ { value: 'svelte', label: 'Svelte', color: C.svelte },
459
+ ],
460
+ '? Framework (arrows, Enter to select) — all get the same CSS and component styles'
461
+ );
462
+
463
+ const selectedThemes = await multiSelectMenu(
464
+ THEMES.map((t) => ({ value: t, label: t })),
465
+ '? Themes (Space to toggle, Enter to confirm)'
466
+ );
467
+ const themeList = selectedThemes.length > 0 ? selectedThemes : [THEMES[0]];
468
+ const theme = THEMES.includes(themeList[0]) ? themeList[0] : THEMES[0];
214
469
 
215
470
  let selectedComponents = [];
216
471
  const componentList = framework === 'svelte' ? SVELTE_COMPONENTS : framework === 'astro' ? ASTRO_COMPONENTS : [];
217
472
  if (componentList.length > 0) {
218
- const label = framework === 'svelte' ? 'Svelte' : 'Astro';
219
- const include = await question('Include ' + label + ' components? (y/n, default: n): ') || 'n';
220
- if (include.toLowerCase() === 'y' || include.toLowerCase() === 'yes') {
221
- console.log('\nComponents (enter numbers to include, e.g. 1 3 5, or "all" / "none"):');
222
- componentList.forEach((c, i) => console.log(' ' + (i + 1) + '. ' + c));
223
- const choice = await question('\nSelection (e.g. 1 2 3 or all): ');
224
- selectedComponents = parseComponentSelection(choice, componentList, componentList.length);
473
+ const includeLabel = framework === 'svelte' ? 'Svelte' : 'Astro';
474
+ const includeChoice = await selectMenu(
475
+ [
476
+ { value: 'none', label: 'None' },
477
+ { value: 'pick', label: 'Yes, pick ' + includeLabel + ' components' },
478
+ ],
479
+ '? Include ' + includeLabel + ' components?'
480
+ );
481
+ if (includeChoice === 'pick') {
482
+ selectedComponents = await multiSelectMenu(
483
+ componentList.map((c) => ({ value: c, label: c })),
484
+ '? Components (Space to toggle, Enter to confirm)'
485
+ );
225
486
  }
226
487
  }
227
488
 
@@ -239,8 +500,22 @@ async function cmdInit() {
239
500
  copyFileSync(cssSource, cssTarget);
240
501
 
241
502
  const linkHref = framework === 'astro' ? '/css/rizzo.min.css' : 'css/rizzo.min.css';
242
- const indexHtml = `<!DOCTYPE html>
243
- <html lang="en" data-theme="${theme}">
503
+ const themeComment = themeList.length > 0
504
+ ? '\n <!-- Selected themes: ' + themeList.join(', ') + ' -->'
505
+ : '';
506
+ const indexPath = join(projectDir, 'index.html');
507
+ const vanillaScaffoldPath = getScaffoldVanillaIndex();
508
+ if (framework === 'vanilla' && existsSync(vanillaScaffoldPath)) {
509
+ let indexHtml = readFileSync(vanillaScaffoldPath, 'utf8');
510
+ indexHtml = indexHtml
511
+ .replace(/\{\{DATA_THEME\}\}/g, theme)
512
+ .replace(/\{\{THEME_LIST_COMMENT\}\}/g, themeComment)
513
+ .replace(/\{\{TITLE\}\}/g, name || 'App')
514
+ .replace(/\{\{LINK_HREF\}\}/g, linkHref);
515
+ writeFileSync(indexPath, indexHtml, 'utf8');
516
+ } else {
517
+ const indexHtml = `<!DOCTYPE html>
518
+ <html lang="en" data-theme="${theme}">${themeComment}
244
519
  <head>
245
520
  <meta charset="UTF-8" />
246
521
  <meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -253,9 +528,8 @@ async function cmdInit() {
253
528
  </body>
254
529
  </html>
255
530
  `;
256
-
257
- const indexPath = join(projectDir, 'index.html');
258
- writeFileSync(indexPath, indexHtml, 'utf8');
531
+ writeFileSync(indexPath, indexHtml, 'utf8');
532
+ }
259
533
 
260
534
  if (framework === 'svelte' && selectedComponents.length > 0) {
261
535
  copySvelteComponents(projectDir, selectedComponents);
@@ -266,6 +540,13 @@ async function cmdInit() {
266
540
  console.log('\n✓ Project ready at ' + projectDir);
267
541
  console.log(' - ' + cssTarget);
268
542
  console.log(' - ' + indexPath);
543
+ if (framework === 'vanilla') {
544
+ console.log(' - Vanilla JS: same CSS and component styles as Astro/Svelte; index includes theme switcher and sample components.');
545
+ }
546
+ if (framework === 'svelte' || framework === 'astro') {
547
+ const fw = framework === 'svelte' ? 'Svelte' : 'Astro';
548
+ console.log('\nTip: To use the official ' + fw + ' scaffold instead, create a project with their CLI (e.g. npm create ' + framework + '@latest my-app), then run npx rizzo-css add in that folder.');
549
+ }
269
550
  console.log('\nRun a local server (e.g. npx serve .) or open index.html. Docs: https://rizzo-css.vercel.app\n');
270
551
  }
271
552
 
@@ -1,6 +1,4 @@
1
- :root{--primary-color:oklch(45.2% 0.198 250.1deg);--secondary-color:oklch(25.1% 0 0deg);--font-family-sans:system-ui,-apple-system,blinkmacsystemfont,"Segoe UI",roboto,"Helvetica Neue",arial,sans-serif;--font-family-serif:georgia,"Times New Roman",times,serif;--font-family-mono:"SF Mono",monaco,"Cascadia Code","Roboto Mono",consolas,"Courier New",monospace;--font-family:var(--font-family-sans);--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-size-scale:1;--font-size-xs:calc(0.75rem*var(--font-size-scale));--font-size-sm:calc(0.875rem*var(--font-size-scale));--font-size-base:calc(1rem*var(--font-size-scale));--font-size-lg:calc(1.125rem*var(--font-size-scale));--font-size-xl:calc(1.25rem*var(--font-size-scale));--font-size-2xl:calc(1.5rem*var(--font-size-scale));--font-size-3xl:calc(1.875rem*var(--font-size-scale));--font-size-4xl:calc(2.25rem*var(--font-size-scale));--font-size-5xl:calc(3rem*var(--font-size-scale));--font-size-6xl:calc(3.75rem*var(--font-size-scale));--line-height-tight:1.25;--line-height-snug:1.375;--line-height-normal:1.5;--line-height-relaxed:1.625;--line-height-loose:2;--letter-spacing-tighter:-0.05em;--letter-spacing-tight:-0.025em;--letter-spacing-normal:0;--letter-spacing-wide:0.025em;--letter-spacing-wider:0.05em;--letter-spacing-widest:0.1em;--spacing-0:0;--spacing-1:0.25rem;--spacing-2:0.5rem;--spacing-3:0.75rem;--spacing-4:1rem;--spacing-5:1.25rem;--spacing-6:1.5rem;--spacing-8:2rem;--spacing-10:2.5rem;--spacing-12:3rem;--spacing-16:4rem;--spacing-20:5rem;--spacing-24:6rem;--spacing-0-125:0.125rem;--spacing-0-375:0.375rem;--spacing-0-625:0.625rem;--spacing-0-875:0.875rem;--spacing-28:7rem;--spacing-32:8rem;--spacing-36:9rem;--spacing-40:10rem;--spacing-48:12rem;--spacing-56:14rem;--spacing-64:16rem;--spacing-72:18rem;--spacing-80:20rem;--spacing-96:24rem;--spacing-50:12.5rem;--spacing-100:25rem;--spacing-150:37.5rem;--spacing-14:3.5rem;--spacing-15:3.75rem;--spacing-75:18.75rem;--spacing-175:43.75rem;--spacing-70:17.5rem;--spacing-105:26.25rem;--spacing-2500:2500rem;--radius-none:0;--radius-sm:0.125rem;--radius:0.25rem;--radius-md:0.375rem;--radius-lg:0.5rem;--radius-xl:0.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--radius-full:9999px;--radius-circle:50%;--z-base:0;--z-1:1;--z-2:2;--z-3:3;--z-10:10;--z-dropdown:10;--z-dropdown-submenu:11;--z-sticky:50;--z-fixed:100;--z-search-overlay:98;--z-search-panel:99;--z-modal-backdrop:1999;--z-modal:2000;--z-tooltip:3000;--z-toast:4000;--z-settings:10000;--z-navbar:5000;--z-navbar-mobile-menu-open:5100;--z-skip-link:10001;--z-navbar-mobile-menu:101;--z-navbar-search-overlay:98;--z-navbar-search-panel:99;--z-navbar-mobile-search-overlay:101;--z-navbar-mobile-search-panel:102;--transition-fast:150ms;--transition-base:200ms;--transition-slow:300ms;--transition-slower:350ms;--transition-slowest:400ms;--transition-ease-out:300ms ease-out;--transition-ease-in:300ms ease-in;--theme-transition-duration:0.2s;--blur-sm:4px;--blur:8px;--blur-md:12px;--blur-lg:16px;--outline-width:2px;--outline-offset:2px;--container-sm:640px;--container-md:768px;--container-lg:1024px;--container-xl:1280px;--container-2xl:1536px;--container-default:1200px;--vh-70:70vh;--vh-80:80vh;--vh-90:90vh;--touch-target-min:3rem;--max-height-dropdown:600px;--max-height-modal:32rem;--max-height-navbar-submenu:2000px;--ease-in-out-cubic:cubic-bezier(0.4,0,0.2,1);--scale-80:0.8;--scale-95:0.95;--scale-100:1;--scale-110:1.1;--border-width:1px;--border-width-2:2px;--border-width-3:3px;--border-width-4:4px;--border-width-arrow:6px;--border-width-accent:3px;--opacity-0:0;--opacity-50:0.5;--opacity-60:0.6;--opacity-70:0.7;--opacity-80:0.8;--opacity-90:0.9;--opacity-100:1;--background:oklch(100% 0 0deg);--background-alt:oklch(96.9% 0 0deg);--text:oklch(25.1% 0 0deg);--text-dim:oklch(50.2% 0 0deg);--icon:var(--text);--icon-dim:var(--text-dim);--border:oklch(90.2% 0 0deg);--accent:oklch(45.2% 0.198 250.1deg);--accent-hover:oklch(40.2% 0.198 250.1deg);--accent-text:oklch(100% 0 0deg);--accent-text-on-hover:var(--accent-text);--success:oklch(60.2% 0.182 145.1deg);--success-hover:oklch(70% 0.16 145deg);--success-text:oklch(20% 0 0deg);--success-text-on-solid:var(--success-text);--warning:oklch(80.2% 0.152 90.1deg);--warning-hover:oklch(88% 0.12 90deg);--warning-text:oklch(100% 0 0deg);--warning-text-on-solid:oklch(22% 0.02 90deg);--text-on-solid-hover:oklch(22% 0.02 0deg);--error:oklch(55.2% 0.218 25.1deg);--error-hover:oklch(65% 0.18 25deg);--error-text:oklch(100% 0 0deg);--error-text-on-solid:var(--error-text);--info:oklch(60.2% 0.118 210.1deg);--info-hover:oklch(70% 0.1 210deg);--info-text:oklch(20% 0 0deg);--info-text-on-solid:var(--info-text);--selection:oklch(70% 0.15 250deg);--shadow-color:oklch(0% 0 0deg);--shadow-sm:0 1px 2px 0 oklch(from var(--shadow-color) l c h/5%);--shadow:0 1px 3px 0 oklch(from var(--shadow-color) l c h/10%),0 1px 2px -1px oklch(from var(--shadow-color) l c h/10%);--shadow-md:0 4px 6px -1px oklch(from var(--shadow-color) l c h/10%),0 2px 4px -2px oklch(from var(--shadow-color) l c h/6%);--shadow-lg:0 10px 15px -3px oklch(from var(--shadow-color) l c h/10%),0 4px 6px -4px oklch(from var(--shadow-color) l c h/5%);--shadow-xl:0 20px 25px -5px oklch(from var(--shadow-color) l c h/10%),0 8px 10px -6px oklch(from var(--shadow-color) l c h/4%);--overlay:oklch(from var(--shadow-color) l c h/50%);--shadow-inset-sm:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%);--shadow-inset:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%)}*,
2
- *::after,
3
- *::before{box-sizing:border-box}html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;margin:0;padding:0} blockquote,body, dd, dl,
1
+ :root{--primary-color:oklch(45.2% 0.198 250.1deg);--secondary-color:oklch(25.1% 0 0deg);--font-family-sans:system-ui,-apple-system,blinkmacsystemfont,"Segoe UI",roboto,"Helvetica Neue",arial,sans-serif;--font-family-serif:georgia,"Times New Roman",times,serif;--font-family-mono:"SF Mono",monaco,"Cascadia Code","Roboto Mono",consolas,"Courier New",monospace;--font-family:var(--font-family-sans);--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-size-scale:1;--font-size-xs:calc(0.75rem*var(--font-size-scale));--font-size-sm:calc(0.875rem*var(--font-size-scale));--font-size-base:calc(1rem*var(--font-size-scale));--font-size-lg:calc(1.125rem*var(--font-size-scale));--font-size-xl:calc(1.25rem*var(--font-size-scale));--font-size-2xl:calc(1.5rem*var(--font-size-scale));--font-size-3xl:calc(1.875rem*var(--font-size-scale));--font-size-4xl:calc(2.25rem*var(--font-size-scale));--font-size-5xl:calc(3rem*var(--font-size-scale));--font-size-6xl:calc(3.75rem*var(--font-size-scale));--line-height-tight:1.25;--line-height-snug:1.375;--line-height-normal:1.5;--line-height-relaxed:1.625;--line-height-loose:2;--letter-spacing-tighter:-0.05em;--letter-spacing-tight:-0.025em;--letter-spacing-normal:0;--letter-spacing-wide:0.025em;--letter-spacing-wider:0.05em;--letter-spacing-widest:0.1em;--spacing-0:0;--spacing-1:0.25rem;--spacing-2:0.5rem;--spacing-3:0.75rem;--spacing-4:1rem;--spacing-5:1.25rem;--spacing-6:1.5rem;--spacing-8:2rem;--spacing-10:2.5rem;--spacing-12:3rem;--spacing-16:4rem;--spacing-20:5rem;--spacing-24:6rem;--spacing-0-125:0.125rem;--spacing-0-375:0.375rem;--spacing-0-625:0.625rem;--spacing-0-875:0.875rem;--spacing-28:7rem;--spacing-32:8rem;--spacing-36:9rem;--spacing-40:10rem;--spacing-48:12rem;--spacing-56:14rem;--spacing-64:16rem;--spacing-72:18rem;--spacing-80:20rem;--spacing-96:24rem;--spacing-50:12.5rem;--spacing-100:25rem;--spacing-150:37.5rem;--spacing-14:3.5rem;--spacing-15:3.75rem;--spacing-75:18.75rem;--spacing-175:43.75rem;--spacing-70:17.5rem;--spacing-105:26.25rem;--spacing-2500:2500rem;--radius-none:0;--radius-sm:0.125rem;--radius:0.25rem;--radius-md:0.375rem;--radius-lg:0.5rem;--radius-xl:0.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--radius-full:9999px;--radius-circle:50%;--z-base:0;--z-1:1;--z-2:2;--z-3:3;--z-10:10;--z-dropdown:10;--z-dropdown-submenu:11;--z-sticky:50;--z-fixed:100;--z-search-overlay:98;--z-search-panel:99;--z-modal-backdrop:1999;--z-modal:2000;--z-tooltip:3000;--z-toast:4000;--z-settings:10000;--z-navbar:5000;--z-navbar-mobile-menu-open:5100;--z-skip-link:10001;--z-navbar-mobile-menu:101;--z-navbar-search-overlay:98;--z-navbar-search-panel:99;--z-navbar-mobile-search-overlay:101;--z-navbar-mobile-search-panel:102;--transition-fast:150ms;--transition-base:200ms;--transition-slow:300ms;--transition-slower:350ms;--transition-slowest:400ms;--transition-ease-out:300ms ease-out;--transition-ease-in:300ms ease-in;--theme-transition-duration:0.2s;--blur-sm:4px;--blur:8px;--blur-md:12px;--blur-lg:16px;--outline-width:2px;--outline-offset:2px;--container-sm:640px;--container-md:768px;--container-lg:1024px;--container-xl:1280px;--container-2xl:1536px;--container-default:1200px;--vh-70:70vh;--vh-80:80vh;--vh-90:90vh;--touch-target-min:3rem;--max-height-dropdown:600px;--max-height-modal:32rem;--max-height-navbar-submenu:2000px;--ease-in-out-cubic:cubic-bezier(0.4,0,0.2,1);--scale-80:0.8;--scale-95:0.95;--scale-100:1;--scale-110:1.1;--border-width:1px;--border-width-2:2px;--border-width-3:3px;--border-width-4:4px;--border-width-arrow:6px;--border-width-accent:3px;--opacity-0:0;--opacity-50:0.5;--opacity-60:0.6;--opacity-70:0.7;--opacity-80:0.8;--opacity-90:0.9;--opacity-100:1;--background:oklch(100% 0 0deg);--background-alt:oklch(96.9% 0 0deg);--text:oklch(25.1% 0 0deg);--text-dim:oklch(50.2% 0 0deg);--icon:var(--text);--icon-dim:var(--text-dim);--border:oklch(90.2% 0 0deg);--accent:oklch(45.2% 0.198 250.1deg);--accent-hover:oklch(40.2% 0.198 250.1deg);--accent-text:oklch(100% 0 0deg);--accent-text-on-hover:var(--accent-text);--success:oklch(60.2% 0.182 145.1deg);--success-hover:oklch(70% 0.16 145deg);--success-text:oklch(20% 0 0deg);--success-text-on-solid:var(--success-text);--warning:oklch(80.2% 0.152 90.1deg);--warning-hover:oklch(88% 0.12 90deg);--warning-text:oklch(100% 0 0deg);--warning-text-on-solid:oklch(22% 0.02 90deg);--text-on-solid-hover:oklch(22% 0.02 0deg);--error:oklch(55.2% 0.218 25.1deg);--error-hover:oklch(65% 0.18 25deg);--error-text:oklch(100% 0 0deg);--error-text-on-solid:var(--error-text);--info:oklch(60.2% 0.118 210.1deg);--info-hover:oklch(70% 0.1 210deg);--info-text:oklch(20% 0 0deg);--info-text-on-solid:var(--info-text);--selection:oklch(70% 0.15 250deg);--shadow-color:oklch(0% 0 0deg);--shadow-sm:0 1px 2px 0 oklch(from var(--shadow-color) l c h/5%);--shadow:0 1px 3px 0 oklch(from var(--shadow-color) l c h/10%),0 1px 2px -1px oklch(from var(--shadow-color) l c h/10%);--shadow-md:0 4px 6px -1px oklch(from var(--shadow-color) l c h/10%),0 2px 4px -2px oklch(from var(--shadow-color) l c h/6%);--shadow-lg:0 10px 15px -3px oklch(from var(--shadow-color) l c h/10%),0 4px 6px -4px oklch(from var(--shadow-color) l c h/5%);--shadow-xl:0 20px 25px -5px oklch(from var(--shadow-color) l c h/10%),0 8px 10px -6px oklch(from var(--shadow-color) l c h/4%);--overlay:oklch(from var(--shadow-color) l c h/50%);--shadow-inset-sm:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%);--shadow-inset:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%)}*, *::after, *::before{box-sizing:border-box;margin:0;padding:0}html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;margin:0;padding:0} blockquote,body, dd, dl,
4
2
  figure, h1, h2, h3, h4, h5, h6, p{margin-block-end:0}
5
3
  ol[role="list"],ul[role="list"]{list-style:none}body{line-height:1.5;margin:0;min-height:100vh;padding:0}
6
4
  button,h1, h2, h3, h4, h5, h6, input, label{line-height:1.1}h1, h2, h3, h4, h5, h6{text-wrap:balance}a:not([class]){-webkit-text-decoration-skip:ink;color:currentcolor;text-decoration-skip-ink:auto}img,
@@ -97,7 +95,7 @@ div.navbar__link{background:none;border:none;cursor:pointer;font:inherit;text-al
97
95
  .navbar__item--has-dropdown:hover .navbar__submenu,.navbar__item--has-dropdown[aria-expanded="true"] .navbar__submenu{opacity:1;transform:translateY(0);visibility:visible}.navbar__sublink{color:var(--text);display:block;font-size:var(--font-size-sm);font-weight:var(--font-weight-normal);padding:var(--spacing-0-625) var(--spacing-4);text-decoration:none;transition:background-color var(--transition-base),color var(--transition-base)}.navbar__sublink:hover,.navbar__sublink[aria-current="page"]{background-color:var(--background);color:var(--accent)}.navbar__sublink[aria-current="page"]{font-weight:var(--font-weight-medium)}.navbar__sublink:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:calc(var(--outline-offset)*-1)}.navbar__link:hover{color:var(--accent)}.navbar__link:focus-visible{border-radius:var(--radius);outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.navbar__link::after{background-color:var(--accent);bottom:0;content:"";height:var(--spacing-0-125);left:0;position:absolute;transition:width var(--transition-slow);width:0}
98
96
  .navbar__link:focus-visible::after,.navbar__link:hover::after,
99
97
  .navbar__link[aria-current="page"]::after{width:100%}.navbar__link[aria-current="page"]{color:var(--accent)}.navbar__actions,.navbar__actions .search{display:none}.navbar__settings-btn{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;font-family:var(--font-family);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);gap:var(--spacing-2);min-width:-moz-fit-content;min-width:fit-content;padding:var(--spacing-2) var(--spacing-6);transition:background-color var(--transition-base),border-color var(--transition-base)}.navbar__settings-btn:hover{background-color:var(--background);border-color:var(--accent);color:var(--text)}.navbar__settings-btn:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.navbar__settings-icon{flex-shrink:0;height:var(--spacing-5);width:var(--spacing-5)}.navbar__settings-label{font-size:var(--font-size-sm)}@media (width <= 1023px){.navbar{overflow-x:clip}.navbar__container{gap:var(--spacing-2);min-width:0;padding-left:var(--spacing-3);padding-right:var(--spacing-3)}.navbar__brand{flex-shrink:1;min-width:0;order:0;overflow:hidden}.navbar__brand-link{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.navbar__toggle{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);display:flex;margin-left:var(--spacing-2);margin-right:0;min-height:var(--touch-target-min);min-width:var(--touch-target-min);order:1;padding:var(--spacing-2) var(--spacing-3);transition:background-color var(--transition-base),border-color var(--transition-base)}.navbar__toggle:hover{background-color:var(--background);border-color:var(--accent)}.navbar__toggle-icon{height:var(--spacing-5)!important;width:var(--spacing-5)!important}.navbar__toggle-icon span{border-radius:var(--radius-sm);height:calc(var(--spacing-0-125)*1.5)!important}.navbar__menu{align-items:stretch;background-color:var(--background-alt);border-top:none;box-shadow:var(--shadow-md);box-sizing:border-box;flex-direction:column;gap:var(--spacing-0);left:0;margin:0;max-height:0;max-width:100%;opacity:0;overflow:hidden;padding:0;pointer-events:none;position:absolute;right:0;top:100%;transition:max-height var(--transition-slowest) var(--ease-in-out-cubic),opacity var(--transition-ease-out),padding var(--transition-slowest) var(--ease-in-out-cubic);width:100%;z-index:var(--z-navbar-mobile-menu)}.navbar__menu--open{border-bottom:none!important;left:0;max-height:var(--vh-80);opacity:1;overflow-x:hidden;overflow-y:auto;padding:var(--spacing-4) 0;pointer-events:auto;position:fixed;right:0;scroll-behavior:auto;top:var(--spacing-16);transform:translateZ(0);transition:max-height var(--transition-slowest) var(--ease-in-out-cubic),opacity var(--transition-ease-in),padding var(--transition-slowest) var(--ease-in-out-cubic);width:100%;will-change:scroll-position;z-index:var(--z-navbar-mobile-menu-open)}.navbar__menu .navbar__item{contain:layout;margin:0;max-width:100%;padding:0;width:100%}.navbar__menu:not(.navbar__menu--open){padding:0;transition:max-height var(--transition-slowest) var(--ease-in-out-cubic),opacity var(--transition-ease-out),padding var(--transition-slowest) var(--ease-in-out-cubic)}.navbar__menu--open .navbar__item:last-of-type .navbar__link{border-bottom:none!important}.navbar__item{width:100%}.navbar__link{align-items:center;border-bottom:var(--border-width) solid var(--border);box-sizing:border-box;display:flex;justify-content:space-between;margin:0;max-width:100%;min-height:var(--touch-target-min);min-width:0;overflow-wrap:break-word;padding:var(--spacing-3) var(--spacing-4) var(--spacing-3) var(--spacing-3);transition:background-color var(--transition-base) ease,color var(--transition-base) ease;width:100%}.navbar__link .navbar__dropdown-icon{display:block!important;flex-shrink:0!important;height:var(--spacing-3)!important;margin-left:var(--spacing-2);margin-right:var(--spacing-4);opacity:1!important;transition:transform var(--transition-base) ease-out;visibility:visible!important;width:var(--spacing-3)!important}.navbar__submenu{background-color:var(--background);border:none;border-top:var(--border-width) solid var(--border);box-shadow:none;contain:layout;grid-template-columns:none!important;list-style:none;margin:0!important;max-height:0;max-width:100%!important;opacity:1;overflow:hidden;padding:0!important;position:static;transform:none;transition:max-height .25s cubic-bezier(.4,0,.2,1);visibility:visible;width:100%!important}.navbar__submenu,.navbar__submenu--components .navbar__submenu-components-grid{display:block!important}.navbar__submenu--components .navbar__submenu-column{display:block!important;margin-top:var(--spacing-2);width:100%!important}.navbar__submenu--components .navbar__submenu-column .navbar__sublink{border-bottom:var(--border-width) solid var(--border);min-height:var(--touch-target-min)!important;padding:var(--spacing-3) var(--spacing-5) var(--spacing-3) var(--spacing-10)!important}.navbar__item--has-dropdown[aria-expanded="true"] .navbar__submenu{max-height:var(--max-height-navbar-submenu);overflow:visible;padding:0!important}@media (prefers-reduced-motion:reduce){.navbar__menu,.navbar__menu--open,.navbar__submenu{transition:none}}.navbar__submenu li{padding:0!important}.navbar__sublink,.navbar__submenu li{display:block!important;margin:0!important;max-width:100%!important;width:100%!important}.navbar__sublink{border-bottom:var(--border-width) solid var(--border);box-sizing:border-box!important;min-height:var(--touch-target-min)!important;min-width:0!important;overflow-wrap:break-word!important;padding:var(--spacing-3) var(--spacing-5) var(--spacing-3) var(--spacing-10)!important}.navbar__sublink:last-child{border-bottom:none}.navbar__submenu--themes .navbar__submenu-themes-grid{display:block!important}.navbar__submenu--themes .navbar__submenu-column{display:block!important;margin-top:var(--spacing-2);width:100%!important}.navbar__submenu--themes .navbar__submenu-column-label{border-bottom:var(--border-width) solid var(--border);box-sizing:border-box;display:block;font-weight:var(--font-weight-bold);margin-bottom:var(--spacing-0-625);margin-top:var(--spacing-2);padding-bottom:var(--spacing-0-625);padding-left:var(--spacing-10);padding-right:var(--spacing-5);width:100%}.navbar__submenu--themes .navbar__submenu-column:first-of-type .navbar__submenu-column-label{margin-top:0}.navbar__submenu--themes .navbar__submenu-column .navbar__sublink{border-bottom:var(--border-width) solid var(--border);min-height:var(--touch-target-min)!important;padding:var(--spacing-3) var(--spacing-5) var(--spacing-3) var(--spacing-10)!important}.navbar__submenu--themes .navbar__sublink--with-icon{align-items:center;display:flex!important;gap:var(--spacing-2)}.navbar__submenu--themes .navbar__sublink-icon{color:var(--text-dim);flex-shrink:0}.navbar__submenu--themes .navbar__sublink-text{min-width:0;overflow:hidden;text-overflow:ellipsis}.navbar__item:last-of-type .navbar__link{border-bottom:var(--border-width) solid var(--border)}.navbar__actions-desktop .navbar__settings-btn{align-items:center;display:flex;justify-content:center;min-height:var(--touch-target-min);min-width:var(--touch-target-min);padding:var(--spacing-2) var(--spacing-3);width:auto}.navbar__actions-desktop .navbar__settings-label{border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.navbar__actions-desktop .search__trigger{justify-content:center;min-height:var(--touch-target-min);min-width:var(--touch-target-min);padding:var(--spacing-2) var(--spacing-3);width:auto}
100
- .navbar__actions-desktop .search__kbd,.navbar__actions-desktop .search__trigger-text{border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.navbar__actions-desktop{display:flex;flex-shrink:0;gap:var(--spacing-2);margin-left:auto;margin-right:0;min-width:0;order:2}.search__panel{z-index:var(--z-navbar-mobile-search-panel)}.search__overlay{z-index:var(--z-navbar-mobile-search-overlay)}}.theme-switcher{display:inline-block;position:relative;width:100%}.settings .theme-switcher{width:100%}.settings .theme-switcher__trigger{justify-content:space-between;width:100%}.settings .theme-switcher__menu{left:0;min-width:auto;position:absolute;right:0;top:calc(100% + var(--spacing-2));z-index:var(--z-dropdown)}.theme-switcher__trigger{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;font-family:var(--font-family);font-size:var(--font-size-base);gap:var(--spacing-3);padding:var(--spacing-3) var(--spacing-4);transition:background-color var(--transition-base),border-color var(--transition-base)}.theme-switcher__label-wrapper{align-items:center;display:flex;gap:var(--spacing-2)}.theme-switcher__label-icon{align-items:center;display:flex;flex-shrink:0;height:var(--spacing-5);justify-content:center;width:var(--spacing-5)}.theme-switcher__label-icon svg{height:100%;width:100%}.theme-switcher__trigger:hover{background-color:var(--background);border-color:var(--accent);color:var(--text)}.theme-switcher__trigger:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.theme-switcher__trigger[aria-expanded="true"] .theme-switcher__icon{transform:rotate(180deg)}.theme-switcher__icon{flex-shrink:0;transition:transform var(--transition-base)}.theme-switcher__menu{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);display:flex;flex-direction:row;gap:0;left:0;max-height:var(--spacing-100);min-width:var(--spacing-64);opacity:0;overflow-y:auto;position:absolute;top:calc(100% + var(--spacing-2));transform:translateY(calc(var(--spacing-2)*-1));transition:opacity var(--transition-base),visibility var(--transition-base),transform var(--transition-base);visibility:hidden;z-index:var(--z-dropdown)}.theme-switcher__menu--open{opacity:1;transform:translateY(0);visibility:visible}.theme-switcher__menu-options{flex:1 1 auto;min-width:0;overflow-y:auto}.theme-switcher__preview{background-color:var(--background);border-left:var(--border-width) solid var(--border);display:flex;flex:0 0 auto;flex-direction:column;gap:var(--spacing-2);justify-content:flex-start;min-width:var(--spacing-32);opacity:0;padding:var(--spacing-4);pointer-events:none;transition:opacity var(--transition-fast);width:var(--spacing-32)}.theme-switcher__preview[aria-hidden="false"]{opacity:1}.theme-switcher__preview-header{color:var(--preview-accent,var(--text-dim));font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);letter-spacing:.04em;line-height:1.2;margin:0;min-height:1.25em;overflow-wrap:break-word;padding:0;text-transform:uppercase}.theme-switcher__preview-swatch-wrap{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px oklch(0 0 0deg/6%);padding:var(--spacing-1)}.theme-switcher__preview-swatch{background-color:var(--background);border-radius:var(--radius);height:var(--spacing-10);min-height:var(--spacing-10);transition:background-color var(--transition-fast);width:100%}.theme-switcher__preview-accent{background-color:var(--preview-accent,var(--accent));border-radius:var(--radius-full);flex-shrink:0;height:var(--spacing-2);transition:background-color var(--transition-fast);width:100%}@media (width <= 480px){.theme-switcher__preview{display:none}}.framework-switcher{align-items:center;border-bottom:var(--border-width) solid var(--border);display:flex;flex-wrap:wrap;gap:var(--spacing-3);margin-bottom:var(--spacing-6);padding:var(--spacing-3) 0}.framework-switcher__label{color:var(--text-dim);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);letter-spacing:.05em;text-transform:uppercase}.framework-switcher__segmented{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:inset 0 1px 2px oklch(from var(--shadow-color) l c h/8%);display:inline-flex;padding:var(--spacing-0-5)}.framework-switcher__segment{align-items:center;border-radius:var(--radius-md);color:var(--text-dim);display:inline-flex;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);justify-content:center;min-width:var(--spacing-20);padding:var(--spacing-2) var(--spacing-4);text-decoration:none;transition:color var(--transition-fast),background-color var(--transition-fast),box-shadow var(--transition-fast)}.framework-switcher__segment--first{border-radius:var(--radius-md) 0 0 var(--radius-md)}.framework-switcher__segment--last{border-radius:0 var(--radius-md) var(--radius-md) 0}.framework-switcher__segment:only-child{border-radius:var(--radius-md)}.framework-switcher__segment:hover:not(.framework-switcher__segment--current){background-color:oklch(from var(--text) l c h/10%);color:var(--text)}.framework-switcher__segment--current{background-color:var(--accent);box-shadow:var(--shadow-sm);color:var(--accent-text)}.framework-switcher__segment--current:hover{background-color:var(--accent-hover);color:var(--accent-text)}.theme-switcher__group{padding:var(--spacing-3) 0}.theme-switcher__group-label{border-bottom:var(--border-width) solid var(--border);color:var(--text-dim);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);letter-spacing:.05em;margin-bottom:var(--spacing-1);padding:var(--spacing-2) var(--spacing-4);text-transform:uppercase}.theme-switcher__option{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:none;color:var(--text);cursor:pointer;display:flex;font:inherit;font-family:var(--font-family);font-size:var(--font-size-base);gap:var(--spacing-3);padding:var(--spacing-2) var(--spacing-4);position:relative;text-align:left;transition:background-color var(--transition-fast),color var(--transition-fast);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}
98
+ .navbar__actions-desktop .search__kbd,.navbar__actions-desktop .search__trigger-text{border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.navbar__actions-desktop{display:flex;flex-shrink:0;gap:var(--spacing-2);margin-left:auto;margin-right:0;min-width:0;order:2}.search__panel{z-index:var(--z-navbar-mobile-search-panel)}.search__overlay{z-index:var(--z-navbar-mobile-search-overlay)}}.theme-switcher{display:inline-block;position:relative;width:100%}.settings .theme-switcher{width:100%}.settings .theme-switcher__trigger{justify-content:space-between;width:100%}.settings .theme-switcher__menu{left:0;min-width:auto;position:absolute;right:0;top:calc(100% + var(--spacing-2));z-index:var(--z-dropdown)}.theme-switcher__trigger{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;font-family:var(--font-family);font-size:var(--font-size-base);gap:var(--spacing-3);padding:var(--spacing-3) var(--spacing-4);transition:background-color var(--transition-base),border-color var(--transition-base)}.theme-switcher__label-wrapper{align-items:center;display:flex;gap:var(--spacing-2)}.theme-switcher__label-icon{align-items:center;display:flex;flex-shrink:0;height:var(--spacing-5);justify-content:center;width:var(--spacing-5)}.theme-switcher__label-icon svg{height:100%;width:100%}.theme-switcher__trigger:hover{background-color:var(--background);border-color:var(--accent);color:var(--text)}.theme-switcher__trigger:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.theme-switcher__trigger[aria-expanded="true"] .theme-switcher__icon{transform:rotate(180deg)}.theme-switcher__icon{flex-shrink:0;transition:transform var(--transition-base)}.theme-switcher__menu{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);display:flex;flex-direction:row;gap:0;left:0;max-height:var(--spacing-100);min-width:var(--spacing-64);opacity:0;overflow-y:auto;position:absolute;top:calc(100% + var(--spacing-2));transform:translateY(calc(var(--spacing-2)*-1));transition:opacity var(--transition-base),visibility var(--transition-base),transform var(--transition-base);visibility:hidden;z-index:var(--z-dropdown)}.theme-switcher__menu--open{opacity:1;transform:translateY(0);visibility:visible}.theme-switcher__menu-options{flex:1 1 auto;min-width:0;overflow-y:auto}.theme-switcher__preview{background-color:var(--background);border-left:var(--border-width) solid var(--border);display:flex;flex:0 0 auto;flex-direction:column;gap:var(--spacing-2);justify-content:flex-start;min-width:var(--spacing-32);opacity:0;padding:var(--spacing-4);pointer-events:none;transition:opacity var(--transition-fast);width:var(--spacing-32)}.theme-switcher__preview[aria-hidden="false"]{opacity:1}.theme-switcher__preview-header{color:var(--preview-accent,var(--text-dim));font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);letter-spacing:.04em;line-height:1.2;margin:0;min-height:1.25em;overflow-wrap:break-word;padding:0;text-transform:uppercase}.theme-switcher__preview-swatch-wrap{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px oklch(0 0 0deg/6%);padding:var(--spacing-1)}.theme-switcher__preview-swatch{background-color:var(--background);border-radius:var(--radius);height:var(--spacing-10);min-height:var(--spacing-10);transition:background-color var(--transition-fast);width:100%}.theme-switcher__preview-accent{background-color:var(--preview-accent,var(--accent));border-radius:var(--radius-full);flex-shrink:0;height:var(--spacing-2);transition:background-color var(--transition-fast);width:100%}@media (width <= 480px){.theme-switcher__preview{display:none}}.framework-switcher{align-items:center;border-bottom:var(--border-width) solid var(--border);display:flex;flex-wrap:wrap;gap:var(--spacing-3);margin-bottom:var(--spacing-6);padding:var(--spacing-3) 0}.framework-switcher__label{color:var(--text-dim);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);letter-spacing:.05em;text-transform:uppercase}.framework-switcher__segmented{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:inset 0 1px 2px oklch(from var(--shadow-color) l c h/8%);display:inline-flex;padding:var(--spacing-0-5)}.framework-switcher__segment{align-items:center;border-radius:var(--radius-md);color:var(--text-dim);display:inline-flex;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);gap:var(--spacing-2);justify-content:center;min-width:var(--spacing-20);padding:var(--spacing-2) var(--spacing-4);text-decoration:none;transition:color var(--transition-fast),background-color var(--transition-fast),box-shadow var(--transition-fast)}.framework-switcher__icon{display:block;flex-shrink:0}.framework-switcher__segment--current .framework-switcher__icon{opacity:.95}.framework-switcher__segment--first{border-radius:var(--radius-md) 0 0 var(--radius-md)}.framework-switcher__segment--last{border-radius:0 var(--radius-md) var(--radius-md) 0}.framework-switcher__segment:only-child{border-radius:var(--radius-md)}.framework-switcher__segment:hover:not(.framework-switcher__segment--current){background-color:oklch(from var(--text) l c h/10%);color:var(--text)}.framework-switcher__segment--current{background-color:var(--accent);box-shadow:var(--shadow-sm);color:var(--accent-text)}.framework-switcher__segment--current:hover{background-color:var(--accent-hover);color:var(--accent-text)}.theme-switcher__group{padding:var(--spacing-3) 0}.theme-switcher__group-label{border-bottom:var(--border-width) solid var(--border);color:var(--text-dim);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);letter-spacing:.05em;margin-bottom:var(--spacing-1);padding:var(--spacing-2) var(--spacing-4);text-transform:uppercase}.theme-switcher__option{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:none;color:var(--text);cursor:pointer;display:flex;font:inherit;font-family:var(--font-family);font-size:var(--font-size-base);gap:var(--spacing-3);padding:var(--spacing-2) var(--spacing-4);position:relative;text-align:left;transition:background-color var(--transition-fast),color var(--transition-fast);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}
101
99
  .theme-switcher__option:focus-visible,.theme-switcher__option:hover{background-color:var(--background);color:var(--text);outline:none}.theme-switcher__option:focus-visible{box-shadow:inset 0 0 0 var(--outline-width) var(--accent)}.theme-switcher__option-icon{flex-shrink:0;height:var(--spacing-5);width:var(--spacing-5)}.theme-switcher__option--active,
102
100
  .theme-switcher__option--active:focus-visible,
103
101
  .theme-switcher__option--active:hover{background-color:var(--theme-bg,var(--background));border-left:var(--border-width-accent) solid var(--accent);border-radius:var(--radius);color:var(--text);font-weight:var(--font-weight-medium);padding-left:calc(var(--spacing-4) - var(--border-width-accent))}.theme-switcher__option--active:focus-visible{box-shadow:inset 0 0 0 var(--outline-width) var(--accent)}@media (width <= 640px){.theme-switcher__menu{left:0;right:auto}}.settings{inset:0;pointer-events:none;position:fixed;z-index:var(--z-settings)}.settings[aria-hidden="true"]{display:none}.settings__overlay{backdrop-filter:blur(var(--blur-sm));background-color:var(--overlay);inset:0;opacity:0;pointer-events:all;position:absolute;transition:opacity var(--transition-ease-out)}.settings[aria-hidden="false"] .settings__overlay[aria-hidden="false"],.settings__overlay[aria-hidden="false"]{opacity:1}.settings__panel{background-color:var(--background-alt);border-left:var(--border-width) solid var(--border);box-shadow:calc(var(--spacing-1)*-1) 0 var(--spacing-3) calc(var(--spacing-0-125)*-1) oklch(from var(--shadow-color) l c h/15%);display:flex;flex-direction:column;height:100%;max-width:var(--spacing-105);overflow-y:auto;pointer-events:all;position:absolute;right:0;top:0;transform:translateX(100%);transition:transform var(--transition-ease-out);width:100%}.settings__panel[data-open="true"]{transform:translateX(0)}.settings[aria-hidden="false"] .settings__panel:not([data-open]){transform:translateX(100%)}@media (prefers-reduced-motion:reduce){.settings__overlay,.settings__panel{transition:none}}.settings__header{align-items:center;background-color:var(--background-alt);border-bottom:var(--border-width) solid var(--border);display:flex;justify-content:space-between;padding:var(--spacing-6);position:sticky;top:0;z-index:var(--z-dropdown)}.settings__title{color:var(--text);font-size:var(--font-size-xl);font-weight:var(--font-weight-bold);margin:0}.settings__close{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;height:var(--spacing-8);justify-content:center;min-height:var(--touch-target-min);min-width:var(--touch-target-min);padding:0;transition:background-color var(--transition-base),color var(--transition-base),border-color var(--transition-base);width:var(--spacing-8)}.settings__close:hover{background-color:var(--background-alt);border-color:var(--accent);color:var(--accent)}.settings__close:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.settings__content{background-color:var(--background);display:flex;flex:1;flex-direction:column;gap:var(--spacing-8);padding:var(--spacing-6)}.settings__section{display:flex;flex-direction:column;gap:var(--spacing-4)}.settings__section-title{color:var(--text);font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);margin:0 0 var(--spacing-4)}.settings__control{display:flex;flex-direction:column;gap:var(--spacing-3)}.settings__label{align-items:center;color:var(--text);display:flex;font-weight:var(--font-weight-medium);justify-content:space-between;margin-bottom:var(--spacing-3)}.settings__label-text{font-size:var(--font-size-base)}.settings__label-value{color:var(--text-dim);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold)}.settings__slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);cursor:pointer;height:var(--spacing-2);outline:none;width:100%}.settings__slider::-webkit-slider-runnable-track{background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);box-shadow:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%);height:var(--spacing-2);width:100%}.settings__slider::-moz-range-track{background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);box-shadow:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%);height:var(--spacing-2);width:100%}.settings__slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:var(--accent);border:var(--outline-width) solid var(--background);border-radius:var(--radius-circle);box-shadow:0 0 0 var(--spacing-0-125) var(--border);cursor:pointer;height:var(--spacing-5);margin-top:calc(var(--spacing-2)*-1);-webkit-transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);width:var(--spacing-5)}.settings__slider::-webkit-slider-thumb:hover{background-color:var(--accent-hover);transform:scale(1.1)}.settings__slider::-moz-range-thumb{background-color:var(--accent);border:var(--outline-width) solid var(--background);border-radius:var(--radius-circle);box-shadow:0 0 0 var(--spacing-0-125) var(--border);cursor:pointer;height:var(--spacing-5);-moz-transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);width:var(--spacing-5)}.settings__slider::-moz-range-thumb:hover{background-color:var(--accent-hover);transform:scale(1.1)}.settings__slider:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.settings__slider-labels{color:var(--text-dim);display:flex;font-size:var(--font-size-xs);justify-content:space-between;margin-top:var(--spacing-1)}.settings__checkbox-label{align-items:center;color:var(--text);cursor:pointer;display:flex;font-size:var(--font-size-base);font-weight:var(--font-weight-medium);gap:var(--spacing-3);-webkit-user-select:none;-moz-user-select:none;user-select:none}.settings__checkbox-label:hover{color:var(--accent)}.settings__checkbox{accent-color:var(--accent);cursor:pointer;height:var(--spacing-5);margin:0;width:var(--spacing-5)}.settings__radio-group{display:flex;flex-direction:column;gap:var(--spacing-2)}.settings__radio-label{align-items:center;border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;font-size:var(--font-size-base);font-weight:var(--font-weight-normal);gap:var(--spacing-2);padding:var(--spacing-2);transition:background-color var(--transition-base),color var(--transition-base);-webkit-user-select:none;-moz-user-select:none;user-select:none}.settings__radio-label:hover{background-color:var(--background-alt);color:var(--accent)}.settings__radio{accent-color:var(--accent);cursor:pointer;height:var(--spacing-5);margin:0;width:var(--spacing-5)}.settings__help-text{color:var(--text-dim);font-size:var(--font-size-sm);line-height:var(--line-height-relaxed);margin:0}@media (width <= 640px){.settings__panel{max-width:100%;width:100%}}.modal__overlay{backdrop-filter:blur(var(--blur-sm));background-color:oklch(from var(--shadow-color) l c h/60%);bottom:0;left:0;opacity:0;pointer-events:none;position:fixed;right:0;top:0;transition:opacity var(--transition-slow) ease;z-index:var(--z-modal-backdrop)}.modal__overlay[aria-hidden="false"]{opacity:1;pointer-events:auto}.modal{background-color:var(--background);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-xl);display:flex;flex-direction:column;left:50%;max-height:var(--vh-90);max-width:var(--max-height-modal);opacity:0;pointer-events:none;position:fixed;top:50%;transform:translate(-50%,-50%);transition:opacity var(--transition-slow) ease,transform var(--transition-slow) ease;width:100%;z-index:var(--z-modal)}.modal[aria-hidden="false"]{opacity:1;pointer-events:auto}.modal__header{align-items:center;border-bottom:var(--border-width) solid var(--border);display:flex;flex-shrink:0;justify-content:space-between;padding:var(--spacing-6)}.modal__title{color:var(--text);font-size:var(--font-size-xl);font-weight:var(--font-weight-semibold);margin:0}.modal__close{align-items:center;background:none;border:none;border-radius:var(--radius);color:var(--text-dim);cursor:pointer;display:flex;flex-shrink:0;justify-content:center;padding:var(--spacing-2);transition:background-color var(--transition-base),color var(--transition-base)}.modal__close:hover{background-color:var(--background-alt);color:var(--text)}.modal__close:focus{box-shadow:0 0 0 3px oklch(from var(--accent) l c h/10%);outline:none}.modal__body{flex:1;min-height:0;overflow-y:auto;padding:var(--spacing-6)}.modal__footer{border-top:var(--border-width) solid var(--border);display:flex;flex-shrink:0;gap:var(--spacing-3);justify-content:flex-end;padding:var(--spacing-6)}.modal__footer:empty{display:none}.modal--sm{max-width:var(--spacing-96)}.modal--md{max-width:var(--max-height-modal)}.modal--lg{max-width:var(--spacing-48)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rizzo-css",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "scripts": {
5
5
  "prepublishOnly": "cd ../.. && pnpm build:css && node scripts/copy-scaffold.js"
6
6
  },
@@ -38,6 +38,7 @@
38
38
  "type": "git",
39
39
  "url": "https://github.com/mingleusa/rizzo-css.git"
40
40
  },
41
+ "homepage": "https://rizzo-css.vercel.app",
41
42
  "license": "MIT",
42
43
  "author": "mingleusa"
43
44
  }
@@ -0,0 +1,28 @@
1
+ ---
2
+ // Devicon-style - React
3
+ // Source: React (https://react.dev)
4
+ // License: MIT
5
+
6
+ interface Props {
7
+ width?: number;
8
+ height?: number;
9
+ class?: string;
10
+ }
11
+
12
+ const { width = 16, height = 16, class: className = '' } = Astro.props;
13
+ ---
14
+
15
+ <svg
16
+ xmlns="http://www.w3.org/2000/svg"
17
+ width={width}
18
+ height={height}
19
+ viewBox="0 0 128 128"
20
+ class={`react-icon ${className}`.trim()}
21
+ aria-hidden="true"
22
+ >
23
+ <title>React</title>
24
+ <g fill="#61dafb">
25
+ <circle cx="64" cy="64" r="11.4"/>
26
+ <path d="M107.3 45.2c-2.2-.8-4.5-1.6-6.9-2.3c.6-2.4 1.1-4.8 1.5-7.1c2.1-13.2-.2-22.5-6.6-26.1c-1.9-1.1-4-1.6-6.4-1.6c-7 0-15.9 5.2-24.9 13.9c-9-8.7-17.9-13.9-24.9-13.9c-2.4 0-4.5.5-6.4 1.6c-6.4 3.7-8.7 13-6.6 26.1c.4 2.3.9 4.7 1.5 7.1c-2.4.7-4.7 1.4-6.9 2.3C8.2 50 1.4 56.6 1.4 64s6.9 14 19.3 18.8c2.2.8 4.5 1.6 6.9 2.3c-.6 2.4-1.1 4.8-1.5 7.1c-2.1 13.2.2 22.5 6.6 26.1c1.9 1.1 4 1.6 6.4 1.6c7.1 0 16-5.2 24.9-13.9c9 8.7 17.9 13.9 24.9 13.9c2.4 0 4.5-.5 6.4-1.6c6.4-3.7 8.7-13 6.6-26.1c-.4-2.3-.9-4.7-1.5-7.1c2.4-.7 4.7-1.4 6.9-2.3c12.5-4.8 19.3-11.4 19.3-18.8s-6.8-14-19.3-18.8M92.5 14.7c4.1 2.4 5.5 9.8 3.8 20.3c-.3 2.1-.8 4.3-1.4 6.6c-5.2-1.2-10.7-2-16.5-2.5c-3.4-4.8-6.9-9.1-10.4-13c7.4-7.3 14.9-12.3 21-12.3c1.3 0 2.5.3 3.5.9M81.3 74c-1.8 3.2-3.9 6.4-6.1 9.6c-3.7.3-7.4.4-11.2.4c-3.9 0-7.6-.1-11.2-.4q-3.3-4.8-6-9.6c-1.9-3.3-3.7-6.7-5.3-10c1.6-3.3 3.4-6.7 5.3-10c1.8-3.2 3.9-6.4 6.1-9.6c3.7-.3 7.4-.4 11.2-.4c3.9 0 7.6.1 11.2.4q3.3 4.8 6 9.6c1.9 3.3 3.7 6.7 5.3 10c-1.7 3.3-3.4 6.6-5.3 10m8.3-3.3c1.5 3.5 2.7 6.9 3.8 10.3c-3.4.8-7 1.4-10.8 1.9c1.2-1.9 2.5-3.9 3.6-6c1.2-2.1 2.3-4.2 3.4-6.2M64 97.8c-2.4-2.6-4.7-5.4-6.9-8.3c2.3.1 4.6.2 6.9.2s4.6-.1 6.9-.2c-2.2 2.9-4.5 5.7-6.9 8.3m-18.6-15c-3.8-.5-7.4-1.1-10.8-1.9c1.1-3.3 2.3-6.8 3.8-10.3c1.1 2 2.2 4.1 3.4 6.1c1.2 2.2 2.4 4.1 3.6 6.1m-7-25.5c-1.5-3.5-2.7-6.9-3.8-10.3c3.4-.8 7-1.4 10.8-1.9c-1.2 1.9-2.5 3.9-3.6 6c-1.2 2.1-2.3 4.2-3.4 6.2M64 30.2c2.4 2.6 4.7 5.4 6.9 8.3c-2.3-.1-4.6-.2-6.9-.2s-4.6.1-6.9.2c2.2-2.9 4.5-5.7 6.9-8.3m22.2 21l-3.6-6c3.8.5 7.4 1.1 10.8 1.9c-1.1 3.3-2.3 6.8-3.8 10.3c-1.1-2.1-2.2-4.2-3.4-6.2M31.7 35c-1.7-10.5-.3-17.9 3.8-20.3c1-.6 2.2-.9 3.5-.9c6 0 13.5 4.9 21 12.3c-3.5 3.8-7 8.2-10.4 13c-5.8.5-11.3 1.4-16.5 2.5c-.6-2.3-1-4.5-1.4-6.6M7 64c0-4.7 5.7-9.7 15.7-13.4c2-.8 4.2-1.5 6.4-2.1c1.6 5 3.6 10.3 6 15.6c-2.4 5.3-4.5 10.5-6 15.5C15.3 75.6 7 69.6 7 64m28.5 49.3c-4.1-2.4-5.5-9.8-3.8-20.3c.3-2.1.8-4.3 1.4-6.6c5.2 1.2 10.7 2 16.5 2.5c3.4 4.8 6.9 9.1 10.4 13c-7.4 7.3-14.9 12.3-21 12.3c-1.3 0-2.5-.3-3.5-.9M96.3 93c1.7 10.5.3 17.9-3.8 20.3c-1 .6-2.2.9-3.5.9c-6 0-13.5-4.9-21-12.3c3.5-3.8 7-8.2 10.4-13c5.8-.5 11.3-1.4 16.5-2.5c.6 2.3 1 4.5 1.4 6.6m9-15.6c-2 .8-4.2 1.5-6.4 2.1c-1.6-5-3.6-10.3-6-15.6c2.4-5.3 4.5-10.5 6-15.5c13.8 4 22.1 10 22.1 15.6c0 4.7-5.8 9.7-15.7 13.4"/>
27
+ </g>
28
+ </svg>
@@ -0,0 +1,26 @@
1
+ ---
2
+ // Devicon-style - Svelte
3
+ // Source: Svelte brand (https://svelte.dev)
4
+ // License: MIT
5
+
6
+ interface Props {
7
+ width?: number;
8
+ height?: number;
9
+ class?: string;
10
+ }
11
+
12
+ const { width = 16, height = 16, class: className = '' } = Astro.props;
13
+ ---
14
+
15
+ <svg
16
+ xmlns="http://www.w3.org/2000/svg"
17
+ width={width}
18
+ height={height}
19
+ viewBox="0 0 128 128"
20
+ class={`svelte-icon ${className}`.trim()}
21
+ aria-hidden="true"
22
+ >
23
+ <title>Svelte</title>
24
+ <path fill="#ff3e00" d="M110.43 16.936C98.553-.076 75.09-5.118 58.13 5.696l-29.792 19a34.2 34.2 0 0 0-15.48 22.897a25.478 30.64 0 0 0-.572 6.396a36.15 36.15 0 0 0 4.163 16.73A34.4 34.4 0 0 0 11.34 83.5a25.348 30.483 0 0 0 .345 14.412a36.5 36.5 0 0 0 5.9 13.152c11.878 17.01 35.394 22.053 52.3 11.24l29.762-19.001a34.13 34.13 0 0 0 15.438-22.918a35.5 35.5 0 0 0 .572-6.386a36.2 36.2 0 0 0-4.112-16.71a34.4 34.4 0 0 0 5.112-12.77c.369-2.11.557-4.245.562-6.386a36.4 36.4 0 0 0-6.787-21.178z"/>
25
+ <path fill="#fff" d="M55.219 112.662a28.463 34.23 0 0 1-5.954.76a23.64 23.64 0 0 1-19.435-10.187a21.9 21.9 0 0 1-4.08-12.74a15.658 18.83 0 0 1 .333-3.833a15.425 18.55 0 0 1 .72-2.782l.561-1.708l1.52 1.156a38.7 38.7 0 0 0 11.658 5.834l1.104.333l-.104 1.104v.573a6.63 6.63 0 0 0 1.228 3.854a7.1 7.1 0 0 0 2.538 2.288a8.262 9.936 0 0 0 3.312.837a8.251 9.923 0 0 0 1.79-.229a7.272 8.745 0 0 0 1.833-.802l29.76-19.094a6.26 6.26 0 0 0 2.904-5.302a6.62 6.62 0 0 0-1.26-3.844a7.14 7.14 0 0 0-2.553-2.252a8.313 9.997 0 0 0-3.307-.81a8.246 9.917 0 0 0-1.79.23a6.938 8.344 0 0 0-1.822.801l-11.346 7.25a24.376 29.314 0 0 1-6.048 2.656a23.64 23.64 0 0 1-25.39-9.416a21.94 21.94 0 0 1-4.08-12.74c.002-1.285.114-2.567.333-3.833a20.65 20.65 0 0 1 9.286-13.781l29.792-18.99a21.9 21.9 0 0 1 6.048-2.667a24 24 0 0 1 5.954-.75A23.68 23.68 0 0 1 98.22 24.745a21.94 21.94 0 0 1 4.029 12.75a15.748 18.939 0 0 1-.334 3.844a15.407 18.529 0 0 1-.718 2.781l-.562 1.708l-1.52-1.114a38.4 38.4 0 0 0-11.658-5.834l-1.104-.343l.104-1.105v-.572a6.7 6.7 0 0 0-1.228-3.865a7.1 7.1 0 0 0-2.55-2.25a8.309 9.992 0 0 0-3.3-.813a8.221 9.887 0 0 0-1.77.271a6.819 8.2 0 0 0-1.831.802l-29.793 18.99a5.88 7.071 0 0 0-1.836 1.79a4.75 5.713 0 0 0-.963 2.377a5.037 6.057 0 0 0-.136 1.104a6.62 6.62 0 0 0 1.228 3.844a7.1 7.1 0 0 0 2.549 2.25a8.299 9.98 0 0 0 3.301.812a8.247 9.918 0 0 0 1.79-.23a6.943 8.35 0 0 0 1.833-.801l11.367-7.292a24.218 29.125 0 0 1 6.048-2.656a28.526 34.305 0 0 1 5.954-.76A23.66 23.66 0 0 1 96.566 60.61a21.94 21.94 0 0 1 3.737 16.614a20.6 20.6 0 0 1-9.286 13.781l-29.74 18.99a24.308 29.233 0 0 1-6.057 2.667z"/>
26
+ </svg>
@@ -0,0 +1,27 @@
1
+ ---
2
+ // Devicon-style - Vue.js
3
+ // Source: Vue (https://vuejs.org)
4
+ // License: MIT
5
+
6
+ interface Props {
7
+ width?: number;
8
+ height?: number;
9
+ class?: string;
10
+ }
11
+
12
+ const { width = 16, height = 16, class: className = '' } = Astro.props;
13
+ ---
14
+
15
+ <svg
16
+ xmlns="http://www.w3.org/2000/svg"
17
+ width={width}
18
+ height={height}
19
+ viewBox="0 0 128 128"
20
+ class={`vue-icon ${className}`.trim()}
21
+ aria-hidden="true"
22
+ >
23
+ <title>Vue</title>
24
+ <path fill="none" d="m0 8.934l49.854.158l14.167 24.47l14.432-24.47L128 8.935l-63.834 110.14zm126.98.637l-24.36.02l-38.476 66.053L25.691 9.592L.942 9.572l63.211 107.89zm-25.149-.008l-22.745.168l-15.053 24.647L49.216 9.73l-22.794-.168l37.731 64.476zm-75.834-.17l23.002.009m-23.002-.01l23.002.01"/>
25
+ <path fill="#35495e" d="m25.997 9.393l23.002.009L64.035 34.36L79.018 9.404L102 9.398L64.15 75.053z"/>
26
+ <path fill="#41b883" d="m.91 9.569l25.067-.172l38.15 65.659L101.98 9.401l25.11.026l-62.966 108.06z"/>
27
+ </svg>
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-theme="{{DATA_THEME}}">{{THEME_LIST_COMMENT}}
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>{{TITLE}}</title>
7
+ <link rel="stylesheet" href="{{LINK_HREF}}" />
8
+ </head>
9
+ <body>
10
+ <header style="margin-bottom: var(--spacing-6);">
11
+ <h1>Hello, Rizzo CSS</h1>
12
+ <p>Vanilla JS — same styles and components as Astro/Svelte. Use the same BEM classes; see <a href="https://rizzo-css.vercel.app/docs/components">docs</a>.</p>
13
+ <div style="display: flex; align-items: center; gap: var(--spacing-3); flex-wrap: wrap; margin-top: var(--spacing-3);">
14
+ <label for="theme-select">Theme:</label>
15
+ <select id="theme-select" style="width: auto; min-width: 12rem;">
16
+ <option value="github-dark-classic">github-dark-classic</option>
17
+ <option value="github-light">github-light</option>
18
+ <option value="shades-of-purple">shades-of-purple</option>
19
+ <option value="sandstorm-classic">sandstorm-classic</option>
20
+ <option value="rocky-blood-orange">rocky-blood-orange</option>
21
+ <option value="minimal-dark-neon-yellow">minimal-dark-neon-yellow</option>
22
+ <option value="hack-the-box">hack-the-box</option>
23
+ <option value="pink-cat-boo">pink-cat-boo</option>
24
+ <option value="red-velvet-cupcake">red-velvet-cupcake</option>
25
+ <option value="orangy-one-light">orangy-one-light</option>
26
+ <option value="sunflower">sunflower</option>
27
+ <option value="green-breeze-light">green-breeze-light</option>
28
+ <option value="cute-pink">cute-pink</option>
29
+ <option value="semi-light-purple">semi-light-purple</option>
30
+ </select>
31
+ </div>
32
+ </header>
33
+
34
+ <section style="margin-bottom: var(--spacing-6);">
35
+ <h2>Buttons</h2>
36
+ <div style="display: flex; flex-wrap: wrap; gap: var(--spacing-3);">
37
+ <button type="button" class="btn">Default</button>
38
+ <button type="button" class="btn btn-primary">Primary</button>
39
+ <button type="button" class="btn btn-success">Success</button>
40
+ <button type="button" class="btn btn-warning">Warning</button>
41
+ <button type="button" class="btn btn-error">Error</button>
42
+ <button type="button" class="btn btn-outline">Outline</button>
43
+ </div>
44
+ </section>
45
+
46
+ <section style="margin-bottom: var(--spacing-6);">
47
+ <h2>Card &amp; Badge</h2>
48
+ <div class="card" style="max-width: 20rem;">
49
+ <div class="card__body">
50
+ <h3 class="card__title">Card title</h3>
51
+ <p>Same component styles as Astro and Svelte. Use class names from the <a href="https://rizzo-css.vercel.app/docs/components">component docs</a>.</p>
52
+ <span class="badge badge--primary">Badge</span>
53
+ </div>
54
+ </div>
55
+ </section>
56
+
57
+ <p><small>All themes and component styles are included. Run <code>npx rizzo-css theme</code> to list themes.</small></p>
58
+
59
+ <script>
60
+ (function () {
61
+ var select = document.getElementById('theme-select');
62
+ var html = document.documentElement;
63
+ var key = 'rizzo-theme';
64
+ function applyTheme(value) {
65
+ html.setAttribute('data-theme', value);
66
+ try { localStorage.setItem(key, value); } catch (e) {}
67
+ select.value = value;
68
+ }
69
+ var stored = null;
70
+ try { stored = localStorage.getItem(key); } catch (e) {}
71
+ var initial = stored || html.getAttribute('data-theme') || 'github-dark-classic';
72
+ applyTheme(initial);
73
+ select.addEventListener('change', function () { applyTheme(select.value); });
74
+ })();
75
+ </script>
76
+ </body>
77
+ </html>