create-nymbal-app 0.0.0 → 0.2.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 (159) hide show
  1. package/bin/create-nymbal-app.mjs +9 -0
  2. package/dist/index.d.ts +37 -0
  3. package/dist/index.js +419 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +41 -7
  6. package/scaffold/project/astro/src/pages/index.astro +57 -0
  7. package/scaffold/templates/astro/README.md +26 -0
  8. package/scaffold/templates/astro/_dot.env.example +6 -0
  9. package/scaffold/templates/astro/_dot.gitignore +16 -0
  10. package/scaffold/templates/astro/_dot.node-version +1 -0
  11. package/scaffold/templates/astro/_dot.npmrc +1 -0
  12. package/scaffold/templates/astro/astro.config.mjs +14 -0
  13. package/scaffold/templates/astro/package.json +59 -0
  14. package/scaffold/templates/astro/src/components/AddressForm.astro +107 -0
  15. package/scaffold/templates/astro/src/components/Breadcrumb.astro +20 -0
  16. package/scaffold/templates/astro/src/components/CategoryNav.astro +27 -0
  17. package/scaffold/templates/astro/src/components/CheckoutSteps.astro +29 -0
  18. package/scaffold/templates/astro/src/components/Footer.astro +108 -0
  19. package/scaffold/templates/astro/src/components/Header.astro +192 -0
  20. package/scaffold/templates/astro/src/components/HeroSection.astro +17 -0
  21. package/scaffold/templates/astro/src/components/ImageGallery.astro +42 -0
  22. package/scaffold/templates/astro/src/components/NewsletterSignup.astro +39 -0
  23. package/scaffold/templates/astro/src/components/OrderSummary.astro +53 -0
  24. package/scaffold/templates/astro/src/components/Pagination.astro +13 -0
  25. package/scaffold/templates/astro/src/components/PriceDisplay.astro +25 -0
  26. package/scaffold/templates/astro/src/components/ProductCard.astro +44 -0
  27. package/scaffold/templates/astro/src/components/RelatedProducts.astro +28 -0
  28. package/scaffold/templates/astro/src/components/ReviewForm.astro +100 -0
  29. package/scaffold/templates/astro/src/components/ReviewList.astro +41 -0
  30. package/scaffold/templates/astro/src/components/SkipNav.astro +3 -0
  31. package/scaffold/templates/astro/src/components/SortDropdown.astro +26 -0
  32. package/scaffold/templates/astro/src/components/StockBadge.astro +32 -0
  33. package/scaffold/templates/astro/src/env.d.ts +2 -0
  34. package/scaffold/templates/astro/src/layouts/AccountLayout.astro +168 -0
  35. package/scaffold/templates/astro/src/layouts/BaseLayout.astro +55 -0
  36. package/scaffold/templates/astro/src/lib/api.ts +89 -0
  37. package/scaffold/templates/astro/src/lib/client.ts +13 -0
  38. package/scaffold/templates/astro/src/lib/format.ts +17 -0
  39. package/scaffold/templates/astro/src/lib/order-status.ts +14 -0
  40. package/scaffold/templates/astro/src/lib/seo.ts +62 -0
  41. package/scaffold/templates/astro/src/pages/404.astro +18 -0
  42. package/scaffold/templates/astro/src/pages/500.astro +17 -0
  43. package/scaffold/templates/astro/src/pages/account/addresses.astro +110 -0
  44. package/scaffold/templates/astro/src/pages/account/index.astro +67 -0
  45. package/scaffold/templates/astro/src/pages/account/login.astro +55 -0
  46. package/scaffold/templates/astro/src/pages/account/orders/[orderNumber].astro +108 -0
  47. package/scaffold/templates/astro/src/pages/account/orders.astro +81 -0
  48. package/scaffold/templates/astro/src/pages/account/profile.astro +131 -0
  49. package/scaffold/templates/astro/src/pages/account/register.astro +94 -0
  50. package/scaffold/templates/astro/src/pages/cart.astro +16 -0
  51. package/scaffold/templates/astro/src/pages/category/[slug].astro +73 -0
  52. package/scaffold/templates/astro/src/pages/checkout.astro +100 -0
  53. package/scaffold/templates/astro/src/pages/fragments/footer.astro +5 -0
  54. package/scaffold/templates/astro/src/pages/fragments/header.astro +5 -0
  55. package/scaffold/templates/astro/src/pages/fragments/nav.astro +9 -0
  56. package/scaffold/templates/astro/src/pages/fragments/product/[slug].astro +14 -0
  57. package/scaffold/templates/astro/src/pages/index.astro +49 -0
  58. package/scaffold/templates/astro/src/pages/order/[orderNumber].astro +127 -0
  59. package/scaffold/templates/astro/src/pages/product/[slug].astro +107 -0
  60. package/scaffold/templates/astro/src/pages/products/index.astro +62 -0
  61. package/scaffold/templates/astro/src/pages/search.astro +37 -0
  62. package/scaffold/templates/astro/src/scripts/account-guard.ts +22 -0
  63. package/scaffold/templates/astro/src/scripts/auth-forms.ts +89 -0
  64. package/scaffold/templates/astro/src/scripts/cart-page.ts +143 -0
  65. package/scaffold/templates/astro/src/scripts/checkout.ts +277 -0
  66. package/scaffold/templates/astro/src/scripts/image-gallery.ts +22 -0
  67. package/scaffold/templates/astro/src/scripts/init-client.ts +16 -0
  68. package/scaffold/templates/astro/src/scripts/order-status.ts +27 -0
  69. package/scaffold/templates/astro/src/scripts/pdp.ts +67 -0
  70. package/scaffold/templates/astro/src/scripts/plp.ts +109 -0
  71. package/scaffold/templates/astro/src/scripts/search.ts +145 -0
  72. package/scaffold/templates/astro/src/styles/global.css +362 -0
  73. package/scaffold/templates/astro/src/styles/pages/account.css +331 -0
  74. package/scaffold/templates/astro/src/styles/pages/cart.css +243 -0
  75. package/scaffold/templates/astro/src/styles/pages/checkout.css +270 -0
  76. package/scaffold/templates/astro/src/styles/pages/confirmation.css +142 -0
  77. package/scaffold/templates/astro/src/styles/pages/error.css +69 -0
  78. package/scaffold/templates/astro/src/styles/pages/home.css +269 -0
  79. package/scaffold/templates/astro/src/styles/pages/pdp.css +272 -0
  80. package/scaffold/templates/astro/src/styles/pages/plp.css +213 -0
  81. package/scaffold/templates/astro/src/styles/pages/search.css +152 -0
  82. package/scaffold/templates/astro/tsconfig.json +3 -0
  83. package/scaffold/templates/nextjs/README.md +26 -0
  84. package/scaffold/templates/nextjs/_dot.env.example +6 -0
  85. package/scaffold/templates/nextjs/_dot.gitignore +17 -0
  86. package/scaffold/templates/nextjs/_dot.node-version +1 -0
  87. package/scaffold/templates/nextjs/_dot.npmrc +1 -0
  88. package/scaffold/templates/nextjs/app/account/addresses/page.tsx +10 -0
  89. package/scaffold/templates/nextjs/app/account/layout.tsx +57 -0
  90. package/scaffold/templates/nextjs/app/account/login/page.tsx +23 -0
  91. package/scaffold/templates/nextjs/app/account/orders/[orderNumber]/page.tsx +192 -0
  92. package/scaffold/templates/nextjs/app/account/orders/page.tsx +123 -0
  93. package/scaffold/templates/nextjs/app/account/page.tsx +59 -0
  94. package/scaffold/templates/nextjs/app/account/profile/page.tsx +10 -0
  95. package/scaffold/templates/nextjs/app/account/register/page.tsx +10 -0
  96. package/scaffold/templates/nextjs/app/cart/page.tsx +10 -0
  97. package/scaffold/templates/nextjs/app/category/[slug]/page.tsx +58 -0
  98. package/scaffold/templates/nextjs/app/checkout/page.tsx +10 -0
  99. package/scaffold/templates/nextjs/app/error.tsx +49 -0
  100. package/scaffold/templates/nextjs/app/globals.css +473 -0
  101. package/scaffold/templates/nextjs/app/layout.tsx +29 -0
  102. package/scaffold/templates/nextjs/app/not-found.tsx +38 -0
  103. package/scaffold/templates/nextjs/app/order/[orderNumber]/page.tsx +127 -0
  104. package/scaffold/templates/nextjs/app/page.tsx +63 -0
  105. package/scaffold/templates/nextjs/app/product/[slug]/page.tsx +111 -0
  106. package/scaffold/templates/nextjs/app/products/page.tsx +40 -0
  107. package/scaffold/templates/nextjs/app/search/page.tsx +24 -0
  108. package/scaffold/templates/nextjs/components/client/AddressManager.tsx +181 -0
  109. package/scaffold/templates/nextjs/components/client/AuthGuard.tsx +55 -0
  110. package/scaffold/templates/nextjs/components/client/CartDrawerToggle.tsx +39 -0
  111. package/scaffold/templates/nextjs/components/client/CartPage.tsx +120 -0
  112. package/scaffold/templates/nextjs/components/client/CheckoutForm.tsx +523 -0
  113. package/scaffold/templates/nextjs/components/client/ImageGallery.tsx +68 -0
  114. package/scaffold/templates/nextjs/components/client/LoginForm.tsx +89 -0
  115. package/scaffold/templates/nextjs/components/client/MiniCartWrapper.tsx +12 -0
  116. package/scaffold/templates/nextjs/components/client/NewsletterSignup.tsx +74 -0
  117. package/scaffold/templates/nextjs/components/client/NymbalSetup.tsx +24 -0
  118. package/scaffold/templates/nextjs/components/client/OrderStatusRefresh.tsx +48 -0
  119. package/scaffold/templates/nextjs/components/client/ProductGrid.tsx +148 -0
  120. package/scaffold/templates/nextjs/components/client/ProductInteractive.tsx +61 -0
  121. package/scaffold/templates/nextjs/components/client/ProfileForm.tsx +112 -0
  122. package/scaffold/templates/nextjs/components/client/RegisterForm.tsx +131 -0
  123. package/scaffold/templates/nextjs/components/client/ReviewForm.tsx +116 -0
  124. package/scaffold/templates/nextjs/components/client/SearchBarWrapper.tsx +27 -0
  125. package/scaffold/templates/nextjs/components/client/SearchResults.tsx +141 -0
  126. package/scaffold/templates/nextjs/components/client/SortDropdown.tsx +35 -0
  127. package/scaffold/templates/nextjs/components/server/Breadcrumb.tsx +36 -0
  128. package/scaffold/templates/nextjs/components/server/CategoryNav.tsx +29 -0
  129. package/scaffold/templates/nextjs/components/server/CheckoutSteps.tsx +60 -0
  130. package/scaffold/templates/nextjs/components/server/Footer.module.css +64 -0
  131. package/scaffold/templates/nextjs/components/server/Footer.tsx +79 -0
  132. package/scaffold/templates/nextjs/components/server/Header.module.css +147 -0
  133. package/scaffold/templates/nextjs/components/server/Header.tsx +102 -0
  134. package/scaffold/templates/nextjs/components/server/HeroSection.tsx +18 -0
  135. package/scaffold/templates/nextjs/components/server/OrderSummary.tsx +79 -0
  136. package/scaffold/templates/nextjs/components/server/PriceDisplay.tsx +31 -0
  137. package/scaffold/templates/nextjs/components/server/ProductCard.tsx +59 -0
  138. package/scaffold/templates/nextjs/components/server/RelatedProducts.tsx +31 -0
  139. package/scaffold/templates/nextjs/components/server/ReviewList.tsx +62 -0
  140. package/scaffold/templates/nextjs/components/server/SkipNav.tsx +7 -0
  141. package/scaffold/templates/nextjs/components/server/StockBadge.tsx +19 -0
  142. package/scaffold/templates/nextjs/lib/api.ts +89 -0
  143. package/scaffold/templates/nextjs/lib/client.ts +23 -0
  144. package/scaffold/templates/nextjs/lib/format.ts +7 -0
  145. package/scaffold/templates/nextjs/lib/order-status.ts +14 -0
  146. package/scaffold/templates/nextjs/lib/seo.ts +73 -0
  147. package/scaffold/templates/nextjs/next.config.mjs +9 -0
  148. package/scaffold/templates/nextjs/package.json +64 -0
  149. package/scaffold/templates/nextjs/styles/pages/account.module.css +377 -0
  150. package/scaffold/templates/nextjs/styles/pages/cart.module.css +240 -0
  151. package/scaffold/templates/nextjs/styles/pages/checkout.module.css +404 -0
  152. package/scaffold/templates/nextjs/styles/pages/confirmation.module.css +237 -0
  153. package/scaffold/templates/nextjs/styles/pages/error.module.css +132 -0
  154. package/scaffold/templates/nextjs/styles/pages/home.module.css +285 -0
  155. package/scaffold/templates/nextjs/styles/pages/pdp.module.css +319 -0
  156. package/scaffold/templates/nextjs/styles/pages/plp.module.css +280 -0
  157. package/scaffold/templates/nextjs/styles/pages/search.module.css +192 -0
  158. package/scaffold/templates/nextjs/tsconfig.json +41 -0
  159. package/README.md +0 -4
