@refrakt-md/lumina 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/base.css +18 -0
  2. package/contracts/structures.json +1360 -3
  3. package/dist/config.d.ts +2 -3
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +6 -229
  6. package/dist/config.js.map +1 -1
  7. package/dist/icons.d.ts +3 -0
  8. package/dist/icons.d.ts.map +1 -0
  9. package/dist/icons.js +86 -0
  10. package/dist/icons.js.map +1 -0
  11. package/dist/transform.d.ts +2 -0
  12. package/dist/transform.d.ts.map +1 -1
  13. package/dist/transform.js +2 -0
  14. package/dist/transform.js.map +1 -1
  15. package/index.css +12 -0
  16. package/package.json +18 -11
  17. package/styles/elements/blockquote.css +8 -4
  18. package/styles/elements/code.css +40 -0
  19. package/styles/global.css +0 -7
  20. package/styles/layouts/blog.css +267 -0
  21. package/styles/layouts/default.css +26 -6
  22. package/styles/layouts/docs.css +84 -18
  23. package/styles/layouts/mobile.css +84 -0
  24. package/styles/runes/bento.css +2 -0
  25. package/styles/runes/codegroup.css +7 -2
  26. package/styles/runes/design-context.css +25 -0
  27. package/styles/runes/feature.css +30 -14
  28. package/styles/runes/form.css +1 -2
  29. package/styles/runes/grid.css +25 -7
  30. package/styles/runes/hero.css +15 -0
  31. package/styles/runes/map.css +113 -0
  32. package/styles/runes/palette.css +91 -0
  33. package/styles/runes/preview.css +188 -0
  34. package/styles/runes/sandbox.css +23 -0
  35. package/styles/runes/spacing.css +110 -0
  36. package/styles/runes/steps.css +21 -3
  37. package/styles/runes/swatch.css +28 -0
  38. package/styles/runes/symbol.css +164 -0
  39. package/styles/runes/tabs.css +6 -0
  40. package/styles/runes/testimonial.css +2 -3
  41. package/styles/runes/timeline.css +43 -24
  42. package/styles/runes/typography.css +104 -0
  43. package/svelte/elements.ts +1 -0
  44. package/{sveltekit → svelte}/index.ts +0 -8
  45. package/svelte/layouts/BlogLayout.svelte +173 -0
  46. package/svelte/layouts/DefaultLayout.svelte +67 -0
  47. package/svelte/layouts/DocsLayout.svelte +155 -0
  48. package/{sveltekit → svelte}/manifest.json +1 -1
  49. package/svelte/registry.ts +2 -0
  50. package/svelte/tokens.css +6 -0
  51. package/dist/lib/engine.d.ts +0 -13
  52. package/dist/lib/engine.d.ts.map +0 -1
  53. package/dist/lib/engine.js +0 -218
  54. package/dist/lib/engine.js.map +0 -1
  55. package/dist/lib/helpers.d.ts +0 -14
  56. package/dist/lib/helpers.d.ts.map +0 -1
  57. package/dist/lib/helpers.js +0 -26
  58. package/dist/lib/helpers.js.map +0 -1
  59. package/dist/lib/types.d.ts +0 -74
  60. package/dist/lib/types.d.ts.map +0 -1
  61. package/dist/lib/types.js +0 -2
  62. package/dist/lib/types.js.map +0 -1
  63. package/sveltekit/components/Accordion.svelte +0 -26
  64. package/sveltekit/components/Bento.svelte +0 -50
  65. package/sveltekit/components/Chart.svelte +0 -121
  66. package/sveltekit/components/CodeGroup.svelte +0 -88
  67. package/sveltekit/components/Comparison.svelte +0 -209
  68. package/sveltekit/components/DataTable.svelte +0 -154
  69. package/sveltekit/components/Details.svelte +0 -23
  70. package/sveltekit/components/Diagram.svelte +0 -45
  71. package/sveltekit/components/Embed.svelte +0 -36
  72. package/sveltekit/components/Form.svelte +0 -194
  73. package/sveltekit/components/Grid.svelte +0 -42
  74. package/sveltekit/components/Nav.svelte +0 -62
  75. package/sveltekit/components/Pricing.svelte +0 -20
  76. package/sveltekit/components/Reveal.svelte +0 -62
  77. package/sveltekit/components/Storyboard.svelte +0 -41
  78. package/sveltekit/components/Tabs.svelte +0 -75
  79. package/sveltekit/components/Testimonial.svelte +0 -26
  80. package/sveltekit/elements/Blockquote.svelte +0 -37
  81. package/sveltekit/elements/Pre.svelte +0 -77
  82. package/sveltekit/elements/Table.svelte +0 -40
  83. package/sveltekit/elements.ts +0 -11
  84. package/sveltekit/layouts/BlogLayout.svelte +0 -382
  85. package/sveltekit/layouts/DefaultLayout.svelte +0 -70
  86. package/sveltekit/layouts/DocsLayout.svelte +0 -133
  87. package/sveltekit/registry.ts +0 -59
  88. package/sveltekit/tokens.css +0 -71
