@luciodale/docs-ui-kit 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @luciodale/docs-ui-kit
2
2
 
3
- Astro component library for building documentation sites. Dark theme, orange accent, Tailwind CSS v4. Ships source `.astro` files — no build step in the library, your Astro project processes them.
3
+ Astro component library for building documentation sites. Dark theme, orange accent, Tailwind CSS v4. Ships source `.astro` files and pre-compiled Tailwind utilities your Astro project processes the components, the CSS works everywhere without `@source` hacks.
4
4
 
5
5
  ## Install
6
6
 
@@ -16,18 +16,25 @@ Runtime dependency: `shiki` (build-time syntax highlighting in Astro frontmatter
16
16
 
17
17
  ### 1. CSS
18
18
 
19
- Create a global CSS file and import the theme + tell Tailwind to scan the library's components:
19
+ Create a global CSS file and import the theme + pre-compiled utilities:
20
20
 
21
21
  ```css
22
22
  /* src/styles/global.css */
23
23
  @import "tailwindcss";
24
24
  @import "@luciodale/docs-ui-kit/styles.css";
25
-
26
- /* Adjust the path to wherever node_modules lives relative to this file */
27
- @source "../../node_modules/@luciodale/docs-ui-kit/src";
25
+ @import "@luciodale/docs-ui-kit/utilities.css";
28
26
  ```
29
27
 
30
- The theme CSS defines Tailwind v4 `@theme` tokens (colors, fonts) and base body styles (`background: black; color: white`). It also provides a `.liquid-glass-border` utility class.
28
+ - `styles.css` Tailwind v4 `@theme` tokens (colors, fonts), base body styles (`background: black; color: white`), and custom utilities like `.liquid-glass-border`
29
+ - `utilities.css` — Pre-compiled Tailwind utility classes used by all components (navbar, sidebar, code blocks, etc.). Ships with the package so you don't need `@source` directives pointing into `node_modules`
30
+
31
+ Then import this CSS in your base layout's frontmatter (not a `<style>` tag):
32
+
33
+ ```astro
34
+ ---
35
+ import "../styles/global.css";
36
+ ---
37
+ ```
31
38
 
32
39
  ### 2. Fonts
33
40
 
@@ -313,6 +320,46 @@ import Callout from "@luciodale/docs-ui-kit/components/Callout.astro";
313
320
 
314
321
  Renders a left-bordered aside with icon, title, and slot content. Supports links (`<a>`) and inline code (`<code>`) in the body.
315
322
 
323
+ #### FeatureList
324
+
325
+ Highlighted feature list with colored dots and keywords. Designed for landing pages and feature summaries.
326
+
327
+ ```astro
328
+ ---
329
+ import FeatureList from "@luciodale/docs-ui-kit/components/FeatureList.astro";
330
+ ---
331
+
332
+ <FeatureList features={[
333
+ { highlight: "Type-safe", description: "Full TypeScript support out of the box" },
334
+ { highlight: "Lightweight", description: "Zero runtime overhead", color: "green" },
335
+ { highlight: "Dark theme", description: "Built for modern documentation sites" },
336
+ ]} />
337
+
338
+ <!-- Or set a global color for all items -->
339
+ <FeatureList
340
+ color="cyan"
341
+ features={[
342
+ { highlight: "Fast", description: "Build-time syntax highlighting via Shiki" },
343
+ { highlight: "Searchable", description: "Full-text search powered by Pagefind" },
344
+ ]}
345
+ />
346
+ ```
347
+
348
+ | Prop | Type | Required | Description |
349
+ |---|---|---|---|
350
+ | `features` | `Array<FeatureItem>` | Yes | List of feature items (see below). |
351
+ | `color` | `FeatureColor` | No | Default: `"accent"`. Global color for all items. Overridden by per-item `color`. |
352
+
353
+ **FeatureItem:**
354
+
355
+ | Field | Type | Required | Description |
356
+ |---|---|---|---|
357
+ | `highlight` | `string` | Yes | Colored keyword/phrase. Rendered in bold with the active color. |
358
+ | `description` | `string` | No | Text after the highlight, separated by an em dash. |
359
+ | `color` | `FeatureColor` | No | Per-item color override. |
360
+
361
+ **FeatureColor:** `"accent"` \| `"blue"` \| `"green"` \| `"purple"` \| `"yellow"` \| `"cyan"`
362
+
316
363
  #### PackageInfo
317
364
 
318
365
  Displays npm version, license, GitHub stars, and a bundlephobia link. Data is fetched at build time from the npm registry and GitHub API (3s timeout, graceful fallback).
@@ -450,6 +497,7 @@ import LinkedInIcon from "@luciodale/docs-ui-kit/components/LinkedInIcon.astro";
450
497
  // src/layouts/Base.astro
451
498
  import SEO from "@luciodale/docs-ui-kit/components/SEO.astro";
452
499
  import { siteConfig } from "../config";
500
+ import "../styles/global.css";
453
501
 
454
502
  type Props = { title: string; description?: string; type?: "website" | "article" };
455
503
 
@@ -472,10 +520,6 @@ const { title, description, type = "website" } = Astro.props;
472
520
  <slot />
473
521
  </body>
474
522
  </html>
475
-
476
- <style is:global>
477
- @import "../styles/global.css";
478
- </style>
479
523
  ```
480
524
 
481
525
  ### Docs layout wrapper (create in your project)
@@ -506,6 +550,7 @@ const { title, description } = Astro.props;
506
550
  // src/pages/index.astro
507
551
  import PageLayout from "@luciodale/docs-ui-kit/components/PageLayout.astro";
508
552
  import HeroSection from "@luciodale/docs-ui-kit/components/HeroSection.astro";
553
+ import FeatureList from "@luciodale/docs-ui-kit/components/FeatureList.astro";
509
554
  import { siteConfig } from "../config";
510
555
  import Base from "../layouts/Base.astro";
511
556
 
@@ -519,9 +564,11 @@ export const prerender = true;
519
564
  description={siteConfig.description}
520
565
  installCommand={siteConfig.installCommand}
521
566
  >
522
- <a href="/docs/getting-started" class="rounded-lg bg-accent px-5 py-2.5 text-sm text-white">
523
- Get Started
524
- </a>
567
+ <FeatureList features={[
568
+ { highlight: "Type-safe", description: "Full TypeScript support" },
569
+ { highlight: "Lightweight", description: "Zero runtime dependencies", color: "green" },
570
+ { highlight: "Fast", description: "Build-time syntax highlighting", color: "cyan" },
571
+ ]} />
525
572
  </HeroSection>
526
573
  </PageLayout>
527
574
  </Base>
@@ -588,7 +635,7 @@ Defined in `theme.css` via Tailwind v4 `@theme` tokens:
588
635
  | `--color-border` | `#e5e7eb` | Light border. |
589
636
  | `--color-muted` | `#848d9f` | Muted text. |
590
637
 
591
- Body: `background: black`, `color: white`. All components use `white/` opacity variants for text hierarchy (`text-white/60`, `text-white/40`, `text-white/30`).
638
+ Body: `background: black`, `color: white`. All components use `white/` opacity variants for text hierarchy (`text-white/70` body text, `text-white/60` secondary, `text-white/40` labels, `text-white/30` decorative).
592
639
 
593
640
  ## Responsive behavior
594
641
 
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@luciodale/docs-ui-kit",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Astro component library for documentation sites. Dark theme, orange accent.",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  "./components/*": "./src/components/*",
8
8
  "./types/config": "./src/types/config.ts",
9
9
  "./types/props": "./src/types/props.ts",
10
- "./styles.css": "./src/styles/theme.css"
10
+ "./styles.css": "./src/styles/theme.css",
11
+ "./utilities.css": "./src/styles/utilities.css"
11
12
  },
