@deriv-com/dds-marketing 0.2.0 → 1.0.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 (279) hide show
  1. package/.llm/components/accordion.md +8 -0
  2. package/.llm/components/accordionitem.md +8 -0
  3. package/.llm/components/aspectratio.md +8 -0
  4. package/.llm/components/badge.md +8 -0
  5. package/.llm/components/bottomsheet.md +8 -0
  6. package/.llm/components/breadcrumb.md +8 -0
  7. package/.llm/components/breadcrumbitem.md +8 -0
  8. package/.llm/components/button.md +46 -22
  9. package/.llm/components/buttonicon.md +14 -6
  10. package/.llm/components/card.md +15 -1
  11. package/.llm/components/cardbody.md +28 -2
  12. package/.llm/components/cardbutton.md +15 -1
  13. package/.llm/components/checkbox.md +8 -0
  14. package/.llm/components/ctabanner.md +186 -0
  15. package/.llm/components/ctabannerslider.md +204 -0
  16. package/.llm/components/divider.md +8 -0
  17. package/.llm/components/dropdownmenu.md +13 -5
  18. package/.llm/components/faqaccordion.md +217 -0
  19. package/.llm/components/featurebullets.md +254 -0
  20. package/.llm/components/featurecards.md +313 -0
  21. package/.llm/components/featurescroll.md +284 -0
  22. package/.llm/components/featuresplit.md +249 -0
  23. package/.llm/components/filterchip.md +8 -0
  24. package/.llm/components/footer.md +8 -0
  25. package/.llm/components/footergroup.md +8 -0
  26. package/.llm/components/grid.md +8 -0
  27. package/.llm/components/icon.md +8 -0
  28. package/.llm/components/landinghero.md +254 -0
  29. package/.llm/components/link.md +9 -1
  30. package/.llm/components/logocolumns.md +235 -0
  31. package/.llm/components/logorows.md +212 -0
  32. package/.llm/components/menuitem.md +8 -0
  33. package/.llm/components/navbar.md +79 -15
  34. package/.llm/components/navbaritem.md +9 -1
  35. package/.llm/components/navbarmenu.md +8 -0
  36. package/.llm/components/navbarmenugroup.md +8 -0
  37. package/.llm/components/navbarpanel.md +9 -1
  38. package/.llm/components/navbarswitcher.md +9 -1
  39. package/.llm/components/navbarswitcheroption.md +8 -0
  40. package/.llm/components/option.md +8 -0
  41. package/.llm/components/pageheader.md +231 -0
  42. package/.llm/components/pagination.md +26 -89
  43. package/.llm/components/paginationdots.md +215 -0
  44. package/.llm/components/producthero.md +248 -0
  45. package/.llm/components/removablechip.md +8 -0
  46. package/.llm/components/row.md +8 -0
  47. package/.llm/components/scroller.md +8 -0
  48. package/.llm/components/searchinput.md +8 -0
  49. package/.llm/components/segmentedcontrol.md +8 -0
  50. package/.llm/components/segmentedcontrolitem.md +8 -0
  51. package/.llm/components/select.md +8 -0
  52. package/.llm/components/selectchip.md +56 -15
  53. package/.llm/components/spinner.md +8 -0
  54. package/.llm/components/stack.md +8 -0
  55. package/.llm/components/statusdot.md +8 -0
  56. package/.llm/components/subdomainnavbar.md +8 -0
  57. package/.llm/components/tab.md +8 -0
  58. package/.llm/components/table.md +8 -0
  59. package/.llm/components/tablebody.md +8 -0
  60. package/.llm/components/tablecell.md +8 -0
  61. package/.llm/components/tablehead.md +8 -0
  62. package/.llm/components/tableheadercell.md +8 -0
  63. package/.llm/components/tablerow.md +8 -0
  64. package/.llm/components/tablist.md +8 -0
  65. package/.llm/components/testimonialrow.md +235 -0
  66. package/.llm/components/testimonialslider.md +254 -0
  67. package/.llm/components/textarea.md +8 -0
  68. package/.llm/components/textinput.md +8 -0
  69. package/.llm/components/tooltip.md +8 -0
  70. package/.llm/components/typography.md +8 -0
  71. package/.llm/digest/button.md +11 -6
  72. package/.llm/digest/buttonicon.md +2 -2
  73. package/.llm/digest/card.md +1 -0
  74. package/.llm/digest/cardbody.md +3 -1
  75. package/.llm/digest/cardbutton.md +1 -0
  76. package/.llm/digest/ctabanner.md +44 -0
  77. package/.llm/digest/ctabannerslider.md +45 -0
  78. package/.llm/digest/dropdownmenu.md +1 -1
  79. package/.llm/digest/faqaccordion.md +43 -0
  80. package/.llm/digest/featurebullets.md +52 -0
  81. package/.llm/digest/featurecards.md +49 -0
  82. package/.llm/digest/featurescroll.md +52 -0
  83. package/.llm/digest/featuresplit.md +54 -0
  84. package/.llm/digest/landinghero.md +53 -0
  85. package/.llm/digest/logocolumns.md +55 -0
  86. package/.llm/digest/logorows.md +48 -0
  87. package/.llm/digest/navbar.md +18 -3
  88. package/.llm/digest/pageheader.md +49 -0
  89. package/.llm/digest/pagination.md +6 -17
  90. package/.llm/digest/paginationdots.md +43 -0
  91. package/.llm/digest/producthero.md +53 -0
  92. package/.llm/digest/selectchip.md +6 -1
  93. package/.llm/digest/testimonialrow.md +51 -0
  94. package/.llm/digest/testimonialslider.md +51 -0
  95. package/.llm/index.md +24 -3
  96. package/.llm/rules.md +24 -0
  97. package/.llm/tokens.md +56 -12
  98. package/AGENTS.md +28 -3
  99. package/README.md +41 -21
  100. package/dist/components/banner-data.d.ts +38 -0
  101. package/dist/components/banner-data.js +15 -0
  102. package/dist/components/blocks/block-reveal.css +90 -0
  103. package/dist/components/blocks/cta-banner/CtaBanner.css +66 -0
  104. package/dist/components/blocks/cta-banner/CtaBanner.d.ts +22 -0
  105. package/dist/components/blocks/cta-banner/CtaBanner.js +31 -0
  106. package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +29 -0
  107. package/dist/components/blocks/cta-banner/CtaBanner.types.js +13 -0
  108. package/dist/components/blocks/cta-banner/cta-banner-impl.css +29 -0
  109. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.css +90 -0
  110. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +39 -0
  111. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +60 -0
  112. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +41 -0
  113. package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +15 -0
  114. package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +73 -0
  115. package/dist/components/blocks/faq-accordion/FaqAccordion.css +54 -0
  116. package/dist/components/blocks/faq-accordion/FaqAccordion.d.ts +20 -0
  117. package/dist/components/blocks/faq-accordion/FaqAccordion.js +28 -0
  118. package/dist/components/blocks/faq-accordion/FaqAccordion.types.d.ts +25 -0
  119. package/dist/components/blocks/faq-accordion/FaqAccordion.types.js +10 -0
  120. package/dist/components/blocks/faq-accordion/faq-accordion-impl.css +54 -0
  121. package/dist/components/blocks/feature-bullets/FeatureBullets.css +139 -0
  122. package/dist/components/blocks/feature-bullets/FeatureBullets.d.ts +31 -0
  123. package/dist/components/blocks/feature-bullets/FeatureBullets.js +55 -0
  124. package/dist/components/blocks/feature-bullets/FeatureBullets.types.d.ts +39 -0
  125. package/dist/components/blocks/feature-bullets/FeatureBullets.types.js +16 -0
  126. package/dist/components/blocks/feature-bullets/feature-bullets-impl.css +104 -0
  127. package/dist/components/blocks/feature-cards/FeatureCards.css +84 -0
  128. package/dist/components/blocks/feature-cards/FeatureCards.d.ts +24 -0
  129. package/dist/components/blocks/feature-cards/FeatureCards.js +66 -0
  130. package/dist/components/blocks/feature-cards/FeatureCards.types.d.ts +33 -0
  131. package/dist/components/blocks/feature-cards/FeatureCards.types.js +14 -0
  132. package/dist/components/blocks/feature-cards/feature-cards-impl.css +245 -0
  133. package/dist/components/blocks/feature-scroll/FeatureScroll.css +137 -0
  134. package/dist/components/blocks/feature-scroll/FeatureScroll.d.ts +39 -0
  135. package/dist/components/blocks/feature-scroll/FeatureScroll.js +167 -0
  136. package/dist/components/blocks/feature-scroll/FeatureScroll.types.d.ts +40 -0
  137. package/dist/components/blocks/feature-scroll/FeatureScroll.types.js +17 -0
  138. package/dist/components/blocks/feature-scroll/feature-scroll-impl.css +292 -0
  139. package/dist/components/blocks/feature-split/FeatureSplit.css +95 -0
  140. package/dist/components/blocks/feature-split/FeatureSplit.d.ts +30 -0
  141. package/dist/components/blocks/feature-split/FeatureSplit.js +38 -0
  142. package/dist/components/blocks/feature-split/FeatureSplit.types.d.ts +39 -0
  143. package/dist/components/blocks/feature-split/FeatureSplit.types.js +14 -0
  144. package/dist/components/blocks/feature-split/feature-split-impl.css +83 -0
  145. package/dist/components/blocks/landing-hero/LandingHero.css +85 -0
  146. package/dist/components/blocks/landing-hero/LandingHero.d.ts +41 -0
  147. package/dist/components/blocks/landing-hero/LandingHero.js +54 -0
  148. package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +37 -0
  149. package/dist/components/blocks/landing-hero/LandingHero.types.js +15 -0
  150. package/dist/components/blocks/landing-hero/landing-hero-impl.css +355 -0
  151. package/dist/components/blocks/logo-columns/LogoColumns.css +161 -0
  152. package/dist/components/blocks/logo-columns/LogoColumns.d.ts +23 -0
  153. package/dist/components/blocks/logo-columns/LogoColumns.js +46 -0
  154. package/dist/components/blocks/logo-columns/LogoColumns.types.d.ts +46 -0
  155. package/dist/components/blocks/logo-columns/LogoColumns.types.js +18 -0
  156. package/dist/components/blocks/logo-columns/logo-columns-impl.css +188 -0
  157. package/dist/components/blocks/logo-rows/LogoRows.css +122 -0
  158. package/dist/components/blocks/logo-rows/LogoRows.d.ts +20 -0
  159. package/dist/components/blocks/logo-rows/LogoRows.js +43 -0
  160. package/dist/components/blocks/logo-rows/LogoRows.types.d.ts +36 -0
  161. package/dist/components/blocks/logo-rows/LogoRows.types.js +16 -0
  162. package/dist/components/blocks/logo-rows/logo-rows-impl.css +179 -0
  163. package/dist/components/blocks/page-header/PageHeader.css +79 -0
  164. package/dist/components/blocks/page-header/PageHeader.d.ts +34 -0
  165. package/dist/components/blocks/page-header/PageHeader.js +43 -0
  166. package/dist/components/blocks/page-header/PageHeader.types.d.ts +32 -0
  167. package/dist/components/blocks/page-header/PageHeader.types.js +14 -0
  168. package/dist/components/blocks/page-header/page-header-impl.css +176 -0
  169. package/dist/components/blocks/product-hero/ProductHero.css +86 -0
  170. package/dist/components/blocks/product-hero/ProductHero.d.ts +35 -0
  171. package/dist/components/blocks/product-hero/ProductHero.js +48 -0
  172. package/dist/components/blocks/product-hero/ProductHero.types.d.ts +37 -0
  173. package/dist/components/blocks/product-hero/ProductHero.types.js +15 -0
  174. package/dist/components/blocks/product-hero/product-hero-impl.css +354 -0
  175. package/dist/components/blocks/testimonial-row/TestimonialRow.css +245 -0
  176. package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +20 -0
  177. package/dist/components/blocks/testimonial-row/TestimonialRow.js +128 -0
  178. package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +54 -0
  179. package/dist/components/blocks/testimonial-row/TestimonialRow.types.js +26 -0
  180. package/dist/components/blocks/testimonial-row/testimonial-row-impl.css +195 -0
  181. package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +181 -0
  182. package/dist/components/blocks/testimonial-slider/TestimonialSlider.d.ts +22 -0
  183. package/dist/components/blocks/testimonial-slider/TestimonialSlider.js +36 -0
  184. package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +49 -0
  185. package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.js +21 -0
  186. package/dist/components/blocks/testimonial-slider/testimonial-slider-impl.css +202 -0
  187. package/dist/components/blocks/use-reveal.d.ts +46 -0
  188. package/dist/components/blocks/use-reveal.js +120 -0
  189. package/dist/components/blocks/use-rotation.d.ts +62 -0
  190. package/dist/components/blocks/use-rotation.js +176 -0
  191. package/dist/components/core/accordion-item/AccordionItem.css +6 -5
  192. package/dist/components/core/bottom-sheet/BottomSheet.css +1 -1
  193. package/dist/components/core/button/Button.css +63 -16
  194. package/dist/components/core/button/Button.d.ts +14 -12
  195. package/dist/components/core/button/Button.js +43 -14
  196. package/dist/components/core/button/Button.types.d.ts +9 -14
  197. package/dist/components/core/button/button-impl.css +25 -0
  198. package/dist/components/core/button-icon/ButtonIcon.css +31 -15
  199. package/dist/components/core/button-icon/ButtonIcon.d.ts +2 -2
  200. package/dist/components/core/button-icon/ButtonIcon.js +2 -2
  201. package/dist/components/core/button-icon/ButtonIcon.types.d.ts +4 -4
  202. package/dist/components/core/card/Card.css +13 -4
  203. package/dist/components/core/card/Card.types.d.ts +2 -1
  204. package/dist/components/core/card-body/CardBody.css +11 -6
  205. package/dist/components/core/card-body/CardBody.d.ts +1 -1
  206. package/dist/components/core/card-body/CardBody.js +2 -2
  207. package/dist/components/core/card-body/CardBody.types.d.ts +4 -1
  208. package/dist/components/core/card-body/CardBody.types.js +1 -0
  209. package/dist/components/core/card-button/CardButton.css +13 -4
  210. package/dist/components/core/card-button/CardButton.types.d.ts +2 -1
  211. package/dist/components/core/checkbox/Checkbox.css +8 -1
  212. package/dist/components/core/dropdown-menu/DropdownMenu.css +13 -12
  213. package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +5 -3
  214. package/dist/components/core/dropdown-menu/DropdownMenu.js +5 -3
  215. package/dist/components/core/filter-chip/FilterChip.css +2 -1
  216. package/dist/components/core/footer/footer-impl.css +1 -1
  217. package/dist/components/core/footer-group/FooterGroup.css +8 -7
  218. package/dist/components/core/icon/Icon.css +1 -1
  219. package/dist/components/core/link/Link.css +1 -1
  220. package/dist/components/core/menu-item/MenuItem.css +1 -1
  221. package/dist/components/core/navbar/Navbar.css +7 -8
  222. package/dist/components/core/navbar/Navbar.d.ts +17 -1
  223. package/dist/components/core/navbar/Navbar.js +139 -12
  224. package/dist/components/core/navbar/Navbar.types.d.ts +23 -4
  225. package/dist/components/core/navbar/Navbar.types.js +1 -1
  226. package/dist/components/core/navbar/navbar-impl.css +10 -3
  227. package/dist/components/core/navbar/navbar-material.css +96 -0
  228. package/dist/components/core/navbar-item/NavbarItem.css +4 -4
  229. package/dist/components/core/navbar-menu/NavbarMenu.css +7 -5
  230. package/dist/components/core/navbar-menu/NavbarMenu.d.ts +1 -0
  231. package/dist/components/core/navbar-menu/NavbarMenu.js +1 -0
  232. package/dist/components/core/navbar-menu/navbar-menu-impl.css +7 -7
  233. package/dist/components/core/navbar-switcher/NavbarSwitcher.css +6 -5
  234. package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +1 -0
  235. package/dist/components/core/navbar-switcher/NavbarSwitcher.js +2 -1
  236. package/dist/components/core/option/Option.css +1 -1
  237. package/dist/components/core/pagination/Pagination.css +1 -75
  238. package/dist/components/core/pagination/Pagination.d.ts +4 -4
  239. package/dist/components/core/pagination/Pagination.js +11 -51
  240. package/dist/components/core/pagination/Pagination.types.d.ts +5 -17
  241. package/dist/components/core/pagination/Pagination.types.js +1 -3
  242. package/dist/components/core/pagination-dots/PaginationDots.css +60 -0
  243. package/dist/components/core/pagination-dots/PaginationDots.d.ts +25 -0
  244. package/dist/components/core/pagination-dots/PaginationDots.js +104 -0
  245. package/dist/components/core/pagination-dots/PaginationDots.types.d.ts +38 -0
  246. package/dist/components/core/pagination-dots/PaginationDots.types.js +9 -0
  247. package/dist/components/core/removable-chip/RemovableChip.css +3 -3
  248. package/dist/components/core/search-input/SearchInput.css +1 -1
  249. package/dist/components/core/segmented-control/SegmentedControl.css +1 -1
  250. package/dist/components/core/segmented-control-item/SegmentedControlItem.css +1 -1
  251. package/dist/components/core/select/Select.css +2 -1
  252. package/dist/components/core/select-chip/SelectChip.css +14 -7
  253. package/dist/components/core/select-chip/SelectChip.d.ts +1 -1
  254. package/dist/components/core/select-chip/SelectChip.js +7 -4
  255. package/dist/components/core/select-chip/SelectChip.types.d.ts +7 -1
  256. package/dist/components/core/select-chip/SelectChip.types.js +1 -1
  257. package/dist/components/core/select-chip/select-chip-impl.css +14 -3
  258. package/dist/components/core/status-dot/StatusDot.css +1 -1
  259. package/dist/components/core/subdomain-navbar/SubdomainNavbar.css +3 -3
  260. package/dist/components/core/tab/Tab.css +1 -1
  261. package/dist/components/core/tab-list/TabList.css +1 -1
  262. package/dist/components/core/table/table-impl.css +36 -14
  263. package/dist/components/core/table-header-cell/TableHeaderCell.css +5 -5
  264. package/dist/components/core/text-area/TextArea.css +1 -1
  265. package/dist/components/core/text-input/TextInput.css +1 -1
  266. package/dist/components/core/tooltip/Tooltip.css +1 -1
  267. package/dist/components/core/typography/Typography.css +5 -5
  268. package/dist/components/index.d.ts +35 -0
  269. package/dist/components/index.js +30 -0
  270. package/dist/components/logo-data.d.ts +24 -0
  271. package/dist/components/logo-data.js +11 -0
  272. package/dist/components/scroll-data.d.ts +64 -0
  273. package/dist/components/scroll-data.js +17 -0
  274. package/dist/components/testimonial-row-data.d.ts +51 -0
  275. package/dist/components/testimonial-row-data.js +11 -0
  276. package/dist/components/testimonial-slider-data.d.ts +26 -0
  277. package/dist/components/testimonial-slider-data.js +10 -0
  278. package/dist/marketing.css +385 -14
  279. package/package.json +1 -6
