@undrr/undrr-mangrove 2.0.0 → 2.1.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 (182) hide show
  1. package/README.md +9 -5
  2. package/components/BookCard.js +2 -2
  3. package/components/Breadcrumbs.js +2 -2
  4. package/components/Checkbox.js +2 -2
  5. package/components/Chips.js +2 -2
  6. package/components/CopyButton.js +2 -2
  7. package/components/CtaButton.js +2 -2
  8. package/components/Drawer.js +3 -3
  9. package/components/Drawer.js.LICENSE.txt +3 -1
  10. package/components/EmbedContainer.js +2 -2
  11. package/components/Footer.js +2 -2
  12. package/components/FormAction.js +2 -2
  13. package/components/FormErrorSummary.js +2 -2
  14. package/components/FormGroup.js +2 -2
  15. package/components/FullWidth.js +2 -2
  16. package/components/Gallery.js +3 -3
  17. package/components/Hero.js +3 -3
  18. package/components/HighlightBox.js +2 -2
  19. package/components/HorizontalBookCard.js +3 -3
  20. package/components/HorizontalBookCard.js.LICENSE.txt +3 -1
  21. package/components/HorizontalCard.js +3 -3
  22. package/components/HorizontalCard.js.LICENSE.txt +3 -1
  23. package/components/IconCard.js +3 -3
  24. package/components/IconCard.js.LICENSE.txt +3 -1
  25. package/components/Legend.js +2 -2
  26. package/components/Loader.js +3 -3
  27. package/components/MegaMenu.js +3 -3
  28. package/components/Notice.js +2 -2
  29. package/components/PageHeader.js +2 -2
  30. package/components/Pager.js +2 -2
  31. package/components/ProgressBar.js +9 -0
  32. package/components/ProgressBar.js.LICENSE.txt +9 -0
  33. package/components/QuoteHighlight.js +3 -3
  34. package/components/QuoteHighlight.js.LICENSE.txt +3 -1
  35. package/components/Radio.js +2 -2
  36. package/components/Range.js +2 -2
  37. package/components/ScrollContainer.js +2 -2
  38. package/components/SegmentedControl.js +2 -2
  39. package/components/Select.js +2 -2
  40. package/components/ServiceNotice.js +2 -2
  41. package/components/ShareButtons.js +3 -3
  42. package/components/ShowMore.js +3 -3
  43. package/components/SkipLink.js +2 -2
  44. package/components/StatsCard.js +3 -3
  45. package/components/StatsCard.js.LICENSE.txt +3 -1
  46. package/components/SyndicationSearchWidget.js +3 -3
  47. package/components/Tab.js +2 -2
  48. package/components/TextCta.js +3 -3
  49. package/components/TextCta.js.LICENSE.txt +3 -1
  50. package/components/TextInput.js +2 -2
  51. package/components/Textarea.js +2 -2
  52. package/components/Tree.js +2 -2
  53. package/components/UserFeedback.js +2 -2
  54. package/components/VerticalCard.js +3 -3
  55. package/components/VerticalCard.js.LICENSE.txt +3 -1
  56. package/components/hydrate.js +3 -3
  57. package/css/style-all.css +147 -128
  58. package/css/style-all.css.map +1 -1
  59. package/css/style-delta.css +147 -128
  60. package/css/style-delta.css.map +1 -1
  61. package/css/style-gutenberg.css +12 -12
  62. package/css/style-gutenberg.css.map +1 -1
  63. package/css/style-irp.css +147 -128
  64. package/css/style-irp.css.map +1 -1
  65. package/css/style-mcr.css +147 -128
  66. package/css/style-mcr.css.map +1 -1
  67. package/css/style-preventionweb.css +147 -128
  68. package/css/style-preventionweb.css.map +1 -1
  69. package/css/style.css +147 -128
  70. package/css/style.css.map +1 -1
  71. package/docs/EDITORIAL-MANUAL.md +193 -0
  72. package/docs/llms-editorial-manual.txt +200 -0
  73. package/docs/llms-motion.txt +125 -0
  74. package/docs/llms-page-building.txt +1140 -0
  75. package/docs/llms-search-widget.txt +765 -0
  76. package/error-pages/401.html +1 -1
  77. package/error-pages/403.html +1 -1
  78. package/error-pages/404.html +1 -1
  79. package/error-pages/429.html +1 -1
  80. package/error-pages/500.html +1 -1
  81. package/error-pages/502.html +1 -1
  82. package/error-pages/503.html +1 -1
  83. package/error-pages/504.html +1 -1
  84. package/error-pages/5xx.html +1 -1
  85. package/error-pages/challenge.html +1 -1
  86. package/error-pages/managed-challenge.html +1 -1
  87. package/js/cite-this.js +994 -0
  88. package/js/on-this-page-nav.js +80 -1
  89. package/js/show-more.js +149 -21
  90. package/package.json +6 -1
  91. package/scss/Atom/BaseTypography/Abbr/abbr.scss +1 -1
  92. package/scss/Atom/BaseTypography/Blockquote/blockquote.scss +1 -1
  93. package/scss/Atom/BaseTypography/Cite/cite.scss +1 -1
  94. package/scss/Atom/BaseTypography/Code/code.scss +1 -1
  95. package/scss/Atom/BaseTypography/Mark/mark.scss +1 -1
  96. package/scss/Atom/BaseTypography/Quotation/quotation.scss +1 -1
  97. package/scss/Atom/BaseTypography/Small/small.scss +1 -1
  98. package/scss/Atom/Colors/color.scss +1 -1
  99. package/scss/Atom/EmptyState/empty-state.scss +1 -1
  100. package/scss/Atom/Icons/_icon-definitions.scss +35 -3
  101. package/scss/Atom/Icons/icons.scss +1 -1
  102. package/scss/Atom/Images/AuthorImage/author-image.scss +10 -3
  103. package/scss/Atom/Images/Image/image.scss +1 -1
  104. package/scss/Atom/Images/ImageCaptionCredit/image-caption-credit.scss +7 -2
  105. package/scss/Atom/Images/ImageCredit/image-credit.scss +1 -1
  106. package/scss/Atom/Layout/Container/container.scss +1 -1
  107. package/scss/Atom/Layout/Grid/grid.scss +1 -1
  108. package/scss/Atom/Layout/Spacing/spacing.scss +1 -1
  109. package/scss/Atom/Logo/logo.scss +1 -1
  110. package/scss/Atom/Navigation/Breadcrumb/breadcrumb.scss +1 -1
  111. package/scss/Atom/Navigation/MenuItems/menu-items.scss +1 -1
  112. package/scss/Atom/ReachElement/Details/details.scss +5 -3
  113. package/scss/Atom/ReachElement/Figcaption/figcaption.scss +1 -1
  114. package/scss/Atom/StatusLabel/status-label.scss +1 -1
  115. package/scss/Atom/Table/table.scss +1 -1
  116. package/scss/Atom/Tag/tag.scss +1 -1
  117. package/scss/Atom/Video/video.scss +1 -1
  118. package/scss/Components/Boilerplate/boilerplate.scss +1 -1
  119. package/scss/Components/Breadcrumbs/breadcrumbs.scss +1 -1
  120. package/scss/Components/Buttons/Chips/chips.scss +1 -1
  121. package/scss/Components/Buttons/CopyButton/copy-button.scss +1 -1
  122. package/scss/Components/Buttons/CtaButton/buttons.scss +1 -1
  123. package/scss/Components/Buttons/CtaButton/cta-button.scss +1 -1
  124. package/scss/Components/Buttons/ShareButtons/share-buttons.scss +90 -1
  125. package/scss/Components/Cards/Card/card.scss +9 -3
  126. package/scss/Components/Cards/StatsCard/stats-card.scss +9 -2
  127. package/scss/Components/CiteThis/cite-this.scss +339 -0
  128. package/scss/Components/CookieConsentBanner/cookie-consent-banner.scss +1 -1
  129. package/scss/Components/DataViz/Legend/legend.scss +1 -1
  130. package/scss/Components/ErrorPages/error-pages.scss +1 -1
  131. package/scss/Components/Footer/footer.scss +1 -1
  132. package/scss/Components/Forms/Checkbox/checkbox.scss +1 -1
  133. package/scss/Components/Forms/FormAction/form-action.scss +1 -1
  134. package/scss/Components/Forms/FormGroup/form-group.scss +1 -1
  135. package/scss/Components/Forms/InputFields/input-fields.scss +1 -1
  136. package/scss/Components/Forms/Radio/radio.scss +1 -1
  137. package/scss/Components/Forms/Range/range.scss +1 -1
  138. package/scss/Components/Forms/SegmentedControl/segmented-control.scss +1 -1
  139. package/scss/Components/Forms/Select/select.scss +1 -1
  140. package/scss/Components/Forms/TextInput/text-input.scss +1 -1
  141. package/scss/Components/Forms/Textarea/textarea.scss +1 -1
  142. package/scss/Components/Forms/_form-base.scss +1 -1
  143. package/scss/Components/Gallery/gallery.scss +41 -16
  144. package/scss/Components/Hero/hero.scss +166 -1
  145. package/scss/Components/HighlightBox/highlight-box.scss +1 -1
  146. package/scss/Components/MegaMenu/mega-menu.scss +43 -122
  147. package/scss/Components/MegaMenu/megamenu.scss +1 -1
  148. package/scss/Components/Navigation/Drawer/drawer.scss +11 -1
  149. package/scss/Components/Navigation/Tree/tree.scss +1 -1
  150. package/scss/Components/Notice/notice.scss +1 -1
  151. package/scss/Components/OnThisPageNav/on-this-page-nav.scss +109 -4
  152. package/scss/Components/PageHeader/page-header.scss +1 -1
  153. package/scss/Components/Pager/pager.scss +1 -1
  154. package/scss/Components/PreviewAccess/preview-access.scss +1 -1
  155. package/scss/Components/ProgressBar/progress-bar.scss +215 -0
  156. package/scss/Components/QuoteHighlight/quote-highlight.scss +1 -1
  157. package/scss/Components/ScrollContainer/scroll-container.scss +1 -1
  158. package/scss/Components/Snackbar/snackbar.scss +1 -1
  159. package/scss/Components/SyndicationSearchWidget/_deprecated-teaser-hide.scss +1 -1
  160. package/scss/Components/SyndicationSearchWidget/syndication-search-widget.scss +253 -128
  161. package/scss/Components/Tab/tab.scss +3 -2
  162. package/scss/Components/TableOfContents/table-of-contents.scss +1 -1
  163. package/scss/Components/TextCta/text-cta.scss +1 -1
  164. package/scss/Components/TextCta/textcta.scss +1 -1
  165. package/scss/Components/UserFeedback/user-feedback.scss +1 -1
  166. package/scss/Molecules/ImageCaption/image-caption.scss +17 -3
  167. package/scss/Molecules/SectionHeader/section-header.scss +1 -1
  168. package/scss/Molecules/SectionHeader/sectionheader.scss +1 -1
  169. package/scss/Patterns/HubHeader/hub-header.scss +1 -1
  170. package/scss/Patterns/RichContent/rich-content.scss +177 -0
  171. package/scss/Patterns/_shared/pattern-demo.scss +6 -1
  172. package/scss/Utilities/EmbedContainer/embed-container.scss +1 -1
  173. package/scss/Utilities/FullWidth/full-width.scss +1 -1
  174. package/scss/Utilities/Loader/loader.scss +133 -12
  175. package/scss/Utilities/Normalize/normalize.scss +1 -1
  176. package/scss/Utilities/PagePatterns/page-patterns.scss +1 -1
  177. package/scss/Utilities/ShowMore/show-more.scss +7 -1
  178. package/scss/Utilities/SkipLink/skip-link.scss +1 -1
  179. package/scss/assets/scss/_components.scss +5 -0
  180. package/scss/assets/scss/_foundational.scss +23 -8
  181. package/scss/assets/scss/_mixins.scss +5 -0
  182. package/scss/assets/scss/_variables.scss +2 -2
