@x-wave/blog 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +387 -0
- package/consts/index.ts +9 -0
- package/consts/navigation.ts +29 -0
- package/index.css +1 -0
- package/index.js +1288 -0
- package/locales/index.ts +156 -0
- package/package.json +52 -0
- package/styles/_variables.scss +60 -0
- package/styles/global.scss +189 -0
- package/styles/main.scss +92 -0
- package/styles/mixins.scss +129 -0
- package/types/index.ts +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# @x-wave/blog
|
|
2
|
+
|
|
3
|
+
A responsive, multi-language documentation framework for React + Vite applications. Ships with TypeScript, i18n (i18next), MDX support, dark mode, and built-in navigation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-language support**: Ship 3+ languages with a single codebase (en, es, zh included)
|
|
8
|
+
- **MDX content**: Write docs in Markdown with React components
|
|
9
|
+
- **Dark mode**: Built-in light/dark/system theme toggle with localStorage persistence
|
|
10
|
+
- **Advanced mode**: Optional Simple/Advanced content variants for the same page
|
|
11
|
+
- **Mobile responsive**: Automatic sidebar → mobile menu on small screens
|
|
12
|
+
- **Headless**: No styling opinions—includes SCSS variables for full customization
|
|
13
|
+
- **HMR-friendly**: Vite development with Hot Module Replacement for instant feedback
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### npm
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @x-wave/blog
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### pnpm
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm add @x-wave/blog
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### yarn
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
yarn add @x-wave/blog
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick setup
|
|
36
|
+
|
|
37
|
+
### 1. Create your app structure
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
src/
|
|
41
|
+
├── App.tsx # Your app component
|
|
42
|
+
├── main.tsx # Entry point
|
|
43
|
+
├── navigation.ts # Site navigation definition
|
|
44
|
+
├── utils.ts # Content loaders
|
|
45
|
+
├── logo.svg # Optional: your logo
|
|
46
|
+
└── docs/
|
|
47
|
+
├── en/
|
|
48
|
+
│ ├── welcome.mdx
|
|
49
|
+
│ ├── glossary.mdx
|
|
50
|
+
│ └── faq.mdx
|
|
51
|
+
├── es/
|
|
52
|
+
│ ├── welcome.mdx
|
|
53
|
+
│ ├── glossary.mdx
|
|
54
|
+
│ └── faq.mdx
|
|
55
|
+
└── zh/
|
|
56
|
+
├── welcome.mdx
|
|
57
|
+
├── glossary.mdx
|
|
58
|
+
└── faq.mdx
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 2. Set up i18n and styles
|
|
62
|
+
|
|
63
|
+
Import the i18n setup and framework styles in your app entry point:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// src/main.tsx
|
|
67
|
+
import '@x-wave/blog/locales' // Initialises i18next with en, es, zh
|
|
68
|
+
import '@x-wave/blog/styles' // Framework styles (required)
|
|
69
|
+
import { createRoot } from 'react-dom/client'
|
|
70
|
+
import App from './App'
|
|
71
|
+
|
|
72
|
+
createRoot(document.getElementById('root')!).render(<App />)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> **The styles import is required** for the UI components and layout to render correctly.
|
|
76
|
+
|
|
77
|
+
**Add custom translations:**
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
// src/main.tsx
|
|
81
|
+
import '@x-wave/blog/locales'
|
|
82
|
+
import i18next from 'i18next'
|
|
83
|
+
|
|
84
|
+
// Add French translations
|
|
85
|
+
i18next.addResourceBundle('fr', 'translation', {
|
|
86
|
+
language: 'Français',
|
|
87
|
+
'ui.simple': 'Simple',
|
|
88
|
+
'ui.advanced': 'Avancé',
|
|
89
|
+
// ... other keys
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 3. Define your navigation
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// src/navigation.ts
|
|
97
|
+
import type { NavigationEntry } from '@x-wave/blog/types'
|
|
98
|
+
|
|
99
|
+
export const NAVIGATION_DATA: NavigationEntry[] = [
|
|
100
|
+
{
|
|
101
|
+
title: 'docs.welcome',
|
|
102
|
+
slug: 'welcome',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
title: 'Help',
|
|
106
|
+
defaultOpen: true,
|
|
107
|
+
items: [
|
|
108
|
+
{
|
|
109
|
+
title: 'docs.glossary',
|
|
110
|
+
slug: 'glossary',
|
|
111
|
+
showTableOfContents: true,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
title: 'docs.faq',
|
|
115
|
+
slug: 'faq',
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 4. Create content loaders
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
// src/utils.ts
|
|
126
|
+
import { createBlogUtils } from '@x-wave/blog'
|
|
127
|
+
|
|
128
|
+
// Vite glob import – resolved relative to this file
|
|
129
|
+
const mdxFiles = import.meta.glob('./docs/**/*.mdx', {
|
|
130
|
+
query: '?raw',
|
|
131
|
+
import: 'default',
|
|
132
|
+
eager: false,
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
// Export all blog utilities in a single object
|
|
136
|
+
export const blog = createBlogUtils(mdxFiles)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 5. Wrap your app with BlogProvider
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
// src/App.tsx
|
|
143
|
+
import { BlogProvider, ContentPage, DocumentationLayout } from '@x-wave/blog'
|
|
144
|
+
import { Navigate, Route, HashRouter as Router, Routes, useParams } from 'react-router-dom'
|
|
145
|
+
import { blog } from './utils'
|
|
146
|
+
import { NAVIGATION_DATA } from './navigation'
|
|
147
|
+
|
|
148
|
+
const SUPPORTED_LANGUAGES = ['en', 'es', 'zh'] as const
|
|
149
|
+
|
|
150
|
+
function DocumentationWrapper() {
|
|
151
|
+
const { language } = useParams<{ language: string }>()
|
|
152
|
+
return (
|
|
153
|
+
<DocumentationLayout>
|
|
154
|
+
<Routes>
|
|
155
|
+
<Route path="/:slug" element={<ContentPage language={language!} />} />
|
|
156
|
+
<Route path="/" element={<Navigate to={`/${language}/welcome`} replace />} />
|
|
157
|
+
</Routes>
|
|
158
|
+
</DocumentationLayout>
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export default function App() {
|
|
163
|
+
return (
|
|
164
|
+
<BlogProvider
|
|
165
|
+
config={{
|
|
166
|
+
title: 'My Documentation',
|
|
167
|
+
supportedLanguages: SUPPORTED_LANGUAGES,
|
|
168
|
+
navigationData: NAVIGATION_DATA,
|
|
169
|
+
header: {
|
|
170
|
+
navLinks: [
|
|
171
|
+
{
|
|
172
|
+
label: 'Visit Site',
|
|
173
|
+
url: 'https://example.com',
|
|
174
|
+
target: '_blank',
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
}}
|
|
179
|
+
blog={blog}
|
|
180
|
+
>
|
|
181
|
+
<Router>
|
|
182
|
+
<Routes>
|
|
183
|
+
<Route path="/:language/*" element={<DocumentationWrapper />} />
|
|
184
|
+
<Route path="/" element={<Navigate to="/en/welcome" replace />} />
|
|
185
|
+
</Routes>
|
|
186
|
+
</Router>
|
|
187
|
+
</BlogProvider>
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Writing content
|
|
193
|
+
|
|
194
|
+
### File naming
|
|
195
|
+
|
|
196
|
+
Place your MDX files in language-specific directories:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
src/docs/
|
|
200
|
+
├── en/welcome.mdx
|
|
201
|
+
├── es/welcome.mdx
|
|
202
|
+
└── zh/welcome.mdx
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
File names must match the `slug` field in your navigation definition.
|
|
206
|
+
|
|
207
|
+
### Frontmatter
|
|
208
|
+
|
|
209
|
+
Optional YAML at the top of your MDX file:
|
|
210
|
+
|
|
211
|
+
```mdx
|
|
212
|
+
---
|
|
213
|
+
title: Getting Started
|
|
214
|
+
author: Jane Doe
|
|
215
|
+
date: 2026-02-23
|
|
216
|
+
hasAdvanced: true
|
|
217
|
+
tags:
|
|
218
|
+
- tutorial
|
|
219
|
+
- beginner
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
# Welcome!
|
|
223
|
+
|
|
224
|
+
Regular content here.
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
| Field | Type | Description |
|
|
228
|
+
|---|---|---|
|
|
229
|
+
| `title` | `string` | Document title (informational, not displayed by framework) |
|
|
230
|
+
| `author` | `string` | Author name. Displayed below the page title with a user icon. |
|
|
231
|
+
| `date` | `string` | Publication or update date. Displayed below the page title with "Last edited" label and calendar icon (i18n supported). |
|
|
232
|
+
| `hasAdvanced` | `boolean` | Enables Simple/Advanced mode toggle. Requires a `-advanced.mdx` variant. |
|
|
233
|
+
| `tags` | `string[]` | Array of tag strings for categorizing content. Tags are automatically indexed by the framework when you pass `mdxFiles` to BlogProvider. Tags are clickable and show search results. |
|
|
234
|
+
|
|
235
|
+
### Advanced mode variants
|
|
236
|
+
|
|
237
|
+
Create `welcome-advanced.mdx` alongside `welcome.mdx`:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
src/docs/
|
|
241
|
+
├── en/
|
|
242
|
+
│ ├── welcome.mdx
|
|
243
|
+
│ └── welcome-advanced.mdx
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Set `hasAdvanced: true` in the simple version's frontmatter, and the framework automatically shows a toggle.
|
|
247
|
+
|
|
248
|
+
## API reference
|
|
249
|
+
|
|
250
|
+
### Components
|
|
251
|
+
|
|
252
|
+
All components are exported from `@x-wave/blog`:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
import {
|
|
256
|
+
BlogProvider,
|
|
257
|
+
DocumentationLayout,
|
|
258
|
+
ContentPage,
|
|
259
|
+
Header,
|
|
260
|
+
Sidebar,
|
|
261
|
+
TableOfContents,
|
|
262
|
+
AdvancedModeToggle
|
|
263
|
+
} from '@x-wave/blog'
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
| Component | Purpose |
|
|
267
|
+
|---|---|
|
|
268
|
+
| `BlogProvider` | Root context wrapper (required) |
|
|
269
|
+
| `DocumentationLayout` | Page layout: header + sidebar + content |
|
|
270
|
+
| `ContentPage` | Loads and renders MDX pages |
|
|
271
|
+
| `Header` | Top navigation bar |
|
|
272
|
+
| `Sidebar` | Left navigation panel |
|
|
273
|
+
| `TableOfContents` | "On this page" anchor panel |
|
|
274
|
+
| `AdvancedModeToggle` | Simple/Advanced tab switch |
|
|
275
|
+
|
|
276
|
+
### Hooks
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
import { useTheme } from '@x-wave/blog'
|
|
280
|
+
|
|
281
|
+
const { theme, setTheme, effectiveTheme } = useTheme()
|
|
282
|
+
```
|
|
283
|
+
Manages light/dark/system theme preference.
|
|
284
|
+
|
|
285
|
+
### Utilities
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
import { createBlogUtils } from '@x-wave/blog'
|
|
289
|
+
|
|
290
|
+
const blog = createBlogUtils(mdxFiles)
|
|
291
|
+
```
|
|
292
|
+
Creates all blog utilities from a Vite glob import. This is the recommended approach as it bundles everything together.
|
|
293
|
+
|
|
294
|
+
Returns an object with:
|
|
295
|
+
- **`mdxFiles`**: The glob import (used internally for automatic tag indexing)
|
|
296
|
+
- **`loadContent(language, slug, advanced?)`**: Loads MDX content for a specific language and slug
|
|
297
|
+
- **`loadEnglishContent(slug, advanced?)`**: Loads English content for heading ID generation
|
|
298
|
+
|
|
299
|
+
Pass the entire `blog` object to BlogProvider:
|
|
300
|
+
|
|
301
|
+
```tsx
|
|
302
|
+
<BlogProvider config={config} blog={blog}>
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Alternative: Advanced usage**
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
import { createContentLoaders } from '@x-wave/blog'
|
|
309
|
+
|
|
310
|
+
const { loadMDXContent, loadEnglishContent, buildTagIndex } = createContentLoaders(mdxFiles)
|
|
311
|
+
```
|
|
312
|
+
For advanced use cases where you need more control over content loading and tag indexing.
|
|
313
|
+
|
|
314
|
+
### Types
|
|
315
|
+
|
|
316
|
+
All TypeScript types are exported from `@x-wave/blog/types`:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
import type { NavigationEntry, BlogConfig, HeaderLink } from '@x-wave/blog/types'
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Customization
|
|
323
|
+
|
|
324
|
+
### CSS variables
|
|
325
|
+
|
|
326
|
+
The framework exports SCSS variable files. Import and override them in your own stylesheets:
|
|
327
|
+
|
|
328
|
+
```scss
|
|
329
|
+
// In your app.scss
|
|
330
|
+
@use '~@x-wave/blog/styles/_variables' as vars;
|
|
331
|
+
|
|
332
|
+
// Override the color palette
|
|
333
|
+
$color-primary: #007bff;
|
|
334
|
+
$color-background: #fafafa;
|
|
335
|
+
|
|
336
|
+
// Your custom styles here
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Or import directly from the framework package:
|
|
340
|
+
|
|
341
|
+
```scss
|
|
342
|
+
@import 'node_modules/@x-wave/blog/dist/styles/_variables.scss';
|
|
343
|
+
|
|
344
|
+
$color-primary: #007bff;
|
|
345
|
+
$color-background: #fafafa;
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Available variables include:
|
|
349
|
+
- `$color-primary`, `$color-secondary`
|
|
350
|
+
- `$color-background`, `$color-text`
|
|
351
|
+
- `$spacing-xs`, `$spacing-sm`, `$spacing-md`, `$spacing-lg`, `$spacing-xl`
|
|
352
|
+
- `$font-family-sans`, `$font-family-mono`
|
|
353
|
+
- And more—see [styles/_variables.scss](packages/styles/_variables.scss)
|
|
354
|
+
|
|
355
|
+
### Config options
|
|
356
|
+
|
|
357
|
+
**BlogConfig** properties:
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
interface BlogConfig {
|
|
361
|
+
title: string // Site title
|
|
362
|
+
logo?: React.ComponentType<{ className?: string }> // Optional logo
|
|
363
|
+
supportedLanguages: readonly string[] // e.g. ['en', 'es', 'zh']
|
|
364
|
+
navigationData: NavigationEntry[] // Menu structure
|
|
365
|
+
header?: {
|
|
366
|
+
navLinks?: HeaderLink[] // Top-level nav links
|
|
367
|
+
dropdownItems?: HeaderDropdownItem[] // Support dropdown menu
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Browser support
|
|
373
|
+
|
|
374
|
+
- Chrome/Edge 90+
|
|
375
|
+
- Firefox 88+
|
|
376
|
+
- Safari 14+
|
|
377
|
+
- Mobile browsers (iOS Safari 14.5+, Chrome Android 90+)
|
|
378
|
+
|
|
379
|
+
## License
|
|
380
|
+
|
|
381
|
+
See LICENSE file in this repository.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## For framework maintainers
|
|
386
|
+
|
|
387
|
+
Contributing or maintaining this framework? See [DEVELOPMENT.md](./DEVELOPMENT.md) for setup, architecture, and build system details.
|
package/consts/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DOCS_TITLE = 'Staking Docs'
|
|
2
|
+
|
|
3
|
+
export const SUPPORTED_LANGUAGES = ['en', 'zh', 'es'] as const
|
|
4
|
+
|
|
5
|
+
export const GITHUB_REPO_URL = 'https://github.com/polkadot-cloud'
|
|
6
|
+
|
|
7
|
+
export const STAKING_DASHBOARD_URL = 'https://staking.polkadot.cloud'
|
|
8
|
+
|
|
9
|
+
export { NAVIGATION_DATA } from './navigation'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { NavigationEntry } from 'types'
|
|
2
|
+
|
|
3
|
+
// Navigation structure with i18n keys instead of hardcoded text
|
|
4
|
+
// Supports both grouped sections and individual items
|
|
5
|
+
// Optional properties:
|
|
6
|
+
// - hasAdvanced: boolean - indicates if the page has an advanced version
|
|
7
|
+
// - showTableOfContents: boolean - set to false to hide "On this page" section (default: true)
|
|
8
|
+
// - defaultOpen: boolean - for sections, set to true to have them open by default
|
|
9
|
+
export const NAVIGATION_DATA: NavigationEntry[] = [
|
|
10
|
+
{
|
|
11
|
+
title: 'docs.helloWorld',
|
|
12
|
+
slug: 'welcome',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
title: 'nav.helpResources',
|
|
16
|
+
defaultOpen: true,
|
|
17
|
+
items: [
|
|
18
|
+
{
|
|
19
|
+
title: 'docs.glossary',
|
|
20
|
+
slug: 'glossary',
|
|
21
|
+
showTableOfContents: true,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
title: 'docs.faq',
|
|
25
|
+
slug: 'faq',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
]
|
package/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._tabContainer_yggpc_1{display:inline-flex;background-color:var(--card);border:1px solid var(--border);border-radius:.5rem;margin-bottom:2rem;overflow:hidden}._tab_yggpc_1{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:.5rem;font-size:.875rem;font-weight:500;transition:.15s cubic-bezier(.4,0,.2,1);cursor:pointer;border:none;outline:none}._tab_yggpc_1:focus-visible{outline:2px solid var(--ring);outline-offset:2px}._tab_yggpc_1:disabled{pointer-events:none;opacity:.5}._tab_yggpc_1{padding:.5rem 1rem;font-size:.87rem;font-weight:500;background-color:transparent;border:none;border-radius:0;color:var(--muted-foreground);cursor:pointer;white-space:nowrap}._tab_yggpc_1:not(:last-child){border-right:1px solid var(--border)}._tab_yggpc_1._active_yggpc_45{background-color:var(--accent);color:var(--accent-foreground)}._tab_yggpc_1:hover:not(._active_yggpc_45){background-color:var(--muted);color:var(--foreground)}._tab_yggpc_1:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}._tableOfContents_vn5e4_1{position:sticky;top:5rem;align-self:flex-start;height:fit-content;max-height:calc(100vh - 8rem);overflow-y:auto;padding:2rem 0 2rem 1.5rem;margin-left:2rem;background:transparent;border-left:1px solid var(--border);flex-shrink:0}@media(max-width:1024px){._tableOfContents_vn5e4_1{display:none}}._header_vn5e4_20{margin-bottom:1rem}._title_vn5e4_24{font-size:.75rem;font-weight:500;color:var(--muted-foreground);text-transform:uppercase;letter-spacing:.05em;margin-bottom:.5rem}._nav_vn5e4_33 ul{margin:0;padding:0;list-style:none}._list_vn5e4_39{display:flex;flex-direction:column;gap:.125rem;margin:0}._link_vn5e4_46{display:block;width:100%;padding:.25rem 0;text-align:left;background:none;border:none;cursor:pointer;font-size:.875rem;line-height:1.4;color:var(--muted-foreground);text-decoration:none;border-radius:.25rem;transition:all .15s cubic-bezier(.4,0,.2,1);position:relative;font-family:inherit}._link_vn5e4_46:hover{color:var(--foreground)}._link_vn5e4_46:focus{outline:none;color:var(--foreground)}._link_vn5e4_46._active_vn5e4_70{color:var(--primary);font-weight:500}._link_vn5e4_46._active_vn5e4_70:before{content:"";position:absolute;left:-1.5rem;top:50%;transform:translateY(-50%);width:1px;height:1rem;background-color:var(--primary);border-radius:.5px}._level1_vn5e4_86{font-weight:500;padding-left:0;margin-bottom:.125rem}._level2_vn5e4_92{padding-left:.5rem;margin-bottom:.0625rem}._level3_vn5e4_97{padding-left:1rem;font-size:.8125rem;margin-bottom:.0625rem}._level4_vn5e4_103{padding-left:1.5rem;font-size:.8125rem;margin-bottom:.0625rem}._level5_vn5e4_109{padding-left:2rem;font-size:.75rem;margin-bottom:.0625rem}._level6_vn5e4_115{padding-left:2.5rem;font-size:.75rem;margin-bottom:.0625rem}._tableOfContents_vn5e4_1::-webkit-scrollbar{width:4px}._tableOfContents_vn5e4_1::-webkit-scrollbar-track{background:transparent}._tableOfContents_vn5e4_1::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px}._tableOfContents_vn5e4_1::-webkit-scrollbar-thumb:hover{background:var(--muted-foreground)}._overlay_s7p1r_1{position:fixed;top:0;left:0;right:0;bottom:0;background:#00000080;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:2000;display:flex;align-items:flex-start;justify-content:center;padding-top:10vh;animation:_fadeIn_s7p1r_1 .2s ease;height:100vh}@keyframes _fadeIn_s7p1r_1{0%{opacity:0}to{opacity:1}}._modal_s7p1r_26{width:90%;max-width:600px;background:var(--card);border:1px solid var(--border);border-radius:.75rem;box-shadow:0 20px 60px #0000004d;animation:_slideIn_s7p1r_1 .2s ease;max-height:80vh;display:flex;flex-direction:column;overflow:hidden}@keyframes _slideIn_s7p1r_1{0%{transform:translateY(-20px);opacity:0}to{transform:translateY(0);opacity:1}}._header_s7p1r_50{display:flex;align-items:center;justify-content:space-between;padding:1.25rem 1.5rem;border-bottom:1px solid var(--border)}._title_s7p1r_58{font-size:1.125rem;font-weight:600;color:var(--foreground);margin:0}._closeButton_s7p1r_65{background:none;border:none;color:var(--muted-foreground);cursor:pointer;padding:.25rem;display:flex;align-items:center;justify-content:center;border-radius:.25rem;transition:all .2s ease}._closeButton_s7p1r_65 svg{width:1.25rem;height:1.25rem}._closeButton_s7p1r_65:hover{background:var(--secondary);color:var(--foreground)}._results_s7p1r_86{flex:1;overflow-y:auto;padding:.5rem;min-height:200px;max-height:400px}._resultsList_s7p1r_94{list-style:none;padding:0;margin:0}._resultItem_s7p1r_100{display:flex;flex-direction:column;align-items:flex-start;gap:.25rem;width:100%;padding:.75rem 1rem;background:none;border:none;border-radius:.5rem;cursor:pointer;text-align:left;transition:all .15s ease;color:var(--foreground)}._resultItem_s7p1r_100:hover{background:var(--secondary)}._resultTitle_s7p1r_119{font-weight:500;font-size:.95rem}._resultSlug_s7p1r_124{font-size:.8rem;color:var(--muted-foreground);opacity:.8}._noResults_s7p1r_130{padding:3rem 1rem;text-align:center;color:var(--muted-foreground);font-size:.9rem}._tags_8uc6s_1{display:flex;align-items:center;gap:.75rem;margin:2rem 0 1rem;padding:1rem 0 0;border-top:1px solid var(--border)}._tags_8uc6s_1._compact_8uc6s_9{margin:2rem 0 1rem;padding:1rem 0 0;border-top:1px solid var(--border)}._tagLabel_8uc6s_15{display:flex;align-items:center;gap:.5rem;color:var(--muted-foreground);font-size:.875rem;font-weight:500;white-space:nowrap}._tagIcon_8uc6s_25{width:1.125rem;height:1.125rem}._tagList_8uc6s_30{display:flex;flex-wrap:wrap;gap:.5rem}._tag_8uc6s_1{display:inline-flex;align-items:center;padding:.25rem .75rem;background:none;border:1px solid var(--border);border-radius:.75rem;color:var(--muted-foreground);font-size:.8rem;font-weight:400;cursor:pointer;transition:all .2s ease}._tag_8uc6s_1:hover{color:var(--foreground);border-color:var(--ring)}._contentPage_godc9_1{flex:1;max-width:48rem;margin:0;padding:0 0 2rem}@media(max-width:767px){._contentPage_godc9_1{padding:1.5rem;max-width:none}}@media(max-width:1024px){._contentPage_godc9_1{max-width:none;padding:2rem}}._metadata_godc9_20{display:flex;gap:1rem;align-items:center;padding:.5rem 0 1rem;color:var(--muted-foreground);font-size:.875rem;border-bottom:1px solid var(--border);margin-bottom:1rem}._metadata_godc9_20 ._author_godc9_30,._metadata_godc9_20 ._date_godc9_31{display:flex;align-items:center;gap:.5rem}._metadata_godc9_20 ._author_godc9_30{font-weight:500;color:var(--foreground)}@media(max-width:767px){._metadata_godc9_20{flex-direction:column;align-items:flex-start;gap:.25rem}}._loadingContainer_godc9_48,._errorContainer_godc9_49{display:flex;align-items:center;justify-content:center;height:16rem}._loadingContainer_godc9_48{flex-direction:column;align-items:flex-start;gap:1.5rem;padding:2rem 0}@keyframes _shimmer_godc9_1{0%{background-position:-1000px 0}to{background-position:1000px 0}}._skeletonTitle_godc9_71{width:60%;height:2.5rem;background:linear-gradient(90deg,var(--muted) 0%,color-mix(in oklch,var(--muted) 50%,white) 50%,var(--muted) 100%);background-size:1000px 100%;animation:_shimmer_godc9_1 2s infinite linear;border-radius:.5rem}._skeletonParagraph_godc9_80{width:100%;height:1rem;background:linear-gradient(90deg,var(--muted) 0%,color-mix(in oklch,var(--muted) 50%,white) 50%,var(--muted) 100%);background-size:1000px 100%;animation:_shimmer_godc9_1 2s infinite linear;border-radius:.25rem;margin-bottom:.5rem}._skeletonParagraph_godc9_80:not(:last-child){margin-bottom:1rem}._skeletonParagraphShort_godc9_93{width:70%;height:1rem;background:linear-gradient(90deg,var(--muted) 0%,color-mix(in oklch,var(--muted) 50%,white) 50%,var(--muted) 100%);background-size:1000px 100%;animation:_shimmer_godc9_1 2s infinite linear;border-radius:.25rem}._loadingText_godc9_102{color:var(--muted-foreground);font-size:1rem}._errorText_godc9_107{color:var(--destructive);font-size:1rem}._mdxContent_godc9_112{max-width:none}._mdxContent_godc9_112 h1{font-size:1.875rem;font-weight:600;letter-spacing:-.025em;margin-bottom:1.5rem;border-bottom:1px solid var(--border);padding-bottom:.75rem;line-height:1.2;scroll-margin-top:5rem}._mdxContent_godc9_112 h1._withMetadata_godc9_125{border-bottom:none;padding-bottom:0;margin-bottom:.5rem}._mdxContent_godc9_112 h1 a{color:inherit;text-decoration:none;border:none;position:relative}._mdxContent_godc9_112 h1 a:hover{color:inherit;border:none}._mdxContent_godc9_112 h1 a:hover:before{content:"#";position:absolute;left:-1.5rem;color:var(--link);opacity:.7;font-weight:400}._mdxContent_godc9_112 h2{font-size:1.5rem;font-weight:500;letter-spacing:-.02em;margin-bottom:1rem;margin-top:2.5rem;border-bottom:1px solid var(--border);padding-bottom:.5rem;line-height:1.3;scroll-margin-top:5rem}._mdxContent_godc9_112 h2 a{color:inherit;text-decoration:none;border:none;position:relative}._mdxContent_godc9_112 h2 a:hover{color:inherit;border:none}._mdxContent_godc9_112 h2 a:hover:before{content:"#";position:absolute;left:-1.5rem;color:var(--link);opacity:.7;font-weight:400}._mdxContent_godc9_112 h3{font-size:1.25rem;font-weight:500;letter-spacing:-.015em;margin-bottom:.75rem;margin-top:2rem;line-height:1.4;scroll-margin-top:5rem}._mdxContent_godc9_112 h3 a{color:inherit;text-decoration:none;border:none;position:relative}._mdxContent_godc9_112 h3 a:hover{color:inherit;border:none}._mdxContent_godc9_112 h3 a:hover:before{content:"#";position:absolute;left:-1.5rem;color:var(--link);opacity:.7;font-weight:400}._mdxContent_godc9_112 h4{font-size:1.125rem;font-weight:500;letter-spacing:-.01em;margin-bottom:.5rem;margin-top:1.5rem;line-height:1.4;scroll-margin-top:5rem}._mdxContent_godc9_112 h4 a{color:inherit;text-decoration:none;border:none;position:relative}._mdxContent_godc9_112 h4 a:hover{color:inherit;border:none}._mdxContent_godc9_112 h4 a:hover:before{content:"#";position:absolute;left:-1.5rem;color:var(--link);opacity:.7;font-weight:400}._mdxContent_godc9_112 h5{font-size:1rem;font-weight:500;margin-bottom:.5rem;margin-top:1.25rem;line-height:1.5}._mdxContent_godc9_112 h6{font-size:.875rem;font-weight:500;margin-bottom:.5rem;margin-top:1rem;line-height:1.5}._mdxContent_godc9_112 p{font-size:1rem;line-height:1.65;margin-bottom:1rem;color:var(--foreground)}._mdxContent_godc9_112 ul,._mdxContent_godc9_112 ol{margin-bottom:1rem;padding-left:1.5rem}._mdxContent_godc9_112 ul li,._mdxContent_godc9_112 ol li{font-size:1rem;line-height:1.65;margin-bottom:.375rem}._mdxContent_godc9_112 ul ul,._mdxContent_godc9_112 ul ol,._mdxContent_godc9_112 ol ul,._mdxContent_godc9_112 ol ol{margin-top:.375rem;margin-bottom:.375rem}._mdxContent_godc9_112 ul{list-style-type:disc}._mdxContent_godc9_112 ol{list-style-type:decimal}._mdxContent_godc9_112 code{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:.875rem;background-color:var(--muted);padding:.1875rem .4375rem;border-radius:.25rem;color:var(--foreground);font-weight:500}._mdxContent_godc9_112 pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;background-color:var(--muted);padding:1.25rem;border-radius:.75rem;overflow-x:auto;margin:1.5rem 0;position:relative;border:1px solid var(--border)}._mdxContent_godc9_112 pre code{background-color:transparent;padding:0;color:inherit;font-weight:400}._mdxContent_godc9_112 ._codeBlock_godc9_300{position:relative;margin-bottom:1.5rem}._mdxContent_godc9_112 ._codeLanguage_godc9_304{position:absolute;top:.5rem;right:.5rem;font-size:.75rem;color:var(--muted-foreground);background-color:var(--background);padding:.25rem .5rem;border-radius:.25rem;border:1px solid var(--border)}._mdxContent_godc9_112 blockquote{border-left:3px solid var(--accent);padding-left:1rem;font-style:italic;color:var(--muted-foreground);margin-bottom:1rem;margin-top:1rem}._mdxContent_godc9_112 blockquote p{margin-bottom:.5rem}._mdxContent_godc9_112 blockquote p:last-child{margin-bottom:0}._mdxContent_godc9_112 a{color:var(--link);text-decoration:none;transition:color .15s cubic-bezier(.4,0,.2,1);border-bottom:1px solid transparent}._mdxContent_godc9_112 a:hover{color:color-mix(in oklch,var(--link) 80%,transparent);border-bottom-color:currentColor}._mdxContent_godc9_112 strong{font-weight:600}._mdxContent_godc9_112 em{font-style:italic}._mdxContent_godc9_112 table{width:100%;border-collapse:collapse;margin:1.5rem 0;font-size:.95rem}._mdxContent_godc9_112 table th,._mdxContent_godc9_112 table td{padding:.75rem 1rem;text-align:left;border-bottom:1px solid var(--border);line-height:1.4}._mdxContent_godc9_112 table th{font-weight:500;background-color:var(--muted);font-size:.875rem;letter-spacing:.025em}._mdxContent_godc9_112 table tbody tr:hover{background-color:color-mix(in oklch,var(--muted) 50%,transparent)}._mdxContent_godc9_112 img{max-width:100%;height:auto;border-radius:.5rem;margin:1.5rem 0;border:1px solid var(--border)}._mdxContent_godc9_112 hr{border:none;border-top:1px solid var(--border);margin:2rem 0}._searchButton_royne_1{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-radius:.375rem;background:none;border:none;color:var(--muted-foreground);cursor:pointer;transition:all .2s ease;font-size:.875rem}._searchButton_royne_1:hover{border-color:var(--input)}._searchButton_royne_1 ._searchIcon_royne_17{width:1rem;height:1rem;opacity:.6}@media(max-width:768px){._searchButton_royne_1 ._searchHint_royne_23{display:none}}._searchButton_royne_1 ._kbd_royne_27{display:none;padding:.125rem .375rem;background:var(--card);border:1px solid var(--border);border-radius:.25rem;font-size:.75rem;font-family:monospace}@media(min-width:768px){._searchButton_royne_1 ._kbd_royne_27{display:block}}._searchOverlay_royne_42{position:fixed;top:0;left:0;right:0;bottom:0;background:#00000080;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:2000;display:flex;align-items:flex-start;justify-content:center;padding-top:10vh;animation:_fadeIn_royne_1 .2s ease;height:100vh}@keyframes _fadeIn_royne_1{0%{opacity:0}to{opacity:1}}._searchModal_royne_67{width:90%;max-width:600px;background:var(--card);border:1px solid var(--border);border-radius:.75rem;box-shadow:0 20px 60px #0000004d;animation:_slideIn_royne_1 .2s ease;max-height:80vh;display:flex;flex-direction:column;overflow:hidden}@keyframes _slideIn_royne_1{0%{transform:translateY(-20px);opacity:0}to{transform:translateY(0);opacity:1}}._searchHeader_royne_91{display:flex;align-items:center;gap:.75rem;padding:1rem 1.25rem;border-bottom:1px solid var(--border)}._searchHeader_royne_91 ._searchIcon_royne_17{width:1.25rem;height:1.25rem;opacity:.5;flex-shrink:0}._searchInput_royne_105{flex:1;border:none;background:transparent;color:var(--foreground);font-size:1rem;outline:none}._searchInput_royne_105:focus{border:none;outline:none;box-shadow:none}._searchInput_royne_105::placeholder{color:var(--muted-foreground);opacity:.6}._closeButton_royne_123{background:none;border:none;color:var(--muted-foreground);cursor:pointer;padding:.25rem;display:flex;align-items:center;justify-content:center;border-radius:.25rem;transition:all .2s ease}._closeButton_royne_123 svg{width:1.25rem;height:1.25rem}._closeButton_royne_123:hover{background:var(--secondary);color:var(--foreground)}._searchResults_royne_144{flex:1;overflow-y:auto;padding:.5rem;min-height:200px;max-height:400px}._resultsList_royne_152{list-style:none;padding:0;margin:0}._resultItem_royne_158{display:flex;flex-direction:column;align-items:flex-start;gap:.25rem;width:100%;padding:.75rem 1rem;background:none;border:none;border-radius:.5rem;cursor:pointer;text-align:left;transition:all .15s ease;color:var(--foreground)}._resultItem_royne_158:hover,._resultItem_royne_158._selected_royne_173{background:var(--secondary)}._resultItem_royne_158 ._resultTitle_royne_176{font-weight:500;font-size:.95rem}._resultItem_royne_158 ._resultSlug_royne_180{font-size:.8rem;color:var(--muted-foreground);opacity:.8}._noResults_royne_186{padding:3rem 1rem;text-align:center;color:var(--muted-foreground);font-size:.9rem}._searchHints_royne_193{display:flex;align-items:center;gap:1.5rem;padding:.75rem 1.25rem;border-top:1px solid var(--border);background:var(--secondary);font-size:.8rem;color:var(--muted-foreground)}@media(max-width:768px){._searchHints_royne_193{flex-direction:column;align-items:flex-start;gap:.5rem}}._searchHints_royne_193 ._hint_royne_210{display:flex;align-items:center;gap:.5rem}._searchHints_royne_193 ._hint_royne_210 kbd{padding:.125rem .375rem;background:var(--card);border:1px solid var(--border);border-radius:.25rem;font-size:.75rem;font-family:monospace;min-width:1.5rem;text-align:center}._header_15xr7_1{position:sticky;top:0;z-index:1020;background-color:#fffc;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);height:3.5rem;padding-left:16rem}.dark ._header_15xr7_1{background-color:#2020201a}@supports not (backdrop-filter: blur(12px)){._header_15xr7_1{background-color:var(--background)}}@media(max-width:767px){._header_15xr7_1{padding:0}}._container_15xr7_24{width:100%;max-width:1400px;margin:0 auto;padding:0 1.5rem}@media(max-width:767px){._container_15xr7_24{padding:0 1rem}}._content_15xr7_36{display:flex;align-items:center;justify-content:space-between;height:3.5rem}._leftSection_15xr7_43{display:flex;align-items:center;gap:1rem}._mobileMenuButton_15xr7_49{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:.5rem;font-size:.875rem;font-weight:500;transition:.15s cubic-bezier(.4,0,.2,1);cursor:pointer;border:none;outline:none}._mobileMenuButton_15xr7_49:focus-visible{outline:2px solid var(--ring);outline-offset:2px}._mobileMenuButton_15xr7_49:disabled{pointer-events:none;opacity:.5}._mobileMenuButton_15xr7_49{padding:.5rem;background-color:transparent;color:var(--muted-foreground);border-radius:.5rem;display:none}._mobileMenuButton_15xr7_49:hover{background-color:var(--muted);color:var(--foreground)}@media(max-width:767px){._mobileMenuButton_15xr7_49{display:flex}}._burgerIcon_15xr7_87{width:1.25rem;height:1.25rem}._logo_15xr7_92,._nav_15xr7_98{display:flex;align-items:center;gap:.5rem}@media(max-width:767px){._nav_15xr7_98{gap:.25rem}}._navLink_15xr7_109{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem 1rem;border-radius:.5rem;font-size:.875rem;font-weight:500;color:var(--muted-foreground);text-decoration:none;transition:all .15s cubic-bezier(.4,0,.2,1)}._navLink_15xr7_109:hover{color:var(--foreground)}._navLink_15xr7_109:focus{outline:none}._githubIcon_15xr7_128{width:1rem;height:1rem;flex-shrink:0;transition:transform .15s cubic-bezier(.4,0,.2,1)}._externalIcon_15xr7_135{width:1rem;height:1rem;flex-shrink:0}._supportDropdown_15xr7_141,._themeDropdown_15xr7_145{position:relative}._themeButton_15xr7_149{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem;border-radius:.5rem;font-size:.875rem;font-weight:500;color:var(--muted-foreground);background:none;border:none;cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1)}._themeButton_15xr7_149:hover{color:var(--foreground);background-color:var(--muted)}._themeButton_15xr7_149:focus{outline:none}._themeIcon_15xr7_171{width:1.125rem;height:1.125rem;flex-shrink:0}._supportButton_15xr7_177{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem 1rem;border-radius:.5rem;font-size:.875rem;font-weight:500;color:var(--muted-foreground);background:none;border:none;cursor:pointer;transition:all .15s cubic-bezier(.4,0,.2,1)}._supportButton_15xr7_177:hover{color:var(--foreground)}._supportButton_15xr7_177:focus{outline:none}._caretIcon_15xr7_198{width:.875rem;height:.875rem;flex-shrink:0;transition:transform .15s cubic-bezier(.4,0,.2,1)}button[aria-expanded=true] ._caretIcon_15xr7_198{transform:rotate(180deg)}._dropdownMenu_15xr7_208{position:absolute;top:calc(100% + .25rem);right:0;min-width:10rem;background-color:var(--popover);border:1px solid var(--border);border-radius:.5rem;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;z-index:1000;overflow:hidden}._dropdownItem_15xr7_221{display:flex;align-items:center;gap:.5rem;width:100%;padding:.5rem 1rem;font-size:.875rem;color:var(--popover-foreground);text-decoration:none;background:none;border:none;cursor:pointer;text-align:left;transition:background-color .15s cubic-bezier(.4,0,.2,1)}._dropdownItem_15xr7_221:hover{background-color:var(--muted)}._dropdownItem_15xr7_221:focus{outline:none;background-color:var(--muted)}._dropdownIcon_15xr7_244{width:1rem;height:1rem;flex-shrink:0}@media(max-width:767px){._logoText_15xr7_251{font-size:1rem}._navLink_15xr7_109{padding:.25rem .5rem;font-size:.8rem;gap:.25rem}._githubIcon_15xr7_128{width:.875rem;height:.875rem}}._backdrop_17kcj_1{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#00000080;z-index:1040;opacity:0;visibility:hidden;transition:all .15s cubic-bezier(.4,0,.2,1)}._backdrop_17kcj_1._open_17kcj_13{opacity:1;visibility:visible}._mobileMenu_17kcj_18{position:fixed;top:0;left:0;width:320px;height:100vh;background-color:var(--background);border-right:1px solid var(--border);z-index:1050;transform:translate(-100%);transition:transform .15s cubic-bezier(.4,0,.2,1);display:flex;flex-direction:column;overflow:hidden}._mobileMenu_17kcj_18._open_17kcj_13{transform:translate(0)}._header_17kcj_37{display:flex;align-items:center;justify-content:space-between;padding:1.5rem;border-bottom:1px solid var(--border);flex-shrink:0}._brand_17kcj_46{flex:1;display:flex;align-items:center;gap:.5rem}._cloudIcon_17kcj_53{width:1.5rem;height:1.5rem;flex-shrink:0}._cloudIcon_17kcj_53 .accent{fill:#d33079}._title_17kcj_62{font-size:1.125rem;font-weight:600;color:var(--foreground);margin:0}._closeButton_17kcj_69{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:.5rem;font-size:.875rem;font-weight:500;transition:.15s cubic-bezier(.4,0,.2,1);cursor:pointer;border:none;outline:none}._closeButton_17kcj_69:focus-visible{outline:2px solid var(--ring);outline-offset:2px}._closeButton_17kcj_69:disabled{pointer-events:none;opacity:.5}._closeButton_17kcj_69{padding:.5rem;background-color:transparent;color:var(--muted-foreground);border-radius:.5rem}._closeButton_17kcj_69:hover{background-color:var(--muted);color:var(--foreground)}._closeIcon_17kcj_101{width:1.25rem;height:1.25rem}._languageSection_17kcj_106{padding:1.5rem;border-bottom:1px solid var(--border);flex-shrink:0}._languageSelect_17kcj_112{position:relative;width:100%}._languageButton_17kcj_117{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:.5rem;font-size:.875rem;font-weight:500;transition:.15s cubic-bezier(.4,0,.2,1);cursor:pointer;border:none;outline:none}._languageButton_17kcj_117:focus-visible{outline:2px solid var(--ring);outline-offset:2px}._languageButton_17kcj_117:disabled{pointer-events:none;opacity:.5}._languageButton_17kcj_117{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.5rem 1rem;background-color:var(--background);border:1px solid var(--border);color:var(--foreground);gap:.5rem}._languageButton_17kcj_117:hover,._languageButton_17kcj_117[aria-expanded=true]{background-color:var(--muted)}._icon_17kcj_156{width:1rem;height:1rem;flex-shrink:0}._chevron_17kcj_162{width:1rem;height:1rem;transition:transform .15s cubic-bezier(.4,0,.2,1);margin-left:auto}._languageButton_17kcj_117[aria-expanded=true] ._chevron_17kcj_162{transform:rotate(180deg)}._languageDropdown_17kcj_172{position:absolute;top:100%;left:0;right:0;background-color:var(--popover);border:1px solid var(--border);border-radius:.5rem;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;z-index:1000;margin-top:.25rem}._languageOption_17kcj_185{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:.5rem;font-size:.875rem;font-weight:500;transition:.15s cubic-bezier(.4,0,.2,1);cursor:pointer;border:none;outline:none}._languageOption_17kcj_185:focus-visible{outline:2px solid var(--ring);outline-offset:2px}._languageOption_17kcj_185:disabled{pointer-events:none;opacity:.5}._languageOption_17kcj_185{width:100%;padding:.5rem 1rem;background-color:transparent;color:var(--foreground);text-align:left;justify-content:flex-start;border-radius:0}._languageOption_17kcj_185:first-child{border-top-left-radius:.5rem;border-top-right-radius:.5rem}._languageOption_17kcj_185:last-child{border-bottom-left-radius:.5rem;border-bottom-right-radius:.5rem}._languageOption_17kcj_185:hover{background-color:var(--muted)}._languageOption_17kcj_185._selected_17kcj_226{background-color:var(--accent);color:var(--accent-foreground)}._scrollArea_17kcj_231{flex:1;overflow-y:auto;padding:1.5rem 0}._navigation_17kcj_237{padding:0 1.5rem}._section_17kcj_241{margin-bottom:1rem}._sectionButton_17kcj_245{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:.5rem;font-size:.875rem;font-weight:500;transition:.15s cubic-bezier(.4,0,.2,1);cursor:pointer;border:none;outline:none}._sectionButton_17kcj_245:focus-visible{outline:2px solid var(--ring);outline-offset:2px}._sectionButton_17kcj_245:disabled{pointer-events:none;opacity:.5}._sectionButton_17kcj_245{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.5rem 1rem;background-color:transparent;color:var(--foreground);font-weight:600;gap:.5rem;border-radius:.5rem}._sectionButton_17kcj_245:hover{background-color:var(--muted)}._sectionButton_17kcj_245 ._icon_17kcj_156{transition:transform .15s cubic-bezier(.4,0,.2,1);margin-left:auto}._sectionButton_17kcj_245._expanded_17kcj_285 ._icon_17kcj_156{transform:rotate(90deg)}._sectionItems_17kcj_289{margin-top:.5rem;margin-left:1rem;display:flex;flex-direction:column;gap:.25rem}._navItem_17kcj_297{display:block;padding:.5rem 1rem;border-radius:.5rem;color:var(--muted-foreground);text-decoration:none;transition:all .15s cubic-bezier(.4,0,.2,1);font-size:.875rem}._navItem_17kcj_297:hover{background-color:var(--muted);color:var(--foreground)}._navItem_17kcj_297._active_17kcj_310{background-color:var(--accent);color:var(--accent-foreground);font-weight:500}._navItemContent_17kcj_316{display:flex;align-items:center;gap:.5rem}._navItemTitle_17kcj_322{flex:1}@media(min-width:1024px){._mobileMenu_17kcj_18,._backdrop_17kcj_1{display:none}}._sidebar_1pfbz_1{position:fixed;top:0;left:0;width:16rem;height:100vh;background-color:var(--sidebar);overflow-y:auto;z-index:1020}@media(max-width:767px){._sidebar_1pfbz_1{display:none}}._header_1pfbz_17{position:sticky;top:0;z-index:1020;padding:1rem;background-color:var(--sidebar);display:flex;flex-direction:column;gap:.5rem;padding-bottom:0}._brand_1pfbz_29{display:flex;align-items:center;gap:.5rem}._cloudIcon_1pfbz_35{width:1.5rem;height:1.5rem;flex-shrink:0}._cloudIcon_1pfbz_35 .accent{fill:#d33079}._title_1pfbz_44{font-size:1rem;font-weight:600;color:var(--foreground);margin:0;letter-spacing:-.02em}._languageSelect_1pfbz_52{position:relative;margin-top:.25rem;width:100%}._languageButton_1pfbz_58{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:.5rem;font-size:.875rem;font-weight:500;transition:.15s cubic-bezier(.4,0,.2,1);cursor:pointer;border:none;outline:none}._languageButton_1pfbz_58:focus-visible{outline:2px solid var(--ring);outline-offset:2px}._languageButton_1pfbz_58:disabled{pointer-events:none;opacity:.5}._languageButton_1pfbz_58{display:flex;align-items:center;justify-content:space-between;padding:.25rem .5rem;width:100%;gap:.25rem;font-size:.8rem;background:transparent;border:1px solid var(--border);border-radius:.25rem;color:var(--muted-foreground)}._languageButton_1pfbz_58:hover{background-color:var(--muted);color:var(--foreground)}._languageButton_1pfbz_58 ._icon_1pfbz_96{width:.875rem;height:.875rem;flex-shrink:0}._languageButton_1pfbz_58 ._chevron_1pfbz_101{width:.875rem;height:.875rem;flex-shrink:0;transition:transform .15s cubic-bezier(.4,0,.2,1)}._languageButton_1pfbz_58[aria-expanded=true] ._chevron_1pfbz_101{transform:rotate(180deg)}._languageDropdown_1pfbz_111{position:absolute;top:100%;left:0;right:0;margin-top:.25rem;background-color:var(--popover);border:1px solid var(--border);border-radius:.5rem;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;z-index:1000;overflow:hidden}._languageOption_1pfbz_125{display:block;width:100%;padding:.25rem .5rem;text-align:left;background:none;border:none;color:var(--popover-foreground);font-size:.85rem;cursor:pointer;transition:background-color .15s cubic-bezier(.4,0,.2,1)}._languageOption_1pfbz_125:hover{background-color:var(--muted)}._languageOption_1pfbz_125:focus{outline:none;background-color:var(--muted)}._languageOption_1pfbz_125._selected_1pfbz_144{background-color:var(--muted);color:var(--foreground)}._scrollArea_1pfbz_149{height:calc(100vh - 120px);padding:1rem .5rem 1rem 1rem;overflow-y:auto}._navigation_1pfbz_155{display:flex;flex-direction:column;gap:.125rem}._section_1pfbz_161{display:flex;flex-direction:column;gap:0}._sectionButton_1pfbz_167{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:.5rem;font-size:.875rem;font-weight:500;transition:.15s cubic-bezier(.4,0,.2,1);cursor:pointer;border:none;outline:none}._sectionButton_1pfbz_167:focus-visible{outline:2px solid var(--ring);outline-offset:2px}._sectionButton_1pfbz_167:disabled{pointer-events:none;opacity:.5}._sectionButton_1pfbz_167{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.25rem .5rem;font-weight:500;font-size:.85rem;color:var(--muted-foreground);background:transparent;text-align:left;letter-spacing:-.01em;border:none}._sectionButton_1pfbz_167:hover{color:var(--foreground)}._sectionButton_1pfbz_167 ._icon_1pfbz_96{width:.875rem;height:.875rem;transition:transform .15s cubic-bezier(.4,0,.2,1)}._sectionButton_1pfbz_167._expanded_1pfbz_210 ._icon_1pfbz_96{transform:rotate(90deg)}._sectionItems_1pfbz_214{margin-top:.25rem;padding-left:1rem;display:flex;flex-direction:column;gap:.125rem}._navItem_1pfbz_222{display:block;width:100%;padding:.25rem .5rem;border-radius:.25rem;font-size:.85rem;color:var(--muted-foreground);text-decoration:none;transition:color .15s cubic-bezier(.4,0,.2,1)}._navItem_1pfbz_222:hover{color:var(--foreground)}._navItem_1pfbz_222._active_1pfbz_235{color:var(--foreground);font-weight:500}._navItemContent_1pfbz_240{display:flex;align-items:center;justify-content:space-between;width:100%}._sidebar_1pfbz_1::-webkit-scrollbar{width:6px}._sidebar_1pfbz_1::-webkit-scrollbar-track{background:transparent}._sidebar_1pfbz_1::-webkit-scrollbar-thumb{background:var(--muted-foreground);border-radius:9999px;opacity:.3}._sidebar_1pfbz_1::-webkit-scrollbar-thumb:hover{opacity:.6}._app_1vinw_1{min-height:100vh;background-color:var(--background);color:var(--foreground);display:flex;flex-direction:column}._layout_1vinw_9{display:flex;flex:1;min-height:calc(100vh - 3.5rem)}._main_1vinw_15{flex:1;display:flex;flex-direction:column;margin-left:16rem}@media(max-width:767px){._main_1vinw_15{margin-left:0}}._contentWrapper_1vinw_27{display:flex;flex:1;position:relative;width:100%;max-width:80rem;margin:0 auto;padding:2rem}@media(max-width:1024px){._contentWrapper_1vinw_27{padding:1.5rem}}@media(max-width:767px){._contentWrapper_1vinw_27{padding:1rem}}
|