reroute-js 0.46.0 → 1.0.0-alpha.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 (214) hide show
  1. package/README.md +2 -4
  2. package/_/store/package.json +1 -3
  3. package/_/store/src/client/components/Header.tsx +8 -20
  4. package/_/store/src/client/components/ProductCard.tsx +9 -16
  5. package/_/store/src/client/routes/[404].tsx +20 -31
  6. package/_/store/src/client/routes/categories/[category].tsx +23 -28
  7. package/_/store/src/client/routes/categories/index.tsx +19 -27
  8. package/_/store/src/client/routes/index.tsx +27 -37
  9. package/_/store/src/client/routes/products/[id].tsx +35 -48
  10. package/_/store/src/client/routes/products/index.tsx +20 -50
  11. package/_/store/src/client/theme.css +907 -95
  12. package/cli/bin.d.ts +1 -1
  13. package/cli/bin.js +78 -176
  14. package/cli/bin.js.map +11 -11
  15. package/cli/index.d.ts +1 -1
  16. package/cli/index.js +17 -112
  17. package/cli/index.js.map +5 -5
  18. package/cli/src/cli.d.ts +1 -1
  19. package/cli/src/commands/analyze.d.ts +1 -1
  20. package/cli/src/commands/build.d.ts +1 -1
  21. package/cli/src/commands/dev.d.ts +1 -1
  22. package/cli/src/commands/gen.d.ts +1 -1
  23. package/cli/src/commands/gen.d.ts.map +1 -1
  24. package/cli/src/commands/index.d.ts +1 -1
  25. package/cli/src/commands/init.d.ts +1 -1
  26. package/cli/src/commands/lib/assets.d.ts +1 -1
  27. package/cli/src/commands/lib/bundler.d.ts +1 -1
  28. package/cli/src/commands/lib/command.d.ts +1 -1
  29. package/cli/src/commands/lib/env.d.ts +1 -1
  30. package/cli/src/commands/lib/index.d.ts +2 -2
  31. package/cli/src/commands/lib/index.d.ts.map +1 -1
  32. package/cli/src/commands/lib/log.d.ts +1 -1
  33. package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
  34. package/cli/src/commands/lib/markdown/index.d.ts +1 -1
  35. package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
  36. package/cli/src/commands/lib/production.d.ts +1 -1
  37. package/cli/src/commands/lib/server.d.ts +1 -1
  38. package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
  39. package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
  40. package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
  41. package/cli/src/commands/lib/theme.d.ts +20 -0
  42. package/cli/src/commands/lib/theme.d.ts.map +1 -0
  43. package/cli/src/commands/lib/version.d.ts +1 -1
  44. package/cli/src/commands/og.d.ts +1 -1
  45. package/cli/src/commands/start.d.ts +1 -1
  46. package/cli/src/index.d.ts +1 -1
  47. package/core/index.d.ts +1 -1
  48. package/core/index.js +12 -12
  49. package/core/index.js.map +6 -6
  50. package/core/src/bundler/hash.d.ts +1 -1
  51. package/core/src/bundler/index.d.ts +1 -1
  52. package/core/src/config.d.ts +1 -1
  53. package/core/src/content/discovery.d.ts +1 -1
  54. package/core/src/content/index.d.ts +1 -1
  55. package/core/src/content/metadata.d.ts +1 -1
  56. package/core/src/i18n/catalog.d.ts +1 -1
  57. package/core/src/i18n/discover.d.ts +1 -1
  58. package/core/src/i18n/index.d.ts +1 -1
  59. package/core/src/i18n/messages.d.ts +1 -1
  60. package/core/src/i18n/negotiate.d.ts +1 -1
  61. package/core/src/i18n/pathname.d.ts +1 -1
  62. package/core/src/i18n/resolve.d.ts +1 -1
  63. package/core/src/i18n/types.d.ts +1 -1
  64. package/core/src/index.d.ts +1 -1
  65. package/core/src/llms/extractor.d.ts +1 -1
  66. package/core/src/llms/formatter.d.ts +1 -1
  67. package/core/src/llms/full-generator.d.ts +1 -1
  68. package/core/src/llms/index-generator.d.ts +1 -1
  69. package/core/src/llms/index.d.ts +1 -1
  70. package/core/src/og/discovery.d.ts +1 -1
  71. package/core/src/og/index.d.ts +1 -1
  72. package/core/src/og/meta.d.ts +1 -1
  73. package/core/src/og/render.d.ts +1 -1
  74. package/core/src/og/types.d.ts +1 -1
  75. package/core/src/robots/discovery.d.ts +1 -1
  76. package/core/src/robots/generator.d.ts +1 -1
  77. package/core/src/robots/index.d.ts +1 -1
  78. package/core/src/robots/policies.d.ts +1 -1
  79. package/core/src/rss/discovery.d.ts +1 -1
  80. package/core/src/rss/generator.d.ts +1 -1
  81. package/core/src/rss/index.d.ts +1 -1
  82. package/core/src/sitemap/discovery.d.ts +1 -1
  83. package/core/src/sitemap/generator.d.ts +1 -1
  84. package/core/src/sitemap/index.d.ts +1 -1
  85. package/core/src/ssr/index.d.ts +1 -1
  86. package/core/src/ssr/lib/cache.d.ts +1 -1
  87. package/core/src/ssr/lib/cleanup.d.ts +1 -1
  88. package/core/src/ssr/lib/collections.d.ts +1 -1
  89. package/core/src/ssr/lib/compression.d.ts +1 -1
  90. package/core/src/ssr/lib/compute/content.d.ts +1 -1
  91. package/core/src/ssr/lib/compute/index.d.ts +1 -1
  92. package/core/src/ssr/lib/compute/layouts.d.ts +1 -1
  93. package/core/src/ssr/lib/compute/routes.d.ts +1 -1
  94. package/core/src/ssr/lib/content-path.d.ts +1 -1
  95. package/core/src/ssr/lib/data.d.ts +1 -1
  96. package/core/src/ssr/lib/html.d.ts +1 -1
  97. package/core/src/ssr/lib/imports.d.ts +1 -1
  98. package/core/src/ssr/lib/index.d.ts +1 -1
  99. package/core/src/ssr/lib/layouts.d.ts +1 -1
  100. package/core/src/ssr/lib/metadata.d.ts +1 -1
  101. package/core/src/ssr/lib/mime.d.ts +1 -1
  102. package/core/src/ssr/lib/modules.d.ts +1 -1
  103. package/core/src/ssr/lib/path.d.ts +1 -1
  104. package/core/src/ssr/lib/preload.d.ts +1 -1
  105. package/core/src/ssr/lib/route-match.d.ts +1 -1
  106. package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
  107. package/core/src/ssr/lib/scripts/data.d.ts +1 -1
  108. package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
  109. package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
  110. package/core/src/ssr/lib/scripts/index.d.ts +1 -1
  111. package/core/src/ssr/lib/seed.d.ts +1 -1
  112. package/core/src/ssr/lib/serialize.d.ts +1 -1
  113. package/core/src/ssr/lib/setup.d.ts +2 -2
  114. package/core/src/ssr/lib/setup.d.ts.map +1 -1
  115. package/core/src/ssr/lib/styles.d.ts +3 -3
  116. package/core/src/ssr/lib/styles.d.ts.map +1 -1
  117. package/core/src/ssr/lib/template.d.ts +1 -1
  118. package/core/src/ssr/lib/types.d.ts +1 -1
  119. package/core/src/ssr/render.d.ts +2 -2
  120. package/core/src/ssr/render.d.ts.map +1 -1
  121. package/core/src/ssr/stream.d.ts +2 -2
  122. package/core/src/ssr/stream.d.ts.map +1 -1
  123. package/elysia/index.d.ts +1 -1
  124. package/elysia/index.js +21 -21
  125. package/elysia/index.js.map +9 -9
  126. package/elysia/src/index.d.ts +1 -1
  127. package/elysia/src/libs/assets.d.ts +1 -1
  128. package/elysia/src/libs/cache.d.ts +1 -1
  129. package/elysia/src/libs/caching.d.ts +1 -1
  130. package/elysia/src/libs/http.d.ts +1 -1
  131. package/elysia/src/libs/i18n.d.ts +1 -1
  132. package/elysia/src/libs/image.d.ts +1 -1
  133. package/elysia/src/libs/index.d.ts +1 -1
  134. package/elysia/src/libs/llms.d.ts +1 -1
  135. package/elysia/src/libs/response.d.ts +1 -1
  136. package/elysia/src/libs/serving.d.ts +1 -1
  137. package/elysia/src/plugin.d.ts +1 -1
  138. package/elysia/src/routes/artifacts.d.ts +1 -1
  139. package/elysia/src/routes/content.d.ts +1 -1
  140. package/elysia/src/routes/image.d.ts +1 -1
  141. package/elysia/src/routes/index.d.ts +1 -1
  142. package/elysia/src/routes/internal.d.ts +1 -1
  143. package/elysia/src/routes/llms.d.ts +1 -1
  144. package/elysia/src/routes/og.d.ts +1 -1
  145. package/elysia/src/routes/redirects.d.ts +1 -1
  146. package/elysia/src/routes/robots.d.ts +1 -1
  147. package/elysia/src/routes/rss.d.ts +1 -1
  148. package/elysia/src/routes/search.d.ts +1 -1
  149. package/elysia/src/routes/sitemap.d.ts +1 -1
  150. package/elysia/src/routes/ssr.d.ts +2 -2
  151. package/elysia/src/routes/ssr.d.ts.map +1 -1
  152. package/elysia/src/routes/static.d.ts +1 -1
  153. package/elysia/src/types.d.ts +1 -1
  154. package/package.json +2 -5
  155. package/react/index.d.ts +1 -1
  156. package/react/index.js +2 -2
  157. package/react/index.js.map +1 -1
  158. package/react/src/components/ClientOnly.d.ts +1 -1
  159. package/react/src/components/ContentRoute.d.ts +1 -1
  160. package/react/src/components/Image.d.ts +1 -1
  161. package/react/src/components/LazyRoute.d.ts +1 -1
  162. package/react/src/components/Link.d.ts +1 -1
  163. package/react/src/components/Markdown.d.ts +1 -1
  164. package/react/src/components/Outlet.d.ts +1 -1
  165. package/react/src/components/index.d.ts +1 -1
  166. package/react/src/hooks/index.d.ts +1 -1
  167. package/react/src/hooks/useContent.d.ts +1 -1
  168. package/react/src/hooks/useData.d.ts +1 -1
  169. package/react/src/hooks/useFeed.d.ts +1 -1
  170. package/react/src/hooks/useLayoutData.d.ts +1 -1
  171. package/react/src/hooks/useLlms.d.ts +1 -1
  172. package/react/src/hooks/useNavigate.d.ts +1 -1
  173. package/react/src/hooks/useParams.d.ts +1 -1
  174. package/react/src/hooks/useRouter.d.ts +1 -1
  175. package/react/src/hooks/useSearch.d.ts +1 -1
  176. package/react/src/hooks/useSearchParams.d.ts +1 -1
  177. package/react/src/hooks/useToc.d.ts +1 -1
  178. package/react/src/i18n/LocaleProvider.d.ts +1 -1
  179. package/react/src/i18n/helpers.d.ts +1 -1
  180. package/react/src/i18n/index.d.ts +1 -1
  181. package/react/src/index.d.ts +1 -1
  182. package/react/src/lib/collection.d.ts +1 -1
  183. package/react/src/lib/content.d.ts +1 -1
  184. package/react/src/lib/head.d.ts +1 -1
  185. package/react/src/lib/index.d.ts +1 -1
  186. package/react/src/lib/lazy-route.d.ts +1 -1
  187. package/react/src/lib/route-loader.d.ts +1 -1
  188. package/react/src/providers/ContentProvider.d.ts +1 -1
  189. package/react/src/providers/RerouteProvider.d.ts +1 -1
  190. package/react/src/providers/RouterProvider.d.ts +1 -1
  191. package/react/src/providers/index.d.ts +1 -1
  192. package/react/src/types/any.d.ts +1 -1
  193. package/react/src/types/index.d.ts +1 -1
  194. package/react/src/types/router.d.ts +1 -1
  195. package/telemetry/react.d.ts +1 -1
  196. package/telemetry/react.js +2 -2
  197. package/telemetry/react.js.map +1 -1
  198. package/telemetry/server.d.ts +1 -1
  199. package/telemetry/server.js +2 -2
  200. package/telemetry/server.js.map +4 -4
  201. package/telemetry/src/react/api.d.ts +1 -1
  202. package/telemetry/src/react/context.d.ts +1 -1
  203. package/telemetry/src/react/index.d.ts +1 -1
  204. package/telemetry/src/react/telemetry.d.ts +1 -1
  205. package/telemetry/src/server/context.d.ts +1 -1
  206. package/telemetry/src/server/headers/extractor.d.ts +1 -1
  207. package/telemetry/src/server/headers/index.d.ts +1 -1
  208. package/telemetry/src/server/headers/presets.d.ts +1 -1
  209. package/telemetry/src/server/index.d.ts +1 -1
  210. package/telemetry/src/server/instrumentation.d.ts +1 -1
  211. package/telemetry/src/server/plugin.d.ts +1 -1
  212. package/telemetry/src/server/sourcemap.d.ts +1 -1
  213. package/cli/src/commands/lib/tailwind.d.ts +0 -20
  214. package/cli/src/commands/lib/tailwind.d.ts.map +0 -1
