@o2vend/theme-cli 1.0.32

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 (116) hide show
  1. package/README.md +425 -0
  2. package/assets/Logo_o2vend.png +0 -0
  3. package/assets/favicon.png +0 -0
  4. package/assets/logo-white.png +0 -0
  5. package/bin/o2vend +42 -0
  6. package/config/widget-map.json +50 -0
  7. package/lib/commands/check.js +201 -0
  8. package/lib/commands/generate.js +33 -0
  9. package/lib/commands/init.js +214 -0
  10. package/lib/commands/optimize.js +216 -0
  11. package/lib/commands/package.js +208 -0
  12. package/lib/commands/serve.js +105 -0
  13. package/lib/commands/validate.js +191 -0
  14. package/lib/lib/api-client.js +357 -0
  15. package/lib/lib/dev-server.js +2618 -0
  16. package/lib/lib/file-watcher.js +80 -0
  17. package/lib/lib/hot-reload.js +106 -0
  18. package/lib/lib/liquid-engine.js +822 -0
  19. package/lib/lib/liquid-filters.js +671 -0
  20. package/lib/lib/mock-api-server.js +989 -0
  21. package/lib/lib/mock-data.js +1468 -0
  22. package/lib/lib/widget-service.js +321 -0
  23. package/package.json +70 -0
  24. package/test-theme/README.md +27 -0
  25. package/test-theme/assets/async-sections.js +446 -0
  26. package/test-theme/assets/cart-drawer.js +463 -0
  27. package/test-theme/assets/cart-manager.js +223 -0
  28. package/test-theme/assets/checkout-price-handler.js +368 -0
  29. package/test-theme/assets/components.css +4629 -0
  30. package/test-theme/assets/delivery-zone.css +299 -0
  31. package/test-theme/assets/delivery-zone.js +396 -0
  32. package/test-theme/assets/logo.png +0 -0
  33. package/test-theme/assets/sections.css +48 -0
  34. package/test-theme/assets/theme.css +3500 -0
  35. package/test-theme/assets/theme.js +3745 -0
  36. package/test-theme/config/settings_data.json +292 -0
  37. package/test-theme/config/settings_schema.json +1050 -0
  38. package/test-theme/layout/theme.liquid +195 -0
  39. package/test-theme/locales/en.default.json +260 -0
  40. package/test-theme/sections/content-fallback.liquid +53 -0
  41. package/test-theme/sections/content.liquid +57 -0
  42. package/test-theme/sections/footer-fallback.liquid +328 -0
  43. package/test-theme/sections/footer.liquid +278 -0
  44. package/test-theme/sections/header-fallback.liquid +1805 -0
  45. package/test-theme/sections/header.liquid +1145 -0
  46. package/test-theme/sections/hero-fallback.liquid +212 -0
  47. package/test-theme/sections/hero.liquid +136 -0
  48. package/test-theme/snippets/account-sidebar.liquid +200 -0
  49. package/test-theme/snippets/add-to-cart-modal.liquid +484 -0
  50. package/test-theme/snippets/breadcrumbs.liquid +134 -0
  51. package/test-theme/snippets/cart-drawer.liquid +467 -0
  52. package/test-theme/snippets/delivery-zone-city-selector.liquid +79 -0
  53. package/test-theme/snippets/delivery-zone-modal.liquid +337 -0
  54. package/test-theme/snippets/delivery-zone-search.liquid +78 -0
  55. package/test-theme/snippets/icon.liquid +105 -0
  56. package/test-theme/snippets/login-modal.liquid +346 -0
  57. package/test-theme/snippets/mega-menu.liquid +812 -0
  58. package/test-theme/snippets/news-thumbnail.liquid +187 -0
  59. package/test-theme/snippets/pagination.liquid +120 -0
  60. package/test-theme/snippets/price.liquid +92 -0
  61. package/test-theme/snippets/product-card-related.liquid +78 -0
  62. package/test-theme/snippets/product-card-simple.liquid +41 -0
  63. package/test-theme/snippets/product-card.liquid +697 -0
  64. package/test-theme/snippets/rating.liquid +85 -0
  65. package/test-theme/snippets/skeleton-collection-grid.liquid +114 -0
  66. package/test-theme/snippets/skeleton-product-card.liquid +124 -0
  67. package/test-theme/snippets/skeleton-product-grid.liquid +34 -0
  68. package/test-theme/snippets/social-sharing.liquid +185 -0
  69. package/test-theme/templates/account/dashboard.liquid +401 -0
  70. package/test-theme/templates/account/loyalty-redemption.liquid +405 -0
  71. package/test-theme/templates/account/loyalty.liquid +588 -0
  72. package/test-theme/templates/account/order-detail.liquid +230 -0
  73. package/test-theme/templates/account/orders.liquid +349 -0
  74. package/test-theme/templates/account/profile.liquid +758 -0
  75. package/test-theme/templates/account/register.liquid +232 -0
  76. package/test-theme/templates/account/return-orders.liquid +348 -0
  77. package/test-theme/templates/account/store-credit.liquid +464 -0
  78. package/test-theme/templates/account/subscriptions.liquid +601 -0
  79. package/test-theme/templates/account/wishlist.liquid +419 -0
  80. package/test-theme/templates/address-book.liquid +1092 -0
  81. package/test-theme/templates/categories.liquid +452 -0
  82. package/test-theme/templates/checkout.liquid +4511 -0
  83. package/test-theme/templates/error.liquid +384 -0
  84. package/test-theme/templates/index.liquid +11 -0
  85. package/test-theme/templates/login.liquid +185 -0
  86. package/test-theme/templates/order-confirmation.liquid +720 -0
  87. package/test-theme/templates/page.liquid +297 -0
  88. package/test-theme/templates/product-detail.liquid +4363 -0
  89. package/test-theme/templates/products.liquid +518 -0
  90. package/test-theme/templates/search.liquid +922 -0
  91. package/test-theme/theme.json.example +19 -0
  92. package/test-theme/widgets/brand-carousel.liquid +676 -0
  93. package/test-theme/widgets/brand.liquid +245 -0
  94. package/test-theme/widgets/carousel.liquid +843 -0
  95. package/test-theme/widgets/category-list-carousel.liquid +656 -0
  96. package/test-theme/widgets/category-list.liquid +340 -0
  97. package/test-theme/widgets/category.liquid +475 -0
  98. package/test-theme/widgets/discount-time.liquid +176 -0
  99. package/test-theme/widgets/footer-menu.liquid +695 -0
  100. package/test-theme/widgets/footer.liquid +179 -0
  101. package/test-theme/widgets/gallery.liquid +271 -0
  102. package/test-theme/widgets/header-menu.liquid +932 -0
  103. package/test-theme/widgets/header.liquid +159 -0
  104. package/test-theme/widgets/html.liquid +214 -0
  105. package/test-theme/widgets/news.liquid +217 -0
  106. package/test-theme/widgets/product-canvas.liquid +235 -0
  107. package/test-theme/widgets/product-carousel.liquid +502 -0
  108. package/test-theme/widgets/product.liquid +45 -0
  109. package/test-theme/widgets/recently-viewed.liquid +26 -0
  110. package/test-theme/widgets/shared/product-grid.liquid +339 -0
  111. package/test-theme/widgets/simple-product.liquid +42 -0
  112. package/test-theme/widgets/single-product.liquid +610 -0
  113. package/test-theme/widgets/spacebar-carousel.liquid +663 -0
  114. package/test-theme/widgets/spacebar.liquid +279 -0
  115. package/test-theme/widgets/splash.liquid +378 -0
  116. package/test-theme/widgets/testimonial-carousel.liquid +709 -0