@@ -4,7 +4,7 @@
4
4
  * Full-bleed and split-column hero banner featuring headline typography, background imagery, and CTAs.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/Hero/Hero.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Hero/Hero.mdx
8
8
  */
9
9
  // The veil between the photograph and the copy, in two layers.
10
10
 
@@ -748,3 +748,168 @@ $variant-colour-props: (
748
748
  direction: rtl; // reverses grid item order (content stays first semantically)
749
749
  }
750
750
  }
751
+
752
+ // Tags below the summary and facts line: a list of outline tags in the
753
+ // hero's own ink, so they read on every surface. On the coloured variants the
754
+ // ink is white, the same pairing as the hero's copy; on the neutral variant it
755
+ // is the interactive colour. The plain fill a .mg-tag has elsewhere would be
756
+ // close to invisible on the theme's hero colour. Tags carrying a Tag modifier
757
+ // (mg-tag--secondary, --accent, …) keep that modifier's styling.
758
+ .mg-hero {
759
+ --mg-hero-tag-color: var(--mg-color-neutral-0);
760
+ }
761
+
762
+ .mg-hero__tags {
763
+ @include mg-list-unmarked;
764
+
765
+ display: flex;
766
+ flex-wrap: wrap;
767
+ gap: var(--mg-spacing-50);
768
+ margin: 0;
769
+ padding: var(--mg-spacing-50) 0;
770
+
771
+ > li {
772
+ margin: 0;
773
+ padding: 0;
774
+ }
775
+
776
+ .mg-tag:not([class*="mg-tag--"]) {
777
+ --mg-tag-foreground: rgb(var(--mg-hero-tag-color));
778
+ --mg-tag-background: transparent;
779
+ --mg-tag-background-hover: transparent;
780
+
781
+ background-color: transparent;
782
+ border-color: currentColor;
783
+ color: rgb(var(--mg-hero-tag-color));
784
+ }
785
+
786
+ // The hero's link colour rules are scoped to its copy; a tag is not copy.
787
+ a.mg-tag:not([class*="mg-tag--"]),
788
+ a.mg-tag:not([class*="mg-tag--"]):visited,
789
+ a.mg-tag:not([class*="mg-tag--"]):hover {
790
+ color: rgb(var(--mg-hero-tag-color));
791
+ }
792
+
793
+ a.mg-tag:hover {
794
+ text-decoration: underline;
795
+ text-underline-offset: 0.15em;
796
+ }
797
+ }
798
+
799
+ // Neutral variant: the page's own white surface, dark copy and the theme's
800
+ // interactive colour for links, for a page header that should not read as a
801
+ // coloured band. Every pairing is a published text token on white, so the
802
+ // contrast is solved rather than sampled: --mg-color-text and
803
+ // --mg-color-interactive both clear 4.5:1 on white in all five themes.
804
+ // --mg-color-hero-title is not used, because DELTA sets it to a light blue
805
+ // meant for a dark surface.
806
+ .mg-hero.mg-hero--neutral {
807
+ --mg-border-color-button-primary: transparent;
808
+ --mg-border-color-button-secondary: transparent;
809
+ --mg-hero-link-color: var(--mg-color-interactive);
810
+
811
+ background-color: rgb(var(--mg-color-neutral-0));
812
+ color: rgb(var(--mg-color-text));
813
+
814
+ // No photograph and no veil: dark copy cannot sit on either.
815
+ &::before {
816
+ content: none;
817
+ }
818
+
819
+ .mg-hero__title,
820
+ .mg-hero__title a,
821
+ .mg-hero__title a:hover,
822
+ .mg-hero__title a:visited {
823
+ color: rgb(var(--mg-color-text));
824
+ }
825
+
826
+ .mg-hero__overlay,
827
+ .mg-hero__content {
828
+ a:hover {
829
+ color: rgb(var(--mg-color-interactive-active));
830
+ }
831
+ }
832
+
833
+ // Outline tags in the interactive colour.
834
+ --mg-hero-tag-color: var(--mg-color-interactive);
835
+
836
+ // Links in the eyebrow, facts line and summary are underlined: colour alone
837
+ // separates them from the text around them by only about 2:1 (WCAG 1.4.1).
838
+ .mg-hero__label a,
839
+ .mg-hero__summaryText a {
840
+ text-decoration: underline;
841
+ text-underline-offset: 0.15em;
842
+ }
843
+
844
+ // Buttons go back to their ordinary page styling.
845
+ a.mg-button,
846
+ a.mg-button:hover,
847
+ a.mg-button:visited {
848
+ color: rgb(var(--mg-color-button));
849
+ }
850
+
851
+ a.mg-button-primary {
852
+ background-color: var(--mg-color-button-background);
853
+
854
+ &:hover {
855
+ background-color: var(--mg-color-button-background--hover);
856
+ }
857
+ }
858
+
859
+ a.mg-button-secondary:not(.mg-button-cta),
860
+ a.mg-button-secondary:not(.mg-button-cta):hover,
861
+ a.mg-button-secondary:not(.mg-button-cta):visited {
862
+ background-color: rgb(var(--mg-color-button-secondary-background));
863
+ border-color: var(--mg-border-color-button-secondary);
864
+ color: rgb(var(--mg-color-button));
865
+ }
866
+
867
+ a.mg-button.mg-button-cta,
868
+ a.mg-button.mg-button-cta:hover,
869
+ a.mg-button.mg-button-cta:visited {
870
+ background: transparent;
871
+ border-color: transparent;
872
+ color: rgb(var(--mg-color-interactive));
873
+
874
+ &::after {
875
+ background: rgb(var(--mg-color-interactive));
876
+ color: rgb(var(--mg-color-neutral-0));
877
+ }
878
+ }
879
+
880
+ a.mg-button:focus-visible {
881
+ @include mg-focus-ring;
882
+ }
883
+
884
+ // The split layout's padding was spacing for a coloured band. On the page
885
+ // surface the copy aligns with the content below, so it starts at the top.
886
+ &.mg-hero--split .mg-hero__content {
887
+ padding-block-start: 0;
888
+ }
889
+ }
890
+
891
+ // Neutral in the background layout drops the photograph even when the markup
892
+ // carries one inline, as Drupal or hand-written markup may: an inline
893
+ // background-image beats any selector, but background-size does not, so the
894
+ // image is sized away. The mobile banner (::after, which inherits the image)
895
+ // and the space reserved for it go too. Three classes, to beat both the
896
+ // mobile banner rules and .mg-hero--no-image.
897
+ .mg-hero.mg-hero--neutral:not(.mg-hero--split) {
898
+ --mg-hero-banner-block-size: 0px;
899
+
900
+ background-size: 0 0;
901
+
902
+ &::after {
903
+ content: none;
904
+ }
905
+ }
906
+
907
+ // On a phone the neutral split hero's image is a short banner above the copy
908
+ // rather than a 16:9 block below it, so the page's first screen keeps the
909
+ // title and summary. Visual order only; the copy stays first in the source.
910
+ .mg-hero.mg-hero--neutral.mg-hero--split .mg-hero__media {
911
+ @media (max-width: $mg-breakpoint-tablet) {
912
+ aspect-ratio: 3 / 1;
913
+ order: -1;
914
+ }
915
+ }
@@ -4,7 +4,7 @@
4
4
  * Callout container for highlighted summary points, key takeaways, and secondary editorial callouts.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/HighlightBox/HighlightBox.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/HighlightBox/HighlightBox.mdx
