@mieweb/ui 0.10.0-dev.23 → 0.10.0-dev.25

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 (147) hide show
  1. package/dist/brands/bluehive.cjs +3 -3
  2. package/dist/brands/bluehive.css +3 -0
  3. package/dist/brands/bluehive.js +1 -1
  4. package/dist/brands/index.cjs +9 -9
  5. package/dist/brands/index.js +3 -3
  6. package/dist/{chunk-YQDA366U.js → chunk-33DEVA3P.js} +2 -2
  7. package/dist/{chunk-YQDA366U.js.map → chunk-33DEVA3P.js.map} +1 -1
  8. package/dist/{chunk-WNJRS7Y7.cjs → chunk-3ZWCIPFT.cjs} +4 -2
  9. package/dist/chunk-3ZWCIPFT.cjs.map +1 -0
  10. package/dist/{chunk-J5CSLNCN.cjs → chunk-6VFDHJSO.cjs} +2 -2
  11. package/dist/{chunk-J5CSLNCN.cjs.map → chunk-6VFDHJSO.cjs.map} +1 -1
  12. package/dist/{chunk-ZTW4KODY.js → chunk-6ZPTZTKN.js} +3 -3
  13. package/dist/{chunk-ZTW4KODY.js.map → chunk-6ZPTZTKN.js.map} +1 -1
  14. package/dist/{chunk-SQ2D7AON.cjs → chunk-AAYXCZMV.cjs} +6 -6
  15. package/dist/{chunk-SQ2D7AON.cjs.map → chunk-AAYXCZMV.cjs.map} +1 -1
  16. package/dist/{chunk-WCDJFMZO.cjs → chunk-ADW7ZYCY.cjs} +1235 -495
  17. package/dist/chunk-ADW7ZYCY.cjs.map +1 -0
  18. package/dist/{chunk-2G75X6TS.cjs → chunk-AHHFFXJR.cjs} +3 -3
  19. package/dist/{chunk-2G75X6TS.cjs.map → chunk-AHHFFXJR.cjs.map} +1 -1
  20. package/dist/{chunk-HQ4CGVWX.cjs → chunk-B2X732V3.cjs} +7 -7
  21. package/dist/{chunk-HQ4CGVWX.cjs.map → chunk-B2X732V3.cjs.map} +1 -1
  22. package/dist/{chunk-UAMXCMST.cjs → chunk-CFI3TQMA.cjs} +3 -3
  23. package/dist/{chunk-UAMXCMST.cjs.map → chunk-CFI3TQMA.cjs.map} +1 -1
  24. package/dist/{chunk-2ABWFQQH.js → chunk-CRS2CQWM.js} +4 -4
  25. package/dist/{chunk-2ABWFQQH.js.map → chunk-CRS2CQWM.js.map} +1 -1
  26. package/dist/{chunk-MZNCLXXU.js → chunk-D22GE27K.js} +3 -3
  27. package/dist/{chunk-MZNCLXXU.js.map → chunk-D22GE27K.js.map} +1 -1
  28. package/dist/{chunk-IH55BEB3.js → chunk-DZFGTWYF.js} +6 -6
  29. package/dist/{chunk-IH55BEB3.js.map → chunk-DZFGTWYF.js.map} +1 -1
  30. package/dist/{chunk-TF7YWJHU.js → chunk-E2PBPQGS.js} +3 -3
  31. package/dist/{chunk-TF7YWJHU.js.map → chunk-E2PBPQGS.js.map} +1 -1
  32. package/dist/chunk-FBCDYTWM.js +385 -0
  33. package/dist/chunk-FBCDYTWM.js.map +1 -0
  34. package/dist/{chunk-R2O72G6Z.cjs → chunk-HC3NAN55.cjs} +7 -7
  35. package/dist/{chunk-R2O72G6Z.cjs.map → chunk-HC3NAN55.cjs.map} +1 -1
  36. package/dist/{chunk-DSB4DKWG.js → chunk-K34DXMLZ.js} +2 -2
  37. package/dist/{chunk-DSB4DKWG.js.map → chunk-K34DXMLZ.js.map} +1 -1
  38. package/dist/{chunk-Z5V7SAZ4.js → chunk-KFEN2SRZ.js} +3 -3
  39. package/dist/{chunk-Z5V7SAZ4.js.map → chunk-KFEN2SRZ.js.map} +1 -1
  40. package/dist/{chunk-MQPG3KVK.cjs → chunk-KGKBZN3T.cjs} +2 -2
  41. package/dist/{chunk-MQPG3KVK.cjs.map → chunk-KGKBZN3T.cjs.map} +1 -1
  42. package/dist/{chunk-G45FBKKV.js → chunk-P4VGVJVI.js} +4 -4
  43. package/dist/{chunk-G45FBKKV.js.map → chunk-P4VGVJVI.js.map} +1 -1
  44. package/dist/{chunk-3T7QGLNB.js → chunk-PJEL5ZZV.js} +4 -2
  45. package/dist/chunk-PJEL5ZZV.js.map +1 -0
  46. package/dist/{chunk-LJZKEMAH.cjs → chunk-R5Z7AOVU.cjs} +10 -10
  47. package/dist/{chunk-LJZKEMAH.cjs.map → chunk-R5Z7AOVU.cjs.map} +1 -1
  48. package/dist/{chunk-RJ6NTJHC.js → chunk-SRMTRD7F.js} +3 -3
  49. package/dist/{chunk-RJ6NTJHC.js.map → chunk-SRMTRD7F.js.map} +1 -1
  50. package/dist/{chunk-KHSFJTEX.js → chunk-T4JYUICS.js} +1177 -444
  51. package/dist/chunk-T4JYUICS.js.map +1 -0
  52. package/dist/{chunk-NJ6MY6V5.js → chunk-T5BBZQ66.js} +3 -3
  53. package/dist/{chunk-NJ6MY6V5.js.map → chunk-T5BBZQ66.js.map} +1 -1
  54. package/dist/{chunk-VYPPQPSZ.cjs → chunk-TJCX4OML.cjs} +3 -3
  55. package/dist/{chunk-VYPPQPSZ.cjs.map → chunk-TJCX4OML.cjs.map} +1 -1
  56. package/dist/{chunk-TAXD5ADA.cjs → chunk-UEDTZYGI.cjs} +3 -3
  57. package/dist/{chunk-TAXD5ADA.cjs.map → chunk-UEDTZYGI.cjs.map} +1 -1
  58. package/dist/{chunk-UQ3VVR6A.cjs → chunk-UPWIJC6I.cjs} +3 -3
  59. package/dist/{chunk-UQ3VVR6A.cjs.map → chunk-UPWIJC6I.cjs.map} +1 -1
  60. package/dist/{chunk-QNDP6PE5.cjs → chunk-VCCGR4J3.cjs} +92 -3
  61. package/dist/chunk-VCCGR4J3.cjs.map +1 -0
  62. package/dist/{chunk-S7WCHDBO.js → chunk-VCI2Y7ST.js} +3 -3
  63. package/dist/{chunk-S7WCHDBO.js.map → chunk-VCI2Y7ST.js.map} +1 -1
  64. package/dist/{chunk-Z4JR23IB.cjs → chunk-VOQJHSXN.cjs} +9 -9
  65. package/dist/{chunk-Z4JR23IB.cjs.map → chunk-VOQJHSXN.cjs.map} +1 -1
  66. package/dist/{chunk-EK3BCET6.js → chunk-WFVE36PO.js} +92 -3
  67. package/dist/chunk-WFVE36PO.js.map +1 -0
  68. package/dist/chunk-XI74P5F2.cjs +424 -0
  69. package/dist/chunk-XI74P5F2.cjs.map +1 -0
  70. package/dist/components/BoardView/index.d.cts +2 -90
  71. package/dist/components/BoardView/index.d.ts +2 -90
  72. package/dist/components/CalendarView/index.d.cts +1 -1
  73. package/dist/components/CalendarView/index.d.ts +1 -1
  74. package/dist/components/CountryCodeDropdown/index.cjs +5 -5
  75. package/dist/components/CountryCodeDropdown/index.js +2 -2
  76. package/dist/components/Dropdown/index.cjs +9 -9
  77. package/dist/components/Dropdown/index.js +2 -2
  78. package/dist/components/GanttView/index.d.cts +1 -1
  79. package/dist/components/GanttView/index.d.ts +1 -1
  80. package/dist/components/GlossaryTooltip/index.cjs +3 -3
  81. package/dist/components/GlossaryTooltip/index.js +2 -2
  82. package/dist/components/Markdown/index.cjs +15 -15
  83. package/dist/components/Markdown/index.js +3 -3
  84. package/dist/components/MediaEditor/index.cjs +10 -10
  85. package/dist/components/MediaEditor/index.js +5 -5
  86. package/dist/components/RadialExplorer/index.cjs +1 -1
  87. package/dist/components/RadialExplorer/index.js +1 -1
  88. package/dist/components/RichTextEditor/index.cjs +6 -6
  89. package/dist/components/RichTextEditor/index.js +3 -3
  90. package/dist/components/Select/index.cjs +4 -4
  91. package/dist/components/Select/index.js +2 -2
  92. package/dist/components/SourceTip/index.cjs +3 -3
  93. package/dist/components/SourceTip/index.js +2 -2
  94. package/dist/components/SuperChat/index.cjs +11 -11
  95. package/dist/components/SuperChat/index.js +4 -4
  96. package/dist/components/SuperChat/plugins/index.cjs +5 -5
  97. package/dist/components/SuperChat/plugins/index.js +4 -4
  98. package/dist/components/ViewSet/index.d.cts +1 -101
  99. package/dist/components/ViewSet/index.d.ts +1 -101
  100. package/dist/components/ViewSwitcher/index.d.cts +4 -57
  101. package/dist/components/ViewSwitcher/index.d.ts +4 -57
  102. package/dist/datavis.cjs +1 -1
  103. package/dist/datavis.js +1 -1
  104. package/dist/deck.cjs +3360 -0
  105. package/dist/deck.cjs.map +1 -0
  106. package/dist/deck.d.cts +712 -0
  107. package/dist/deck.d.ts +712 -0
  108. package/dist/deck.js +3316 -0
  109. package/dist/deck.js.map +1 -0
  110. package/dist/esheet.cjs +10 -10
  111. package/dist/esheet.js +7 -7
  112. package/dist/hooks/index.cjs +15 -15
  113. package/dist/hooks/index.js +3 -3
  114. package/dist/icons-wBacj6BW.d.cts +142 -0
  115. package/dist/icons-wBacj6BW.d.ts +142 -0
  116. package/dist/index-DoYYWsNc.d.cts +127 -0
  117. package/dist/index-DoYYWsNc.d.ts +127 -0
  118. package/dist/index.cjs +604 -551
  119. package/dist/index.cjs.map +1 -1
  120. package/dist/index.d.cts +313 -4
  121. package/dist/index.d.ts +313 -4
  122. package/dist/index.js +60 -59
  123. package/dist/index.js.map +1 -1
  124. package/dist/maps.cjs +160 -0
  125. package/dist/maps.cjs.map +1 -0
  126. package/dist/maps.d.cts +42 -0
  127. package/dist/maps.d.ts +42 -0
  128. package/dist/maps.js +138 -0
  129. package/dist/maps.js.map +1 -0
  130. package/dist/styles/effects.css +100 -0
  131. package/dist/styles/init.css +3 -0
  132. package/dist/styles.css +1 -1
  133. package/dist/tailwind-preset.cjs +4 -4
  134. package/dist/tailwind-preset.js +1 -1
  135. package/dist/templates.cjs +82 -29
  136. package/dist/templates.d.cts +316 -142
  137. package/dist/templates.d.ts +316 -142
  138. package/dist/templates.js +2 -1
  139. package/dist/{types-C3HQe74F.d.cts → types-DsdZvEI1.d.cts} +7 -1
  140. package/dist/{types-C3HQe74F.d.ts → types-DsdZvEI1.d.ts} +7 -1
  141. package/package.json +27 -1
  142. package/dist/chunk-3T7QGLNB.js.map +0 -1
  143. package/dist/chunk-EK3BCET6.js.map +0 -1
  144. package/dist/chunk-KHSFJTEX.js.map +0 -1
  145. package/dist/chunk-QNDP6PE5.cjs.map +0 -1
  146. package/dist/chunk-WCDJFMZO.cjs.map +0 -1
  147. package/dist/chunk-WNJRS7Y7.cjs.map +0 -1