@@ -1,6 +1,4 @@
1
- @import "tailwindcss";
2
-
3
- @theme {
1
+ :root {
4
2
  /* Primary Brand Colors */
5
3
  --color-primary-50: #eff6ff;
6
4
  --color-primary-100: #dbeafe;
@@ -14,12 +12,28 @@
14
12
  --color-primary-900: #1e3a8a;
15
13
  --color-primary-950: #172554;
16
14
 
15
+ /* Neutrals */
16
+ --color-gray-50: #f9fafb;
17
+ --color-gray-100: #f3f4f6;
18
+ --color-gray-200: #e5e7eb;
19
+ --color-gray-300: #d1d5db;
20
+ --color-gray-600: #4b5563;
21
+ --color-gray-700: #374151;
22
+ --color-gray-900: #111827;
23
+
24
+ /* Semantic */
25
+ --color-red-50: #fef2f2;
26
+ --color-red-600: #dc2626;
27
+ --color-green-600: #16a34a;
28
+
17
29
  /* Custom Shadows */
18
30
  --shadow-soft:
19
31
  0 2px 15px -3px rgb(0 0 0 / 0.07), 0 10px 20px -2px rgb(0 0 0 / 0.04);
20
32
  --shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px 0 rgb(0 0 0 / 0.06);
21
33
  --shadow-card-hover:
22
34
  0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -2px rgb(0 0 0 / 0.05);
35
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
36
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
23
37
 
24
38
  /* Custom Animations */
25
39
  --animate-fade-in: fadeIn 0.3s ease-in-out;
@@ -58,17 +72,149 @@
58
72
  }
59
73
  }
