@hraness/design-kit 0.34.0 → 0.35.1

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 (50) hide show
  1. package/AGENT_SETUP.md +4 -0
  2. package/ARTICLE_COPY.md +12 -6
  3. package/README.md +20 -2
  4. package/dist/{chunk-nwpcjm48.js → chunk-6bfr0g23.js} +1115 -441
  5. package/dist/{chunk-h4k7yv6x.js → chunk-6ts4955n.js} +36 -36
  6. package/dist/chunk-gmea6p0d.js +13 -0
  7. package/dist/{chunk-mr1vdcjq.js → chunk-tzd7177a.js} +142 -82
  8. package/dist/index.js +5 -1
  9. package/dist/mockups/client.js +50 -15
  10. package/dist/portfolio.js +586 -85
  11. package/dist/react/index.js +169 -105
  12. package/dist/react/platform-install.js +3 -2
  13. package/dist/react/server.js +17 -3
  14. package/dist/stylex-manifest.json +1 -1
  15. package/dist/stylex.css +376 -58
  16. package/package.json +16 -3
  17. package/portfolio-inventory.json +1 -1
  18. package/src/diagrams.ts +11 -0
  19. package/src/index.ts +2 -0
  20. package/src/marketing-comparison.css +162 -0
  21. package/src/marketing-diagram.css +24 -0
  22. package/src/mockups/client.tsx +25 -17
  23. package/src/mockups.css +19 -0
  24. package/src/plain-publication.css +9 -6
  25. package/src/portfolio.generated.json +578 -86
  26. package/src/portfolio.generated.ts +578 -86
  27. package/src/portfolio.ts +73 -0
  28. package/src/product-marketing-foundation.css +29 -0
  29. package/src/product-marketing.css +133 -38
  30. package/src/react/agent-setup-prompt.stylex.ts +5 -25
  31. package/src/react/agent-setup-prompt.tsx +9 -18
  32. package/src/react/article.tsx +2 -2
  33. package/src/react/design-gallery.tsx +34 -6
  34. package/src/react/index.ts +3 -0
  35. package/src/react/marketing-account.stylex.ts +74 -0
  36. package/src/react/marketing-account.tsx +69 -0
  37. package/src/react/marketing-comparison.stylex.ts +24 -0
  38. package/src/react/marketing-comparison.tsx +73 -0
  39. package/src/react/marketing-diagram.stylex.ts +8 -0
  40. package/src/react/marketing-diagram.tsx +33 -0
  41. package/src/react/platform-install.stylex.ts +9 -37
  42. package/src/react/platform-install.tsx +17 -24
  43. package/src/react/product-marketing.stylex.ts +138 -109
  44. package/src/react/product-marketing.tsx +69 -43
  45. package/src/react/server.ts +3 -0
  46. package/src/react/setup-copy-button.stylex.ts +39 -0
  47. package/src/react/setup-copy-button.tsx +20 -0
  48. package/src/styles.css +2 -0
  49. package/src/typography.css +32 -0
  50. /package/dist/{chunk-4d79eskk.js → chunk-c80g58j1.js} +0 -0