@@ -1,333 +1,14 @@
1
+ import { SectionShell, cardClass, SectionHeading, CtaLinks, mutedTextClass, toneClass, containerClass, IconTile, accentTextClass, headingTextClass, TemplateAnchor, TemplateImg, safeHref, TemplateIcon, MetricStatusBadge, ownProperty } from './chunk-FBCDYTWM.js';
1
2
  import { inputVariants, RequiredMark } from './chunk-3IMM2PM4.js';
2
3
  import { Badge } from './chunk-BMSG4NBH.js';
3
4
  import { buttonVariants } from './chunk-GVM6DTR5.js';
4
5
  import { cn } from './chunk-TQONQSJO.js';
5
- import * as React from 'react';
6
- import { ChevronDown, ArrowRight, ChevronRight, CircleCheck, Check, TrendingDown, TrendingUp, Star, X, Zap, Wrench, Workflow, Users, UserCheck, Truck, Timer, Target, Syringe, Stethoscope, Sparkles, Smartphone, ShieldCheck, Shield, Settings, Search, Scale, Rocket, Plug, Plane, Phone, Microscope, MessageSquare, MapPin, Mail, Lock, Lightbulb, Leaf, Layers, Hospital, HeartPulse, Headset, HardHat, Handshake, GraduationCap, Globe, FlaskConical, FileText, Factory, DollarSign, Database, Cloud, Clock, ClipboardCheck, ChartLine, ChartColumn, CalendarCheck, Calendar, Building2, Briefcase, Bell, BadgeCheck, Award, Activity } from 'lucide-react';
6
+ import * as React5 from 'react';
7
+ import { ChevronDown, ArrowRight, ChevronRight, CircleCheck, Check, TrendingDown, TrendingUp, Star, Info, Download, ExternalLink, X } from 'lucide-react';
7
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
9
 
9
- // src/utils/own.ts
10
- function ownProperty(map, key) {
11
- return map != null && Object.hasOwn(map, key) ? map[key] : void 0;
12
- }
13
- var templateIcons = {
14
- activity: Activity,
15
- award: Award,
16
- "badge-check": BadgeCheck,
17
- bell: Bell,
18
- briefcase: Briefcase,
19
- building: Building2,
20
- calendar: Calendar,
21
- "calendar-check": CalendarCheck,
22
- "chart-column": ChartColumn,
23
- "chart-line": ChartLine,
24
- "circle-check": CircleCheck,
25
- "clipboard-check": ClipboardCheck,
26
- clock: Clock,
27
- cloud: Cloud,
28
- database: Database,
29
- "dollar-sign": DollarSign,
30
- factory: Factory,
31
- "file-text": FileText,
32
- flask: FlaskConical,
33
- globe: Globe,
34
- "graduation-cap": GraduationCap,
35
- handshake: Handshake,
36
- "hard-hat": HardHat,
37
- headset: Headset,
38
- "heart-pulse": HeartPulse,
39
- hospital: Hospital,
40
- layers: Layers,
41
- leaf: Leaf,
42
- lightbulb: Lightbulb,
43
- lock: Lock,
44
- mail: Mail,
45
- "map-pin": MapPin,
46
- "message-square": MessageSquare,
47
- microscope: Microscope,
48
- phone: Phone,
49
- plane: Plane,
50
- plug: Plug,
51
- rocket: Rocket,
52
- scale: Scale,
53
- search: Search,
54
- settings: Settings,
55
- shield: Shield,
56
- "shield-check": ShieldCheck,
57
- smartphone: Smartphone,
58
- sparkles: Sparkles,
59
- stethoscope: Stethoscope,
60
- syringe: Syringe,
61
- target: Target,
62
- timer: Timer,
63
- "trending-up": TrendingUp,
64
- truck: Truck,
65
- "user-check": UserCheck,
66
- users: Users,
67
- workflow: Workflow,
68
- wrench: Wrench,
69
- zap: Zap
70
- };
71
- function TemplateIcon({ name, icons, className }) {
72
- const Icon = ownProperty(icons, name) ?? ownProperty(templateIcons, name);
73
- if (Icon)
74
- return /* @__PURE__ */ jsx(
75
- Icon,
76
- {
77
- "aria-hidden": "true",
78
- strokeWidth: 1.75,
79
- className: cn("size-5", className)
80
- }
81
- );
82
- if (name.length <= 4)
83
- return /* @__PURE__ */ jsx(
84
- "span",
85
- {
86
- "aria-hidden": "true",
87
- className: cn("text-xs font-bold tracking-wide", className),
88
- children: name
89
- }
90
- );
91
- return null;
92
- }
93
- var toneSurface = {
94
- default: "bg-background text-foreground",
95
- muted: "bg-muted text-foreground",
96
- brand: "bg-primary-900 text-white"
97
- };
98
- var toneClass = (tone) => toneSurface[tone];
99
- var cardClass = (tone) => tone === "brand" ? "border border-white/15 bg-white/5 text-white" : "border border-border bg-card text-card-foreground";
100
- var mutedTextClass = (tone) => tone === "brand" ? "text-white/80" : tone === "muted" ? "text-foreground/80" : "text-muted-foreground";
101
- var headingTextClass = (tone) => tone === "brand" ? "text-white" : "text-foreground";
102
- var accentTextClass = (tone) => tone === "brand" ? "text-white" : "text-primary-800 dark:text-primary-300";
103
- var containerClass = (width = "wide") => cn(
104
- "mx-auto w-full px-4 sm:px-6 lg:px-8",
105
- width === "narrow" ? "max-w-3xl" : "max-w-7xl"
106
- );
107
- var SAFE_HREF_SCHEME = /^(?:https?|mailto|tel):/i;
108
- function safeHref(href) {
109
- if (href == null) return void 0;
110
- const stripped = href.replace(/[\u0000-\u0020]/g, "");
111
- if (!stripped) return void 0;
112
- if (!/^[a-z][a-z0-9+.-]*:/i.test(stripped)) return href;
113
- return SAFE_HREF_SCHEME.test(stripped) ? href : void 0;
114
- }
115
- function TemplateAnchor({
116
- components,
117
- trackingId,
118
- children,
119
- ...props
120
- }) {
121
- const Link = components?.Link;
122
- const href = safeHref(props.href);
123
- const all = { ...props, href, "data-track": trackingId };
124
- return Link && href != null ? /* @__PURE__ */ jsx(Link, { ...all, href, children }) : /* @__PURE__ */ jsx("a", { ...all, children });
125
- }
126
- var fetchPriorityHigh = React.version.startsWith("18.") ? { fetchpriority: "high" } : { fetchPriority: "high" };
127
- function TemplateImg({
128
- components,
129
- priority,
130
- ...image
131
- }) {
132
- const Image = components?.Image;
133
- if (Image) return /* @__PURE__ */ jsx(Image, { ...image, priority });
134
- return /* @__PURE__ */ jsx(
135
- "img",
136
- {
137
- ...image,
138
- alt: image.alt,
139
- loading: priority ? void 0 : "lazy",
140
- ...priority ? fetchPriorityHigh : {},
141
- decoding: "async"
142
- }
143
- );
144
- }
145
- function SectionHeading({
146
- eyebrow,
147
- title,
148
- description,
149
- as: Heading = "h2",
150
- size = "section",
151
- align = "start",
152
- tone = "default",
153
- titleId,
154
- className
155
- }) {
156
- if (!eyebrow && !title && !description) return null;
157
- return /* @__PURE__ */ jsxs(
158
- "div",
159
- {
160
- "data-slot": "section-heading",
161
- className: cn(
162
- "max-w-3xl",
163
- align === "center" && "mx-auto text-center",
164
- className
165
- ),
166
- children: [
167
- eyebrow && /* @__PURE__ */ jsx(
168
- "p",
169
- {
170
- className: cn(
171
- "mb-3 text-sm font-semibold tracking-wider uppercase",
172
- accentTextClass(tone)
173
- ),
174
- children: eyebrow
175
- }
176
- ),
177
- title && /* @__PURE__ */ jsx(
178
- Heading,
179
- {
180
- id: titleId,
181
- className: cn(
182
- "font-bold tracking-tight text-balance",
183
- headingTextClass(tone),
184
- size === "hero" ? "text-4xl sm:text-5xl lg:text-6xl" : "text-3xl sm:text-4xl"
185
- ),
186
- children: title
187
- }
188
- ),
189
- description && /* @__PURE__ */ jsx(
190
- "p",
191
- {
192
- className: cn(
193
- "mt-4 text-pretty",
194
- size === "hero" ? "text-lg sm:text-xl" : "text-lg",
195
- mutedTextClass(tone)
196
- ),
197
- children: description
198
- }
199
- )
200
- ]
201
- }
202
- );
203
- }
204
- var SectionShell = React.forwardRef(
205
- ({
206
- eyebrow,
207
- title,
208
- description,
209
- tone = "default",
210
- align = "start",
211
- width = "wide",
212
- spacing = "default",
213
- className,
214
- children,
215
- components,
216
- ...rest
217
- }, ref) => {
218
- const titleId = React.useId();
219
- return /* @__PURE__ */ jsx(
220
- "section",
221
- {
222
- ref,
223
- "data-slot": "landing-section",
224
- "data-tone": tone,
225
- "aria-labelledby": title ? titleId : void 0,
226
- className: cn(
227
- spacing === "compact" ? "py-10 sm:py-14" : "py-16 sm:py-24",
228
- toneClass(tone),
229
- className
230
- ),
231
- ...rest,
232
- children: /* @__PURE__ */ jsxs("div", { className: containerClass(width), children: [
233
- /* @__PURE__ */ jsx(
234
- SectionHeading,
235
- {
236
- eyebrow,
237
- title,
238
- description,
239
- align,
240
- tone,
241
- titleId,
242
- className: cn(width === "narrow" && "max-w-none")
243
- }
244
- ),
245
- children
246
- ] })
247
- }
248
- );
249
- }
250
- );
251
- SectionShell.displayName = "SectionShell";
252
- function CtaLinks({
253
- primary,
254
- secondary,
255
- tone = "default",
256
- align = "start",
257
- className,
258
- components
259
- }) {
260
- if (!primary && !secondary) return null;
261
- const onBrand = tone === "brand";
262
- const wrap = "h-auto min-h-12 py-3 whitespace-normal text-center";
263
- return /* @__PURE__ */ jsxs(
264
- "div",
265
- {
266
- "data-slot": "cta-links",
267
- className: cn(
268
- "flex flex-col gap-3 sm:flex-row sm:flex-wrap",
269
- align === "center" && "sm:justify-center",
270
- className
271
- ),
272
- children: [
273
- primary && /* @__PURE__ */ jsxs(
274
- TemplateAnchor,
275
- {
276
- href: primary.href,
277
- trackingId: primary.trackingId,
278
- components,
279
- "data-slot": "cta-primary",
280
- className: cn(
281
- buttonVariants({ variant: "primary", size: "lg" }),
282
- wrap,
283
- onBrand && "text-primary-900 hover:bg-primary-50 active:bg-primary-100 bg-white"
284
- ),
285
- children: [
286
- primary.label,
287
- /* @__PURE__ */ jsx(ArrowRight, { "aria-hidden": "true", className: "size-5 rtl:-scale-x-100" })
288
- ]
289
- }
290
- ),
291
- secondary && /* @__PURE__ */ jsx(
292
- TemplateAnchor,
293
- {
294
- href: secondary.href,
295
- trackingId: secondary.trackingId,
296
- components,
297
- "data-slot": "cta-secondary",
298
- className: cn(
299
- buttonVariants({ variant: "outline", size: "lg" }),
300
- wrap,
301
- onBrand && "border-white/70 text-white hover:bg-white/10 hover:text-white dark:border-white/70 dark:text-white dark:hover:bg-white/10"
302
- ),
303
- children: secondary.label
304
- }
305
- )
306
- ]
307
- }
308
- );
309
- }
310
- function IconTile({
311
- name,
312
- icons,
313
- tone = "default",
314
- className
315
- }) {
316
- return /* @__PURE__ */ jsx(
317
- "span",
318
- {
319
- "data-slot": "icon-tile",
320
- className: cn(
321
- "inline-flex size-11 shrink-0 items-center justify-center rounded-xl",
322
- tone === "brand" ? "bg-white/10 text-white" : "bg-primary-100 text-primary-900 dark:bg-primary-900/60 dark:text-primary-200",
323
- className
324
- ),
325
- children: /* @__PURE__ */ jsx(TemplateIcon, { name, icons })
326
- }
327
- );
328
- }
329
10
  var cellClass = "px-3 py-3 sm:px-5 sm:py-4";