60
74
 
61
- @layer base {
62
- body {
63
- @apply antialiased bg-gray-50 text-gray-900;
75
+ @keyframes pulse {
76
+ 0%,
77
+ 100% {
78
+ opacity: 1;
79
+ }
80
+ 50% {
81
+ opacity: 0.5;
82
+ }
83
+ }
84
+
85
+ /* Base */
86
+ *,
87
+ *::before,
88
+ *::after {
89
+ box-sizing: border-box;
90
+ border-color: #e5e7eb;
91
+ }
92
+
93
+ body {
94
+ margin: 0;
95
+ background: #f9fafb;
96
+ color: #111827;
97
+ -webkit-font-smoothing: antialiased;
98
+ }
99
+
100
+ a {
101
+ text-decoration: none;
102
+ color: inherit;
103
+ }
104
+
105
+ img {
106
+ display: block;
107
+ max-width: 100%;
108
+ }
109
+
110
+ button,
111
+ input,
112
+ select {
113
+ font: inherit;
114
+ }
115
+
116
+ /* Layout */
117
+ .page-main {
118
+ max-width: 80rem;
119
+ margin-left: auto;
120
+ margin-right: auto;
121
+ padding: 2rem 1rem;
122
+ }
123
+
124
+ @media (min-width: 640px) {
125
+ .page-main {
126
+ padding-left: 1.5rem;
127
+ padding-right: 1.5rem;
64
128
  }
129
+ }
65
130
 
66
- * {
67
- @apply border-gray-200;
131
+ @media (min-width: 1024px) {
132
+ .page-main {
133
+ padding-left: 2rem;
134
+ padding-right: 2rem;
68
135
  }
69
136
  }
70
137
 
71
- @utility btn {
138
+ .page-main-lg {
139
+ padding-top: 4rem;
140
+ padding-bottom: 4rem;
141
+ }
142
+
143
+ .container-custom {
144
+ max-width: 80rem;
145
+ margin-left: auto;
146
+ margin-right: auto;
147
+ padding-left: 1rem;
148
+ padding-right: 1rem;
149
+ }
150
+
151
+ @media (min-width: 640px) {
152
+ .container-custom {
153
+ padding-left: 1.5rem;
154
+ padding-right: 1.5rem;
155
+ }
156
+ }
157
+
158
+ @media (min-width: 1024px) {
159
+ .container-custom {
160
+ padding-left: 2rem;
161
+ padding-right: 2rem;
162
+ }
163
+ }
164
+
165
+ /* Header */
166
+ .site-header {
167
+ position: sticky;
168
+ top: 0;
169
+ z-index: 50;
170
+ background-color: white;
171
+ border-bottom: 1px solid var(--color-gray-200);
172
+ box-shadow: var(--shadow-sm);
173
+ }
174
+
175
+ .header-inner {
176
+ display: flex;
177
+ align-items: center;
178
+ justify-content: space-between;
179
+ height: 4rem;
180
+ }
181
+
182
+ .header-logo {
183
+ display: flex;
184
+ align-items: center;
185
+ gap: 0.5rem;
186
+ font-size: 1.5rem;
187
+ font-weight: 700;
188
+ color: var(--color-primary-600);
189
+ transition: color 0.15s;
190
+ }
191
+
192
+ .header-logo:hover {
193
+ color: var(--color-primary-700);
194
+ }
195
+
196
+ .header-logo-icon {
197
+ font-size: 1.875rem;
198
+ }
199
+
200
+ .header-nav {
201
+ display: flex;
202
+ align-items: center;
203
+ gap: 2rem;
204
+ }
205
+
206
+ .nav-link {
207
+ color: var(--color-gray-600);
208
+ font-weight: 500;
209
+ transition: color 0.15s;
210
+ }
211
+
212
+ .nav-link:hover {
213
+ color: var(--color-primary-600);
214
+ }
215
+
216
+ /* Buttons */
217
+ .btn {
72
218
  display: inline-flex;
73
219
  align-items: center;
74
220
  justify-content: center;
@@ -76,87 +222,155 @@
76
222
  border-radius: 0.5rem;
77
223
  font-weight: 600;
78
224
  transition: all 0.2s;
225
+ border: none;
226
+ cursor: pointer;
227
+ }
79
228
 
80
- &:disabled {
81
- opacity: 0.5;
82
- cursor: not-allowed;
83
- }
229
+ .btn:disabled {
230
+ opacity: 0.5;
231
+ cursor: not-allowed;
84
232
  }
85
233
 
86
- @utility btn-primary {
234
+ .btn-primary {
235
+ display: inline-flex;
236
+ align-items: center;
237
+ justify-content: center;
238
+ padding: 0.75rem 1.5rem;
239
+ border-radius: 0.5rem;
240
+ font-weight: 600;
241
+ transition: all 0.2s;
242
+ border: none;
243
+ cursor: pointer;
87
244
  background-color: var(--color-primary-600);
88
245
  color: white;
89
- box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
246
+ box-shadow: var(--shadow-sm);
247
+ }
90
248
 
91
- &:hover:not(:disabled) {
92
- background-color: var(--color-primary-700);
93
- box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
94
- transform: translateY(-1px);
95
- }
249
+ .btn-primary:hover:not(:disabled) {
250
+ background-color: var(--color-primary-700);
251
+ box-shadow: var(--shadow-md);
252
+ transform: translateY(-1px);
253
+ }
96
254
 
97
- &:active:not(:disabled) {
98
- background-color: var(--color-primary-800);
99
- }
255
+ .btn-primary:active:not(:disabled) {
256
+ background-color: var(--color-primary-800);
257
+ }
258
+
259
+ .btn-primary:disabled {
260
+ opacity: 0.5;
261
+ cursor: not-allowed;
100
262
  }
101
263
 
102
- @utility btn-secondary {
264
+ .btn-secondary {
265
+ display: inline-flex;
266
+ align-items: center;
267
+ justify-content: center;
268
+ padding: 0.75rem 1.5rem;
269
+ border-radius: 0.5rem;
270
+ font-weight: 600;
271
+ transition: all 0.2s;
272
+ cursor: pointer;
103
273
  background-color: white;
104
274
  color: var(--color-primary-600);
105
275
  border: 2px solid var(--color-primary-600);
276
+ }
106
277
 
107
- &:hover:not(:disabled) {
108
- background-color: var(--color-primary-50);
109
- transform: translateY(-1px);
110
- }
278
+ .btn-secondary:hover:not(:disabled) {
279
+ background-color: var(--color-primary-50);
280
+ transform: translateY(-1px);
281
+ }
111
282
 
112
- &:active:not(:disabled) {
113
- background-color: var(--color-primary-100);
114
- }
283
+ .btn-secondary:active:not(:disabled) {
284
+ background-color: var(--color-primary-100);
115
285
  }
116
286
 
117
- @utility btn-sm {
287
+ .btn-secondary:disabled {
288
+ opacity: 0.5;
289
+ cursor: not-allowed;
290
+ }
291
+
292
+ .btn-sm {
118
293
  padding: 0.5rem 1rem;
119
294
  font-size: 0.875rem;
120
295
  }
121
296
 
122
- @utility btn-lg {
297
+ .btn-lg {
123
298
  padding: 1rem 2rem;
124
299
  font-size: 1.125rem;
125
300
  }
126
301
 
127
- @utility card {
302
+ .btn-grow {
303
+ flex: 1;
304
+ }
305
+
306
+ .sort-btn {
307
+ padding: 0.5rem 1rem;
308
+ font-size: 0.875rem;
309
+ font-weight: 600;
310
+ border-radius: 0.5rem;
311
+ border: 1px solid var(--color-gray-300);
312
+ background-color: white;
313
+ color: var(--color-gray-700);
314
+ cursor: pointer;
315
+ transition: all 0.2s;
316
+ }
317
+
318
+ .sort-btn:hover {
319
+ background-color: var(--color-gray-50);
320
+ }
321
+
322
+ .sort-btn.is-active {
323
+ background-color: var(--color-primary-600);
324
+ color: white;
325
+ border-color: var(--color-primary-600);
326
+ }
327
+
328
+ /* Cards */
329
+ .card {
128
330
  background-color: white;
129
331
  border-radius: 0.75rem;
130
332
  box-shadow: var(--shadow-card);
131
333
  transition: all 0.2s;
132
334
  }
133
335
 
134
- @utility card-hover {
135
- &:hover {
136
- box-shadow: var(--shadow-card-hover);
137
- transform: translateY(-4px);
138
- }
336
+ .card-hover:hover {
337
+ box-shadow: var(--shadow-card-hover);
338
+ transform: translateY(-4px);
339
+ }
340
+
341
+ .card-padded {
342
+ padding: 1.5rem;
139
343
  }
140
344
 
141
- @utility link {
345
+ /* Links */
346
+ .link {
142
347
  color: var(--color-primary-600);
143
348
  transition: color 0.15s;
349
+ }
144
350
 
145
- &:hover {
146
- color: var(--color-primary-700);
147
- }
351
+ .link:hover {
352
+ color: var(--color-primary-700);
148
353
  }
149
354
 
150
- @utility link-muted {
151
- color: rgb(75 85 99);
355
+ .link-muted {
356
+ color: var(--color-gray-600);
152
357
  transition: color 0.15s;
358
+ }
153
359
 
154
- &:hover {
155
- color: rgb(17 24 39);
156
- }
360
+ .link-muted:hover {
361
+ color: var(--color-gray-900);
362
+ }
363
+
364
+ .link-semibold {
365
+ font-weight: 600;
366
+ }
367
+
368
+ .link-lg {
369
+ font-size: 1.125rem;
157
370
  }
158
371
 
159
- @utility badge {
372
+ /* Badges */
373
+ .badge {
160
374
  display: inline-flex;
161
375
  align-items: center;
162
376
  padding: 0.25rem 0.75rem;
@@ -167,123 +381,721 @@
167
381
  letter-spacing: 0.05em;
168
382
  }
169
383
 
170
- @utility badge-primary {
384
+ .badge-primary {
385
+ display: inline-flex;
386
+ align-items: center;
387
+ padding: 0.25rem 0.75rem;
388
+ border-radius: 9999px;
389
+ font-size: 0.75rem;
390
+ font-weight: 600;
391
+ text-transform: uppercase;
392
+ letter-spacing: 0.05em;
171
393
  background-color: var(--color-primary-100);
172
394
  color: var(--color-primary-700);
173
395
  }
174
396
 
175
- @utility badge-success {
397
+ .badge-success {
398
+ display: inline-flex;
399
+ align-items: center;
400
+ padding: 0.25rem 0.75rem;
401
+ border-radius: 9999px;
402
+ font-size: 0.75rem;
403
+ font-weight: 600;
404
+ text-transform: uppercase;
405
+ letter-spacing: 0.05em;
176
406
  background-color: rgb(220 252 231);
177
407
  color: rgb(21 128 61);
178
408
  }
179
409
 
180
- @utility input {
410
+ /* Form controls */
411
+ .input {
181
412
  width: 100%;
182
413
  padding: 0.625rem 1rem;
183
414
  border-radius: 0.5rem;
184
- border: 1px solid rgb(209 213 219);
415
+ border: 1px solid var(--color-gray-300);
185
416
  outline: none;
186
417
  transition: all 0.15s;
418
+ }
187
419
 
188
- &:focus {
189
- border-color: var(--color-primary-500);
190
- box-shadow: 0 0 0 3px rgb(37 99 235 / 0.1);
191
- }
420
+ .input:focus {
421
+ border-color: var(--color-primary-500);
422
+ box-shadow: 0 0 0 3px rgb(37 99 235 / 0.1);
192
423
  }
193
424
 
194
- @utility select {
425
+ .input-grow {
426
+ flex: 1;
427
+ min-width: 250px;
428
+ }
429
+
430
+ .select {
195
431
  width: 100%;
196
432
  padding: 0.625rem 1rem;
197
433
  border-radius: 0.5rem;
198
- border: 1px solid rgb(209 213 219);
434
+ border: 1px solid var(--color-gray-300);
199
435
  background-color: white;
200
436
  cursor: pointer;
201
437
  outline: none;
202
438
  transition: all 0.15s;
203
-
204
- &:focus {
205
- border-color: var(--color-primary-500);
206
- box-shadow: 0 0 0 3px rgb(37 99 235 / 0.1);
207
- }
208
439
  }
209
440
 
210
- @utility container-custom {
211
- max-width: 80rem;
212
- margin-left: auto;
213
- margin-right: auto;
214
- padding-left: 1rem;
215
- padding-right: 1rem;
216
-
217
- @media (min-width: 640px) {
218
- padding-left: 1.5rem;
219
- padding-right: 1.5rem;
220
- }
441
+ .select:focus {
442
+ border-color: var(--color-primary-500);
443
+ box-shadow: 0 0 0 3px rgb(37 99 235 / 0.1);
444
+ }
221
445
 
222
- @media (min-width: 1024px) {
223
- padding-left: 2rem;
224
- padding-right: 2rem;
225
- }
446
+ .select-min {
447
+ min-width: 200px;
226
448
  }
227
449
 
228
- @utility section-heading {
450
+ /* Typography / sections */
451
+ .section-heading {
229
452
  font-size: 1.875rem;
230
453
  font-weight: 700;
231
- color: rgb(17 24 39);
454
+ color: var(--color-gray-900);
232
455
  margin-bottom: 0.5rem;
456
+ }
233
457
 
234
- @media (min-width: 768px) {
458
+ @media (min-width: 768px) {
459
+ .section-heading {
235
460
  font-size: 2.25rem;
236
461
  }
237
462
  }
238
463
 
239
- @utility section-subheading {
464
+ .section-heading-flush {
465
+ margin-bottom: 0;
466
+ }
467
+
468
+ .section-subheading {
240
469
  font-size: 1.125rem;
241
- color: rgb(107 114 128);
470
+ color: var(--color-gray-600);
242
471
  margin-bottom: 2rem;
243
472
  }
244
473
 
245
- @utility product-grid {
474
+ .section-header {
475
+ display: flex;
476
+ justify-content: space-between;
477
+ align-items: center;
478
+ margin-bottom: 1.5rem;
479
+ }
480
+
481
+ .section-block {
482
+ margin-bottom: 4rem;
483
+ }
484
+
485
+ .page-title {
486
+ font-size: 2.25rem;
487
+ font-weight: 700;
488
+ color: var(--color-gray-900);
489
+ margin-bottom: 2rem;
490
+ }
491
+
492
+ /* Hero */
493
+ .hero {
494
+ text-align: center;
495
+ padding: 3rem 0;
496
+ margin-bottom: 3rem;
497
+ }
498
+
499
+ .hero-title {
500
+ font-size: 3rem;
501
+ font-weight: 700;
502
+ color: var(--color-gray-900);
503
+ margin-bottom: 1rem;
504
+ line-height: 1.1;
505
+ }
506
+
507
+ @media (min-width: 768px) {
508
+ .hero-title {
509
+ font-size: 3.75rem;
510
+ }
511
+ }
512
+
513
+ .hero-lead {
514
+ font-size: 1.25rem;
515
+ color: var(--color-gray-600);
516
+ margin-bottom: 2rem;
517
+ max-width: 42rem;
518
+ margin-left: auto;
519
+ margin-right: auto;
520
+ }
521
+
522
+ .hero-actions {
523
+ display: flex;
524
+ gap: 1rem;
525
+ justify-content: center;
526
+ flex-wrap: wrap;
527
+ }
528
+
529
+ /* Grids */
530
+ .product-grid {
246
531
  display: grid;
247
532
  grid-template-columns: repeat(1, minmax(0, 1fr));
248
533
  gap: 1.5rem;
534
+ }
249
535
 
250
- @media (min-width: 640px) {
536
+ @media (min-width: 640px) {
537
+ .product-grid {
251
538
  grid-template-columns: repeat(2, minmax(0, 1fr));
252
539
  }
540
+ }
541
+
542
+ @media (min-width: 1024px) {
543
+ .product-grid {
544
+ grid-template-columns: repeat(3, minmax(0, 1fr));
545
+ }
546
+ }
547
+
548
+ @media (min-width: 1280px) {
549
+ .product-grid {
550
+ grid-template-columns: repeat(4, minmax(0, 1fr));
551
+ }
552
+ }
553
+
554
+ .features-grid {
555
+ display: grid;
556
+ grid-template-columns: 1fr;
557
+ gap: 2rem;
558
+ margin-top: 3rem;
559
+ padding-top: 2rem;
560
+ }
561
+
562
+ @media (min-width: 768px) {
563
+ .features-grid {
564
+ grid-template-columns: repeat(2, minmax(0, 1fr));
565
+ }
566
+ }
567
+
568
+ @media (min-width: 1024px) {
569
+ .features-grid {
570
+ grid-template-columns: repeat(4, minmax(0, 1fr));
571
+ }
572
+ }
573
+
574
+ .category-grid {
575
+ display: grid;
576
+ grid-template-columns: 1fr;
577
+ gap: 2rem;
578
+ margin-bottom: 3rem;
579
+ }
580
+
581
+ @media (min-width: 640px) {
582
+ .category-grid {
583
+ grid-template-columns: repeat(2, minmax(0, 1fr));
584
+ }
585
+ }
586
+
587
+ @media (min-width: 1024px) {
588
+ .category-grid {
589
+ grid-template-columns: repeat(4, minmax(0, 1fr));
590
+ }
591
+ }
592
+
593
+ .not-found-links {
594
+ display: grid;
595
+ grid-template-columns: 1fr;
596
+ gap: 1.5rem;
597
+ margin-top: 4rem;
598
+ }
253
599
 
254
- @media (min-width: 1024px) {
600
+ @media (min-width: 768px) {
601
+ .not-found-links {
255
602
  grid-template-columns: repeat(3, minmax(0, 1fr));
256
603
  }
604
+ }
257
605
 
258
- @media (min-width: 1280px) {
606
+ .why-shop-grid {
607
+ display: grid;
608
+ grid-template-columns: 1fr;
609
+ gap: 2rem;
610
+ }
611
+
612
+ @media (min-width: 640px) {
613
+ .why-shop-grid {
614
+ grid-template-columns: repeat(2, minmax(0, 1fr));
615
+ }
616
+ }
617
+
618
+ @media (min-width: 1024px) {
619
+ .why-shop-grid {
259
620
  grid-template-columns: repeat(4, minmax(0, 1fr));
260
621
  }
261
622
  }
262
623
 
263
- @utility feature-card {
624
+ /* Feature cards */
625
+ .feature-card {
264
626
  text-align: center;
265
627
  padding: 1.5rem;
266
628
  border-radius: 0.75rem;
267
629
  transition: all 0.2s;
630
+ }
631
+
632
+ .feature-card:hover {
633
+ background-color: white;
634
+ box-shadow: var(--shadow-soft);
635
+ }
636
+
637
+ .feature-icon {
638
+ font-size: 3rem;
639
+ margin-bottom: 1rem;
640
+ }
641
+
642
+ .feature-title {
643
+ font-size: 1.25rem;
644
+ font-weight: 600;
645
+ margin-bottom: 0.5rem;
646
+ color: var(--color-gray-900);
647
+ }
648
+
649
+ .feature-text {
650
+ color: var(--color-gray-600);
651
+ line-height: 1.625;
652
+ }
653
+
654
+ /* Product card */
655
+ .product-card {
656
+ display: flex;
657
+ flex-direction: column;
658
+ height: 100%;
659
+ }
660
+
661
+ .product-card-link {
662
+ display: block;
663
+ height: 100%;
664
+ color: inherit;
665
+ }
666
+
667
+ .product-card-image-wrap {
668
+ width: 100%;
669
+ height: 15rem;
670
+ background-color: var(--color-gray-50);
671
+ display: flex;
672
+ align-items: center;
673
+ justify-content: center;
674
+ padding: 1rem;
675
+ }
676
+
677
+ .product-card-image {
678
+ max-width: 100%;
679
+ max-height: 100%;
680
+ object-fit: contain;
681
+ position: relative;
682
+ z-index: 10;
683
+ background-color: white;
684
+ }
685
+
686
+ .product-card-body {
687
+ padding: 1rem;
688
+ display: flex;
689
+ flex-direction: column;
690
+ gap: 0.5rem;
691
+ flex: 1;
692
+ }
693
+
694
+ .product-card-title {
695
+ font-size: 1rem;
696
+ font-weight: 600;
697
+ color: var(--color-gray-900);
698
+ line-height: 1.5;
699
+ display: -webkit-box;
700
+ -webkit-line-clamp: 2;
701
+ -webkit-box-orient: vertical;
702
+ overflow: hidden;
703
+ min-height: 3em;
704
+ transition: color 0.15s;
705
+ }
706
+
707
+ .product-card:hover .product-card-title {
708
+ color: var(--color-primary-600);
709
+ }
710
+
711
+ .product-card-footer {
712
+ display: flex;
713
+ justify-content: space-between;
714
+ align-items: center;
715
+ margin-top: auto;
716
+ padding-top: 0.5rem;
717
+ }
718
+
719
+ .price {
720
+ font-size: 1.25rem;
721
+ font-weight: 700;
722
+ color: var(--color-primary-600);
723
+ }
724
+
725
+ .price-lg {
726
+ font-size: 2.25rem;
727
+ font-weight: 700;
728
+ color: var(--color-primary-600);
729
+ }
730
+
731
+ .product-rating {
732
+ display: flex;
733
+ align-items: center;
734
+ gap: 0.25rem;
735
+ font-size: 0.875rem;
736
+ color: var(--color-gray-600);
737
+ }
738
+
739
+ .product-rating-lg {
740
+ display: flex;
741
+ align-items: center;
742
+ gap: 0.5rem;
743
+ font-size: 1rem;
744
+ color: var(--color-gray-600);
745
+ }
746
+
747
+ .product-rating-star {
748
+ font-size: 1.5rem;
749
+ }
750
+
751
+ .product-rating-value {
752
+ font-weight: 600;
753
+ font-size: 1.25rem;
754
+ }
755
+
756
+ /* Category card */
757
+ .category-card {
758
+ display: block;
759
+ padding: 2rem;
760
+ color: var(--color-gray-900);
761
+ }
762
+
763
+ .category-card-icon {
764
+ font-size: 3rem;
765
+ margin-bottom: 1rem;
766
+ }
767
+
768
+ .category-card-title {
769
+ font-size: 1.5rem;
770
+ font-weight: 700;
771
+ margin-bottom: 0.5rem;
772
+ text-transform: capitalize;
773
+ transition: color 0.15s;
774
+ }
775
+
776
+ .category-card:hover .category-card-title {
777
+ color: var(--color-primary-600);
778
+ }
779
+
780
+ .category-card-desc {
781
+ color: var(--color-gray-600);
782
+ font-size: 0.875rem;
783
+ margin-bottom: 1rem;
784
+ }
785
+
786
+ .category-card-cta {
787
+ display: inline-flex;
788
+ align-items: center;
789
+ gap: 0.5rem;
790
+ }
268
791
 
269
- &:hover {
270
- background-color: white;
271
- box-shadow: var(--shadow-soft);
792
+ /* Filter bar */
793
+ .filter-bar {
794
+ display: flex;
795
+ flex-wrap: wrap;
796
+ align-items: center;
797
+ gap: 1rem;
798
+ margin-bottom: 2rem;
799
+ padding: 1.5rem;
800
+ background-color: white;
801
+ border-radius: 0.75rem;
802
+ box-shadow: var(--shadow-card);
803
+ }
804
+
805
+ .filter-group {
806
+ display: flex;
807
+ align-items: center;
808
+ gap: 0.5rem;
809
+ }
810
+
811
+ .filter-label {
812
+ font-weight: 600;
813
+ color: var(--color-gray-700);
814
+ }
815
+
816
+ .filter-sort-group {
817
+ display: flex;
818
+ gap: 0.5rem;
819
+ flex-wrap: wrap;
820
+ }
821
+
822
+ .filter-count {
823
+ margin-left: auto;
824
+ font-size: 0.875rem;
825
+ color: var(--color-gray-600);
826
+ }
827
+
828
+ /* Breadcrumb */
829
+ .breadcrumb {
830
+ display: flex;
831
+ align-items: center;
832
+ gap: 0.5rem;
833
+ font-size: 0.875rem;
834
+ color: var(--color-gray-600);
835
+ margin-bottom: 2rem;
836
+ flex-wrap: wrap;
837
+ }
838
+
839
+ .breadcrumb-current {
840
+ color: var(--color-gray-900);
841
+ }
842
+
843
+ /* States */
844
+ .state-loading {
845
+ text-align: center;
846
+ padding: 4rem 0;
847
+ color: var(--color-gray-600);
848
+ font-size: 1.125rem;
849
+ }
850
+
851
+ .state-loading-pulse {
852
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
853
+ }
854
+
855
+ .state-error {
856
+ text-align: center;
857
+ padding: 3rem 0;
858
+ background-color: var(--color-red-50);
859
+ color: var(--color-red-600);
860
+ font-size: 1.125rem;
861
+ border-radius: 0.75rem;
862
+ }
863
+
864
+ .state-error-inline {
865
+ text-align: center;
866
+ padding: 3rem 0;
867
+ background-color: var(--color-red-50);
868
+ color: var(--color-red-600);
869
+ font-size: 1.125rem;
870
+ border-radius: 0.75rem;
871
+ }
872
+
873
+ .state-error-action {
874
+ margin-top: 1rem;
875
+ }
876
+
877
+ .state-empty {
878
+ text-align: center;
879
+ padding: 4rem 0;
880
+ color: var(--color-gray-600);
881
+ font-size: 1.125rem;
882
+ }
883
+
884
+ .state-empty-icon {
885
+ font-size: 3.75rem;
886
+ margin-bottom: 1rem;
887
+ }
888
+
889
+ .state-empty-action {
890
+ margin-bottom: 1rem;
891
+ }
892
+
893
+ /* Product detail */
894
+ .product-detail-grid {
895
+ display: grid;
896
+ grid-template-columns: 1fr;
897
+ gap: 3rem;
898
+ margin-bottom: 4rem;
899
+ }
900
+
901
+ @media (min-width: 1024px) {
902
+ .product-detail-grid {
903
+ grid-template-columns: repeat(2, minmax(0, 1fr));
272
904
  }
273
905
  }
274
906
 
275
- @utility animate-in {
907
+ .product-detail-image {
908
+ display: flex;
909
+ align-items: center;
910
+ justify-content: center;
911
+ padding: 2rem;
912
+ min-height: 500px;
913
+ }
914
+
915
+ .product-detail-image-img {
916
+ max-width: 100%;
917
+ max-height: 500px;
918
+ object-fit: contain;
919
+ position: relative;
920
+ z-index: 10;
921
+ }
922
+
923
+ .product-detail-info {
924
+ display: flex;
925
+ flex-direction: column;
926
+ gap: 1.5rem;
927
+ }
928
+
929
+ .product-detail-title {
930
+ font-size: 2.25rem;
931
+ font-weight: 700;
932
+ color: var(--color-gray-900);
933
+ line-height: 1.1;
934
+ }
935
+
936
+ .product-detail-description {
937
+ font-size: 1.125rem;
938
+ color: var(--color-gray-700);
939
+ line-height: 1.625;
940
+ }
941
+
942
+ .product-actions {
943
+ display: flex;
944
+ gap: 1rem;
945
+ margin-top: 1rem;
946
+ }
947
+
948
+ .product-perks {
949
+ padding: 1rem;
950
+ background-color: var(--color-gray-50);
951
+ border-radius: 0.75rem;
952
+ font-size: 0.875rem;
953
+ color: var(--color-gray-600);
954
+ }
955
+
956
+ .product-perk {
957
+ display: flex;
958
+ align-items: center;
959
+ gap: 0.5rem;
960
+ }
961
+
962
+ .product-perk + .product-perk {
963
+ margin-top: 0.5rem;
964
+ }
965
+
966
+ .product-perk-check {
967
+ color: var(--color-green-600);
968
+ font-weight: 700;
969
+ }
970
+
971
+ /* Category page header */
972
+ .category-header {
973
+ display: flex;
974
+ align-items: center;
975
+ gap: 0.75rem;
976
+ margin-bottom: 0.5rem;
977
+ }
978
+
979
+ .category-header-icon {
980
+ font-size: 3rem;
981
+ }
982
+
983
+ /* Why shop block */
984
+ .why-shop {
985
+ margin-top: 4rem;
986
+ padding: 2rem;
987
+ background-color: var(--color-gray-50);
988
+ border-radius: 0.75rem;
989
+ text-align: center;
990
+ }
991
+
992
+ .why-shop-title {
993
+ font-size: 1.5rem;
994
+ font-weight: 700;
995
+ margin-bottom: 1.5rem;
996
+ color: var(--color-gray-900);
997
+ }
998
+
999
+ .why-shop-item-icon {
1000
+ font-size: 2.25rem;
1001
+ margin-bottom: 0.5rem;
1002
+ }
1003
+
1004
+ .why-shop-item-title {
1005
+ font-weight: 600;
1006
+ color: var(--color-gray-700);
1007
+ margin-bottom: 0.25rem;
1008
+ }
1009
+
1010
+ .why-shop-item-desc {
1011
+ font-size: 0.875rem;
1012
+ color: var(--color-gray-600);
1013
+ }
1014
+
1015
+ /* 404 */
1016
+ .not-found-content {
1017
+ max-width: 42rem;
1018
+ margin-left: auto;
1019
+ margin-right: auto;
1020
+ text-align: center;
1021
+ }
1022
+
1023
+ .not-found-code {
1024
+ font-size: 6rem;
1025
+ font-weight: 700;
1026
+ color: var(--color-primary-600);
1027
+ margin-bottom: 1rem;
1028
+ line-height: 1;
1029
+ }
1030
+
1031
+ .not-found-title {
1032
+ font-size: 2.25rem;
1033
+ font-weight: 700;
1034
+ color: var(--color-gray-900);
1035
+ margin-bottom: 1rem;
1036
+ }
1037
+
1038
+ .not-found-lead {
1039
+ font-size: 1.25rem;
1040
+ color: var(--color-gray-600);
1041
+ margin-bottom: 2rem;
1042
+ }
1043
+
1044
+ .not-found-actions {
1045
+ display: flex;
1046
+ flex-direction: column;
1047
+ gap: 1rem;
1048
+ justify-content: center;
1049
+ margin-bottom: 3rem;
1050
+ }
1051
+
1052
+ @media (min-width: 640px) {
1053
+ .not-found-actions {
1054
+ flex-direction: row;
1055
+ }
1056
+ }
1057
+
1058
+ .not-found-card-icon {
1059
+ font-size: 2.25rem;
1060
+ margin-bottom: 0.75rem;
1061
+ }
1062
+
1063
+ .not-found-card-title {
1064
+ font-weight: 600;
1065
+ margin-bottom: 0.5rem;
1066
+ }
1067
+
1068
+ .not-found-card-desc {
1069
+ font-size: 0.875rem;
1070
+ color: var(--color-gray-600);
1071
+ }
1072
+
1073
+ /* Page intro */
1074
+ .page-intro {
1075
+ margin-bottom: 2rem;
1076
+ }
1077
+
1078
+ .page-intro-lg {
1079
+ margin-bottom: 3rem;
1080
+ }
1081
+
1082
+ /* Animations */
1083
+ .animate-in {
276
1084
  animation: var(--animate-fade-in);
277
1085
  }
278
1086
 
279
- @utility animate-slide-up {
1087
+ .animate-slide-up {
280
1088
  animation: var(--animate-slide-up);
281
1089
  }
282
1090
 
283
- @utility animate-scale {
1091
+ .animate-scale {
284
1092
  animation: var(--animate-scale-in);
285
1093
  }
286
1094
 
1095
+ .shadow-card {
1096
+ box-shadow: var(--shadow-card);
1097
+ }
1098
+
287
1099
  /* View Transition API Configuration */
288
1100
  ::view-transition-old(root) {
289
1101
  animation: 0.25s cubic-bezier(0.4, 0, 1, 1) both fade-out;