@@ -0,0 +1,269 @@
1
+ /* ----------------------------------------------------------------
2
+ Home page styles
3
+ ---------------------------------------------------------------- */
4
+
5
+ /* ---- Hero section ---- */
6
+
7
+ .hero {
8
+ position: relative;
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ text-align: center;
13
+ padding: 4rem var(--nymbal-spacing-md, 1rem);
14
+ min-height: 420px;
15
+ background: linear-gradient(135deg, var(--nymbal-color-primary, #18181b) 0%, #27272a 50%, var(--nymbal-color-accent, #2563eb) 100%);
16
+ color: var(--nymbal-color-text-inverse, #fff);
17
+ overflow: hidden;
18
+ }
19
+
20
+ .hero::before {
21
+ content: '';
22
+ position: absolute;
23
+ inset: 0;
24
+ background: radial-gradient(ellipse at 30% 50%, rgba(37, 99, 235, 0.15) 0%, transparent 60%);
25
+ pointer-events: none;
26
+ }
27
+
28
+ .hero-content {
29
+ position: relative;
30
+ max-width: 40rem;
31
+ }
32
+
33
+ .hero-title {
34
+ font-size: 2.25rem;
35
+ font-weight: var(--nymbal-font-weight-bold, 700);
36
+ line-height: 1.1;
37
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
38
+ letter-spacing: -0.02em;
39
+ }
40
+
41
+ @media (min-width: 641px) {
42
+ .hero {
43
+ padding: 5rem var(--nymbal-spacing-lg, 1.5rem);
44
+ min-height: 480px;
45
+ }
46
+
47
+ .hero-title {
48
+ font-size: 3rem;
49
+ }
50
+ }
51
+
52
+ @media (min-width: 1025px) {
53
+ .hero {
54
+ padding: 6rem var(--nymbal-spacing-lg, 1.5rem);
55
+ min-height: 540px;
56
+ }
57
+
58
+ .hero-title {
59
+ font-size: 3.5rem;
60
+ }
61
+ }
62
+
63
+ .hero-subtitle {
64
+ font-size: var(--nymbal-font-size-lg, 1.125rem);
65
+ font-weight: var(--nymbal-font-weight-normal, 400);
66
+ color: rgba(255, 255, 255, 0.8);
67
+ margin-bottom: var(--nymbal-spacing-lg, 1.5rem);
68
+ line-height: 1.5;
69
+ }
70
+
71
+ .hero-actions {
72
+ display: flex;
73
+ gap: var(--nymbal-spacing-sm, 0.5rem);
74
+ justify-content: center;
75
+ flex-wrap: wrap;
76
+ }
77
+
78
+ .hero-actions .btn-primary {
79
+ background-color: var(--nymbal-color-text-inverse, #fff);
80
+ color: var(--nymbal-color-primary, #18181b);
81
+ border-color: var(--nymbal-color-text-inverse, #fff);
82
+ }
83
+
84
+ .hero-actions .btn-primary:hover {
85
+ background-color: rgba(255, 255, 255, 0.9);
86
+ }
87
+
88
+ .hero-actions .btn-secondary {
89
+ color: var(--nymbal-color-text-inverse, #fff);
90
+ border-color: rgba(255, 255, 255, 0.3);
91
+ }
92
+
93
+ .hero-actions .btn-secondary:hover {
94
+ background-color: rgba(255, 255, 255, 0.1);
95
+ border-color: rgba(255, 255, 255, 0.5);
96
+ }
97
+
98
+ /* ---- Category grid ---- */
99
+
100
+ .category-grid {
101
+ display: grid;
102
+ grid-template-columns: repeat(2, 1fr);
103
+ gap: var(--nymbal-spacing-md, 1rem);
104
+ }
105
+
106
+ @media (min-width: 641px) {
107
+ .category-grid {
108
+ grid-template-columns: repeat(4, 1fr);
109
+ gap: var(--nymbal-spacing-lg, 1.5rem);
110
+ }
111
+ }
112
+
113
+ .category-card {
114
+ display: flex;
115
+ flex-direction: column;
116
+ align-items: center;
117
+ justify-content: center;
118
+ text-align: center;
119
+ padding: var(--nymbal-spacing-lg, 1.5rem) var(--nymbal-spacing-md, 1rem);
120
+ background-color: var(--nymbal-color-surface, #fff);
121
+ border: 1px solid var(--nymbal-color-border, #e4e4e7);
122
+ border-radius: var(--nymbal-radius-lg, 0.75rem);
123
+ text-decoration: none;
124
+ transition: border-color var(--nymbal-transition-fast, 150ms) ease,
125
+ box-shadow var(--nymbal-transition-fast, 150ms) ease,
126
+ transform var(--nymbal-transition-fast, 150ms) ease;
127
+ min-height: 140px;
128
+ }
129
+
130
+ .category-card:hover {
131
+ border-color: var(--nymbal-color-accent, #2563eb);
132
+ box-shadow: var(--nymbal-shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1));
133
+ transform: translateY(-2px);
134
+ }
135
+
136
+ .category-card-icon {
137
+ font-size: 2rem;
138
+ margin-bottom: var(--nymbal-spacing-sm, 0.5rem);
139
+ }
140
+
141
+ .category-card-name {
142
+ font-size: var(--nymbal-font-size-base, 1rem);
143
+ font-weight: var(--nymbal-font-weight-medium, 500);
144
+ color: var(--nymbal-color-text, #18181b);
145
+ }
146
+
147
+ /* ---- Featured products ---- */
148
+
149
+ .featured-section {
150
+ background-color: #fafafa;
151
+ }
152
+
153
+ .featured-header {
154
+ display: flex;
155
+ align-items: center;
156
+ justify-content: space-between;
157
+ margin-bottom: var(--nymbal-spacing-lg, 1.5rem);
158
+ flex-wrap: wrap;
159
+ gap: var(--nymbal-spacing-sm, 0.5rem);
160
+ }
161
+
162
+ .featured-link {
163
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
164
+ font-weight: var(--nymbal-font-weight-medium, 500);
165
+ color: var(--nymbal-color-accent, #2563eb);
166
+ text-decoration: none;
167
+ }
168
+
169
+ .featured-link:hover {
170
+ text-decoration: underline;
171
+ }
172
+
173
+ /* ---- Product card (shared home / PLP) ---- */
174
+
175
+ .product-card {
176
+ display: flex;
177
+ flex-direction: column;
178
+ background-color: var(--nymbal-color-surface, #fff);
179
+ border: 1px solid var(--nymbal-color-border, #e4e4e7);
180
+ border-radius: var(--nymbal-radius-lg, 0.75rem);
181
+ overflow: hidden;
182
+ text-decoration: none;
183
+ transition: box-shadow var(--nymbal-transition-normal, 200ms) ease,
184
+ transform var(--nymbal-transition-fast, 150ms) ease;
185
+ }
186
+
187
+ .product-card:hover {
188
+ box-shadow: var(--nymbal-shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1));
189
+ transform: translateY(-2px);
190
+ }
191
+
192
+ .product-card-image {
193
+ aspect-ratio: 1 / 1;
194
+ width: 100%;
195
+ object-fit: cover;
196
+ background-color: #f4f4f5;
197
+ }
198
+
199
+ .product-card-body {
200
+ padding: var(--nymbal-spacing-md, 1rem);
201
+ flex: 1;
202
+ display: flex;
203
+ flex-direction: column;
204
+ gap: var(--nymbal-spacing-xs, 0.25rem);
205
+ }
206
+
207
+ .product-card-name {
208
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
209
+ font-weight: var(--nymbal-font-weight-medium, 500);
210
+ color: var(--nymbal-color-text, #18181b);
211
+ line-height: 1.3;
212
+ }
213
+
214
+ .product-card-price {
215
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
216
+ font-weight: var(--nymbal-font-weight-bold, 700);
217
+ color: var(--nymbal-color-primary, #18181b);
218
+ }
219
+
220
+ /* ---- Newsletter section ---- */
221
+
222
+ .newsletter {
223
+ text-align: center;
224
+ background-color: var(--nymbal-color-primary, #18181b);
225
+ color: var(--nymbal-color-text-inverse, #fff);
226
+ }
227
+
228
+ .newsletter-title {
229
+ font-size: 1.5rem;
230
+ font-weight: var(--nymbal-font-weight-bold, 700);
231
+ margin-bottom: var(--nymbal-spacing-xs, 0.25rem);
232
+ color: var(--nymbal-color-text-inverse, #fff);
233
+ }
234
+
235
+ .newsletter-subtitle {
236
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
237
+ color: rgba(255, 255, 255, 0.7);
238
+ margin-bottom: var(--nymbal-spacing-lg, 1.5rem);
239
+ }
240
+
241
+ .newsletter-form {
242
+ display: flex;
243
+ gap: var(--nymbal-spacing-sm, 0.5rem);
244
+ max-width: 28rem;
245
+ margin-inline: auto;
246
+ flex-wrap: wrap;
247
+ justify-content: center;
248
+ }
249
+
250
+ .newsletter-form input[type="email"] {
251
+ flex: 1;
252
+ min-width: 200px;
253
+ border-color: rgba(255, 255, 255, 0.2);
254
+ background-color: rgba(255, 255, 255, 0.1);
255
+ color: var(--nymbal-color-text-inverse, #fff);
256
+ }
257
+
258
+ .newsletter-form input[type="email"]::placeholder {
259
+ color: rgba(255, 255, 255, 0.5);
260
+ }
261
+
262
+ .newsletter-form input[type="email"]:focus {
263
+ border-color: var(--nymbal-color-accent, #2563eb);
264
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.3);
265
+ }
266
+
267
+ .newsletter-form .btn {
268
+ flex-shrink: 0;
269
+ }
@@ -0,0 +1,272 @@
1
+ /* ----------------------------------------------------------------
2
+ Product detail page (PDP) styles
3
+ ---------------------------------------------------------------- */
4
+
5
+ /* ---- Two-column layout ---- */
6
+
7
+ .pdp-layout {
8
+ display: grid;
9
+ grid-template-columns: 1fr;
10
+ gap: var(--nymbal-spacing-lg, 1.5rem);
11
+ }
12
+
13
+ @media (min-width: 769px) {
14
+ .pdp-layout {
15
+ grid-template-columns: 1fr 1fr;
16
+ gap: var(--nymbal-spacing-xl, 2rem);
17
+ }
18
+ }
19
+
20
+ @media (min-width: 1025px) {
21
+ .pdp-layout {
22
+ grid-template-columns: 1.2fr 1fr;
23
+ gap: 3rem;
24
+ }
25
+ }
26
+
27
+ /* ---- Breadcrumbs ---- */
28
+
29
+ .pdp-breadcrumbs {
30
+ display: flex;
31
+ align-items: center;
32
+ gap: var(--nymbal-spacing-xs, 0.25rem);
33
+ font-size: var(--nymbal-font-size-xs, 0.75rem);
34
+ color: var(--nymbal-color-text-muted, #71717a);
35
+ margin-bottom: var(--nymbal-spacing-md, 1rem);
36
+ flex-wrap: wrap;
37
+ }
38
+
39
+ .pdp-breadcrumbs a {
40
+ color: var(--nymbal-color-text-muted, #71717a);
41
+ text-decoration: none;
42
+ transition: color var(--nymbal-transition-fast, 150ms) ease;
43
+ }
44
+
45
+ .pdp-breadcrumbs a:hover {
46
+ color: var(--nymbal-color-accent, #2563eb);
47
+ }
48
+
49
+ .pdp-breadcrumbs .separator {
50
+ color: var(--nymbal-color-border, #e4e4e7);
51
+ }
52
+
53
+ .pdp-breadcrumbs .current {
54
+ color: var(--nymbal-color-text, #18181b);
55
+ font-weight: var(--nymbal-font-weight-medium, 500);
56
+ }
57
+
58
+ /* ---- Image gallery ---- */
59
+
60
+ .pdp-gallery {
61
+ position: sticky;
62
+ top: 80px;
63
+ align-self: start;
64
+ }
65
+
66
+ .pdp-main-image {
67
+ width: 100%;
68
+ aspect-ratio: 1 / 1;
69
+ object-fit: cover;
70
+ border-radius: var(--nymbal-radius-lg, 0.75rem);
71
+ background-color: #f4f4f5;
72
+ margin-bottom: var(--nymbal-spacing-sm, 0.5rem);
73
+ }
74
+
75
+ .pdp-thumbnails {
76
+ display: flex;
77
+ gap: var(--nymbal-spacing-sm, 0.5rem);
78
+ overflow-x: auto;
79
+ scrollbar-width: thin;
80
+ padding-bottom: var(--nymbal-spacing-xs, 0.25rem);
81
+ }
82
+
83
+ .pdp-thumbnail {
84
+ width: 64px;
85
+ height: 64px;
86
+ object-fit: cover;
87
+ border-radius: var(--nymbal-radius-md, 0.5rem);
88
+ border: 2px solid transparent;
89
+ cursor: pointer;
90
+ flex-shrink: 0;
91
+ background-color: #f4f4f5;
92
+ transition: border-color var(--nymbal-transition-fast, 150ms) ease;
93
+ }
94
+
95
+ .pdp-thumbnail:hover {
96
+ border-color: var(--nymbal-color-border, #e4e4e7);
97
+ }
98
+
99
+ .pdp-thumbnail.active {
100
+ border-color: var(--nymbal-color-primary, #18181b);
101
+ }
102
+
103
+ @media (min-width: 641px) {
104
+ .pdp-thumbnail {
105
+ width: 80px;
106
+ height: 80px;
107
+ }
108
+ }
109
+
110
+ /* ---- Product info ---- */
111
+
112
+ .pdp-info {
113
+ display: flex;
114
+ flex-direction: column;
115
+ gap: var(--nymbal-spacing-md, 1rem);
116
+ }
117
+
118
+ .pdp-title {
119
+ font-size: 1.5rem;
120
+ font-weight: var(--nymbal-font-weight-bold, 700);
121
+ color: var(--nymbal-color-primary, #18181b);
122
+ line-height: 1.2;
123
+ }
124
+
125
+ @media (min-width: 641px) {
126
+ .pdp-title {
127
+ font-size: 1.75rem;
128
+ }
129
+ }
130
+
131
+ .pdp-price {
132
+ font-size: 1.5rem;
133
+ font-weight: var(--nymbal-font-weight-bold, 700);
134
+ color: var(--nymbal-color-primary, #18181b);
135
+ }
136
+
137
+ .pdp-price-range {
138
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
139
+ color: var(--nymbal-color-text-muted, #71717a);
140
+ font-weight: var(--nymbal-font-weight-normal, 400);
141
+ margin-left: var(--nymbal-spacing-xs, 0.25rem);
142
+ }
143
+
144
+ .pdp-stock {
145
+ display: inline-flex;
146
+ align-items: center;
147
+ gap: var(--nymbal-spacing-xs, 0.25rem);
148
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
149
+ font-weight: var(--nymbal-font-weight-medium, 500);
150
+ }
151
+
152
+ .pdp-stock.in-stock {
153
+ color: var(--nymbal-color-success, #16a34a);
154
+ }
155
+
156
+ .pdp-stock.out-of-stock {
157
+ color: var(--nymbal-color-error, #dc2626);
158
+ }
159
+
160
+ .pdp-stock-dot {
161
+ width: 8px;
162
+ height: 8px;
163
+ border-radius: var(--nymbal-radius-full, 9999px);
164
+ background-color: currentColor;
165
+ }
166
+
167
+ .pdp-description {
168
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
169
+ color: var(--nymbal-color-text-muted, #71717a);
170
+ line-height: 1.7;
171
+ }
172
+
173
+ /* ---- Variant / quantity / add-to-cart area ---- */
174
+
175
+ .pdp-actions {
176
+ display: flex;
177
+ flex-direction: column;
178
+ gap: var(--nymbal-spacing-md, 1rem);
179
+ padding-top: var(--nymbal-spacing-md, 1rem);
180
+ border-top: 1px solid var(--nymbal-color-border, #e4e4e7);
181
+ }
182
+
183
+ nymbal-variant-selector {
184
+ display: block;
185
+ }
186
+
187
+ nymbal-quantity-selector {
188
+ display: inline-flex;
189
+ }
190
+
191
+ nymbal-add-to-cart {
192
+ display: block;
193
+ }
194
+
195
+ .pdp-add-row {
196
+ display: flex;
197
+ align-items: center;
198
+ gap: var(--nymbal-spacing-md, 1rem);
199
+ flex-wrap: wrap;
200
+ }
201
+
202
+ /* ---- Reviews section ---- */
203
+
204
+ .pdp-reviews {
205
+ margin-top: var(--nymbal-spacing-xl, 2rem);
206
+ padding-top: var(--nymbal-spacing-xl, 2rem);
207
+ border-top: 1px solid var(--nymbal-color-border, #e4e4e7);
208
+ }
209
+
210
+ .pdp-reviews-title {
211
+ font-size: 1.25rem;
212
+ font-weight: var(--nymbal-font-weight-bold, 700);
213
+ color: var(--nymbal-color-primary, #18181b);
214
+ margin-bottom: var(--nymbal-spacing-lg, 1.5rem);
215
+ }
216
+
217
+ .review-list {
218
+ display: flex;
219
+ flex-direction: column;
220
+ gap: var(--nymbal-spacing-lg, 1.5rem);
221
+ }
222
+
223
+ .review-item {
224
+ padding-bottom: var(--nymbal-spacing-lg, 1.5rem);
225
+ border-bottom: 1px solid var(--nymbal-color-border, #e4e4e7);
226
+ }
227
+
228
+ .review-item:last-child {
229
+ border-bottom: none;
230
+ padding-bottom: 0;
231
+ }
232
+
233
+ .review-header {
234
+ display: flex;
235
+ align-items: center;
236
+ justify-content: space-between;
237
+ gap: var(--nymbal-spacing-sm, 0.5rem);
238
+ margin-bottom: var(--nymbal-spacing-xs, 0.25rem);
239
+ flex-wrap: wrap;
240
+ }
241
+
242
+ .review-rating {
243
+ display: flex;
244
+ gap: 2px;
245
+ color: var(--nymbal-color-warning, #d97706);
246
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
247
+ }
248
+
249
+ .review-date {
250
+ font-size: var(--nymbal-font-size-xs, 0.75rem);
251
+ color: var(--nymbal-color-text-muted, #71717a);
252
+ }
253
+
254
+ .review-title {
255
+ font-size: var(--nymbal-font-size-base, 1rem);
256
+ font-weight: var(--nymbal-font-weight-medium, 500);
257
+ color: var(--nymbal-color-text, #18181b);
258
+ margin-bottom: var(--nymbal-spacing-xs, 0.25rem);
259
+ }
260
+
261
+ .review-body {
262
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
263
+ color: var(--nymbal-color-text-muted, #71717a);
264
+ line-height: 1.6;
265
+ }
266
+
267
+ .reviews-empty {
268
+ text-align: center;
269
+ padding: var(--nymbal-spacing-xl, 2rem);
270
+ color: var(--nymbal-color-text-muted, #71717a);
271
+ font-size: var(--nymbal-font-size-sm, 0.875rem);
272
+ }