@@ -713,6 +713,7 @@ export const marketingStyles = stylex.create({
713
713
  "line-height": "var(--hraness-marketing-summary-leading, 1.6)",
714
714
  "max-inline-size": "var(--hraness-marketing-copy-measure)"
715
715
  },
716
+ "hero__install": { "inline-size": "min(100%, 44rem)", "min-inline-size": "0", "margin-block-start": "0.75rem", "text-align": "start" },
716
717
  "hero__example": {
717
718
  "margin": "0",
718
719
  "color": "var(--hraness-marketing-ink)",
@@ -1063,6 +1064,9 @@ export const marketingStyles = stylex.create({
1063
1064
  "@media (max-width: 48rem)": "minmax(0, 1fr)"
1064
1065
  }
1065
1066
  },
1067
+ "pillarsBenefits": { "border-block": "0", "gap": "2.75rem 3rem" },
1068
+ "pillars__benefit": { "display": "grid", "min-inline-size": "0", "align-content": "start", "gap": "0.75rem", "padding": "0", "border-block": "0", "border-inline": "0" },
1069
+ "pillars__icon": { "display": "block", "inline-size": "1.5rem", "block-size": "1.5rem", "margin-block-end": "1.1rem", "color": "var(--primary)" },
1066
1070
  "pillars__item": {
1067
1071
  "display": "grid",
1068
1072
  "min-inline-size": "0",
@@ -1694,10 +1698,22 @@ export const marketingStyles = stylex.create({
1694
1698
  "font-size": "1.125rem",
1695
1699
  "line-height": "1.5"
1696
1700
  },
1701
+ "related__groups": {
1702
+ "display": "grid",
1703
+ "grid-template-columns": "repeat(auto-fit, minmax(min(100%, 24rem), 1fr))",
1704
+ "gap": "2.5rem 3.5rem",
1705
+ "align-items": "start"
1706
+ },
1697
1707
  "related__group": {
1708
+ "--hraness-marketing-related-tone": {
1709
+ "default": "var(--hraness-marketing-ink)",
1710
+ "@media (forced-colors: active)": "CanvasText"
1711
+ },
1698
1712
  "display": "grid",
1699
- "gap": "1.5rem",
1700
- "min-inline-size": "0"
1713
+ "gap": "1rem",
1714
+ "min-inline-size": "0",
1715
+ "border-block-start": "2px solid var(--hraness-marketing-related-tone)",
1716
+ "padding-block-start": "1rem"
1701
1717
  },
1702
1718
  "related__group_header": {
1703
1719
  "display": "grid",
@@ -1707,146 +1723,146 @@ export const marketingStyles = stylex.create({
1707
1723
  "related__group_heading": {
1708
1724
  "margin": "0",
1709
1725
  "color": "var(--hraness-marketing-ink)",
1710
- "font-family": "var(--hraness-marketing-heading-font)",
1711
- "font-weight": "var(--hraness-marketing-heading-weight)",
1712
- "letter-spacing": "var(--hraness-marketing-h2-tracking, -0.012em)",
1713
- "line-height": "var(--hraness-marketing-h3-leading, 1.15)",
1726
+ "font-family": "var(--hraness-marketing-text-font)",
1727
+ "font-weight": "600",
1728
+ "letter-spacing": "-0.01em",
1729
+ "line-height": "1.35",
1714
1730
  "text-wrap": "balance",
1715
- "font-size": "var(--hraness-marketing-h3-size, clamp(1.75rem, 1.35rem + 1.6vw, 2.5rem))"
1731
+ "font-size": "1.125rem"
1716
1732
  },
1717
1733
  "related__group_summary": {
1718
1734
  "margin": "0",
1719
1735
  "color": "var(--hraness-marketing-muted)",
1720
1736
  "font-family": "var(--hraness-marketing-text-font)",
1721
- "font-size": "1.125rem",
1737
+ "font-size": "1rem",
1722
1738
  "line-height": "1.5"
1723
1739
  },
1740
+ "related__list": {
1741
+ "--hraness-marketing-grid-columns": "initial",
1742
+ "--_hraness-marketing-grid-track": "max(16rem, calc((100% - (var(--hraness-marketing-grid-columns) - 1) * 0.5rem) / var(--hraness-marketing-grid-columns)))",
1743
+ "grid-template-columns": "repeat(auto-fit, minmax(min(100%, var(--_hraness-marketing-grid-track, 100%)), 1fr))",
1744
+ "display": "grid",
1745
+ "gap": "0.5rem",
1746
+ "list-style": "none",
1747
+ "margin": "0",
1748
+ "padding": "0",
1749
+ "min-inline-size": "0"
1750
+ },
1751
+ "related__item": {
1752
+ "margin": "0",
1753
+ "min-inline-size": "0"
1754
+ },
1724
1755
  "related__card": {
1725
1756
  "display": "flex",
1726
1757
  "flex-direction": "row",
1727
- "align-items": "center",
1758
+ "align-items": "flex-start",
1728
1759
  "position": "relative",
1729
- "isolation": "isolate",
1730
1760
  "min-inline-size": "0",
1731
- "min-block-size": "100%",
1732
- "align-self": "stretch",
1733
- "gap": "1rem",
1734
- "padding": "clamp(1rem, 2vw, 1.25rem) clamp(1.125rem, 2.5vw, 1.5rem)",
1735
- "border-top": {
1736
- "default": "var(--hraness-marketing-surface-rule)",
1737
- "@media (forced-colors: active)": "1px solid CanvasText"
1738
- },
1739
- "border-right": {
1740
- "default": "var(--hraness-marketing-surface-rule)",
1741
- "@media (forced-colors: active)": "1px solid CanvasText"
1742
- },
1743
- "border-bottom": {
1744
- "default": "var(--hraness-marketing-surface-rule)",
1745
- "@media (forced-colors: active)": "1px solid CanvasText"
1746
- },
1747
- "border-left": {
1748
- "default": "var(--hraness-marketing-surface-rule)",
1749
- "@media (forced-colors: active)": "1px solid CanvasText"
1750
- },
1751
- "border-image-source": {
1752
- "default": "none",
1753
- "@media (forced-colors: active)": "none"
1754
- },
1755
- "border-image-slice": {
1756
- "default": "100%",
1757
- "@media (forced-colors: active)": "100%"
1758
- },
1759
- "border-image-width": {
1760
- "default": "1",
1761
- "@media (forced-colors: active)": "1"
1762
- },
1763
- "border-image-outset": {
1764
- "default": "0",
1765
- "@media (forced-colors: active)": "0"
1766
- },
1767
- "border-image-repeat": {
1768
- "default": "stretch",
1769
- "@media (forced-colors: active)": "stretch"
1770
- },
1771
- "border-radius": "var(--hraness-marketing-frame-radius)",
1761
+ "min-block-size": "2.75rem",
1762
+ "gap": "0.85rem",
1763
+ "padding": "0.55rem 0.5rem",
1764
+ "margin-inline": "0",
1765
+ "border-top": "0",
1766
+ "border-right": "0",
1767
+ "border-bottom": "0",
1768
+ "border-left": "0",
1769
+ "border-radius": "0.375rem",
1772
1770
  "background-color": {
1773
- "default": "var(--hraness-marketing-surface)",
1774
- "@media (forced-colors: active)": "Canvas"
1775
- },
1776
- "background-image": {
1777
- "default": "none",
1778
- "@media (forced-colors: active)": "none"
1779
- },
1780
- "background-position": {
1781
- "default": "0% 0%",
1782
- "@media (forced-colors: active)": "0% 0%"
1783
- },
1784
- "background-size": {
1785
- "default": "auto auto",
1786
- "@media (forced-colors: active)": "auto auto"
1787
- },
1788
- "background-repeat": {
1789
- "default": "repeat",
1790
- "@media (forced-colors: active)": "repeat"
1791
- },
1792
- "background-origin": {
1793
- "default": "padding-box",
1794
- "@media (forced-colors: active)": "padding-box"
1795
- },
1796
- "background-clip": {
1797
- "default": "border-box",
1798
- "@media (forced-colors: active)": "border-box"
1799
- },
1800
- "background-attachment": {
1801
- "default": "scroll",
1802
- "@media (forced-colors: active)": "scroll"
1803
- },
1804
- "box-shadow": {
1805
- "default": "var(--hraness-marketing-surface-shadow)",
1806
- ":hover": "0 0 0 1px var(--hraness-marketing-line-strong)",
1807
- "@media (forced-colors: active)": "none"
1808
- },
1809
- "color": {
1810
- "default": "inherit",
1811
- "@media (forced-colors: active)": "CanvasText"
1771
+ "default": "transparent",
1772
+ ":hover": "color-mix(in srgb, var(--hraness-marketing-related-tone, var(--hraness-marketing-ink)) 6%, transparent)"
1812
1773
  },
1774
+ "color": "var(--hraness-marketing-ink)",
1813
1775
  "text-decoration": "none",
1814
- outline: { default: null, ":focus-visible": "2px solid var(--hraness-marketing-accent)" },
1815
- "outline-offset": { default: null, ":focus-visible": "2px" }
1776
+ "box-shadow": "none",
1777
+ "outline": {
1778
+ "default": null,
1779
+ ":focus-visible": "2px solid var(--hraness-marketing-ink)"
1780
+ },
1781
+ "outline-offset": {
1782
+ "default": null,
1783
+ ":focus-visible": "-2px"
1784
+ }
1816
1785
  },
1817
1786
  "related__card_mark": {
1787
+ "--hraness-foil-text-base": "var(--hraness-marketing-related-tone, var(--hraness-marketing-ink))",
1788
+ "color": "var(--hraness-marketing-related-tone, var(--hraness-marketing-ink))",
1818
1789
  "flex-grow": "0",
1819
1790
  "flex-shrink": "0",
1820
1791
  "flex-basis": "auto",
1821
1792
  "display": "inline-flex",
1822
1793
  "align-items": "center",
1823
1794
  "justify-content": "center",
1824
- "inline-size": "2.75rem",
1825
- "block-size": "2.75rem"
1795
+ "inline-size": "1.75rem",
1796
+ "block-size": "1.75rem",
1797
+ "margin-block-start": "0.1rem"
1826
1798
  },
1827
1799
  "related__card_text": {
1828
1800
  "display": "grid",
1829
- "gap": "0.25rem",
1801
+ "gap": "0.05rem",
1830
1802
  "min-inline-size": "0"
1831
1803
  },
1804
+ "related__card_heading": {
1805
+ "display": "flex",
1806
+ "flex-wrap": "wrap",
1807
+ "align-items": "baseline",
1808
+ "column-gap": "0.6rem"
1809
+ },
1832
1810
  "related__card_name": {
1833
1811
  "margin": "0",
1834
1812
  "color": "var(--hraness-marketing-ink)",
1835
1813
  "font-family": "var(--hraness-marketing-text-font)",
1836
- "font-size": "1.25rem",
1837
- "font-weight": "700",
1814
+ "font-size": "1.0625rem",
1815
+ "font-weight": "600",
1838
1816
  "letter-spacing": "-0.01em",
1839
- "line-height": "1.25",
1817
+ "line-height": "1.35",
1818
+ "overflow-wrap": "anywhere",
1819
+ "text-decoration-line": "underline",
1820
+ "text-decoration-style": "dotted",
1821
+ "text-decoration-color": "color-mix(in srgb, currentColor 40%, transparent)",
1822
+ "text-decoration-thickness": "1px",
1823
+ "text-underline-offset": "0.2em"
1824
+ },
1825
+ "related__card_domain": {
1826
+ "color": "var(--hraness-marketing-muted)",
1827
+ "font-family": "var(--hraness-marketing-text-font)",
1828
+ "font-size": "0.8125rem",
1829
+ "font-weight": "400",
1830
+ "line-height": "1.5",
1840
1831
  "overflow-wrap": "anywhere"
1841
1832
  },
1842
1833
  "related__card_role": {
1843
1834
  "margin": "0",
1844
- "color": "var(--hraness-marketing-ink)",
1835
+ "color": "var(--hraness-marketing-muted)",
1845
1836
  "font-family": "var(--hraness-marketing-text-font)",
1846
- "font-size": "1.0625rem",
1837
+ "font-size": "0.9375rem",
1847
1838
  "line-height": "1.45",
1839
+ "overflow-wrap": "anywhere",
1848
1840
  "text-wrap": "pretty"
1849
1841
  },
1842
+ "relatedToneRose": {
1843
+ "--hraness-marketing-related-tone": {
1844
+ "default": "var(--hraness-studio-rose)",
1845
+ "@media (forced-colors: active)": "CanvasText"
1846
+ }
1847
+ },
1848
+ "relatedToneIndigo": {
1849
+ "--hraness-marketing-related-tone": {
1850
+ "default": "var(--hraness-studio-indigo)",
1851
+ "@media (forced-colors: active)": "CanvasText"
1852
+ }
1853
+ },
1854
+ "relatedToneAmber": {
1855
+ "--hraness-marketing-related-tone": {
1856
+ "default": "var(--hraness-studio-amber)",
1857
+ "@media (forced-colors: active)": "CanvasText"
1858
+ }
1859
+ },
1860
+ "relatedToneEmerald": {
1861
+ "--hraness-marketing-related-tone": {
1862
+ "default": "var(--hraness-studio-emerald)",
1863
+ "@media (forced-colors: active)": "CanvasText"
1864
+ }
1865
+ },
1850
1866
  "trust": {
1851
1867
  "color": "var(--hraness-marketing-ink)",
1852
1868
  "font-family": "var(--hraness-marketing-text-font)",
@@ -2689,10 +2705,15 @@ export const marketingStyles = stylex.create({
2689
2705
  },
2690
2706
  "quote__link": {
2691
2707
  "color": "inherit",
2692
- "text-decoration": {
2693
- "default": "none",
2694
- ":hover": "underline"
2695
- }
2708
+ "text-decoration-line": "underline",
2709
+ "text-decoration-style": "dotted",
2710
+ "text-decoration-color": {
2711
+ "default": "color-mix(in srgb, currentColor 40%, transparent)",
2712
+ ":hover": "currentColor",
2713
+ ":focus-visible": "currentColor"
2714
+ },
2715
+ "text-decoration-thickness": "1px",
2716
+ "text-underline-offset": "0.2em"
2696
2717
  },
2697
2718
  "plan_grid": {
2698
2719
  "display": "grid",
@@ -4276,6 +4297,7 @@ const recipes = {
4276
4297
  "hraness-marketing-hero__name": { "default": marketingStyles.hero__name },
4277
4298
  "hraness-marketing-hero__heading": { "default": marketingStyles.hero__heading },
4278
4299
  "hraness-marketing-hero__summary": { "default": marketingStyles.hero__summary },
4300
+ "hraness-marketing-hero__install": { "default": marketingStyles.hero__install },
4279
4301
  "hraness-marketing-hero__example": { "default": marketingStyles.hero__example },
4280
4302
  "hraness-marketing-hero__actions": { "default": marketingStyles.hero__actions, "start": marketingStyles.hero__actionsStart },
4281
4303
  "hraness-marketing-hero__boundary": { "default": marketingStyles.hero__boundary },
@@ -4302,7 +4324,8 @@ const recipes = {
4302
4324
  "hraness-marketing-stats__source": { "default": marketingStyles.stats__source },
4303
4325
  "hraness-marketing-stats__value": { "default": marketingStyles.stats__value },
4304
4326
  "hraness-marketing-pillars": { "default": marketingStyles.pillars },
4305
- "hraness-marketing-pillars__item": { "default": marketingStyles.pillars__item, "later": marketingStyles.pillars__itemLater },
4327
+ "hraness-marketing-pillars__item": { "default": marketingStyles.pillars__item, "later": marketingStyles.pillars__itemLater, "benefit": marketingStyles.pillars__benefit },
4328
+ "hraness-marketing-pillars__icon": { "default": marketingStyles.pillars__icon },
4306
4329
  "hraness-marketing-pillars__label": { "default": marketingStyles.pillars__label },
4307
4330
  "hraness-marketing-pillars__summary": { "default": marketingStyles.pillars__summary },
4308
4331
  "hraness-marketing-proof-frame": { "default": marketingStyles.proof_frame },
@@ -4352,7 +4375,12 @@ const recipes = {
4352
4375
  "hraness-marketing-related__label": { "default": marketingStyles.related__label },
4353
4376
  "hraness-marketing-related__heading": { "default": marketingStyles.related__heading },
4354
4377
  "hraness-marketing-related__summary": { "default": marketingStyles.related__summary },
4355
- "hraness-marketing-related__group": { "default": marketingStyles.related__group },
4378
+ "hraness-marketing-related__groups": { "default": marketingStyles.related__groups },
4379
+ "hraness-marketing-related__list": { "default": marketingStyles.related__list },
4380
+ "hraness-marketing-related__item": { "default": marketingStyles.related__item },
4381
+ "hraness-marketing-related__card-heading": { "default": marketingStyles.related__card_heading },
4382
+ "hraness-marketing-related__card-domain": { "default": marketingStyles.related__card_domain },
4383
+ "hraness-marketing-related__group": { "default": marketingStyles.related__group, "neutral": marketingStyles.related__group, "rose": [marketingStyles.related__group, marketingStyles.relatedToneRose], "indigo": [marketingStyles.related__group, marketingStyles.relatedToneIndigo], "amber": [marketingStyles.related__group, marketingStyles.relatedToneAmber], "emerald": [marketingStyles.related__group, marketingStyles.relatedToneEmerald] },
4356
4384
  "hraness-marketing-related__group-header": { "default": marketingStyles.related__group_header },
4357
4385
  "hraness-marketing-related__group-heading": { "default": marketingStyles.related__group_heading },
4358
4386
  "hraness-marketing-related__group-summary": { "default": marketingStyles.related__group_summary },
@@ -4462,18 +4490,19 @@ const gridColumns = {
4462
4490
 
4463
4491
  /** Explicit finite columns compose static atoms, including the existing media rules. */
4464
4492
  export function marketingColumnClassName(
4465
- hook: "hraness-marketing-facts" | "hraness-marketing-pillars" | "hraness-marketing-stats__list" | "hraness-marketing-card-row" | "hraness-marketing-primitives__list" | "hraness-marketing-interface-grid" | "hraness-marketing-trust-grid",
4493
+ hook: "hraness-marketing-facts" | "hraness-marketing-pillars" | "hraness-marketing-stats__list" | "hraness-marketing-card-row" | "hraness-marketing-primitives__list" | "hraness-marketing-interface-grid" | "hraness-marketing-trust-grid" | "hraness-marketing-related__list",
4466
4494
  caller: string | undefined,
4467
4495
  columns: MarketingColumnCount | undefined,
4496
+ presentation: "default" | "benefits" = "default",
4468
4497
  ): string {
4469
4498
  if (columns !== undefined && columns !== 1 && columns !== 2 && columns !== 3 && columns !== 4) {
4470
4499
  throw new RangeError("Marketing columns must be 1, 2, 3, or 4 when specified.");
4471
4500
  }
4472
4501
  const columnRecipe = columns === undefined ? undefined
4473
4502
  : (hook === "hraness-marketing-pillars" ? pillarColumns
4474
- : hook === "hraness-marketing-card-row" || hook === "hraness-marketing-primitives__list" || hook === "hraness-marketing-interface-grid" || hook === "hraness-marketing-trust-grid" ? gridColumns
4503
+ : hook === "hraness-marketing-card-row" || hook === "hraness-marketing-primitives__list" || hook === "hraness-marketing-interface-grid" || hook === "hraness-marketing-trust-grid" || hook === "hraness-marketing-related__list" ? gridColumns
4475
4504
  : factColumns)[columns];
4476
- return [hook, stylex.props(recipes[hook].default, columnRecipe).className, caller]
4505
+ return [hook, stylex.props(recipes[hook].default, columnRecipe, hook === "hraness-marketing-pillars" && presentation === "benefits" && marketingStyles.pillarsBenefits).className, caller]
4477
4506
  .filter((value) => value !== undefined && value.length > 0).join(" ");
4478
4507
  }
4479
4508
 
@@ -546,6 +546,8 @@ export interface ProductHeroProps {
546
546
  readonly heading: string;
547
547
  readonly headingId: string;
548
548
  readonly headingLevel?: MarketingHeadingLevel;
549
+ /** An install command or installer selector directly below the summary. */
550
+ readonly install?: ReactNode;
549
551
  readonly name: string;
550
552
  /** Product-owned notice after the copy boundary, without an added wrapper. */
551
553
  readonly notice?: ReactNode;
@@ -571,6 +573,7 @@ export function ProductHero({
571
573
  heading,
572
574
  headingId,
573
575
  headingLevel = 1,
576
+ install,
574
577
  name,
575
578
  notice,
576
579
  proof,
@@ -587,11 +590,12 @@ export function ProductHero({
587
590
  >
588
591
  <div className={classNames("hraness-marketing-hero__copy", undefined, align === "start" ? "start" : "default")}>
589
592
  {eyebrow === undefined || eyebrow === "" ? null : <p className={classNames("hraness-marketing-hero__eyebrow", undefined, tone === "accent" ? "accent" : "default")}>{eyebrow}</p>}
590
- <p className={classNames("hraness-marketing-hero__name")}>{name}</p>
593
+ {name === "" ? null : <p className={classNames("hraness-marketing-hero__name")}>{name}</p>}
591
594
  <Heading className={classNames("hraness-marketing-hero__heading")} id={headingId} level={headingLevel}>
592
595
  {heading}
593
596
  </Heading>
594
597
  <p className={classNames("hraness-marketing-hero__summary")}>{summary}</p>
598
+ {install === undefined ? null : <div className={classNames("hraness-marketing-hero__install")}>{install}</div>}
595
599
  {example === undefined
596
600
  ? null
597
601
  : <p className={classNames("hraness-marketing-hero__example")}>{example}</p>}
@@ -627,6 +631,7 @@ export function ProductHero({
627
631
  }
628
632
 
629
633
  export interface MarketingPillar {
634
+ readonly icon?: ReactNode;
630
635
  readonly label: string;
631
636
  readonly summary: string;
632
637
  }
@@ -636,25 +641,28 @@ export function MarketingPillars({
636
641
  className,
637
642
  columns,
638
643
  pillars,
644
+ presentation = "columns",
639
645
  }: Readonly<{
640
646
  ariaLabel: string;
641
647
  className?: string;
642
648
  /** Static desktop columns without inline styles; omission uses the collection length. Mobile stays one column. */
643
649
  columns?: MarketingColumnCount;
644
650
  pillars: readonly MarketingPillar[];
651
+ presentation?: "columns" | "benefits";
645
652
  }>) {
646
- const rootClassName = marketingColumnClassName("hraness-marketing-pillars", className, columns);
653
+ const rootClassName = marketingColumnClassName("hraness-marketing-pillars", className, columns, presentation === "benefits" ? "benefits" : "default");
647
654
  if (pillars.length === 0) return null;
648
655
  return (
649
656
  <dl
650
657
  aria-label={ariaLabel}
651
658
  className={rootClassName}
652
659
  data-hraness-marketing="pillars"
660
+ data-presentation={presentation}
653
661
  style={columns === undefined ? { "--hraness-marketing-pillar-columns": String(pillars.length) } as Record<string, string> : undefined}
654
662
  >
655
663
  {pillars.map((pillar, index) => (
656
- <div className={classNames("hraness-marketing-pillars__item", undefined, index === 0 ? "default" : "later")} key={pillar.label}>
657
- <dt className={classNames("hraness-marketing-pillars__label")}>{pillar.label}</dt>
664
+ <div className={classNames("hraness-marketing-pillars__item", undefined, presentation === "benefits" ? "benefit" : index === 0 ? "default" : "later")} key={pillar.label}>
665
+ <dt className={classNames("hraness-marketing-pillars__label")}>{pillar.icon === undefined ? null : <span aria-hidden="true" className={classNames("hraness-marketing-pillars__icon")}>{pillar.icon}</span>}{pillar.label}</dt>
658
666
  <dd className={classNames("hraness-marketing-pillars__summary")}>{pillar.summary}</dd>
659
667
  </div>
660
668
  ))}
@@ -1487,8 +1495,10 @@ export function MarketingMaker({
1487
1495
  }
1488
1496
 
1489
1497
  export interface MarketingRelatedProduct {
1490
- /** Custom artwork in place of `mark`, drawn in the same 44px slot. */
1498
+ /** Custom artwork in place of `mark`, drawn in the same 28px slot. */
1491
1499
  readonly art?: ReactNode;
1500
+ /** Optional public host, displayed beside the product name. */
1501
+ readonly domain?: string;
1492
1502
  readonly href: string;
1493
1503
  /** Transparent product mark, such as a portfolio item's `mark`; drawn as a foil mark before the name. */
1494
1504
  readonly mark?: string;
@@ -1502,6 +1512,8 @@ export interface MarketingRelatedProduct {
1502
1512
  readonly role: string;
1503
1513
  }
1504
1514
 
1515
+ export type MarketingRelatedTone = "rose" | "indigo" | "amber" | "emerald" | "neutral";
1516
+
1505
1517
  export interface MarketingRelatedGroup {
1506
1518
  /** Maximum columns for this group, overriding the section default. */
1507
1519
  readonly columns?: MarketingColumnCount;
@@ -1510,33 +1522,44 @@ export interface MarketingRelatedGroup {
1510
1522
  readonly headingId: string;
1511
1523
  readonly items: readonly MarketingRelatedProduct[];
1512
1524
  readonly summary?: string;
1525
+ /** The category color used on the studio portfolio. */
1526
+ readonly tone?: MarketingRelatedTone;
1513
1527
  }
1514
1528
 
1515
1529
  function MarketingRelatedCards({
1530
+ ariaLabel,
1531
+ columns,
1516
1532
  items,
1517
1533
  level,
1518
1534
  }: Readonly<{
1535
+ ariaLabel?: string;
1536
+ columns?: MarketingColumnCount;
1519
1537
  items: readonly MarketingRelatedProduct[];
1520
1538
  level: MarketingHeadingLevel;
1521
1539
  }>) {
1522
1540
  return (
1523
- <>
1541
+ <ul aria-label={ariaLabel} className={marketingColumnClassName("hraness-marketing-related__list", undefined, columns)}>
1524
1542
  {items.map((item) => (
1525
- <a className={classNames("hraness-marketing-related__card")} data-foil="" data-hraness-marketing="card" href={item.href} key={item.name}>
1526
- {isPresentNode(item.art) || (item.mark !== undefined && item.mark !== "")
1527
- ? (
1528
- <span aria-hidden="true" className={classNames("hraness-marketing-related__card-mark")}>
1529
- {isPresentNode(item.art) ? item.art : <FoilMark size={44} src={item.mark ?? ""} />}
1530
- </span>
1531
- )
1532
- : null}
1533
- <span className={classNames("hraness-marketing-related__card-text")}>
1534
- <Heading className={classNames("hraness-marketing-related__card-name")} level={level}>{item.name}</Heading>
1535
- <span className={classNames("hraness-marketing-related__card-role")}>{item.role}</span>
1536
- </span>
1537
- </a>
1543
+ <li className={classNames("hraness-marketing-related__item")} key={item.name}>
1544
+ <a className={classNames("hraness-marketing-related__card")} data-foil="" data-hraness-marketing="card" href={item.href}>
1545
+ {isPresentNode(item.art) || (item.mark !== undefined && item.mark !== "")
1546
+ ? (
1547
+ <span aria-hidden="true" className={classNames("hraness-marketing-related__card-mark")}>
1548
+ {isPresentNode(item.art) ? item.art : <FoilMark size={28} src={item.mark ?? ""} />}
1549
+ </span>
1550
+ )
1551
+ : null}
1552
+ <div className={classNames("hraness-marketing-related__card-text")}>
1553
+ <div className={classNames("hraness-marketing-related__card-heading")}>
1554
+ <Heading className={classNames("hraness-marketing-related__card-name")} level={level}>{item.name}</Heading>
1555
+ {item.domain === undefined ? null : <span className={classNames("hraness-marketing-related__card-domain")}>{item.domain}</span>}
1556
+ </div>
1557
+ <span className={classNames("hraness-marketing-related__card-role")}>{item.role}</span>
1558
+ </div>
1559
+ </a>
1560
+ </li>
1538
1561
  ))}
1539
- </>
1562
+ </ul>
1540
1563
  );
1541
1564
  }
1542
1565
 
@@ -1544,7 +1567,7 @@ type MarketingRelatedBody =
1544
1567
  | Readonly<{ groups: readonly MarketingRelatedGroup[]; items?: undefined }>
1545
1568
  | Readonly<{ groups?: undefined; items: readonly MarketingRelatedProduct[] }>;
1546
1569
 
1547
- /** Linked cards for sibling products: each shows the product's mark, name, and one-line description. */
1570
+ /** Compact studio product rows, grouped by portfolio category when supplied. */
1548
1571
  export function MarketingRelated({
1549
1572
  className,
1550
1573
  columns,
@@ -1585,30 +1608,33 @@ export function MarketingRelated({
1585
1608
  summary={summary}
1586
1609
  />
1587
1610
  {groups === undefined
1588
- ? (
1589
- <MarketingCardRow {...defaultColumnProps}>
1590
- <MarketingRelatedCards items={items} level={childHeadingLevel(headingLevel)} />
1591
- </MarketingCardRow>
1592
- )
1593
- : groups.map((group) => (
1594
- <div className={classNames("hraness-marketing-related__group")} key={group.headingId}>
1595
- <div className={classNames("hraness-marketing-related__group-header")}>
1596
- <Heading
1597
- className={classNames("hraness-marketing-related__group-heading")}
1598
- id={group.headingId}
1599
- level={childHeadingLevel(headingLevel)}
1611
+ ? <MarketingRelatedCards {...defaultColumnProps} items={items} level={childHeadingLevel(headingLevel)} />
1612
+ : (
1613
+ <div className={classNames("hraness-marketing-related__groups")}>
1614
+ {groups.map((group) => (
1615
+ <div
1616
+ aria-labelledby={group.headingId}
1617
+ className={classNames("hraness-marketing-related__group", undefined, group.tone ?? "neutral")}
1618
+ data-tone={group.tone ?? "neutral"}
1619
+ key={group.headingId}
1600
1620
  >
1601
- {group.heading}
1602
- </Heading>
1603
- {group.summary === undefined
1604
- ? null
1605
- : <p className={classNames("hraness-marketing-related__group-summary")}>{group.summary}</p>}
1606
- </div>
1607
- <MarketingCardRow ariaLabel={group.heading} {...(group.columns === undefined ? defaultColumnProps : { columns: group.columns })}>
1608
- <MarketingRelatedCards items={group.items} level={childHeadingLevel(childHeadingLevel(headingLevel))} />
1609
- </MarketingCardRow>
1621
+ <div className={classNames("hraness-marketing-related__group-header")}>
1622
+ <Heading
1623
+ className={classNames("hraness-marketing-related__group-heading")}
1624
+ id={group.headingId}
1625
+ level={childHeadingLevel(headingLevel)}
1626
+ >
1627
+ {group.heading}
1628
+ </Heading>
1629
+ {group.summary === undefined
1630
+ ? null
1631
+ : <p className={classNames("hraness-marketing-related__group-summary")}>{group.summary}</p>}
1632
+ </div>
1633
+ <MarketingRelatedCards ariaLabel={group.heading} {...(group.columns === undefined ? defaultColumnProps : { columns: group.columns })} items={group.items} level={childHeadingLevel(childHeadingLevel(headingLevel))} />
1634
+ </div>
1635
+ ))}
1610
1636
  </div>
1611
- ))}
1637
+ )}
1612
1638
  </section>
1613
1639
  );
1614
1640
  }
@@ -3,9 +3,12 @@ export * from "./particle-halo.js";
3
3
  export * from "./procedural-backdrop.js";
4
4
  export * from "./procedural-recipe.js";
5
5
  export * from "./product-marketing.js";
6
+ export * from "./marketing-account.js";
7
+ export * from "./marketing-comparison.js";
6
8
  export * from "./surfaces.js";
7
9
  export * from "./syntax-code.js";
8
10
  export * from "./foil-mark.js";
9
11
  export * from "./provider-mark.js";
10
12
  export * from "./platform-icons.js";
11
13
  export * from "./launch-beats.js";
14
+ export * from "./marketing-diagram.js";
@@ -0,0 +1,39 @@
1
+ import * as stylex from "@stylexjs/stylex";
2
+
3
+ const ink = "var(--foreground, CanvasText)";
4
+ const surface = "var(--surface, Canvas)";
5
+ const background = "var(--background, Canvas)";
6
+ const forced = "@media (forced-colors: active)";
7
+
8
+ export const setupCopyButtonStyles = stylex.create({
9
+ button: {
10
+ alignItems: "center",
11
+ appearance: "none",
12
+ backgroundColor: { default: background, ":hover": surface, [forced]: "ButtonFace" },
13
+ borderColor: { default: `color-mix(in srgb, ${ink} 15%, transparent)`, [forced]: "ButtonText" },
14
+ borderRadius: "0.5rem",
15
+ borderStyle: "solid",
16
+ borderWidth: "1px",
17
+ boxSizing: "border-box",
18
+ color: { default: ink, [forced]: "ButtonText" },
19
+ cursor: "pointer",
20
+ display: { default: "inline-flex", "@media (scripting: none)": "none" },
21
+ flexShrink: 0,
22
+ fontFamily: "var(--font-text, ui-sans-serif, system-ui, sans-serif)",
23
+ fontSize: "0.8125rem",
24
+ fontWeight: 500,
25
+ gap: "0.4rem",
26
+ justifyContent: "center",
27
+ lineHeight: 1,
28
+ margin: 0,
29
+ minBlockSize: "2.75rem",
30
+ outline: { default: "none", ":focus-visible": "2px solid var(--focus, Highlight)" },
31
+ outlineOffset: "2px",
32
+ padding: "0.65rem 0.8rem",
33
+ },
34
+ icon: { blockSize: "1rem", flexShrink: 0, inlineSize: "1rem" },
35
+ });
36
+
37
+ export function setupCopyButtonClassName(part: keyof typeof setupCopyButtonStyles, caller?: string): string {
38
+ return [`hraness-setup-copy__${part}`, stylex.props(setupCopyButtonStyles[part]).className, caller].filter(Boolean).join(" ");
39
+ }