create-brainerce-store 1.21.0 → 1.22.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/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var require_package = __commonJS({
31
31
  "package.json"(exports2, module2) {
32
32
  module2.exports = {
33
33
  name: "create-brainerce-store",
34
- version: "1.21.0",
34
+ version: "1.22.0",
35
35
  description: "Scaffold a production-ready e-commerce storefront connected to Brainerce",
36
36
  bin: {
37
37
  "create-brainerce-store": "dist/index.js"
@@ -220,8 +220,16 @@ async function runInteractive(defaults) {
220
220
  description: "Clean, neutral design with Inter font",
221
221
  value: "minimal"
222
222
  },
223
- { title: "Luxury (coming soon)", value: "luxury", disabled: true },
224
- { title: "Playful (coming soon)", value: "playful", disabled: true }
223
+ {
224
+ title: "Luxury",
225
+ description: "Dark, sophisticated design with Cormorant Garamond serif font",
226
+ value: "luxury"
227
+ },
228
+ {
229
+ title: "Playful",
230
+ description: "Warm, vibrant design with Nunito rounded font",
231
+ value: "playful"
232
+ }
225
233
  ],
226
234
  initial: 0
227
235
  },
@@ -260,8 +268,23 @@ var import_ejs = __toESM(require("ejs"));
260
268
  function getDirection(language) {
261
269
  return language === "he" ? "rtl" : "ltr";
262
270
  }
263
- function getFontConfig(language) {
264
- if (language === "he") {
271
+ function getFontConfig(language, theme) {
272
+ const isHebrew = language === "he";
273
+ if (theme === "luxury") {
274
+ const subsets = isHebrew ? "['latin']" : "['latin']";
275
+ return {
276
+ fontImport: "import { Cormorant_Garamond } from 'next/font/google';",
277
+ fontVariable: `const font = Cormorant_Garamond({ weight: ['400', '500', '600', '700'], subsets: ${subsets} });`
278
+ };
279
+ }
280
+ if (theme === "playful") {
281
+ const subsets = isHebrew ? "['latin']" : "['latin']";
282
+ return {
283
+ fontImport: "import { Nunito } from 'next/font/google';",
284
+ fontVariable: `const font = Nunito({ subsets: ${subsets} });`
285
+ };
286
+ }
287
+ if (isHebrew) {
265
288
  return {
266
289
  fontImport: "import { Rubik } from 'next/font/google';",
267
290
  fontVariable: "const font = Rubik({ subsets: ['hebrew', 'latin'] });"
@@ -288,7 +311,7 @@ async function scaffold(options) {
288
311
  throw new Error(`Template "${framework}" not found at ${baseDir}`);
289
312
  }
290
313
  const direction = getDirection(options.language);
291
- const fontConfig = getFontConfig(options.language);
314
+ const fontConfig = getFontConfig(options.language, theme);
292
315
  const ogLocale = options.language === "he" ? "he_IL" : "en_US";
293
316
  const isMultiLocale = options.i18n?.enabled === true && options.i18n.supportedLocales.length > 1;
294
317
  const supportedLocales = options.i18n?.supportedLocales || [options.language];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-brainerce-store",
3
- "version": "1.21.0",
3
+ "version": "1.22.0",
4
4
  "description": "Scaffold a production-ready e-commerce storefront connected to Brainerce",
5
5
  "bin": {
6
6
  "create-brainerce-store": "dist/index.js"
@@ -534,15 +534,45 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
534
534
 
535
535
  if (sdk.renderType === 'iframe') {
536
536
  return (
537
- <div className={cn('py-4', className)}>
538
- <iframe
539
- src={paymentIntent.clientSecret}
540
- className="w-full border-0"
541
- style={{ minHeight: '500px' }}
542
- title={t('payment')}
543
- allow="payment"
544
- />
545
- </div>
537
+ <>
538
+ {/* Modal overlay */}
539
+ <div className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/50 py-6 backdrop-blur-sm">
540
+ <div className="relative mx-4 w-full max-w-md rounded-2xl bg-white shadow-2xl">
541
+ {/* Close button */}
542
+ <button
543
+ onClick={() => {
544
+ window.location.href = `/checkout?checkout_id=${checkoutId}&canceled=true`;
545
+ }}
546
+ className="absolute end-3 top-3 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white/80 text-gray-500 shadow-sm transition-colors hover:bg-gray-100 hover:text-gray-700"
547
+ aria-label="Close"
548
+ >
549
+ <svg
550
+ width="14"
551
+ height="14"
552
+ viewBox="0 0 14 14"
553
+ fill="none"
554
+ stroke="currentColor"
555
+ strokeWidth="2"
556
+ strokeLinecap="round"
557
+ >
558
+ <path d="M1 1l12 12M13 1L1 13" />
559
+ </svg>
560
+ </button>
561
+ <iframe
562
+ src={paymentIntent.clientSecret}
563
+ className="w-full rounded-2xl border-0"
564
+ style={{ height: '80vh' }}
565
+ title={t('payment')}
566
+ allow="payment"
567
+ />
568
+ </div>
569
+ </div>
570
+ {/* Placeholder so the checkout layout doesn't collapse */}
571
+ <div className={cn('flex flex-col items-center justify-center py-12', className)}>
572
+ <LoadingSpinner size="lg" />
573
+ <p className="text-muted-foreground mt-4 text-sm">{t('preparingPayment')}</p>
574
+ </div>
575
+ </>
546
576
  );
547
577
  }
548
578
 
@@ -0,0 +1,399 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 20 14% 4%;
8
+ --foreground: 38 25% 86%;
9
+ --primary: 38 60% 55%;
10
+ --primary-foreground: 20 14% 4%;
11
+ --secondary: 20 10% 10%;
12
+ --secondary-foreground: 38 25% 86%;
13
+ --muted: 20 10% 12%;
14
+ --muted-foreground: 30 10% 50%;
15
+ --accent: 38 60% 55%;
16
+ --accent-foreground: 20 14% 4%;
17
+ --destructive: 0 72% 51%;
18
+ --destructive-foreground: 38 25% 86%;
19
+ --border: 30 10% 16%;
20
+ --radius: 0.25rem;
21
+
22
+ /* Luxury-specific tokens */
23
+ --gold: 38 60% 55%;
24
+ --gold-light: 38 50% 72%;
25
+ --gold-dark: 38 70% 40%;
26
+ --surface: 20 12% 7%;
27
+ --surface-elevated: 20 10% 10%;
28
+ }
29
+
30
+ * {
31
+ @apply border-border;
32
+ }
33
+
34
+ body {
35
+ @apply bg-background text-foreground antialiased;
36
+ letter-spacing: 0.01em;
37
+ line-height: 1.7;
38
+ }
39
+
40
+ /* Luxury typography — editorial serif hierarchy */
41
+ h1,
42
+ h2,
43
+ h3,
44
+ h4 {
45
+ letter-spacing: 0.04em;
46
+ font-weight: 500;
47
+ line-height: 1.2;
48
+ }
49
+
50
+ h1 {
51
+ text-transform: uppercase;
52
+ letter-spacing: 0.1em;
53
+ font-weight: 400;
54
+ line-height: 1.1;
55
+ }
56
+
57
+ h2 {
58
+ text-transform: uppercase;
59
+ letter-spacing: 0.06em;
60
+ }
61
+
62
+ /* Elegant link underline animation */
63
+ a:not([class*="bg-"]) {
64
+ position: relative;
65
+ transition: color 0.3s ease, opacity 0.3s ease;
66
+ }
67
+
68
+ main a:not([class*="bg-"]):not([class*="group"])::after {
69
+ content: '';
70
+ position: absolute;
71
+ bottom: -1px;
72
+ left: 0;
73
+ width: 0;
74
+ height: 1px;
75
+ background: hsl(var(--gold));
76
+ transition: width 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
77
+ }
78
+
79
+ main a:not([class*="bg-"]):not([class*="group"]):hover::after {
80
+ width: 100%;
81
+ }
82
+
83
+ /* Refined text selection */
84
+ ::selection {
85
+ background: hsl(var(--gold) / 0.3);
86
+ color: hsl(38 25% 96%);
87
+ }
88
+
89
+ /* Subtle body texture overlay */
90
+ body::before {
91
+ content: '';
92
+ position: fixed;
93
+ inset: 0;
94
+ background: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.015'/%3E%3C/svg%3E");
95
+ pointer-events: none;
96
+ z-index: 9999;
97
+ }
98
+
99
+ /* Custom scrollbar */
100
+ ::-webkit-scrollbar {
101
+ width: 5px;
102
+ }
103
+
104
+ ::-webkit-scrollbar-track {
105
+ background: hsl(20 14% 4%);
106
+ }
107
+
108
+ ::-webkit-scrollbar-thumb {
109
+ background: hsl(30 10% 18%);
110
+ border-radius: 3px;
111
+ }
112
+
113
+ ::-webkit-scrollbar-thumb:hover {
114
+ background: hsl(var(--gold) / 0.5);
115
+ }
116
+
117
+ /* Smooth focus states */
118
+ :focus-visible {
119
+ outline: 1px solid hsl(var(--gold) / 0.5);
120
+ outline-offset: 3px;
121
+ }
122
+ }
123
+
124
+ @layer components {
125
+ /* ─── Buttons ─── */
126
+
127
+ /* Primary CTA — gold with shimmer sweep */
128
+ button[class*="bg-primary"],
129
+ a[class*="bg-primary"] {
130
+ position: relative;
131
+ overflow: hidden;
132
+ font-weight: 500;
133
+ letter-spacing: 0.08em;
134
+ text-transform: uppercase;
135
+ font-size: 0.78rem;
136
+ border: 1px solid hsl(var(--gold) / 0.3);
137
+ transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
138
+ }
139
+
140
+ button[class*="bg-primary"]:hover,
141
+ a[class*="bg-primary"]:hover {
142
+ box-shadow:
143
+ 0 0 20px hsl(var(--gold) / 0.2),
144
+ 0 4px 16px hsl(0 0% 0% / 0.3);
145
+ border-color: hsl(var(--gold) / 0.6);
146
+ opacity: 1 !important;
147
+ }
148
+
149
+ button[class*="bg-primary"]::after,
150
+ a[class*="bg-primary"]::after {
151
+ content: '';
152
+ position: absolute;
153
+ top: -50%;
154
+ left: -75%;
155
+ width: 50%;
156
+ height: 200%;
157
+ background: linear-gradient(
158
+ 90deg,
159
+ transparent,
160
+ hsl(var(--gold-light) / 0.12),
161
+ hsl(var(--gold-light) / 0.2),
162
+ transparent
163
+ );
164
+ transform: skewX(-20deg);
165
+ transition: left 0.7s ease;
166
+ pointer-events: none;
167
+ }
168
+
169
+ button[class*="bg-primary"]:hover::after,
170
+ a[class*="bg-primary"]:hover::after {
171
+ left: 130%;
172
+ }
173
+
174
+ /* Secondary/ghost buttons — thin border, minimal */
175
+ [class*="bg-secondary"] {
176
+ border: 1px solid hsl(var(--border));
177
+ transition: all 0.3s ease;
178
+ letter-spacing: 0.04em;
179
+ text-transform: uppercase;
180
+ font-size: 0.8rem;
181
+ }
182
+
183
+ [class*="bg-secondary"]:hover {
184
+ border-color: hsl(var(--gold) / 0.4);
185
+ background: hsl(var(--surface-elevated)) !important;
186
+ }
187
+
188
+ /* ─── Product Cards ─── */
189
+
190
+ [class*="group"][class*="border"] {
191
+ transition: all 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
192
+ border-color: hsl(var(--border) / 0.5);
193
+ background: hsl(var(--surface));
194
+ }
195
+
196
+ [class*="group"][class*="border"]:hover {
197
+ border-color: hsl(var(--gold) / 0.25);
198
+ box-shadow:
199
+ 0 8px 40px hsl(0 0% 0% / 0.5),
200
+ 0 0 0 1px hsl(var(--gold) / 0.08);
201
+ }
202
+
203
+ /* Product image — slow cinematic zoom */
204
+ [class*="group-hover\\:scale-105"] {
205
+ transition: transform 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) !important;
206
+ }
207
+
208
+ /* Product image overlay on hover — subtle dark gradient */
209
+ [class*="group"] [class*="aspect-square"] {
210
+ position: relative;
211
+ }
212
+
213
+ [class*="group"]:hover [class*="aspect-square"]::after {
214
+ content: '';
215
+ position: absolute;
216
+ inset: 0;
217
+ background: linear-gradient(
218
+ to top,
219
+ hsl(20 14% 4% / 0.3),
220
+ transparent 50%
221
+ );
222
+ pointer-events: none;
223
+ transition: opacity 0.5s ease;
224
+ }
225
+
226
+ /* ─── Form Elements ─── */
227
+
228
+ input[class*="border-border"],
229
+ select[class*="border-border"],
230
+ textarea[class*="border-border"] {
231
+ background: hsl(var(--surface)) !important;
232
+ transition: all 0.3s ease;
233
+ }
234
+
235
+ input[class*="border-border"]:focus,
236
+ select[class*="border-border"]:focus,
237
+ textarea[class*="border-border"]:focus {
238
+ border-color: hsl(var(--gold) / 0.5) !important;
239
+ box-shadow: 0 0 0 3px hsl(var(--gold) / 0.08);
240
+ background: hsl(var(--surface-elevated)) !important;
241
+ }
242
+
243
+ /* Placeholder text */
244
+ input::placeholder,
245
+ textarea::placeholder {
246
+ letter-spacing: 0.03em;
247
+ font-size: 0.85rem;
248
+ }
249
+
250
+ /* ─── Navigation & Header ─── */
251
+
252
+ header[class*="sticky"] {
253
+ backdrop-filter: blur(16px) saturate(1.2);
254
+ background: hsl(20 14% 4% / 0.8) !important;
255
+ border-bottom: 1px solid hsl(var(--gold) / 0.08) !important;
256
+ }
257
+
258
+ /* Nav links */
259
+ nav a {
260
+ letter-spacing: 0.06em;
261
+ text-transform: uppercase;
262
+ font-size: 0.75rem;
263
+ font-weight: 500;
264
+ }
265
+
266
+ /* ─── Badges & Tags ─── */
267
+
268
+ [class*="bg-muted"][class*="text-xs"] {
269
+ text-transform: uppercase;
270
+ letter-spacing: 0.1em;
271
+ font-size: 0.6rem;
272
+ font-weight: 600;
273
+ border: 1px solid hsl(var(--border));
274
+ }
275
+
276
+ /* Sale badges — dark red, refined */
277
+ [class*="bg-destructive"] {
278
+ background: hsl(0 60% 38%) !important;
279
+ font-weight: 600;
280
+ letter-spacing: 0.06em;
281
+ text-transform: uppercase;
282
+ font-size: 0.65rem;
283
+ }
284
+
285
+ /* ─── Price Display ─── */
286
+
287
+ /* Gold gradient on prices */
288
+ [class*="font-bold"][class*="text-lg"],
289
+ [class*="font-bold"][class*="text-xl"],
290
+ [class*="font-bold"][class*="text-2xl"] {
291
+ background: linear-gradient(
292
+ 135deg,
293
+ hsl(var(--gold-light)),
294
+ hsl(var(--gold)),
295
+ hsl(var(--gold-dark))
296
+ );
297
+ -webkit-background-clip: text;
298
+ -webkit-text-fill-color: transparent;
299
+ background-clip: text;
300
+ }
301
+
302
+ /* Strikethrough original prices */
303
+ [class*="line-through"] {
304
+ opacity: 0.4;
305
+ }
306
+
307
+ /* ─── Dividers & Separators ─── */
308
+
309
+ hr {
310
+ border-color: hsl(var(--border) / 0.3);
311
+ }
312
+
313
+ /* Decorative gold separator */
314
+ main > section + section {
315
+ border-top: 1px solid hsl(var(--gold) / 0.06);
316
+ }
317
+
318
+ /* ─── Cart & Checkout ─── */
319
+
320
+ /* Sticky summary panel */
321
+ [class*="sticky"][class*="top-"] {
322
+ background: hsl(var(--surface));
323
+ border: 1px solid hsl(var(--border) / 0.5);
324
+ }
325
+ }
326
+
327
+ /* ─── Animations ─── */
328
+
329
+ /* Elegant fade-in-up */
330
+ @keyframes luxury-fade-in {
331
+ from {
332
+ opacity: 0;
333
+ transform: translateY(16px);
334
+ }
335
+ to {
336
+ opacity: 1;
337
+ transform: translateY(0);
338
+ }
339
+ }
340
+
341
+ main > * {
342
+ animation: luxury-fade-in 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
343
+ }
344
+
345
+ main > *:nth-child(2) {
346
+ animation-delay: 0.1s;
347
+ }
348
+
349
+ main > *:nth-child(3) {
350
+ animation-delay: 0.2s;
351
+ }
352
+
353
+ main > *:nth-child(4) {
354
+ animation-delay: 0.3s;
355
+ }
356
+
357
+ /* Staggered grid item reveal */
358
+ @keyframes luxury-grid-item {
359
+ from {
360
+ opacity: 0;
361
+ transform: translateY(12px) scale(0.98);
362
+ }
363
+ to {
364
+ opacity: 1;
365
+ transform: translateY(0) scale(1);
366
+ }
367
+ }
368
+
369
+ [class*="grid"] > [class*="group"] {
370
+ animation: luxury-grid-item 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
371
+ }
372
+
373
+ [class*="grid"] > [class*="group"]:nth-child(2) {
374
+ animation-delay: 0.08s;
375
+ }
376
+
377
+ [class*="grid"] > [class*="group"]:nth-child(3) {
378
+ animation-delay: 0.16s;
379
+ }
380
+
381
+ [class*="grid"] > [class*="group"]:nth-child(4) {
382
+ animation-delay: 0.24s;
383
+ }
384
+
385
+ [class*="grid"] > [class*="group"]:nth-child(5) {
386
+ animation-delay: 0.32s;
387
+ }
388
+
389
+ [class*="grid"] > [class*="group"]:nth-child(6) {
390
+ animation-delay: 0.4s;
391
+ }
392
+
393
+ [class*="grid"] > [class*="group"]:nth-child(7) {
394
+ animation-delay: 0.48s;
395
+ }
396
+
397
+ [class*="grid"] > [class*="group"]:nth-child(8) {
398
+ animation-delay: 0.56s;
399
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "Luxury",
3
+ "description": "Dark, sophisticated design with Cormorant Garamond serif font and warm gold accents",
4
+ "font": {
5
+ "family": "Cormorant Garamond",
6
+ "import": "next/font/google"
7
+ },
8
+ "colors": {
9
+ "background": "20 14% 4%",
10
+ "foreground": "38 25% 86%",
11
+ "primary": "38 60% 55%",
12
+ "primary-foreground": "20 14% 4%",
13
+ "secondary": "20 10% 10%",
14
+ "secondary-foreground": "38 25% 86%",
15
+ "muted": "20 10% 12%",
16
+ "muted-foreground": "30 10% 50%",
17
+ "accent": "38 60% 55%",
18
+ "accent-foreground": "20 14% 4%",
19
+ "destructive": "0 72% 51%",
20
+ "border": "30 10% 16%"
21
+ },
22
+ "radius": "0.25rem"
23
+ }
@@ -0,0 +1,400 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 99%;
8
+ --foreground: 260 25% 16%;
9
+ --primary: 330 75% 56%;
10
+ --primary-foreground: 0 0% 100%;
11
+ --secondary: 260 50% 94%;
12
+ --secondary-foreground: 260 25% 16%;
13
+ --muted: 270 30% 95%;
14
+ --muted-foreground: 260 10% 45%;
15
+ --accent: 280 60% 60%;
16
+ --accent-foreground: 0 0% 100%;
17
+ --destructive: 0 84% 60%;
18
+ --destructive-foreground: 0 0% 100%;
19
+ --border: 270 20% 88%;
20
+ --radius: 1rem;
21
+
22
+ /* Playful-specific tokens */
23
+ --pink: 330 75% 56%;
24
+ --purple: 280 60% 60%;
25
+ --lavender: 260 50% 94%;
26
+ --peach: 20 80% 88%;
27
+ --mint: 160 50% 88%;
28
+ }
29
+
30
+ * {
31
+ @apply border-border;
32
+ }
33
+
34
+ body {
35
+ @apply bg-background text-foreground antialiased;
36
+ line-height: 1.65;
37
+ }
38
+
39
+ /* Playful typography — friendly, bold, tight */
40
+ h1,
41
+ h2,
42
+ h3,
43
+ h4 {
44
+ font-weight: 700;
45
+ letter-spacing: -0.02em;
46
+ line-height: 1.2;
47
+ }
48
+
49
+ h1 {
50
+ font-weight: 800;
51
+ letter-spacing: -0.03em;
52
+ }
53
+
54
+ /* Fun colorful selection */
55
+ ::selection {
56
+ background: hsl(var(--pink) / 0.25);
57
+ color: hsl(260 25% 16%);
58
+ }
59
+
60
+ /* Colorful focus rings */
61
+ :focus-visible {
62
+ outline: 2.5px solid hsl(var(--purple));
63
+ outline-offset: 3px;
64
+ border-radius: var(--radius);
65
+ }
66
+
67
+ /* Playful scrollbar */
68
+ ::-webkit-scrollbar {
69
+ width: 8px;
70
+ }
71
+
72
+ ::-webkit-scrollbar-track {
73
+ background: hsl(var(--lavender));
74
+ }
75
+
76
+ ::-webkit-scrollbar-thumb {
77
+ background: linear-gradient(
78
+ 180deg,
79
+ hsl(var(--pink)),
80
+ hsl(var(--purple))
81
+ );
82
+ border-radius: 999px;
83
+ }
84
+ }
85
+
86
+ @layer components {
87
+ /* ─── Buttons ─── */
88
+
89
+ /* Primary CTA — gradient with bounce and glow */
90
+ button[class*="bg-primary"],
91
+ a[class*="bg-primary"] {
92
+ font-weight: 700;
93
+ letter-spacing: 0.01em;
94
+ background: linear-gradient(
95
+ 135deg,
96
+ hsl(var(--pink)),
97
+ hsl(330 80% 52%),
98
+ hsl(var(--purple))
99
+ ) !important;
100
+ background-size: 200% 200%;
101
+ box-shadow:
102
+ 0 4px 14px hsl(var(--pink) / 0.3),
103
+ 0 2px 6px hsl(var(--purple) / 0.15);
104
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
105
+ border: none;
106
+ }
107
+
108
+ button[class*="bg-primary"]:hover,
109
+ a[class*="bg-primary"]:hover {
110
+ transform: translateY(-3px) scale(1.03);
111
+ box-shadow:
112
+ 0 8px 28px hsl(var(--pink) / 0.4),
113
+ 0 4px 12px hsl(var(--purple) / 0.2);
114
+ background-position: 100% 0;
115
+ opacity: 1 !important;
116
+ }
117
+
118
+ button[class*="bg-primary"]:active,
119
+ a[class*="bg-primary"]:active {
120
+ transform: translateY(0) scale(0.97);
121
+ box-shadow: 0 2px 8px hsl(var(--pink) / 0.2);
122
+ }
123
+
124
+ /* Secondary buttons — soft pill with hover pop */
125
+ [class*="bg-secondary"] {
126
+ border-radius: 999px !important;
127
+ font-weight: 600;
128
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
129
+ }
130
+
131
+ [class*="bg-secondary"]:hover {
132
+ background: hsl(var(--lavender)) !important;
133
+ transform: translateY(-2px);
134
+ box-shadow: 0 4px 16px hsl(var(--purple) / 0.12);
135
+ }
136
+
137
+ /* ─── Product Cards ─── */
138
+
139
+ [class*="group"][class*="border"] {
140
+ border-radius: var(--radius);
141
+ overflow: hidden;
142
+ border: 2px solid hsl(var(--border));
143
+ background: white;
144
+ transition: all 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
145
+ }
146
+
147
+ [class*="group"][class*="border"]:hover {
148
+ transform: translateY(-6px) rotate(-0.5deg);
149
+ border-color: hsl(var(--pink) / 0.3);
150
+ box-shadow:
151
+ 0 16px 40px hsl(var(--purple) / 0.12),
152
+ 0 6px 16px hsl(var(--pink) / 0.1);
153
+ }
154
+
155
+ /* Product image hover — fun overshoot zoom */
156
+ [class*="group-hover\\:scale-105"] {
157
+ transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
158
+ }
159
+
160
+ [class*="group"]:hover [class*="group-hover\\:scale-105"] {
161
+ transform: scale(1.08) !important;
162
+ }
163
+
164
+ /* ─── Form Elements ─── */
165
+
166
+ input[class*="border-border"],
167
+ select[class*="border-border"],
168
+ textarea[class*="border-border"] {
169
+ border-radius: var(--radius);
170
+ border-width: 2px;
171
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
172
+ }
173
+
174
+ input[class*="border-border"]:focus,
175
+ select[class*="border-border"]:focus,
176
+ textarea[class*="border-border"]:focus {
177
+ border-color: hsl(var(--purple)) !important;
178
+ box-shadow: 0 0 0 4px hsl(var(--purple) / 0.1);
179
+ transform: scale(1.01);
180
+ }
181
+
182
+ input::placeholder,
183
+ textarea::placeholder {
184
+ color: hsl(var(--muted-foreground) / 0.6);
185
+ }
186
+
187
+ /* ─── Navigation & Header ─── */
188
+
189
+ header[class*="sticky"] {
190
+ border-bottom: none !important;
191
+ box-shadow: 0 4px 20px hsl(var(--purple) / 0.06);
192
+ background: hsl(0 0% 99% / 0.9) !important;
193
+ backdrop-filter: blur(10px);
194
+ }
195
+
196
+ /* Nav link hover — colorful underline */
197
+ nav a {
198
+ position: relative;
199
+ font-weight: 600;
200
+ transition: color 0.2s ease;
201
+ }
202
+
203
+ nav a::after {
204
+ content: '';
205
+ position: absolute;
206
+ bottom: -2px;
207
+ left: 50%;
208
+ width: 0;
209
+ height: 3px;
210
+ background: linear-gradient(90deg, hsl(var(--pink)), hsl(var(--purple)));
211
+ border-radius: 999px;
212
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
213
+ transform: translateX(-50%);
214
+ }
215
+
216
+ nav a:hover::after {
217
+ width: 100%;
218
+ }
219
+
220
+ nav a:hover {
221
+ color: hsl(var(--pink));
222
+ }
223
+
224
+ /* ─── Badges & Tags ─── */
225
+
226
+ /* Category/filter pills */
227
+ [class*="bg-muted"][class*="text-xs"] {
228
+ border-radius: 999px;
229
+ font-weight: 700;
230
+ padding-left: 0.85rem;
231
+ padding-right: 0.85rem;
232
+ transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
233
+ }
234
+
235
+ [class*="bg-muted"][class*="text-xs"]:hover {
236
+ background: hsl(var(--lavender)) !important;
237
+ transform: scale(1.05);
238
+ }
239
+
240
+ /* Sale/discount badges — fun wiggle + pill */
241
+ [class*="bg-destructive"] {
242
+ border-radius: 999px;
243
+ font-weight: 800;
244
+ box-shadow: 0 2px 8px hsl(0 84% 60% / 0.3);
245
+ animation: playful-wiggle 3s ease-in-out infinite;
246
+ }
247
+
248
+ /* ─── Price Display ─── */
249
+
250
+ [class*="font-bold"][class*="text-lg"],
251
+ [class*="font-bold"][class*="text-xl"],
252
+ [class*="font-bold"][class*="text-2xl"] {
253
+ color: hsl(var(--pink));
254
+ }
255
+
256
+ /* Strikethrough — more playful */
257
+ [class*="line-through"] {
258
+ opacity: 0.4;
259
+ text-decoration-color: hsl(var(--purple) / 0.4);
260
+ text-decoration-thickness: 2px;
261
+ }
262
+
263
+ /* ─── Dividers ─── */
264
+
265
+ hr {
266
+ border: none;
267
+ height: 3px;
268
+ background: linear-gradient(
269
+ 90deg,
270
+ transparent,
271
+ hsl(var(--lavender)),
272
+ hsl(var(--pink) / 0.2),
273
+ hsl(var(--lavender)),
274
+ transparent
275
+ );
276
+ border-radius: 999px;
277
+ }
278
+
279
+ /* ─── Cart & Checkout ─── */
280
+
281
+ /* Sticky summary — playful card */
282
+ [class*="sticky"][class*="top-"] {
283
+ border-radius: var(--radius);
284
+ border: 2px solid hsl(var(--border));
285
+ box-shadow: 0 4px 20px hsl(var(--purple) / 0.06);
286
+ }
287
+
288
+ /* Quantity buttons */
289
+ button[class*="h-8"][class*="w-8"],
290
+ button[class*="h-10"][class*="w-10"] {
291
+ border-radius: 999px !important;
292
+ transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
293
+ }
294
+
295
+ button[class*="h-8"][class*="w-8"]:hover,
296
+ button[class*="h-10"][class*="w-10"]:hover {
297
+ transform: scale(1.1);
298
+ background: hsl(var(--lavender)) !important;
299
+ }
300
+
301
+ /* ─── Images ─── */
302
+
303
+ /* Product images — rounded */
304
+ [class*="aspect-square"] {
305
+ border-radius: calc(var(--radius) - 2px);
306
+ overflow: hidden;
307
+ }
308
+ }
309
+
310
+ /* ─── Animations ─── */
311
+
312
+ /* Bouncy slide-up entrance */
313
+ @keyframes playful-slide-up {
314
+ from {
315
+ opacity: 0;
316
+ transform: translateY(24px) scale(0.96);
317
+ }
318
+ 50% {
319
+ transform: translateY(-6px) scale(1.01);
320
+ }
321
+ to {
322
+ opacity: 1;
323
+ transform: translateY(0) scale(1);
324
+ }
325
+ }
326
+
327
+ /* Wiggle for discount badges */
328
+ @keyframes playful-wiggle {
329
+ 0%,
330
+ 85%,
331
+ 100% {
332
+ transform: rotate(0deg);
333
+ }
334
+ 90% {
335
+ transform: rotate(-3deg);
336
+ }
337
+ 95% {
338
+ transform: rotate(3deg);
339
+ }
340
+ }
341
+
342
+ /* Pop-in for grid items */
343
+ @keyframes playful-pop-in {
344
+ from {
345
+ opacity: 0;
346
+ transform: scale(0.9) translateY(16px);
347
+ }
348
+ 60% {
349
+ transform: scale(1.02) translateY(-2px);
350
+ }
351
+ to {
352
+ opacity: 1;
353
+ transform: scale(1) translateY(0);
354
+ }
355
+ }
356
+
357
+ main > * {
358
+ animation: playful-slide-up 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
359
+ }
360
+
361
+ main > *:nth-child(2) {
362
+ animation-delay: 0.06s;
363
+ }
364
+
365
+ main > *:nth-child(3) {
366
+ animation-delay: 0.12s;
367
+ }
368
+
369
+ /* Staggered grid items — playful pop */
370
+ [class*="grid"] > [class*="group"] {
371
+ animation: playful-pop-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
372
+ }
373
+
374
+ [class*="grid"] > [class*="group"]:nth-child(2) {
375
+ animation-delay: 0.06s;
376
+ }
377
+
378
+ [class*="grid"] > [class*="group"]:nth-child(3) {
379
+ animation-delay: 0.12s;
380
+ }
381
+
382
+ [class*="grid"] > [class*="group"]:nth-child(4) {
383
+ animation-delay: 0.18s;
384
+ }
385
+
386
+ [class*="grid"] > [class*="group"]:nth-child(5) {
387
+ animation-delay: 0.24s;
388
+ }
389
+
390
+ [class*="grid"] > [class*="group"]:nth-child(6) {
391
+ animation-delay: 0.3s;
392
+ }
393
+
394
+ [class*="grid"] > [class*="group"]:nth-child(7) {
395
+ animation-delay: 0.36s;
396
+ }
397
+
398
+ [class*="grid"] > [class*="group"]:nth-child(8) {
399
+ animation-delay: 0.42s;
400
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "Playful",
3
+ "description": "Warm, vibrant design with Nunito rounded font and energetic pink-purple palette",
4
+ "font": {
5
+ "family": "Nunito",
6
+ "import": "next/font/google"
7
+ },
8
+ "colors": {
9
+ "background": "0 0% 99%",
10
+ "foreground": "260 25% 16%",
11
+ "primary": "330 75% 56%",
12
+ "primary-foreground": "0 0% 100%",
13
+ "secondary": "260 50% 94%",
14
+ "secondary-foreground": "260 25% 16%",
15
+ "muted": "270 30% 95%",
16
+ "muted-foreground": "260 10% 45%",
17
+ "accent": "280 60% 60%",
18
+ "accent-foreground": "0 0% 100%",
19
+ "destructive": "0 84% 60%",
20
+ "border": "270 20% 88%"
21
+ },
22
+ "radius": "1rem"
23
+ }