toiljs 0.0.11 → 0.0.14

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 (120) hide show
  1. package/README.md +3 -1
  2. package/build/cli/.tsbuildinfo +1 -1
  3. package/build/cli/configure.js +10 -4
  4. package/build/cli/create.js +58 -30
  5. package/build/cli/diagnostics.d.ts +55 -0
  6. package/build/cli/diagnostics.js +333 -0
  7. package/build/cli/doctor.d.ts +6 -0
  8. package/build/cli/doctor.js +249 -0
  9. package/build/cli/index.js +26 -0
  10. package/build/cli/proc.d.ts +5 -0
  11. package/build/cli/proc.js +20 -0
  12. package/build/cli/ui.d.ts +1 -0
  13. package/build/cli/ui.js +1 -0
  14. package/build/cli/update.d.ts +7 -0
  15. package/build/cli/update.js +117 -0
  16. package/build/cli/updates.d.ts +10 -0
  17. package/build/cli/updates.js +45 -0
  18. package/build/client/.tsbuildinfo +1 -1
  19. package/build/client/dev/error-overlay.js +1 -1
  20. package/build/client/head/metadata.js +3 -1
  21. package/build/client/index.d.ts +5 -1
  22. package/build/client/index.js +2 -0
  23. package/build/client/navigation/navigation.js +1 -1
  24. package/build/client/routing/Router.js +2 -2
  25. package/build/client/search/search.d.ts +26 -0
  26. package/build/client/search/search.js +101 -0
  27. package/build/client/search/use-page-search.d.ts +8 -0
  28. package/build/client/search/use-page-search.js +21 -0
  29. package/build/compiler/.tsbuildinfo +1 -1
  30. package/build/compiler/generate.js +33 -24
  31. package/build/compiler/index.d.ts +2 -0
  32. package/build/compiler/index.js +1 -0
  33. package/build/compiler/pages.d.ts +8 -0
  34. package/build/compiler/pages.js +37 -0
  35. package/build/compiler/plugin.js +3 -1
  36. package/build/compiler/prerender.d.ts +1 -0
  37. package/build/compiler/prerender.js +11 -5
  38. package/build/compiler/seo.js +10 -3
  39. package/build/io/.tsbuildinfo +1 -1
  40. package/examples/basic/client/components/Header.tsx +43 -41
  41. package/examples/basic/client/components/HoneycombBackground.tsx +223 -230
  42. package/examples/basic/client/public/index.html +18 -16
  43. package/examples/basic/client/routes/(legal)/privacy.tsx +18 -19
  44. package/examples/basic/client/routes/(legal)/terms.tsx +15 -16
  45. package/examples/basic/client/routes/about.tsx +21 -22
  46. package/examples/basic/client/routes/blog/[id].tsx +26 -18
  47. package/examples/basic/client/routes/features/actions.tsx +67 -67
  48. package/examples/basic/client/routes/features/error/index.tsx +27 -27
  49. package/examples/basic/client/routes/features/head.tsx +38 -38
  50. package/examples/basic/client/routes/features/index.tsx +83 -75
  51. package/examples/basic/client/routes/features/realtime.tsx +34 -32
  52. package/examples/basic/client/routes/features/script.tsx +31 -31
  53. package/examples/basic/client/routes/features/seo.tsx +39 -39
  54. package/examples/basic/client/routes/features/template/index.tsx +20 -20
  55. package/examples/basic/client/routes/features/template/template.tsx +16 -18
  56. package/examples/basic/client/routes/gallery/@modal/(.)photo/[id].tsx +23 -23
  57. package/examples/basic/client/routes/gallery/index.tsx +42 -42
  58. package/examples/basic/client/routes/gallery/photo/[id].tsx +18 -18
  59. package/examples/basic/client/routes/get-started.tsx +157 -84
  60. package/examples/basic/client/routes/index.tsx +137 -96
  61. package/examples/basic/client/routes/loader-demo/index.tsx +59 -52
  62. package/examples/basic/client/routes/search.tsx +61 -0
  63. package/examples/basic/client/routes/test.tsx +7 -8
  64. package/examples/basic/client/styles/main.css +624 -552
  65. package/package.json +2 -2
  66. package/presets/eslint.js +10 -3
  67. package/src/cli/configure.ts +363 -353
  68. package/src/cli/create.ts +563 -530
  69. package/src/cli/diagnostics.ts +421 -0
  70. package/src/cli/doctor.ts +318 -0
  71. package/src/cli/features.ts +166 -160
  72. package/src/cli/index.ts +242 -211
  73. package/src/cli/proc.ts +30 -0
  74. package/src/cli/ui.ts +111 -103
  75. package/src/cli/update.ts +150 -0
  76. package/src/cli/updates.ts +69 -0
  77. package/src/client/components/Image.tsx +91 -89
  78. package/src/client/dev/error-overlay.tsx +193 -197
  79. package/src/client/head/metadata.ts +94 -92
  80. package/src/client/index.ts +79 -64
  81. package/src/client/navigation/Link.tsx +94 -100
  82. package/src/client/navigation/navigation.ts +215 -218
  83. package/src/client/routing/Router.tsx +210 -193
  84. package/src/client/routing/hooks.ts +110 -114
  85. package/src/client/routing/lazy.ts +77 -81
  86. package/src/client/search/search.ts +189 -0
  87. package/src/client/search/use-page-search.ts +73 -0
  88. package/src/compiler/config.ts +173 -171
  89. package/src/compiler/fonts.ts +89 -87
  90. package/src/compiler/generate.ts +45 -27
  91. package/src/compiler/image-report.ts +88 -85
  92. package/src/compiler/index.ts +2 -0
  93. package/src/compiler/pages.ts +70 -0
  94. package/src/compiler/plugin.ts +51 -47
  95. package/src/compiler/prerender.ts +152 -130
  96. package/src/compiler/routes.ts +132 -131
  97. package/src/compiler/seo.ts +381 -356
  98. package/src/compiler/vite.ts +155 -145
  99. package/src/io/FastSet.ts +99 -96
  100. package/test/configure.test.ts +94 -90
  101. package/test/doctor.test.ts +140 -0
  102. package/test/dom/Image.test.tsx +73 -46
  103. package/test/dom/Script.test.tsx +48 -45
  104. package/test/dom/action.test.tsx +146 -129
  105. package/test/dom/error-overlay.test.tsx +1 -1
  106. package/test/dom/loader.test.tsx +2 -2
  107. package/test/dom/revalidate.test.tsx +1 -1
  108. package/test/dom/route-head.test.tsx +1 -2
  109. package/test/dom/router-loading.test.tsx +1 -1
  110. package/test/dom/slot.test.tsx +131 -109
  111. package/test/dom/view-transitions.test.tsx +53 -51
  112. package/test/features.test.ts +149 -142
  113. package/test/fonts.test.ts +28 -26
  114. package/test/head.test.ts +45 -35
  115. package/test/metadata.test.ts +42 -41
  116. package/test/pages.test.ts +105 -0
  117. package/test/prerender.test.ts +54 -46
  118. package/test/search.test.ts +114 -0
  119. package/test/seo.test.ts +30 -8
  120. package/test/update.test.ts +44 -0
