cyclecad 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/index.html ADDED
@@ -0,0 +1,1226 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>cycleCAD — Browser-Based Parametric 3D CAD</title>
7
+ <meta name="description" content="cycleCAD is a browser-based parametric 3D CAD modeler with AI-powered tools, native Inventor file parsing, and smart assembly management. No install required.">
8
+ <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚙️</text></svg>">
9
+ <style>
10
+ /* ============================================================
11
+ RESET & BASE
12
+ ============================================================ */
13
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
14
+
15
+ :root, [data-theme="dark"] {
16
+ --bg-primary: #141418;
17
+ --bg-card: #1c1c22;
18
+ --bg-card-hover: #242430;
19
+ --border-card: #2e2e3a;
20
+ --text-primary: #f4f4f6;
21
+ --text-secondary: #a0a0b4;
22
+ --text-muted: #72728a;
23
+ --accent-orange: #ff9520;
24
+ --accent-orange-light: #ffb040;
25
+ --accent-blue: #5aabff;
26
+ --accent-gradient: linear-gradient(135deg, #ff9520, #ff6010);
27
+ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
28
+ --max-width: 1200px;
29
+ --nav-bg: rgba(20, 20, 24, 0.85);
30
+ --btn-secondary-border: #2e2e3a;
31
+ --btn-secondary-hover-bg: rgba(255,255,255,0.05);
32
+ --mockup-bg: #1c1c22;
33
+ --mockup-toolbar: #262630;
34
+ --mockup-toolbar-border: #363642;
35
+ --mockup-sidebar: #1a1a22;
36
+ --mockup-sidebar-border: #2e2e3a;
37
+ --mockup-viewport-center: #1e1e28;
38
+ --mockup-viewport-edge: #141418;
39
+ --mockup-tree: #383848;
40
+ --mockup-grid-line: rgba(255,255,255,0.035);
41
+ --cube-border: rgba(255, 149, 32, 0.5);
42
+ --cube-bg: rgba(255, 149, 32, 0.06);
43
+ }
44
+
45
+ [data-theme="light"] {
46
+ --bg-primary: #f5f6f8;
47
+ --bg-card: #ffffff;
48
+ --bg-card-hover: #f0f1f3;
49
+ --border-card: #d8dae0;
50
+ --text-primary: #111128;
51
+ --text-secondary: #44445a;
52
+ --text-muted: #6e6e88;
53
+ --accent-orange: #e07800;
54
+ --accent-orange-light: #ff9922;
55
+ --accent-blue: #2b7fd4;
56
+ --accent-gradient: linear-gradient(135deg, #e07800, #d04800);
57
+ --nav-bg: rgba(248, 249, 250, 0.9);
58
+ --btn-secondary-border: #d0d2d6;
59
+ --btn-secondary-hover-bg: rgba(0,0,0,0.03);
60
+ --mockup-bg: #ffffff;
61
+ --mockup-toolbar: #f0f0f4;
62
+ --mockup-toolbar-border: #e0e0e6;
63
+ --mockup-sidebar: #f5f5f8;
64
+ --mockup-sidebar-border: #e0e2e6;
65
+ --mockup-viewport-center: #eaeaf0;
66
+ --mockup-viewport-edge: #dddde4;
67
+ --mockup-tree: #d0d0da;
68
+ --mockup-grid-line: rgba(0,0,0,0.04);
69
+ --cube-border: rgba(224, 120, 0, 0.5);
70
+ --cube-bg: rgba(224, 120, 0, 0.08);
71
+ }
72
+
73
+ html { scroll-behavior: smooth; }
74
+
75
+ body {
76
+ font-family: var(--font-sans);
77
+ background: var(--bg-primary);
78
+ color: var(--text-primary);
79
+ line-height: 1.6;
80
+ overflow-x: hidden;
81
+ -webkit-font-smoothing: antialiased;
82
+ }
83
+
84
+ /* ============================================================
85
+ TYPOGRAPHY
86
+ ============================================================ */
87
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
88
+
89
+ h1, h2, h3 { font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
90
+
91
+ .gradient-text {
92
+ background: var(--accent-gradient);
93
+ -webkit-background-clip: text;
94
+ -webkit-text-fill-color: transparent;
95
+ background-clip: text;
96
+ }
97
+
98
+ /* Light mode: darken gradient for better contrast on white */
99
+ [data-theme="light"] .gradient-text {
100
+ background: linear-gradient(135deg, #b85800, #8a2e00);
101
+ -webkit-background-clip: text;
102
+ background-clip: text;
103
+ }
104
+
105
+ /* Light mode nav CTA */
106
+ [data-theme="light"] .nav-cta {
107
+ color: #fff !important;
108
+ }
109
+
110
+ /* Light mode: ensure primary button text is readable */
111
+ [data-theme="light"] .btn-primary {
112
+ color: #fff;
113
+ }
114
+
115
+ /* Light mode: section label stronger */
116
+ [data-theme="light"] .section-label {
117
+ color: #b85800;
118
+ }
119
+
120
+ /* Light mode: feature icon backgrounds stronger */
121
+ [data-theme="light"] .feature-icon.orange { background: rgba(184,88,0,0.1); }
122
+ [data-theme="light"] .feature-icon.blue { background: rgba(43,127,212,0.1); }
123
+ [data-theme="light"] .feature-icon.green { background: rgba(30,140,40,0.1); }
124
+ [data-theme="light"] .feature-icon.purple { background: rgba(120,70,200,0.1); }
125
+ [data-theme="light"] .feature-icon.red { background: rgba(200,50,40,0.1); }
126
+ [data-theme="light"] .feature-icon.cyan { background: rgba(40,120,200,0.1); }
127
+
128
+ /* Light mode: card shadow for depth */
129
+ [data-theme="light"] .feature-card,
130
+ [data-theme="light"] .problem-card,
131
+ [data-theme="light"] .cap-item {
132
+ box-shadow: 0 1px 3px rgba(0,0,0,0.06);
133
+ }
134
+
135
+ /* Light mode: hero badge */
136
+ [data-theme="light"] .hero-badge {
137
+ background: rgba(184,88,0,0.06);
138
+ border-color: rgba(184,88,0,0.15);
139
+ }
140
+
141
+ /* Light mode: hero visual glow */
142
+ [data-theme="light"] .hero-visual {
143
+ background: radial-gradient(ellipse at center bottom, rgba(184,88,0,0.04) 0%, transparent 70%);
144
+ }
145
+
146
+ .section-label {
147
+ font-size: 0.8rem;
148
+ font-weight: 700;
149
+ letter-spacing: 0.15em;
150
+ text-transform: uppercase;
151
+ color: var(--accent-orange);
152
+ margin-bottom: 16px;
153
+ }
154
+
155
+ /* ============================================================
156
+ LAYOUT
157
+ ============================================================ */
158
+ .container {
159
+ max-width: var(--max-width);
160
+ margin: 0 auto;
161
+ padding: 0 24px;
162
+ }
163
+
164
+ section {
165
+ padding: 120px 0;
166
+ }
167
+
168
+ /* ============================================================
169
+ NAVIGATION
170
+ ============================================================ */
171
+ nav {
172
+ position: fixed;
173
+ top: 0;
174
+ left: 0;
175
+ right: 0;
176
+ z-index: 100;
177
+ padding: 16px 0;
178
+ background: var(--nav-bg);
179
+ backdrop-filter: blur(20px);
180
+ -webkit-backdrop-filter: blur(20px);
181
+ border-bottom: 1px solid var(--border-card);
182
+ transition: all 0.3s;
183
+ }
184
+
185
+ nav .container {
186
+ display: flex;
187
+ justify-content: space-between;
188
+ align-items: center;
189
+ }
190
+
191
+ .nav-logo {
192
+ display: flex;
193
+ align-items: center;
194
+ gap: 10px;
195
+ text-decoration: none;
196
+ color: var(--text-primary);
197
+ font-size: 1.3rem;
198
+ font-weight: 700;
199
+ }
200
+
201
+ .nav-logo-icon {
202
+ width: 32px;
203
+ height: 32px;
204
+ background: var(--accent-gradient);
205
+ border-radius: 8px;
206
+ display: flex;
207
+ align-items: center;
208
+ justify-content: center;
209
+ font-size: 18px;
210
+ }
211
+
212
+ .nav-logo .cycle { color: var(--text-secondary); font-weight: 400; }
213
+ .nav-logo .cad { color: var(--text-primary); font-weight: 800; }
214
+
215
+ .nav-links {
216
+ display: flex;
217
+ gap: 32px;
218
+ align-items: center;
219
+ list-style: none;
220
+ }
221
+
222
+ .nav-links a {
223
+ color: var(--text-secondary);
224
+ text-decoration: none;
225
+ font-size: 0.9rem;
226
+ font-weight: 500;
227
+ transition: color 0.2s;
228
+ }
229
+
230
+ .nav-links a:hover { color: var(--text-primary); }
231
+
232
+ .nav-cta {
233
+ padding: 8px 20px;
234
+ background: var(--accent-gradient);
235
+ color: #000 !important;
236
+ border-radius: 8px;
237
+ font-weight: 600 !important;
238
+ font-size: 0.85rem !important;
239
+ transition: opacity 0.2s !important;
240
+ }
241
+
242
+ .nav-cta:hover { opacity: 0.9; }
243
+
244
+ /* ============================================================
245
+ HERO
246
+ ============================================================ */
247
+ .hero {
248
+ min-height: 100vh;
249
+ display: flex;
250
+ flex-direction: column;
251
+ align-items: center;
252
+ justify-content: center;
253
+ text-align: center;
254
+ padding-top: 80px;
255
+ position: relative;
256
+ }
257
+
258
+ .hero-badge {
259
+ display: inline-flex;
260
+ align-items: center;
261
+ gap: 8px;
262
+ padding: 8px 20px;
263
+ background: rgba(255, 140, 0, 0.08);
264
+ border: 1px solid rgba(255, 140, 0, 0.15);
265
+ border-radius: 100px;
266
+ font-size: 0.85rem;
267
+ color: var(--text-secondary);
268
+ margin-bottom: 32px;
269
+ }
270
+
271
+ .hero-badge span { color: var(--accent-orange); font-weight: 600; }
272
+
273
+ .hero h1 {
274
+ font-size: clamp(3rem, 7vw, 5.5rem);
275
+ max-width: 900px;
276
+ margin-bottom: 24px;
277
+ }
278
+
279
+ .hero p {
280
+ font-size: 1.2rem;
281
+ color: var(--text-secondary);
282
+ max-width: 640px;
283
+ margin-bottom: 40px;
284
+ line-height: 1.7;
285
+ }
286
+
287
+ .hero-ctas {
288
+ display: flex;
289
+ gap: 16px;
290
+ flex-wrap: wrap;
291
+ justify-content: center;
292
+ }
293
+
294
+ .btn-primary {
295
+ display: inline-flex;
296
+ align-items: center;
297
+ gap: 8px;
298
+ padding: 14px 32px;
299
+ background: var(--accent-gradient);
300
+ color: #000;
301
+ border: none;
302
+ border-radius: 10px;
303
+ font-size: 1rem;
304
+ font-weight: 700;
305
+ cursor: pointer;
306
+ text-decoration: none;
307
+ transition: all 0.2s;
308
+ }
309
+
310
+ .btn-primary:hover { opacity: 0.9; transform: translateY(-1px); }
311
+
312
+ .btn-secondary {
313
+ display: inline-flex;
314
+ align-items: center;
315
+ gap: 8px;
316
+ padding: 14px 32px;
317
+ background: transparent;
318
+ color: var(--text-primary);
319
+ border: 1px solid var(--btn-secondary-border);
320
+ border-radius: 10px;
321
+ font-size: 1rem;
322
+ font-weight: 600;
323
+ cursor: pointer;
324
+ text-decoration: none;
325
+ transition: all 0.2s;
326
+ }
327
+
328
+ .btn-secondary:hover {
329
+ border-color: var(--text-muted);
330
+ background: var(--btn-secondary-hover-bg);
331
+ }
332
+
333
+ /* Theme toggle */
334
+ .theme-toggle {
335
+ width: 40px;
336
+ height: 40px;
337
+ border-radius: 10px;
338
+ border: 1px solid var(--border-card);
339
+ background: var(--bg-card);
340
+ color: var(--text-secondary);
341
+ font-size: 18px;
342
+ cursor: pointer;
343
+ display: flex;
344
+ align-items: center;
345
+ justify-content: center;
346
+ transition: all 0.2s;
347
+ margin-left: 8px;
348
+ }
349
+
350
+ .theme-toggle:hover {
351
+ border-color: var(--accent-orange);
352
+ color: var(--accent-orange);
353
+ background: var(--bg-card-hover);
354
+ }
355
+
356
+ /* Hero 3D visual */
357
+ .hero-visual {
358
+ margin-top: 60px;
359
+ width: 100%;
360
+ max-width: 900px;
361
+ aspect-ratio: 16/9;
362
+ background: radial-gradient(ellipse at center bottom, rgba(255,149,32,0.12) 0%, transparent 70%);
363
+ border-radius: 16px;
364
+ border: 1px solid var(--border-card);
365
+ overflow: hidden;
366
+ position: relative;
367
+ display: flex;
368
+ align-items: center;
369
+ justify-content: center;
370
+ }
371
+
372
+ .hero-visual-inner {
373
+ color: var(--text-muted);
374
+ font-size: 0.9rem;
375
+ text-align: center;
376
+ padding: 40px;
377
+ }
378
+
379
+ .hero-visual-inner .app-mockup {
380
+ width: 100%;
381
+ height: 100%;
382
+ background: var(--mockup-bg);
383
+ border-radius: 12px;
384
+ display: flex;
385
+ flex-direction: column;
386
+ overflow: hidden;
387
+ }
388
+
389
+ .mockup-toolbar {
390
+ height: 36px;
391
+ background: var(--mockup-toolbar);
392
+ border-bottom: 1px solid var(--mockup-toolbar-border);
393
+ display: flex;
394
+ align-items: center;
395
+ padding: 0 12px;
396
+ gap: 6px;
397
+ }
398
+
399
+ .mockup-dot {
400
+ width: 8px;
401
+ height: 8px;
402
+ border-radius: 50%;
403
+ }
404
+
405
+ .mockup-dot.red { background: #ff5f57; }
406
+ .mockup-dot.yellow { background: #febc2e; }
407
+ .mockup-dot.green { background: #28c840; }
408
+
409
+ .mockup-toolbar-items {
410
+ display: flex;
411
+ gap: 8px;
412
+ margin-left: 16px;
413
+ }
414
+
415
+ .mockup-toolbar-item {
416
+ width: 40px;
417
+ height: 6px;
418
+ background: var(--mockup-tree);
419
+ border-radius: 3px;
420
+ }
421
+
422
+ .mockup-body {
423
+ flex: 1;
424
+ display: flex;
425
+ }
426
+
427
+ .mockup-sidebar {
428
+ width: 160px;
429
+ background: var(--mockup-sidebar);
430
+ border-right: 1px solid var(--mockup-sidebar-border);
431
+ padding: 12px 8px;
432
+ }
433
+
434
+ .mockup-tree-item {
435
+ height: 5px;
436
+ background: var(--mockup-tree);
437
+ border-radius: 3px;
438
+ margin-bottom: 6px;
439
+ }
440
+
441
+ .mockup-tree-item.active { background: var(--accent-orange); opacity: 0.6; }
442
+ .mockup-tree-item.indent { margin-left: 12px; width: calc(100% - 12px); }
443
+
444
+ .mockup-viewport {
445
+ flex: 1;
446
+ background: radial-gradient(ellipse at center, var(--mockup-viewport-center) 0%, var(--mockup-viewport-edge) 100%);
447
+ display: flex;
448
+ align-items: center;
449
+ justify-content: center;
450
+ position: relative;
451
+ overflow: hidden;
452
+ }
453
+
454
+ .mockup-grid {
455
+ position: absolute;
456
+ inset: 0;
457
+ background-image:
458
+ linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
459
+ linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
460
+ background-size: 30px 30px;
461
+ transform: perspective(600px) rotateX(45deg);
462
+ transform-origin: center 70%;
463
+ }
464
+
465
+ .mockup-3d-shape {
466
+ position: relative;
467
+ z-index: 1;
468
+ }
469
+
470
+ /* CSS-only 3D cube */
471
+ .cube-container {
472
+ width: 120px;
473
+ height: 120px;
474
+ perspective: 400px;
475
+ }
476
+
477
+ .cube {
478
+ width: 100%;
479
+ height: 100%;
480
+ transform-style: preserve-3d;
481
+ transform: rotateX(-25deg) rotateY(40deg);
482
+ animation: cubeRotate 20s linear infinite;
483
+ }
484
+
485
+ @keyframes cubeRotate {
486
+ 0% { transform: rotateX(-25deg) rotateY(40deg); }
487
+ 100% { transform: rotateX(-25deg) rotateY(400deg); }
488
+ }
489
+
490
+ .cube-face {
491
+ position: absolute;
492
+ width: 100px;
493
+ height: 100px;
494
+ border: 1.5px solid var(--cube-border);
495
+ background: var(--cube-bg);
496
+ display: flex;
497
+ align-items: center;
498
+ justify-content: center;
499
+ font-size: 10px;
500
+ color: var(--text-muted);
501
+ }
502
+
503
+ .cube-face.front { transform: translateZ(50px) translateX(10px) translateY(10px); }
504
+ .cube-face.back { transform: rotateY(180deg) translateZ(50px) translateX(10px) translateY(10px); }
505
+ .cube-face.right { transform: rotateY(90deg) translateZ(50px) translateX(10px) translateY(10px); }
506
+ .cube-face.left { transform: rotateY(-90deg) translateZ(50px) translateX(10px) translateY(10px); }
507
+ .cube-face.top { transform: rotateX(90deg) translateZ(50px) translateX(10px) translateY(10px); }
508
+ .cube-face.bottom { transform: rotateX(-90deg) translateZ(50px) translateX(10px) translateY(10px); }
509
+
510
+ .mockup-props {
511
+ width: 180px;
512
+ background: var(--mockup-sidebar);
513
+ border-left: 1px solid var(--mockup-sidebar-border);
514
+ padding: 12px 8px;
515
+ }
516
+
517
+ .mockup-prop-label {
518
+ height: 4px;
519
+ width: 40px;
520
+ background: var(--mockup-tree);
521
+ border-radius: 2px;
522
+ margin-bottom: 8px;
523
+ }
524
+
525
+ .mockup-prop-value {
526
+ height: 4px;
527
+ width: 70px;
528
+ background: var(--mockup-tree);
529
+ border-radius: 2px;
530
+ margin-bottom: 12px;
531
+ }
532
+
533
+ /* ============================================================
534
+ PROBLEM SECTION
535
+ ============================================================ */
536
+ .problem { text-align: center; }
537
+
538
+ .problem h2 {
539
+ font-size: clamp(2rem, 4.5vw, 3.5rem);
540
+ max-width: 800px;
541
+ margin: 0 auto 60px;
542
+ }
543
+
544
+ .problem-cards {
545
+ display: grid;
546
+ grid-template-columns: repeat(2, 1fr);
547
+ gap: 24px;
548
+ max-width: 900px;
549
+ margin: 0 auto;
550
+ }
551
+
552
+ .problem-card {
553
+ background: var(--bg-card);
554
+ border: 1px solid var(--border-card);
555
+ border-radius: 16px;
556
+ padding: 32px;
557
+ text-align: left;
558
+ transition: all 0.3s;
559
+ }
560
+
561
+ .problem-card:hover {
562
+ border-color: rgba(255,140,0,0.15);
563
+ background: var(--bg-card-hover);
564
+ }
565
+
566
+ .problem-card h3 {
567
+ font-size: 1.25rem;
568
+ font-weight: 700;
569
+ margin-bottom: 12px;
570
+ }
571
+
572
+ .problem-card p {
573
+ color: var(--text-secondary);
574
+ font-size: 0.95rem;
575
+ line-height: 1.7;
576
+ }
577
+
578
+ /* ============================================================
579
+ SOLUTION / FEATURES
580
+ ============================================================ */
581
+ .solution { text-align: center; }
582
+
583
+ .solution h2 {
584
+ font-size: clamp(2rem, 4.5vw, 3.5rem);
585
+ max-width: 800px;
586
+ margin: 0 auto 60px;
587
+ }
588
+
589
+ .feature-cards {
590
+ display: grid;
591
+ grid-template-columns: repeat(3, 1fr);
592
+ gap: 24px;
593
+ }
594
+
595
+ .feature-card {
596
+ background: var(--bg-card);
597
+ border: 1px solid var(--border-card);
598
+ border-radius: 16px;
599
+ padding: 32px;
600
+ text-align: left;
601
+ transition: all 0.3s;
602
+ }
603
+
604
+ .feature-card:hover {
605
+ border-color: rgba(255,140,0,0.15);
606
+ background: var(--bg-card-hover);
607
+ transform: translateY(-2px);
608
+ }
609
+
610
+ .feature-icon {
611
+ width: 48px;
612
+ height: 48px;
613
+ border-radius: 12px;
614
+ display: flex;
615
+ align-items: center;
616
+ justify-content: center;
617
+ font-size: 22px;
618
+ margin-bottom: 20px;
619
+ }
620
+
621
+ .feature-icon.orange { background: rgba(255,140,0,0.12); }
622
+ .feature-icon.blue { background: rgba(77,159,255,0.12); }
623
+ .feature-icon.green { background: rgba(63,185,80,0.12); }
624
+ .feature-icon.purple { background: rgba(163,113,247,0.12); }
625
+ .feature-icon.red { background: rgba(248,81,73,0.12); }
626
+ .feature-icon.cyan { background: rgba(88,166,255,0.12); }
627
+
628
+ .feature-card h3 {
629
+ font-size: 1.15rem;
630
+ font-weight: 700;
631
+ margin-bottom: 12px;
632
+ }
633
+
634
+ .feature-card p {
635
+ color: var(--text-secondary);
636
+ font-size: 0.9rem;
637
+ line-height: 1.7;
638
+ }
639
+
640
+ /* ============================================================
641
+ CAPABILITIES GRID
642
+ ============================================================ */
643
+ .capabilities { text-align: center; }
644
+
645
+ .capabilities h2 {
646
+ font-size: clamp(2rem, 4.5vw, 3.5rem);
647
+ max-width: 800px;
648
+ margin: 0 auto 20px;
649
+ }
650
+
651
+ .capabilities > .container > p {
652
+ color: var(--text-secondary);
653
+ max-width: 600px;
654
+ margin: 0 auto 60px;
655
+ font-size: 1.1rem;
656
+ }
657
+
658
+ .cap-grid {
659
+ display: grid;
660
+ grid-template-columns: repeat(4, 1fr);
661
+ gap: 16px;
662
+ }
663
+
664
+ .cap-item {
665
+ background: var(--bg-card);
666
+ border: 1px solid var(--border-card);
667
+ border-radius: 12px;
668
+ padding: 20px 16px;
669
+ text-align: center;
670
+ transition: all 0.2s;
671
+ }
672
+
673
+ .cap-item:hover {
674
+ border-color: rgba(255,140,0,0.2);
675
+ background: var(--bg-card-hover);
676
+ }
677
+
678
+ .cap-item .cap-icon {
679
+ font-size: 24px;
680
+ margin-bottom: 10px;
681
+ }
682
+
683
+ .cap-item h4 {
684
+ font-size: 0.85rem;
685
+ font-weight: 600;
686
+ color: var(--text-primary);
687
+ }
688
+
689
+ .cap-item p {
690
+ font-size: 0.75rem;
691
+ color: var(--text-muted);
692
+ margin-top: 4px;
693
+ }
694
+
695
+ /* ============================================================
696
+ USE CASE / SHOWCASE
697
+ ============================================================ */
698
+ .showcase { text-align: center; }
699
+
700
+ .showcase h2 {
701
+ font-size: clamp(2rem, 4.5vw, 3.5rem);
702
+ max-width: 800px;
703
+ margin: 0 auto 60px;
704
+ }
705
+
706
+ .showcase-visual {
707
+ max-width: 900px;
708
+ margin: 0 auto;
709
+ aspect-ratio: 16/9;
710
+ background: var(--bg-card);
711
+ border: 1px solid var(--border-card);
712
+ border-radius: 16px;
713
+ overflow: hidden;
714
+ display: flex;
715
+ align-items: center;
716
+ justify-content: center;
717
+ position: relative;
718
+ }
719
+
720
+ .showcase-visual .app-mockup {
721
+ width: 100%;
722
+ height: 100%;
723
+ }
724
+
725
+ /* ============================================================
726
+ FINAL CTA
727
+ ============================================================ */
728
+ .final-cta {
729
+ text-align: center;
730
+ padding: 160px 0;
731
+ position: relative;
732
+ }
733
+
734
+ .final-cta::before {
735
+ content: '';
736
+ position: absolute;
737
+ top: 0;
738
+ left: 50%;
739
+ transform: translateX(-50%);
740
+ width: 600px;
741
+ height: 400px;
742
+ background: radial-gradient(ellipse, rgba(255,149,32,0.1) 0%, transparent 70%);
743
+ pointer-events: none;
744
+ }
745
+
746
+ .final-cta h2 {
747
+ font-size: clamp(2.5rem, 5vw, 4rem);
748
+ max-width: 800px;
749
+ margin: 0 auto 24px;
750
+ }
751
+
752
+ .final-cta p {
753
+ color: var(--text-secondary);
754
+ font-size: 1.1rem;
755
+ max-width: 500px;
756
+ margin: 0 auto 40px;
757
+ }
758
+
759
+ .final-cta .hero-ctas {
760
+ justify-content: center;
761
+ }
762
+
763
+ /* ============================================================
764
+ FOOTER
765
+ ============================================================ */
766
+ footer {
767
+ padding: 32px 0;
768
+ border-top: 1px solid var(--border-card);
769
+ text-align: center;
770
+ }
771
+
772
+ footer .container {
773
+ display: flex;
774
+ justify-content: space-between;
775
+ align-items: center;
776
+ }
777
+
778
+ footer .nav-logo { font-size: 1rem; }
779
+
780
+ footer p {
781
+ color: var(--text-muted);
782
+ font-size: 0.8rem;
783
+ }
784
+
785
+ footer .footer-links {
786
+ display: flex;
787
+ gap: 24px;
788
+ list-style: none;
789
+ }
790
+
791
+ footer .footer-links a {
792
+ color: var(--text-muted);
793
+ text-decoration: none;
794
+ font-size: 0.8rem;
795
+ transition: color 0.2s;
796
+ }
797
+
798
+ footer .footer-links a:hover { color: var(--text-secondary); }
799
+
800
+ /* ============================================================
801
+ RESPONSIVE
802
+ ============================================================ */
803
+ @media (max-width: 900px) {
804
+ .problem-cards { grid-template-columns: 1fr; }
805
+ .feature-cards { grid-template-columns: 1fr; }
806
+ .cap-grid { grid-template-columns: repeat(2, 1fr); }
807
+ .mockup-props, .mockup-sidebar { display: none; }
808
+ nav .nav-links { display: none; }
809
+ }
810
+
811
+ @media (max-width: 600px) {
812
+ section { padding: 80px 0; }
813
+ .cap-grid { grid-template-columns: 1fr 1fr; }
814
+ .hero-ctas { flex-direction: column; align-items: center; }
815
+ footer .container { flex-direction: column; gap: 16px; }
816
+ footer .footer-links { gap: 16px; }
817
+ }
818
+
819
+ /* ============================================================
820
+ ANIMATIONS
821
+ ============================================================ */
822
+ @keyframes fadeUp {
823
+ from { opacity: 0; transform: translateY(30px); }
824
+ to { opacity: 1; transform: translateY(0); }
825
+ }
826
+
827
+ .fade-up {
828
+ opacity: 0;
829
+ animation: fadeUp 0.8s ease forwards;
830
+ }
831
+
832
+ .fade-up.d1 { animation-delay: 0.1s; }
833
+ .fade-up.d2 { animation-delay: 0.2s; }
834
+ .fade-up.d3 { animation-delay: 0.3s; }
835
+ .fade-up.d4 { animation-delay: 0.4s; }
836
+ .fade-up.d5 { animation-delay: 0.5s; }
837
+
838
+ /* Scroll-triggered animations */
839
+ .reveal {
840
+ opacity: 0;
841
+ transform: translateY(30px);
842
+ transition: all 0.8s cubic-bezier(0.16, 1, 0.3, 1);
843
+ }
844
+
845
+ .reveal.visible {
846
+ opacity: 1;
847
+ transform: translateY(0);
848
+ }
849
+ </style>
850
+ </head>
851
+ <body>
852
+
853
+ <!-- ============================================================
854
+ NAVIGATION
855
+ ============================================================ -->
856
+ <nav>
857
+ <div class="container">
858
+ <a href="#" class="nav-logo">
859
+ <div class="nav-logo-icon">⚙</div>
860
+ <span class="cycle">cycle</span><span class="cad">CAD</span>
861
+ </a>
862
+ <ul class="nav-links">
863
+ <li><a href="#features">Features</a></li>
864
+ <li><a href="#capabilities">Tools</a></li>
865
+ <li><a href="#showcase">Showcase</a></li>
866
+ <li><a href="https://github.com/vvlars-cmd/cyclecad" target="_blank">GitHub</a></li>
867
+ <li><a href="/app/" class="nav-cta">Try It Free</a></li>
868
+ <li><button class="theme-toggle" id="theme-toggle" title="Toggle dark/light mode" aria-label="Toggle theme">🌙</button></li>
869
+ </ul>
870
+ </div>
871
+ </nav>
872
+
873
+ <!-- ============================================================
874
+ HERO
875
+ ============================================================ -->
876
+ <section class="hero" id="hero">
877
+ <div class="hero-badge fade-up d1">
878
+ <span>100% Browser-Based</span> — No Install Required
879
+ </div>
880
+
881
+ <h1 class="fade-up d2">
882
+ Parametric 3D CAD<br>
883
+ <span class="gradient-text">in your browser</span>
884
+ </h1>
885
+
886
+ <p class="fade-up d3">
887
+ A modern CAD modeler built from scratch with AI-powered tools,
888
+ native Inventor file parsing, and smart assembly management.
889
+ Zero downloads. Just open and design.
890
+ </p>
891
+
892
+ <div class="hero-ctas fade-up d4">
893
+ <a href="/app/" class="btn-primary">Launch cycleCAD</a>
894
+ <a href="#features" class="btn-secondary">See Features</a>
895
+ </div>
896
+
897
+ <div class="hero-visual fade-up d5">
898
+ <div class="app-mockup">
899
+ <div class="mockup-toolbar">
900
+ <div class="mockup-dot red"></div>
901
+ <div class="mockup-dot yellow"></div>
902
+ <div class="mockup-dot green"></div>
903
+ <div class="mockup-toolbar-items">
904
+ <div class="mockup-toolbar-item"></div>
905
+ <div class="mockup-toolbar-item"></div>
906
+ <div class="mockup-toolbar-item" style="width:50px"></div>
907
+ <div class="mockup-toolbar-item"></div>
908
+ <div class="mockup-toolbar-item" style="width:30px"></div>
909
+ <div class="mockup-toolbar-item"></div>
910
+ <div class="mockup-toolbar-item" style="width:60px;background:rgba(255,140,0,0.3);"></div>
911
+ </div>
912
+ </div>
913
+ <div class="mockup-body">
914
+ <div class="mockup-sidebar">
915
+ <div style="height:4px;width:50px;background:#ff8c00;opacity:0.5;border-radius:2px;margin-bottom:10px;"></div>
916
+ <div class="mockup-tree-item" style="width:80%"></div>
917
+ <div class="mockup-tree-item indent active"></div>
918
+ <div class="mockup-tree-item indent" style="width:60%"></div>
919
+ <div class="mockup-tree-item indent" style="width:70%"></div>
920
+ <div class="mockup-tree-item" style="width:75%"></div>
921
+ <div class="mockup-tree-item indent" style="width:55%"></div>
922
+ <div class="mockup-tree-item indent active" style="width:65%"></div>
923
+ <div class="mockup-tree-item" style="width:85%"></div>
924
+ <div class="mockup-tree-item indent" style="width:50%"></div>
925
+ <div class="mockup-tree-item indent" style="width:60%"></div>
926
+ <div class="mockup-tree-item" style="width:70%"></div>
927
+ </div>
928
+ <div class="mockup-viewport">
929
+ <div class="mockup-grid"></div>
930
+ <div class="mockup-3d-shape">
931
+ <div class="cube-container">
932
+ <div class="cube">
933
+ <div class="cube-face front"></div>
934
+ <div class="cube-face back"></div>
935
+ <div class="cube-face right"></div>
936
+ <div class="cube-face left"></div>
937
+ <div class="cube-face top"></div>
938
+ <div class="cube-face bottom"></div>
939
+ </div>
940
+ </div>
941
+ </div>
942
+ </div>
943
+ <div class="mockup-props">
944
+ <div style="height:4px;width:50px;background:#4d9fff;opacity:0.4;border-radius:2px;margin-bottom:10px;"></div>
945
+ <div class="mockup-prop-label"></div>
946
+ <div class="mockup-prop-value"></div>
947
+ <div class="mockup-prop-label" style="width:50px"></div>
948
+ <div class="mockup-prop-value" style="width:55px"></div>
949
+ <div class="mockup-prop-label" style="width:35px"></div>
950
+ <div class="mockup-prop-value" style="width:60px"></div>
951
+ <div style="height:1px;background:var(--border-card);margin:16px 0;"></div>
952
+ <div class="mockup-prop-label" style="width:55px"></div>
953
+ <div class="mockup-prop-value" style="width:80px"></div>
954
+ <div class="mockup-prop-label" style="width:45px"></div>
955
+ <div class="mockup-prop-value" style="width:65px"></div>
956
+ </div>
957
+ </div>
958
+ </div>
959
+ </div>
960
+ </section>
961
+
962
+ <!-- ============================================================
963
+ THE PROBLEM
964
+ ============================================================ -->
965
+ <section class="problem" id="problem">
966
+ <div class="container">
967
+ <div class="section-label reveal">THE PROBLEM</div>
968
+ <h2 class="reveal">
969
+ CAD software is <span class="gradient-text">stuck in the past</span>
970
+ </h2>
971
+
972
+ <div class="problem-cards">
973
+ <div class="problem-card reveal">
974
+ <h3>Locked behind expensive licenses</h3>
975
+ <p>Professional CAD tools cost thousands per seat per year. Small teams and independent designers are priced out of the tools they need to build real products.</p>
976
+ </div>
977
+ <div class="problem-card reveal">
978
+ <h3>Install, update, repeat</h3>
979
+ <p>Desktop-only CAD means waiting for downloads, managing updates, and being tied to one machine. Need to check a design on your tablet? Tough luck.</p>
980
+ </div>
981
+ </div>
982
+ </div>
983
+ </section>
984
+
985
+ <!-- ============================================================
986
+ THE SOLUTION / FEATURES
987
+ ============================================================ -->
988
+ <section class="solution" id="features">
989
+ <div class="container">
990
+ <div class="section-label reveal">THE SOLUTION</div>
991
+ <h2 class="reveal">
992
+ Built for <span class="gradient-text">the modern designer</span>
993
+ </h2>
994
+
995
+ <div class="feature-cards">
996
+ <div class="feature-card reveal">
997
+ <div class="feature-icon orange">⚡</div>
998
+ <h3>Browser-native</h3>
999
+ <p>Full parametric 3D modeler running entirely in your browser. Three.js-powered viewport with real-time rendering. No plugins, no install, no waiting.</p>
1000
+ </div>
1001
+ <div class="feature-card reveal">
1002
+ <div class="feature-icon blue">🤖</div>
1003
+ <h3>AI-powered tools</h3>
1004
+ <p>AI part identification, smart natural language search, automated assembly instructions, and an integrated chatbot that understands your model. Design with intelligence.</p>
1005
+ </div>
1006
+ <div class="feature-card reveal">
1007
+ <div class="feature-icon green">🏭</div>
1008
+ <h3>Native Inventor parsing</h3>
1009
+ <p>Open Autodesk Inventor .ipt and .iam files directly in the browser. Extract features, parameters, and assembly constraints. Generate Fusion 360 rebuild guides automatically.</p>
1010
+ </div>
1011
+ <div class="feature-card reveal">
1012
+ <div class="feature-icon purple">📐</div>
1013
+ <h3>Full parametric modeling</h3>
1014
+ <p>Sketch, extrude, revolve, fillet, chamfer, boolean operations. Constraint-driven design with a live feature tree. Everything you expect from a professional CAD tool.</p>
1015
+ </div>
1016
+ <div class="feature-card reveal">
1017
+ <div class="feature-icon red">🔧</div>
1018
+ <h3>Maintenance intelligence</h3>
1019
+ <p>Heatmaps, wear timelines, service mode, and smart BOM generation with estimated pricing. Go from design to maintenance planning in one tool.</p>
1020
+ </div>
1021
+ <div class="feature-card reveal">
1022
+ <div class="feature-icon cyan">📤</div>
1023
+ <h3>Export everything</h3>
1024
+ <p>STL, OBJ, GLTF, PLY per part. CSV/HTML reports. Slicer integration for 3D printing. Technical reports, assembly manuals, and screenshots with one click.</p>
1025
+ </div>
1026
+ </div>
1027
+ </div>
1028
+ </section>
1029
+
1030
+ <!-- ============================================================
1031
+ CAPABILITIES GRID
1032
+ ============================================================ -->
1033
+ <section class="capabilities" id="capabilities">
1034
+ <div class="container">
1035
+ <div class="section-label reveal">40+ BUILT-IN TOOLS</div>
1036
+ <h2 class="reveal">
1037
+ Everything you need, <span class="gradient-text">nothing you don't</span>
1038
+ </h2>
1039
+ <p class="reveal">Every feature is keyboard-accessible. Press <strong style="color:var(--accent-orange);">?</strong> to see all shortcuts.</p>
1040
+
1041
+ <div class="cap-grid">
1042
+ <div class="cap-item reveal"><div class="cap-icon">✏️</div><h4>Sketch & Constrain</h4><p>Lines, arcs, rectangles, circles</p></div>
1043
+ <div class="cap-item reveal"><div class="cap-icon">📦</div><h4>Extrude & Revolve</h4><p>Solid body creation</p></div>
1044
+ <div class="cap-item reveal"><div class="cap-icon">✂️</div><h4>Boolean Ops</h4><p>Cut, union, intersect</p></div>
1045
+ <div class="cap-item reveal"><div class="cap-icon">📏</div><h4>Measurement</h4><p>Distance, angle, 3-point</p></div>
1046
+ <div class="cap-item reveal"><div class="cap-icon">🔍</div><h4>Smart Search</h4><p>Natural language queries</p></div>
1047
+ <div class="cap-item reveal"><div class="cap-icon">🎯</div><h4>AI Identify</h4><p>Auto-classify parts</p></div>
1048
+ <div class="cap-item reveal"><div class="cap-icon">📋</div><h4>Smart BOM</h4><p>AI-generated bill of materials</p></div>
1049
+ <div class="cap-item reveal"><div class="cap-icon">🔥</div><h4>Maint. Heatmap</h4><p>Urgency color coding</p></div>
1050
+ <div class="cap-item reveal"><div class="cap-icon">📖</div><h4>Auto Manual</h4><p>Step-by-step instructions</p></div>
1051
+ <div class="cap-item reveal"><div class="cap-icon">📊</div><h4>Tech Reports</h4><p>Full HTML export</p></div>
1052
+ <div class="cap-item reveal"><div class="cap-icon">🔩</div><h4>McMaster Links</h4><p>Direct part sourcing</p></div>
1053
+ <div class="cap-item reveal"><div class="cap-icon">📸</div><h4>Screenshot Export</h4><p>High-res PNG capture</p></div>
1054
+ <div class="cap-item reveal"><div class="cap-icon">🔄</div><h4>Section Cut</h4><p>X/Y/Z clipping planes</p></div>
1055
+ <div class="cap-item reveal"><div class="cap-icon">📐</div><h4>Annotations</h4><p>Click-to-place pins</p></div>
1056
+ <div class="cap-item reveal"><div class="cap-icon">🖨️</div><h4>3D Print Slicer</h4><p>G-code generation</p></div>
1057
+ <div class="cap-item reveal"><div class="cap-icon">🌐</div><h4>6 Languages</h4><p>EN DE FR ES IT NL</p></div>
1058
+ </div>
1059
+ </div>
1060
+ </section>
1061
+
1062
+ <!-- ============================================================
1063
+ SHOWCASE
1064
+ ============================================================ -->
1065
+ <section class="showcase" id="showcase">
1066
+ <div class="container">
1067
+ <div class="section-label reveal">BUILT FOR REAL PRODUCTS</div>
1068
+ <h2 class="reveal">
1069
+ Designed for the <span class="gradient-text">cycleWASH DUO</span>
1070
+ </h2>
1071
+
1072
+ <div class="showcase-visual reveal">
1073
+ <div class="app-mockup">
1074
+ <div class="mockup-toolbar">
1075
+ <div class="mockup-dot red"></div>
1076
+ <div class="mockup-dot yellow"></div>
1077
+ <div class="mockup-dot green"></div>
1078
+ <div class="mockup-toolbar-items">
1079
+ <div class="mockup-toolbar-item" style="width:32px"></div>
1080
+ <div class="mockup-toolbar-item" style="width:32px"></div>
1081
+ <div class="mockup-toolbar-item" style="width:32px"></div>
1082
+ <div class="mockup-toolbar-item" style="width:24px"></div>
1083
+ <div style="margin-left:auto;display:flex;gap:6px;">
1084
+ <div class="mockup-toolbar-item" style="width:50px;background:rgba(255,140,0,0.3);"></div>
1085
+ <div class="mockup-toolbar-item" style="width:50px;background:rgba(77,159,255,0.2);"></div>
1086
+ </div>
1087
+ </div>
1088
+ </div>
1089
+ <div class="mockup-body">
1090
+ <div class="mockup-sidebar">
1091
+ <div style="height:4px;width:70px;background:#ff8c00;opacity:0.5;border-radius:2px;margin-bottom:12px;"></div>
1092
+ <div style="font-size:8px;color:var(--text-muted);margin-bottom:4px;font-family:monospace;">DUO Assembly</div>
1093
+ <div class="mockup-tree-item" style="width:90%;background:rgba(255,140,0,0.2);"></div>
1094
+ <div class="mockup-tree-item indent" style="width:65%"></div>
1095
+ <div class="mockup-tree-item indent" style="width:70%"></div>
1096
+ <div class="mockup-tree-item indent active" style="width:55%"></div>
1097
+ <div class="mockup-tree-item" style="width:80%"></div>
1098
+ <div class="mockup-tree-item indent" style="width:60%"></div>
1099
+ <div class="mockup-tree-item indent" style="width:65%"></div>
1100
+ <div class="mockup-tree-item" style="width:85%"></div>
1101
+ <div class="mockup-tree-item indent" style="width:50%"></div>
1102
+ <div class="mockup-tree-item indent" style="width:70%"></div>
1103
+ <div class="mockup-tree-item" style="width:75%"></div>
1104
+ <div class="mockup-tree-item indent" style="width:55%"></div>
1105
+ <div class="mockup-tree-item indent" style="width:45%"></div>
1106
+ <div class="mockup-tree-item" style="width:70%"></div>
1107
+ <div class="mockup-tree-item indent" style="width:60%"></div>
1108
+ <div style="font-size:7px;color:var(--text-muted);margin-top:12px;font-family:monospace;">473 parts loaded</div>
1109
+ </div>
1110
+ <div class="mockup-viewport" style="background:radial-gradient(ellipse at center, var(--mockup-viewport-center) 0%, var(--mockup-viewport-edge) 100%);">
1111
+ <div class="mockup-grid"></div>
1112
+ <div style="position:relative;z-index:1;text-align:center;">
1113
+ <div style="font-size:48px;opacity:0.7;">🚲</div>
1114
+ <div style="color:var(--text-muted);font-size:11px;margin-top:8px;">cycleWASH DUO — 473 Parts, 6 Assemblies</div>
1115
+ </div>
1116
+ </div>
1117
+ <div class="mockup-props">
1118
+ <div style="font-size:8px;color:#4d9fff;font-family:monospace;margin-bottom:8px;">AI Identified</div>
1119
+ <div class="mockup-prop-label"></div>
1120
+ <div class="mockup-prop-value" style="background:rgba(63,185,80,0.2);"></div>
1121
+ <div class="mockup-prop-label" style="width:50px"></div>
1122
+ <div class="mockup-prop-value" style="width:65px;background:rgba(255,140,0,0.2);"></div>
1123
+ <div style="height:1px;background:var(--border-card);margin:12px 0;"></div>
1124
+ <div style="font-size:8px;color:#4d9fff;font-family:monospace;margin-bottom:8px;">McMaster-Carr</div>
1125
+ <div class="mockup-prop-value" style="background:rgba(77,159,255,0.15);width:80px;"></div>
1126
+ <div class="mockup-prop-value" style="background:rgba(77,159,255,0.15);width:65px;"></div>
1127
+ <div style="height:1px;background:var(--border-card);margin:12px 0;"></div>
1128
+ <div style="font-size:8px;color:#4d9fff;font-family:monospace;margin-bottom:8px;">Dimensions</div>
1129
+ <div class="mockup-prop-label" style="width:30px"></div>
1130
+ <div class="mockup-prop-value" style="width:50px"></div>
1131
+ <div class="mockup-prop-label" style="width:30px"></div>
1132
+ <div class="mockup-prop-value" style="width:45px"></div>
1133
+ </div>
1134
+ </div>
1135
+ </div>
1136
+ </div>
1137
+ </div>
1138
+ </section>
1139
+
1140
+ <!-- ============================================================
1141
+ FINAL CTA
1142
+ ============================================================ -->
1143
+ <section class="final-cta" id="try">
1144
+ <div class="container">
1145
+ <h2 class="reveal">
1146
+ Ready to design<br>
1147
+ <span class="gradient-text">without limits?</span>
1148
+ </h2>
1149
+ <p class="reveal">Open cycleCAD in your browser. Free, instant, no account required.</p>
1150
+ <div class="hero-ctas reveal">
1151
+ <a href="/app/" class="btn-primary">Launch cycleCAD</a>
1152
+ <a href="https://github.com/vvlars-cmd/cyclecad" target="_blank" class="btn-secondary">View on GitHub</a>
1153
+ </div>
1154
+ </div>
1155
+ </section>
1156
+
1157
+ <!-- ============================================================
1158
+ FOOTER
1159
+ ============================================================ -->
1160
+ <footer>
1161
+ <div class="container">
1162
+ <a href="#" class="nav-logo">
1163
+ <div class="nav-logo-icon" style="width:24px;height:24px;font-size:14px;border-radius:6px;">⚙</div>
1164
+ <span class="cycle">cycle</span><span class="cad">CAD</span>
1165
+ </a>
1166
+ <ul class="footer-links">
1167
+ <li><a href="https://cyclewash.de/en" target="_blank">cycleWASH</a></li>
1168
+ <li><a href="https://github.com/vvlars-cmd/cyclecad" target="_blank">GitHub</a></li>
1169
+ <li><a href="mailto:vvlars@googlemail.com">Contact</a></li>
1170
+ </ul>
1171
+ <p>&copy; 2026 cycleCAD. All rights reserved.</p>
1172
+ </div>
1173
+ </footer>
1174
+
1175
+ <!-- ============================================================
1176
+ SCROLL REVEAL SCRIPT
1177
+ ============================================================ -->
1178
+ <script>
1179
+ // Intersection Observer for scroll-triggered animations
1180
+ const observer = new IntersectionObserver((entries) => {
1181
+ entries.forEach(entry => {
1182
+ if (entry.isIntersecting) {
1183
+ entry.target.classList.add('visible');
1184
+ observer.unobserve(entry.target);
1185
+ }
1186
+ });
1187
+ }, {
1188
+ threshold: 0.1,
1189
+ rootMargin: '0px 0px -50px 0px'
1190
+ });
1191
+
1192
+ document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
1193
+
1194
+ // Theme toggle — dark/light mode
1195
+ const themeToggle = document.getElementById('theme-toggle');
1196
+ const html = document.documentElement;
1197
+
1198
+ // Check saved preference or system preference
1199
+ const savedTheme = (() => {
1200
+ try { return localStorage.getItem('cyclecad-theme'); } catch { return null; }
1201
+ })();
1202
+ const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
1203
+ const initialTheme = savedTheme || (systemDark ? 'dark' : 'dark'); // Default dark
1204
+ html.setAttribute('data-theme', initialTheme);
1205
+ themeToggle.textContent = initialTheme === 'dark' ? '☀️' : '🌙';
1206
+
1207
+ themeToggle.addEventListener('click', () => {
1208
+ const current = html.getAttribute('data-theme') || 'dark';
1209
+ const next = current === 'dark' ? 'light' : 'dark';
1210
+ html.setAttribute('data-theme', next);
1211
+ themeToggle.textContent = next === 'dark' ? '☀️' : '🌙';
1212
+ try { localStorage.setItem('cyclecad-theme', next); } catch {}
1213
+ });
1214
+
1215
+ // Listen for system preference changes
1216
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
1217
+ if (!localStorage.getItem('cyclecad-theme')) {
1218
+ const theme = e.matches ? 'dark' : 'light';
1219
+ html.setAttribute('data-theme', theme);
1220
+ themeToggle.textContent = theme === 'dark' ? '☀️' : '🌙';
1221
+ }
1222
+ });
1223
+ </script>
1224
+
1225
+ </body>
1226
+ </html>