@undrr/undrr-mangrove 1.3.2 → 1.4.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 (156) hide show
  1. package/README.md +32 -25
  2. package/components/BarChart.js +2 -2
  3. package/components/BookCard.js +6 -0
  4. package/components/BookCard.js.LICENSE.txt +11 -0
  5. package/components/Breadcrumbs.js +6 -0
  6. package/components/Breadcrumbs.js.LICENSE.txt +9 -0
  7. package/components/Checkbox.js +6 -0
  8. package/components/Checkbox.js.LICENSE.txt +9 -0
  9. package/components/Chips.js +6 -0
  10. package/components/Chips.js.LICENSE.txt +9 -0
  11. package/components/CtaButton.js +6 -0
  12. package/components/CtaButton.js.LICENSE.txt +9 -0
  13. package/components/EmbedContainer.js +6 -0
  14. package/components/EmbedContainer.js.LICENSE.txt +9 -0
  15. package/components/Fetcher.js +2 -2
  16. package/components/Footer.js +6 -0
  17. package/components/Footer.js.LICENSE.txt +9 -0
  18. package/components/FormErrorSummary.js +6 -0
  19. package/components/FormErrorSummary.js.LICENSE.txt +9 -0
  20. package/components/FormGroup.js +6 -0
  21. package/components/FormGroup.js.LICENSE.txt +9 -0
  22. package/components/FullWidth.js +6 -0
  23. package/components/FullWidth.js.LICENSE.txt +9 -0
  24. package/components/Gallery.js +2 -2
  25. package/components/Hero.js +6 -0
  26. package/components/Hero.js.LICENSE.txt +9 -0
  27. package/components/HighlightBox.js +6 -0
  28. package/components/HighlightBox.js.LICENSE.txt +9 -0
  29. package/components/HorizontalBookCard.js +6 -0
  30. package/components/HorizontalBookCard.js.LICENSE.txt +11 -0
  31. package/components/HorizontalCard.js +6 -0
  32. package/components/HorizontalCard.js.LICENSE.txt +11 -0
  33. package/components/IconCard.js +2 -2
  34. package/components/IconCard.js.LICENSE.txt +1 -1
  35. package/components/Loader.js +6 -0
  36. package/components/Loader.js.LICENSE.txt +9 -0
  37. package/components/MapComponent.js +2 -2
  38. package/components/MegaMenu.js +2 -2
  39. package/components/PageHeader.js +6 -0
  40. package/components/PageHeader.js.LICENSE.txt +9 -0
  41. package/components/Pager.js +2 -2
  42. package/components/QuoteHighlight.js +2 -2
  43. package/components/Radio.js +6 -0
  44. package/components/Radio.js.LICENSE.txt +9 -0
  45. package/components/ScrollContainer.js +2 -2
  46. package/components/Select.js +6 -0
  47. package/components/Select.js.LICENSE.txt +9 -0
  48. package/components/ShareButtons.js +2 -2
  49. package/components/ShowMore.js +6 -0
  50. package/components/ShowMore.js.LICENSE.txt +9 -0
  51. package/components/StatsCard.js +2 -2
  52. package/components/SyndicationSearchWidget.js +2 -2
  53. package/components/Tab.js +6 -0
  54. package/components/Tab.js.LICENSE.txt +9 -0
  55. package/components/TextCta.js +6 -0
  56. package/components/TextCta.js.LICENSE.txt +11 -0
  57. package/components/TextInput.js +6 -0
  58. package/components/TextInput.js.LICENSE.txt +9 -0
  59. package/components/Textarea.js +6 -0
  60. package/components/Textarea.js.LICENSE.txt +9 -0
  61. package/components/VerticalCard.js +6 -0
  62. package/components/VerticalCard.js.LICENSE.txt +11 -0
  63. package/components/hydrate.js +5 -0
  64. package/css/style-delta.css +464 -0
  65. package/css/style-delta.css.map +1 -0
  66. package/css/style-gutenberg.css +19 -18
  67. package/css/style-gutenberg.css.map +1 -1
  68. package/css/style-irp-legacy.css +469 -0
  69. package/css/style-irp-legacy.css.map +1 -0
  70. package/css/style-irp.css +96 -103
  71. package/css/style-irp.css.map +1 -1
  72. package/css/style-legacy.css +462 -0
  73. package/css/style-legacy.css.map +1 -0
  74. package/css/style-mcr-legacy.css +469 -0
  75. package/css/style-mcr-legacy.css.map +1 -0
  76. package/css/style-mcr.css +96 -103
  77. package/css/style-mcr.css.map +1 -1
  78. package/css/style-preventionweb-legacy.css +469 -0
  79. package/css/style-preventionweb-legacy.css.map +1 -0
  80. package/css/style-preventionweb.css +96 -103
  81. package/css/style-preventionweb.css.map +1 -1
  82. package/css/style.css +96 -103
  83. package/css/style.css.map +1 -1
  84. package/error-pages/401.html +10 -11
  85. package/error-pages/403.html +11 -12
  86. package/error-pages/404.html +13 -14
  87. package/error-pages/429.html +12 -13
  88. package/error-pages/500.html +10 -11
  89. package/error-pages/502.html +12 -13
  90. package/error-pages/503.html +12 -13
  91. package/error-pages/504.html +10 -11
  92. package/error-pages/5xx.html +10 -11
  93. package/error-pages/challenge.html +12 -13
  94. package/error-pages/managed-challenge.html +12 -13
  95. package/js/tabs.js +427 -88
  96. package/package.json +1 -1
  97. package/scss/Atom/BaseTypography/Blockquote/blockquote.scss +1 -8
  98. package/scss/Atom/BaseTypography/Cite/cite.scss +2 -2
  99. package/scss/Atom/Images/AuthorImage/author-image.scss +4 -4
  100. package/scss/Atom/Images/ImageCaptionCredit/image-caption-credit.scss +24 -28
  101. package/scss/Atom/Images/ImageCredit/image-credit.scss +1 -1
  102. package/scss/Atom/Layout/Container/container.scss +2 -2
  103. package/scss/Atom/Layout/Grid/grid.scss +1 -1
  104. package/scss/Atom/ReachElement/Details/details.scss +6 -6
  105. package/scss/Atom/ReachElement/Figcaption/figcaption.scss +1 -1
  106. package/scss/Atom/Table/table.scss +0 -8
  107. package/scss/Components/Boilerplate/boilerplate.scss +2 -2
  108. package/scss/Components/Breadcrumbs/breadcrumbs.scss +2 -9
  109. package/scss/Components/Buttons/Chips/chips.scss +5 -19
  110. package/scss/Components/Buttons/CtaButton/buttons.scss +3 -124
  111. package/scss/Components/Buttons/CtaButton/cta-button.scss +124 -0
  112. package/scss/Components/Buttons/ShareButtons/share-buttons.scss +2 -2
  113. package/scss/Components/Cards/Card/card.scss +41 -2
  114. package/scss/Components/ErrorPages/error-pages.scss +12 -12
  115. package/scss/Components/Footer/footer.scss +72 -4
  116. package/scss/Components/Forms/Select/select.scss +2 -2
  117. package/scss/Components/Forms/_form-base.scss +5 -5
  118. package/scss/Components/Forms/_form-legacy.scss +1 -1
  119. package/scss/Components/Gallery/gallery.scss +4 -4
  120. package/scss/Components/Hero/hero.scss +18 -17
  121. package/scss/Components/HighlightBox/highlight-box.scss +5 -5
  122. package/scss/Components/MegaMenu/mega-menu.scss +750 -0
  123. package/scss/Components/MegaMenu/megamenu.scss +3 -659
  124. package/scss/Components/PageHeader/page-header.scss +4 -4
  125. package/scss/Components/Pagination/pagination.scss +2 -2
  126. package/scss/Components/SyndicationSearchWidget/SyndicationSearchWidget.scss +3 -1480
  127. package/scss/Components/SyndicationSearchWidget/syndication-search-widget.scss +1515 -0
  128. package/scss/Components/Tab/tab.scss +66 -7
  129. package/scss/Components/TextCta/text-cta.scss +129 -0
  130. package/scss/Components/TextCta/textcta.scss +3 -27
  131. package/scss/Molecules/ImageCaption/image-caption.scss +6 -16
  132. package/scss/Molecules/SectionHeader/section-header.scss +8 -0
  133. package/scss/Molecules/SectionHeader/sectionheader.scss +3 -8
  134. package/scss/Utilities/FullWidth/FullWidth.scss +3 -23
  135. package/scss/Utilities/FullWidth/full-width.scss +23 -0
  136. package/scss/Utilities/Loader/loader.scss +1 -1
  137. package/scss/Utilities/ShowMore/ShowMore.scss +3 -26
  138. package/scss/Utilities/ShowMore/show-more.scss +26 -0
  139. package/scss/assets/scss/_components.scss +14 -9
  140. package/scss/assets/scss/_foundational.scss +13 -7
  141. package/scss/assets/scss/_mixins.scss +9 -314
  142. package/scss/assets/scss/_utility.scss +19 -71
  143. package/scss/assets/scss/_variables-delta.scss +105 -0
  144. package/scss/assets/scss/_variables-irp.scss +1 -1
  145. package/scss/assets/scss/_variables-mcr.scss +1 -1
  146. package/scss/assets/scss/_variables-preventionweb.scss +1 -1
  147. package/scss/assets/scss/_variables.scss +68 -34
  148. package/scss/assets/scss/style-delta.scss +8 -0
  149. package/scss/assets/scss/style-gutenberg.scss +2 -2
  150. package/scss/assets/scss/style-irp-legacy.scss +20 -0
  151. package/scss/assets/scss/style-legacy.scss +20 -0
  152. package/scss/assets/scss/style-mcr-legacy.scss +20 -0
  153. package/scss/assets/scss/style-preventionweb-legacy.scss +20 -0
  154. package/scss/Components/BlockquoteComponent/blockquotecomp.scss +0 -31
  155. package/scss/Components/Buttons/CtaLink/cta-link.scss +0 -61
  156. /package/scss/Components/TableOfContents/{TableOfContents.scss → table-of-contents.scss} +0 -0