12
13
  "files": [
13
14
  "src"
@@ -16,7 +17,8 @@
16
17
  "format": "biome format --write .",
17
18
  "lint": "biome check .",
18
19
  "lint:fix": "biome check --write .",
19
- "npm": "npm publish --access public",
20
+ "build": "bunx @tailwindcss/cli --input src/styles/build-input.css --output src/styles/utilities.css --minify",
21
+ "npm": "bun run build && npm publish --access public",
20
22
  "npm:test": "npm pack --dry-run"
21
23
  },
22
24
  "peerDependencies": {
@@ -27,7 +29,9 @@
27
29
  },
28
30
  "devDependencies": {
29
31
  "@biomejs/biome": "^2.4.7",
32
+ "@tailwindcss/cli": "^4.2.2",
30
33
  "astro": "^5.0.0",
34
+ "tailwindcss": "^4.2.2",
31
35
  "typescript": "^5.9.3"
32
36
  },
33
37
  "keywords": [
@@ -52,7 +52,7 @@ const heading = title ?? s.defaultTitle;
52
52
  {type === "danger" && <DangerIcon />}
53
53
  {heading}
54
54
  </div>
55
- <div class="text-sm text-white/60 leading-relaxed [&_a]:text-accent [&_a]:underline [&_code]:text-white/70 [&_code]:font-mono [&_code]:text-xs">
55
+ <div class="text-sm text-white/70 leading-relaxed [&_a]:text-accent [&_a]:underline [&_code]:text-white/80 [&_code]:font-mono [&_code]:text-xs">
56
56
  <slot />
57
57
  </div>
58
58
  </aside>
@@ -17,10 +17,10 @@ const html = await codeToHtml(trimmed, {
17
17
 
18
18
  <div class="rounded-lg border border-white/10 bg-[#161618] overflow-hidden my-4">
19
19
  <div class="flex items-center justify-between px-4 py-2.5 border-b border-white/[0.06] bg-white/[0.02]">
20
- <span class="text-xs text-white/30 font-mono">{filename ?? language}</span>
20
+ <span class="text-xs text-white/40 font-mono">{filename ?? language}</span>
21
21
  <button
22
22
  type="button"
23
- class="copy-btn text-xs text-white/30 hover:text-white/60 transition-colors cursor-pointer"
23
+ class="copy-btn text-xs text-white/40 hover:text-white/70 transition-colors cursor-pointer"
24
24
  data-code={trimmed}
25
25
  >
26
26
  <span class="copy-label">Copy</span>
@@ -0,0 +1,42 @@
1
+ ---
2
+ type FeatureColor = "accent" | "blue" | "green" | "purple" | "yellow" | "cyan";
3
+
4
+ type FeatureItem = {
5
+ highlight: string;
6
+ description?: string;
7
+ color?: FeatureColor;
8
+ };
9
+
10
+ type Props = {
11
+ features: FeatureItem[];
12
+ color?: FeatureColor;
13
+ };
14
+
15
+ const { features, color = "accent" } = Astro.props;
16
+
17
+ const colorMap: Record<FeatureColor, { text: string; dot: string }> = {
18
+ accent: { text: "text-accent", dot: "bg-accent" },
19
+ blue: { text: "text-blue-400", dot: "bg-blue-400" },
20
+ green: { text: "text-green-400", dot: "bg-green-400" },
21
+ purple: { text: "text-purple-400", dot: "bg-purple-400" },
22
+ yellow: { text: "text-yellow-400", dot: "bg-yellow-400" },
23
+ cyan: { text: "text-cyan-400", dot: "bg-cyan-400" },
24
+ };
25
+ ---
26
+
27
+ <ul class="flex flex-col gap-3 list-none m-0 p-0">
28
+ {features.map((feature) => {
29
+ const c = colorMap[feature.color ?? color];
30
+ return (
31
+ <li class="flex items-start gap-3">
32
+ <span class:list={["mt-[7px] w-1.5 h-1.5 rounded-full shrink-0", c.dot]} />
33
+ <span class="text-base leading-relaxed">
34
+ <span class:list={["font-semibold", c.text]}>{feature.highlight}</span>
35
+ {feature.description && (
36
+ <span class="text-white/70">{" "}&mdash; {feature.description}</span>
37
+ )}
38
+ </span>
39
+ </li>
40
+ );
41
+ })}
42
+ </ul>
@@ -20,13 +20,13 @@ const copyright = config.copyright ?? config.title;
20
20
  {config.logoSrc && (
21
21
  <a href={withBase("/")}>
22
22
  <img
23
- src={config.logoSrc}
23
+ src={withBase(config.logoSrc)}
24
24
  alt={config.logoAlt ?? config.title}
25
25
  class="w-8 h-auto opacity-60 hover:opacity-100 transition-opacity"
26
26
  />
27
27
  </a>
28
28
  )}
29
- <span class="text-white/40 text-sm">
29
+ <span class="text-white/50 text-sm">
30
30
  &copy; {year} {copyright}
31
31
  </span>
32
32
  </div>
@@ -35,7 +35,7 @@ const copyright = config.copyright ?? config.title;
35
35
  {config.navLinks.map((link) => (
36
36
  <a
37
37
  href={withBase(link.href)}
38
- class="text-white/40 text-sm hover:text-white/70 transition-colors"
38
+ class="text-white/50 text-sm hover:text-white/80 transition-colors"
39
39
  >
40
40
  {link.label}
41
41
  </a>
@@ -47,7 +47,7 @@ const copyright = config.copyright ?? config.title;
47
47
  href={config.socialLinks.github}
48
48
  target="_blank"
49
49
  rel="noopener noreferrer"
50
- class="text-white/30 hover:text-white/60 transition-colors"
50
+ class="text-white/40 hover:text-white/70 transition-colors"
51
51
  >
52
52
  <GithubIcon class="w-5" />
53
53
  </a>
@@ -56,7 +56,7 @@ const copyright = config.copyright ?? config.title;
56
56
  href={config.socialLinks.linkedin}
57
57
  target="_blank"
58
58
  rel="noopener noreferrer"
59
- class="text-white/30 hover:text-white/60 transition-colors"
59
+ class="text-white/40 hover:text-white/70 transition-colors"
60
60
  >
61
61
  <LinkedInIcon class="w-5" />
62
62
  </a>
@@ -18,7 +18,7 @@ const hasExtra = Astro.slots.has("default");
18
18
  <h1 class="text-4xl md:text-5xl font-bold tracking-tight text-white leading-[1.1] mb-4">
19
19
  {title}
20
20
  </h1>
21
- <p class="text-lg text-white/50 leading-relaxed max-w-xl mb-10">{description}</p>
21
+ <p class="text-lg text-white/60 leading-relaxed max-w-xl mb-10">{description}</p>
22
22
  <button
23
23
  type="button"
24
24
  class="copy-btn group rounded-lg border border-white/10 bg-white/5 hover:bg-white/[0.08] px-5 py-3 font-mono text-sm text-white/70 transition-colors cursor-pointer"
@@ -26,7 +26,7 @@ const hasExtra = Astro.slots.has("default");
26
26
  >
27
27
  <span class="text-accent">$</span>
28
28
  <span class="ml-2">{installCommand}</span>
29
- <span class="ml-3 text-white/30 group-hover:text-white/50 transition-colors text-xs copy-label">
29
+ <span class="ml-3 text-white/40 group-hover:text-white/60 transition-colors text-xs copy-label">
30
30
  Copy
31
31
  </span>
32
32
  </button>
@@ -16,7 +16,7 @@ const { config, currentPath } = Astro.props;
16
16
  <div class="max-w-7xl h-full mx-auto px-6 md:px-8 flex items-center justify-between">
17
17
  <a href={withBase("/")} class="flex items-center gap-3 text-white hover:opacity-80 transition-opacity">
18
18
  {config.logoSrc ? (
19
- <img src={config.logoSrc} alt={config.logoAlt ?? config.title} class="h-7" />
19
+ <img src={withBase(config.logoSrc)} alt={config.logoAlt ?? config.title} class="h-7" />
20
20
  ) : (
21
21
  <span class="text-base font-semibold tracking-tight">{config.title}</span>
22
22
  )}
@@ -30,7 +30,7 @@ const { config, currentPath } = Astro.props;
30
30
  "text-sm font-medium transition-colors duration-150",
31
31
  currentPath.startsWith(link.href)
32
32
  ? "text-white"
33
- : "text-white/50 hover:text-white/80",
33
+ : "text-white/60 hover:text-white/90",
34
34
  ]}
35
35
  >
36
36
  {link.label}
@@ -39,14 +39,14 @@ const { config, currentPath } = Astro.props;
39
39
  <button
40
40
  id="search-trigger"
41
41
  type="button"
42
- class="flex items-center gap-2 rounded-lg border border-white/10 bg-white/[0.03] hover:bg-white/[0.06] px-3 py-1.5 text-white/40 hover:text-white/60 transition-colors cursor-pointer"
42
+ class="flex items-center gap-2 rounded-lg border border-white/10 bg-white/[0.03] hover:bg-white/[0.06] px-3 py-1.5 text-white/50 hover:text-white/70 transition-colors cursor-pointer"
43
43
  >
44
44
  <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
45
45
  <circle cx="11" cy="11" r="7" />
46
46
  <line x1="16.5" y1="16.5" x2="21" y2="21" />
47
47
  </svg>
48
48
  <span class="text-xs">Search</span>
49
- <kbd class="ml-2 rounded border border-white/10 bg-white/[0.04] px-1.5 py-0.5 text-[10px] font-mono text-white/30">
49
+ <kbd class="ml-2 rounded border border-white/10 bg-white/[0.04] px-1.5 py-0.5 text-[10px] font-mono text-white/40">
50
50
  <span class="text-[10px]">&#8984;</span>K
51
51
  </kbd>
52
52
  </button>
@@ -54,7 +54,7 @@ const { config, currentPath } = Astro.props;
54
54
  href={config.githubUrl}
55
55
  target="_blank"
56
56
  rel="noopener noreferrer"
57
- class="text-white/40 hover:text-white/70 transition-colors duration-150"
57
+ class="text-white/50 hover:text-white/80 transition-colors duration-150"
58
58
  >
59
59
  <GithubIcon class="w-5" />
60
60
  </a>
@@ -64,7 +64,7 @@ const { config, currentPath } = Astro.props;
64
64
  <button
65
65
  id="search-trigger-mobile"
66
66
  type="button"
67
- class="text-white/50 hover:text-white transition-colors cursor-pointer"
67
+ class="text-white/60 hover:text-white transition-colors cursor-pointer"
68
68
  aria-label="Search"
69
69
  >
70
70
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
@@ -75,7 +75,7 @@ const { config, currentPath } = Astro.props;
75
75
  <button
76
76
  id="mobile-nav-toggle"
77
77
  type="button"
78
- class="text-white/60 hover:text-white transition-colors cursor-pointer"
78
+ class="text-white/70 hover:text-white transition-colors cursor-pointer"
79
79
  aria-label="Toggle menu"
80
80
  >
81
81
  <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -97,7 +97,7 @@ const { config, currentPath } = Astro.props;
97
97
  <button
98
98
  id="mobile-nav-close"
99
99
  type="button"
100
- class="text-white/60 hover:text-white transition-colors cursor-pointer"
100
+ class="text-white/70 hover:text-white transition-colors cursor-pointer"
101
101
  aria-label="Close menu"
102
102
  >
103
103
  <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -114,7 +114,7 @@ const { config, currentPath } = Astro.props;
114
114
  "text-sm font-medium transition-colors",
115
115
  currentPath.startsWith(link.href)
116
116
  ? "text-white"
117
- : "text-white/50 hover:text-white/80",
117
+ : "text-white/60 hover:text-white/90",
118
118
  ]}
119
119
  >
120
120
  {link.label}
@@ -126,7 +126,7 @@ const { config, currentPath } = Astro.props;
126
126
  <div class="px-6 py-4">
127
127
  {config.sidebarSections.map((section) => (
128
128
  <div class="mb-5">
129
- <div class="text-xs font-semibold uppercase tracking-widest text-white/30 mb-2">
129
+ <div class="text-xs font-semibold uppercase tracking-widest text-white/40 mb-2">
130
130
  {section.title}
131
131
  </div>
132
132
  <div class="flex flex-col">
@@ -137,7 +137,7 @@ const { config, currentPath } = Astro.props;
137
137
  "block py-1.5 pl-3 text-sm border-l-2 transition-colors",
138
138
  currentPath === link.href
139
139
  ? "border-accent text-white font-medium"
140
- : "border-transparent text-white/50 hover:text-white/80 hover:border-white/20",
140
+ : "border-transparent text-white/60 hover:text-white/90 hover:border-white/20",
141
141
  ]}
142
142
  >
143
143
  {link.label}
@@ -154,7 +154,7 @@ const { config, currentPath } = Astro.props;
154
154
  href={config.socialLinks.github}
155
155
  target="_blank"
156
156
  rel="noopener noreferrer"
157
- class="text-white/30 hover:text-white/60 transition-colors"
157
+ class="text-white/40 hover:text-white/70 transition-colors"
158
158
  >
159
159
  <GithubIcon class="w-5" />
160
160
  </a>
@@ -61,7 +61,7 @@ const [npm, github] = await Promise.all([fetchNpm(), fetchGithub()]);
61
61
  </a>
62
62
  )}
63
63
  {npm?.license && (
64
- <span class="inline-flex items-center rounded-md border border-white/10 bg-white/[0.03] px-2.5 py-1 text-white/50">
64
+ <span class="inline-flex items-center rounded-md border border-white/10 bg-white/[0.03] px-2.5 py-1 text-white/60">
65
65
  {npm.license}
66
66
  </span>
67
67
  )}
@@ -70,7 +70,7 @@ const [npm, github] = await Promise.all([fetchNpm(), fetchGithub()]);
70
70
  href={`https://github.com/${githubRepo}`}
71
71
  target="_blank"
72
72
  rel="noopener noreferrer"
73
- class="inline-flex items-center gap-1.5 rounded-md border border-white/10 bg-white/[0.03] px-2.5 py-1 text-white/50 hover:bg-white/[0.06] transition-colors"
73
+ class="inline-flex items-center gap-1.5 rounded-md border border-white/10 bg-white/[0.03] px-2.5 py-1 text-white/60 hover:bg-white/[0.06] transition-colors"
74
74
  >
75
75
  <svg class="w-3 h-3" fill="currentColor" viewBox="0 0 24 24">
76
76
  <path d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279L12 19.771l-7.416 3.642 1.48-8.279L0 9.306l8.332-1.151z" />
@@ -82,7 +82,7 @@ const [npm, github] = await Promise.all([fetchNpm(), fetchGithub()]);
82
82
  href={`https://bundlephobia.com/package/${packageName}${npm?.version ? `@${npm.version}` : ""}`}
83
83
  target="_blank"
84
84
  rel="noopener noreferrer"
85
- class="inline-flex items-center gap-1.5 rounded-md border border-white/10 bg-white/[0.03] px-2.5 py-1 text-white/50 hover:bg-white/[0.06] transition-colors"
85
+ class="inline-flex items-center gap-1.5 rounded-md border border-white/10 bg-white/[0.03] px-2.5 py-1 text-white/60 hover:bg-white/[0.06] transition-colors"
86
86
  >
87
87
  <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
88
88
  <path d="M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 002 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z" />
@@ -16,10 +16,10 @@ const { title, rows } = Astro.props;
16
16
  <table class="w-full text-left text-sm">
17
17
  <thead>
18
18
  <tr class="border-b border-white/10 bg-white/[0.02]">
19
- <th class="py-3 px-4 text-xs font-medium text-white/40 uppercase tracking-wider">Prop</th>
20
- <th class="py-3 px-4 text-xs font-medium text-white/40 uppercase tracking-wider">Type</th>
21
- <th class="py-3 px-4 text-xs font-medium text-white/40 uppercase tracking-wider">Default</th>
22
- <th class="py-3 px-4 text-xs font-medium text-white/40 uppercase tracking-wider">Description</th>
19
+ <th class="py-3 px-4 text-xs font-medium text-white/50 uppercase tracking-wider">Prop</th>
20
+ <th class="py-3 px-4 text-xs font-medium text-white/50 uppercase tracking-wider">Type</th>
21
+ <th class="py-3 px-4 text-xs font-medium text-white/50 uppercase tracking-wider">Default</th>
22
+ <th class="py-3 px-4 text-xs font-medium text-white/50 uppercase tracking-wider">Description</th>
23
23
  </tr>
24
24
  </thead>
25
25
  <tbody>
@@ -30,12 +30,12 @@ const { title, rows } = Astro.props;
30
30
  {row.required && <span class="ml-1 text-red-400 text-xs">*</span>}
31
31
  </td>
32
32
  <td class="py-3 px-4">
33
- <code class="text-white/50 font-mono text-xs">{row.type}</code>
33
+ <code class="text-white/60 font-mono text-xs">{row.type}</code>
34
34
  </td>
35
- <td class="py-3 px-4 text-white/35 text-xs font-mono">
35
+ <td class="py-3 px-4 text-white/45 text-xs font-mono">
36
36
  {row.defaultValue ?? "\u2014"}
37
37
  </td>
38
- <td class="py-3 px-4 text-white/60 text-sm">{row.description}</td>
38
+ <td class="py-3 px-4 text-white/70 text-sm">{row.description}</td>
39
39
  </tr>
40
40
  ))}