@@ -0,0 +1,922 @@
1
+ {% layout 'layout/theme' %}
2
+
3
+ <!-- Search Page -->
4
+ {% hook 'search_before' %}
5
+ <div class="search-page">
6
+ <div class="search-header">
7
+ <div class="search-header-content">
8
+ <h1 class="page-title display-2">
9
+ {% if search.query %}
10
+ Search Results for "{{ search.query }}"
11
+ {% else %}
12
+ Search Products
13
+ {% endif %}
14
+ </h1>
15
+
16
+ <div class="search-form-container">
17
+ <form class="search-form" action="/search" method="get">
18
+ <div class="search-input-group">
19
+ <div class="search-input-wrapper">
20
+ <svg class="search-input-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
21
+ <circle cx="11" cy="11" r="8"></circle>
22
+ <path d="m21 21-4.35-4.35"></path>
23
+ </svg>
24
+ <input type="text"
25
+ name="q"
26
+ value="{{ search.query }}"
27
+ placeholder="Search for products, collections, or pages..."
28
+ class="search-input"
29
+ autocomplete="off">
30
+ </div>
31
+ <button type="submit" class="search-button">
32
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
33
+ <circle cx="11" cy="11" r="8"></circle>
34
+ <path d="m21 21-4.35-4.35"></path>
35
+ </svg>
36
+ Search
37
+ </button>
38
+ </div>
39
+ </form>
40
+ </div>
41
+ </div>
42
+ </div>
43
+
44
+ {% if search.query %}
45
+ <div class="search-results">
46
+ <div class="search-meta">
47
+ <p class="results-count">
48
+ {% if search.results_count > 0 %}
49
+ Found {{ search.results_count }} result{{ search.results_count | pluralize }} for "{{ search.query }}"
50
+ {% else %}
51
+ No results found for "{{ search.query }}"
52
+ {% endif %}
53
+ </p>
54
+
55
+ {% if search.results_count > 0 %}
56
+ <div class="search-filters">
57
+ <div class="filter-group">
58
+ <label for="search-type" class="filter-label">Search in:</label>
59
+ <div class="filter-select-wrapper">
60
+ <select id="search-type" name="type" class="filter-select">
61
+ <option value="all" {% if search.type == 'all' %}selected{% endif %}>All</option>
62
+ <option value="products" {% if search.type == 'products' %}selected{% endif %}>Products</option>
63
+ <option value="collections" {% if search.type == 'collections' %}selected{% endif %}>Collections</option>
64
+ <option value="pages" {% if search.type == 'pages' %}selected{% endif %}>Pages</option>
65
+ </select>
66
+ <svg class="filter-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
67
+ <polyline points="6,9 12,15 18,9"></polyline>
68
+ </svg>
69
+ </div>
70
+ </div>
71
+
72
+ <div class="filter-group">
73
+ <label for="search-sort" class="filter-label">Sort by:</label>
74
+ <div class="filter-select-wrapper">
75
+ <select id="search-sort" name="sort" class="filter-select">
76
+ <option value="relevance" {% if search.sort == 'relevance' %}selected{% endif %}>Relevance</option>
77
+ <option value="price-asc" {% if search.sort == 'price-asc' %}selected{% endif %}>Price: Low to High</option>
78
+ <option value="price-desc" {% if search.sort == 'price-desc' %}selected{% endif %}>Price: High to Low</option>
79
+ <option value="name-asc" {% if search.sort == 'name-asc' %}selected{% endif %}>Name: A to Z</option>
80
+ <option value="name-desc" {% if search.sort == 'name-desc' %}selected{% endif %}>Name: Z to A</option>
81
+ </select>
82
+ <svg class="filter-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
83
+ <polyline points="6,9 12,15 18,9"></polyline>
84
+ </svg>
85
+ </div>
86
+ </div>
87
+ </div>
88
+ {% endif %}
89
+ </div>
90
+
91
+ {% if search.results_count > 0 %}
92
+ {% hook 'search_results_before' %}
93
+ <div class="search-results-content">
94
+ <!-- Products Results -->
95
+ {% if search.results.products.size > 0 %}
96
+ <section class="search-section">
97
+ <h2 class="section-title">Products</h2>
98
+ <div class="products-grid">
99
+ {% for product in search.results.products %}
100
+ {% include 'snippets/product-card-simple', product: product %}
101
+ {% endfor %}
102
+ </div>
103
+ </section>
104
+ {% endif %}
105
+
106
+ <!-- Collections Results -->
107
+ {% if search.results.collections.size > 0 %}
108
+ <section class="search-section">
109
+ <h2 class="section-title">Collections</h2>
110
+ <div class="collections-grid">
111
+ {% for collection in search.results.collections %}
112
+ <div class="collection-card">
113
+ <a href="/{{ collection.slug }}">
114
+ <div class="collection-image">
115
+ {% if collection.image %}
116
+ <img src="{{ collection.image }}"
117
+ alt="{{ collection.title }}"
118
+ loading="lazy">
119
+ {% else %}
120
+ <div class="collection-image-placeholder">
121
+ {% raw %}<svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
122
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
123
+ <circle cx="8.5" cy="8.5" r="1.5"></circle>
124
+ <polyline points="21,15 16,10 5,21"></polyline>
125
+ </svg>{% endraw %}
126
+ </div>
127
+ {% endif %}
128
+ </div>
129
+ <div class="collection-info">
130
+ <h3>{{ collection.title }}</h3>
131
+ <p>{{ collection.products.size }} products</p>
132
+ </div>
133
+ </a>
134
+ </div>
135
+ {% endfor %}
136
+ </div>
137
+ </section>
138
+ {% endif %}
139
+
140
+ <!-- Pages Results -->
141
+ {% if search.results.pages.size > 0 %}
142
+ <section class="search-section">
143
+ <h2 class="section-title">Pages</h2>
144
+ <div class="pages-list">
145
+ {% for page in search.results.pages %}
146
+ <div class="page-result">
147
+ <a href="/pages/{{ page.slug }}" class="page-link">
148
+ <h3 class="page-title">{{ page.title }}</h3>
149
+ <p class="page-excerpt">{{ page.content | strip_html | truncate: 150 }}</p>
150
+ </a>
151
+ </div>
152
+ {% endfor %}
153
+ </div>
154
+ </section>
155
+ {% endif %}
156
+ </div>
157
+ {% hook 'search_results_after' %}
158
+ {% else %}
159
+ <!-- No Results -->
160
+ {% hook 'search_no_results_before' %}
161
+ <div class="no-results">
162
+ <div class="no-results-content">
163
+ <div class="no-results-icon">
164
+ <svg width="80" height="80" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
165
+ <circle cx="11" cy="11" r="8"></circle>
166
+ <path d="m21 21-4.35-4.35"></path>
167
+ </svg>
168
+ </div>
169
+ <h2 class="no-results-title text-3xl font-semibold">No results found</h2>
170
+ <p class="no-results-description lead">We couldn't find anything matching "{{ search.query }}". Try adjusting your search terms or browse our categories.</p>
171
+
172
+ <div class="search-suggestions">
173
+ <h3 class="suggestions-title">Search suggestions:</h3>
174
+ <ul class="suggestions-list">
175
+ <li>Check your spelling</li>
176
+ <li>Try different keywords</li>
177
+ <li>Use more general terms</li>
178
+ <li>Try fewer keywords</li>
179
+ </ul>
180
+ </div>
181
+
182
+ <div class="no-results-actions">
183
+ <a href="/products" class="btn btn-primary btn-lg">
184
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
185
+ <circle cx="9" cy="21" r="1"></circle>
186
+ <circle cx="20" cy="21" r="1"></circle>
187
+ <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
188
+ </svg>
189
+ Browse Products
190
+ </a>
191
+ <a href="/" class="btn btn-outline btn-lg">
192
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
193
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
194
+ <circle cx="8.5" cy="8.5" r="1.5"></circle>
195
+ <polyline points="21,15 16,10 5,21"></polyline>
196
+ </svg>
197
+ View Collections
198
+ </a>
199
+ </div>
200
+ </div>
201
+ </div>
202
+ {% hook 'search_no_results_after' %}
203
+ {% endif %}
204
+ </div>
205
+ {% else %}
206
+ <!-- Search Landing Page -->
207
+ <div class="search-landing">
208
+ <div class="search-landing-content">
209
+ <h2 class="landing-title text-4xl font-bold">What are you looking for?</h2>
210
+ <p class="landing-description lead">Search our store for products, collections, and helpful information.</p>
211
+
212
+ <div class="search-categories">
213
+ <div class="category-card">
214
+ <a href="/products" class="category-link">
215
+ <div class="category-icon">
216
+ <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
217
+ <circle cx="9" cy="21" r="1"></circle>
218
+ <circle cx="20" cy="21" r="1"></circle>
219
+ <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
220
+ </svg>
221
+ </div>
222
+ <h3 class="category-title">Products</h3>
223
+ <p class="category-description">Browse our product catalog</p>
224
+ </a>
225
+ </div>
226
+
227
+ <div class="category-card">
228
+ <a href="/" class="category-link">
229
+ <div class="category-icon">
230
+ <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
231
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
232
+ <circle cx="8.5" cy="8.5" r="1.5"></circle>
233
+ <polyline points="21,15 16,10 5,21"></polyline>
234
+ </svg>
235
+ </div>
236
+ <h3 class="category-title">Collections</h3>
237
+ <p class="category-description">Shop by category</p>
238
+ </a>
239
+ </div>
240
+
241
+ <div class="category-card">
242
+ <a href="/pages" class="category-link">
243
+ <div class="category-icon">
244
+ <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
245
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
246
+ <polyline points="14,2 14,8 20,8"></polyline>
247
+ <line x1="16" y1="13" x2="8" y2="13"></line>
248
+ <line x1="16" y1="17" x2="8" y2="17"></line>
249
+ <polyline points="10,9 9,9 8,9"></polyline>
250
+ </svg>
251
+ </div>
252
+ <h3 class="category-title">Pages</h3>
253
+ <p class="category-description">Help and information</p>
254
+ </a>
255
+ </div>
256
+ </div>
257
+
258
+ <div class="popular-searches">
259
+ <h3 class="popular-title text-xl font-semibold">Popular Searches</h3>
260
+ <div class="search-tags">
261
+ <a href="/search?q=electronics" class="search-tag">Electronics</a>
262
+ <a href="/search?q=clothing" class="search-tag">Clothing</a>
263
+ <a href="/search?q=home" class="search-tag">Home & Garden</a>
264
+ <a href="/search?q=sports" class="search-tag">Sports</a>
265
+ <a href="/search?q=books" class="search-tag">Books</a>
266
+ </div>
267
+ </div>
268
+ </div>
269
+ </div>
270
+ {% endif %}
271
+ </div>
272
+ {% hook 'search_after' %}
273
+
274
+ <!-- Search Page Styles -->
275
+ <style>
276
+ /* Search Page Layout */
277
+ .search-page {
278
+ padding: var(--space-16) 0;
279
+ min-height: 60vh;
280
+ }
281
+
282
+ /* Search Header */
283
+ .search-header {
284
+ background: linear-gradient(135deg, var(--color-gray-50) 0%, var(--color-white) 100%);
285
+ padding: var(--space-20) 0;
286
+ margin-bottom: var(--space-16);
287
+ position: relative;
288
+ overflow: hidden;
289
+ }
290
+
291
+ .search-header::before {
292
+ content: '';
293
+ position: absolute;
294
+ top: 0;
295
+ left: 0;
296
+ right: 0;
297
+ bottom: 0;
298
+ background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="50" cy="50" r="1" fill="%23000" opacity="0.02"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
299
+ opacity: 0.3;
300
+ }
301
+
302
+ .search-header-content {
303
+ position: relative;
304
+ z-index: 1;
305
+ text-align: center;
306
+ max-width: 800px;
307
+ margin: 0 auto;
308
+ padding: 0 var(--space-6);
309
+ }
310
+
311
+ .page-title {
312
+ margin: 0 0 var(--space-8) 0;
313
+ color: var(--color-gray-900);
314
+ line-height: 1.1;
315
+ letter-spacing: -0.05em;
316
+ }
317
+
318
+ .search-form-container {
319
+ max-width: 600px;
320
+ margin: 0 auto;
321
+ }
322
+
323
+ .search-input-group {
324
+ display: flex;
325
+ background: var(--color-white);
326
+ border-radius: var(--radius-2xl);
327
+ overflow: hidden;
328
+ box-shadow: var(--shadow-lg);
329
+ border: 2px solid transparent;
330
+ transition: all var(--transition-fast);
331
+ }
332
+
333
+ .search-input-group:focus-within {
334
+ border-color: var(--color-accent);
335
+ box-shadow: var(--shadow-primary);
336
+ }
337
+
338
+ .search-input-wrapper {
339
+ position: relative;
340
+ flex: 1;
341
+ display: flex;
342
+ align-items: center;
343
+ }
344
+
345
+ .search-input-icon {
346
+ position: absolute;
347
+ left: var(--space-4);
348
+ color: var(--color-gray-400);
349
+ pointer-events: none;
350
+ z-index: 1;
351
+ }
352
+
353
+ .search-input {
354
+ width: 100%;
355
+ border: none;
356
+ padding: var(--space-4) var(--space-4) var(--space-4) var(--space-12);
357
+ font-size: var(--text-lg);
358
+ outline: none;
359
+ background: transparent;
360
+ color: var(--color-gray-900);
361
+ }
362
+
363
+ .search-input::placeholder {
364
+ color: var(--color-gray-500);
365
+ }
366
+
367
+ .search-button {
368
+ background: var(--color-accent);
369
+ color: var(--color-white);
370
+ border: none;
371
+ padding: var(--space-4) var(--space-6);
372
+ cursor: pointer;
373
+ font-size: var(--text-base);
374
+ font-weight: 600;
375
+ display: flex;
376
+ align-items: center;
377
+ gap: var(--space-2);
378
+ transition: all var(--transition-fast);
379
+ text-transform: uppercase;
380
+ letter-spacing: var(--tracking-wide);
381
+ }
382
+
383
+ .search-button:hover {
384
+ background: var(--color-accent-dark);
385
+ transform: translateY(-1px);
386
+ box-shadow: var(--shadow-lg);
387
+ }
388
+
389
+ /* Search Results */
390
+ .search-results {
391
+ max-width: 1200px;
392
+ margin: 0 auto;
393
+ padding: 0 var(--space-6);
394
+ }
395
+
396
+ .search-meta {
397
+ margin-bottom: var(--space-12);
398
+ padding: var(--space-8);
399
+ background: var(--color-white);
400
+ border-radius: var(--radius-xl);
401
+ box-shadow: var(--shadow-sm);
402
+ border: 1px solid var(--color-gray-200);
403
+ }
404
+
405
+ .results-count {
406
+ font-size: var(--text-lg);
407
+ color: var(--color-gray-700);
408
+ margin-bottom: var(--space-6);
409
+ font-weight: 500;
410
+ }
411
+
412
+ .search-filters {
413
+ display: flex;
414
+ gap: var(--space-8);
415
+ flex-wrap: wrap;
416
+ }
417
+
418
+ .filter-group {
419
+ display: flex;
420
+ flex-direction: column;
421
+ gap: var(--space-2);
422
+ }
423
+
424
+ .filter-label {
425
+ font-size: var(--text-sm);
426
+ font-weight: 600;
427
+ color: var(--color-gray-700);
428
+ text-transform: uppercase;
429
+ letter-spacing: var(--tracking-wide);
430
+ }
431
+
432
+ .filter-select-wrapper {
433
+ position: relative;
434
+ display: flex;
435
+ align-items: center;
436
+ }
437
+
438
+ .filter-select {
439
+ appearance: none;
440
+ background-color: var(--color-white);
441
+ border: 1px solid var(--color-gray-300);
442
+ border-radius: var(--radius-lg);
443
+ padding: var(--space-3) var(--space-4);
444
+ padding-right: var(--space-10);
445
+ font-size: var(--text-sm);
446
+ font-weight: 500;
447
+ color: var(--color-gray-700);
448
+ cursor: pointer;
449
+ transition: all var(--transition-fast);
450
+ min-width: 180px;
451
+ }
452
+
453
+ .filter-select:focus {
454
+ outline: none;
455
+ border-color: var(--color-accent);
456
+ box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.1);
457
+ }
458
+
459
+ .filter-arrow {
460
+ position: absolute;
461
+ right: var(--space-3);
462
+ pointer-events: none;
463
+ color: var(--color-gray-500);
464
+ transition: transform var(--transition-fast);
465
+ }
466
+
467
+ .filter-select:focus + .filter-arrow {
468
+ transform: rotate(180deg);
469
+ }
470
+
471
+ /* Search Results Content */
472
+ .search-results-content {
473
+ display: flex;
474
+ flex-direction: column;
475
+ gap: var(--space-12);
476
+ }
477
+
478
+ .search-section {
479
+ background: var(--color-white);
480
+ border-radius: var(--radius-xl);
481
+ padding: var(--space-8);
482
+ box-shadow: var(--shadow-sm);
483
+ border: 1px solid var(--color-gray-200);
484
+ }
485
+
486
+ .section-title {
487
+ font-size: var(--text-2xl);
488
+ margin-bottom: var(--space-8);
489
+ color: var(--color-gray-900);
490
+ font-weight: 600;
491
+ border-bottom: 2px solid var(--color-gray-100);
492
+ padding-bottom: var(--space-4);
493
+ }
494
+
495
+ /* Pages List */
496
+ .pages-list {
497
+ display: flex;
498
+ flex-direction: column;
499
+ gap: var(--space-6);
500
+ }
501
+
502
+ .page-result {
503
+ border: 1px solid var(--color-gray-200);
504
+ border-radius: var(--radius-lg);
505
+ padding: var(--space-6);
506
+ transition: all var(--transition-fast);
507
+ background: var(--color-white);
508
+ }
509
+
510
+ .page-result:hover {
511
+ border-color: var(--color-accent);
512
+ box-shadow: var(--shadow-md);
513
+ transform: translateY(-2px);
514
+ }
515
+
516
+ .page-link {
517
+ text-decoration: none;
518
+ color: inherit;
519
+ }
520
+
521
+ .page-result .page-title {
522
+ font-size: var(--text-xl);
523
+ margin-bottom: var(--space-3);
524
+ color: var(--color-gray-900);
525
+ font-weight: 600;
526
+ line-height: 1.3;
527
+ }
528
+
529
+ .page-excerpt {
530
+ color: var(--color-gray-600);
531
+ line-height: 1.6;
532
+ margin: 0;
533
+ font-size: var(--text-base);
534
+ }
535
+
536
+ /* No Results */
537
+ .no-results {
538
+ display: flex;
539
+ justify-content: center;
540
+ align-items: center;
541
+ min-height: 400px;
542
+ text-align: center;
543
+ }
544
+
545
+ .no-results-content {
546
+ display: flex;
547
+ flex-direction: column;
548
+ align-items: center;
549
+ gap: var(--space-8);
550
+ max-width: 500px;
551
+ }
552
+
553
+ .no-results-icon {
554
+ color: var(--color-gray-400);
555
+ }
556
+
557
+ .no-results-title {
558
+ margin: 0;
559
+ color: var(--color-gray-900);
560
+ font-weight: 600;
561
+ }
562
+
563
+ .no-results-description {
564
+ margin: 0;
565
+ color: var(--color-gray-600);
566
+ line-height: 1.6;
567
+ }
568
+
569
+ .search-suggestions {
570
+ text-align: left;
571
+ margin-bottom: var(--space-8);
572
+ padding: var(--space-6);
573
+ background: var(--color-gray-50);
574
+ border-radius: var(--radius-lg);
575
+ border: 1px solid var(--color-gray-200);
576
+ }
577
+
578
+ .suggestions-title {
579
+ font-size: var(--text-lg);
580
+ margin-bottom: var(--space-4);
581
+ color: var(--color-gray-900);
582
+ font-weight: 600;
583
+ }
584
+
585
+ .suggestions-list {
586
+ list-style: none;
587
+ padding: 0;
588
+ margin: 0;
589
+ }
590
+
591
+ .suggestions-list li {
592
+ padding: var(--space-2) 0;
593
+ color: var(--color-gray-600);
594
+ position: relative;
595
+ padding-left: var(--space-6);
596
+ }
597
+
598
+ .suggestions-list li::before {
599
+ content: '•';
600
+ position: absolute;
601
+ left: 0;
602
+ color: var(--color-accent);
603
+ font-weight: bold;
604
+ font-size: var(--text-lg);
605
+ }
606
+
607
+ .no-results-actions {
608
+ display: flex;
609
+ gap: var(--space-4);
610
+ justify-content: center;
611
+ flex-wrap: wrap;
612
+ }
613
+
614
+ .no-results-actions .btn {
615
+ display: flex;
616
+ align-items: center;
617
+ gap: var(--space-2);
618
+ padding: var(--space-4) var(--space-6);
619
+ font-weight: 600;
620
+ text-decoration: none;
621
+ transition: all var(--transition-fast);
622
+ }
623
+
624
+ .no-results-actions .btn-primary {
625
+ background-color: var(--color-accent);
626
+ color: var(--color-white);
627
+ border: none;
628
+ box-shadow: var(--shadow-primary);
629
+ }
630
+
631
+ .no-results-actions .btn-primary:hover {
632
+ background-color: var(--color-accent-dark);
633
+ transform: translateY(-2px);
634
+ box-shadow: var(--shadow-xl);
635
+ }
636
+
637
+ .no-results-actions .btn-outline {
638
+ background-color: transparent;
639
+ color: var(--color-gray-700);
640
+ border: 1px solid var(--color-gray-300);
641
+ }
642
+
643
+ .no-results-actions .btn-outline:hover {
644
+ background-color: var(--color-gray-50);
645
+ border-color: var(--color-gray-400);
646
+ }
647
+
648
+ /* Search Landing */
649
+ .search-landing {
650
+ display: flex;
651
+ justify-content: center;
652
+ align-items: center;
653
+ min-height: 500px;
654
+ padding: var(--space-16) 0;
655
+ }
656
+
657
+ .search-landing-content {
658
+ text-align: center;
659
+ max-width: 800px;
660
+ padding: 0 var(--space-6);
661
+ }
662
+
663
+ .landing-title {
664
+ margin: 0 0 var(--space-6) 0;
665
+ color: var(--color-gray-900);
666
+ line-height: 1.1;
667
+ letter-spacing: -0.05em;
668
+ }
669
+
670
+ .landing-description {
671
+ margin: 0 0 var(--space-12) 0;
672
+ color: var(--color-gray-600);
673
+ line-height: 1.6;
674
+ }
675
+
676
+ .search-categories {
677
+ display: grid;
678
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
679
+ gap: var(--space-8);
680
+ margin-bottom: var(--space-12);
681
+ }
682
+
683
+ .category-card {
684
+ background: var(--color-white);
685
+ border-radius: var(--radius-xl);
686
+ padding: var(--space-8);
687
+ box-shadow: var(--shadow-sm);
688
+ border: 1px solid var(--color-gray-200);
689
+ transition: all var(--transition-fast);
690
+ }
691
+
692
+ .category-card:hover {
693
+ transform: translateY(-4px);
694
+ box-shadow: var(--shadow-lg);
695
+ border-color: var(--color-accent);
696
+ }
697
+
698
+ .category-link {
699
+ text-decoration: none;
700
+ color: inherit;
701
+ display: flex;
702
+ flex-direction: column;
703
+ align-items: center;
704
+ gap: var(--space-4);
705
+ }
706
+
707
+ .category-icon {
708
+ color: var(--color-accent);
709
+ display: flex;
710
+ align-items: center;
711
+ justify-content: center;
712
+ width: 80px;
713
+ height: 80px;
714
+ background: var(--color-gray-50);
715
+ border-radius: var(--radius-xl);
716
+ transition: all var(--transition-fast);
717
+ }
718
+
719
+ .category-card:hover .category-icon {
720
+ background: var(--color-accent);
721
+ color: var(--color-white);
722
+ transform: scale(1.1);
723
+ }
724
+
725
+ .category-title {
726
+ font-size: var(--text-xl);
727
+ margin: 0;
728
+ color: var(--color-gray-900);
729
+ font-weight: 600;
730
+ }
731
+
732
+ .category-description {
733
+ color: var(--color-gray-600);
734
+ margin: 0;
735
+ text-align: center;
736
+ line-height: 1.5;
737
+ }
738
+
739
+ .popular-searches {
740
+ margin-top: var(--space-12);
741
+ }
742
+
743
+ .popular-title {
744
+ margin: 0 0 var(--space-6) 0;
745
+ color: var(--color-gray-900);
746
+ font-weight: 600;
747
+ }
748
+
749
+ .search-tags {
750
+ display: flex;
751
+ flex-wrap: wrap;
752
+ gap: var(--space-3);
753
+ justify-content: center;
754
+ }
755
+
756
+ .search-tag {
757
+ background: var(--color-gray-100);
758
+ color: var(--color-accent);
759
+ padding: var(--space-2) var(--space-4);
760
+ border-radius: var(--radius-full);
761
+ text-decoration: none;
762
+ font-weight: 500;
763
+ font-size: var(--text-sm);
764
+ transition: all var(--transition-fast);
765
+ border: 2px solid transparent;
766
+ text-transform: uppercase;
767
+ letter-spacing: var(--tracking-wide);
768
+ }
769
+
770
+ .search-tag:hover {
771
+ background: var(--color-accent);
772
+ color: var(--color-white);
773
+ border-color: var(--color-accent);
774
+ transform: translateY(-2px);
775
+ box-shadow: var(--shadow-md);
776
+ }
777
+
778
+ /* Responsive Design */
779
+ @media (max-width: 768px) {
780
+ .search-page {
781
+ padding: var(--space-8) 0;
782
+ }
783
+
784
+ .search-header {
785
+ padding: var(--space-12) 0;
786
+ }
787
+
788
+ .page-title {
789
+ font-size: var(--text-5xl);
790
+ }
791
+
792
+ .search-filters {
793
+ flex-direction: column;
794
+ gap: var(--space-4);
795
+ }
796
+
797
+ .filter-group {
798
+ flex-direction: row;
799
+ align-items: center;
800
+ gap: var(--space-4);
801
+ }
802
+
803
+ .filter-select {
804
+ width: 100%;
805
+ }
806
+
807
+ .search-categories {
808
+ grid-template-columns: 1fr;
809
+ gap: var(--space-6);
810
+ }
811
+
812
+ .no-results-actions {
813
+ flex-direction: column;
814
+ align-items: stretch;
815
+ }
816
+
817
+ .no-results-actions .btn {
818
+ width: 100%;
819
+ }
820
+
821
+ .search-tags {
822
+ justify-content: flex-start;
823
+ }
824
+
825
+ .landing-title {
826
+ font-size: var(--text-3xl);
827
+ }
828
+ }
829
+
830
+ @media (max-width: 480px) {
831
+ .search-header {
832
+ padding: var(--space-8) 0;
833
+ }
834
+
835
+ .search-input-group {
836
+ flex-direction: column;
837
+ border-radius: var(--radius-lg);
838
+ }
839
+
840
+ .search-button {
841
+ border-radius: 0 0 var(--radius-lg) var(--radius-lg);
842
+ }
843
+
844
+ .search-results-content {
845
+ gap: var(--space-8);
846
+ }
847
+
848
+ .search-section {
849
+ padding: var(--space-6);
850
+ }
851
+ }
852
+ </style>
853
+
854
+ <script>
855
+ document.addEventListener('DOMContentLoaded', function() {
856
+ // Search form enhancement
857
+ const searchForm = document.querySelector('.search-form');
858
+ const searchInput = document.querySelector('.search-input');
859
+
860
+ if (searchForm && searchInput) {
861
+ // Auto-focus search input
862
+ searchInput.focus();
863
+
864
+ // Handle search form submission
865
+ searchForm.addEventListener('submit', function(e) {
866
+ const query = searchInput.value.trim();
867
+ if (!query) {
868
+ e.preventDefault();
869
+ searchInput.focus();
870
+ return;
871
+ }
872
+ });
873
+ }
874
+
875
+ // Filter change handlers
876
+ const searchType = document.getElementById('search-type');
877
+ const searchSort = document.getElementById('search-sort');
878
+
879
+ if (searchType) {
880
+ searchType.addEventListener('change', function() {
881
+ updateSearchURL();
882
+ });
883
+ }
884
+
885
+ if (searchSort) {
886
+ searchSort.addEventListener('change', function() {
887
+ updateSearchURL();
888
+ });
889
+ }
890
+
891
+ function updateSearchURL() {
892
+ const url = new URL(window.location);
893
+ const params = new URLSearchParams(url.search);
894
+
895
+ if (searchType && searchType.value !== 'all') {
896
+ params.set('type', searchType.value);
897
+ } else {
898
+ params.delete('type');
899
+ }
900
+
901
+ if (searchSort && searchSort.value !== 'relevance') {
902
+ params.set('sort', searchSort.value);
903
+ } else {
904
+ params.delete('sort');
905
+ }
906
+
907
+ url.search = params.toString();
908
+ window.location.href = url.toString();
909
+ }
910
+
911
+ // Search suggestions (mock implementation)
912
+ if (searchInput) {
913
+ searchInput.addEventListener('input', function() {
914
+ const query = this.value.trim();
915
+ if (query.length >= 2) {
916
+ // In a real implementation, this would fetch suggestions from the API
917
+ console.log('Search suggestions for:', query);
918
+ }
919
+ });
920
+ }
921
+ });
922
+ </script>