@@ -0,0 +1,85 @@
1
+ /* GENERATED from landinghero.contract.json. Do not edit. */
2
+
3
+ :where([data-dds-context="marketing"]) .dds-landinghero {
4
+ box-sizing: border-box;
5
+ container-type: inline-size;
6
+ display: flex;
7
+ inline-size: 100%;
8
+ justify-content: center;
9
+ overflow: hidden;
10
+ position: relative;
11
+ background-color: var(--color-bg-brand-strong);
12
+ color: var(--color-fg-on-brand-strong);
13
+ }
14
+
15
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__inner {
16
+ box-sizing: border-box;
17
+ display: flex;
18
+ inline-size: 100%;
19
+ min-inline-size: 0;
20
+ position: relative;
21
+ max-inline-size: var(--size-content-max);
22
+ padding-block: var(--space-section-default);
23
+ padding-inline: var(--space-inset-page);
24
+ }
25
+
26
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__content {
27
+ display: flex;
28
+ flex-direction: column;
29
+ inline-size: 100%;
30
+ min-inline-size: 0;
31
+ row-gap: var(--space-heading-description-actions);
32
+ }
33
+
34
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__text {
35
+ display: flex;
36
+ flex-direction: column;
37
+ min-inline-size: 0;
38
+ row-gap: var(--space-gap-none);
39
+ }
40
+
41
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__eyebrow {
42
+ margin-block: 0;
43
+ font-family: var(--font-eyebrow-lg-family);
44
+ font-size: var(--font-eyebrow-lg-size);
45
+ font-weight: var(--font-eyebrow-lg-weight);
46
+ letter-spacing: var(--font-eyebrow-lg-letter-spacing);
47
+ line-height: var(--font-eyebrow-lg-line-height);
48
+ margin-block-end: var(--space-heading-eyebrow-title);
49
+ }
50
+
51
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__title {
52
+ margin-block: 0;
53
+ text-wrap: balance;
54
+ font-family: var(--font-h1-family);
55
+ font-size: var(--font-h1-size);
56
+ font-weight: var(--font-h1-weight);
57
+ letter-spacing: var(--font-h1-letter-spacing);
58
+ line-height: var(--font-h1-line-height);
59
+ margin-block-end: var(--space-heading-title-description);
60
+ }
61
+
62
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__description {
63
+ margin-block: 0;
64
+ font-family: var(--font-body-md-family);
65
+ font-size: var(--font-body-md-size);
66
+ font-weight: var(--font-body-md-weight);
67
+ letter-spacing: var(--font-body-md-letter-spacing);
68
+ line-height: var(--font-body-md-line-height);
69
+ max-inline-size: var(--size-measure-hero-description);
70
+ }
71
+
72
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__actions {
73
+ display: flex;
74
+ flex-wrap: wrap;
75
+ column-gap: var(--space-actions-gap);
76
+ row-gap: var(--space-actions-gap);
77
+ }
78
+
79
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__media {
80
+ min-inline-size: 0;
81
+ position: relative;
82
+ aspect-ratio: var(--aspect-portrait);
83
+ border-radius: var(--radius-none);
84
+ }
85
+
@@ -0,0 +1,41 @@
1
+ import './LandingHero.css';
2
+ import './landing-hero-impl.css';
3
+ import '../block-reveal.css';
4
+ import { type LandingHeroProps } from './LandingHero.types.js';
5
+ export type { LandingHeroProps };
6
+ /**
7
+ * The band that opens a marketing page.
8
+ *
9
+ * The landing tier's band, and one of three. Which band a page opens with follows from where the
10
+ * page sits rather than from a prop: a product page takes ProductHero and a legal page PageHeader.
11
+ * Separate components rather than one with a switch, so a page cannot be given a tier it is not.
12
+ *
13
+ * One column, read down: what the page is about, then what a reader can do about it. The eyebrow,
14
+ * the title and the description are strings the page passes; the calls to action and both visuals
15
+ * are nodes it composes. Nothing here writes copy or decides a destination — the same stance
16
+ * Footer takes at the other end of the page.
17
+ *
18
+ * `root` spans the full width and `inner` holds the measure, which is the arrangement Footer uses
19
+ * and for the same reason: a ground stopping at the measure would read as a wide card at the top of
20
+ * the page rather than as the page beginning. The ground is dark and the ink is set once on the
21
+ * root, inherited by the eyebrow, the title and the description alike — this package's rule about a
22
+ * section that paints a ground, and the reason none of the three names a colour of its own.
23
+ *
24
+ * The steps inside the text block are carried by each part's own `margin-block-end` rather than by
25
+ * a gap on the block. Eyebrow-to-title and title-to-description are two different roles that happen
26
+ * to agree at full width and part company on a phone — twelve against sixteen — so a single gap
27
+ * could only ever have been one of them. `text` binds `space.gap.none` to say the absence is
28
+ * deliberate rather than forgotten.
29
+ *
30
+ * `media` is a child of the band rather than of the column. The visual is
31
+ * placed against the band's own edge, which an element nested inside the measure could not reach.
32
+ * The title carries the band's accessible name through `aria-labelledby`. A `<section>` is only a
33
+ * region landmark once it has a name, and a hero that announced itself as an unnamed section is one
34
+ * more thing a screen reader user walks through rather than a place they can skip to. The id is
35
+ * `useId` rather than a prop, because a page should not have to invent one to get a landmark.
36
+ *
37
+ * Both visual slots are hidden from assistive technology. What the band says is the
38
+ * title and the description; a photograph that carried meaning they do not would be a hero that
39
+ * reads as empty to anyone who cannot see it, and the contract says so.
40
+ */
41
+ export declare function LandingHero({ eyebrow, title, headingLevel, description, actions, media, backgroundImage, }: LandingHeroProps): import("react").JSX.Element;
@@ -0,0 +1,54 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId } from 'react';
4
+ import './LandingHero.css';
5
+ import './landing-hero-impl.css';
6
+ import '../block-reveal.css';
7
+ import { arriving, useReveal } from '../use-reveal.js';
8
+ import { given } from '../../given.js';
9
+ import { landingHeroDefaults, landingHeroParts, } from './LandingHero.types.js';
10
+ /**
11
+ * The band that opens a marketing page.
12
+ *
13
+ * The landing tier's band, and one of three. Which band a page opens with follows from where the
14
+ * page sits rather than from a prop: a product page takes ProductHero and a legal page PageHeader.
15
+ * Separate components rather than one with a switch, so a page cannot be given a tier it is not.
16
+ *
17
+ * One column, read down: what the page is about, then what a reader can do about it. The eyebrow,
18
+ * the title and the description are strings the page passes; the calls to action and both visuals
19
+ * are nodes it composes. Nothing here writes copy or decides a destination — the same stance
20
+ * Footer takes at the other end of the page.
21
+ *
22
+ * `root` spans the full width and `inner` holds the measure, which is the arrangement Footer uses
23
+ * and for the same reason: a ground stopping at the measure would read as a wide card at the top of
24
+ * the page rather than as the page beginning. The ground is dark and the ink is set once on the
25
+ * root, inherited by the eyebrow, the title and the description alike — this package's rule about a
26
+ * section that paints a ground, and the reason none of the three names a colour of its own.
27
+ *
28
+ * The steps inside the text block are carried by each part's own `margin-block-end` rather than by
29
+ * a gap on the block. Eyebrow-to-title and title-to-description are two different roles that happen
30
+ * to agree at full width and part company on a phone — twelve against sixteen — so a single gap
31
+ * could only ever have been one of them. `text` binds `space.gap.none` to say the absence is
32
+ * deliberate rather than forgotten.
33
+ *
34
+ * `media` is a child of the band rather than of the column. The visual is
35
+ * placed against the band's own edge, which an element nested inside the measure could not reach.
36
+ * The title carries the band's accessible name through `aria-labelledby`. A `<section>` is only a
37
+ * region landmark once it has a name, and a hero that announced itself as an unnamed section is one
38
+ * more thing a screen reader user walks through rather than a place they can skip to. The id is
39
+ * `useId` rather than a prop, because a page should not have to invent one to get a landmark.
40
+ *
41
+ * Both visual slots are hidden from assistive technology. What the band says is the
42
+ * title and the description; a photograph that carried meaning they do not would be a hero that
43
+ * reads as empty to anyone who cannot see it, and the contract says so.
44
+ */
45
+ export function LandingHero({ eyebrow, title, headingLevel = landingHeroDefaults.headingLevel, description, actions, media, backgroundImage, }) {
46
+ const titleId = useId();
47
+ const [band, revealed] = useReveal();
48
+ const Title = headingLevel === 'h2' ? 'h2' : 'h1';
49
+ return (_jsxs("section", { className: landingHeroParts.root, "aria-labelledby": titleId,
50
+ /* The one inline style here, and it is a value rather than a decision: which photograph,
51
+ supplied by the page. Everything about how it is drawn — the cover fit and the position — is in the stylesheet, where it can be reasoned about. A background shorthand
52
+ would have reset those four properties every time the page passed an image. */
53
+ style: given(backgroundImage) ? { backgroundImage: `url(${backgroundImage})` } : undefined, children: [media ? (_jsx("div", { className: landingHeroParts.media, "aria-hidden": "true", children: media })) : null, _jsx("div", { className: landingHeroParts.inner, ref: band, "data-revealed": revealed, children: _jsxs("div", { className: landingHeroParts.content, children: [_jsxs("div", { className: landingHeroParts.text, children: [given(eyebrow) ? (_jsx("p", { className: landingHeroParts.eyebrow, ...arriving(0), children: eyebrow })) : null, _jsx(Title, { className: landingHeroParts.title, ...arriving(1), id: titleId, children: title }), given(description) ? (_jsx("p", { className: landingHeroParts.description, ...arriving(2), children: description })) : null] }), actions ? (_jsx("div", { className: landingHeroParts.actions, ...arriving(3), children: actions })) : null] }) })] }));
54
+ }
@@ -0,0 +1,37 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface LandingHeroOwnProps {
3
+ /** A word or two placing the page before its title names it — a product family, a market, a campaign */
4
+ eyebrow?: string;
5
+ /** Always. The one thing the page is about, in the fewest words that still say it. It is the page's leading heading and the band's accessible name */
6
+ title: string;
7
+ /**
8
+ * `h1` — The default, and correct whenever the hero opens the page — which is what a hero is for
9
+ * `h2` — The rare page that already carries its `h1` elsewhere, and would otherwise have two
10
+ */
11
+ headingLevel?: 'h1' | 'h2';
12
+ /** The sentence under the title that says what the claim above it means, for the reader who is not yet convinced by the claim alone */
13
+ description?: string;
14
+ /** The one or two things the page wants a reader to do. Composed by the page rather than described to this component, so a call to action is the same Button here as anywhere else on the site */
15
+ actions?: ReactNode;
16
+ /** The band's visual — the subject standing beside the claim, cropped by the band's own inline edge rather than floating clear of it */
17
+ media?: ReactNode;
18
+ /** A photograph filling the whole band. It is shown as it is — nothing is painted over it, so choose one already dark enough that the title reads on it */
19
+ backgroundImage?: string;
20
+ }
21
+ export type LandingHeroProps = LandingHeroOwnProps;
22
+ /** The class each part carries. Apply these — do not retype them. */
23
+ export declare const landingHeroParts: {
24
+ readonly root: "dds-landinghero";
25
+ readonly inner: "dds-landinghero__inner";
26
+ readonly content: "dds-landinghero__content";
27
+ readonly text: "dds-landinghero__text";
28
+ readonly eyebrow: "dds-landinghero__eyebrow";
29
+ readonly title: "dds-landinghero__title";
30
+ readonly description: "dds-landinghero__description";
31
+ readonly actions: "dds-landinghero__actions";
32
+ readonly media: "dds-landinghero__media";
33
+ };
34
+ /** Generated so defaults cannot drift from the contract. */
35
+ export declare const landingHeroDefaults: {
36
+ readonly headingLevel: "h1";
37
+ };
@@ -0,0 +1,15 @@
1
+ // GENERATED from landing-hero.contract.json. Do not edit.
2
+ /** The class each part carries. Apply these — do not retype them. */
3
+ export const landingHeroParts = {
4
+ root: 'dds-landinghero',
5
+ inner: 'dds-landinghero__inner',
6
+ content: 'dds-landinghero__content',
7
+ text: 'dds-landinghero__text',
8
+ eyebrow: 'dds-landinghero__eyebrow',
9
+ title: 'dds-landinghero__title',
10
+ description: 'dds-landinghero__description',
11
+ actions: 'dds-landinghero__actions',
12
+ media: 'dds-landinghero__media',
13
+ };
14
+ /** Generated so defaults cannot drift from the contract. */
15
+ export const landingHeroDefaults = { headingLevel: 'h1' };
@@ -0,0 +1,355 @@
1
+ /*
2
+ * Scoped to this package, like the generated sheet beside it.
3
+ *
4
+ * `:where([data-dds-context="marketing"])` confines these rules without contributing specificity,
5
+ * so each is decided against the generated rule on its own terms. Rules that have to win are
6
+ * written a class deeper than they look, which is what footer-impl.css does and for the same
7
+ * reason: weight rather than which sheet the bundler happened to write last.
8
+ */
9
+
10
+ /*
11
+ * The photograph, drawn the one way a band wants it.
12
+ *
13
+ * The page passes which image; how it is fitted is this component's decision and belongs here
14
+ * rather than in the inline style, where a page could not see it and a reader of the markup would
15
+ * think the four properties were the page's choice. `cover` because a hero is a band of fixed
16
+ * height and a photograph that letterboxed would show the ground through it.
17
+ */
18
+ :where([data-dds-context="marketing"]) .dds-landinghero {
19
+ background-position: center;
20
+ background-repeat: no-repeat;
21
+ background-size: cover;
22
+ }
23
+
24
+ /*
25
+ * A title with nothing under it carries no step under it.
26
+ *
27
+ * The steps inside the text block sit on each part's own `margin-block-end`, because eyebrow-to-
28
+ * title and title-to-description are two roles that agree at full width and part company on a
29
+ * phone. The cost of that arrangement is a trailing margin: with `description` absent the title is
30
+ * the last child and its step is measured against nothing, which adds sixteen pixels to the step
31
+ * `content` already sets between the text and the actions.
32
+ *
33
+ * `:last-child` is the condition itself rather than a prop standing in for it — the description is
34
+ * one of two parts that can follow the title, and asking the DOM which is last is the question with
35
+ * one answer.
36
+ */
37
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__title:last-child {
38
+ margin-block-end: 0;
39
+ }
40
+
41
+ /*
42
+ * The band is at least a screen tall.
43
+ *
44
+ * `100cqh` rather than `100svh`, and the two are the same number on a real page: with no ancestor
45
+ * declaring size containment, a container query length falls back to the small viewport, which is
46
+ * the unit this wants and the reason it is not `vh` — on a phone the large viewport is measured
47
+ * with the browser chrome retracted, so a hero sized to it puts its own actions under the address
48
+ * bar until the reader scrolls, which is the one thing the band exists to prevent.
49
+ *
50
+ * What the container unit adds is an answer for a frame standing in for a window. The preview
51
+ * shows a band inside a panel a fraction of the screen's height; sized against the viewport it
52
+ * escaped that panel and covered the controls under it. A frame that declares `container-type:
53
+ * size` is now what this measures against, which is the same arrangement the preview already uses
54
+ * for a component pinned to the window — the component is right about what it wants, and the frame
55
+ * is what has to behave like a window.
56
+ *
57
+ * `min-block-size` rather than `block-size`, so a band whose copy runs long grows instead of
58
+ * clipping it. A fixed height was the source design's and it loses the description at a large text
59
+ * size.
60
+ */
61
+ :where([data-dds-context="marketing"]) .dds-landinghero {
62
+ /*
63
+ * Where the content sits is `inner`'s to say, not this element's.
64
+ *
65
+ * The band declares `container-type`, and a container query cannot reach the element that
66
+ * declares it — a rule on the band inside one is measured against the band's own ancestor, which
67
+ * on a page is nothing at all. Written here, the phone's arrangement held at every width and the
68
+ * claim ran off the foot of a desktop band. `inner` is a descendant, so a query reaches it, and
69
+ * the band simply lets it fill the height.
70
+ *
71
+ * On a phone the claim sits at the foot of the band, not in the middle of it.
72
+ *
73
+ * There the subject fills the band behind the words, and text centred against it reads as
74
+ * floating in front of a picture. At the base the words read as standing on the same ground —
75
+ * subject above, claim at the foot, where a reader's eye finishes and the scroll carries on.
76
+ *
77
+ * At full width the arrangement is the other one and the wide rule says so: the subject is
78
+ * beside the claim rather than behind it, so there is nothing to stand on and centring is what
79
+ * pairs the two columns.
80
+ *
81
+ * The step below the words is the band's own `padding-block`, which holds here, where the
82
+ * content rests on the band's foot. The wide rule zeroes it, because centred content needs no
83
+ * step, and content resting on an edge is the one case that does.
84
+ */
85
+ min-block-size: 100cqh;
86
+ }
87
+
88
+ /*
89
+ * The subject is placed against the band at every width, never laid out beside the text.
90
+ *
91
+ * Absolute is the base rule rather than the wide one, which is the correction: `media` is a child
92
+ * of the band and the band is a flex row, so without this it became a second column at anything
93
+ * under the fold width — a picture beside the claim, each squeezing the other, with the title run
94
+ * off the inline edge. The source design has it absolute at every width for exactly this reason
95
+ * and moves it at the breakpoint rather than placing it there.
96
+ *
97
+ * Centred and filling the band by default, which is what a narrow screen wants: the subject behind
98
+ * the claim rather than next to it. `inner` is painted over it by DOM order — it comes last in the
99
+ * markup and both are positioned — so no stacking order has to be named.
100
+ *
101
+ * `pointer-events: none` because it is decoration and the contract says so. Without it a subject
102
+ * covering the band would swallow a press meant for the button underneath.
103
+ */
104
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__media {
105
+ /*
106
+ * Stood on the band's foot rather than floated in it.
107
+ *
108
+ * A cutout of a person hanging with air under it reads as a sticker; cropped by the edge it is
109
+ * standing in the band. It is also what puts the subject above the claim now that the claim is
110
+ * at the base — the two share the foot of the band rather than overlapping in the middle of it.
111
+ *
112
+ * One inset and a size, never both insets: naming a start, an end and a height over-constrains
113
+ * the box, and CSS resolves that by dropping the end — which is how the wide rule came to hug
114
+ * the top while saying bottom.
115
+ */
116
+ align-items: flex-end;
117
+ display: flex;
118
+ inset-block-end: 0;
119
+ inset-block-start: auto;
120
+ inset-inline: 0;
121
+ block-size: 80%;
122
+ justify-content: center;
123
+ pointer-events: none;
124
+ position: absolute;
125
+ }
126
+
127
+ /*
128
+ * And the words are read off a scrim rather than off the subject.
129
+ *
130
+ * At a phone's width the claim sits over the picture, and a photograph is not a ground anybody
131
+ * chose — whatever is behind a given line is whatever the art happened to put there. The scrim
132
+ * darkens the foot of the band and fades out above it, so the words have a ground that is the
133
+ * band's own and the subject is still visible through it.
134
+ *
135
+ * `color.bg.overlay` rather than `overlay-subtle`, and the difference is what the scrim is for. A
136
+ * light scrim is enough to settle a picture that is already dark; this one has to hold white type
137
+ * over art nobody has seen. A page passing a bright photograph is the case that decides the value,
138
+ * and at a quarter of black white text on it is unreadable — which is a legibility failure a
139
+ * component cannot leave to whoever picks the art.
140
+ *
141
+ * It costs nothing where it is not needed: the band's own ground is near-black, so over that the
142
+ * scrim is invisible, and it only does work once something light is behind it.
143
+ *
144
+ * It is a black alpha, so fading it to `transparent` fades within one hue: a scrim of any other
145
+ * colour would pass through grey on its way out and leave a band across the picture.
146
+ *
147
+ * On `inner` rather than on the band, because the band paints before the subject and the scrim has
148
+ * to come after it. `inner` is the last thing in the markup and is positioned, so it paints over
149
+ * the picture without a stacking order being named — the same arrangement the subject itself
150
+ * relies on. At this width `inner` is the full width of the phone, so the scrim runs edge to edge
151
+ * and only its contents are held off by the gutter.
152
+ */
153
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__inner {
154
+ /* At the foot on a phone, and filling the band so the scrim has somewhere to sit. */
155
+ align-items: flex-end;
156
+ background-image: linear-gradient(to top, var(--color-bg-overlay), transparent);
157
+ /* Anchored to the foot and given a height of its own, so the scrim is a band under the words
158
+ rather than a wash over the whole picture. This box is the height of the viewport; the paint
159
+ is three fifths of it, which covers the claim and its actions and leaves the subject above
160
+ them untouched. */
161
+ background-position: bottom;
162
+ background-repeat: no-repeat;
163
+ background-size: 100% 60%;
164
+ }
165
+
166
+ /*
167
+ * Text against the measure's leading edge, visual against the band's own.
168
+ *
169
+ * The column takes half the measure and no more. A claim set at eighty pixels across the full
170
+ * twelve hundred is two words a line with a ragged edge, and the visual it is supposed to sit
171
+ * beside has nowhere to be.
172
+ *
173
+ * `@container` rather than `@media`, asking the band's own width: the root declares
174
+ * `container-type`, so a hero placed in a narrow region of a wide page folds on its own measure.
175
+ * `48rem` longhand because `var()` is not permitted in a container query condition — the same
176
+ * constraint footer-impl.css works under, and the same width, so the two bands fold together.
177
+ */
178
+ @container (min-width: 48rem) {
179
+ /*
180
+ * Half the measure, which is the reference design's 600 against its 1280 to within a few pixels
181
+ * — and holds at any width, where a number would only be right at one.
182
+ */
183
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__content {
184
+ max-inline-size: 50%;
185
+ }
186
+
187
+ /*
188
+ * No step above or below the words at this width.
189
+ *
190
+ * The band is already a screen tall and the content is centred in it, so the section step has
191
+ * nothing to do: centring sets where the words sit, and a step on either side would only move
192
+ * them off the middle. The step the contract binds is for the narrower arrangement, where the
193
+ * words rest on the band's foot and need the distance from it.
194
+ */
195
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__inner {
196
+ /* Centred, because the two columns are a pair rather than a thing standing on a ground. */
197
+ align-items: center;
198
+ /* No scrim: the subject is beside the claim here, not behind it, so there is nothing for the
199
+ words to be read off and a gradient would be a shadow under a column of text. */
200
+ background-image: none;
201
+ padding-block: 0;
202
+ }
203
+
204
+ /*
205
+ * The visual is placed against the band's inline end, not the column.
206
+ *
207
+ * Absolute against the root — which is why `media` is the band's child and not the content's.
208
+ * Off the band's block end but held off its inline one, so a cutout of a person is cropped at the
209
+ * waist by the band's own foot while still standing inside the page's gutter. The source design
210
+ * bleeds it off the side as well; run to the edge it read as a panel butted against the window
211
+ * rather than as a subject in the band, and the two edges are not the same decision — the foot
212
+ * is a crop and the side is a margin.
213
+ *
214
+ * `space.inset.page` is that margin, which is the role that holds a page's content off the edge
215
+ * of the window. The subject lands on the same line the content does, so the band has one gutter
216
+ * rather than a gutter and a picture that ignores it.
217
+ *
218
+ * The two `auto`s are what make that true, and their absence is why it was not. The base rule
219
+ * above sets `inset: 0` — all four sides — because at narrow widths the visual fills the band.
220
+ * Naming only the end insets here left both sides set on each axis with a size as well, which is
221
+ * over-constrained: CSS resolves that by ignoring the end value, so the visual hugged the start
222
+ * and the top while the rule said end and bottom. Releasing the start insets is what lets the
223
+ * ones named below take effect.
224
+ */
225
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__media {
226
+ block-size: 100%;
227
+ /*
228
+ * Wide enough for the shape rather than for a share of the band.
229
+ *
230
+ * The height is the band's and `aspect.portrait` is bound on the part, so the width follows
231
+ * from the two — about half the band at a laptop's proportions, which is what the fixed half
232
+ * was approximating. Stated as a share it was right at one window shape and wrong at every
233
+ * other: a tall window gave a portrait subject a landscape box and cropped the figure's head.
234
+ */
235
+ inline-size: auto;
236
+ inset-block-end: -14%;
237
+ inset-block-start: auto;
238
+ inset-inline-end: var(--space-inset-page);
239
+ inset-inline-start: auto;
240
+ position: absolute;
241
+ }
242
+
243
+ }
244
+
245
+ /*
246
+ * Whatever the page put in a visual slot fills the slot.
247
+ *
248
+ * The slots take a node rather than a source, so what arrives is the page's element and this
249
+ * cannot know whether it carries dimensions. Left alone an `<img>` renders at its intrinsic size,
250
+ * which for a product screenshot is wider than the band. `max-inline-size` rather than
251
+ * `inline-size` so a mark narrower than the slot is not stretched to fill it.
252
+ */
253
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__media > * {
254
+ block-size: 100%;
255
+ max-inline-size: 100%;
256
+ object-fit: contain;
257
+ }
258
+
259
+ /*
260
+ * The band rounds off as it leaves.
261
+ *
262
+ * Scroll-driven rather than timed: `view()` measures the band against the viewport, so the corner
263
+ * arrives as the reader scrolls and reverses when they scroll back. There is no element entering
264
+ * and no transition to hang it on, which is what puts a keyframed animation in this file rather
265
+ * than in a binding.
266
+ *
267
+ * `radius.expressive` is the corner, and it is the role's own description — the most rounding
268
+ * before full, for high-impact visual sections and banners. The source design carries fifty-six
269
+ * pixels here, which is not a step on this ramp; forty-eight is, and the difference is invisible
270
+ * against a band the width of the page.
271
+ *
272
+ * Only the two lower corners. The band starts at the top of the document with nothing above it to
273
+ * round away from, and a hero that curved at the top would read as a card the page had been
274
+ * dropped into.
275
+ */
276
+ @keyframes dds-landinghero-exit {
277
+ to {
278
+ border-end-end-radius: var(--radius-expressive);
279
+ border-end-start-radius: var(--radius-expressive);
280
+ scale: var(--motion-scale-band-exit);
281
+ }
282
+ }
283
+
284
+ @supports (animation-timeline: view()) {
285
+ :where([data-dds-context="marketing"]) .dds-landinghero {
286
+ animation: dds-landinghero-exit linear both;
287
+ animation-range: exit 0% exit 40%;
288
+ animation-timeline: view();
289
+ }
290
+ }
291
+
292
+ /*
293
+ * A reader who asked for less movement gets none of it.
294
+ *
295
+ * The generated sheet writes a reduced-motion block from its bindings, and this animation is not
296
+ * one of them — it is written here, so its own exception has to be too. The band simply keeps its
297
+ * square corner, which is what it has at rest anyway.
298
+ */
299
+ @media (prefers-reduced-motion: reduce) {
300
+ :where([data-dds-context="marketing"]) .dds-landinghero {
301
+ animation: none;
302
+ }
303
+ }
304
+
305
+ /*
306
+ * A band in a short container compacts, rather than clipping what it holds.
307
+ *
308
+ * `space.section.default` is 112 top and bottom — 224 of the band before a word is set, which is
309
+ * right at a screen's height and is most of an overview row. The band is as tall as the screen, so
310
+ * it is the screen's height that is asked: a `@media` query, on a real page. The band's own
311
+ * `container-type` is `inline-size`, which cannot answer a height, so a container query alone
312
+ * matched only inside a frame that measures its height — the preview's — and never in production.
313
+ * Both are written: the media query for a page, the container query for a frame. The role already
314
+ * exists for a band that has to be shorter; nothing new is named here.
315
+ *
316
+ * `40rem` longhand because `var()` is not permitted in a container query condition.
317
+ */
318
+ @container (max-height: 40rem) {
319
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__inner {
320
+ padding-block: var(--space-section-compact);
321
+ }
322
+ }
323
+
324
+ @media (max-height: 40rem) {
325
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__inner {
326
+ padding-block: var(--space-section-compact);
327
+ }
328
+ }
329
+
330
+ /*
331
+ * Two calls to action stack on a phone and stand side by side once there is room.
332
+ *
333
+ * The reference design makes each one full width at the narrow end — a button that hugs its label
334
+ * on a phone is a tap target sized by how long the word happens to be — and lets them hug once the
335
+ * band is wide enough to hold both on a line.
336
+ */
337
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__actions {
338
+ align-items: stretch;
339
+ flex-direction: column;
340
+ }
341
+
342
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__actions > * {
343
+ inline-size: 100%;
344
+ }
345
+
346
+ @container (min-width: 48rem) {
347
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__actions {
348
+ align-items: center;
349
+ flex-direction: row;
350
+ }
351
+
352
+ :where([data-dds-context="marketing"]) .dds-landinghero .dds-landinghero__actions > * {
353
+ inline-size: auto;
354
+ }
355
+ }