create-frootkit 1.2.8 → 1.2.9

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 (40) hide show
  1. package/package.json +1 -1
  2. package/templates/auth/src/app/dashboard/layout.tsx +14 -9
  3. package/templates/auth/src/app/dashboard/page.tsx +55 -24
  4. package/templates/auth/src/app/layout.tsx +3 -3
  5. package/templates/auth/src/app/login/page.tsx +5 -1
  6. package/templates/auth/src/app/page.tsx +103 -45
  7. package/templates/auth/src/app/signup/page.tsx +5 -1
  8. package/templates/auth/src/components/AuthForm.tsx +34 -19
  9. package/templates/auth/src/components/DashboardNav.tsx +97 -56
  10. package/templates/auth/src/components/MetricCard.tsx +13 -6
  11. package/templates/auth/src/components/Navbar.tsx +13 -12
  12. package/templates/auth/src/styles.css +27 -5
  13. package/templates/blog/src/app/blog/[slug]/page.tsx +19 -18
  14. package/templates/blog/src/app/layout.tsx +4 -4
  15. package/templates/blog/src/app/page.tsx +15 -14
  16. package/templates/blog/src/components/Footer.tsx +6 -6
  17. package/templates/blog/src/components/Navbar.tsx +17 -15
  18. package/templates/blog/src/components/Newsletter.tsx +11 -9
  19. package/templates/blog/src/components/PostCard.tsx +29 -27
  20. package/templates/blog/src/styles.css +14 -5
  21. package/templates/ecommerce/src/app/cart/page.tsx +3 -3
  22. package/templates/ecommerce/src/app/layout.tsx +2 -2
  23. package/templates/ecommerce/src/app/page.tsx +37 -15
  24. package/templates/ecommerce/src/app/products/[id]/page.tsx +34 -25
  25. package/templates/ecommerce/src/components/CartDrawer.tsx +20 -17
  26. package/templates/ecommerce/src/components/Footer.tsx +6 -6
  27. package/templates/ecommerce/src/components/Navbar.tsx +21 -14
  28. package/templates/ecommerce/src/components/ProductCard.tsx +22 -15
  29. package/templates/ecommerce/src/data/products.ts +17 -11
  30. package/templates/ecommerce/src/styles.css +29 -5
  31. package/templates/empty/src/app/layout.tsx +5 -5
  32. package/templates/empty/src/app/page.tsx +10 -9
  33. package/templates/empty/src/styles.css +13 -15
  34. package/templates/starter/src/app/layout.tsx +4 -4
  35. package/templates/starter/src/app/page.tsx +41 -33
  36. package/templates/starter/src/components/FeatureCard.tsx +5 -5
  37. package/templates/starter/src/components/Footer.tsx +6 -6
  38. package/templates/starter/src/components/Header.tsx +18 -14
  39. package/templates/starter/src/components/TerminalPreview.tsx +30 -30
  40. package/templates/starter/src/styles.css +14 -5