41
41
  </tbody>
@@ -75,7 +75,7 @@
75
75
  .search-dialog-icon {
76
76
  width: 0.875rem;
77
77
  height: 0.875rem;
78
- color: rgb(255 255 255 / 0.3);
78
+ color: rgb(255 255 255 / 0.4);
79
79
  flex-shrink: 0;
80
80
  }
81
81
 
@@ -88,7 +88,7 @@
88
88
  }
89
89
 
90
90
  .search-dialog-input::placeholder {
91
- color: rgb(255 255 255 / 0.3);
91
+ color: rgb(255 255 255 / 0.4);
92
92
  }
93
93
 
94
94
  .search-dialog-kbd {
@@ -98,7 +98,7 @@
98
98
  padding: 0.125rem 0.375rem;
99
99
  font-size: 10px;
100
100
  font-family: ui-monospace, monospace;
101
- color: rgb(255 255 255 / 0.3);
101
+ color: rgb(255 255 255 / 0.4);
102
102
  }
103
103
 
104
104
  .search-dialog-results {
@@ -111,7 +111,7 @@
111
111
  padding: 1.5rem 0.75rem;
112
112
  text-align: center;
113
113
  font-size: 0.875rem;
114
- color: rgb(255 255 255 / 0.3);
114
+ color: rgb(255 255 255 / 0.4);
115
115
  }