8
8
  */
9
9
  // Highlight box component (RTL-safe)
10
10
  // https://gitlab.com/undrr/web-backlog/-/issues/1678
@@ -4,7 +4,7 @@
4
4
  * Responsive header navigation bar with multi-level dropdown menus, mobile drawer, and keyboard accessibility.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/MegaMenu/MegaMenu.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/MegaMenu/MegaMenu.mdx
8
8
  */
9
9
  .mg-mega-wrapper {
10
10
  position: relative;
@@ -188,14 +188,6 @@
188
188
  background: rgb(var(--mg-color-interactive));
189
189
  opacity: 0;
190
190
  transform: scaleX(0);
191
-
192
- @media (prefers-reduced-motion: no-preference) {
193
- transition:
194
- transform var(--mg-motion-duration-fast)
195
- var(--mg-motion-easing-standard),
196
- opacity var(--mg-motion-duration-fast)
197
- var(--mg-motion-easing-standard);
198
- }
199
191
  }
200
192
  }
201
193
  }
@@ -386,9 +378,9 @@
386
378
 
387
379
  font-weight: 600;
388
380
  transition:
389
- background-color 150ms ease,
390
- color 150ms ease,
391
- transform 150ms ease;
381
+ background-color var(--mg-motion-duration-fast)
382
+ var(--mg-motion-easing-standard),
383
+ color var(--mg-motion-duration-fast) var(--mg-motion-easing-standard);
392
384
 
