@howssatoshi/quantumcss 1.10.1 → 1.11.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.
Files changed (43) hide show
  1. package/README.md +11 -10
  2. package/dist/quantum.min.css +2 -2
  3. package/examples/admin-panel.html +317 -600
  4. package/examples/analytics-dashboard.html +130 -288
  5. package/examples/blog.css +297 -0
  6. package/examples/blog.html +216 -0
  7. package/examples/chat-messaging.html +11 -27
  8. package/examples/email-client.css +582 -0
  9. package/examples/email-client.html +432 -0
  10. package/examples/gaming-portal.css +352 -0
  11. package/examples/gaming-portal.html +239 -0
  12. package/examples/index.html +342 -232
  13. package/examples/kitchen-sink.html +284 -94
  14. package/examples/music-streaming.html +32 -91
  15. package/examples/{news-template.html → news.html} +35 -11
  16. package/examples/{portfolio-resume.html → portfolio.html} +56 -26
  17. package/examples/shopping.html +812 -0
  18. package/examples/starlight.html +7 -6
  19. package/examples/task.md +12 -0
  20. package/examples/travel.html +514 -0
  21. package/examples/video-streaming.html +303 -92
  22. package/package.json +9 -3
  23. package/src/cli.js +5 -5
  24. package/src/defaults.js +18 -16
  25. package/src/starlight.js +20 -15
  26. package/src/styles/quantum-base.css +4 -0
  27. package/src/styles/quantum-components.css +1879 -134
  28. package/src/styles/quantum-icons.css +345 -0
  29. package/src/styles/starlight.css +2606 -1186
  30. package/dist/quantum.css +0 -2374
  31. package/examples/blog-template.html +0 -288
  32. package/examples/email-template.html +0 -712
  33. package/examples/gaming-template.html +0 -471
  34. package/examples/gradient-test.html +0 -129
  35. package/examples/shopping/images/headset.jpg +0 -0
  36. package/examples/shopping/images/sneakers.jpg +0 -0
  37. package/examples/shopping/images/windbreaker.jpg +0 -0
  38. package/examples/shopping/index.html +0 -525
  39. package/examples/theme-test.html +0 -159
  40. package/examples/travel/index.html +0 -432
  41. package/examples/verify_fixes.html +0 -52
  42. package/examples/verify_presets.html +0 -32
  43. /package/examples/{shopping/nova-shop.css → nova-shop.css} +0 -0