@@ -1,21 +1,23 @@
1
1
  export function Newsletter() {
2
2
  return (
3
- <div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-8 sm:p-10 my-16">
3
+ <div id="newsletter" class="rounded-xl border border-white/[0.08] bg-[#0f1117] p-8 sm:p-10 my-16 shadow-[inset_0_1px_0_0_rgba(255,255,255,0.05)] relative overflow-hidden">
4
+ <div class="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-indigo-500/30 to-transparent" />
4
5
  <div class="max-w-xl">
5
- <div class="text-xs font-mono font-medium text-emerald-400 mb-2 uppercase tracking-wide">
6
- Engineering Dispatch
6
+ <div class="inline-flex items-center gap-2 px-2.5 py-0.5 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 text-[11px] font-medium mb-3">
7
+ <span class="w-1.5 h-1.5 rounded-full bg-indigo-400" />
8
+ <span>Engineering Dispatch</span>
7
9
  </div>
8
- <h3 class="text-2xl font-bold text-white mb-2">
10
+ <h3 class="text-xl sm:text-2xl font-semibold text-white tracking-tight mb-2">
9
11
  Subscribe for Technical Deep Dives
10
12
  </h3>
11
- <p class="text-slate-400 text-sm mb-6 leading-relaxed">
12
- Bi-weekly write-ups on sub-millisecond server rendering, zero-hydration architectures, and high-performance TypeScript.
13
+ <p class="text-zinc-400 text-xs sm:text-sm mb-6 leading-relaxed">
14
+ Bi-weekly write-ups on sub-millisecond server rendering, zero-hydration architectures, and high-performance TypeScript runtime optimizations.
13
15
  </p>
14
16
 
15
17
  <form
16
18
  action="/api/posts"
17
19
  method="GET"
18
- class="flex flex-col sm:flex-row gap-3 max-w-md"
20
+ class="flex flex-col sm:flex-row gap-2.5 max-w-md"
19
21
  >
20
22
  <label class="sr-only" for="newsletter-email">Work Email</label>
21
23
  <input
@@ -23,11 +25,11 @@ export function Newsletter() {
23
25
  type="email"
24
26
  placeholder="developer@company.com"
25
27
  required
26
- class="flex-1 px-4 py-2.5 rounded-lg bg-[#06090f] border border-[#1a2333] text-white text-sm focus:outline-none focus:border-emerald-500 transition-colors"
28
+ class="flex-1 px-3.5 py-2 rounded-lg bg-[#08090a] border border-white/[0.08] text-white text-xs placeholder:text-zinc-600 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 transition-colors"
27
29
  />
28
30
  <button
29
31
  type="submit"
30
- class="px-5 py-2.5 rounded-lg bg-emerald-500 text-slate-950 font-semibold hover:bg-emerald-400 transition-colors text-sm"
32
+ class="px-4 py-2 rounded-lg bg-white text-zinc-950 font-medium hover:bg-zinc-200 transition-all text-xs shadow-sm"
31
33
  >
32
34
  Subscribe
33
35
  </button>
@@ -3,45 +3,46 @@ import type { Post } from '../data/posts.js';
3
3
  export function PostCard({ post, featured = false }: { post: Post; featured?: boolean }) {
4
4
  if (featured) {
5
5
  return (
6
- <article class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-8 hover:border-slate-700 transition-colors mb-10">
7
- <div class="flex items-center gap-3 mb-4 text-xs font-mono">
8
- <span class="text-emerald-400 font-semibold px-2.5 py-0.5 rounded bg-emerald-500/10 border border-emerald-500/20">
6
+ <article class="rounded-xl border border-white/[0.08] bg-[#0f1117] p-7 sm:p-8 hover:border-white/[0.18] transition-all duration-200 mb-10 shadow-[inset_0_1px_0_0_rgba(255,255,255,0.05)] group">
7
+ <div class="flex flex-wrap items-center gap-2.5 mb-4 text-xs">
8
+ <span class="text-indigo-400 font-medium px-2.5 py-0.5 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-[11px]">
9
9
  Featured • {post.category}
10
10
  </span>
11
- <span class="text-slate-500">•</span>
12
- <span class="text-slate-400">{post.readTime}</span>
13
- <span class="text-slate-500">•</span>
14
- <span class="text-slate-400">{post.date}</span>
11
+ <span class="text-zinc-600">•</span>
12
+ <span class="text-zinc-400">{post.readTime}</span>
13
+ <span class="text-zinc-600">•</span>
14
+ <span class="text-zinc-400">{post.date}</span>
15
15
  </div>
16
16
 
17
- <h2 class="text-2xl sm:text-3xl font-extrabold text-white mb-4 leading-snug hover:text-emerald-400 transition-colors">
17
+ <h2 class="text-2xl sm:text-3xl font-semibold text-white mb-3 tracking-[-0.02em] leading-snug group-hover:text-indigo-300 transition-colors">
18
18
  <a href={`/blog/${post.slug}`}>
19
19
  {post.title}
20
20
  </a>
21
21
  </h2>
22
22
 
23
- <p class="text-slate-300 text-base leading-relaxed mb-6 max-w-3xl">
23
+ <p class="text-zinc-400 text-sm sm:text-base leading-relaxed mb-6 max-w-3xl">
24
24
  {post.summary}
25
25
  </p>
26
26
 
27
- <div class="pt-6 border-t border-[#1a2333] flex items-center justify-between">
27
+ <div class="pt-6 border-t border-white/[0.06] flex items-center justify-between">
28
28
  <div class="flex items-center gap-3">
29
29
  <img
30
30
  src={post.author.avatar}
31
31
  alt={post.author.name}
32
- class="w-8 h-8 rounded-full object-cover border border-[#1a2333]"
32
+ class="w-8 h-8 rounded-full object-cover border border-white/[0.1]"
33
33
  />
34
34
  <div class="text-xs">
35
- <span class="font-medium text-white block">{post.author.name}</span>
36
- <span class="text-slate-500">{post.author.role}</span>
35
+ <span class="font-medium text-zinc-200 block">{post.author.name}</span>
36
+ <span class="text-zinc-500">{post.author.role}</span>
37
37
  </div>
38
38
  </div>
39
39
 
40
40
  <a
41
41
  href={`/blog/${post.slug}`}
42
- class="text-emerald-400 text-xs font-semibold hover:text-emerald-300 transition-colors flex items-center gap-1"
42
+ class="text-zinc-200 text-xs font-medium group-hover:text-white transition-colors flex items-center gap-1.5"
43
43
  >
44
- Read Article →
44
+ <span>Read Article</span>
45
+ <span class="text-zinc-500 group-hover:translate-x-0.5 transition-transform">→</span>
45
46
  </a>
46
47
  </div>
47
48
  </article>
@@ -49,44 +50,45 @@ export function PostCard({ post, featured = false }: { post: Post; featured?: bo
49
50
  }
50
51
 
51
52
  return (
52
- <article class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-6 hover:border-slate-700 transition-colors flex flex-col justify-between">
53
+ <article class="rounded-xl border border-white/[0.08] bg-[#0f1117] p-5 sm:p-6 hover:border-white/[0.18] transition-all duration-200 flex flex-col justify-between shadow-[inset_0_1px_0_0_rgba(255,255,255,0.05)] group">
53
54
  <div>
54
- <div class="flex items-center justify-between mb-3 text-xs font-mono">
55
- <span class="text-emerald-400 font-semibold px-2 py-0.5 rounded bg-emerald-500/10 border border-emerald-500/20">
55
+ <div class="flex items-center justify-between mb-3 text-xs">
56
+ <span class="text-zinc-300 font-medium px-2 py-0.5 rounded-full bg-white/[0.04] border border-white/[0.06] text-[10px]">
56
57
  {post.category}
57
58
  </span>
58
- <span class="text-slate-500">{post.readTime}</span>
59
+ <span class="text-zinc-500 text-[11px]">{post.readTime}</span>
59
60
  </div>
60
61
 
61
- <h3 class="text-lg font-bold text-white mb-3 hover:text-emerald-400 transition-colors line-clamp-2 leading-snug">
62
+ <h3 class="text-base font-semibold text-zinc-100 mb-2.5 group-hover:text-white transition-colors line-clamp-2 leading-snug">
62
63
  <a href={`/blog/${post.slug}`}>
63
64
  {post.title}
64
65
  </a>
65
66
  </h3>
66
67
 
67
- <p class="text-slate-400 text-sm leading-relaxed mb-6 line-clamp-3">
68
+ <p class="text-zinc-400 text-xs leading-relaxed mb-6 line-clamp-3">
68
69
  {post.summary}
69
70
  </p>
70
71
  </div>
71
72
 
72
- <div class="pt-4 border-t border-[#1a2333] flex items-center justify-between">
73
+ <div class="pt-4 border-t border-white/[0.06] flex items-center justify-between">
73
74
  <div class="flex items-center gap-2.5">
74
75
  <img
75
76
  src={post.author.avatar}
76
77
  alt={post.author.name}
77
- class="w-6 h-6 rounded-full object-cover border border-[#1a2333]"
78
+ class="w-6 h-6 rounded-full object-cover border border-white/[0.1]"
78
79
  />
79
80
  <div class="text-[11px]">
80
- <span class="font-medium text-slate-200 block">{post.author.name}</span>
81
- <span class="text-slate-500">{post.date}</span>
81
+ <span class="font-medium text-zinc-300 block">{post.author.name}</span>
82
+ <span class="text-zinc-500">{post.date}</span>
82
83
  </div>
83
84
  </div>
84
85
 
85
86
  <a
86
87
  href={`/blog/${post.slug}`}
87
- class="text-emerald-400 text-xs font-semibold hover:text-emerald-300 transition-colors"
88
+ class="text-xs font-medium text-zinc-400 group-hover:text-white transition-colors flex items-center gap-1"
88
89
  >
89
- Read →
90
+ <span>Read</span>
91
+ <span class="text-zinc-600">→</span>
90
92
  </a>
91
93
  </div>
92
94
  </article>
@@ -4,23 +4,32 @@
4
4
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
5
5
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
6
6
 
7
- --color-brand-primary: #10b981;
8
- --color-brand-hover: #34d399;
7
+ --color-brand-primary: #6366f1;
8
+ --color-brand-hover: #4f46e5;
9
9
  }
10
10
 
11
11
  :root {
12
12
  color-scheme: dark;
13
+ --bg-canvas: #08090a;
14
+ --bg-surface: #0f1117;
15
+ --bg-elevated: #151822;
16
+ --border-subtle: rgba(255, 255, 255, 0.08);
17
+ --border-strong: rgba(255, 255, 255, 0.16);
18
+ --text-primary: #f4f4f5;
19
+ --text-secondary: #9496a1;
20
+ --text-muted: #5c6370;
13
21
  }
14
22
 
15
23
  html {
16
- background-color: #06090f;
17
- color: #f8fafc;
24
+ background-color: var(--bg-canvas);
25
+ color: var(--text-primary);
18
26
  font-family: var(--font-sans);
19
27
  scroll-behavior: smooth;
20
28
  -webkit-font-smoothing: antialiased;
29
+ -moz-osx-font-smoothing: grayscale;
21
30
  }
22
31
 
23
- /* SVG safety: prevents flex ballooning across all browsers */
32
+ /* Strict SVG safety to prevent flex ballooning */
24
33
  svg {
25
34
  flex-shrink: 0;
26
35
  max-width: 100%;
@@ -8,11 +8,11 @@ export const metadata = {
8
8
 
9
9
  export default function CartPage() {
10
10
  return (
11
- <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
11
+ <div class="min-h-screen bg-[#090a0f] text-zinc-100 flex flex-col justify-between selection:bg-white/20 selection:text-white">
12
12
  <Navbar />
13
13
 
14
- <main class="max-w-4xl mx-auto px-6 py-12 flex-1 w-full">
15
- <h1 class="text-3xl font-extrabold text-white mb-8">Order Cart</h1>
14
+ <main class="max-w-3xl mx-auto px-6 py-12 flex-1 w-full">
15
+ <h1 class="text-2xl font-semibold text-white tracking-tight mb-6">Shopping Cart</h1>
16
16
  <CartDrawer />
17
17
  </main>
18
18
 
@@ -24,12 +24,12 @@ export default function RootLayout({ children, metadata }: RootLayoutProps) {
24
24
  <link rel="preconnect" href="https://fonts.googleapis.com" />
25
25
  <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
26
26
  <link
27
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap"
27
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
28
28
  rel="stylesheet"
29
29
  />
30
30
  <link rel="stylesheet" href="/styles.css" />
31
31
  </head>
32
- <body class="bg-[#030712] text-slate-100 min-h-screen antialiased selection:bg-emerald-500/20 selection:text-emerald-300 font-sans">
32
+ <body class="bg-[#090a0f] text-zinc-100 min-h-screen antialiased selection:bg-white/20 selection:text-white font-sans">
33
33
  {children}
34
34
  </body>
35
35
  </html>
@@ -4,36 +4,58 @@ import { ProductCard } from '../components/ProductCard.js';
4
4
  import { Footer } from '../components/Footer.js';
5
5
 
6
6
  export const metadata = {
7
- title: 'FrootStore — Hardware Instruments for Developers',
7
+ title: 'FrootStore — Tactile Instruments for Developers',
8
8
  description: 'Precision mechanical keyboards, studio audio, and ergonomic setups.',
9
9
  };
10
10
 
11
11
  export default function StoreHomePage() {
12
+ const categories = ['All Products', 'Keyboards', 'Audio', 'Peripherals', 'Desk Setup', 'Accessories'];
13
+
12
14
  return (
13
- <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
15
+ <div class="min-h-screen bg-[#090a0f] text-zinc-100 flex flex-col justify-between selection:bg-white/20 selection:text-white">
14
16
  <Navbar />
15
17
 
16
- <main class="max-w-6xl mx-auto px-6 py-12 flex-1 w-full">
17
- {/* Collection Header */}
18
- <div class="mb-12 border-b border-[#1a2333] pb-8">
19
- <div class="text-xs font-mono font-medium text-emerald-400 mb-2 uppercase tracking-wide">
20
- Curated Instruments
18
+ <main class="max-w-6xl mx-auto px-6 py-12 sm:py-16 flex-1 w-full">
19
+ {/* Curated Collection Hero */}
20
+ <div class="mb-12 border-b border-white/[0.08] pb-10">
21
+ <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/[0.04] border border-white/[0.08] text-zinc-300 text-xs font-medium mb-4">
22
+ <span class="w-1.5 h-1.5 rounded-full bg-emerald-400" />
23
+ <span>Curated Hardware Collection</span>
21
24
  </div>
22
- <h1 class="text-3xl sm:text-5xl font-extrabold text-white tracking-tight mb-3">
23
- Hardware Engineered for Precision
25
+
26
+ <h1 class="text-3xl sm:text-5xl font-semibold text-white tracking-[-0.03em] leading-tight mb-4">
27
+ Tactile Instruments for Focused Engineering.
24
28
  </h1>
25
- <p class="text-slate-400 text-base max-w-2xl leading-relaxed">
26
- Tactile peripherals and minimal workspace instruments designed to eliminate friction from extended coding sessions.
29
+
30
+ <p class="text-zinc-400 text-base max-w-2xl leading-relaxed">
31
+ Minimal workspace instruments, CNC aluminum mechanical keyboards, and planar audio drivers designed to eliminate friction from extended development sessions.
27
32
  </p>
33
+
34
+ {/* Category Filter Pills */}
35
+ <div class="flex flex-wrap items-center gap-2 mt-8">
36
+ {categories.map((c, i) => (
37
+ <a
38
+ key={c}
39
+ href="/#catalog"
40
+ class={`px-3 py-1 rounded-full text-xs font-medium transition-colors ${
41
+ i === 0
42
+ ? 'bg-white text-zinc-950 shadow-sm'
43
+ : 'bg-white/[0.04] border border-white/[0.08] text-zinc-400 hover:text-white hover:bg-white/[0.08]'
44
+ }`}
45
+ >
46
+ {c}
47
+ </a>
48
+ ))}
49
+ </div>
28
50
  </div>
29
51
 
30
52
  {/* Catalog Section Header */}
31
53
  <div id="catalog" class="mb-6 flex items-center justify-between">
32
- <h2 class="text-xs font-mono uppercase tracking-wider text-slate-400 font-semibold">
33
- All Products
54
+ <h2 class="text-xs uppercase tracking-wider text-zinc-400 font-semibold">
55
+ Featured Instruments
34
56
  </h2>
35
- <span class="text-xs font-mono text-slate-500">
36
- {PRODUCTS.length} instruments available
57
+ <span class="text-xs text-zinc-500 tabular-nums">
58
+ {PRODUCTS.length} products available
37
59
  </span>
38
60
  </div>
39
61
 
@@ -11,73 +11,82 @@ export default function ProductDetailPage({ params }: { params?: { id?: string }
11
11
  const product = PRODUCTS.find((p) => p.id === id) || PRODUCTS[0]!;
12
12
 
13
13
  return (
14
- <div class="min-h-screen bg-[#06090f] text-slate-100 flex flex-col justify-between">
14
+ <div class="min-h-screen bg-[#090a0f] text-zinc-100 flex flex-col justify-between selection:bg-white/20 selection:text-white">
15
15
  <Navbar />
16
16
 
17
17
  <main class="max-w-6xl mx-auto px-6 py-12 flex-1 w-full">
18
18
  <a
19
19
  href="/"
20
- class="inline-flex items-center gap-2 text-xs font-mono text-slate-400 hover:text-emerald-400 mb-8 transition-colors"
20
+ class="inline-flex items-center gap-2 text-xs text-zinc-400 hover:text-white mb-8 transition-colors"
21
21
  >
22
- ← Back to catalog
22
+ <span>←</span>
23
+ <span>Back to catalog</span>
23
24
  </a>
24
25
 
25
- <div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-start">
26
- <div class="rounded-xl border border-[#1a2333] overflow-hidden bg-[#0a0f18] aspect-[4/3]">
26
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-16 items-start">
27
+ {/* Product Gallery Image */}
28
+ <div class="rounded-2xl border border-white/[0.08] overflow-hidden bg-[#0f1117] aspect-[4/3] shadow-2xl relative">
27
29
  <img
28
30
  src={product.image}
29
31
  alt={product.name}
30
32
  class="w-full h-full object-cover"
31
33
  />
34
+ <div class="absolute inset-0 bg-gradient-to-t from-black/30 via-transparent to-transparent pointer-events-none" />
32
35
  </div>
33
36
 
37
+ {/* Details & Purchase */}
34
38
  <div>
35
- <div class="flex items-center gap-3 mb-3 text-xs font-mono">
36
- <span class="px-2.5 py-0.5 rounded bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 font-semibold">
39
+ <div class="flex items-center gap-3 mb-3 text-xs">
40
+ <span class="px-2.5 py-0.5 rounded-full bg-white/[0.04] text-zinc-300 border border-white/[0.08] font-medium text-[11px] uppercase tracking-wider">
37
41
  {product.category}
38
42
  </span>
39
- <span class="text-slate-500">•</span>
40
- <span class="text-slate-300 font-semibold">
41
- {product.rating.toFixed(1)} / 5.0 ({product.reviewsCount} reviews)
42
- </span>
43
+ <span class="text-zinc-600">•</span>
44
+ <div class="flex items-center gap-1.5 text-zinc-400 font-medium">
45
+ <span class="text-amber-400">★</span>
46
+ <span class="text-zinc-200 tabular-nums">{product.rating.toFixed(1)}</span>
47
+ <span class="text-zinc-500 tabular-nums">({product.reviewsCount} verified reviews)</span>
48
+ </div>
43
49
  </div>
44
50
 
45
- <h1 class="text-3xl sm:text-4xl font-extrabold text-white tracking-tight mb-4">
51
+ <h1 class="text-3xl sm:text-4xl font-semibold text-white tracking-[-0.025em] mb-4">
46
52
  {product.name}
47
53
  </h1>
48
54
 
49
- <div class="text-3xl font-bold text-white mb-6 font-mono">
55
+ <div class="text-3xl font-semibold text-white mb-6 tabular-nums">
50
56
  ${product.price.toFixed(2)}
51
57
  </div>
52
58
 
53
- <p class="text-slate-300 text-base leading-relaxed mb-8">
59
+ <p class="text-zinc-300 text-sm sm:text-base leading-relaxed mb-8">
54
60
  {product.description}
55
61
  </p>
56
62
 
57
- <div class="border-t border-[#1a2333] pt-6 mb-8">
58
- <h2 class="text-xs font-mono uppercase tracking-wider font-semibold text-slate-400 mb-4">
59
- Engineering Specifications
63
+ <div class="border-t border-white/[0.08] pt-6 mb-8">
64
+ <h2 class="text-xs uppercase tracking-wider font-semibold text-zinc-400 mb-4">
65
+ Hardware Specifications
60
66
  </h2>
61
- <ul class="grid grid-cols-1 sm:grid-cols-2 gap-3 text-sm text-slate-300 font-mono">
67
+ <ul class="grid grid-cols-1 sm:grid-cols-2 gap-3 text-xs text-zinc-300">
62
68
  {product.features.map((f) => (
63
69
  <li key={f} class="flex items-center gap-2">
64
- <span class="text-emerald-400 font-bold">✓</span>
70
+ <span class="w-1.5 h-1.5 rounded-full bg-zinc-400 shrink-0" />
65
71
  <span>{f}</span>
66
72
  </li>
67
73
  ))}
68
74
  </ul>
69
75
  </div>
70
76
 
71
- <div class="flex items-center gap-4">
77
+ <div class="flex flex-col sm:flex-row sm:items-center gap-4 pt-2">
72
78
  <a
73
79
  href="/cart"
74
- class="flex-1 py-3 rounded-lg bg-emerald-500 text-slate-950 font-semibold text-center text-sm hover:bg-emerald-400 transition-colors"
80
+ class="flex-1 py-3 px-6 rounded-xl bg-white text-zinc-950 font-medium text-center text-sm hover:bg-zinc-200 transition-all shadow-md flex items-center justify-center gap-2"
75
81
  >
76
- Add to Cart • ${product.price.toFixed(2)}
82
+ <span>Add to Cart</span>
83
+ <span class="text-zinc-500">•</span>
84
+ <span class="tabular-nums font-semibold">${product.price.toFixed(2)}</span>
77
85
  </a>
78
- <span class="text-xs text-slate-400 font-mono">
79
- {product.inStock ? 'In Stock (Ships in 24h)' : 'Backorder'}
80
- </span>
86
+ <div class="flex items-center gap-2 text-xs text-zinc-400 px-3">
87
+ <span class="w-2 h-2 rounded-full bg-emerald-400" />
88
+ <span>{product.inStock ? 'In Stock · Ships in 24h' : 'Backorder'}</span>
89
+ </div>
81
90
  </div>
82
91
  </div>
83
92
  </div>
@@ -11,52 +11,55 @@ export function CartDrawer() {
11
11
  const total = subtotal + shipping;
12
12
 
13
13
  return (
14
- <div class="rounded-xl border border-[#1a2333] bg-[#0a0f18] p-6 sm:p-8">
15
- <h2 class="text-lg font-bold text-white mb-6 flex items-center justify-between border-b border-[#1a2333] pb-4">
14
+ <div class="rounded-xl border border-white/[0.08] bg-[#0f1117] p-6 sm:p-8 shadow-xl">
15
+ <h2 class="text-base font-semibold text-white mb-6 flex items-center justify-between border-b border-white/[0.08] pb-4">
16
16
  <span>Order Summary</span>
17
- <span class="text-xs font-mono text-emerald-400 font-semibold">{cartItems.length} items</span>
17
+ <span class="text-xs text-zinc-400 font-medium px-2 py-0.5 rounded-full bg-white/[0.04] border border-white/[0.06] tabular-nums">
18
+ {cartItems.length} items
19
+ </span>
18
20
  </h2>
19
21
 
20
22
  <div class="space-y-4 mb-6">
21
23
  {cartItems.map(({ product, quantity }) => (
22
- <div key={product.id} class="flex items-center gap-4 pb-4 border-b border-[#1a2333]">
24
+ <div key={product.id} class="flex items-center gap-4 pb-4 border-b border-white/[0.06]">
23
25
  <img
24
26
  src={product.image}
25
27
  alt={product.name}
26
- class="w-14 h-14 rounded-lg object-cover bg-[#06090f] border border-[#1a2333]"
28
+ class="w-14 h-14 rounded-lg object-cover bg-zinc-950/40 border border-white/[0.08]"
27
29
  />
28
30
  <div class="flex-1 min-w-0">
29
- <h4 class="text-sm font-semibold text-white truncate">{product.name}</h4>
30
- <div class="text-xs text-slate-400 font-mono mt-0.5">Qty: {quantity} × ${product.price.toFixed(2)}</div>
31
+ <h4 class="text-xs sm:text-sm font-medium text-zinc-100 truncate">{product.name}</h4>
32
+ <div class="text-xs text-zinc-400 mt-0.5 tabular-nums">Qty: {quantity} × ${product.price.toFixed(2)}</div>
31
33
  </div>
32
- <div class="font-bold text-sm text-white font-mono">
34
+ <div class="font-medium text-xs sm:text-sm text-white tabular-nums">
33
35
  ${(product.price * quantity).toFixed(2)}
34
36
  </div>
35
37
  </div>
36
38
  ))}
37
39
  </div>
38
40
 
39
- <div class="space-y-2.5 text-xs text-slate-300 mb-6 font-mono">
41
+ <div class="space-y-2.5 text-xs text-zinc-300 mb-6">
40
42
  <div class="flex justify-between">
41
- <span class="text-slate-400">Subtotal</span>
42
- <span class="text-white font-bold">${subtotal.toFixed(2)}</span>
43
+ <span class="text-zinc-400">Subtotal</span>
44
+ <span class="text-white font-medium tabular-nums">${subtotal.toFixed(2)}</span>
43
45
  </div>
44
46
  <div class="flex justify-between">
45
- <span class="text-slate-400">Standard Shipping</span>
46
- <span class="text-emerald-400 font-semibold">{shipping === 0 ? 'FREE' : `$${shipping.toFixed(2)}`}</span>
47
+ <span class="text-zinc-400">Standard Shipping</span>
48
+ <span class="text-emerald-400 font-medium">{shipping === 0 ? 'FREE' : `$${shipping.toFixed(2)}`}</span>
47
49
  </div>
48
- <div class="pt-3 border-t border-[#1a2333] flex justify-between text-sm text-white font-bold">
50
+ <div class="pt-3 border-t border-white/[0.08] flex justify-between text-sm text-white font-semibold">
49
51
  <span>Total</span>
50
- <span class="text-emerald-400 text-base font-mono font-black">${total.toFixed(2)}</span>
52
+ <span class="text-base text-white tabular-nums">${total.toFixed(2)}</span>
51
53
  </div>
52
54
  </div>
53
55
 
54
56
  <form action="/api/checkout" method="POST">
55
57
  <button
56
58
  type="submit"
57
- class="w-full py-3 rounded-lg bg-emerald-500 text-slate-950 font-semibold text-sm hover:bg-emerald-400 transition-colors"
59
+ class="w-full py-3 rounded-lg bg-white text-zinc-950 font-medium text-xs hover:bg-zinc-200 transition-all shadow-sm flex items-center justify-center gap-2 group"
58
60
  >
59
- Proceed to Checkout →
61
+ <span>Proceed to Checkout</span>
62
+ <span class="text-zinc-500 group-hover:translate-x-0.5 transition-transform">→</span>
60
63
  </button>
61
64
  </form>
62
65
  </div>
@@ -1,14 +1,14 @@
1
1
  export function Footer() {
2
2
  return (
3
- <footer class="border-t border-[#1a2333] bg-[#06090f] py-8 text-xs text-slate-400">
4
- <div class="max-w-6xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4 font-mono">
3
+ <footer class="border-t border-white/[0.08] bg-[#090a0f] py-8 text-xs text-zinc-500">
4
+ <div class="max-w-6xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4">
5
5
  <div>
6
- FrootStore © {new Date().getFullYear()} OrbitNorth LLC. MIT Licensed.
6
+ FrootStore © {new Date().getFullYear()} OrbitNorth LLC. Built with FrootKit.
7
7
  </div>
8
8
  <div class="flex items-center gap-6">
9
- <a href="https://github.com/orbitnorth/frootkit" class="hover:text-white transition-colors">GitHub</a>
10
- <a href="https://frootjs.org" class="hover:text-white transition-colors">Documentation</a>
11
- <a href="/api/products" class="hover:text-white transition-colors">Products API</a>
9
+ <a href="https://github.com/orbitnorth/frootkit" class="hover:text-zinc-300 transition-colors">GitHub</a>
10
+ <a href="https://frootjs.org" class="hover:text-zinc-300 transition-colors">Documentation</a>
11
+ <a href="/api/products" class="hover:text-zinc-300 transition-colors font-mono text-[11px]">/api/products</a>
12
12
  </div>
13
13
  </div>
14
14
  </footer>
@@ -1,32 +1,39 @@
1
1
  export function Navbar() {
2
2
  return (
3
- <header class="border-b border-[#1a2333] bg-[#06090f]/95 sticky top-0 z-50">
4
- <div class="max-w-6xl mx-auto px-6 h-16 flex items-center justify-between">
5
- <a href="/" class="flex items-center gap-3 font-bold text-white text-base tracking-tight hover:text-emerald-400 transition-colors">
6
- <div class="w-8 h-8 rounded-lg bg-emerald-500/10 border border-emerald-500/30 flex items-center justify-center text-emerald-400">
7
- <svg width="16" height="16" class="w-4 h-4 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
8
- <path stroke-linecap="round" stroke-linejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" />
3
+ <header class="border-b border-white/[0.08] bg-[#090a0f]/80 backdrop-blur-md sticky top-0 z-50">
4
+ <div class="max-w-6xl mx-auto px-6 h-14 flex items-center justify-between">
5
+ <a href="/" class="flex items-center gap-2.5 font-semibold text-zinc-100 text-sm tracking-tight group">
6
+ <div class="w-7 h-7 rounded-md bg-white/[0.06] border border-white/[0.1] flex items-center justify-center text-zinc-200 group-hover:border-white/[0.2] transition-colors shrink-0">
7
+ <svg style="width: 14px; height: 14px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
8
+ <path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z" />
9
+ <line x1="3" y1="6" x2="21" y2="6" />
10
+ <path d="M16 10a4 4 0 0 1-8 0" />
9
11
  </svg>
10
12
  </div>
11
- <span>Froot<span class="text-emerald-400">Store</span></span>
13
+ <span>Froot<span class="text-zinc-400 font-normal">Store</span></span>
12
14
  </a>
13
15
 
14
- <nav class="flex items-center gap-6 text-sm font-medium">
15
- <a href="/" class="text-slate-300 hover:text-white transition-colors">
16
+ <nav class="flex items-center gap-5 text-xs font-medium">
17
+ <a href="/#catalog" class="text-zinc-400 hover:text-zinc-200 transition-colors">
16
18
  Catalog
17
19
  </a>
18
- <a href="/api/products" class="text-emerald-400 hover:text-emerald-300 font-mono text-xs px-2.5 py-1 rounded-md bg-[#0a0f18] border border-[#1a2333] transition-colors">
20
+ <a
21
+ href="/api/products"
22
+ class="text-zinc-400 hover:text-zinc-200 font-mono text-[11px] px-2 py-0.5 rounded bg-white/[0.03] border border-white/[0.06] transition-colors"
23
+ >
19
24
  /api/products
20
25
  </a>
21
26
  <a
22
27
  href="/cart"
23
- class="flex items-center gap-2 px-3.5 py-1.5 rounded-lg bg-[#0a0f18] border border-[#1a2333] text-slate-200 hover:border-slate-700 hover:text-white transition-colors text-xs font-semibold"
28
+ class="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-white/[0.05] border border-white/[0.08] text-zinc-200 hover:text-white hover:bg-white/[0.08] transition-all text-xs font-medium"
24
29
  >
25
- <svg width="14" height="14" class="w-3.5 h-3.5 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
26
- <path stroke-linecap="round" stroke-linejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" />
30
+ <svg style="width: 13px; height: 13px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
31
+ <path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z" />
32
+ <line x1="3" y1="6" x2="21" y2="6" />
33
+ <path d="M16 10a4 4 0 0 1-8 0" />
27
34
  </svg>
28
35
  <span>Cart</span>
29
- <span class="px-1.5 py-0.2 rounded bg-emerald-500 text-slate-950 font-bold text-[10px]">
36
+ <span class="px-1.5 py-0.2 rounded-full bg-white text-zinc-950 font-bold text-[10px] tabular-nums">
30
37
  2
31
38
  </span>
32
39
  </a>