393
385
  &:hover,
394
386
  &:focus-visible {
@@ -405,11 +397,8 @@
405
397
  inset-inline-end: auto;
406
398
  padding-inline-start: var(--mg-spacing-150);
407
399
  margin-inline-end: var(--mg-spacing-150);
408
- transition:
409
- transform 150ms ease,
410
- inset-inline-start 200ms cubic-bezier(0.4, 0, 0.2, 1),
411
- inset-inline-end 200ms cubic-bezier(0.4, 0, 0.2, 1),
412
- opacity 150ms ease;
400
+ transition: opacity var(--mg-motion-duration-fast)
401
+ var(--mg-motion-easing-standard);
413
402
  opacity: 0.55;
414
403
  }
415
404
 
@@ -435,43 +424,9 @@
435
424
  content: "‹";
436
425
  }
437
426
 
438
- /* Brief pulse to draw attention when active becomes visible */
439
- @keyframes mg-mega-tab-pulse {
440
- 0% {
441
- box-shadow:
442
- inset 4px 0 0 0 rgb(var(--mg-color-button)),
443
- 0 0 0 0 rgb(var(--mg-color-blue-900) / 0);
444
- }
445
- 60% {
446
- box-shadow:
447
- inset 4px 0 0 0 rgb(var(--mg-color-button)),
448
- 0 0 0 8px rgb(var(--mg-color-blue-900) / 0.12);
449
- }
450
- 100% {
451
- box-shadow:
452
- inset 4px 0 0 0 rgb(var(--mg-color-button)),
453
- 0 0 0 0 rgb(var(--mg-color-blue-900) / 0);
454
- }
455
- }
456
-
457
- .mg-mega-content__section-list-link--active {
458
- animation: mg-mega-tab-pulse 700ms ease-out 1;
459
- }
460
-
461
- /* Slide motion for right content when tab changes */
462
- @keyframes mg-mega-content-swap {
463
- 0% {
464
- transform: translateX(8px);
465
- opacity: 0.98;
466
- }
467
- 100% {
468
- transform: translateX(0);
469
- opacity: 1;
470
- }
471
- }
472
-
427
+ // Public compatibility hook: content changes are immediate, without a slide.
473
428
  .mg-mega-content__right--sliding {
474
- animation: mg-mega-content-swap 180ms ease-out;
429
+ animation: none;
475
430
  }