116
116
 
117
117
  #search-results :global(mark) {
@@ -180,7 +180,7 @@
180
180
  const container = document.getElementById("search-results");
181
181
  if (!container) return;
182
182
 
183
- const placeholderStyle = "padding: 1.5rem 0.75rem; text-align: center; font-size: 0.875rem; color: rgb(255 255 255 / 0.3);";
183
+ const placeholderStyle = "padding: 1.5rem 0.75rem; text-align: center; font-size: 0.875rem; color: rgb(255 255 255 / 0.4);";
184
184
 
185
185
  if (!query.trim()) {
186
186
  container.innerHTML = `<p style="${placeholderStyle}">Type to search...</p>`;
@@ -200,9 +200,9 @@
200
200
  <a href="${r.url}" style="display: block; border-radius: 0.5rem; padding: 0.625rem 0.75rem; transition: background-color 150ms; text-decoration: none;" onmouseenter="this.style.background='rgb(255 255 255 / 0.04)'" onmouseleave="this.style.background='transparent'" data-search-result>
201
201
  <div style="display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.125rem;">
202
202
  <span style="font-size: 0.875rem; font-weight: 500; color: rgb(255 255 255 / 0.8);">${r.title}</span>
203
- ${r.section ? `<span style="font-size: 11px; color: rgb(255 255 255 / 0.25);">${r.section}</span>` : ""}
203
+ ${r.section ? `<span style="font-size: 11px; color: rgb(255 255 255 / 0.35);">${r.section}</span>` : ""}
204
204
  </div>
205
- <div style="font-size: 0.75rem; color: rgb(255 255 255 / 0.4); line-height: 1.625; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;">${r.excerpt}</div>
205
+ <div style="font-size: 0.75rem; color: rgb(255 255 255 / 0.5); line-height: 1.625; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;">${r.excerpt}</div>
206
206
  </a>`,
207
207
  )
208
208
  .join("");
@@ -215,7 +215,7 @@
215
215
  if (!pf) {
216
216
  const container = document.getElementById("search-results");
217
217
  if (container) {
218
- container.innerHTML = '<p style="padding: 1.5rem 0.75rem; text-align: center; font-size: 0.875rem; color: rgb(255 255 255 / 0.3);">Search not available. Run <code style="font-family: ui-monospace, monospace; color: rgb(255 255 255 / 0.5);">npx pagefind</code> after building.</p>';
218
+ container.innerHTML = '<p style="padding: 1.5rem 0.75rem; text-align: center; font-size: 0.875rem; color: rgb(255 255 255 / 0.4);">Search not available. Run <code style="font-family: ui-monospace, monospace; color: rgb(255 255 255 / 0.6);">npx pagefind</code> after building.</p>';
219
219
  }
220
220
  return;
221
221
  }
@@ -11,7 +11,7 @@ const { section, currentPath } = Astro.props;
11
11
  ---
12
12
 
13
13
  <details class="mb-6 group" open>
14
- <summary class="flex items-center justify-between w-full py-1.5 text-xs font-semibold uppercase tracking-widest text-white/30 hover:text-white/50 transition-colors cursor-pointer list-none [&::-webkit-details-marker]:hidden">
14
+ <summary class="flex items-center justify-between w-full py-1.5 text-xs font-semibold uppercase tracking-widest text-white/40 hover:text-white/60 transition-colors cursor-pointer list-none [&::-webkit-details-marker]:hidden">
15
15
  {section.title}
16
16
  <svg
17
17
  class="w-3 h-3 transition-transform duration-150 group-open:rotate-180"
@@ -30,7 +30,7 @@ const { section, currentPath } = Astro.props;
30
30
  "block py-1.5 pl-3 text-sm border-l-2 transition-colors",
31
31
  currentPath === link.href
32
32
  ? "border-accent text-white font-medium"
33
- : "border-transparent text-white/50 hover:text-white/80 hover:border-white/20",
33
+ : "border-transparent text-white/60 hover:text-white/90 hover:border-white/20",
34
34
  ]}
35
35
  >
36
36
  {link.label}
@@ -4,7 +4,7 @@
4
4
  ---
5
5
 
6
6
  <nav id="toc" class="w-44 shrink-0 hidden xl:block sticky top-16 h-[calc(100dvh-4rem)] pt-8 pr-4 overflow-y-auto">
7
- <div class="text-xs font-semibold uppercase tracking-widest text-white/30 mb-3">On this page</div>
7
+ <div class="text-xs font-semibold uppercase tracking-widest text-white/40 mb-3">On this page</div>
8
8
  <ul id="toc-list" class="flex flex-col gap-0.5"></ul>
9
9
  </nav>
10
10
 
@@ -12,7 +12,7 @@
12
12
  const ACTIVE_CLASS =
13
13
  "block py-1 text-sm border-l-2 pl-3 transition-colors border-accent text-white font-medium";
14
14
  const INACTIVE_CLASS =
15
- "block py-1 text-sm border-l-2 pl-3 transition-colors border-transparent text-white/40 hover:text-white/60 hover:border-white/20";
15
+ "block py-1 text-sm border-l-2 pl-3 transition-colors border-transparent text-white/50 hover:text-white/70 hover:border-white/20";
16
16
 
17
17
  function initToc() {
18
18
  const tocList = document.getElementById("toc-list");
@@ -0,0 +1,3 @@
1
+ @import "tailwindcss";
2
+ @source "../components/**/*.{astro,ts}";
3
+ @source "../utils/**/*.ts";
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-400:oklch(70.4% .191 22.216);--color-yellow-400:oklch(85.2% .199 91.936);--color-green-400:oklch(79.2% .209 151.711);--color-cyan-400:oklch(78.9% .154 211.53);--color-blue-400:oklch(70.7% .165 254.624);--color-purple-400:oklch(71.4% .203 305.504);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xl:36rem;--container-3xl:48rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--ease-out:cubic-bezier(0, 0, .2, 1);--blur-sm:8px;--blur-md:12px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.fixed{position:fixed}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-16{top:calc(var(--spacing) * 16)}.right-0{right:calc(var(--spacing) * 0)}.z-40{z-index:40}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing) * 0)}.mx-auto{margin-inline:auto}.my-4{margin-block:calc(var(--spacing) * 4)}.my-6{margin-block:calc(var(--spacing) * 6)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-12{margin-top:calc(var(--spacing) * 12)}.mt-\[7px\]{margin-top:7px}.mt-auto{margin-top:auto}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.mb-10{margin-bottom:calc(var(--spacing) * 10)}.mb-12{margin-bottom:calc(var(--spacing) * 12)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-3{margin-left:calc(var(--spacing) * 3)}.block{display:block}.flex{display:flex}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-16{height:calc(var(--spacing) * 16)}.h-20{height:calc(var(--spacing) * 20)}.h-\[calc\(100dvh-4rem\)\]{height:calc(100dvh - 4rem)}.h-auto{height:auto}.h-dvh{height:100dvh}.h-full{height:100%}.min-h-dvh{min-height:100dvh}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-20{width:calc(var(--spacing) * 20)}.w-44{width:calc(var(--spacing) * 44)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-xl{max-width:var(--container-xl)}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.translate-x-full{--tw-translate-x:100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-pointer{cursor:pointer}.scroll-mt-24{scroll-margin-top:calc(var(--spacing) * 24)}.list-none{list-style-type:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-blue-400\/30{border-color:#54a2ff4d}@supports (color:color-mix(in lab, red, red)){.border-blue-400\/30{border-color:color-mix(in oklab, var(--color-blue-400) 30%, transparent)}}.border-green-400\/30{border-color:#05df724d}@supports (color:color-mix(in lab, red, red)){.border-green-400\/30{border-color:color-mix(in oklab, var(--color-green-400) 30%, transparent)}}.border-red-400\/30{border-color:#ff65684d}@supports (color:color-mix(in lab, red, red)){.border-red-400\/30{border-color:color-mix(in oklab, var(--color-red-400) 30%, transparent)}}.border-transparent{border-color:#0000}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\/10{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-white\/\[0\.04\]{border-color:#ffffff0a}@supports (color:color-mix(in lab, red, red)){.border-white\/\[0\.04\]{border-color:color-mix(in oklab, var(--color-white) 4%, transparent)}}.border-white\/\[0\.06\]{border-color:#ffffff0f}@supports (color:color-mix(in lab, red, red)){.border-white\/\[0\.06\]{border-color:color-mix(in oklab, var(--color-white) 6%, transparent)}}.border-yellow-400\/30{border-color:#fac8004d}@supports (color:color-mix(in lab, red, red)){.border-yellow-400\/30{border-color:color-mix(in oklab, var(--color-yellow-400) 30%, transparent)}}.bg-\[\#161618\]{background-color:#161618}.bg-black{background-color:var(--color-black)}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab, red, red)){.bg-black\/60{background-color:color-mix(in oklab, var(--color-black) 60%, transparent)}}.bg-black\/80{background-color:#000c}@supports (color:color-mix(in lab, red, red)){.bg-black\/80{background-color:color-mix(in oklab, var(--color-black) 80%, transparent)}}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-400\/5{background-color:#54a2ff0d}@supports (color:color-mix(in lab, red, red)){.bg-blue-400\/5{background-color:color-mix(in oklab, var(--color-blue-400) 5%, transparent)}}.bg-cyan-400{background-color:var(--color-cyan-400)}.bg-green-400{background-color:var(--color-green-400)}.bg-green-400\/5{background-color:#05df720d}@supports (color:color-mix(in lab, red, red)){.bg-green-400\/5{background-color:color-mix(in oklab, var(--color-green-400) 5%, transparent)}}.bg-purple-400{background-color:var(--color-purple-400)}.bg-red-400\/5{background-color:#ff65680d}@supports (color:color-mix(in lab, red, red)){.bg-red-400\/5{background-color:color-mix(in oklab, var(--color-red-400) 5%, transparent)}}.bg-white\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.bg-white\/5{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.bg-white\/\[0\.02\]{background-color:#ffffff05}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[0\.02\]{background-color:color-mix(in oklab, var(--color-white) 2%, transparent)}}.bg-white\/\[0\.03\]{background-color:#ffffff08}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[0\.03\]{background-color:color-mix(in oklab, var(--color-white) 3%, transparent)}}.bg-white\/\[0\.04\]{background-color:#ffffff0a}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[0\.04\]{background-color:color-mix(in oklab, var(--color-white) 4%, transparent)}}.bg-yellow-400{background-color:var(--color-yellow-400)}.bg-yellow-400\/5{background-color:#fac8000d}@supports (color:color-mix(in lab, red, red)){.bg-yellow-400\/5{background-color:color-mix(in oklab, var(--color-yellow-400) 5%, transparent)}}.p-0{padding:calc(var(--spacing) * 0)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-24{padding-block:calc(var(--spacing) * 24)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pb-10{padding-bottom:calc(var(--spacing) * 10)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-6{padding-left:calc(var(--spacing) * 6)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.leading-\[1\.1\]{--tw-leading:1.1;line-height:1.1}.leading-\[1\.7\]{--tw-leading:1.7;line-height:1.7}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-blue-400{color:var(--color-blue-400)}.text-cyan-400{color:var(--color-cyan-400)}.text-green-400{color:var(--color-green-400)}.text-purple-400{color:var(--color-purple-400)}.text-red-400{color:var(--color-red-400)}.text-white{color:var(--color-white)}.text-white\/30{color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.text-white\/30{color:color-mix(in oklab, var(--color-white) 30%, transparent)}}.text-white\/40{color:#fff6}@supports (color:color-mix(in lab, red, red)){.text-white\/40{color:color-mix(in oklab, var(--color-white) 40%, transparent)}}.text-white\/45{color:#ffffff73}@supports (color:color-mix(in lab, red, red)){.text-white\/45{color:color-mix(in oklab, var(--color-white) 45%, transparent)}}.text-white\/50{color:#ffffff80}@supports (color:color-mix(in lab, red, red)){.text-white\/50{color:color-mix(in oklab, var(--color-white) 50%, transparent)}}.text-white\/60{color:#fff9}@supports (color:color-mix(in lab, red, red)){.text-white\/60{color:color-mix(in oklab, var(--color-white) 60%, transparent)}}.text-white\/70{color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.text-white\/70{color:color-mix(in oklab, var(--color-white) 70%, transparent)}}.text-yellow-400{color:var(--color-yellow-400)}.uppercase{text-transform:uppercase}.opacity-60{opacity:.6}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-md{--tw-backdrop-blur:blur(var(--blur-md));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.group-open\:rotate-180:is(:where(.group):is([open],:popover-open,:open) *){rotate:180deg}@media (hover:hover){.group-hover\:text-white\/60:is(:where(.group):hover *){color:#fff9}@supports (color:color-mix(in lab, red, red)){.group-hover\:text-white\/60:is(:where(.group):hover *){color:color-mix(in oklab, var(--color-white) 60%, transparent)}}}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:border-white\/20:hover{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\:border-white\/20:hover{border-color:color-mix(in oklab, var(--color-white) 20%, transparent)}}.hover\:bg-white\/\[0\.06\]:hover{background-color:#ffffff0f}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.06\]:hover{background-color:color-mix(in oklab, var(--color-white) 6%, transparent)}}.hover\:bg-white\/\[0\.08\]:hover{background-color:#ffffff14}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.08\]:hover{background-color:color-mix(in oklab, var(--color-white) 8%, transparent)}}.hover\:text-white:hover{color:var(--color-white)}.hover\:text-white\/60:hover{color:#fff9}@supports (color:color-mix(in lab, red, red)){.hover\:text-white\/60:hover{color:color-mix(in oklab, var(--color-white) 60%, transparent)}}.hover\:text-white\/70:hover{color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.hover\:text-white\/70:hover{color:color-mix(in oklab, var(--color-white) 70%, transparent)}}.hover\:text-white\/80:hover{color:#fffc}@supports (color:color-mix(in lab, red, red)){.hover\:text-white\/80:hover{color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.hover\:text-white\/90:hover{color:#ffffffe6}@supports (color:color-mix(in lab, red, red)){.hover\:text-white\/90:hover{color:color-mix(in oklab, var(--color-white) 90%, transparent)}}.hover\:opacity-80:hover{opacity:.8}.hover\:opacity-100:hover{opacity:1}}@media (min-width:48rem){.md\:block{display:block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:h-24{height:calc(var(--spacing) * 24)}.md\:w-1\/3{width:33.3333%}.md\:w-24{width:calc(var(--spacing) * 24)}.md\:flex-row{flex-direction:row}.md\:gap-4{gap:calc(var(--spacing) * 4)}.md\:px-8{padding-inline:calc(var(--spacing) * 8)}.md\:py-16{padding-block:calc(var(--spacing) * 16)}.md\:py-32{padding-block:calc(var(--spacing) * 32)}.md\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.md\:text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}}@media (min-width:80rem){.xl\:block{display:block}.xl\:px-12{padding-inline:calc(var(--spacing) * 12)}}.\[\&_a\]\:underline a{text-decoration-line:underline}.\[\&_code\]\:font-mono code{font-family:var(--font-mono)}.\[\&_code\]\:text-xs code{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\[\&_code\]\:text-white\/80 code{color:#fffc}@supports (color:color-mix(in lab, red, red)){.\[\&_code\]\:text-white\/80 code{color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.\[\&_pre\]\:\!m-0 pre{margin:calc(var(--spacing) * 0)!important}.\[\&_pre\]\:\!bg-transparent pre{background-color:#0000!important}.\[\&_pre\]\:\!p-0 pre{padding:calc(var(--spacing) * 0)!important}.\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker{display:none}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}