@@ -1,525 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en" data-theme="dark">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>NOVA — Quantum Shop</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com" />
8
- <link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Sans:wght@300;400;500&display=swap" rel="stylesheet" />
9
-
10
- <!-- Quantum CSS Framework -->
11
- <link rel="stylesheet" href="../../dist/quantum.min.css" />
12
-
13
- <!-- Custom Nova Shop Styles -->
14
- <link rel="stylesheet" href="nova-shop.css" />
15
- </head>
16
- <body>
17
-
18
- <!-- ── Starfield ── -->
19
- <div class="stars-bg" id="stars"></div>
20
-
21
- <div class="site-wrapper">
22
-
23
- <!-- ══════════ NAVBAR ══════════ -->
24
- <nav class="starlight-navbar">
25
- <div class="container mx-auto px-6 h-20 flex items-center justify-between">
26
- <!-- Brand -->
27
- <a href="#" class="nav-brand text-gradient-starlight">NOVA</a>
28
-
29
- <!-- Nav links -->
30
- <ul class="hidden md:flex items-center gap-8 nav-links">
31
- <li><a href="#">New In</a></li>
32
- <li><a href="#">Collections</a></li>
33
- <li><a href="#">Sale</a></li>
34
- <li><a href="#">Brands</a></li>
35
- <li><a href="#">About</a></li>
36
- </ul>
37
-
38
- <!-- Actions -->
39
- <div class="flex items-center gap-3">
40
- <div class="search-bar-wrap">
41
- <span class="search-icon-pos">
42
- <svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
43
- </span>
44
- <input class="search-bar-input" type="search" placeholder="Search products…" />
45
- </div>
46
-
47
- <button class="icon-btn" id="themeToggle" title="Toggle Theme">
48
- <svg class="sun-icon hidden" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
49
- <svg class="moon-icon hidden" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
50
- <svg class="system-icon hidden" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/></svg>
51
- </button>
52
-
53
- <button class="icon-btn">
54
- <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
55
- </button>
56
-
57
- <button class="icon-btn" style="position:relative">
58
- <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/><line x1="3" y1="6" x2="21" y2="6"/><path d="M16 10a4 4 0 0 1-8 0"/></svg>
59
- <span class="badge-count absolute -top-1 -right-1">3</span>
60
- </button>
61
-
62
- <button class="icon-btn">
63
- <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
64
- </button>
65
- </div>
66
- </div>
67
- </nav>
68
-
69
- <!-- ══════════ HERO ══════════ -->
70
- <section class="hero">
71
- <div class="hero-glow"></div>
72
- <div class="hero-content">
73
- <div class="hero-eyebrow ani-slide-up">
74
- <span></span>
75
- New Collection — Summer 2025
76
- </div>
77
- <h1 class="ani-slide-up ani-stagger-1">
78
- Dress the
79
- <span class="text-gradient-starlight">Future.</span><br>
80
- Own the Moment.
81
- </h1>
82
- <p class="hero-sub ani-slide-up ani-stagger-2">
83
- Curated fashion from tomorrow's most iconic labels.
84
- Pieces that define who you are before the world catches up.
85
- </p>
86
- <div class="flex flex-wrap justify-center gap-4 ani-slide-up ani-stagger-3">
87
- <button class="btn-starlight" style="padding:.75rem 2rem; font-size:.95rem; border-radius:9999px;">
88
- Shop Now
89
- <svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
90
- </button>
91
- <button class="btn-outline-glow">
92
- Explore Collections
93
- </button>
94
- </div>
95
- <div class="hero-stats ani-slide-up ani-stagger-4">
96
- <div>
97
- <div class="hero-stat-value">12K+</div>
98
- <div class="hero-stat-label">Happy Customers</div>
99
- </div>
100
- <div>
101
- <div class="hero-stat-value">340+</div>
102
- <div class="hero-stat-label">Brands</div>
103
- </div>
104
- <div>
105
- <div class="hero-stat-value">4.9★</div>
106
- <div class="hero-stat-label">Avg. Rating</div>
107
- </div>
108
- </div>
109
- </div>
110
- </section>
111
-
112
- <!-- ══════════ TRUST BAR ══════════ -->
113
- <div class="trust-section">
114
- <div class="container">
115
- <div class="flex flex-wrap justify-around gap-8">
116
- <div class="trust-item">
117
- <span class="trust-icon">🚀</span>
118
- <div>
119
- <div class="trust-text-title">Express Shipping</div>
120
- <div class="trust-text-sub">Free on orders over $75</div>
121
- </div>
122
- </div>
123
- <div class="trust-item">
124
- <span class="trust-icon">🔄</span>
125
- <div>
126
- <div class="trust-text-title">Free Returns</div>
127
- <div class="trust-text-sub">Within 30 days, no hassle</div>
128
- </div>
129
- </div>
130
- <div class="trust-item">
131
- <span class="trust-icon">🔐</span>
132
- <div>
133
- <div class="trust-text-title">Secure Payment</div>
134
- <div class="trust-text-sub">256-bit SSL encryption</div>
135
- </div>
136
- </div>
137
- <div class="trust-item">
138
- <span class="trust-icon">🌍</span>
139
- <div>
140
- <div class="trust-text-title">Ships Worldwide</div>
141
- <div class="trust-text-sub">Over 120 countries</div>
142
- </div>
143
- </div>
144
- </div>
145
- </div>
146
- </div>
147
-
148
- <!-- ══════════ CATEGORIES ══════════ -->
149
- <section class="categories-section">
150
- <div class="container">
151
- <div class="section-label">Browse by category</div>
152
- <div class="categories-scroll">
153
- <button class="cat-pill active"><span class="cat-pill-icon">✨</span> All</button>
154
- <button class="cat-pill"><span class="cat-pill-icon">👗</span> Dresses</button>
155
- <button class="cat-pill"><span class="cat-pill-icon">👟</span> Sneakers</button>
156
- <button class="cat-pill"><span class="cat-pill-icon">🧥</span> Outerwear</button>
157
- <button class="cat-pill"><span class="cat-pill-icon">👜</span> Bags</button>
158
- <button class="cat-pill"><span class="cat-pill-icon">💍</span> Jewellery</button>
159
- <button class="cat-pill"><span class="cat-pill-icon">🧢</span> Accessories</button>
160
- <button class="cat-pill"><span class="cat-pill-icon">🩱</span> Swimwear</button>
161
- <button class="cat-pill"><span class="cat-pill-icon">🎽</span> Activewear</button>
162
- <button class="cat-pill"><span class="cat-pill-icon">🕶️</span> Eyewear</button>
163
- </div>
164
- </div>
165
- </section>
166
-
167
- <!-- ══════════ TRENDING MARQUEE ══════════ -->
168
- <div class="trending-section">
169
- <div class="marquee-track" id="marquee">
170
- <!-- items duplicated in JS -->
171
- </div>
172
- </div>
173
-
174
- <!-- ══════════ PRODUCTS ══════════ -->
175
- <section class="products-section">
176
- <div class="container">
177
- <div class="section-header">
178
- <div>
179
- <div class="section-label">Hand-picked for you</div>
180
- <h2 class="section-title">New Arrivals</h2>
181
- </div>
182
- <a href="#" class="view-all-link">
183
- View all
184
- <svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
185
- </a>
186
- </div>
187
-
188
- <div class="product-grid" id="productGrid"></div>
189
- </div>
190
- </section>
191
-
192
- <!-- ══════════ FEATURED BANNERS ══════════ -->
193
- <section class="featured-section">
194
- <div class="container">
195
- <div class="section-label" style="margin-bottom:1.25rem">Spotlight</div>
196
- <div class="featured-grid">
197
-
198
- <div class="featured-card">
199
- <div class="featured-card-bg featured-bg-1">
200
- <div class="featured-glow-1"></div>
201
- <div class="featured-float-icon" style="top:30%;left:60%;">👟</div>
202
- </div>
203
- <div class="featured-content">
204
- <div class="featured-eyebrow">New Drop — Limited Edition</div>
205
- <h3 class="featured-title">Future-Sole<br>Sneaker Series</h3>
206
- <p class="featured-desc">Ultra-light composites. Cosmic colourways. Zero-break-in comfort.</p>
207
- <button class="btn-starlight" style="border-radius:9999px;">Shop Kicks →</button>
208
- </div>
209
- </div>
210
-
211
- <div class="featured-card">
212
- <div class="featured-card-bg featured-bg-2">
213
- <div class="featured-glow-2"></div>
214
- <div class="featured-float-icon" style="top:25%;left:55%;">💫</div>
215
- </div>
216
- <div class="featured-content">
217
- <div class="featured-eyebrow" style="color:var(--q-color-starlight-peach)">Up to 60% Off</div>
218
- <h3 class="featured-title">Summer<br>Edit Sale</h3>
219
- <p class="featured-desc">The season's most wanted pieces, now at their best prices.</p>
220
- <button class="btn-starlight" style="background:linear-gradient(135deg,#ff7e5f,#ffb38a);border-radius:9999px;">Grab a Deal →</button>
221
- </div>
222
- </div>
223
-
224
- </div>
225
- </div>
226
- </section>
227
-
228
- <!-- ══════════ BESTSELLERS ══════════ -->
229
- <section class="products-section" style="padding-top:0">
230
- <div class="container">
231
- <div class="section-header">
232
- <div>
233
- <div class="section-label">Community favourites</div>
234
- <h2 class="section-title">Best Sellers</h2>
235
- </div>
236
- <a href="#" class="view-all-link">View all <svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M5 12h14M12 5l7 7-7 7"/></svg></a>
237
- </div>
238
- <div class="product-grid" id="bestsellersGrid"></div>
239
- </div>
240
- </section>
241
-
242
- <!-- ══════════ TESTIMONIALS ══════════ -->
243
- <section class="testimonials-section">
244
- <div class="container">
245
- <div class="section-header">
246
- <div>
247
- <div class="section-label">What they say</div>
248
- <h2 class="section-title">Loved by thousands</h2>
249
- </div>
250
- </div>
251
- <div class="testimonials-grid" id="testimonialsGrid"></div>
252
- </div>
253
- </section>
254
-
255
- <!-- ══════════ NEWSLETTER ══════════ -->
256
- <section class="newsletter-section">
257
- <div class="container">
258
- <div class="newsletter-card">
259
- <div class="newsletter-bg-glow"></div>
260
- <div class="hero-eyebrow" style="display:inline-flex;margin-bottom:1.25rem;">
261
- <span></span> Exclusive Access
262
- </div>
263
- <h2 class="newsletter-title">
264
- Stay ahead of the<br><span class="text-gradient-starlight">curve.</span>
265
- </h2>
266
- <p class="newsletter-sub">Early access, secret drops, and 10% off your first order.</p>
267
- <div class="newsletter-form">
268
- <input class="newsletter-input" type="email" placeholder="your@email.com" />
269
- <button class="btn-starlight" style="border-radius:9999px;padding:.65rem 1.75rem;">
270
- Subscribe →
271
- </button>
272
- </div>
273
- <p style="font-size:.72rem;color:var(--q-text-muted);margin-top:1rem;">No spam ever. Unsubscribe anytime.</p>
274
- </div>
275
- </div>
276
- </section>
277
-
278
- <!-- ══════════ FOOTER ══════════ -->
279
- <footer class="starlight-footer">
280
- <div class="container">
281
- <div class="footer-grid">
282
- <div>
283
- <div class="footer-brand text-gradient-starlight">NOVA</div>
284
- <p class="footer-desc">The destination for forward-thinking fashion. We curate the best from the world's most exciting brands — so you never have to compromise.</p>
285
- <div class="footer-socials" style="margin-top:1.25rem;">
286
- <a class="social-btn" href="#">𝕏</a>
287
- <a class="social-btn" href="#">ig</a>
288
- <a class="social-btn" href="#">in</a>
289
- <a class="social-btn" href="#">yt</a>
290
- </div>
291
- </div>
292
- <div>
293
- <div class="footer-col-title">Shop</div>
294
- <ul class="footer-links">
295
- <li><a href="#">New Arrivals</a></li>
296
- <li><a href="#">Best Sellers</a></li>
297
- <li><a href="#">Sale</a></li>
298
- <li><a href="#">Brands</a></li>
299
- <li><a href="#">Collections</a></li>
300
- </ul>
301
- </div>
302
- <div>
303
- <div class="footer-col-title">Help</div>
304
- <ul class="footer-links">
305
- <li><a href="#">Shipping & Returns</a></li>
306
- <li><a href="#">Size Guide</a></li>
307
- <li><a href="#">Track Order</a></li>
308
- <li><a href="#">FAQ</a></li>
309
- <li><a href="#">Contact Us</a></li>
310
- </ul>
311
- </div>
312
- <div>
313
- <div class="footer-col-title">Company</div>
314
- <ul class="footer-links">
315
- <li><a href="#">About NOVA</a></li>
316
- <li><a href="#">Sustainability</a></li>
317
- <li><a href="#">Careers</a></li>
318
- <li><a href="#">Press</a></li>
319
- <li><a href="#">Affiliates</a></li>
320
- </ul>
321
- </div>
322
- </div>
323
- <hr class="footer-divider" />
324
- <div class="footer-bottom">
325
- <span>© 2025 NOVA Commerce Inc. All rights reserved.</span>
326
- <span style="display:flex;gap:1.5rem;">
327
- <a href="#" style="color:inherit;text-decoration:none;">Privacy</a>
328
- <a href="#" style="color:inherit;text-decoration:none;">Terms</a>
329
- <a href="#" style="color:inherit;text-decoration:none;">Cookies</a>
330
- </span>
331
- </div>
332
- </div>
333
- </footer>
334
-
335
- </div><!-- /.site-wrapper -->
336
-
337
- <!-- Floating cart -->
338
- <div class="floating-cta">
339
- <button class="floating-cart-btn">
340
- 🛒 Cart (3)
341
- </button>
342
- </div>
343
-
344
-
345
- <script>
346
- /* ── Stars ── */
347
- const starsEl = document.getElementById('stars');
348
- for (let i = 0; i < 120; i++) {
349
- const s = document.createElement('div');
350
- s.className = 'star';
351
- const size = Math.random() * 2.5 + 0.5;
352
- s.style.cssText = `
353
- width:${size}px; height:${size}px;
354
- left:${Math.random()*100}%; top:${Math.random()*100}%;
355
- --d:${2+Math.random()*5}s;
356
- animation-delay:${Math.random()*5}s;
357
- `;
358
- starsEl.appendChild(s);
359
- }
360
-
361
- /* ── Product data ── */
362
- const products = [
363
- { name: 'Aurora Silk Dress', brand: 'Lumière', price: 289, original: null, rating: 4.8, reviews: 214, emoji: '👗', bg: 'linear-gradient(135deg,#1a0a3e,#0d1f3e)', colors: ['#00d4ff','#ff7e5f','#1e293b'], badges: ['new'] },
364
- { name: 'Nebula Runner Pro', brand: 'Voidwear', price: 179, original: 229, rating: 4.9, reviews: 847, emoji: '👟', bg: 'linear-gradient(135deg,#0d2b1a,#1a1052)', colors: ['#10b981','#3b82f6','#f59e0b'], badges: ['sale','hot'] },
365
- { name: 'Quantum Puffer Vest', brand: 'Arctis', price: 195, original: null, rating: 4.7, reviews: 133, emoji: '🦺', bg: 'linear-gradient(135deg,#1f0a0a,#2d1a0a)', colors: ['#ef4444','#f59e0b','#1e293b'], badges: ['new'] },
366
- { name: 'Starmap Tote Bag', brand: 'Cosmo', price: 145, original: 195, rating: 4.8, reviews: 529, emoji: '👜', bg: 'linear-gradient(135deg,#080a2d,#1a0a3e)', colors: ['#8b5cf6','#ec4899','#f1f5f9'], badges: ['sale'] },
367
- { name: 'Photon Blazer', brand: 'Lumière', price: 349, original: null, rating: 4.6, reviews: 88, emoji: '🧥', bg: 'linear-gradient(135deg,#0a1f1a,#0d1f3e)', colors: ['#00d4ff','#1e293b'], badges: ['new'] },
368
- { name: 'Crystal Drop Earrings', brand: 'Stellaris', price: 89, original: 120, rating: 4.9, reviews: 302, emoji: '💎', bg: 'linear-gradient(135deg,#1a0a2d,#0a1a1f)', colors: ['#e2e8f0','#fbbf24','#ec4899'], badges: ['sale'] },
369
- { name: 'Void Linen Pants', brand: 'Voidwear', price: 165, original: null, rating: 4.5, reviews: 176, emoji: '👖', bg: 'linear-gradient(135deg,#0d1a0d,#1a1a0a)', colors: ['#1e293b','#f1f5f9','#78716c'], badges: [] },
370
- { name: 'Orbital Sunglasses', brand: 'Eclipse', price: 215, original: 269, rating: 4.8, reviews: 441, emoji: '🕶️', bg: 'linear-gradient(135deg,#1a0a0a,#1a1052)', colors: ['#000','#fbbf24','#ec4899'], badges: ['hot','sale'] },
371
- ];
372
-
373
- const bestsellers = [
374
- { name: 'Supernova Hoodie', brand: 'Voidwear', price: 139, original: null, rating: 4.9, reviews: 1203, emoji: '🌟', bg: 'linear-gradient(135deg,#0a0a2d,#2d0a1a)', colors: ['#8b5cf6','#00d4ff','#f87171'], badges: ['hot'] },
375
- { name: 'Eclipse Trench Coat', brand: 'Arctis', price: 495, original: 629, rating: 4.8, reviews: 389, emoji: '🌑', bg: 'linear-gradient(135deg,#0a0a0a,#1a0a2d)', colors: ['#000','#1e293b','#ffb38a'], badges: ['sale'] },
376
- { name: 'Prism Mini Skirt', brand: 'Lumière', price: 115, original: null, rating: 4.7, reviews: 672, emoji: '🌈', bg: 'linear-gradient(135deg,#1a0a3e,#0a2d1a)', colors: ['#ec4899','#f59e0b','#00d4ff'], badges: ['new'] },
377
- { name: 'Gravity Belt', brand: 'Cosmo', price: 79, original: 99, rating: 4.6, reviews: 218, emoji: '⚡', bg: 'linear-gradient(135deg,#1f1a0a,#0a1a2d)', colors: ['#f59e0b','#1e293b','#f87171'], badges: ['sale'] },
378
- ];
379
-
380
- function buildCard(p) {
381
- const badgeHtml = p.badges.map(b => {
382
- let variant = 'secondary';
383
- if (b === 'new') variant = 'primary';
384
- if (b === 'sale') variant = 'error';
385
- if (b === 'hot') variant = 'warning';
386
- return `<span class="badge badge-${variant}">${b}</span>`;
387
- }).join('');
388
-
389
- const colorHtml = p.colors.map((c, i) =>
390
- `<span class="color-swatch ${i===0?'active':''}" style="background:${c}" title="${c}"></span>`
391
- ).join('');
392
- const pct = p.original ? Math.round((1 - p.price/p.original)*100) : 0;
393
-
394
- return `
395
- <div class="product-card">
396
- <div class="product-image-wrap">
397
- <div class="product-img-placeholder" style="background:${p.bg}">
398
- ${p.emoji}
399
- </div>
400
- <div class="product-badge-wrap">${badgeHtml}</div>
401
- <div class="product-quick-add">
402
- <button class="btn-quick-add">+ Add to Cart</button>
403
- <button class="btn-wishlist">♡</button>
404
- </div>
405
- </div>
406
- <div class="product-info">
407
- <div class="product-brand">${p.brand}</div>
408
- <div class="product-name">${p.name}</div>
409
- <div class="product-rating">
410
- <span class="stars">${'★'.repeat(Math.floor(p.rating))}${'☆'.repeat(5-Math.floor(p.rating))}</span>
411
- <span class="rating-count">(${p.reviews.toLocaleString()})</span>
412
- </div>
413
- <div class="product-price-row">
414
- <span class="price-current">$${p.price}</span>
415
- ${p.original ? `<span class="price-original">$${p.original}</span><span class="price-discount">−${pct}%</span>` : ''}
416
- </div>
417
- <div class="product-colors">${colorHtml}</div>
418
- </div>
419
- </div>
420
- `;
421
- }
422
-
423
- document.getElementById('productGrid').innerHTML = products.map(buildCard).join('');
424
- document.getElementById('bestsellersGrid').innerHTML = bestsellers.map(buildCard).join('');
425
-
426
- /* ── Testimonials ── */
427
- const testimonials = [
428
- { text: "NOVA is genuinely the only store I trust for cutting-edge pieces. The curation is unreal — every drop feels like it was made for me.", name: 'Aria M.', handle: '@aria.makes', initials: 'AM', stars: 5 },
429
- { text: "Delivery was faster than I expected, and the packaging feels like opening a gift. Even my friends are jealous of the unboxing experience.", name: 'Jordan K.', handle: '@jkvisuals', initials: 'JK', stars: 5 },
430
- { text: "I've been shopping fashion for 10 years and NOVA just changed the game. The Nebula Runner is the most comfortable sneaker I've ever owned.", name: 'Priya S.', handle: '@priyastyle_', initials: 'PS', stars: 5 },
431
- ];
432
-
433
- document.getElementById('testimonialsGrid').innerHTML = testimonials.map(t => `
434
- <div class="testimonial-card">
435
- <div class="testimonial-quote">"</div>
436
- <p class="testimonial-text">${t.text}</p>
437
- <div class="testimonial-author">
438
- <div class="t-avatar">${t.initials}</div>
439
- <div>
440
- <div class="t-name">${t.name}</div>
441
- <div class="t-handle">${t.handle} · ${'★'.repeat(t.stars)}</div>
442
- </div>
443
- </div>
444
- </div>
445
- `).join('');
446
-
447
- /* ── Marquee ── */
448
- const trendingItems = [
449
- 'Nebula Runner', 'Aurora Dress', 'Eclipse Trench', 'Prism Skirt',
450
- 'Void Pants', 'Crystal Drops', 'Supernova Hoodie', 'Photon Blazer',
451
- 'Orbital Shades', 'Starmap Tote'
452
- ];
453
- const marquee = document.getElementById('marquee');
454
- const all = [...trendingItems, ...trendingItems];
455
- marquee.innerHTML = all.map((item, i) => `
456
- <div class="marquee-item">
457
- <span class="marquee-dot"></span>
458
- Trending: <span>${item}</span>
459
- </div>
460
- `).join('');
461
-
462
- /* ── Category filter ── */
463
- document.querySelectorAll('.cat-pill').forEach(btn => {
464
- btn.addEventListener('click', () => {
465
- document.querySelectorAll('.cat-pill').forEach(b => b.classList.remove('active'));
466
- btn.classList.add('active');
467
- });
468
- });
469
-
470
- /* ── Wishlist toggle ── */
471
- document.addEventListener('click', e => {
472
- if (e.target.classList.contains('btn-wishlist')) {
473
- e.target.textContent = e.target.textContent === '♡' ? '♥' : '♡';
474
- e.target.style.color = e.target.textContent === '♥' ? '#f87171' : '';
475
- }
476
- });
477
-
478
- /* ── Theme Toggle (3-State: Light, Dark, System) ── */
479
- const themeToggle = document.getElementById('themeToggle');
480
- const sunIcon = themeToggle.querySelector('.sun-icon');
481
- const moonIcon = themeToggle.querySelector('.moon-icon');
482
- const systemIcon = themeToggle.querySelector('.system-icon');
483
-
484
- const modes = ['light', 'dark', 'system'];
485
-
486
- const getNextMode = (current) => {
487
- const idx = modes.indexOf(current);
488
- return modes[(idx + 1) % modes.length];
489
- };
490
-
491
- const updateUI = (mode) => {
492
- // Show correct icon
493
- sunIcon.classList.toggle('hidden', mode !== 'light');
494
- moonIcon.classList.toggle('hidden', mode !== 'dark');
495
- systemIcon.classList.toggle('hidden', mode !== 'system');
496
-
497
- // Apply theme
498
- let themeToApply = mode;
499
- if (mode === 'system') {
500
- themeToApply = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
501
- }
502
- document.documentElement.setAttribute('data-theme', themeToApply);
503
- };
504
-
505
- themeToggle.addEventListener('click', () => {
506
- const currentMode = localStorage.getItem('nova-mode') || 'system';
507
- const nextMode = getNextMode(currentMode);
508
-
509
- localStorage.setItem('nova-mode', nextMode);
510
- updateUI(nextMode);
511
- });
512
-
513
- // OS Preference Listener
514
- window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
515
- if ((localStorage.getItem('nova-mode') || 'system') === 'system') {
516
- updateUI('system');
517
- }
518
- });
519
-
520
- // Initialize
521
- const savedMode = localStorage.getItem('nova-mode') || 'system';
522
- updateUI(savedMode);
523
- </script>
524
- </body>
525
- </html>