476
431
 
477
432
  /* Stronger keyboard focus ring for accessibility.
@@ -518,19 +473,7 @@
518
473
  .mg-mega-content__menu--desktop {
519
474
  display: block;
520
475
 
521
- // Blue flash background that fades out (retriggered via React key)
522
- animation: mg-mega-right-flash 400ms ease-out;
523
-
524
- // Staggered slide-in for menu items
525
- li {
526
- animation: mg-mega-item-slide-in 250ms ease-out both;
527
-
528
- @for $i from 1 through 25 {
529
- &:nth-child(#{$i}) {
530
- animation-delay: #{($i - 1) * 30}ms;
531
- }
532
- }
533
- }
476
+ // Every destination is available immediately, including long menus.
534
477
  }
535
478
  }
536
479
 
@@ -588,32 +531,6 @@
588
531
  }
589
532
  }
590
533
 
591
- /* Subtle blue gradient flash that fades to transparent on right content area */
592
- @keyframes mg-mega-right-flash {
593
- 0% {
594
- background: linear-gradient(
595
- to bottom,
596
- rgb(var(--mg-color-blue-900) / 0.06) 0%,
597
- transparent 100%
598
- );
599
- }
600
- 100% {
601
- background: transparent;
602
- }
603
- }
604
-
605
- /* Menu items slide in from the left */
606
- @keyframes mg-mega-item-slide-in {
607
- 0% {
608
- opacity: 0;
609
- transform: translateX(-12px);
610
- }
611
- 100% {
612
- opacity: 1;
613
- transform: translateX(0);
614
- }
615
- }
616
-
617
534
  .mg-mega-sidebar-section {
618
535
  // This is the <li> inside .mg-mega-sidebar__list. A bare `list-style: none`
619
536
  // here overrides the empty-string marker the list sets, and the item's
@@ -684,13 +601,15 @@
684
601
  &[aria-expanded="true"] {
685
602
  .mg-icon-angle-circled-left {
686
603
  transform: rotate(-90deg);
687
- transition: transform 0.3s ease-in-out;
604
+ transition: transform var(--mg-motion-duration-medium)
605
+ var(--mg-motion-easing-standard);
688
606
  }
689
607
  }
690
608
 
691
609
  // Ensure smooth transition for icon default state
692
610
  .mg-icon-angle-circled-left {
693
- transition: transform 0.3s ease-in-out;
611
+ transition: transform var(--mg-motion-duration-medium)
612
+ var(--mg-motion-easing-standard);
694
613
  }
695
614
  }