330
- var ComparisonSection = React.forwardRef(
11
+ var ComparisonSection = React5.forwardRef(
331
12
  ({
332
13
  columns,
333
14
  rows,
@@ -446,7 +127,7 @@ var ComparisonSection = React.forwardRef(
446
127
  }
447
128
  );
448
129
  ComparisonSection.displayName = "ComparisonSection";
449
- var CtaSection = React.forwardRef(
130
+ var CtaSection = React5.forwardRef(
450
131
  ({
451
132
  eyebrow,
452
133
  title,
@@ -461,7 +142,7 @@ var CtaSection = React.forwardRef(
461
142
  className,
462
143
  ...rest
463
144
  }, ref) => {
464
- const titleId = React.useId();
145
+ const titleId = React5.useId();
465
146
  const body = /* @__PURE__ */ jsxs(Fragment, { children: [
466
147
  /* @__PURE__ */ jsx(
467
148
  SectionHeading,
@@ -526,7 +207,7 @@ var CtaSection = React.forwardRef(
526
207
  }
527
208
  );
528
209
  CtaSection.displayName = "CtaSection";
529
- var FaqSection = React.forwardRef(
210
+ var FaqSection = React5.forwardRef(
530
211
  ({ items, tone = "default", align = "center", ...rest }, ref) => /* @__PURE__ */ jsx(
531
212
  SectionShell,
532
213
  {
@@ -585,7 +266,7 @@ var columnClass = {
585
266
  3: "lg:grid-cols-3",
586
267
  4: "lg:grid-cols-4"
587
268
  };
588
- var FeatureGridSection = React.forwardRef(
269
+ var FeatureGridSection = React5.forwardRef(
589
270
  ({
590
271
  features,
591
272
  columns = 3,
@@ -660,7 +341,7 @@ var FeatureGridSection = React.forwardRef(
660
341
  )
661
342
  );
662
343
  FeatureGridSection.displayName = "FeatureGridSection";
663
- var HeroSection = React.forwardRef(
344
+ var HeroSection = React5.forwardRef(
664
345
  ({
665
346
  eyebrow,
666
347
  title,
@@ -671,6 +352,8 @@ var HeroSection = React.forwardRef(
671
352
  secondaryCta,
672
353
  ctaNote,
673
354
  highlights,
355
+ meta,
356
+ logo,
674
357
  image,
675
358
  breadcrumbs,
676
359
  headingLevel = "h1",
@@ -679,7 +362,7 @@ var HeroSection = React.forwardRef(
679
362
  className,
680
363
  ...rest
681
364
  }, ref) => {
682
- const titleId = React.useId();
365
+ const titleId = React5.useId();
683
366
  const split = variant === "split" && !!image;
684
367
  const align = split ? "start" : "center";
685
368
  return /* @__PURE__ */ jsx(
@@ -739,6 +422,14 @@ var HeroSection = React.forwardRef(
739
422
  )
740
423
  }
741
424
  ),
425
+ logo && /* @__PURE__ */ jsx(
426
+ TemplateImg,
427
+ {
428
+ ...logo,
429
+ components,
430
+ className: "mb-6 h-12 w-auto"
431
+ }
432
+ ),
742
433
  /* @__PURE__ */ jsx(
743
434
  SectionHeading,
744
435
  {
@@ -752,6 +443,21 @@ var HeroSection = React.forwardRef(
752
443
  titleId
753
444
  }
754
445
  ),
446
+ meta && meta.length > 0 && /* @__PURE__ */ jsx(
447
+ "p",
448
+ {
449
+ "data-slot": "hero-meta",
450
+ className: cn(
451
+ "mt-6 flex flex-wrap gap-x-2 gap-y-1 text-sm font-medium",
452
+ mutedTextClass(tone),
453
+ !split && "justify-center"
454
+ ),
455
+ children: meta.map((item, i) => /* @__PURE__ */ jsxs(React5.Fragment, { children: [
456
+ i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
457
+ /* @__PURE__ */ jsx("span", { children: item })
458
+ ] }, item))
459
+ }
460
+ ),
755
461
  /* @__PURE__ */ jsx(
756
462
  CtaLinks,
757
463
  {
@@ -839,7 +545,7 @@ var controlClass = cn(
839
545
  inputVariants({ size: "md" }),
840
546
  "block h-auto py-2.5"
841
547
  );
842
- var LeadFormSection = React.forwardRef(
548
+ var LeadFormSection = React5.forwardRef(
843
549
  ({
844
550
  eyebrow,
845
551
  title,
@@ -851,13 +557,14 @@ var LeadFormSection = React.forwardRef(
851
557
  submitLabel = "Submit",
852
558
  note,
853
559
  layout = "split",
560
+ highlights,
854
561
  tone = "muted",
855
562
  submitTrackingId,
856
563
  components,
857
564
  className,
858
565
  ...rest
859
566
  }, ref) => {
860
- const baseId = React.useId();
567
+ const baseId = React5.useId();
861
568
  const titleId = `${baseId}-title`;
862
569
  const split = layout === "split";
863
570
  const resolvedAction = typeof action === "string" ? safeHref(action) : action;
@@ -879,17 +586,42 @@ var LeadFormSection = React.forwardRef(
879
586
  split && "grid items-start gap-12 lg:grid-cols-2"
880
587
  ),
881
588
  children: [
882
- /* @__PURE__ */ jsx(
883
- SectionHeading,
884
- {
885
- eyebrow,
886
- title,
887
- description,
888
- align: split ? "start" : "center",
889
- tone,
890
- titleId
891
- }
892
- ),
589
+ /* @__PURE__ */ jsxs("div", { children: [
590
+ /* @__PURE__ */ jsx(
591
+ SectionHeading,
592
+ {
593
+ eyebrow,
594
+ title,
595
+ description,
596
+ align: split ? "start" : "center",
597
+ tone,
598
+ titleId
599
+ }
600
+ ),
601
+ highlights && highlights.length > 0 && /* @__PURE__ */ jsx(
602
+ "ul",
603
+ {
604
+ className: cn(
605
+ "mt-6 space-y-2",
606
+ !split && "mx-auto w-fit",
607
+ mutedTextClass(tone)
608
+ ),
609
+ children: highlights.map((item) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2", children: [
610
+ /* @__PURE__ */ jsx(
611
+ CircleCheck,
612
+ {
613
+ "aria-hidden": "true",
614
+ className: cn(
615
+ "mt-0.5 size-4 shrink-0",
616
+ accentTextClass(tone)
617
+ )
618
+ }
619
+ ),
620
+ item
621
+ ] }, item))
622
+ }
623
+ )
624
+ ] }),
893
625
  /* @__PURE__ */ jsxs(
894
626
  "form",
895
627
  {
@@ -1024,7 +756,7 @@ function Logo({
1024
756
  }
1025
757
  ) : mark;
1026
758
  }
1027
- var LogoCloudSection = React.forwardRef(
759
+ var LogoCloudSection = React5.forwardRef(
1028
760
  ({
1029
761
  logos,
1030
762
  variant = "grid",
@@ -1073,7 +805,7 @@ var columnClass2 = [
1073
805
  "lg:grid-cols-3",
1074
806
  "lg:grid-cols-4"
1075
807
  ];
1076
- var PricingSection = React.forwardRef(
808
+ var PricingSection = React5.forwardRef(
1077
809
  ({ plans, note, tone = "default", align = "center", components, ...rest }, ref) => /* @__PURE__ */ jsxs(
1078
810
  SectionShell,
1079
811
  {
@@ -1183,7 +915,7 @@ var connectorInset = [
1183
915
  "inset-x-[16.667%]",
1184
916
  "inset-x-[12.5%]"
1185
917
  ];
1186
- var ProcessStepsSection = React.forwardRef(({ steps, icons, tone = "default", align = "center", ...rest }, ref) => {
918
+ var ProcessStepsSection = React5.forwardRef(({ steps, icons, tone = "default", align = "center", ...rest }, ref) => {
1187
919
  const columns = Math.min(steps.length, 4);
1188
920
  return /* @__PURE__ */ jsx(
1189
921
  SectionShell,
@@ -1246,7 +978,7 @@ var columnClass4 = {
1246
978
  3: "lg:grid-cols-3",
1247
979
  4: "lg:grid-cols-4"
1248
980
  };
1249
- var ResourceCardsSection = React.forwardRef(
981
+ var ResourceCardsSection = React5.forwardRef(
1250
982
  ({
1251
983
  items,
1252
984
  columns = 3,
@@ -1348,7 +1080,7 @@ var ResourceCardsSection = React.forwardRef(
1348
1080
  )
1349
1081
  );
1350
1082
  ResourceCardsSection.displayName = "ResourceCardsSection";
1351
- var SplitContentSection = React.forwardRef(
1083
+ var SplitContentSection = React5.forwardRef(
1352
1084
  ({
1353
1085
  eyebrow,
1354
1086
  title,
@@ -1364,7 +1096,7 @@ var SplitContentSection = React.forwardRef(
1364
1096
  className,
1365
1097
  ...rest
1366
1098
  }, ref) => {
1367
- const titleId = React.useId();
1099
+ const titleId = React5.useId();
1368
1100
  return /* @__PURE__ */ jsx(
1369
1101
  "section",
1370
1102
  {
@@ -1443,7 +1175,7 @@ var columnClass5 = [
1443
1175
  "lg:grid-cols-3",
1444
1176
  "lg:grid-cols-4"
1445
1177
  ];
1446
- var StatsSection = React.forwardRef(
1178
+ var StatsSection = React5.forwardRef(
1447
1179
  ({
1448
1180
  stats,
1449
1181
  variant = "plain",
@@ -1470,13 +1202,17 @@ var StatsSection = React.forwardRef(
1470
1202
  ),
1471
1203
  children: stats.map((stat) => {
1472
1204
  const Trend = stat.trend === "down" ? TrendingDown : TrendingUp;
1205
+ const ruled = variant === "ruled";
1206
+ const shown = typeof stat.value === "number" ? format.format(stat.value) : stat.value;
1207
+ const long = `${stat.prefix ?? ""}${shown}${stat.suffix ?? ""}`.length > 6;
1473
1208
  return /* @__PURE__ */ jsxs(
1474
1209
  "div",
1475
1210
  {
1476
1211
  className: cn(
1477
1212
  "flex flex-col-reverse gap-2",
1478
- align === "center" && "items-center text-center",
1479
- variant === "cards" && cn("rounded-2xl p-6", cardClass(tone))
1213
+ align === "center" && !ruled && "items-center text-center",
1214
+ variant === "cards" && cn("rounded-2xl p-6", cardClass(tone)),
1215
+ ruled && "border-accent/70 border-s-2 ps-5"
1480
1216
  ),
1481
1217
  children: [
1482
1218
  /* @__PURE__ */ jsxs("dt", { children: [
@@ -1493,13 +1229,14 @@ var StatsSection = React.forwardRef(
1493
1229
  "dd",
1494
1230
  {
1495
1231
  className: cn(
1496
- "flex items-center gap-2 text-4xl font-bold tracking-tight tabular-nums sm:text-5xl",
1232
+ "flex items-center gap-2 font-bold tracking-tight tabular-nums",
1233
+ ruled && long ? "text-2xl sm:text-3xl" : "text-4xl sm:text-5xl",
1497
1234
  tone === "brand" ? "text-white" : "text-primary-800 dark:text-primary-300"
1498
1235
  ),
1499
1236
  children: [
1500
1237
  stat.trend && /* @__PURE__ */ jsx(Trend, { "aria-hidden": "true", className: "size-7 shrink-0" }),
1501
1238
  stat.prefix,
1502
- typeof stat.value === "number" ? format.format(stat.value) : stat.value,
1239
+ shown,
1503
1240
  stat.suffix
1504
1241
  ]
1505
1242
  }
@@ -1516,7 +1253,7 @@ var StatsSection = React.forwardRef(
1516
1253
  }
1517
1254
  );
1518
1255
  StatsSection.displayName = "StatsSection";
1519
- var TestimonialSection = React.forwardRef(
1256
+ var TestimonialSection = React5.forwardRef(
1520
1257
  ({
1521
1258
  testimonials,
1522
1259
  variant = "cards",
@@ -1615,7 +1352,7 @@ var TestimonialSection = React.forwardRef(
1615
1352
  }
1616
1353
  );
1617
1354
  TestimonialSection.displayName = "TestimonialSection";
1618
- var VideoSection = React.forwardRef(
1355
+ var VideoSection = React5.forwardRef(
1619
1356
  ({ video, caption, tone = "default", align = "center", ...rest }, ref) => /* @__PURE__ */ jsx(
1620
1357
  SectionShell,
1621
1358
  {
@@ -1674,92 +1411,1050 @@ var VideoSection = React.forwardRef(
1674
1411
  )
1675
1412
  );
1676
1413
  VideoSection.displayName = "VideoSection";
1677
- var sections = {
1678
- hero: HeroSection,
1679
- logos: LogoCloudSection,
1680
- features: FeatureGridSection,
1681
- split: SplitContentSection,
1682
- process: ProcessStepsSection,
1683
- stats: StatsSection,
1684
- comparison: ComparisonSection,
1685
- pricing: PricingSection,
1686
- video: VideoSection,
1687
- testimonials: TestimonialSection,
1688
- resources: ResourceCardsSection,
1689
- faq: FaqSection,
1690
- "lead-form": LeadFormSection,
1691
- cta: CtaSection
1692
- };
1693
- var landingBlockTypes = [
1694
- ...Object.keys(sections),
1695
- "custom"
1696
- ];
1697
- var takesIcons = /* @__PURE__ */ new Set(["features", "process"]);
1698
- var LandingPage = React.forwardRef(
1699
- ({ blocks, icons, components, custom, actions, ...rest }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "landing-page", ...rest, children: blocks.map((block, i) => {
1700
- const key = block.id ?? `${block.type}-${i}`;
1701
- if (block.type === "custom") {
1702
- const Custom = ownProperty(custom, block.component);
1703
- return Custom ? /* @__PURE__ */ jsx(Custom, { id: block.id, ...block.props }, key) : null;
1704
- }
1705
- const { type, ...props } = block;
1706
- const Section = ownProperty(
1707
- sections,
1708
- type
1414
+ var BenchmarkTableSection = React5.forwardRef(
1415
+ ({
1416
+ columns,
1417
+ rows,
1418
+ rowHeader,
1419
+ caption,
1420
+ footnote,
1421
+ locale,
1422
+ tone = "default",
1423
+ components,
1424
+ title,
1425
+ ...rest
1426
+ }, ref) => {
1427
+ const formatters = columns.map(
1428
+ (col) => new Intl.NumberFormat(locale, col.format)
1709
1429
  );
1710
- if (!Section) return null;
1711
- const action = block.type === "lead-form" ? ownProperty(actions, block.action) ?? safeHref(block.action) : void 0;
1712
- if (block.type === "lead-form" && action == null) return null;
1713
- const data = { ...props };
1714
- delete data.children;
1715
- delete data.dangerouslySetInnerHTML;
1716
- return /* @__PURE__ */ jsx(
1717
- Section,
1430
+ const maxima = columns.map(
1431
+ (col) => col.bar ? Math.max(
1432
+ 1,
1433
+ ...rows.map((r) => {
1434
+ const v = r.values[col.key];
1435
+ return typeof v === "number" ? v : 0;
1436
+ })
1437
+ ) : 1
1438
+ );
1439
+ const cellBase = "px-4 py-3 tabular-nums";
1440
+ const stickyBg = tone === "brand" ? "bg-primary-900" : "bg-card";
1441
+ return /* @__PURE__ */ jsxs(
1442
+ SectionShell,
1718
1443
  {
1719
- ...data,
1444
+ ref,
1445
+ "data-slot": "benchmark-table-section",
1446
+ tone,
1447
+ title,
1720
1448
  components,
1721
- ...takesIcons.has(type) ? { icons } : {},
1722
- ...block.type === "lead-form" ? { action } : {}
1723
- },
1724
- key
1725
- );
1726
- }) })
1727
- );
1728
- LandingPage.displayName = "LandingPage";
1729
-
1730
- // src/components/LandingPage/presets.ts
1731
- var landingPresets = {
1732
- "vertical-hub": {
1733
- label: "Industry / vertical hub",
1734
- description: "One page per industry served: the sector problem, what the product does for it, proof, and a way in.",
1735
- sequence: [
1736
- "hero",
1737
- "logos",
1738
- "features",
1739
- "split",
1740
- "stats",
1741
- "process",
1742
- "testimonials",
1743
- "resources",
1744
- "faq",
1745
- "cta"
1746
- ],
1747
- required: ["hero", "features", "faq", "cta"]
1748
- },
1749
- "service-detail": {
1750
- label: "Service / product detail",
1751
- description: "One offering explained: what it is, how it works, how it compares, and how to start.",
1752
- sequence: [
1753
- "hero",
1754
- "features",
1755
- "video",
1756
- "process",
1757
- "comparison",
1758
- "pricing",
1759
- "stats",
1760
- "testimonials",
1761
- "faq",
1762
- "cta"
1449
+ ...rest,
1450
+ children: [
1451
+ /* @__PURE__ */ jsx(
1452
+ "div",
1453
+ {
1454
+ className: cn("mt-10 overflow-x-auto rounded-2xl", cardClass(tone)),
1455
+ children: /* @__PURE__ */ jsxs("table", { className: "divide-border min-w-full divide-y text-sm", children: [
1456
+ (caption ?? title) && /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption ?? title }),
1457
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
1458
+ /* @__PURE__ */ jsx(
1459
+ "th",
1460
+ {
1461
+ scope: "col",
1462
+ className: cn(
1463
+ "sticky start-0 z-10 px-4 py-3 text-start font-semibold",
1464
+ stickyBg
1465
+ ),
1466
+ children: rowHeader
1467
+ }
1468
+ ),
1469
+ columns.map((col) => /* @__PURE__ */ jsx(
1470
+ "th",
1471
+ {
1472
+ scope: "col",
1473
+ className: cn(
1474
+ "px-4 py-3 font-semibold whitespace-nowrap",
1475
+ col.bar ? "text-start" : "text-end",
1476
+ col.emphasis && "bg-primary-500/10"
1477
+ ),
1478
+ children: col.label
1479
+ },
1480
+ col.key
1481
+ ))
1482
+ ] }) }),
1483
+ /* @__PURE__ */ jsx("tbody", { className: "divide-border divide-y", children: rows.map((row) => /* @__PURE__ */ jsxs("tr", { children: [
1484
+ /* @__PURE__ */ jsxs(
1485
+ "th",
1486
+ {
1487
+ scope: "row",
1488
+ className: cn(
1489
+ "sticky start-0 z-10 px-4 py-3 text-start font-medium",
1490
+ stickyBg
1491
+ ),
1492
+ children: [
1493
+ row.href ? /* @__PURE__ */ jsx(
1494
+ TemplateAnchor,
1495
+ {
1496
+ href: row.href,
1497
+ components,
1498
+ className: cn(
1499
+ "underline-offset-2 hover:underline",
1500
+ accentTextClass(tone)
1501
+ ),
1502
+ children: row.label
1503
+ }
1504
+ ) : row.label,
1505
+ row.sublabel && /* @__PURE__ */ jsx(
1506
+ "span",
1507
+ {
1508
+ className: cn(
1509
+ "block text-xs font-normal",
1510
+ mutedTextClass(tone)
1511
+ ),
1512
+ children: row.sublabel
1513
+ }
1514
+ )
1515
+ ]
1516
+ }
1517
+ ),
1518
+ columns.map((col, c) => {
1519
+ const v = row.values[col.key];
1520
+ const shown = v == null ? "\u2014" : typeof v === "number" ? formatters[c].format(v) : v;
1521
+ return /* @__PURE__ */ jsx(
1522
+ "td",
1523
+ {
1524
+ className: cn(
1525
+ cellBase,
1526
+ col.bar ? "text-start" : "text-end whitespace-nowrap",
1527
+ col.emphasis && cn(
1528
+ "bg-primary-500/10 font-semibold",
1529
+ accentTextClass(tone)
1530
+ )
1531
+ ),
1532
+ children: col.bar && typeof v === "number" ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-3", children: [
1533
+ /* @__PURE__ */ jsx(
1534
+ "span",
1535
+ {
1536
+ "aria-hidden": "true",
1537
+ className: "bg-muted h-2 w-32 max-w-full flex-none overflow-hidden rounded-full",
1538
+ children: /* @__PURE__ */ jsx(
1539
+ "span",
1540
+ {
1541
+ className: "bg-primary-600 block h-full rounded-full",
1542
+ style: {
1543
+ width: `${Math.round(v / maxima[c] * 100)}%`
1544
+ }
1545
+ }
1546
+ )
1547
+ }
1548
+ ),
1549
+ shown
1550
+ ] }) : shown
1551
+ },
1552
+ col.key
1553
+ );
1554
+ })
1555
+ ] }, row.label)) })
1556
+ ] })
1557
+ }
1558
+ ),
1559
+ footnote && /* @__PURE__ */ jsx("p", { className: cn("mt-4 max-w-3xl text-sm", mutedTextClass(tone)), children: footnote })
1560
+ ]
1561
+ }
1562
+ );
1563
+ }
1564
+ );
1565
+ BenchmarkTableSection.displayName = "BenchmarkTableSection";
1566
+ var LinkGroupsSection = React5.forwardRef(({ groups, columns = 3, tone = "muted", components, ...rest }, ref) => /* @__PURE__ */ jsx(
1567
+ SectionShell,
1568
+ {
1569
+ ref,
1570
+ "data-slot": "link-groups-section",
1571
+ tone,
1572
+ components,
1573
+ ...rest,
1574
+ children: /* @__PURE__ */ jsx(
1575
+ "div",
1576
+ {
1577
+ className: cn(
1578
+ "mt-10 grid gap-6",
1579
+ columns === 3 ? "lg:grid-cols-3" : "md:grid-cols-2"
1580
+ ),
1581
+ children: groups.map((group) => /* @__PURE__ */ jsxs(
1582
+ "div",
1583
+ {
1584
+ className: cn("rounded-2xl p-6", cardClass(tone)),
1585
+ children: [
1586
+ /* @__PURE__ */ jsx("h3", { className: cn("text-lg font-semibold", headingTextClass(tone)), children: group.title }),
1587
+ group.description && /* @__PURE__ */ jsx("p", { className: cn("mt-1 text-sm", mutedTextClass(tone)), children: group.description }),
1588
+ /* @__PURE__ */ jsx("ul", { className: "mt-4 space-y-1", children: group.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
1589
+ TemplateAnchor,
1590
+ {
1591
+ href: link.href,
1592
+ trackingId: link.trackingId,
1593
+ components,
1594
+ className: cn(
1595
+ "group flex items-center justify-between gap-2 rounded-lg px-3 py-2 text-sm font-medium transition-colors",
1596
+ tone === "brand" ? "hover:bg-white/10" : "hover:bg-primary-500/10 hover:text-primary-800 dark:hover:text-primary-300"
1597
+ ),
1598
+ children: [
1599
+ /* @__PURE__ */ jsx("span", { children: link.label }),
1600
+ /* @__PURE__ */ jsx(
1601
+ ArrowRight,
1602
+ {
1603
+ "aria-hidden": "true",
1604
+ className: "size-4 flex-none opacity-50 group-hover:opacity-100 rtl:-scale-x-100"
1605
+ }
1606
+ )
1607
+ ]
1608
+ }
1609
+ ) }, link.href)) })
1610
+ ]
1611
+ },
1612
+ group.title
1613
+ ))
1614
+ }
1615
+ )
1616
+ }
1617
+ ));
1618
+ LinkGroupsSection.displayName = "LinkGroupsSection";
1619
+ var MetricListSection = React5.forwardRef(
1620
+ ({
1621
+ metrics,
1622
+ takeaway,
1623
+ positive,
1624
+ labels,
1625
+ tone = "default",
1626
+ components,
1627
+ ...rest
1628
+ }, ref) => {
1629
+ const measured = metrics.some((m) => m.value);
1630
+ return /* @__PURE__ */ jsxs(
1631
+ SectionShell,
1632
+ {
1633
+ ref,
1634
+ "data-slot": "metric-list-section",
1635
+ "data-measured": measured || void 0,
1636
+ tone,
1637
+ spacing: "compact",
1638
+ status: measured ? "live" : "maturing",
1639
+ components,
1640
+ ...rest,
1641
+ children: [
1642
+ !measured && /* @__PURE__ */ jsx("p", { className: cn("mt-3 text-xs font-medium", mutedTextClass(tone)), children: labels?.preview ?? "Roadmap preview" }),
1643
+ takeaway && /* @__PURE__ */ jsx(
1644
+ "p",
1645
+ {
1646
+ className: cn(
1647
+ "mt-6 max-w-3xl rounded-xl border p-4 text-sm leading-relaxed font-medium",
1648
+ tone === "brand" ? "border-white/20 bg-white/5" : "border-success/30 bg-success/10 text-foreground"
1649
+ ),
1650
+ children: takeaway
1651
+ }
1652
+ ),
1653
+ /* @__PURE__ */ jsx(
1654
+ "ul",
1655
+ {
1656
+ className: cn(
1657
+ "mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
1658
+ !measured && "border-border rounded-3xl border border-dashed p-4"
1659
+ ),
1660
+ children: metrics.map((metric) => /* @__PURE__ */ jsxs(
1661
+ "li",
1662
+ {
1663
+ className: cn(
1664
+ "rounded-xl p-5",
1665
+ cardClass(tone),
1666
+ positive && metric.value && "border-s-success border-s-4"
1667
+ ),
1668
+ children: [
1669
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
1670
+ /* @__PURE__ */ jsx(
1671
+ "h3",
1672
+ {
1673
+ className: cn(
1674
+ "min-w-0 text-sm font-semibold",
1675
+ headingTextClass(tone)
1676
+ ),
1677
+ children: metric.label
1678
+ }
1679
+ ),
1680
+ metric.unit && /* @__PURE__ */ jsx("span", { className: "bg-primary-500/10 flex-none rounded-full px-2 py-0.5 text-xs font-medium", children: metric.unit })
1681
+ ] }),
1682
+ metric.value && /* @__PURE__ */ jsx(
1683
+ "p",
1684
+ {
1685
+ className: cn(
1686
+ "mt-3 text-3xl font-bold tracking-tight tabular-nums",
1687
+ headingTextClass(tone)
1688
+ ),
1689
+ children: metric.value
1690
+ }
1691
+ ),
1692
+ /* @__PURE__ */ jsx(
1693
+ "p",
1694
+ {
1695
+ className: cn(
1696
+ "mt-2 text-sm leading-relaxed",
1697
+ mutedTextClass(tone)
1698
+ ),
1699
+ children: metric.description
1700
+ }
1701
+ )
1702
+ ]
1703
+ },
1704
+ metric.label
1705
+ ))
1706
+ }
1707
+ )
1708
+ ]
1709
+ }
1710
+ );
1711
+ }
1712
+ );
1713
+ MetricListSection.displayName = "MetricListSection";
1714
+ var PdfEmbedSection = React5.forwardRef(
1715
+ ({
1716
+ title,
1717
+ src,
1718
+ downloadAs,
1719
+ aspectRatio = 0.5625,
1720
+ notice,
1721
+ labels,
1722
+ tone = "muted",
1723
+ align = "center",
1724
+ components,
1725
+ ...rest
1726
+ }, ref) => {
1727
+ const pdfSrc = safeHref(src);
1728
+ const viewerSrc = pdfSrc && (pdfSrc.includes("#") ? pdfSrc : `${pdfSrc}#view=FitH`);
1729
+ const onBrand = tone === "brand";
1730
+ return /* @__PURE__ */ jsxs(
1731
+ SectionShell,
1732
+ {
1733
+ ref,
1734
+ "data-slot": "pdf-embed-section",
1735
+ title,
1736
+ tone,
1737
+ align,
1738
+ components,
1739
+ ...rest,
1740
+ children: [
1741
+ notice && /* @__PURE__ */ jsxs("p", { className: "border-primary-500/30 bg-primary-500/10 mx-auto mt-8 flex max-w-3xl items-start gap-3 rounded-xl border px-4 py-3 text-start text-sm", children: [
1742
+ /* @__PURE__ */ jsx(Info, { "aria-hidden": "true", className: "mt-0.5 size-5 flex-none" }),
1743
+ notice
1744
+ ] }),
1745
+ pdfSrc && /* @__PURE__ */ jsxs(Fragment, { children: [
1746
+ /* @__PURE__ */ jsx(
1747
+ "div",
1748
+ {
1749
+ className: "border-border bg-card relative mt-10 overflow-hidden rounded-2xl border shadow-lg",
1750
+ style: { paddingTop: `${(aspectRatio * 100).toFixed(4)}%` },
1751
+ children: /* @__PURE__ */ jsx(
1752
+ "object",
1753
+ {
1754
+ data: viewerSrc,
1755
+ type: "application/pdf",
1756
+ "aria-label": title,
1757
+ className: "absolute inset-0 size-full",
1758
+ children: /* @__PURE__ */ jsx(
1759
+ "p",
1760
+ {
1761
+ className: cn(
1762
+ "flex size-full items-center justify-center p-6 text-center text-sm",
1763
+ mutedTextClass("default")
1764
+ ),
1765
+ children: /* @__PURE__ */ jsx("a", { href: pdfSrc, className: "underline underline-offset-2", children: labels?.fallback ?? "Open the PDF" })
1766
+ }
1767
+ )
1768
+ }
1769
+ )
1770
+ }
1771
+ ),
1772
+ /* @__PURE__ */ jsxs(
1773
+ "div",
1774
+ {
1775
+ className: cn(
1776
+ "mt-6 flex flex-wrap gap-3",
1777
+ align === "center" && "justify-center"
1778
+ ),
1779
+ children: [
1780
+ /* @__PURE__ */ jsxs(
1781
+ "a",
1782
+ {
1783
+ href: pdfSrc,
1784
+ download: downloadAs ?? true,
1785
+ className: cn(
1786
+ buttonVariants({ variant: "primary" }),
1787
+ onBrand && "text-primary-900 hover:bg-primary-50 bg-white"
1788
+ ),
1789
+ children: [
1790
+ /* @__PURE__ */ jsx(Download, { "aria-hidden": "true", className: "size-4" }),
1791
+ labels?.download ?? "Download PDF"
1792
+ ]
1793
+ }
1794
+ ),
1795
+ /* @__PURE__ */ jsxs(
1796
+ "a",
1797
+ {
1798
+ href: pdfSrc,
1799
+ target: "_blank",
1800
+ rel: "noopener noreferrer",
1801
+ className: cn(
1802
+ buttonVariants({ variant: "outline" }),
1803
+ onBrand && "border-white/70 text-white hover:bg-white/10"
1804
+ ),
1805
+ children: [
1806
+ /* @__PURE__ */ jsx(ExternalLink, { "aria-hidden": "true", className: "size-4" }),
1807
+ labels?.open ?? "Open in new tab"
1808
+ ]
1809
+ }
1810
+ )
1811
+ ]
1812
+ }
1813
+ )
1814
+ ] })
1815
+ ]
1816
+ }
1817
+ );
1818
+ }
1819
+ );
1820
+ PdfEmbedSection.displayName = "PdfEmbedSection";
1821
+ var barClass = {
1822
+ primary: "bg-primary-600",
1823
+ accent: "bg-accent",
1824
+ success: "bg-success"
1825
+ };
1826
+ var RankedListSection = React5.forwardRef(
1827
+ ({
1828
+ lists,
1829
+ numbered,
1830
+ layout = "stacked",
1831
+ bar = "primary",
1832
+ locale,
1833
+ tone = "default",
1834
+ components,
1835
+ ...rest
1836
+ }, ref) => {
1837
+ const format = new Intl.NumberFormat(locale);
1838
+ return /* @__PURE__ */ jsx(
1839
+ SectionShell,
1840
+ {
1841
+ ref,
1842
+ "data-slot": "ranked-list-section",
1843
+ tone,
1844
+ components,
1845
+ ...rest,
1846
+ children: /* @__PURE__ */ jsx(
1847
+ "div",
1848
+ {
1849
+ className: cn(
1850
+ "mt-10 grid gap-6",
1851
+ lists.length > 1 && "lg:grid-cols-2"
1852
+ ),
1853
+ children: lists.map((list, l) => {
1854
+ const max = Math.max(1, ...list.items.map((i) => i.value));
1855
+ return /* @__PURE__ */ jsxs(
1856
+ "div",
1857
+ {
1858
+ className: cn(
1859
+ layout === "inline" && cn("rounded-2xl p-6", cardClass(tone))
1860
+ ),
1861
+ children: [
1862
+ list.title && /* @__PURE__ */ jsx(
1863
+ "h3",
1864
+ {
1865
+ className: cn(
1866
+ "mb-4 text-lg font-semibold",
1867
+ headingTextClass(tone)
1868
+ ),
1869
+ children: list.title
1870
+ }
1871
+ ),
1872
+ /* @__PURE__ */ jsx("ol", { className: "space-y-3", children: list.items.map((item, i) => {
1873
+ const label = item.href ? /* @__PURE__ */ jsx(
1874
+ TemplateAnchor,
1875
+ {
1876
+ href: item.href,
1877
+ components,
1878
+ className: cn(
1879
+ "font-medium underline-offset-2 hover:underline",
1880
+ accentTextClass(tone)
1881
+ ),
1882
+ children: item.label
1883
+ }
1884
+ ) : /* @__PURE__ */ jsx(
1885
+ "span",
1886
+ {
1887
+ className: cn("font-medium", headingTextClass(tone)),
1888
+ children: item.label
1889
+ }
1890
+ );
1891
+ const track = /* @__PURE__ */ jsx(
1892
+ "span",
1893
+ {
1894
+ "aria-hidden": "true",
1895
+ className: cn(
1896
+ "block h-2 overflow-hidden rounded-full",
1897
+ tone === "brand" ? "bg-white/10" : "bg-muted"
1898
+ ),
1899
+ children: /* @__PURE__ */ jsx(
1900
+ "span",
1901
+ {
1902
+ className: cn(
1903
+ "block h-full rounded-full",
1904
+ barClass[bar]
1905
+ ),
1906
+ style: {
1907
+ width: `${Math.round(item.value / max * 100)}%`
1908
+ }
1909
+ }
1910
+ )
1911
+ }
1912
+ );
1913
+ const rank = numbered && /* @__PURE__ */ jsx(
1914
+ "span",
1915
+ {
1916
+ className: cn(
1917
+ "text-sm font-semibold tabular-nums",
1918
+ mutedTextClass(tone)
1919
+ ),
1920
+ children: String(i + 1).padStart(2, "0")
1921
+ }
1922
+ );
1923
+ const value = item.display ?? format.format(item.value);
1924
+ return layout === "inline" ? /* @__PURE__ */ jsxs(
1925
+ "li",
1926
+ {
1927
+ className: "flex items-center gap-3 text-sm",
1928
+ children: [
1929
+ rank,
1930
+ /* @__PURE__ */ jsx("span", { className: "w-28 flex-none truncate sm:w-36", children: label }),
1931
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: track }),
1932
+ /* @__PURE__ */ jsx("span", { className: "w-20 flex-none text-end font-semibold tabular-nums", children: value })
1933
+ ]
1934
+ },
1935
+ item.label
1936
+ ) : /* @__PURE__ */ jsxs(
1937
+ "li",
1938
+ {
1939
+ className: cn("rounded-xl p-4", cardClass(tone)),
1940
+ children: [
1941
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
1942
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-3", children: [
1943
+ rank,
1944
+ label
1945
+ ] }),
1946
+ /* @__PURE__ */ jsxs("span", { className: cn("text-xs", mutedTextClass(tone)), children: [
1947
+ item.note ?? value,
1948
+ item.note && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
1949
+ ": ",
1950
+ value
1951
+ ] })
1952
+ ] })
1953
+ ] }),
1954
+ /* @__PURE__ */ jsx("span", { className: "mt-2 block", children: track })
1955
+ ]
1956
+ },
1957
+ item.label
1958
+ );
1959
+ }) })
1960
+ ]
1961
+ },
1962
+ list.title ?? l
1963
+ );
1964
+ })
1965
+ }
1966
+ )
1967
+ }
1968
+ );
1969
+ }
1970
+ );
1971
+ RankedListSection.displayName = "RankedListSection";
1972
+ var ReportByline = React5.forwardRef(
1973
+ ({
1974
+ authors,
1975
+ published,
1976
+ updated,
1977
+ labels,
1978
+ tone = "default",
1979
+ components,
1980
+ className,
1981
+ ...rest
1982
+ }, ref) => {
1983
+ const headingId = React5.useId();
1984
+ return /* @__PURE__ */ jsx(
1985
+ "section",
1986
+ {
1987
+ ref,
1988
+ "data-slot": "report-byline",
1989
+ "data-tone": tone,
1990
+ "aria-labelledby": headingId,
1991
+ className: cn(
1992
+ "border-border border-t py-8",
1993
+ toneClass(tone),
1994
+ className
1995
+ ),
1996
+ ...rest,
1997
+ children: /* @__PURE__ */ jsxs("div", { className: containerClass(), children: [
1998
+ /* @__PURE__ */ jsx("h2", { id: headingId, className: "sr-only", children: labels?.heading ?? "About the author" }),
1999
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-6", children: authors.map((author) => /* @__PURE__ */ jsxs(
2000
+ "li",
2001
+ {
2002
+ className: "flex flex-wrap items-center gap-4",
2003
+ children: [
2004
+ author.avatar && /* @__PURE__ */ jsx(
2005
+ TemplateImg,
2006
+ {
2007
+ ...author.avatar,
2008
+ width: author.avatar.width ?? 48,
2009
+ height: author.avatar.height ?? 48,
2010
+ components,
2011
+ className: "ring-border size-12 flex-none rounded-full object-cover ring-1"
2012
+ }
2013
+ ),
2014
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2015
+ /* @__PURE__ */ jsxs("p", { className: cn("text-sm", mutedTextClass(tone)), children: [
2016
+ labels?.by ?? "By",
2017
+ " ",
2018
+ author.href ? /* @__PURE__ */ jsx(
2019
+ TemplateAnchor,
2020
+ {
2021
+ href: author.href,
2022
+ components,
2023
+ className: cn(
2024
+ "font-semibold underline-offset-2 hover:underline",
2025
+ headingTextClass(tone)
2026
+ ),
2027
+ children: author.name
2028
+ }
2029
+ ) : /* @__PURE__ */ jsx(
2030
+ "span",
2031
+ {
2032
+ className: cn("font-semibold", headingTextClass(tone)),
2033
+ children: author.name
2034
+ }
2035
+ ),
2036
+ author.role && /* @__PURE__ */ jsxs("span", { children: [
2037
+ " \xB7 ",
2038
+ author.role
2039
+ ] })
2040
+ ] }),
2041
+ (published || updated) && /* @__PURE__ */ jsxs("p", { className: cn("text-sm", mutedTextClass(tone)), children: [
2042
+ published && `${labels?.published ?? "Published"} ${published}`,
2043
+ published && updated && " \xB7 ",
2044
+ updated && `${labels?.updated ?? "Updated"} ${updated}`
2045
+ ] })
2046
+ ] }),
2047
+ author.profiles && author.profiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "ms-auto flex flex-wrap gap-2", children: author.profiles.map((profile) => {
2048
+ const href = safeHref(profile.href);
2049
+ if (!href) return null;
2050
+ return /* @__PURE__ */ jsxs(
2051
+ "a",
2052
+ {
2053
+ href,
2054
+ target: "_blank",
2055
+ rel: "noopener noreferrer",
2056
+ "data-track": profile.trackingId,
2057
+ className: "border-border hover:border-primary-600 hover:text-primary-800 dark:hover:text-primary-300 inline-flex items-center rounded-full border px-3 py-1.5 text-sm font-medium",
2058
+ children: [
2059
+ /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
2060
+ author.name,
2061
+ " on "
2062
+ ] }),
2063
+ profile.label
2064
+ ]
2065
+ },
2066
+ profile.href
2067
+ );
2068
+ }) })
2069
+ ]
2070
+ },
2071
+ author.name
2072
+ )) })
2073
+ ] })
2074
+ }
2075
+ );
2076
+ }
2077
+ );
2078
+ ReportByline.displayName = "ReportByline";
2079
+ var ReportLegend = React5.forwardRef(
2080
+ ({
2081
+ entries,
2082
+ title = "How to read the data",
2083
+ tone = "muted",
2084
+ components,
2085
+ ...rest
2086
+ }, ref) => /* @__PURE__ */ jsx(
2087
+ SectionShell,
2088
+ {
2089
+ ref,
2090
+ "data-slot": "report-legend",
2091
+ title,
2092
+ tone,
2093
+ spacing: "compact",
2094
+ components,
2095
+ ...rest,
2096
+ children: /* @__PURE__ */ jsx("dl", { className: "mt-6 grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: entries.map((entry) => /* @__PURE__ */ jsxs(
2097
+ "div",
2098
+ {
2099
+ className: cn(
2100
+ "flex flex-col gap-2 rounded-xl p-4",
2101
+ cardClass(tone)
2102
+ ),
2103
+ children: [
2104
+ /* @__PURE__ */ jsx("dt", { children: /* @__PURE__ */ jsx(
2105
+ MetricStatusBadge,
2106
+ {
2107
+ status: entry.status,
2108
+ label: entry.label,
2109
+ onDark: tone === "brand"
2110
+ }
2111
+ ) }),
2112
+ /* @__PURE__ */ jsx("dd", { className: cn("text-sm leading-snug", mutedTextClass(tone)), children: entry.description })
2113
+ ]
2114
+ },
2115
+ entry.status
2116
+ )) })
2117
+ }
2118
+ )
2119
+ );
2120
+ ReportLegend.displayName = "ReportLegend";
2121
+ var ReportMethodology = React5.forwardRef(
2122
+ ({
2123
+ sources,
2124
+ citation,
2125
+ notes,
2126
+ resources,
2127
+ labels,
2128
+ tone = "muted",
2129
+ components,
2130
+ ...rest
2131
+ }, ref) => {
2132
+ const card = cn("rounded-2xl p-6", cardClass(tone));
2133
+ const subheading = cn(
2134
+ "text-sm font-semibold tracking-wide uppercase",
2135
+ mutedTextClass(tone)
2136
+ );
2137
+ return /* @__PURE__ */ jsxs(
2138
+ SectionShell,
2139
+ {
2140
+ ref,
2141
+ "data-slot": "report-methodology",
2142
+ tone,
2143
+ components,
2144
+ ...rest,
2145
+ children: [
2146
+ /* @__PURE__ */ jsx("dl", { className: "mt-10 grid gap-6 sm:grid-cols-2", children: sources.map((source) => /* @__PURE__ */ jsxs("div", { className: card, children: [
2147
+ /* @__PURE__ */ jsx("dt", { className: cn("font-semibold", headingTextClass(tone)), children: source.label }),
2148
+ /* @__PURE__ */ jsxs("dd", { className: cn("mt-2 text-sm", mutedTextClass(tone)), children: [
2149
+ source.description,
2150
+ safeHref(source.href) && /* @__PURE__ */ jsxs(Fragment, { children: [
2151
+ " ",
2152
+ /* @__PURE__ */ jsxs(
2153
+ "a",
2154
+ {
2155
+ href: safeHref(source.href),
2156
+ rel: "noopener noreferrer",
2157
+ className: cn(
2158
+ "font-medium underline underline-offset-2",
2159
+ accentTextClass(tone)
2160
+ ),
2161
+ children: [
2162
+ labels?.sourceLink ?? "Source",
2163
+ /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
2164
+ ": ",
2165
+ source.label
2166
+ ] })
2167
+ ]
2168
+ }
2169
+ )
2170
+ ] })
2171
+ ] })
2172
+ ] }, source.label)) }),
2173
+ citation && /* @__PURE__ */ jsxs("div", { className: cn(card, "mt-10 border-dashed"), children: [
2174
+ /* @__PURE__ */ jsx("h3", { className: subheading, children: labels?.citation ?? "How to cite this report" }),
2175
+ /* @__PURE__ */ jsx("p", { className: "mt-3 font-mono text-sm break-words select-all", children: citation })
2176
+ ] }),
2177
+ notes?.map((note) => /* @__PURE__ */ jsxs("div", { className: cn(card, "mt-6"), children: [
2178
+ /* @__PURE__ */ jsx("h3", { className: subheading, children: note.title }),
2179
+ /* @__PURE__ */ jsx("p", { className: cn("mt-3 max-w-3xl text-sm", mutedTextClass(tone)), children: note.body })
2180
+ ] }, note.title)),
2181
+ resources && /* @__PURE__ */ jsxs("div", { className: cn(card, "mt-6"), children: [
2182
+ /* @__PURE__ */ jsx("h3", { className: subheading, children: resources.title }),
2183
+ resources.description && /* @__PURE__ */ jsx("p", { className: cn("mt-3 max-w-3xl text-sm", mutedTextClass(tone)), children: resources.description }),
2184
+ /* @__PURE__ */ jsx("div", { className: "mt-4 flex flex-wrap gap-3", children: resources.links.map((link) => /* @__PURE__ */ jsx(
2185
+ TemplateAnchor,
2186
+ {
2187
+ href: link.href,
2188
+ trackingId: link.trackingId,
2189
+ components,
2190
+ className: cn(
2191
+ "border-border hover:border-primary-600 inline-flex items-center rounded-full border px-4 py-2 text-sm font-medium",
2192
+ accentTextClass(tone)
2193
+ ),
2194
+ children: link.label
2195
+ },
2196
+ link.href
2197
+ )) })
2198
+ ] })
2199
+ ]
2200
+ }
2201
+ );
2202
+ }
2203
+ );
2204
+ ReportMethodology.displayName = "ReportMethodology";
2205
+
2206
+ // src/components/TileCartogramSection/tiles.ts
2207
+ var grid = [
2208
+ ["AK", "Alaska", 0, 0],
2209
+ ["ME", "Maine", 0, 10],
2210
+ ["VT", "Vermont", 1, 9],
2211
+ ["NH", "New Hampshire", 1, 10],
2212
+ ["WA", "Washington", 2, 0],
2213
+ ["ID", "Idaho", 2, 1],
2214
+ ["MT", "Montana", 2, 2],
2215
+ ["ND", "North Dakota", 2, 3],
2216
+ ["MN", "Minnesota", 2, 4],
2217
+ ["IL", "Illinois", 2, 5],
2218
+ ["WI", "Wisconsin", 2, 6],
2219
+ ["MI", "Michigan", 2, 8],
2220
+ ["NY", "New York", 2, 9],
2221
+ ["MA", "Massachusetts", 2, 10],
2222
+ ["OR", "Oregon", 3, 0],
2223
+ ["NV", "Nevada", 3, 1],
2224
+ ["WY", "Wyoming", 3, 2],
2225
+ ["SD", "South Dakota", 3, 3],
2226
+ ["IA", "Iowa", 3, 4],
2227
+ ["IN", "Indiana", 3, 5],
2228
+ ["OH", "Ohio", 3, 6],
2229
+ ["PA", "Pennsylvania", 3, 7],
2230
+ ["NJ", "New Jersey", 3, 8],
2231
+ ["CT", "Connecticut", 3, 9],
2232
+ ["RI", "Rhode Island", 3, 10],
2233
+ ["CA", "California", 4, 0],
2234
+ ["UT", "Utah", 4, 1],
2235
+ ["CO", "Colorado", 4, 2],
2236
+ ["NE", "Nebraska", 4, 3],
2237
+ ["MO", "Missouri", 4, 4],
2238
+ ["KY", "Kentucky", 4, 5],
2239
+ ["WV", "West Virginia", 4, 6],
2240
+ ["VA", "Virginia", 4, 7],
2241
+ ["MD", "Maryland", 4, 8],
2242
+ ["DE", "Delaware", 4, 9],
2243
+ ["AZ", "Arizona", 5, 1],
2244
+ ["NM", "New Mexico", 5, 2],
2245
+ ["KS", "Kansas", 5, 3],
2246
+ ["AR", "Arkansas", 5, 4],
2247
+ ["TN", "Tennessee", 5, 5],
2248
+ ["NC", "North Carolina", 5, 6],
2249
+ ["SC", "South Carolina", 5, 7],
2250
+ ["DC", "District of Columbia", 5, 8],
2251
+ ["OK", "Oklahoma", 6, 3],
2252
+ ["LA", "Louisiana", 6, 4],
2253
+ ["MS", "Mississippi", 6, 5],
2254
+ ["AL", "Alabama", 6, 6],
2255
+ ["GA", "Georgia", 6, 7],
2256
+ ["HI", "Hawaii", 7, 0],
2257
+ ["TX", "Texas", 7, 3],
2258
+ ["FL", "Florida", 7, 7]
2259
+ ];
2260
+ var usStateTiles = grid.map(
2261
+ ([code, name, row, col]) => ({ code, name, row, col })
2262
+ );
2263
+ function quartileBuckets(values) {
2264
+ const sorted = Object.values(values).filter((v) => typeof v === "number").sort((a, b) => a - b);
2265
+ const q = (p) => sorted[Math.floor((sorted.length - 1) * p)];
2266
+ const out = {};
2267
+ for (const [code, v] of Object.entries(values)) {
2268
+ out[code] = typeof v !== "number" || sorted.length === 0 ? 0 : v <= q(0.25) ? 1 : v <= q(0.5) ? 2 : v <= q(0.75) ? 3 : 4;
2269
+ }
2270
+ return out;
2271
+ }
2272
+ var bucketClass = {
2273
+ 0: "bg-muted text-muted-foreground",
2274
+ 1: "bg-primary-600/20 text-foreground",
2275
+ 2: "bg-primary-600/40 text-foreground",
2276
+ 3: "bg-primary-800 text-white",
2277
+ 4: "bg-primary-950 text-white"
2278
+ };
2279
+ var TileCartogramSection = React5.forwardRef(
2280
+ ({
2281
+ values,
2282
+ legend,
2283
+ layout = usStateTiles,
2284
+ mapTitle,
2285
+ mapDescription,
2286
+ tone = "default",
2287
+ components,
2288
+ ...rest
2289
+ }, ref) => {
2290
+ const columns = Math.max(...layout.map((t) => t.col)) + 1;
2291
+ return /* @__PURE__ */ jsx(
2292
+ SectionShell,
2293
+ {
2294
+ ref,
2295
+ "data-slot": "tile-cartogram-section",
2296
+ tone,
2297
+ components,
2298
+ ...rest,
2299
+ children: /* @__PURE__ */ jsxs("div", { className: cn("mt-10 rounded-2xl p-6", cardClass(tone)), children: [
2300
+ mapTitle && /* @__PURE__ */ jsx("h3", { className: cn("text-lg font-semibold", headingTextClass(tone)), children: mapTitle }),
2301
+ mapDescription && /* @__PURE__ */ jsx("p", { className: cn("mt-1 text-sm", mutedTextClass(tone)), children: mapDescription }),
2302
+ /* @__PURE__ */ jsx(
2303
+ "ul",
2304
+ {
2305
+ className: "mx-auto mt-6 grid w-full max-w-xl gap-1",
2306
+ style: {
2307
+ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`
2308
+ },
2309
+ children: layout.map((tile) => {
2310
+ const value = values[tile.code];
2311
+ const bucket = value?.bucket ?? 0;
2312
+ return /* @__PURE__ */ jsxs(
2313
+ "li",
2314
+ {
2315
+ title: value?.detail ? `${tile.name}: ${value.detail}` : tile.name,
2316
+ style: {
2317
+ gridColumnStart: tile.col + 1,
2318
+ gridRowStart: tile.row + 1
2319
+ },
2320
+ className: cn(
2321
+ "flex aspect-square items-center justify-center rounded-md text-[9px] font-semibold sm:text-[11px]",
2322
+ bucketClass[bucket]
2323
+ ),
2324
+ children: [
2325
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: tile.code }),
2326
+ /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
2327
+ tile.name,
2328
+ value?.detail ? `: ${value.detail}` : ""
2329
+ ] })
2330
+ ]
2331
+ },
2332
+ tile.code
2333
+ );
2334
+ })
2335
+ }
2336
+ ),
2337
+ /* @__PURE__ */ jsx("ul", { className: "mt-6 flex flex-wrap items-center justify-center gap-x-4 gap-y-2 text-xs", children: legend.map((entry) => /* @__PURE__ */ jsxs(
2338
+ "li",
2339
+ {
2340
+ className: "inline-flex items-center gap-1.5",
2341
+ children: [
2342
+ /* @__PURE__ */ jsx(
2343
+ "span",
2344
+ {
2345
+ "aria-hidden": "true",
2346
+ className: cn(
2347
+ "ring-border size-3 rounded ring-1",
2348
+ bucketClass[entry.bucket]
2349
+ )
2350
+ }
2351
+ ),
2352
+ entry.label
2353
+ ]
2354
+ },
2355
+ entry.bucket
2356
+ )) })
2357
+ ] })
2358
+ }
2359
+ );
2360
+ }
2361
+ );
2362
+ TileCartogramSection.displayName = "TileCartogramSection";
2363
+ var sections = {
2364
+ hero: HeroSection,
2365
+ logos: LogoCloudSection,
2366
+ features: FeatureGridSection,
2367
+ split: SplitContentSection,
2368
+ process: ProcessStepsSection,
2369
+ stats: StatsSection,
2370
+ comparison: ComparisonSection,
2371
+ pricing: PricingSection,
2372
+ video: VideoSection,
2373
+ testimonials: TestimonialSection,
2374
+ resources: ResourceCardsSection,
2375
+ faq: FaqSection,
2376
+ "lead-form": LeadFormSection,
2377
+ cta: CtaSection,
2378
+ "report-legend": ReportLegend,
2379
+ "benchmark-table": BenchmarkTableSection,
2380
+ "ranked-list": RankedListSection,
2381
+ "tile-cartogram": TileCartogramSection,
2382
+ "metric-list": MetricListSection,
2383
+ methodology: ReportMethodology,
2384
+ byline: ReportByline,
2385
+ "link-groups": LinkGroupsSection,
2386
+ "pdf-embed": PdfEmbedSection
2387
+ };
2388
+ var landingBlockTypes = [
2389
+ ...Object.keys(sections),
2390
+ "custom"
2391
+ ];
2392
+ var takesIcons = /* @__PURE__ */ new Set(["features", "process"]);
2393
+ var LandingPage = React5.forwardRef(
2394
+ ({ blocks, icons, components, custom, actions, ...rest }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "landing-page", ...rest, children: blocks.map((block, i) => {
2395
+ const key = block.id ?? `${block.type}-${i}`;
2396
+ if (block.type === "custom") {
2397
+ const Custom = ownProperty(custom, block.component);
2398
+ return Custom ? /* @__PURE__ */ jsx(Custom, { id: block.id, ...block.props }, key) : null;
2399
+ }
2400
+ const { type, ...props } = block;
2401
+ const Section = ownProperty(
2402
+ sections,
2403
+ type
2404
+ );
2405
+ if (!Section) return null;
2406
+ const action = block.type === "lead-form" ? ownProperty(actions, block.action) ?? safeHref(block.action) : void 0;
2407
+ if (block.type === "lead-form" && action == null) return null;
2408
+ const data = { ...props };
2409
+ delete data.children;
2410
+ delete data.dangerouslySetInnerHTML;
2411
+ return /* @__PURE__ */ jsx(
2412
+ Section,
2413
+ {
2414
+ ...data,
2415
+ components,
2416
+ ...takesIcons.has(type) ? { icons } : {},
2417
+ ...block.type === "lead-form" ? { action } : {}
2418
+ },
2419
+ key
2420
+ );
2421
+ }) })
2422
+ );
2423
+ LandingPage.displayName = "LandingPage";
2424
+
2425
+ // src/components/LandingPage/presets.ts
2426
+ var landingPresets = {
2427
+ "vertical-hub": {
2428
+ label: "Industry / vertical hub",
2429
+ description: "One page per industry served: the sector problem, what the product does for it, proof, and a way in.",
2430
+ sequence: [
2431
+ "hero",
2432
+ "logos",
2433
+ "features",
2434
+ "split",
2435
+ "stats",
2436
+ "process",
2437
+ "testimonials",
2438
+ "resources",
2439
+ "faq",
2440
+ "cta"
2441
+ ],
2442
+ required: ["hero", "features", "faq", "cta"]
2443
+ },
2444
+ "service-detail": {
2445
+ label: "Service / product detail",
2446
+ description: "One offering explained: what it is, how it works, how it compares, and how to start.",
2447
+ sequence: [
2448
+ "hero",
2449
+ "features",
2450
+ "video",
2451
+ "process",
2452
+ "comparison",
2453
+ "pricing",
2454
+ "stats",
2455
+ "testimonials",
2456
+ "faq",
2457
+ "cta"
1763
2458
  ],
1764
2459
  required: ["hero", "features", "cta"]
1765
2460
  },
@@ -1802,14 +2497,38 @@ var landingPresets = {
1802
2497
  "cta"
1803
2498
  ],
1804
2499
  required: ["hero", "pricing", "faq"]
2500
+ },
2501
+ "benchmark-report": {
2502
+ label: "Benchmark report",
2503
+ description: "A published data report: headline findings, the figures with their provenance, how they were built, and who wrote it.",
2504
+ sequence: [
2505
+ "hero",
2506
+ "stats",
2507
+ "report-legend",
2508
+ "features",
2509
+ "benchmark-table",
2510
+ "tile-cartogram",
2511
+ "ranked-list",
2512
+ "metric-list",
2513
+ "methodology",
2514
+ "byline",
2515
+ "link-groups",
2516
+ "pdf-embed",
2517
+ "lead-form",
2518
+ "cta"
2519
+ ],
2520
+ required: ["hero", "methodology"]
1805
2521
  }
1806
2522
  };
1807
2523
  var headedItems = /* @__PURE__ */ new Set([
1808
2524
  "features",
1809
2525
  "process",
1810
2526
  "pricing",
1811
- "resources"
2527
+ "resources",
2528
+ "metric-list",
2529
+ "link-groups"
1812
2530
  ]);
2531
+ var rendersH3 = (b) => headedItems.has(b.type) || b.type === "ranked-list" && b.lists.some((l) => l.title) || b.type === "tile-cartogram" && !!b.mapTitle || b.type === "methodology" && !!(b.citation || b.notes?.length || b.resources);
1813
2532
  function validateLandingPage(blocks, preset) {
1814
2533
  const issues = [];
1815
2534
  const types = blocks.map((b) => b.type);
@@ -1874,12 +2593,24 @@ function validateLandingPage(blocks, preset) {
1874
2593
  });
1875
2594
  });
1876
2595
  blocks.forEach((b, index) => {
1877
- if (headedItems.has(b.type) && !("title" in b && b.title))
2596
+ if (rendersH3(b) && !("title" in b && b.title))
1878
2597
  issues.push({
1879
2598
  severity: "warning",
1880
2599
  index,
1881
2600
  message: `"${b.type}" has no title, so its h3 item titles skip the h2 level.`
1882
2601
  });
2602
+ if (b.type === "benchmark-table") {
2603
+ const keys = new Set(b.columns.map((c) => c.key));
2604
+ b.rows.forEach((row) => {
2605
+ const unknown = Object.keys(row.values).filter((k) => !keys.has(k));
2606
+ if (unknown.length)
2607
+ issues.push({
2608
+ severity: "warning",
2609
+ index,
2610
+ message: `Benchmark row "${row.label}" has values for unknown columns: ${unknown.join(", ")}.`
2611
+ });
2612
+ });
2613
+ }
1883
2614
  if (b.type !== "comparison") return;
1884
2615
  b.rows.forEach((row, r) => {
1885
2616
  if (row.values.length !== b.columns.length)
@@ -1905,9 +2636,11 @@ function validateLandingPage(blocks, preset) {
1905
2636
  message: `Missing required "${type}" block for the ${spec.label} preset.`
1906
2637
  });
1907
2638
  let last = -1;
2639
+ const placed = /* @__PURE__ */ new Set();
1908
2640
  blocks.forEach((b, index) => {
1909
2641
  const rank = spec.sequence.indexOf(b.type);
1910
- if (rank === -1) return;
2642
+ if (rank === -1 || placed.has(b.type)) return;
2643
+ placed.add(b.type);
1911
2644
  if (rank < last)
1912
2645
  issues.push({
1913
2646
  severity: "warning",
@@ -1919,6 +2652,6 @@ function validateLandingPage(blocks, preset) {
1919
2652
  return issues;
1920
2653
  }
1921
2654
 
1922
- export { ComparisonSection, CtaSection, FaqSection, FeatureGridSection, HeroSection, LandingPage, LeadFormSection, LogoCloudSection, PricingSection, ProcessStepsSection, ResourceCardsSection, SectionHeading, SectionShell, SplitContentSection, StatsSection, TemplateIcon, TestimonialSection, VideoSection, defaultLeadFormFields, landingPresets, templateIcons, validateLandingPage };
1923
- //# sourceMappingURL=chunk-KHSFJTEX.js.map
1924
- //# sourceMappingURL=chunk-KHSFJTEX.js.map
2655
+ export { BenchmarkTableSection, ComparisonSection, CtaSection, FaqSection, FeatureGridSection, HeroSection, LandingPage, LeadFormSection, LinkGroupsSection, LogoCloudSection, MetricListSection, PdfEmbedSection, PricingSection, ProcessStepsSection, RankedListSection, ReportByline, ReportLegend, ReportMethodology, ResourceCardsSection, SplitContentSection, StatsSection, TestimonialSection, TileCartogramSection, VideoSection, defaultLeadFormFields, landingPresets, quartileBuckets, usStateTiles, validateLandingPage };
2656
+ //# sourceMappingURL=chunk-T4JYUICS.js.map
2657
+ //# sourceMappingURL=chunk-T4JYUICS.js.map