@@ -1,552 +1,624 @@
1
- /* Global styles */
2
-
3
- :root {
4
- color-scheme: dark;
5
- --accent: #2563ff;
6
- --accent2: #7c3aed;
7
- --accent3: #22e3ab;
8
- --bg: #080d11;
9
- --surface: #0e1520;
10
- --border: #1b2330;
11
- --text: #f5f6fa;
12
- --muted: #8b9ab4;
13
- }
14
-
15
- *, *::before, *::after { box-sizing: border-box; }
16
-
17
- body {
18
- margin: 0;
19
- min-height: 100vh;
20
- background: var(--bg);
21
- color: var(--text);
22
- font-family: system-ui, -apple-system, sans-serif;
23
- line-height: 1.6;
24
- }
25
-
26
- a { color: var(--accent); text-decoration: none; }
27
- a:hover { color: var(--accent3); }
28
-
29
- /* ── App shell ── */
30
- .app {
31
- display: flex;
32
- flex-direction: column;
33
- min-height: 100vh;
34
- }
35
-
36
- .content {
37
- flex: 1;
38
- display: flex;
39
- align-items: center;
40
- justify-content: center;
41
- }
42
-
43
- /* ── Nav ── */
44
- .nav {
45
- display: flex;
46
- align-items: center;
47
- justify-content: space-between;
48
- padding: 0 2rem;
49
- height: 60px;
50
- border-bottom: 1px solid var(--border);
51
- background: rgba(8, 13, 17, 0.85);
52
- backdrop-filter: blur(10px);
53
- position: sticky;
54
- top: 0;
55
- z-index: 100;
56
- }
57
-
58
- .nav-logo {
59
- display: flex;
60
- align-items: center;
61
- gap: 0.6rem;
62
- font-weight: 800;
63
- font-size: 1.05rem;
64
- font-family: 'Montserrat', system-ui, sans-serif;
65
- color: var(--text) !important;
66
- line-height: 1;
67
- }
68
-
69
- .nav-logo span {
70
- display: block;
71
- line-height: 1;
72
- padding-top: 0.1em;
73
- }
74
-
75
- .nav-logo img {
76
- display: block;
77
- border-radius: 6px;
78
- flex-shrink: 0;
79
- }
80
-
81
- .nav-links {
82
- display: flex;
83
- gap: 1.5rem;
84
- font-size: 0.95rem;
85
- }
86
-
87
- .nav-links a { color: var(--muted); }
88
- .nav-links a:hover { color: var(--text); }
89
-
90
- /* Center nav */
91
- .nav-center {
92
- position: absolute;
93
- left: 50%;
94
- transform: translateX(-50%);
95
- display: flex;
96
- gap: 0.25rem;
97
- }
98
-
99
- .nav-center-link {
100
- padding: 0.3em 0.85em;
101
- border-radius: 6px;
102
- font-size: 0.9rem;
103
- color: var(--muted) !important;
104
- transition: color 150ms, background 150ms;
105
- }
106
-
107
- .nav-center-link:hover {
108
- color: var(--text) !important;
109
- background: rgba(255,255,255,0.05);
110
- }
111
-
112
- .nav-center-link.active {
113
- color: var(--text) !important;
114
- background: rgba(37,99,255,0.12);
115
- }
116
-
117
- .nav-github {
118
- display: flex;
119
- align-items: center;
120
- gap: 0.4rem;
121
- }
122
-
123
- .nav-github svg { display: block; }
124
-
125
- /* ── Hero ── */
126
- .hero {
127
- display: flex;
128
- flex-direction: column;
129
- align-items: center;
130
- text-align: center;
131
- padding: 5rem 1.5rem 4rem;
132
- gap: 1.25rem;
133
- max-width: 680px;
134
- margin: 0 auto;
135
- }
136
-
137
- /* Logo with blurred glow clone */
138
- .hero-logo {
139
- position: relative;
140
- width: 96px;
141
- height: 96px;
142
- }
143
-
144
- .hero-logo-img {
145
- position: relative;
146
- z-index: 1;
147
- display: block;
148
- border-radius: 22px;
149
- transition: transform 300ms;
150
- }
151
-
152
- .hero-logo-img:hover {
153
- transform: scale(1.06);
154
- }
155
-
156
- .hero-logo-glow {
157
- position: absolute;
158
- inset: 0;
159
- z-index: 0;
160
- display: block;
161
- border-radius: 22px;
162
- transform: scale(1.1);
163
- filter: blur(18px) saturate(1.4);
164
- opacity: 0.65;
165
- transition: opacity 300ms, filter 300ms, transform 300ms;
166
- }
167
-
168
- .hero-logo:hover .hero-logo-glow {
169
- opacity: 0.9;
170
- filter: blur(24px) saturate(1.8);
171
- transform: scale(1.15);
172
- }
173
-
174
- /* Heading */
175
- .hero-title {
176
- margin: 0;
177
- font-size: clamp(2.8rem, 7vw, 4.5rem);
178
- font-weight: 900;
179
- font-family: 'Montserrat', system-ui, sans-serif;
180
- letter-spacing: -0.03em;
181
- background: linear-gradient(100deg, var(--accent), var(--accent2) 50%, var(--accent3));
182
- -webkit-background-clip: text;
183
- background-clip: text;
184
- color: transparent;
185
- }
186
-
187
- .hero-tagline {
188
- margin: 0;
189
- font-size: clamp(1.2rem, 3vw, 1.6rem);
190
- font-weight: 600;
191
- color: var(--text);
192
- line-height: 1.4;
193
- }
194
-
195
- .hero-tagline span {
196
- color: var(--muted);
197
- font-weight: 400;
198
- }
199
-
200
- .hero-desc {
201
- margin: 0;
202
- font-size: 1rem;
203
- color: var(--muted);
204
- max-width: 480px;
205
- }
206
-
207
- /* ── Feature badges ── */
208
- .features {
209
- list-style: none;
210
- margin: 0.25rem 0 0;
211
- padding: 0;
212
- display: flex;
213
- flex-wrap: wrap;
214
- gap: 0.6rem;
215
- justify-content: center;
216
- }
217
-
218
- .feature-badge {
219
- display: flex;
220
- align-items: center;
221
- gap: 0.45rem;
222
- padding: 0.35em 0.9em;
223
- background: var(--surface);
224
- border: 1px solid var(--border);
225
- border-radius: 999px;
226
- font-size: 0.88rem;
227
- color: var(--muted);
228
- transition: border-color 200ms, color 200ms;
229
- }
230
-
231
- .feature-badge svg {
232
- flex-shrink: 0;
233
- display: block;
234
- color: var(--accent);
235
- transition: color 200ms;
236
- }
237
-
238
- .feature-badge:hover {
239
- border-color: var(--accent);
240
- color: var(--text);
241
- }
242
-
243
- .feature-badge:hover svg {
244
- color: var(--accent3);
245
- }
246
-
247
- /* ── CTA buttons ── */
248
- .hero-cta {
249
- display: flex;
250
- gap: 0.75rem;
251
- flex-wrap: wrap;
252
- justify-content: center;
253
- margin-top: 0.5rem;
254
- }
255
-
256
- .btn {
257
- display: inline-flex;
258
- align-items: center;
259
- justify-content: center;
260
- gap: 0.45rem;
261
- padding: 0.65em 1.6em;
262
- border-radius: 8px;
263
- font-size: 0.95rem;
264
- font-weight: 600;
265
- font-family: inherit;
266
- cursor: pointer;
267
- transition: filter 200ms, background 200ms, border-color 200ms;
268
- text-decoration: none !important;
269
- }
270
-
271
- .btn svg { display: block; }
272
-
273
- .btn-primary {
274
- background: var(--accent);
275
- color: #fff !important;
276
- border: 1px solid var(--accent);
277
- }
278
-
279
- .btn-primary:hover {
280
- filter: brightness(1.15);
281
- }
282
-
283
- .btn-secondary {
284
- background: var(--surface);
285
- color: var(--text) !important;
286
- border: 1px solid var(--border);
287
- }
288
-
289
- .btn-secondary:hover {
290
- border-color: var(--accent);
291
- background: #131d2e;
292
- }
293
-
294
- /* ── Global Error ── */
295
- .global-error {
296
- padding: 3rem;
297
- font-family: system-ui;
298
- text-align: center;
299
- }
300
-
301
- .global-error-message {
302
- opacity: 0.7;
303
- }
304
-
305
- /* ── Footer ── */
306
- .footer {
307
- padding: 1.25rem;
308
- font-size: 0.82rem;
309
- color: var(--muted);
310
- border-top: 1px solid var(--border);
311
- background: var(--bg);
312
- position: relative;
313
- z-index: 1;
314
- }
315
-
316
- /* ── Misc ── */
317
- code {
318
- background: #0d131c;
319
- color: var(--accent3);
320
- padding: 0.1rem 0.4rem;
321
- border-radius: 4px;
322
- font-size: 0.88em;
323
- }
324
-
325
- /* ── Get Started page ── */
326
- .gs-page {
327
- width: 100%;
328
- max-width: 860px;
329
- margin: 0 auto;
330
- padding: 4rem 1.5rem 5rem;
331
- display: flex;
332
- flex-direction: column;
333
- gap: 3rem;
334
- }
335
-
336
- .gs-hero {
337
- text-align: center;
338
- }
339
-
340
- .gs-title {
341
- margin: 0 0 0.5rem;
342
- font-size: clamp(2.2rem, 5vw, 3.2rem);
343
- font-weight: 900;
344
- font-family: 'Montserrat', system-ui, sans-serif;
345
- letter-spacing: -0.03em;
346
- background: linear-gradient(100deg, var(--accent), var(--accent2) 50%, var(--accent3));
347
- -webkit-background-clip: text;
348
- background-clip: text;
349
- color: transparent;
350
- }
351
-
352
- .gs-desc {
353
- margin: 0;
354
- font-size: 1.05rem;
355
- color: var(--muted);
356
- }
357
-
358
- /* Section */
359
- .gs-section {
360
- display: flex;
361
- flex-direction: column;
362
- gap: 1rem;
363
- }
364
-
365
- .gs-section-title {
366
- margin: 0;
367
- font-size: 0.72rem;
368
- font-weight: 700;
369
- letter-spacing: 0.12em;
370
- text-transform: uppercase;
371
- color: var(--muted);
372
- }
373
-
374
-
375
- /* Info grid */
376
- .gs-grid {
377
- display: grid;
378
- grid-template-columns: repeat(2, 1fr);
379
- gap: 1rem;
380
- }
381
-
382
- @media (max-width: 560px) {
383
- .gs-grid { grid-template-columns: 1fr; }
384
- }
385
-
386
- .gs-card {
387
- background: var(--surface);
388
- border: 1px solid var(--border);
389
- border-radius: 14px;
390
- padding: 1.5rem;
391
- display: flex;
392
- flex-direction: column;
393
- gap: 0.6rem;
394
- transition: border-color 200ms, transform 200ms, box-shadow 200ms;
395
- }
396
-
397
- .gs-card {
398
- transform: translateY(-2px);
399
- }
400
-
401
- /* Accent top-border glow per card */
402
- .gs-card--accent1 { border-top: 2px solid var(--accent); }
403
- .gs-card--accent1:hover { box-shadow: 0 8px 32px rgba(37,99,255,0.15); }
404
-
405
- .gs-card--accent2 { border-top: 2px solid var(--accent2); }
406
- .gs-card--accent2:hover { box-shadow: 0 8px 32px rgba(124,58,237,0.15); }
407
-
408
- .gs-card--accent3 { border-top: 2px solid var(--accent3); }
409
- .gs-card--accent3:hover { box-shadow: 0 8px 32px rgba(34,227,171,0.12); }
410
-
411
- .gs-card--accent4 { border-top: 2px solid #f59e0b; }
412
- .gs-card--accent4:hover { box-shadow: 0 8px 32px rgba(245,158,11,0.12); }
413
-
414
- .gs-card--flat {
415
- border-top: 2px solid var(--accent);
416
- }
417
- .gs-card--flat:hover {
418
- border-color: var(--accent);
419
- box-shadow: 0 8px 32px rgba(37,99,255,0.12);
420
- }
421
-
422
- .gs-card-icon {
423
- display: flex;
424
- align-items: center;
425
- justify-content: center;
426
- width: 42px;
427
- height: 42px;
428
- border-radius: 10px;
429
- background: rgba(37,99,255,0.1);
430
- color: var(--accent);
431
- margin-bottom: 0.25rem;
432
- }
433
-
434
- .gs-card--accent2 .gs-card-icon { background: rgba(124,58,237,0.1); color: var(--accent2); }
435
- .gs-card--accent3 .gs-card-icon { background: rgba(34,227,171,0.1); color: var(--accent3); }
436
- .gs-card--accent4 .gs-card-icon { background: rgba(245,158,11,0.1); color: #f59e0b; }
437
-
438
- .gs-card h3 {
439
- margin: 0;
440
- font-size: 0.97rem;
441
- font-weight: 700;
442
- color: var(--text);
443
- }
444
-
445
- .gs-card p {
446
- margin: 0;
447
- font-size: 0.85rem;
448
- color: var(--muted);
449
- line-height: 1.6;
450
- }
451
-
452
- .gs-card pre {
453
- margin: 0;
454
- background: #0a0f18;
455
- border: 1px solid var(--border);
456
- border-radius: 6px;
457
- padding: 0.6rem 0.85rem;
458
- overflow-x: auto;
459
- }
460
-
461
- .gs-card pre code {
462
- background: none;
463
- padding: 0;
464
- font-size: 0.8rem;
465
- color: var(--accent3);
466
- white-space: pre;
467
- }
468
-
469
- .gs-actions {
470
- display: flex;
471
- gap: 0.75rem;
472
- flex-wrap: wrap;
473
- }
474
-
475
- /* Route loading fallback (loader-demo/loading.tsx) */
476
- .loading-bar {
477
- position: fixed;
478
- inset: 0 0 auto 0;
479
- height: 3px;
480
- background: linear-gradient(90deg, var(--accent), var(--accent2) 50%, var(--accent3));
481
- transform-origin: 0 50%;
482
- animation: loading-bar 2s ease-in-out infinite;
483
- z-index: 50;
484
- }
485
-
486
- @keyframes loading-bar {
487
- 0% { transform: scaleX(0); opacity: 1; }
488
- 80% { transform: scaleX(0.9); opacity: 1; }
489
- 100% { transform: scaleX(1); opacity: 0; }
490
- }
491
-
492
- .loading-center {
493
- display: flex;
494
- flex-direction: column;
495
- align-items: center;
496
- gap: 1rem;
497
- padding: 4rem 0;
498
- color: var(--muted);
499
- }
500
-
501
- .spinner {
502
- width: 2.25rem;
503
- height: 2.25rem;
504
- border: 3px solid var(--border);
505
- border-top-color: var(--accent);
506
- border-radius: 50%;
507
- animation: spinner 0.7s linear infinite;
508
- }
509
-
510
- @keyframes spinner {
511
- to { transform: rotate(360deg); }
512
- }
513
-
514
- @media (prefers-reduced-motion: reduce) {
515
- .loading-bar,
516
- .spinner { animation-duration: 0s; }
517
- }
518
-
519
- /* ── Global Error ── */
520
- .global-error {
521
- padding: 3rem;
522
- font-family: system-ui;
523
- text-align: center;
524
- }
525
-
526
- .global-error-message {
527
- opacity: 0.7;
528
- }
529
-
530
- /* ── Test page ── */
531
- .test-page {
532
- display: flex;
533
- justify-content: center;
534
- align-items: center;
535
- min-height: 100%;
536
- }
537
-
538
- .test-page-image {
539
- max-width: 100%;
540
- max-height: 80vh;
541
- border-radius: 8px;
542
- }
543
-
544
- /* ── Honeycomb background ── */
545
- .honeycomb-canvas {
546
- position: fixed;
547
- inset: 0;
548
- width: 100%;
549
- height: 100%;
550
- pointer-events: none;
551
- z-index: 0;
552
- }
1
+ /* Global styles */
2
+
3
+ :root {
4
+ color-scheme: dark;
5
+ --accent: #2563ff;
6
+ --accent2: #7c3aed;
7
+ --accent3: #22e3ab;
8
+ --bg: #080d11;
9
+ --surface: #0e1520;
10
+ --border: #1b2330;
11
+ --text: #f5f6fa;
12
+ --muted: #8b9ab4;
13
+ }
14
+
15
+ *,
16
+ *::before,
17
+ *::after {
18
+ box-sizing: border-box;
19
+ }
20
+
21
+ body {
22
+ margin: 0;
23
+ min-height: 100vh;
24
+ background: var(--bg);
25
+ color: var(--text);
26
+ font-family:
27
+ system-ui,
28
+ -apple-system,
29
+ sans-serif;
30
+ line-height: 1.6;
31
+ }
32
+
33
+ a {
34
+ color: var(--accent);
35
+ text-decoration: none;
36
+ }
37
+ a:hover {
38
+ color: var(--accent3);
39
+ }
40
+
41
+ /* ── App shell ── */
42
+ .app {
43
+ display: flex;
44
+ flex-direction: column;
45
+ min-height: 100vh;
46
+ }
47
+
48
+ .content {
49
+ flex: 1;
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: center;
53
+ }
54
+
55
+ /* ── Nav ── */
56
+ .nav {
57
+ display: flex;
58
+ align-items: center;
59
+ justify-content: space-between;
60
+ padding: 0 2rem;
61
+ height: 60px;
62
+ border-bottom: 1px solid var(--border);
63
+ background: rgba(8, 13, 17, 0.85);
64
+ backdrop-filter: blur(10px);
65
+ position: sticky;
66
+ top: 0;
67
+ z-index: 100;
68
+ }
69
+
70
+ .nav-logo {
71
+ display: flex;
72
+ align-items: center;
73
+ gap: 0.6rem;
74
+ font-weight: 800;
75
+ font-size: 1.05rem;
76
+ font-family: 'Montserrat', system-ui, sans-serif;
77
+ color: var(--text) !important;
78
+ line-height: 1;
79
+ }
80
+
81
+ .nav-logo span {
82
+ display: block;
83
+ line-height: 1;
84
+ padding-top: 0.1em;
85
+ }
86
+
87
+ .nav-logo img {
88
+ display: block;
89
+ border-radius: 6px;
90
+ flex-shrink: 0;
91
+ }
92
+
93
+ .nav-links {
94
+ display: flex;
95
+ gap: 1.5rem;
96
+ font-size: 0.95rem;
97
+ }
98
+
99
+ .nav-links a {
100
+ color: var(--muted);
101
+ }
102
+ .nav-links a:hover {
103
+ color: var(--text);
104
+ }
105
+
106
+ /* Center nav */
107
+ .nav-center {
108
+ position: absolute;
109
+ left: 50%;
110
+ transform: translateX(-50%);
111
+ display: flex;
112
+ gap: 0.25rem;
113
+ }
114
+
115
+ .nav-center-link {
116
+ padding: 0.3em 0.85em;
117
+ border-radius: 6px;
118
+ font-size: 0.9rem;
119
+ color: var(--muted) !important;
120
+ transition:
121
+ color 150ms,
122
+ background 150ms;
123
+ }
124
+
125
+ .nav-center-link:hover {
126
+ color: var(--text) !important;
127
+ background: rgba(255, 255, 255, 0.05);
128
+ }
129
+
130
+ .nav-center-link.active {
131
+ color: var(--text) !important;
132
+ background: rgba(37, 99, 255, 0.12);
133
+ }
134
+
135
+ .nav-github {
136
+ display: flex;
137
+ align-items: center;
138
+ gap: 0.4rem;
139
+ }
140
+
141
+ .nav-github svg {
142
+ display: block;
143
+ }
144
+
145
+ /* ── Hero ── */
146
+ .hero {
147
+ display: flex;
148
+ flex-direction: column;
149
+ align-items: center;
150
+ text-align: center;
151
+ padding: 5rem 1.5rem 4rem;
152
+ gap: 1.25rem;
153
+ max-width: 680px;
154
+ margin: 0 auto;
155
+ }
156
+
157
+ /* Logo with blurred glow clone */
158
+ .hero-logo {
159
+ position: relative;
160
+ width: 96px;
161
+ height: 96px;
162
+ }
163
+
164
+ .hero-logo-img {
165
+ position: relative;
166
+ z-index: 1;
167
+ display: block;
168
+ border-radius: 22px;
169
+ transition: transform 300ms;
170
+ }
171
+
172
+ .hero-logo-img:hover {
173
+ transform: scale(1.06);
174
+ }
175
+
176
+ .hero-logo-glow {
177
+ position: absolute;
178
+ inset: 0;
179
+ z-index: 0;
180
+ display: block;
181
+ border-radius: 22px;
182
+ transform: scale(1.1);
183
+ filter: blur(18px) saturate(1.4);
184
+ opacity: 0.65;
185
+ transition:
186
+ opacity 300ms,
187
+ filter 300ms,
188
+ transform 300ms;
189
+ }
190
+
191
+ .hero-logo:hover .hero-logo-glow {
192
+ opacity: 0.9;
193
+ filter: blur(24px) saturate(1.8);
194
+ transform: scale(1.15);
195
+ }
196
+
197
+ /* Heading */
198
+ .hero-title {
199
+ margin: 0;
200
+ font-size: clamp(2.8rem, 7vw, 4.5rem);
201
+ font-weight: 900;
202
+ font-family: 'Montserrat', system-ui, sans-serif;
203
+ letter-spacing: -0.03em;
204
+ background: linear-gradient(100deg, var(--accent), var(--accent2) 50%, var(--accent3));
205
+ -webkit-background-clip: text;
206
+ background-clip: text;
207
+ color: transparent;
208
+ }
209
+
210
+ .hero-tagline {
211
+ margin: 0;
212
+ font-size: clamp(1.2rem, 3vw, 1.6rem);
213
+ font-weight: 600;
214
+ color: var(--text);
215
+ line-height: 1.4;
216
+ }
217
+
218
+ .hero-tagline span {
219
+ color: var(--muted);
220
+ font-weight: 400;
221
+ }
222
+
223
+ .hero-desc {
224
+ margin: 0;
225
+ font-size: 1rem;
226
+ color: var(--muted);
227
+ max-width: 480px;
228
+ }
229
+
230
+ /* ── Feature badges ── */
231
+ .features {
232
+ list-style: none;
233
+ margin: 0.25rem 0 0;
234
+ padding: 0;
235
+ display: flex;
236
+ flex-wrap: wrap;
237
+ gap: 0.6rem;
238
+ justify-content: center;
239
+ }
240
+
241
+ .feature-badge {
242
+ display: flex;
243
+ align-items: center;
244
+ gap: 0.45rem;
245
+ padding: 0.35em 0.9em;
246
+ background: var(--surface);
247
+ border: 1px solid var(--border);
248
+ border-radius: 999px;
249
+ font-size: 0.88rem;
250
+ color: var(--muted);
251
+ transition:
252
+ border-color 200ms,
253
+ color 200ms;
254
+ }
255
+
256
+ .feature-badge svg {
257
+ flex-shrink: 0;
258
+ display: block;
259
+ color: var(--accent);
260
+ transition: color 200ms;
261
+ }
262
+
263
+ .feature-badge:hover {
264
+ border-color: var(--accent);
265
+ color: var(--text);
266
+ }
267
+
268
+ .feature-badge:hover svg {
269
+ color: var(--accent3);
270
+ }
271
+
272
+ /* ── CTA buttons ── */
273
+ .hero-cta {
274
+ display: flex;
275
+ gap: 0.75rem;
276
+ flex-wrap: wrap;
277
+ justify-content: center;
278
+ margin-top: 0.5rem;
279
+ }
280
+
281
+ .btn {
282
+ display: inline-flex;
283
+ align-items: center;
284
+ justify-content: center;
285
+ gap: 0.45rem;
286
+ padding: 0.65em 1.6em;
287
+ border-radius: 8px;
288
+ font-size: 0.95rem;
289
+ font-weight: 600;
290
+ font-family: inherit;
291
+ cursor: pointer;
292
+ transition:
293
+ filter 200ms,
294
+ background 200ms,
295
+ border-color 200ms;
296
+ text-decoration: none !important;
297
+ }
298
+
299
+ .btn svg {
300
+ display: block;
301
+ }
302
+
303
+ .btn-primary {
304
+ background: var(--accent);
305
+ color: #fff !important;
306
+ border: 1px solid var(--accent);
307
+ }
308
+
309
+ .btn-primary:hover {
310
+ filter: brightness(1.15);
311
+ }
312
+
313
+ .btn-secondary {
314
+ background: var(--surface);
315
+ color: var(--text) !important;
316
+ border: 1px solid var(--border);
317
+ }
318
+
319
+ .btn-secondary:hover {
320
+ border-color: var(--accent);
321
+ background: #131d2e;
322
+ }
323
+
324
+ /* ── Global Error ── */
325
+ .global-error {
326
+ padding: 3rem;
327
+ font-family: system-ui;
328
+ text-align: center;
329
+ }
330
+
331
+ .global-error-message {
332
+ opacity: 0.7;
333
+ }
334
+
335
+ /* ── Footer ── */
336
+ .footer {
337
+ padding: 1.25rem;
338
+ font-size: 0.82rem;
339
+ color: var(--muted);
340
+ border-top: 1px solid var(--border);
341
+ background: var(--bg);
342
+ position: relative;
343
+ z-index: 1;
344
+ }
345
+
346
+ /* ── Misc ── */
347
+ code {
348
+ background: #0d131c;
349
+ color: var(--accent3);
350
+ padding: 0.1rem 0.4rem;
351
+ border-radius: 4px;
352
+ font-size: 0.88em;
353
+ }
354
+
355
+ /* ── Get Started page ── */
356
+ .gs-page {
357
+ width: 100%;
358
+ max-width: 860px;
359
+ margin: 0 auto;
360
+ padding: 4rem 1.5rem 5rem;
361
+ display: flex;
362
+ flex-direction: column;
363
+ gap: 3rem;
364
+ }
365
+
366
+ .gs-hero {
367
+ text-align: center;
368
+ }
369
+
370
+ .gs-title {
371
+ margin: 0 0 0.5rem;
372
+ font-size: clamp(2.2rem, 5vw, 3.2rem);
373
+ font-weight: 900;
374
+ font-family: 'Montserrat', system-ui, sans-serif;
375
+ letter-spacing: -0.03em;
376
+ background: linear-gradient(100deg, var(--accent), var(--accent2) 50%, var(--accent3));
377
+ -webkit-background-clip: text;
378
+ background-clip: text;
379
+ color: transparent;
380
+ }
381
+
382
+ .gs-desc {
383
+ margin: 0;
384
+ font-size: 1.05rem;
385
+ color: var(--muted);
386
+ }
387
+
388
+ /* Section */
389
+ .gs-section {
390
+ display: flex;
391
+ flex-direction: column;
392
+ gap: 1rem;
393
+ }
394
+
395
+ .gs-section-title {
396
+ margin: 0;
397
+ font-size: 0.72rem;
398
+ font-weight: 700;
399
+ letter-spacing: 0.12em;
400
+ text-transform: uppercase;
401
+ color: var(--muted);
402
+ }
403
+
404
+ /* Info grid */
405
+ .gs-grid {
406
+ display: grid;
407
+ grid-template-columns: repeat(2, 1fr);
408
+ gap: 1rem;
409
+ }
410
+
411
+ @media (max-width: 560px) {
412
+ .gs-grid {
413
+ grid-template-columns: 1fr;
414
+ }
415
+ }
416
+
417
+ .gs-card {
418
+ background: var(--surface);
419
+ border: 1px solid var(--border);
420
+ border-radius: 14px;
421
+ padding: 1.5rem;
422
+ display: flex;
423
+ flex-direction: column;
424
+ gap: 0.6rem;
425
+ transition:
426
+ border-color 200ms,
427
+ transform 200ms,
428
+ box-shadow 200ms;
429
+ }
430
+
431
+ .gs-card {
432
+ transform: translateY(-2px);
433
+ }
434
+
435
+ /* Accent top-border glow per card */
436
+ .gs-card--accent1 {
437
+ border-top: 2px solid var(--accent);
438
+ }
439
+ .gs-card--accent1:hover {
440
+ box-shadow: 0 8px 32px rgba(37, 99, 255, 0.15);
441
+ }
442
+
443
+ .gs-card--accent2 {
444
+ border-top: 2px solid var(--accent2);
445
+ }
446
+ .gs-card--accent2:hover {
447
+ box-shadow: 0 8px 32px rgba(124, 58, 237, 0.15);
448
+ }
449
+
450
+ .gs-card--accent3 {
451
+ border-top: 2px solid var(--accent3);
452
+ }
453
+ .gs-card--accent3:hover {
454
+ box-shadow: 0 8px 32px rgba(34, 227, 171, 0.12);
455
+ }
456
+
457
+ .gs-card--accent4 {
458
+ border-top: 2px solid #f59e0b;
459
+ }
460
+ .gs-card--accent4:hover {
461
+ box-shadow: 0 8px 32px rgba(245, 158, 11, 0.12);
462
+ }
463
+
464
+ .gs-card--flat {
465
+ border-top: 2px solid var(--accent);
466
+ }
467
+ .gs-card--flat:hover {
468
+ border-color: var(--accent);
469
+ box-shadow: 0 8px 32px rgba(37, 99, 255, 0.12);
470
+ }
471
+
472
+ .gs-card-icon {
473
+ display: flex;
474
+ align-items: center;
475
+ justify-content: center;
476
+ width: 42px;
477
+ height: 42px;
478
+ border-radius: 10px;
479
+ background: rgba(37, 99, 255, 0.1);
480
+ color: var(--accent);
481
+ margin-bottom: 0.25rem;
482
+ }
483
+
484
+ .gs-card--accent2 .gs-card-icon {
485
+ background: rgba(124, 58, 237, 0.1);
486
+ color: var(--accent2);
487
+ }
488
+ .gs-card--accent3 .gs-card-icon {
489
+ background: rgba(34, 227, 171, 0.1);
490
+ color: var(--accent3);
491
+ }
492
+ .gs-card--accent4 .gs-card-icon {
493
+ background: rgba(245, 158, 11, 0.1);
494
+ color: #f59e0b;
495
+ }
496
+
497
+ .gs-card h3 {
498
+ margin: 0;
499
+ font-size: 0.97rem;
500
+ font-weight: 700;
501
+ color: var(--text);
502
+ }
503
+
504
+ .gs-card p {
505
+ margin: 0;
506
+ font-size: 0.85rem;
507
+ color: var(--muted);
508
+ line-height: 1.6;
509
+ }
510
+
511
+ .gs-card pre {
512
+ margin: 0;
513
+ background: #0a0f18;
514
+ border: 1px solid var(--border);
515
+ border-radius: 6px;
516
+ padding: 0.6rem 0.85rem;
517
+ overflow-x: auto;
518
+ }
519
+
520
+ .gs-card pre code {
521
+ background: none;
522
+ padding: 0;
523
+ font-size: 0.8rem;
524
+ color: var(--accent3);
525
+ white-space: pre;
526
+ }
527
+
528
+ .gs-actions {
529
+ display: flex;
530
+ gap: 0.75rem;
531
+ flex-wrap: wrap;
532
+ }
533
+
534
+ /* Route loading fallback (loader-demo/loading.tsx) */
535
+ .loading-bar {
536
+ position: fixed;
537
+ inset: 0 0 auto 0;
538
+ height: 3px;
539
+ background: linear-gradient(90deg, var(--accent), var(--accent2) 50%, var(--accent3));
540
+ transform-origin: 0 50%;
541
+ animation: loading-bar 2s ease-in-out infinite;
542
+ z-index: 50;
543
+ }
544
+
545
+ @keyframes loading-bar {
546
+ 0% {
547
+ transform: scaleX(0);
548
+ opacity: 1;
549
+ }
550
+ 80% {
551
+ transform: scaleX(0.9);
552
+ opacity: 1;
553
+ }
554
+ 100% {
555
+ transform: scaleX(1);
556
+ opacity: 0;
557
+ }
558
+ }
559
+
560
+ .loading-center {
561
+ display: flex;
562
+ flex-direction: column;
563
+ align-items: center;
564
+ gap: 1rem;
565
+ padding: 4rem 0;
566
+ color: var(--muted);
567
+ }
568
+
569
+ .spinner {
570
+ width: 2.25rem;
571
+ height: 2.25rem;
572
+ border: 3px solid var(--border);
573
+ border-top-color: var(--accent);
574
+ border-radius: 50%;
575
+ animation: spinner 0.7s linear infinite;
576
+ }
577
+
578
+ @keyframes spinner {
579
+ to {
580
+ transform: rotate(360deg);
581
+ }
582
+ }
583
+
584
+ @media (prefers-reduced-motion: reduce) {
585
+ .loading-bar,
586
+ .spinner {
587
+ animation-duration: 0s;
588
+ }
589
+ }
590
+
591
+ /* ── Global Error ── */
592
+ .global-error {
593
+ padding: 3rem;
594
+ font-family: system-ui;
595
+ text-align: center;
596
+ }
597
+
598
+ .global-error-message {
599
+ opacity: 0.7;
600
+ }
601
+
602
+ /* ── Test page ── */
603
+ .test-page {
604
+ display: flex;
605
+ justify-content: center;
606
+ align-items: center;
607
+ min-height: 100%;
608
+ }
609
+
610
+ .test-page-image {
611
+ max-width: 100%;
612
+ max-height: 80vh;
613
+ border-radius: 8px;
614
+ }
615
+
616
+ /* ── Honeycomb background ── */
617
+ .honeycomb-canvas {
618
+ position: fixed;
619
+ inset: 0;
620
+ width: 100%;
621
+ height: 100%;
622
+ pointer-events: none;
623
+ z-index: 0;
624
+ }