696
615
 
@@ -713,7 +632,8 @@
713
632
  max-height: 80vh;
714
633
  top: -100%;
715
634
  inset-inline: 0; // RTL-friendly
716
- transition: top 0.4s ease-in-out;
635
+ transition: top var(--mg-motion-duration-medium)
636
+ var(--mg-motion-easing-standard);
717
637
  box-shadow: 0 5px 8px -4px rgb(0 0 0 / 0.25);
718
638
 
719
639
  &.mg-sidebar-open {
@@ -827,7 +747,8 @@
827
747
  max-height: 80vh;
828
748
  height: 80vh;
829
749
  transform: translateY(-100vh);
830
- transition: transform 0.4s ease-in-out;
750
+ transition: transform var(--mg-motion-duration-medium)
751
+ var(--mg-motion-easing-standard);
831
752
  box-shadow: 0 5px 8px -4px rgb(0 0 0 / 0.25);
832
753
 
833
754
  &.mg-mega-mobile-sidebar--open {
@@ -910,8 +831,8 @@
910
831
  opacity: 0;
911
832
  transform: translateX(var(--mg-mega-enter-offset, 8px));
912
833
  transition:
913
- opacity 180ms ease,
914
- transform 180ms ease;
834
+ opacity var(--mg-motion-duration-fast) var(--mg-motion-easing-standard),
835
+ transform var(--mg-motion-duration-fast) var(--mg-motion-easing-standard);
915
836
  pointer-events: none;
916
837
 
917
838
  &[hidden] {
@@ -922,7 +843,13 @@
922
843
  opacity: 1;
923
844
  transform: translateX(0);
924
845
  pointer-events: auto;
925
- animation: mg-mega-surface-enter 180ms ease-out;
846
+
847
+ // Establish the entry frame when the hidden surface becomes rendered.
848
+ // Transitions also reverse smoothly if a close is interrupted by reopening.
849
+ @starting-style {
850
+ opacity: 0;
851
+ transform: translateX(var(--mg-mega-enter-offset, 8px));
852
+ }
926
853
  }
927
854
 
928
855
  .mg-mega-mobile-sidebar__header {
@@ -967,7 +894,8 @@
967
894
  .mg-mega-mobile-sidebar__page {
968
895
  padding: var(--mg-spacing-250);
969
896
  padding-bottom: max(var(--mg-spacing-300), env(safe-area-inset-bottom));
970
- animation: mg-mega-progressive-enter 160ms ease-out;
897
+ animation: mg-mega-progressive-enter var(--mg-motion-duration-fast)
898
+ var(--mg-motion-easing-standard);
971
899
  }
972
900
 
973
901
  .mg-mega-mobile-sidebar__title {
@@ -1099,36 +1027,20 @@
1099
1027
  z-index: var(--mg-z-index-modal);
1100
1028
  }
1101
1029
 
1102
- @keyframes mg-mega-surface-enter {
1103
- from {
1104
- opacity: 0;
1105
- transform: translateX(var(--mg-mega-enter-offset, 8px));
1106
- }
1107
- to {
1108
- opacity: 1;
1109
- transform: translateX(0);
1110
- }
1111
- }
1112
-
1113
1030
  .mg-mega-mobile-sidebar-overlay {
1114
1031
  opacity: 0;
1115
1032
  pointer-events: none;
1116
- transition: opacity 180ms ease;
1033
+ transition: opacity var(--mg-motion-duration-fast)
1034
+ var(--mg-motion-easing-standard);
1117
1035
  background: rgb(var(--mg-color-black) / 0.16);
1118
1036
 
1119
1037
  &--open {
1120
1038
  opacity: 1;
1121
1039
  pointer-events: auto;
1122
- animation: mg-mega-backdrop-enter 180ms ease-out;
1123
- }
1124
- }
1125
1040
 
1126
- @keyframes mg-mega-backdrop-enter {
1127
- from {
1128
- opacity: 0;
1129
- }
1130
- to {
1131
- opacity: 1;
1041
+ @starting-style {
1042
+ opacity: 0;
1043
+ }
1132
1044
  }
1133
1045
  }
1134
1046
 
@@ -1163,7 +1075,16 @@
1163
1075
  }
1164
1076
 
1165
1077
  // Reduced motion: keep states, remove transition animation.
1166
- .mg-mega-content {
1078
+ .mg-mega-topbar__item .mg-mega-content,
1079
+ .mg-mega-topbar__item--active .mg-mega-content,
1080
+ .mg-mega-content__section-list-item .mg-mega-content__section-list-link,
1081
+ .mg-mega-content__section-list-item
1082
+ .mg-mega-content__section-list-link::after,
1083
+ .mg-mega-sidebar,
1084
+ .mg-mega-mobile-sidebar,
1085
+ .mg-mega-sidebar-section__item .mg-icon-angle-circled-left,
1086
+ .mg-mega-sidebar-section__item[aria-expanded="true"]
1087
+ .mg-icon-angle-circled-left {
1167
1088
  transition: none;
1168
1089
  }
1169
1090
  }
@@ -4,7 +4,7 @@
4
4
  * Legacy stylesheet forwarding to mega-menu.scss.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/MegaMenu/MegaMenu.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/MegaMenu/MegaMenu.mdx
8
8
  */
9
9
  // megamenu.scss — DEPRECATED, use mega-menu.scss
10
10
  @import "./mega-menu";
@@ -5,7 +5,7 @@
5
5
  * The close control reuses .mg-icon-button and its shared focus ring.
6
6
  *
7
7
  * Full documentation:
8
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/Navigation/Drawer/Drawer.mdx
8
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Navigation/Drawer/Drawer.mdx
9
9
  */
10
10
 
11
11
  .mg-drawer,
@@ -149,3 +149,13 @@
149
149
  max-block-size: mg-rem(400);
150
150
  }
151
151
  }