@@ -0,0 +1,1515 @@
1
+ /**
2
+ * @file SearchWidget.scss
3
+ * @description Styles for the UNDRR Search Widget React component.
4
+ *
5
+ * Uses BEM naming convention with mg- prefix for Mangrove components.
6
+ * Designed to work with the UNDRR theme system.
7
+ *
8
+ * @see stories/assets/scss/_variables.scss for Mangrove design tokens
9
+ */
10
+
11
+ // @import "../../assets/scss/variables";
12
+
13
+ // Component-specific variables (using Mangrove tokens)
14
+ // Colors
15
+ $search-primary: $mg-color-interactive;
16
+ $search-primary-dark: $mg-color-interactive-active;
17
+ $search-chip-bg: $mg-color-blue-50;
18
+ $search-chip-hover: $mg-color-blue-100;
19
+ $search-text: $mg-color-text;
20
+ $search-text-muted: $mg-color-neutral-500;
21
+ $search-border: $mg-color-neutral-100;
22
+ $search-border-light: $mg-color-neutral-50;
23
+ $search-skeleton-bg: $mg-color-neutral-25;
24
+ $search-error-bg: $mg-color-red-50;
25
+ $search-error-border: $mg-color-red-400;
26
+ $search-debug-bg: $mg-color-yellow-light;
27
+ $search-debug-text: $mg-color-yellow-dark;
28
+
29
+ // Spacing & sizing (component needs rounded corners, base theme has 0)
30
+ $search-radius: $mg-spacing-25;
31
+ $search-input-padding-x: $mg-spacing-250;
32
+
33
+ // Screen reader only utility
34
+ .mg-u-sr-only {
35
+ position: absolute;
36
+ width: 1px;
37
+ height: 1px;
38
+ padding: 0;
39
+ margin: -1px;
40
+ overflow: hidden;
41
+ clip-path: inset(50%);
42
+ white-space: nowrap;
43
+ border: 0;
44
+ }
45
+
46
+ // Main widget container
47
+ .mg-search-widget {
48
+ font-family: inherit;
49
+ line-height: 1.5;
50
+ position: relative;
51
+ }
52
+
53
+ // ========================================
54
+ // Loading Progress Bar
55
+ // ========================================
56
+
57
+ .mg-search__progress {
58
+ position: absolute;
59
+ top: 0;
60
+ left: 0;
61
+ right: 0;
62
+ height: 3px;
63
+ background: $search-border-light;
64
+ overflow: hidden;
65
+ z-index: 10;
66
+ }
67
+
68
+ .mg-search__progress-bar {
69
+ height: 100%;
70
+ width: 30%;
71
+ background: linear-gradient(90deg, $search-primary, $search-primary-dark);
72
+ animation: mg-search-progress 1.2s ease-in-out infinite;
73
+ }
74
+
75
+ @keyframes mg-search-progress {
76
+ 0% {
77
+ transform: translateX(-100%);
78
+ }
79
+ 50% {
80
+ transform: translateX(200%);
81
+ }
82
+ 100% {
83
+ transform: translateX(400%);
84
+ }
85
+ }
86
+
87
+ // Search form
88
+ .mg-search__form {
89
+ display: flex;
90
+ gap: $mg-spacing-50;
91
+ margin-bottom: $mg-spacing-100;
92
+ }
93
+
94
+ .mg-search__input-wrapper {
95
+ position: relative;
96
+ flex: 1;
97
+ }
98
+
99
+ .mg-search__input {
100
+ width: 100%;
101
+ padding: $mg-spacing-75 $search-input-padding-x $mg-spacing-75 $mg-spacing-100;
102
+ border: 1px solid $search-border;
103
+ border-radius: $search-radius;
104
+ transition: border-color 0.2s, box-shadow 0.2s;
105
+
106
+ &:focus {
107
+ outline: none;
108
+ border-color: $search-primary;
109
+ box-shadow: 0 0 0 3px rgba($search-primary, 0.15);
110
+ }
111
+
112
+ &::placeholder {
113
+ color: $search-text-muted;
114
+ }
115
+ }
116
+
117
+ .mg-search__clear {
118
+ position: absolute;
119
+ right: $search-input-padding-x;
120
+ top: 50%;
121
+ transform: translateY(-50%);
122
+ padding: $mg-spacing-25 $mg-spacing-50;
123
+ background: none;
124
+ border: none;
125
+ font-size: $mg-font-size-200;
126
+ color: $search-text-muted;
127
+ cursor: pointer;
128
+ line-height: 1;
129
+
130
+ &:hover {
131
+ color: $search-text;
132
+ }
133
+ }
134
+
135
+ .mg-search__loading {
136
+ position: absolute;
137
+ right: $mg-spacing-75;
138
+ top: 50%;
139
+ transform: translateY(-50%);
140
+ width: $mg-spacing-100;
141
+ height: $mg-spacing-100;
142
+ border: 2px solid $search-border-light;
143
+ border-top-color: $search-primary;
144
+ border-radius: 50%;
145
+ animation: mg-search-spin 0.8s linear infinite;
146
+ }
147
+
148
+ @keyframes mg-search-spin {
149
+ to {
150
+ transform: translateY(-50%) rotate(360deg);
151
+ }
152
+ }
153
+
154
+ .mg-search__submit {
155
+ display: flex;
156
+ align-items: center;
157
+ gap: $mg-spacing-50;
158
+ padding: $mg-spacing-75 $mg-spacing-150;
159
+ font-size: $mg-font-size-100;
160
+ font-weight: 500;
161
+ color: #fff;
162
+ background-color: $search-primary;
163
+ border: none;
164
+ border-radius: $search-radius;
165
+ cursor: pointer;
166
+ transition: background-color 0.2s;
167
+
168
+ &:hover {
169
+ background-color: $search-primary-dark;
170
+ }
171
+
172
+ &:focus {
173
+ outline: none;
174
+ box-shadow: 0 0 0 3px rgba($search-primary, 0.3);
175
+ }
176
+ }
177
+
178
+ .mg-search__submit-icon {
179
+ display: flex;
180
+ align-items: center;
181
+ }
182
+
183
+ // Submit button loading state
184
+ .mg-search__submit--loading {
185
+ opacity: 0.85;
186
+ cursor: wait;
187
+ }
188
+
189
+ .mg-search__submit-spinner {
190
+ display: inline-block;
191
+ width: 16px;
192
+ height: 16px;
193
+ border: 2px solid rgb(255 255 255 / 0.3);
194
+ border-top-color: #fff;
195
+ border-radius: 50%;
196
+ animation: mg-search-spin 0.7s linear infinite;
197
+ }
198
+
199
+ // Active filters
200
+ .mg-search__active-filters {
201
+ display: flex;
202
+ flex-wrap: wrap;
203
+ align-items: center;
204
+ gap: $mg-spacing-50;
205
+ margin-bottom: $mg-spacing-100;
206
+ padding: $mg-spacing-75;
207
+ background: $search-chip-bg;
208
+ border-radius: $search-radius;
209
+ }
210
+
211
+ .mg-search__active-filters-label {
212
+ font-weight: 500;
213
+ color: $search-text;
214
+ margin-right: $mg-spacing-25;
215
+ }
216
+
217
+ .mg-search__active-filters-list {
218
+ display: flex;
219
+ flex-wrap: wrap;
220
+ gap: $mg-spacing-50;
221
+ list-style: none;
222
+ margin: 0;
223
+ padding: 0;
224
+ }
225
+
226
+ .mg-search__filter-chip {
227
+ display: inline-flex;
228
+ align-items: center;
229
+ gap: $mg-spacing-50;
230
+ padding: $mg-spacing-25 $mg-spacing-50;
231
+ color: $search-text;
232
+ background: #fff;
233
+ border: 1px solid $search-border;
234
+ border-radius: $search-radius;
235
+ cursor: pointer;
236
+ transition: background-color 0.2s, border-color 0.2s;
237
+
238
+ &:hover {
239
+ background: $search-chip-hover;
240
+ border-color: $search-primary;
241
+ }
242
+
243
+ &:focus {
244
+ outline: none;
245
+ box-shadow: 0 0 0 2px $search-primary;
246
+ }
247
+ }
248
+
249
+ .mg-search__filter-chip-remove {
250
+ font-weight: 900;
251
+ }
252
+
253
+ .mg-search__clear-all {
254
+ padding: $mg-spacing-25 $mg-spacing-75;
255
+ color: $search-primary;
256
+ background: none;
257
+ border: 1px solid $search-primary;
258
+ border-radius: $search-radius;
259
+ cursor: pointer;
260
+ transition: background-color 0.2s, color 0.2s;
261
+
262
+ &:hover {
263
+ color: #fff;
264
+ background: $search-primary;
265
+ }
266
+ }
267
+
268
+ // Content layout
269
+ .mg-search__content {
270
+ display: flex;
271
+ gap: $mg-spacing-200;
272
+ }
273
+
274
+ .mg-search__main {
275
+ flex: 1;
276
+ min-width: 0;
277
+ }
278
+
279
+ .mg-search__sidebar {
280
+ width: 280px;
281
+ flex-shrink: 0;
282
+
283
+ @media (width <= 768px) {
284
+ display: none; // TODO: Mobile drawer in Phase 2
285
+ }
286
+ }
287
+
288
+ // Results
289
+ .mg-search__results {
290
+ transition: opacity 0.2s ease-out;
291
+ }
292
+
293
+ .mg-search__results-header {
294
+ display: flex;
295
+ flex-wrap: wrap;
296
+ align-items: center;
297
+ justify-content: space-between;
298
+ gap: $mg-spacing-50;
299
+ margin-bottom: $mg-spacing-100;
300
+ }
301
+
302
+ .mg-search__results-count {
303
+ color: $search-text-muted;
304
+ margin: 0;
305
+
306
+ strong {
307
+ color: $search-text;
308
+ }
309
+ }
310
+
311
+ .mg-search__results-time {
312
+ color: $search-text-muted;
313
+ }
314
+
315
+ // Compact filter button (mobile only, in results header)
316
+ .mg-search__filter-btn {
317
+ display: none; // Hidden on desktop by default
318
+ align-items: center;
319
+ gap: $mg-spacing-25;
320
+ padding: $mg-spacing-50 $mg-spacing-75;
321
+ font-size: $mg-font-size-200;
322
+ font-weight: 500;
323
+ color: $search-primary;
324
+ background: transparent;
325
+ border: 1px solid $search-border;
326
+ border-radius: $search-radius;
327
+ cursor: pointer;
328
+ transition: background-color 0.15s, border-color 0.15s;
329
+ white-space: nowrap;
330
+
331
+ &:hover {
332
+ background: $search-chip-bg;
333
+ border-color: $search-primary;
334
+ }
335
+
336
+ &:focus-visible {
337
+ outline: 2px solid $search-primary;
338
+ outline-offset: 2px;
339
+ }
340
+ }
341
+
342
+ .mg-search__filter-btn-icon {
343
+ flex-shrink: 0;
344
+ }
345
+
346
+ .mg-search__filter-btn-badge {
347
+ display: inline-flex;
348
+ align-items: center;
349
+ justify-content: center;
350
+ min-width: 18px;
351
+ height: 18px;
352
+ padding: 0 $mg-spacing-25;
353
+ font-size: $mg-font-size-200;
354
+ font-weight: 600;
355
+ color: #fff;
356
+ background: $search-primary;
357
+ border-radius: 9px;
358
+ }
359
+
360
+ .mg-search__results-list {
361
+ display: flex;
362
+ flex-direction: column;
363
+ gap: $mg-spacing-150;
364
+ }
365
+
366
+ .mg-search__results-more {
367
+ margin-top: $mg-spacing-150;
368
+ padding: $mg-spacing-100;
369
+ font-size: $mg-font-size-200;
370
+ color: $search-text-muted;
371
+ background: $search-chip-bg;
372
+ border-radius: $search-radius;
373
+ text-align: center;
374
+ }
375
+
376
+ .mg-search__results-empty,
377
+ .mg-search__results-placeholder {
378
+ padding: $mg-spacing-200;
379
+ text-align: center;
380
+ color: $search-text-muted;
381
+
382
+ p {
383
+ margin: 0 0 $mg-spacing-50;
384
+ }
385
+ }
386
+
387
+ .mg-search__results-hint {
388
+ font-size: $mg-font-size-200;
389
+ }
390
+
391
+ .mg-search__results-error {
392
+ padding: $mg-spacing-100;
393
+ background: $search-error-bg;
394
+ border: 1px solid $search-error-border;
395
+ border-radius: $search-radius;
396
+
397
+ p {
398
+ margin: 0 0 $mg-spacing-50;
399
+
400
+ &:last-child {
401
+ margin-bottom: 0;
402
+ }
403
+ }
404
+ }
405
+
406
+ // Result item
407
+ .mg-search__result {
408
+ padding-bottom: $mg-spacing-150;
409
+ border-bottom: 1px solid $search-border-light;
410
+
411
+ &:last-child {
412
+ border-bottom: none;
413
+ padding-bottom: 0;
414
+ }
415
+ }
416
+
417
+ .mg-search__result-content {
418
+ display: flex;
419
+ gap: $mg-spacing-100;
420
+ }
421
+
422
+ .mg-search__result-image {
423
+ flex-shrink: 0;
424
+ width: 120px;
425
+
426
+ img {
427
+ width: 100%;
428
+ height: auto;
429
+ border-radius: $search-radius;
430
+ object-fit: cover;
431
+ }
432
+
433
+ @media (width <= 480px) {
434
+ display: none;
435
+ }
436
+ }
437
+
438
+ .mg-search__result-text {
439
+ flex: 1;
440
+ min-width: 0;
441
+ }
442
+
443
+ .mg-search__result-title {
444
+ margin: 0 0 $mg-spacing-50;
445
+ font-size: $mg-font-size-200;
446
+ font-weight: 600;
447
+ line-height: 1.3;
448
+
449
+ a {
450
+ color: $search-primary;
451
+ text-decoration: none;
452
+
453
+ &:hover {
454
+ text-decoration: underline;
455
+ }
456
+
457
+ em {
458
+ font-style: normal;
459
+ background: rgba($search-primary, 0.1);
460
+ padding: 0 2px;
461
+ }
462
+ }
463
+ }
464
+
465
+ .mg-search__result-meta {
466
+ display: flex;
467
+ flex-wrap: wrap;
468
+ gap: $mg-spacing-50;
469
+ margin-bottom: $mg-spacing-50;
470
+ font-size: $mg-font-size-150;
471
+ color: $search-text-muted;
472
+ }
473
+
474
+ .mg-search__result-type {
475
+ padding: $mg-spacing-25 $mg-spacing-50;
476
+ background: $search-chip-bg;
477
+ border-radius: $search-radius;
478
+ text-transform: uppercase;
479
+ letter-spacing: 0.025em;
480
+ }
481
+
482
+ .mg-search__result-domain,
483
+ .mg-search__result-date {
484
+ &::before {
485
+ content: '•';
486
+ margin-right: $mg-spacing-50;
487
+ color: $search-border;
488
+ }
489
+ }
490
+
491
+ .mg-search__result-snippet {
492
+ margin: 0;
493
+ font-size: $mg-font-size-150;
494
+ color: $search-text;
495
+ line-height: 1.6;
496
+
497
+ em {
498
+ font-style: normal;
499
+ background: rgba($search-primary, 0.1);
500
+ padding: 0 2px;
501
+ }
502
+ }
503
+
504
+ .mg-search__result-metrics {
505
+ display: flex;
506
+ flex-wrap: wrap;
507
+ gap: $mg-spacing-50;
508
+ margin-bottom: $mg-spacing-50;
509
+ }
510
+
511
+ .mg-search__result-metric {
512
+ display: inline-block;
513
+ padding: $mg-spacing-25 $mg-spacing-50;
514
+ font-size: $mg-font-size-200;
515
+ background: $search-debug-bg;
516
+ border-radius: $mg-spacing-25;
517
+ }
518
+
519
+ // Loading skeleton
520
+ .mg-search__skeleton {
521
+ display: flex;
522
+ flex-direction: column;
523
+ gap: $mg-spacing-150;
524
+ }
525
+
526
+ .mg-search__skeleton-item {
527
+ padding-bottom: $mg-spacing-150;
528
+ border-bottom: 1px solid $search-border-light;
529
+ }
530
+
531
+ .mg-search__skeleton-title,
532
+ .mg-search__skeleton-meta,
533
+ .mg-search__skeleton-text {
534
+ background: linear-gradient(90deg, $search-skeleton-bg 25%, #e8e8e8 50%, $search-skeleton-bg 75%);
535
+ background-size: 200% 100%;
536
+ animation: mg-search-shimmer 1.5s infinite;
537
+ border-radius: $search-radius;
538
+ }
539
+
540
+ .mg-search__skeleton-title {
541
+ height: $mg-spacing-150;
542
+ width: 70%;
543
+ margin-bottom: $mg-spacing-75;
544
+ }
545
+
546
+ .mg-search__skeleton-meta {
547
+ height: $mg-spacing-100;
548
+ width: 40%;
549
+ margin-bottom: $mg-spacing-75;
550
+ }
551
+
552
+ .mg-search__skeleton-text {
553
+ height: $mg-spacing-100;
554
+ width: 100%;
555
+ margin-bottom: $mg-spacing-50;
556
+
557
+ &--short {
558
+ width: 60%;
559
+ }
560
+ }
561
+
562
+ // Card skeleton — layout is controlled by mg-grid classes applied in JSX.
563
+ // Reset the flex declarations inherited from .mg-search__skeleton so they
564
+ // don't fight mg-grid's own flex fallback / CSS grid (@supports) path.
565
+ .mg-search__skeleton--card {
566
+ flex-direction: initial;
567
+ }
568
+
569
+ .mg-search__skeleton-card {
570
+ display: flex;
571
+ flex-direction: column;
572
+ border-radius: $search-radius;
573
+ overflow: hidden;
574
+ border: 1px solid $search-border-light;
575
+ }
576
+
577
+ .mg-search__skeleton-card-image {
578
+ aspect-ratio: 16 / 9;
579
+ background: linear-gradient(90deg, $search-skeleton-bg 25%, #e8e8e8 50%, $search-skeleton-bg 75%);
580
+ background-size: 200% 100%;
581
+ animation: mg-search-shimmer 1.5s infinite;
582
+ }
583
+
584
+ .mg-search__skeleton-card-body {
585
+ padding: $mg-spacing-100;
586
+
587
+ .mg-search__skeleton-title {
588
+ width: 85%;
589
+ }
590
+
591
+ .mg-search__skeleton-meta {
592
+ width: 50%;
593
+ margin-bottom: 0;
594
+ }
595
+ }
596
+
597
+ @keyframes mg-search-shimmer {
598
+ 0% {
599
+ background-position: 200% 0;
600
+ }
601
+ 100% {
602
+ background-position: -200% 0;
603
+ }
604
+ }
605
+
606
+ // Facets placeholder
607
+ .mg-search__facets-placeholder {
608
+ padding: $mg-spacing-100;
609
+ background: $search-chip-bg;
610
+ border-radius: $search-radius;
611
+ }
612
+
613
+ .mg-search__facets-notice {
614
+ margin: 0;
615
+ font-size: $mg-font-size-200;
616
+ color: $search-text-muted;
617
+ text-align: center;
618
+ }
619
+
620
+ // ========================================
621
+ // Facets Sidebar
622
+ // ========================================
623
+
624
+ .mg-search__facets {
625
+ display: flex;
626
+ flex-direction: column;
627
+ gap: $mg-spacing-150;
628
+ }
629
+
630
+ .mg-search__facets-loading {
631
+ padding: $mg-spacing-100;
632
+ font-size: $mg-font-size-200;
633
+ color: $search-text-muted;
634
+ text-align: center;
635
+ }
636
+
637
+ .mg-search__facet-containers {
638
+ display: flex;
639
+ flex-direction: column;
640
+ gap: $mg-spacing-100;
641
+ }
642
+
643
+ // Sort Options
644
+ .mg-search__sort {
645
+ padding: 0;
646
+ margin: 0;
647
+ border: none;
648
+
649
+ legend {
650
+ font-weight: 600;
651
+ font-size: $mg-font-size-200;
652
+ margin-bottom: $mg-spacing-50;
653
+ color: $search-text;
654
+ }
655
+ }
656
+
657
+ .mg-search__sort-option {
658
+ display: flex;
659
+ align-items: center;
660
+ gap: $mg-spacing-50;
661
+ margin-bottom: $mg-spacing-25;
662
+
663
+ input[type="radio"] {
664
+ margin: 0;
665
+ }
666
+
667
+ label {
668
+ font-size: $mg-font-size-200;
669
+ color: $search-text;
670
+ cursor: pointer;
671
+ }
672
+ }
673
+
674
+ // Individual Facet
675
+ .mg-search__facet {
676
+ padding: 0;
677
+ margin: 0;
678
+ border: none;
679
+
680
+ legend {
681
+ font-weight: 600;
682
+ font-size: $mg-font-size-200;
683
+ margin-bottom: $mg-spacing-50;
684
+ color: $search-text;
685
+ }
686
+ }
687
+
688
+ .mg-search__facet-select {
689
+ width: 100%;
690
+ padding: $mg-spacing-50;
691
+ font-size: $mg-font-size-200;
692
+ border: 1px solid $search-border;
693
+ border-radius: $search-radius;
694
+ background-color: #fff;
695
+ cursor: pointer;
696
+
697
+ &:focus {
698
+ outline: none;
699
+ border-color: $search-primary;
700
+ box-shadow: 0 0 0 2px rgba($search-primary, 0.15);
701
+ }
702
+
703
+ &[multiple] {
704
+ min-height: 100px;
705
+
706
+ option {
707
+ padding: $mg-spacing-25 $mg-spacing-50;
708
+
709
+ &:checked {
710
+ background-color: $search-chip-bg;
711
+ }
712
+ }
713
+ }
714
+ }
715
+
716
+ // Custom facet styling
717
+ // .mg-search__facet--custom {
718
+ // background: $search-chip-bg;
719
+ // padding: $mg-spacing-100;
720
+ // border-radius: $search-radius;
721
+ // }
722
+
723
+ // ========================================
724
+ // Result teaser HTML overrides
725
+ // ========================================
726
+
727
+ // Type badge and site name badges injected before the title in teaser results
728
+ .mg-search__result-badges {
729
+ display: inline-flex;
730
+ flex-wrap: wrap;
731
+ align-items: center;
732
+ gap: $mg-spacing-50;
733
+ margin-bottom: $mg-spacing-25;
734
+ }
735
+
736
+ // Content type badge — uses the system-level .mg-tag atom.
737
+ // No additional styles needed; the class is applied in ResultItem.jsx.
738
+
739
+ // Site name label in search results
740
+ .mg-search__result-site-name {
741
+ display: inline-block;
742
+ margin: 0;
743
+ padding: $mg-spacing-25 $mg-spacing-50;
744
+ font-size: $mg-font-size-200;
745
+ color: $search-text-muted;
746
+ background: $search-chip-bg;
747
+ border-radius: $search-radius;
748
+ }
749
+
750
+
751
+ // Error result styling
752
+ .mg-search__result--error {
753
+ padding: $mg-spacing-100;
754
+ background: $search-error-bg;
755
+ border: 1px solid $search-error-border;
756
+ border-radius: $search-radius;
757
+ }
758
+
759
+ .mg-search__result-error {
760
+ margin: 0;
761
+ color: #d32f2f;
762
+
763
+ a {
764
+ color: inherit;
765
+ text-decoration: underline;
766
+ }
767
+ }
768
+
769
+ // ========================================
770
+ // Teaser Field Visibility
771
+ // ========================================
772
+ // Modifier classes on the results container hide specific teaser fields
773
+ // via the visibleTeaserFields config option.
774
+ // Title (.mg-card__title) is intentionally not toggleable.
775
+ // Teaser HTML uses standard mg-card__* BEM wrapper classes added by
776
+ // Drupal teaser templates (see web-backlog#2660).
777
+
778
+ .mg-search--hide-image .mg-card__visual { display: none; }
779
+ .mg-search--hide-contentType .mg-card__tag { display: none; }
780
+ .mg-search--hide-publicationType .mg-card__publication-type { display: none; }
781
+ .mg-search--hide-date .mg-card__date { display: none; }
782
+ .mg-search--hide-siteName .mg-search__result-site-name { display: none; }
783
+ .mg-search--hide-summary .mg-card__description { display: none; }
784
+ .mg-search--hide-organization .mg-card__organization { display: none; }
785
+
786
+ // ========================================
787
+ // Card Display Mode (mg-grid layout)
788
+ // ========================================
789
+
790
+ .mg-search__results-grid {
791
+ gap: $mg-spacing-150;
792
+
793
+ // Card items within grid
794
+ > [role="listitem"] {
795
+ display: flex;
796
+ }
797
+
798
+ // Remove list-style dividers in grid/card mode
799
+ .mg-search__result {
800
+ padding-bottom: 0;
801
+ border-bottom: 0;
802
+ }
803
+ }
804
+
805
+ // ========================================
806
+ // Result Animations
807
+ // Sequential fade-in and slide from left for search results.
808
+ // Animation classes applied via JS (which checks prefers-reduced-motion).
809
+ // ========================================
810
+
811
+ // Initial hidden state - applied before animation
812
+ .mg-search__result--pending {
813
+ opacity: 0;
814
+ transform: translateX(-20px);
815
+ }
816
+
817
+ // Animated state - triggers the transition
818
+ .mg-search__result--visible {
819
+ opacity: 1;
820
+ transform: translateX(0);
821
+ transition: opacity 0.3s ease-out, transform 0.3s ease-out;
822
+ }
823
+
824
+ // Stale state - dim results while loading new data
825
+ .mg-search__results--stale {
826
+ opacity: 0.5;
827
+ pointer-events: none;
828
+ }
829
+
830
+ // Stale main area with more visible feedback
831
+ .mg-search__main--stale {
832
+ position: relative;
833
+
834
+ &::after {
835
+ content: '';
836
+ position: absolute;
837
+ inset: 0;
838
+ background: rgb(255 255 255 / 0.4);
839
+ pointer-events: none;
840
+ animation: mg-search-pulse 1.5s ease-in-out infinite;
841
+ }
842
+ }
843
+
844
+ @keyframes mg-search-pulse {
845
+ 0%, 100% {
846
+ opacity: 0.3;
847
+ }
848
+ 50% {
849
+ opacity: 0.6;
850
+ }
851
+ }
852
+
853
+ // ========================================
854
+ // Collapsible Filter Sections
855
+ // ========================================
856
+
857
+ // Hide overflow items by default (when fieldset doesn't have .facet-expanded)
858
+ .mg-search__facet .mg-search__facet-overflow-item {
859
+ display: none;
860
+ }
861
+
862
+ // Show overflow items when expanded
863
+ .mg-search__facet--expanded .mg-search__facet-overflow-item {
864
+ display: block;
865
+ }
866
+
867
+ // Toggle button for collapsible sections
868
+ .mg-search__facet-toggle {
869
+ display: inline-flex;
870
+ align-items: center;
871
+ gap: $mg-spacing-25;
872
+ background: none;
873
+ border: none;
874
+ padding: $mg-spacing-50 0;
875
+ margin-top: $mg-spacing-50;
876
+ font-size: $mg-font-size-200;
877
+ color: $search-primary;
878
+ cursor: pointer;
879
+ font-weight: 500;
880
+
881
+ &:hover {
882
+ text-decoration: underline;
883
+ }
884
+
885
+ &:focus-visible {
886
+ outline: 2px solid $search-primary;
887
+ outline-offset: 2px;
888
+ }
889
+ }
890
+
891
+ // Toggle icon (arrow)
892
+ .mg-search__facet-toggle-icon {
893
+ display: inline-block;
894
+ width: 0;
895
+ height: 0;
896
+ border-left: 5px solid transparent;
897
+ border-right: 5px solid transparent;
898
+ border-top: 6px solid currentColor;
899
+ transition: transform 0.2s ease;
900
+
901
+ .mg-search__facet-toggle[aria-expanded="false"] & {
902
+ transform: rotate(-90deg);
903
+ }
904
+
905
+ .mg-search__facet-toggle[aria-expanded="true"] & {
906
+ transform: rotate(0deg);
907
+ }
908
+ }
909
+
910
+ // ========================================
911
+ // Loading Spinner (full-page initial load)
912
+ // ========================================
913
+
914
+ .mg-search__loader {
915
+ display: flex;
916
+ align-items: center;
917
+ justify-content: center;
918
+ padding: $mg-spacing-200;
919
+ }
920
+
921
+ .mg-search__spinner {
922
+ border: 4px solid $search-border-light;
923
+ border-top: 4px solid $search-primary;
924
+ border-radius: 50%;
925
+ width: 40px;
926
+ height: 40px;
927
+ animation: mg-search-spin 1s linear infinite;
928
+ }
929
+
930
+ .mg-search__loader-text {
931
+ text-align: center;
932
+ color: $search-text-muted;
933
+ margin-top: $mg-spacing-100;
934
+ }
935
+
936
+ // ========================================
937
+ // Custom Select Dropdown (replaces Chosen.js)
938
+ // ========================================
939
+ // Lightweight, self-contained dropdown that works in any environment.
940
+ // No external dependencies required.
941
+
942
+ .mg-select {
943
+ position: relative;
944
+ width: 100%;
945
+ margin-top: $mg-spacing-50;
946
+ }
947
+
948
+ .mg-select__trigger {
949
+ display: flex;
950
+ align-items: center;
951
+ justify-content: space-between;
952
+ width: 100%;
953
+ min-height: 44px; // Touch-friendly
954
+ padding: $mg-spacing-50 $mg-spacing-75;
955
+ font-size: $mg-font-size-200;
956
+ color: $search-text;
957
+ text-align: left;
958
+ background: #fff;
959
+ border: 1px solid $search-border;
960
+ border-radius: $search-radius;
961
+ cursor: pointer;
962
+ transition: border-color 0.15s, box-shadow 0.15s;
963
+
964
+ &:hover {
965
+ border-color: $search-primary;
966
+ }
967
+
968
+ &:focus {
969
+ outline: none;
970
+ border-color: $search-primary;
971
+ box-shadow: 0 0 0 2px rgba($search-primary, 0.15);
972
+ }
973
+
974
+ .mg-select--open & {
975
+ border-color: $search-primary;
976
+ border-bottom-left-radius: 0;
977
+ border-bottom-right-radius: 0;
978
+ }
979
+ }
980
+
981
+ .mg-select__trigger-text {
982
+ flex: 1;
983
+ overflow: hidden;
984
+ text-overflow: ellipsis;
985
+ white-space: nowrap;
986
+ }
987
+
988
+ .mg-select__trigger-icon {
989
+ flex-shrink: 0;
990
+ margin-left: $mg-spacing-50;
991
+ color: $search-text-muted;
992
+ transition: transform 0.2s ease;
993
+
994
+ .mg-select--open & {
995
+ transform: rotate(180deg);
996
+ }
997
+ }
998
+
999
+ .mg-select__backdrop {
1000
+ position: fixed;
1001
+ inset: 0;
1002
+ z-index: 9998; // High z-index since it's portaled to body
1003
+ background: transparent;
1004
+ cursor: default;
1005
+ }
1006
+
1007
+ .mg-select__dropdown {
1008
+ position: absolute;
1009
+ top: 100%;
1010
+ left: 0;
1011
+ right: 0;
1012
+ z-index: 9999; // Above backdrop
1013
+ background: #fff;
1014
+ border: 1px solid $search-primary;
1015
+ border-top: none;
1016
+ border-radius: 0 0 $search-radius $search-radius;
1017
+ box-shadow: 0 4px 12px rgb(0 0 0 / 0.1);
1018
+ animation: mg-select-fade-in 0.15s ease-out;
1019
+ }
1020
+
1021
+ @keyframes mg-select-fade-in {
1022
+ from {
1023
+ opacity: 0;
1024
+ transform: translateY(-4px);
1025
+ }
1026
+ to {
1027
+ opacity: 1;
1028
+ transform: translateY(0);
1029
+ }
1030
+ }
1031
+
1032
+ .mg-select__search {
1033
+ padding: $mg-spacing-50;
1034
+ border-bottom: 1px solid $search-border-light;
1035
+ }
1036
+
1037
+ .mg-select__search-input {
1038
+ width: 100%;
1039
+ padding: $mg-spacing-50;
1040
+ font-size: $mg-font-size-200;
1041
+ border: 1px solid $search-border;
1042
+ border-radius: $search-radius;
1043
+
1044
+ &:focus {
1045
+ outline: none;
1046
+ border-color: $search-primary;
1047
+ }
1048
+
1049
+ &::placeholder {
1050
+ color: $search-text-muted;
1051
+ }
1052
+ }
1053
+
1054
+ .mg-select__list {
1055
+ list-style: none;
1056
+ margin: 0;
1057
+ padding: $mg-spacing-25 0;
1058
+ max-height: 240px;
1059
+ overflow-y: auto;
1060
+ overscroll-behavior: contain;
1061
+ }
1062
+
1063
+ .mg-select__option {
1064
+ display: flex;
1065
+ align-items: center;
1066
+ gap: $mg-spacing-50;
1067
+ padding: $mg-spacing-50 $mg-spacing-75;
1068
+ min-height: 40px; // Touch-friendly
1069
+ cursor: pointer;
1070
+ transition: background-color 0.1s ease;
1071
+
1072
+ &:hover,
1073
+ &--highlighted {
1074
+ background-color: $search-chip-bg;
1075
+ }
1076
+
1077
+ &--selected {
1078
+ background-color: rgba($search-primary, 0.08);
1079
+
1080
+ .mg-select__option-label {
1081
+ font-weight: 600;
1082
+ color: $search-primary;
1083
+ }
1084
+ }
1085
+
1086
+ &--selected#{&}--highlighted {
1087
+ background-color: rgba($search-primary, 0.12);
1088
+ }
1089
+ }
1090
+
1091
+ .mg-select__indicator {
1092
+ display: flex;
1093
+ align-items: center;
1094
+ justify-content: center;
1095
+ width: 18px;
1096
+ height: 18px;
1097
+ flex-shrink: 0;
1098
+ border: 2px solid $search-border;
1099
+ color: $search-primary;
1100
+
1101
+ &--checkbox {
1102
+ border-radius: $search-radius;
1103
+ }
1104
+
1105
+ &--radio {
1106
+ border-radius: 50%;
1107
+ }
1108
+
1109
+ .mg-select__option--selected & {
1110
+ border-color: $search-primary;
1111
+ background-color: $search-primary;
1112
+ color: #fff;
1113
+ }
1114
+ }
1115
+
1116
+ .mg-select__indicator-dot {
1117
+ width: 8px;
1118
+ height: 8px;
1119
+ background: #fff;
1120
+ border-radius: 50%;
1121
+ }
1122
+
1123
+ .mg-select__option-label {
1124
+ flex: 1;
1125
+ font-size: $mg-font-size-200;
1126
+ color: $search-text;
1127
+ line-height: 1.4;
1128
+ }
1129
+
1130
+ .mg-select__option-count {
1131
+ flex-shrink: 0;
1132
+ font-size: $mg-font-size-100;
1133
+ color: $search-text-muted;
1134
+ }
1135
+
1136
+ // Subtype options (indented children under parent content types)
1137
+ .mg-select__option--subtype {
1138
+ padding-left: $mg-spacing-150;
1139
+
1140
+ .mg-select__option-label {
1141
+ font-size: $mg-font-size-100;
1142
+
1143
+ // Add visual connector
1144
+ &::before {
1145
+ content: "└";
1146
+ margin-right: $mg-spacing-25;
1147
+ color: $search-text-muted;
1148
+ }
1149
+ }
1150
+ }
1151
+
1152
+ .mg-select__empty {
1153
+ padding: $mg-spacing-100;
1154
+ text-align: center;
1155
+ color: $search-text-muted;
1156
+ font-size: $mg-font-size-200;
1157
+ }
1158
+
1159
+ // ========================================
1160
+ // Enhanced Facet Option Styling
1161
+ // ========================================
1162
+
1163
+ .mg-search__facet-option {
1164
+ display: grid;
1165
+ grid-template-columns: 1.25em 1fr auto;
1166
+ padding: $mg-spacing-50;
1167
+ border-radius: $search-radius;
1168
+ align-items: baseline;
1169
+ gap: 0 $mg-spacing-25;
1170
+ transition: background-color 0.15s ease;
1171
+
1172
+ &:hover {
1173
+ background-color: rgba($search-primary, 0.05);
1174
+ }
1175
+
1176
+ input[type="checkbox"],
1177
+ input[type="radio"] {
1178
+ margin: 0;
1179
+ cursor: pointer;
1180
+ accent-color: $search-primary;
1181
+ }
1182
+
1183
+ label {
1184
+ padding-left: $mg-spacing-25;
1185
+ font-weight: normal;
1186
+ text-wrap: balance;
1187
+ cursor: pointer;
1188
+ line-height: 1.5;
1189
+ color: $search-text;
1190
+
1191
+ &:hover {
1192
+ text-decoration: underline;
1193
+ color: $search-primary;
1194
+ }
1195
+ }
1196
+
1197
+ // Selected/checked state
1198
+ &:has(input:checked) {
1199
+ background-color: rgba($search-primary, 0.08);
1200
+
1201
+ label {
1202
+ font-weight: 600;
1203
+ color: $search-primary;
1204
+ }
1205
+ }
1206
+ }
1207
+
1208
+ // Count badges in facets
1209
+ .mg-search__facet-count {
1210
+ color: $search-text-muted;
1211
+ font-size: $mg-font-size-200;
1212
+ white-space: nowrap;
1213
+ }
1214
+
1215
+ // ========================================
1216
+ // Mobile Filter Drawer (Left Slide-in)
1217
+ // ========================================
1218
+ // UX patterns informed by:
1219
+ // @see https://www.pencilandpaper.io/articles/ux-pattern-analysis-mobile-filters
1220
+ // Key decisions:
1221
+ // - Sidebar overlay: Maintains context, click outside to close
1222
+ // - Sticky header/footer: Always visible, no scrolling required
1223
+ // - 44px minimum touch targets: Finger-friendly interaction
1224
+ // - Batch filtering: Apply all filters at once (View Results button)
1225
+
1226
+ .mg-search__drawer-backdrop {
1227
+ position: fixed;
1228
+ inset: 0;
1229
+ background: rgb(0 0 0 / 0.5);
1230
+ z-index: 1000;
1231
+ animation: mg-search-fade-in 0.2s ease-out;
1232
+ cursor: pointer; // Indicate clickable to close
1233
+ }
1234
+
1235
+ @keyframes mg-search-fade-in {
1236
+ from {
1237
+ opacity: 0;
1238
+ }
1239
+ to {
1240
+ opacity: 1;
1241
+ }
1242
+ }
1243
+
1244
+ .mg-search__drawer {
1245
+ position: fixed;
1246
+ top: 0;
1247
+ left: 0;
1248
+ bottom: 0;
1249
+ width: min(320px, 85vw); // Max 320px or 85% of viewport
1250
+ background: #fff;
1251
+ box-shadow: 4px 0 20px rgb(0 0 0 / 0.15);
1252
+ display: flex;
1253
+ flex-direction: column;
1254
+ animation: mg-search-slide-in-left 0.3s ease-out;
1255
+ z-index: 1001;
1256
+ cursor: default; // Reset cursor inside drawer
1257
+ }
1258
+
1259
+ @keyframes mg-search-slide-in-left {
1260
+ from {
1261
+ transform: translateX(-100%);
1262
+ }
1263
+ to {
1264
+ transform: translateX(0);
1265
+ }
1266
+ }
1267
+
1268
+ .mg-search__drawer-header {
1269
+ display: flex;
1270
+ align-items: center;
1271
+ justify-content: space-between;
1272
+ padding: $mg-spacing-100 $mg-spacing-150;
1273
+ border-bottom: 1px solid $search-border;
1274
+ flex-shrink: 0;
1275
+ min-height: 56px; // Consistent header height
1276
+ }
1277
+
1278
+ .mg-search__drawer-title {
1279
+ margin: 0;
1280
+ font-size: $mg-font-size-300;
1281
+ font-weight: 600;
1282
+ color: $search-text;
1283
+ display: flex;
1284
+ align-items: center;
1285
+ gap: $mg-spacing-50;
1286
+ }
1287
+
1288
+ .mg-search__drawer-count {
1289
+ display: inline-flex;
1290
+ align-items: center;
1291
+ justify-content: center;
1292
+ min-width: 22px;
1293
+ height: 22px;
1294
+ padding: 0 $mg-spacing-25;
1295
+ font-size: $mg-font-size-200;
1296
+ font-weight: 600;
1297
+ color: #fff;
1298
+ background: $search-primary;
1299
+ border-radius: 11px;
1300
+ }
1301
+
1302
+ .mg-search__drawer-close {
1303
+ display: flex;
1304
+ align-items: center;
1305
+ justify-content: center;
1306
+ width: 44px; // Minimum touch target per UX guidelines
1307
+ height: 44px;
1308
+ padding: 0;
1309
+ color: $search-text-muted;
1310
+ background: none;
1311
+ border: none;
1312
+ border-radius: $search-radius;
1313
+ cursor: pointer;
1314
+ transition: background-color 0.15s, color 0.15s;
1315
+
1316
+ &:hover {
1317
+ background: $search-chip-bg;
1318
+ color: $search-text;
1319
+ }
1320
+
1321
+ &:focus-visible {
1322
+ outline: 2px solid $search-primary;
1323
+ outline-offset: -2px;
1324
+ }
1325
+ }
1326
+
1327
+ .mg-search__drawer-content {
1328
+ flex: 1;
1329
+ overflow-y: auto;
1330
+ padding: $mg-spacing-100 $mg-spacing-150;
1331
+ -webkit-overflow-scrolling: touch;
1332
+ overscroll-behavior: contain; // Prevent scroll chaining
1333
+ }
1334
+
1335
+ .mg-search__drawer-footer {
1336
+ padding: $mg-spacing-100 $mg-spacing-150;
1337
+ border-top: 1px solid $search-border;
1338
+ flex-shrink: 0;
1339
+ background: #fff; // Ensure footer is opaque
1340
+ }
1341
+
1342
+ .mg-search__drawer-apply {
1343
+ display: flex;
1344
+ align-items: center;
1345
+ justify-content: center;
1346
+ gap: $mg-spacing-50;
1347
+ width: 100%;
1348
+ min-height: 48px; // Touch-friendly height
1349
+ padding: $mg-spacing-75 $mg-spacing-100;
1350
+ font-size: $mg-font-size-200;
1351
+ font-weight: 600;
1352
+ color: #fff;
1353
+ background: $search-primary;
1354
+ border: none;
1355
+ border-radius: $search-radius;
1356
+ cursor: pointer;
1357
+ transition: background-color 0.15s;
1358
+
1359
+ &:hover {
1360
+ background: $search-primary-dark;
1361
+ }
1362
+
1363
+ &:focus-visible {
1364
+ outline: 2px solid $search-primary-dark;
1365
+ outline-offset: 2px;
1366
+ }
1367
+ }
1368
+
1369
+ .mg-search__drawer-apply-count {
1370
+ font-weight: 400;
1371
+ opacity: 0.9;
1372
+ }
1373
+
1374
+ // ========================================
1375
+ // Mobile Responsive Styles
1376
+ // ========================================
1377
+
1378
+ @media (width <= 800px) {
1379
+ // Show compact filter button in results header
1380
+ .mg-search__filter-btn {
1381
+ display: inline-flex;
1382
+ }
1383
+
1384
+ // Hide desktop sidebar
1385
+ .mg-search__sidebar {
1386
+ display: none;
1387
+ }
1388
+
1389
+ .mg-search__content {
1390
+ flex-direction: column;
1391
+ }
1392
+ }
1393
+
1394
+ @media (width >= 801px) {
1395
+ // Hide mobile elements on desktop
1396
+ .mg-search__filter-btn {
1397
+ display: none;
1398
+ }
1399
+
1400
+ .mg-search__drawer-backdrop {
1401
+ display: none;
1402
+ }
1403
+ }
1404
+
1405
+ // ========================================
1406
+ // Accessibility Focus States
1407
+ // ========================================
1408
+
1409
+ .mg-search__facet-select:focus-visible,
1410
+ .mg-search__facet input:focus-visible {
1411
+ outline: 2px solid $search-primary;
1412
+ outline-offset: 2px;
1413
+ }
1414
+
1415
+ // ========================================
1416
+ // Debug Mode
1417
+ // ========================================
1418
+
1419
+ .mg-search-debug {
1420
+ display: none;
1421
+ }
1422
+
1423
+ [data-mg-search-debug="true"] .mg-search-debug {
1424
+ display: block;
1425
+ }
1426
+
1427
+ // ========================================
1428
+ // Facet Operator Toggle (AND/OR)
1429
+ // ========================================
1430
+
1431
+ .mg-search__facet-operator {
1432
+ display: flex;
1433
+ flex-direction: column;
1434
+ gap: $mg-spacing-50;
1435
+ margin-top: $mg-spacing-75;
1436
+ font-size: $mg-font-size-200;
1437
+ }
1438
+
1439
+ .mg-search__facet-operator-row {
1440
+ display: flex;
1441
+ align-items: center;
1442
+ gap: $mg-spacing-50;
1443
+ }
1444
+
1445
+ .mg-search__facet-operator-label {
1446
+ color: $search-text-muted;
1447
+ font-weight: 500;
1448
+ }
1449
+
1450
+ .mg-search__facet-operator-hint {
1451
+ margin: 0;
1452
+ color: $search-text-muted;
1453
+ font-style: italic;
1454
+ line-height: 1.4;
1455
+ }
1456
+
1457
+ .mg-search__facet-operator-toggle {
1458
+ display: inline-flex;
1459
+ gap: $mg-spacing-25;
1460
+ }
1461
+
1462
+ .mg-search__facet-operator-option {
1463
+ display: flex;
1464
+ align-items: center;
1465
+ padding: $mg-spacing-25 $mg-spacing-50;
1466
+ cursor: pointer;
1467
+ transition: color 0.15s, border-color 0.15s;
1468
+ font-weight: 400;
1469
+ font-size: $mg-font-size-200;
1470
+ user-select: none;
1471
+ color: $search-text-muted;
1472
+ border-bottom: 2px solid transparent;
1473
+ border-radius: 0;
1474
+
1475
+ // Hide the actual radio input
1476
+ input {
1477
+ position: absolute;
1478
+ opacity: 0;
1479
+ pointer-events: none;
1480
+ }
1481
+
1482
+ &:hover:not(&--active) {
1483
+ color: $search-text;
1484
+ }
1485
+
1486
+ &--active {
1487
+ color: $search-primary;
1488
+ font-weight: 500;
1489
+ border-bottom-color: $search-primary;
1490
+ }
1491
+
1492
+ // Focus visible for keyboard navigation
1493
+ &:focus-within {
1494
+ outline: 2px solid $search-primary;
1495
+ outline-offset: 2px;
1496
+ border-radius: $search-radius;
1497
+ }
1498
+ }
1499
+
1500
+ // ========================================
1501
+ // Active Filter Chip Connector (AND grouping)
1502
+ // ========================================
1503
+
1504
+ .mg-search__filter-chip-connector {
1505
+ display: inline-flex;
1506
+ align-items: center;
1507
+ margin-right: $mg-spacing-25;
1508
+ color: $search-text-muted;
1509
+ font-weight: 600;
1510
+ text-transform: uppercase;
1511
+ letter-spacing: 0.05em;
1512
+ }
1513
+
1514
+ // Pager styles now live in the standalone Pager component.
1515
+ // @see stories/Components/Pager/pager.scss