@@ -1,77 +0,0 @@
1
- <script lang="ts">
2
- import type { SerializedTag } from '@refrakt-md/svelte';
3
- import type { Snippet } from 'svelte';
4
-
5
- let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
6
-
7
- const isCodeBlock = 'data-language' in (tag.attributes || {});
8
-
9
- let preEl: HTMLPreElement;
10
- let copied = $state(false);
11
- let timer: ReturnType<typeof setTimeout>;
12
-
13
- function copy() {
14
- const text = preEl.textContent ?? '';
15
- navigator.clipboard.writeText(text);
16
- copied = true;
17
- clearTimeout(timer);
18
- timer = setTimeout(() => copied = false, 2000);
19
- }
20
- </script>
21
-
22
- {#if isCodeBlock}
23
- <div class="rf-codeblock">
24
- <pre bind:this={preEl} {...tag.attributes}>{@render children()}</pre>
25
- <button class="rf-codeblock__copy" class:rf-codeblock__copy--copied={copied} onclick={copy} aria-label="Copy code">
26
- {#if copied}
27
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
28
- <polyline points="20 6 9 17 4 12" />
29
- </svg>
30
- {:else}
31
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
32
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
33
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
34
- </svg>
35
- {/if}
36
- </button>
37
- </div>
38
- {:else}
39
- <pre {...tag.attributes}>{@render children()}</pre>
40
- {/if}
41
-
42
- <style>
43
- .rf-codeblock {
44
- position: relative;
45
- }
46
- .rf-codeblock :global(pre) {
47
- margin: 0;
48
- }
49
- .rf-codeblock__copy {
50
- position: absolute;
51
- top: 0.5rem;
52
- right: 0.5rem;
53
- display: flex;
54
- align-items: center;
55
- justify-content: center;
56
- width: 2rem;
57
- height: 2rem;
58
- border: none;
59
- border-radius: var(--rf-radius-sm);
60
- background: transparent;
61
- color: var(--rf-color-code-text, #e2e8f0);
62
- cursor: pointer;
63
- opacity: 0;
64
- transition: opacity 150ms ease, background-color 150ms ease;
65
- }
66
- .rf-codeblock:hover .rf-codeblock__copy {
67
- opacity: 0.6;
68
- }
69
- .rf-codeblock__copy:hover {
70
- opacity: 1 !important;
71
- background: rgba(255, 255, 255, 0.1);
72
- }
73
- .rf-codeblock__copy--copied {
74
- opacity: 1 !important;
75
- color: var(--rf-color-success, #4ade80);
76
- }
77
- </style>
@@ -1,40 +0,0 @@
1
- <script lang="ts">
2
- import type { SerializedTag } from '@refrakt-md/svelte';
3
- import type { Snippet } from 'svelte';
4
-
5
- let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
6
- </script>
7
-
8
- <div class="table-wrapper">
9
- <table {...tag.attributes}>
10
- {@render children()}
11
- </table>
12
- </div>
13
-
14
- <style>
15
- .table-wrapper {
16
- overflow-x: auto;
17
- -webkit-overflow-scrolling: touch;
18
- margin: 1.5rem 0;
19
- border: 1px solid var(--color-border);
20
- border-radius: var(--radius-md);
21
- }
22
- .table-wrapper :global(table) {
23
- margin: 0;
24
- border-collapse: collapse;
25
- width: 100%;
26
- min-width: 100%;
27
- }
28
- .table-wrapper :global(th) {
29
- background: var(--color-surface);
30
- }
31
- .table-wrapper :global(th:first-child) {
32
- border-top-left-radius: var(--radius-md);
33
- }
34
- .table-wrapper :global(th:last-child) {
35
- border-top-right-radius: var(--radius-md);
36
- }
37
- .table-wrapper :global(tr:last-child td) {
38
- border-bottom: none;
39
- }
40
- </style>
@@ -1,11 +0,0 @@
1
- import type { ElementOverrides } from '@refrakt-md/svelte';
2
- import Table from './elements/Table.svelte';
3
- import Blockquote from './elements/Blockquote.svelte';
4
- import Pre from './elements/Pre.svelte';
5
-
6
- /** Maps HTML element names to Lumina theme override components */
7
- export const elements: ElementOverrides = {
8
- 'table': Table,
9
- 'blockquote': Blockquote,
10
- 'pre': Pre,
11
- };
@@ -1,382 +0,0 @@
1
- <script lang="ts">
2
- import { Renderer } from '@refrakt-md/svelte';
3
-
4
- let { title, frontmatter, regions, renderable, pages }: {
5
- title: string;
6
- description: string;
7
- frontmatter?: Record<string, unknown>;
8
- regions: Record<string, { name: string; mode: string; content: any[] }>;
9
- renderable: any;
10
- pages: Array<{
11
- url: string;
12
- title: string;
13
- draft: boolean;
14
- description?: string;
15
- date?: string;
16
- author?: string;
17
- tags?: string[];
18
- image?: string;
19
- }>;
20
- } = $props();
21
-
22
- const date = $derived(frontmatter?.date as string | undefined);
23
- const author = $derived(frontmatter?.author as string | undefined);
24
- const tags = $derived(frontmatter?.tags as string[] | undefined);
25
-
26
- // Index page has no date; individual posts always have one
27
- const isIndex = $derived(!date);
28
-
29
- const posts = $derived(
30
- isIndex
31
- ? pages
32
- .filter(p => p.url.startsWith('/blog/') && p.url !== '/blog' && !p.draft && p.date)
33
- .sort((a, b) => (b.date ?? '').localeCompare(a.date ?? ''))
34
- : []
35
- );
36
-
37
- const hasSidebar = $derived(!!regions.sidebar);
38
-
39
- function formatDate(iso: string): string {
40
- const d = new Date(iso + 'T00:00:00');
41
- return d.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
42
- }
43
- </script>
44
-
45
- {#if regions.header}
46
- <header class="site-header">
47
- <div class="site-header-inner">
48
- <Renderer node={regions.header.content} />
49
- </div>
50
- </header>
51
- {/if}
52
-
53
- <div class="blog-layout" class:has-sidebar={hasSidebar}>
54
- {#if isIndex}
55
- <div class="blog-index">
56
- <h1 class="blog-index-title">{title}</h1>
57
-
58
- <div class="blog-index-body">
59
- <Renderer node={renderable} />
60
- </div>
61
-
62
- <div class="blog-index-posts">
63
- {#each posts as post}
64
- <a href={post.url} class="blog-post-card">
65
- <h2 class="blog-post-card-title">{post.title}</h2>
66
- <div class="blog-post-card-meta">
67
- {#if post.date}
68
- <time datetime={post.date}>{formatDate(post.date)}</time>
69
- {/if}
70
- {#if post.author}
71
- <span class="blog-post-card-author">{post.author}</span>
72
- {/if}
73
- </div>
74
- {#if post.description}
75
- <p class="blog-post-card-desc">{post.description}</p>
76
- {/if}
77
- {#if post.tags && post.tags.length > 0}
78
- <div class="blog-post-card-tags">
79
- {#each post.tags as tag}
80
- <span class="blog-article-tag">{tag}</span>
81
- {/each}
82
- </div>
83
- {/if}
84
- <span class="blog-post-card-link">Read more &rarr;</span>
85
- </a>
86
- {/each}
87
- </div>
88
- </div>
89
- {:else}
90
- <article class="blog-article">
91
- <header class="blog-article-header">
92
- <h1 class="blog-article-title">{title}</h1>
93
- {#if date || author}
94
- <div class="blog-article-meta">
95
- {#if date}
96
- <time datetime={date}>{formatDate(date)}</time>
97
- {/if}
98
- {#if author}
99
- <span class="blog-article-author">{author}</span>
100
- {/if}
101
- </div>
102
- {/if}
103
- {#if tags && tags.length > 0}
104
- <div class="blog-article-tags">
105
- {#each tags as tag}
106
- <span class="blog-article-tag">{tag}</span>
107
- {/each}
108
- </div>
109
- {/if}
110
- </header>
111
-
112
- <div class="blog-article-body">
113
- <Renderer node={renderable} />
114
- </div>
115
- </article>
116
-
117
- {#if regions.sidebar}
118
- <aside class="blog-sidebar">
119
- <Renderer node={regions.sidebar.content} />
120
- </aside>
121
- {/if}
122
- {/if}
123
- </div>
124
-
125
- {#if regions.footer}
126
- <footer class="site-footer">
127
- <Renderer node={regions.footer.content} />
128
- </footer>
129
- {/if}
130
-
131
- <style>
132
- /* ---- Site header (shared with other layouts) ---- */
133
- .site-header {
134
- border-bottom: 1px solid var(--color-border);
135
- }
136
- .site-header-inner {
137
- display: flex;
138
- align-items: center;
139
- justify-content: space-between;
140
- padding: 0.875rem 1.5rem;
141
- }
142
- .site-header :global(p) {
143
- margin: 0;
144
- line-height: 1;
145
- }
146
- .site-header :global(a) {
147
- display: inline-block;
148
- color: inherit;
149
- text-decoration: none;
150
- }
151
- .site-header :global(a:hover) {
152
- text-decoration: none;
153
- }
154
- .site-header :global(img) {
155
- display: block;
156
- height: 1.5rem;
157
- width: auto;
158
- }
159
- .site-header-inner :global(p:last-child:not(:first-child)) {
160
- font-size: 0.85rem;
161
- }
162
- .site-header-inner :global(p:last-child:not(:first-child) a) {
163
- margin-left: 1.5rem;
164
- color: var(--color-muted);
165
- }
166
- .site-header-inner :global(p:last-child:not(:first-child) a:hover) {
167
- color: var(--color-text);
168
- }
169
-
170
- /* ---- Blog layout ---- */
171
- .blog-layout {
172
- max-width: 72rem;
173
- margin: 0 auto;
174
- padding: 2.5rem 1.5rem 4rem;
175
- }
176
- .blog-layout.has-sidebar {
177
- display: grid;
178
- grid-template-columns: 1fr 16rem;
179
- gap: 3rem;
180
- align-items: start;
181
- }
182
-
183
- /* ---- Blog index ---- */
184
- .blog-index {
185
- max-width: 42rem;
186
- }
187
- .blog-index-title {
188
- font-size: 2.25rem;
189
- font-weight: 800;
190
- line-height: 1.15;
191
- letter-spacing: -0.02em;
192
- margin: 0 0 1rem;
193
- color: var(--color-text);
194
- }
195
- .blog-index-body {
196
- margin-bottom: 2rem;
197
- line-height: 1.8;
198
- color: var(--color-muted);
199
- }
200
- .blog-index-body:empty {
201
- display: none;
202
- }
203
- .blog-index-posts {
204
- display: flex;
205
- flex-direction: column;
206
- gap: 1.5rem;
207
- }
208
-
209
- /* ---- Post card ---- */
210
- .blog-post-card {
211
- display: block;
212
- padding: 1.5rem;
213
- border: 1px solid var(--color-border);
214
- border-radius: var(--radius-md, 0.5rem);
215
- text-decoration: none;
216
- color: inherit;
217
- transition: border-color 0.15s, box-shadow 0.15s;
218
- }
219
- .blog-post-card:hover {
220
- border-color: var(--color-text);
221
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
222
- text-decoration: none;
223
- }
224
- .blog-post-card-title {
225
- font-size: 1.35rem;
226
- font-weight: 700;
227
- margin: 0 0 0.5rem;
228
- color: var(--color-text);
229
- }
230
- .blog-post-card-meta {
231
- display: flex;
232
- align-items: center;
233
- gap: 0.75rem;
234
- font-size: 0.85rem;
235
- color: var(--color-muted);
236
- margin-bottom: 0.5rem;
237
- }
238
- .blog-post-card-author::before {
239
- content: '\00b7';
240
- margin-right: 0.75rem;
241
- }
242
- .blog-post-card-desc {
243
- margin: 0 0 0.75rem;
244
- font-size: 0.95rem;
245
- line-height: 1.6;
246
- color: var(--color-muted);
247
- }
248
- .blog-post-card-tags {
249
- display: flex;
250
- flex-wrap: wrap;
251
- gap: 0.5rem;
252
- margin-bottom: 0.75rem;
253
- }
254
- .blog-post-card-link {
255
- font-size: 0.85rem;
256
- font-weight: 600;
257
- color: var(--color-primary, var(--color-text));
258
- }
259
-
260
- /* ---- Article ---- */
261
- .blog-article {
262
- max-width: 42rem;
263
- }
264
- .blog-article-header {
265
- margin-bottom: 2.5rem;
266
- padding-bottom: 1.5rem;
267
- border-bottom: 1px solid var(--color-border);
268
- }
269
- .blog-article-title {
270
- font-size: 2.25rem;
271
- font-weight: 800;
272
- line-height: 1.15;
273
- letter-spacing: -0.02em;
274
- margin: 0 0 1rem;
275
- color: var(--color-text);
276
- }
277
- .blog-article-meta {
278
- display: flex;
279
- align-items: center;
280
- gap: 0.75rem;
281
- font-size: 0.9rem;
282
- color: var(--color-muted);
283
- }
284
- .blog-article-meta time {
285
- font-weight: 500;
286
- }
287
- .blog-article-author::before {
288
- content: '\00b7';
289
- margin-right: 0.75rem;
290
- }
291
- .blog-article-tags {
292
- display: flex;
293
- flex-wrap: wrap;
294
- gap: 0.5rem;
295
- margin-top: 0.75rem;
296
- }
297
- .blog-article-tag {
298
- font-size: 0.75rem;
299
- font-weight: 500;
300
- padding: 0.2rem 0.6rem;
301
- border-radius: 9999px;
302
- background: var(--color-surface);
303
- color: var(--color-muted);
304
- border: 1px solid var(--color-border);
305
- }
306
-
307
- /* ---- Article body typography ---- */
308
- .blog-article-body {
309
- line-height: 1.8;
310
- }
311
- .blog-article-body :global(h2) {
312
- margin-top: 2.5rem;
313
- }
314
- .blog-article-body :global(h3) {
315
- margin-top: 2rem;
316
- }
317
- .blog-article-body :global(p) {
318
- margin-bottom: 1.25rem;
319
- }
320
- .blog-article-body :global(img) {
321
- border-radius: var(--radius-md);
322
- margin: 1.5rem 0;
323
- }
324
-
325
- /* ---- Sidebar ---- */
326
- .blog-sidebar {
327
- position: sticky;
328
- top: 2.5rem;
329
- font-size: 0.85rem;
330
- color: var(--color-muted);
331
- }
332
- .blog-sidebar :global(h2),
333
- .blog-sidebar :global(h3),
334
- .blog-sidebar :global(h4) {
335
- font-size: 0.75rem;
336
- font-weight: 600;
337
- text-transform: uppercase;
338
- letter-spacing: 0.05em;
339
- color: var(--color-muted);
340
- margin-top: 0;
341
- margin-bottom: 0.5rem;
342
- }
343
- .blog-sidebar :global(ul) {
344
- list-style: none;
345
- padding: 0;
346
- margin: 0;
347
- }
348
- .blog-sidebar :global(li) {
349
- padding: 0.25rem 0;
350
- }
351
- .blog-sidebar :global(a) {
352
- color: var(--color-muted);
353
- text-decoration: none;
354
- }
355
- .blog-sidebar :global(a:hover) {
356
- color: var(--color-text);
357
- }
358
-
359
- /* ---- Footer ---- */
360
- .site-footer {
361
- border-top: 1px solid var(--color-border);
362
- padding: 2rem 1.5rem;
363
- text-align: center;
364
- font-size: 0.85rem;
365
- color: var(--color-muted);
366
- }
367
-
368
- /* ---- Mobile ---- */
369
- @media (max-width: 768px) {
370
- .blog-layout.has-sidebar {
371
- grid-template-columns: 1fr;
372
- }
373
- .blog-article-title {
374
- font-size: 1.75rem;
375
- }
376
- .blog-sidebar {
377
- position: static;
378
- border-top: 1px solid var(--color-border);
379
- padding-top: 1.5rem;
380
- }
381
- }
382
- </style>
@@ -1,70 +0,0 @@
1
- <script lang="ts">
2
- import { Renderer } from '@refrakt-md/svelte';
3
-
4
- let { regions, renderable }: {
5
- title: string;
6
- description: string;
7
- regions: Record<string, { name: string; mode: string; content: any[] }>;
8
- renderable: any;
9
- pages: any[];
10
- } = $props();
11
- </script>
12
-
13
- {#if regions.header}
14
- <header class="site-header">
15
- <div class="site-header-inner">
16
- <Renderer node={regions.header.content} />
17
- </div>
18
- </header>
19
- {/if}
20
-
21
- <main class="page-content">
22
- <Renderer node={renderable} />
23
- </main>
24
-
25
- <style>
26
- .site-header {
27
- border-bottom: 1px solid var(--color-border);
28
- }
29
- .site-header-inner {
30
- display: flex;
31
- align-items: center;
32
- justify-content: space-between;
33
- padding: 0.875rem 1.5rem;
34
- }
35
- .site-header :global(p) {
36
- margin: 0;
37
- line-height: 1;
38
- }
39
- .site-header :global(a) {
40
- display: inline-block;
41
- color: inherit;
42
- text-decoration: none;
43
- }
44
- .site-header :global(a:hover) {
45
- text-decoration: none;
46
- }
47
- .site-header :global(img) {
48
- display: block;
49
- height: 1.5rem;
50
- width: auto;
51
- }
52
- .site-header-inner :global(p:last-child:not(:first-child)) {
53
- font-size: 0.85rem;
54
- }
55
- .site-header-inner :global(p:last-child:not(:first-child) a) {
56
- margin-left: 1.5rem;
57
- color: var(--color-muted);
58
- }
59
- .site-header-inner :global(p:last-child:not(:first-child) a:hover) {
60
- color: var(--color-text);
61
- }
62
- .page-content {
63
- padding-top: 2.5rem;
64
- padding-bottom: 4rem;
65
- max-width: 64rem;
66
- margin: 0 auto;
67
- padding-left: 1.5rem;
68
- padding-right: 1.5rem;
69
- }
70
- </style>
@@ -1,133 +0,0 @@
1
- <script lang="ts">
2
- import { Renderer } from '@refrakt-md/svelte';
3
-
4
- let { regions, renderable }: {
5
- title: string;
6
- description: string;
7
- regions: Record<string, { name: string; mode: string; content: any[] }>;
8
- renderable: any;
9
- pages: any[];
10
- } = $props();
11
-
12
- const hasNav = $derived(!!regions.nav);
13
- </script>
14
-
15
- {#if regions.header}
16
- <header class="site-header">
17
- <div class="site-header-inner">
18
- <Renderer node={regions.header.content} />
19
- </div>
20
- </header>
21
- {/if}
22
-
23
- {#if regions.nav}
24
- <aside class="sidebar">
25
- <Renderer node={regions.nav.content} />
26
- </aside>
27
- {/if}
28
-
29
- <main class="page-content" class:has-nav={hasNav}>
30
- <div class="page-content-inner">
31
- <Renderer node={renderable} />
32
- </div>
33
- </main>
34
-
35
- <style>
36
- /* ---- Fixed header ---- */
37
- .site-header {
38
- position: fixed;
39
- top: 0;
40
- left: 0;
41
- right: 0;
42
- z-index: 10;
43
- background: var(--color-bg, #fff);
44
- border-bottom: 1px solid var(--color-border);
45
- }
46
- .site-header-inner {
47
- display: flex;
48
- align-items: center;
49
- justify-content: space-between;
50
- padding: 0.875rem 1.5rem;
51
- }
52
- .site-header :global(p) {
53
- margin: 0;
54
- line-height: 1;
55
- }
56
- .site-header :global(a) {
57
- display: inline-block;
58
- color: inherit;
59
- text-decoration: none;
60
- }
61
- .site-header :global(a:hover) {
62
- text-decoration: none;
63
- }
64
- .site-header :global(img) {
65
- display: block;
66
- height: 1.5rem;
67
- width: auto;
68
- }
69
- .site-header-inner :global(p:last-child:not(:first-child)) {
70
- font-size: 0.85rem;
71
- }
72
- .site-header-inner :global(p:last-child:not(:first-child) a) {
73
- margin-left: 1.5rem;
74
- color: var(--color-muted);
75
- }
76
- .site-header-inner :global(p:last-child:not(:first-child) a:hover) {
77
- color: var(--color-text);
78
- }
79
-
80
- /* ---- Fixed sidebar ---- */
81
- .sidebar {
82
- position: fixed;
83
- left: 0;
84
- top: 3.375rem; /* header height */
85
- bottom: 0;
86
- width: 240px;
87
- overflow-y: auto;
88
- padding: 1.5rem;
89
- border-right: 1px solid var(--color-border);
90
- background: var(--color-bg, #fff);
91
- z-index: 5;
92
- }
93
- .sidebar::-webkit-scrollbar {
94
- width: 0;
95
- }
96
-
97
- /* ---- Content area ---- */
98
- .page-content {
99
- padding-top: 5rem; /* clears fixed header */
100
- padding-bottom: 4rem;
101
- }
102
- .page-content.has-nav {
103
- margin-left: 240px;
104
- }
105
- .page-content-inner {
106
- max-width: 60rem;
107
- margin: 0 auto;
108
- padding: 0 2.5rem;
109
- }
110
-
111
- /* ---- Mobile ---- */
112
- @media (max-width: 768px) {
113
- .site-header {
114
- position: static;
115
- }
116
- .sidebar {
117
- position: static;
118
- width: auto;
119
- border-right: none;
120
- border-bottom: 1px solid var(--color-border);
121
- padding: 1rem 1.5rem;
122
- }
123
- .page-content {
124
- padding-top: 2rem;
125
- }
126
- .page-content.has-nav {
127
- margin-left: 0;
128
- }
129
- .page-content-inner {
130
- padding: 0 1.5rem;
131
- }
132
- }
133
- </style>