152
+
153
+ // The global reduced-motion reset gives every element a tiny transition
154
+ // duration. With the initial `all` transition property, descendants briefly
155
+ // animate inherited visibility and cannot receive opening focus. Disable the
156
+ // properties themselves so an open drawer and its controls appear together.
157
+ @media (prefers-reduced-motion: reduce) {
158
+ .mg-drawer * {
159
+ transition-property: none !important;
160
+ }
161
+ }
@@ -4,7 +4,7 @@
4
4
  * Accessible tree and nested hierarchy view with expand/collapse and selection states.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/Navigation/Tree/Tree.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Navigation/Tree/Tree.mdx
8
8
  */
9
9
 
10
10
  .mg-tree {
@@ -7,7 +7,7 @@
7
7
  * Actions reuse .mg-buttons and the dismiss control reuses .mg-icon-button.
8
8
  *
9
9
  * Full documentation:
10
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/Notice/Notice.mdx
10
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Notice/Notice.mdx
11
11
  */
12
12
 
13
13
  .mg-notice {
@@ -4,7 +4,7 @@
4
4
  * In-page table of contents navigation with active section indicator and smooth scrolling.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/OnThisPageNav/OnThisPageNav.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/OnThisPageNav/OnThisPageNav.mdx
8
8
  */
9
9
  // On this page nav
10
10
  // https://gitlab.com/undrr/web-backlog/-/issues/337
@@ -46,6 +46,39 @@
46
46
  display: none;
47
47
  }
48
48
 
49
+ // Line the links up with an mg-container content column instead of the
50
+ // bar's own padding. The bar stays full-bleed; only its padding changes, to
51
+ // half the space outside the container plus the container's gutter. A
52
+ // container is 100% wide below the mobile breakpoint, so the padding is the
53
+ // gutter alone there.
54
+ &--align-container {
55
+ --mg-on-this-page-nav-container: 100vw;
56
+
57
+ padding-inline: calc(
58
+ (100vw - var(--mg-on-this-page-nav-container)) / 2 + #{mg-rem(10)}
59
+ );
60
+
61
+ @media (min-width: $mg-breakpoint-mobile) {
62
+ --mg-on-this-page-nav-container: #{$mg-breakpoint-mobile};
63
+ }
64
+
65
+ @media screen and (min-width: $mg-breakpoint-tablet) {
66
+ --mg-on-this-page-nav-container: #{$mg-breakpoint-tablet};
67
+
68
+ padding-inline: calc(
69
+ (100vw - var(--mg-on-this-page-nav-container)) / 2 + #{mg-rem(10)}
70
+ );
71
+ }
72
+
73
+ @media (min-width: $mg-breakpoint-desktop) {
74
+ --mg-on-this-page-nav-container: #{$mg-breakpoint-desktop};
75
+ }
76
+
77
+ @media (min-width: $mg-breakpoint-desktop-wide) {
78
+ --mg-on-this-page-nav-container: #{$mg-breakpoint-desktop-wide};
79
+ }
80
+ }
81
+
49
82
  &__list {
50
83
  display: flex;
51
84
  align-items: center;
@@ -227,6 +260,78 @@
227
260
 
228
261
  // RTL: flex layout places prevBtn at the right (visual-start) edge and nextBtn
229
262
  // at the left (visual-end) edge. The JS scrollBy direction, button visibility,
230
- // and chevron icon direction are all RTL-aware. The mask-image gradient uses
231
- // physical `to right` which fades the correct edge in LTR; RTL gradient
232
- // correction is a known open item.
263
+ // and chevron icon direction are all RTL-aware. The fades are physical
264
+ // gradients, so RTL states each case: a fade only on a side with content
265
+ // hidden behind it, and the trailing (left) edge when nothing is hidden, to
266
+ // match LTR. has-left-overflow and has-right-overflow are set by the script.
267
+ // Each rule outranks the direction-neutral has-left-overflow rule above.
268
+
269
+ // Nothing hidden, or hidden only on the left (at the start of the list).
270
+ [dir="rtl"] .mg-on-this-page-nav__list,
271
+ [dir="rtl"] .mg-on-this-page-nav--has-left-overflow .mg-on-this-page-nav__list {
272
+ padding-inline-start: 0;
273
+ -webkit-mask-image: linear-gradient(
274
+ to left,
275
+ #000 calc(100% - var(--mg-spacing-500)),
276
+ transparent
277
+ );
278
+ mask-image: linear-gradient(
279
+ to left,
280
+ #000 calc(100% - var(--mg-spacing-500)),
281
+ transparent
282
+ );
283
+ }
284
+
285
+ // Hidden only on the right (scrolled to the end of the list).
286
+ [dir="rtl"]
287
+ .mg-on-this-page-nav--has-right-overflow
288
+ .mg-on-this-page-nav__list {
289
+ padding-inline-start: var(--mg-spacing-300);
290
+ -webkit-mask-image: linear-gradient(
291
+ to right,
292
+ #000 calc(100% - var(--mg-spacing-500)),
293
+ transparent
294
+ );
295
+ mask-image: linear-gradient(
296
+ to right,
297
+ #000 calc(100% - var(--mg-spacing-500)),
298
+ transparent
299
+ );
300
+ }
301
+
302
+ // Hidden on both sides (mid-scroll).
303
+ [dir="rtl"]
304
+ .mg-on-this-page-nav--has-left-overflow.mg-on-this-page-nav--has-right-overflow
305
+ .mg-on-this-page-nav__list {
306
+ padding-inline-start: var(--mg-spacing-300);
307
+ -webkit-mask-image: linear-gradient(
308
+ to right,
309
+ transparent,
310
+ #000 var(--mg-spacing-500),
311
+ #000 calc(100% - var(--mg-spacing-500)),
312
+ transparent
313
+ );
314
+ mask-image: linear-gradient(
315
+ to right,
316
+ transparent,
317
+ #000 var(--mg-spacing-500),
318
+ #000 calc(100% - var(--mg-spacing-500)),
319
+ transparent
320
+ );
321
+ }
322
+
323
+ // Anything the browser scrolls into view (keyboard focus, anchors, a pager's
324
+ // scrollIntoView) lands below the docked bar instead of under it (WCAG 2.4.11
325
+ // Focus Not Obscured). The script publishes the bar's height as
326
+ // --mg-on-this-page-nav-block-size while it is sticky, and 0px when it is not.
327
+ // --mg-on-this-page-nav-offset is read here from the root, so set it on :root
328
+ // for it to count.
329
+ // Zero specificity (:where), so a site's own `html { scroll-padding-top }`
330
+ // wins outright. A site that wants both sets --mg-on-this-page-nav-scroll-padding-base to its
331
+ // own value and lets this rule add the bar on top.
332
+ :where(html:has(.mg-on-this-page-nav:not(.mg-on-this-page-nav--hidden))) {
333
+ // prettier-ignore
334
+ --mg-on-this-page-nav-scroll-padding: calc(var(--mg-on-this-page-nav-scroll-padding-base, 0px) + var(--mg-on-this-page-nav-offset, 0px) + var(--mg-on-this-page-nav-block-size, 0px));
335
+
336
+ scroll-padding-top: var(--mg-on-this-page-nav-scroll-padding);
337
+ }
@@ -4,7 +4,7 @@
4
4
  * Standardized page heading banner with title, breadcrumbs, category metadata, and intro text.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/PageHeader/PageHeader.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/PageHeader/PageHeader.mdx
8
8
  */
9
9
  .mg-page-header {
10
10
  // Base styles for page header
@@ -4,7 +4,7 @@
4
4
  * Accessible pagination component with numbered pages, previous/next controls, and ellipsis truncation.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/Pager/Pager.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Pager/Pager.mdx
8
8
  */
9
9
  // ========================================
10
10
  // Pager — standalone pagination component
@@ -4,7 +4,7 @@
4
4
  * Protected preview bar and password gate interface for staging and draft content views.
5
5
  *
6
6
  * Full documentation:
7
- * https://github.com/unisdr/undrr-mangrove/blob/main/stories/Components/PreviewAccess/PreviewAccess.mdx
7
+ * https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/PreviewAccess/PreviewAccess.mdx
8
8
  */
9
9
  // Preview access
10
10
  // Soft preview gate for unfinished UNDRR pages. CSS hides the page on parse