@mieweb/ui 0.10.0-dev.24 → 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
package/dist/deck.js ADDED
@@ -0,0 +1,3316 @@
1
+ import { TemplateAnchor, TemplateImg, TemplateIcon, safeHref } from './chunk-FBCDYTWM.js';
2
+ import './chunk-GVM6DTR5.js';
3
+ import { cn } from './chunk-TQONQSJO.js';
4
+ import './chunk-PX6F3LHL.js';
5
+ import * as React9 from 'react';
6
+ import { createPortal } from 'react-dom';
7
+ import { List, Printer, Minimize2, Maximize2, Play, ExternalLink, ChevronUp, ChevronDown, X, ArrowUp, ArrowDown, ChevronRight, Check, Copy, ArrowRight, TrendingUp, TrendingDown, Minus } from 'lucide-react';
8
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
+
10
+ var chrome = "mie-deck-chrome print:hidden";
11
+ var iconButton = "flex size-9 items-center justify-center rounded-lg border border-white/10 bg-white/5 text-white/70 backdrop-blur transition-colors hover:bg-white/10 hover:text-white focus-visible:ring-2 focus-visible:ring-accent focus-visible:outline-none";
12
+ var slideLabel = (s) => s.navLabel ?? ("title" in s ? s.title : void 0) ?? "";
13
+ function ProgressBar({ progress }) {
14
+ return /* @__PURE__ */ jsx(
15
+ "div",
16
+ {
17
+ className: cn(
18
+ chrome,
19
+ "pointer-events-none absolute inset-x-0 top-0 z-40 h-[3px] bg-white/5"
20
+ ),
21
+ children: /* @__PURE__ */ jsx(
22
+ "div",
23
+ {
24
+ className: "bg-accent h-full transition-[width] duration-500 ease-out",
25
+ style: { width: `${progress}%` }
26
+ }
27
+ )
28
+ }
29
+ );
30
+ }
31
+ function SlideCounter({
32
+ active,
33
+ total,
34
+ section
35
+ }) {
36
+ return /* @__PURE__ */ jsxs(
37
+ "div",
38
+ {
39
+ className: cn(
40
+ chrome,
41
+ "pointer-events-none absolute start-5 bottom-5 z-40 hidden select-none md:block"
42
+ ),
43
+ children: [
44
+ /* @__PURE__ */ jsxs("div", { className: "text-sm font-semibold text-white/80 tabular-nums", children: [
45
+ String(active + 1).padStart(2, "0"),
46
+ /* @__PURE__ */ jsxs("span", { className: "text-white/70", children: [
47
+ " ",
48
+ "/ ",
49
+ String(total).padStart(2, "0")
50
+ ] })
51
+ ] }),
52
+ section && /* @__PURE__ */ jsx("div", { className: "text-accent mt-0.5 text-[0.7rem] tracking-[0.18em] uppercase", children: section })
53
+ ]
54
+ }
55
+ );
56
+ }
57
+ function DotNav({
58
+ slides,
59
+ active,
60
+ goTo,
61
+ labels
62
+ }) {
63
+ return /* @__PURE__ */ jsx(
64
+ "nav",
65
+ {
66
+ "aria-label": labels.slideNavigation,
67
+ className: cn(
68
+ chrome,
69
+ "absolute end-3 top-1/2 z-40 hidden -translate-y-1/2 flex-col items-center gap-2 md:flex"
70
+ ),
71
+ children: slides.map((s, i) => /* @__PURE__ */ jsxs(
72
+ "button",
73
+ {
74
+ type: "button",
75
+ onClick: () => goTo(i),
76
+ "aria-label": labels.goToSlide(i + 1, slideLabel(s)),
77
+ "aria-current": i === active ? "true" : void 0,
78
+ className: "group relative flex size-4 items-center justify-center",
79
+ children: [
80
+ /* @__PURE__ */ jsx(
81
+ "span",
82
+ {
83
+ className: cn(
84
+ "block rounded-full transition-all duration-300",
85
+ i === active ? "bg-accent size-2.5" : "size-1.5 bg-white/30 group-hover:bg-white/60"
86
+ )
87
+ }
88
+ ),
89
+ /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute end-6 rounded-md border border-white/10 bg-neutral-900/95 px-2 py-1 text-xs whitespace-nowrap text-white opacity-0 shadow-lg transition-opacity group-hover:opacity-100 group-focus-visible:opacity-100", children: slideLabel(s) })
90
+ ]
91
+ },
92
+ i
93
+ ))
94
+ }
95
+ );
96
+ }
97
+ function Controls({
98
+ isFullscreen,
99
+ onToggleFullscreen,
100
+ onOpenOutline,
101
+ labels
102
+ }) {
103
+ return /* @__PURE__ */ jsxs(
104
+ "div",
105
+ {
106
+ className: cn(
107
+ chrome,
108
+ "absolute end-5 bottom-5 z-40 hidden items-center gap-2 md:flex"
109
+ ),
110
+ children: [
111
+ /* @__PURE__ */ jsx(
112
+ "button",
113
+ {
114
+ type: "button",
115
+ className: iconButton,
116
+ onClick: onOpenOutline,
117
+ "aria-label": labels.openOutline,
118
+ children: /* @__PURE__ */ jsx(List, { "aria-hidden": "true", className: "size-4" })
119
+ }
120
+ ),
121
+ /* @__PURE__ */ jsx(
122
+ "button",
123
+ {
124
+ type: "button",
125
+ className: iconButton,
126
+ onClick: () => window.print(),
127
+ "aria-label": labels.print,
128
+ children: /* @__PURE__ */ jsx(Printer, { "aria-hidden": "true", className: "size-4" })
129
+ }
130
+ ),
131
+ /* @__PURE__ */ jsx(
132
+ "button",
133
+ {
134
+ type: "button",
135
+ className: iconButton,
136
+ onClick: onToggleFullscreen,
137
+ "aria-label": isFullscreen ? labels.exitFullscreen : labels.enterFullscreen,
138
+ children: isFullscreen ? /* @__PURE__ */ jsx(Minimize2, { "aria-hidden": "true", className: "size-4" }) : /* @__PURE__ */ jsx(Maximize2, { "aria-hidden": "true", className: "size-4" })
139
+ }
140
+ )
141
+ ]
142
+ }
143
+ );
144
+ }
145
+ function Kbd({ children }) {
146
+ return /* @__PURE__ */ jsx("kbd", { className: "inline-flex min-w-5 items-center justify-center rounded border border-white/15 bg-white/5 px-1 py-0.5 text-[0.65rem] text-white/80", children });
147
+ }
148
+ function KeyboardHints({
149
+ pulse,
150
+ labels
151
+ }) {
152
+ const [visible, setVisible] = React9.useState(true);
153
+ React9.useEffect(() => {
154
+ setVisible(true);
155
+ const t = setTimeout(() => setVisible(false), 5e3);
156
+ return () => clearTimeout(t);
157
+ }, [pulse]);
158
+ return /* @__PURE__ */ jsxs(
159
+ "div",
160
+ {
161
+ "aria-hidden": "true",
162
+ className: cn(
163
+ chrome,
164
+ "pointer-events-none absolute bottom-5 left-1/2 z-40 hidden -translate-x-1/2 items-center gap-3 rounded-full border border-white/10 bg-neutral-900/80 px-4 py-1.5 text-xs text-white/70 backdrop-blur transition-opacity duration-500 select-none md:flex",
165
+ visible ? "opacity-100" : "opacity-0"
166
+ ),
167
+ children: [
168
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
169
+ /* @__PURE__ */ jsx(Kbd, { children: "\u2191" }),
170
+ /* @__PURE__ */ jsx(Kbd, { children: "\u2193" }),
171
+ " ",
172
+ labels.navigateHint
173
+ ] }),
174
+ /* @__PURE__ */ jsx("span", { className: "text-white/20", children: "\xB7" }),
175
+ /* @__PURE__ */ jsxs("span", { children: [
176
+ /* @__PURE__ */ jsx(Kbd, { children: "F" }),
177
+ " ",
178
+ labels.fullscreenHint
179
+ ] }),
180
+ /* @__PURE__ */ jsx("span", { className: "text-white/20", children: "\xB7" }),
181
+ /* @__PURE__ */ jsxs("span", { children: [
182
+ /* @__PURE__ */ jsx(Kbd, { children: "?" }),
183
+ " ",
184
+ labels.helpHint
185
+ ] })
186
+ ]
187
+ }
188
+ );
189
+ }
190
+ function MobileNav({
191
+ active,
192
+ total,
193
+ onPrev,
194
+ onNext,
195
+ onOpenOutline,
196
+ labels
197
+ }) {
198
+ const btn = "flex size-10 items-center justify-center rounded-full text-white/80 transition-colors hover:bg-white/10 disabled:opacity-30";
199
+ return /* @__PURE__ */ jsxs(
200
+ "div",
201
+ {
202
+ className: cn(
203
+ chrome,
204
+ "absolute inset-x-0 bottom-0 z-40 flex items-center justify-between border-t border-white/10 bg-neutral-950/90 px-3 py-2 pb-[max(0.5rem,env(safe-area-inset-bottom))] backdrop-blur md:hidden"
205
+ ),
206
+ children: [
207
+ /* @__PURE__ */ jsx(
208
+ "button",
209
+ {
210
+ type: "button",
211
+ className: btn,
212
+ onClick: onPrev,
213
+ disabled: active === 0,
214
+ "aria-label": labels.previous,
215
+ children: /* @__PURE__ */ jsx(ChevronUp, { "aria-hidden": "true", className: "size-5" })
216
+ }
217
+ ),
218
+ /* @__PURE__ */ jsxs(
219
+ "button",
220
+ {
221
+ type: "button",
222
+ onClick: onOpenOutline,
223
+ className: "flex items-center gap-2 rounded-full px-4 py-1.5 text-sm font-semibold text-white/80 tabular-nums",
224
+ "aria-label": labels.openOutline,
225
+ children: [
226
+ /* @__PURE__ */ jsx(List, { "aria-hidden": "true", className: "text-accent size-4" }),
227
+ active + 1,
228
+ " / ",
229
+ total
230
+ ]
231
+ }
232
+ ),
233
+ /* @__PURE__ */ jsx(
234
+ "button",
235
+ {
236
+ type: "button",
237
+ className: btn,
238
+ onClick: onNext,
239
+ disabled: active === total - 1,
240
+ "aria-label": labels.next,
241
+ children: /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": "true", className: "size-5" })
242
+ }
243
+ )
244
+ ]
245
+ }
246
+ );
247
+ }
248
+ function OutlineDialog({
249
+ open,
250
+ onClose,
251
+ slides,
252
+ active,
253
+ goTo,
254
+ labels
255
+ }) {
256
+ const panelRef = React9.useRef(null);
257
+ const titleId = React9.useId();
258
+ React9.useEffect(() => {
259
+ if (!open) return;
260
+ const previous = document.activeElement;
261
+ const panel = panelRef.current;
262
+ const focusables = () => Array.from(
263
+ panel?.querySelectorAll("button:not([disabled])") ?? []
264
+ );
265
+ (focusables()[1] ?? focusables()[0])?.focus();
266
+ const onKey = (e) => {
267
+ if (e.key === "Escape") {
268
+ e.preventDefault();
269
+ onClose();
270
+ return;
271
+ }
272
+ if (e.key !== "Tab") return;
273
+ const items = focusables();
274
+ const first = items[0];
275
+ const last = items[items.length - 1];
276
+ if (e.shiftKey && document.activeElement === first) {
277
+ e.preventDefault();
278
+ last?.focus();
279
+ } else if (!e.shiftKey && document.activeElement === last) {
280
+ e.preventDefault();
281
+ first?.focus();
282
+ }
283
+ };
284
+ document.addEventListener("keydown", onKey, true);
285
+ return () => {
286
+ document.removeEventListener("keydown", onKey, true);
287
+ previous?.focus?.();
288
+ };
289
+ }, [open, onClose]);
290
+ if (!open || typeof document === "undefined") return null;
291
+ return createPortal(
292
+ /* @__PURE__ */ jsxs(
293
+ "div",
294
+ {
295
+ ref: panelRef,
296
+ role: "dialog",
297
+ "aria-modal": "true",
298
+ "aria-labelledby": titleId,
299
+ className: "mie-deck-chrome fixed inset-0 z-[80] flex flex-col bg-neutral-950/95 text-white backdrop-blur-md",
300
+ children: [
301
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-white/10 px-5 py-4", children: [
302
+ /* @__PURE__ */ jsx("h2", { id: titleId, className: "text-lg font-bold text-white", children: labels.outline }),
303
+ /* @__PURE__ */ jsx(
304
+ "button",
305
+ {
306
+ type: "button",
307
+ onClick: onClose,
308
+ "aria-label": labels.closeOutline,
309
+ className: iconButton,
310
+ children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true", className: "size-5" })
311
+ }
312
+ )
313
+ ] }),
314
+ /* @__PURE__ */ jsx("ol", { className: "flex-1 overflow-y-auto px-3 py-3", children: slides.map((s, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
315
+ "button",
316
+ {
317
+ type: "button",
318
+ onClick: () => {
319
+ goTo(i);
320
+ onClose();
321
+ },
322
+ "aria-current": i === active ? "true" : void 0,
323
+ className: cn(
324
+ "flex w-full items-baseline gap-3 rounded-lg px-4 py-3 text-start transition-colors",
325
+ i === active ? "bg-accent/15" : "hover:bg-white/5"
326
+ ),
327
+ children: [
328
+ /* @__PURE__ */ jsx("span", { className: "text-accent text-sm font-semibold tabular-nums", children: String(i + 1).padStart(2, "0") }),
329
+ /* @__PURE__ */ jsx("span", { className: i === active ? "text-white" : "text-white/75", children: slideLabel(s) })
330
+ ]
331
+ }
332
+ ) }, i)) })
333
+ ]
334
+ }
335
+ ),
336
+ document.body
337
+ );
338
+ }
339
+
340
+ // src/components/Deck/tones.ts
341
+ var dark = {
342
+ isLight: false,
343
+ text: "text-white",
344
+ muted: "text-white/70",
345
+ hairline: "border-white/10",
346
+ card: "bg-white/5"
347
+ };
348
+ var TONES = {
349
+ brand: {
350
+ ...dark,
351
+ surface: "bg-gradient-to-br from-primary-900 via-primary-950 to-primary-950"
352
+ },
353
+ deep: {
354
+ ...dark,
355
+ surface: "bg-gradient-to-b from-neutral-900 to-neutral-950"
356
+ },
357
+ ink: { ...dark, surface: "bg-neutral-950" },
358
+ glow: {
359
+ ...dark,
360
+ surface: "bg-gradient-to-br from-primary-950 via-primary-800 to-accent/70"
361
+ },
362
+ light: {
363
+ isLight: true,
364
+ surface: "bg-white",
365
+ text: "text-neutral-900",
366
+ muted: "text-neutral-600",
367
+ hairline: "border-neutral-200",
368
+ card: "bg-neutral-50"
369
+ }
370
+ };
371
+ var onDark = {
372
+ primary: {
373
+ text: "text-primary-300",
374
+ soft: "bg-primary-400/15",
375
+ border: "border-primary-400/30",
376
+ fill: "bg-primary-400",
377
+ svgFill: "fill-primary-400",
378
+ svgStroke: "stroke-primary-400"
379
+ },
380
+ secondary: {
381
+ text: "text-secondary-300",
382
+ soft: "bg-secondary-400/15",
383
+ border: "border-secondary-400/30",
384
+ fill: "bg-secondary-400",
385
+ svgFill: "fill-secondary-400",
386
+ svgStroke: "stroke-secondary-400"
387
+ },
388
+ accent: {
389
+ text: "text-accent",
390
+ soft: "bg-accent/15",
391
+ border: "border-accent/30",
392
+ fill: "bg-accent",
393
+ svgFill: "fill-accent",
394
+ svgStroke: "stroke-accent"
395
+ },
396
+ success: {
397
+ text: "text-success",
398
+ soft: "bg-success/15",
399
+ border: "border-success/30",
400
+ fill: "bg-success",
401
+ svgFill: "fill-success",
402
+ svgStroke: "stroke-success"
403
+ },
404
+ warning: {
405
+ text: "text-warning",
406
+ soft: "bg-warning/15",
407
+ border: "border-warning/30",
408
+ fill: "bg-warning",
409
+ svgFill: "fill-warning",
410
+ svgStroke: "stroke-warning"
411
+ },
412
+ danger: {
413
+ text: "text-destructive",
414
+ soft: "bg-destructive/15",
415
+ border: "border-destructive/30",
416
+ fill: "bg-destructive",
417
+ svgFill: "fill-destructive",
418
+ svgStroke: "stroke-destructive"
419
+ }
420
+ };
421
+ var lightText = {
422
+ primary: "text-primary-800",
423
+ secondary: "text-secondary-800",
424
+ accent: "text-neutral-900",
425
+ success: "text-neutral-900",
426
+ warning: "text-neutral-900",
427
+ danger: "text-destructive"
428
+ };
429
+ function accent(name = "accent", isLight = false) {
430
+ const spec = onDark[name];
431
+ return isLight ? { ...spec, text: lightText[name] } : spec;
432
+ }
433
+ var toneOf = (slide, fallback) => TONES[slide.tone ?? fallback];
434
+ var ACCENT_CYCLE = [
435
+ "accent",
436
+ "primary",
437
+ "secondary",
438
+ "success",
439
+ "warning"
440
+ ];
441
+
442
+ // src/components/Deck/DeckContext.tsx
443
+ var DeckContext = React9.createContext(null);
444
+ var DeckProvider = DeckContext.Provider;
445
+ function useDeck() {
446
+ const ctx = React9.useContext(DeckContext);
447
+ if (!ctx) throw new Error("Slide renderers must be rendered inside <Deck>.");
448
+ return ctx;
449
+ }
450
+ var ToneContext = React9.createContext(TONES.brand);
451
+ var useTone = () => React9.useContext(ToneContext);
452
+
453
+ // src/components/Deck/labels.ts
454
+ var defaultDeckLabels = {
455
+ presentation: "slide presentation",
456
+ slide: "slide",
457
+ slideNavigation: "Slide navigation",
458
+ goToSlide: (n, title) => `Go to slide ${n}${title ? `: ${title}` : ""}`,
459
+ outline: "Slides",
460
+ openOutline: "Open slide outline",
461
+ closeOutline: "Close outline",
462
+ print: "Print or save as PDF",
463
+ enterFullscreen: "Enter fullscreen",
464
+ exitFullscreen: "Exit fullscreen",
465
+ previous: "Previous slide",
466
+ next: "Next slide",
467
+ navigateHint: "Navigate",
468
+ fullscreenHint: "Fullscreen",
469
+ helpHint: "Help",
470
+ copy: "Copy link",
471
+ copied: "Copied",
472
+ statusNow: "Now",
473
+ statusNext: "Next",
474
+ statusLater: "Later",
475
+ watchVideo: "Watch the video",
476
+ lines: "Lines",
477
+ bars: "Bars",
478
+ more: (n) => `Show ${n} more`,
479
+ less: "Show less"
480
+ };
481
+ function reveal(i = 0) {
482
+ return {
483
+ className: "mie-deck-reveal",
484
+ style: { "--mie-reveal-i": i }
485
+ };
486
+ }
487
+ function Eyebrow({
488
+ children,
489
+ className
490
+ }) {
491
+ const tone = useTone();
492
+ const r = reveal(0);
493
+ return /* @__PURE__ */ jsx(
494
+ "p",
495
+ {
496
+ className: cn(
497
+ r.className,
498
+ "mb-4 text-xs font-semibold tracking-[0.2em] uppercase",
499
+ accent("accent", tone.isLight).text,
500
+ className
501
+ ),
502
+ style: r.style,
503
+ children
504
+ }
505
+ );
506
+ }
507
+ function SlideTitle({
508
+ children,
509
+ className,
510
+ size = "md"
511
+ }) {
512
+ const tone = useTone();
513
+ const r = reveal(1);
514
+ return /* @__PURE__ */ jsx(
515
+ "h2",
516
+ {
517
+ className: cn(
518
+ r.className,
519
+ "font-bold tracking-tight text-balance",
520
+ tone.text,
521
+ size === "xl" ? "text-5xl sm:text-6xl lg:text-7xl" : size === "lg" ? "text-4xl sm:text-5xl lg:text-6xl" : "text-3xl sm:text-4xl lg:text-5xl",
522
+ className
523
+ ),
524
+ style: r.style,
525
+ children
526
+ }
527
+ );
528
+ }
529
+ function Subtitle({
530
+ children,
531
+ className
532
+ }) {
533
+ const tone = useTone();
534
+ const r = reveal(2);
535
+ return /* @__PURE__ */ jsx(
536
+ "p",
537
+ {
538
+ className: cn(
539
+ r.className,
540
+ "mt-4 max-w-2xl text-base leading-relaxed text-pretty sm:text-lg",
541
+ tone.muted,
542
+ className
543
+ ),
544
+ style: r.style,
545
+ children
546
+ }
547
+ );
548
+ }
549
+ function SlideHeader({
550
+ eyebrow,
551
+ title,
552
+ subtitle,
553
+ center
554
+ }) {
555
+ return /* @__PURE__ */ jsxs("div", { className: cn(center && "mx-auto text-center"), children: [
556
+ eyebrow && /* @__PURE__ */ jsx(Eyebrow, { children: eyebrow }),
557
+ /* @__PURE__ */ jsx(SlideTitle, { children: title }),
558
+ subtitle && /* @__PURE__ */ jsx(Subtitle, { className: cn(center && "mx-auto"), children: subtitle })
559
+ ] });
560
+ }
561
+ function splitFigure(value) {
562
+ const start = value.search(/\d/);
563
+ if (start === -1) return null;
564
+ let end = start;
565
+ while (end < value.length && /[\d,.]/.test(value[end])) end += 1;
566
+ return [value.slice(0, start), value.slice(start, end), value.slice(end)];
567
+ }
568
+ function CountUp({
569
+ value,
570
+ duration = 1400
571
+ }) {
572
+ const ref = React9.useRef(null);
573
+ const match = splitFigure(value);
574
+ React9.useEffect(() => {
575
+ const el = ref.current;
576
+ if (!el || !match) return;
577
+ if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return;
578
+ const [prefix, digits, suffix] = match;
579
+ const target = parseFloat(digits.replace(/,/g, ""));
580
+ if (Number.isNaN(target)) return;
581
+ const decimals = digits.split(".")[1]?.length ?? 0;
582
+ const grouped = digits.includes(",");
583
+ const render = (n) => {
584
+ let out = n.toFixed(decimals);
585
+ if (grouped) {
586
+ const [whole, frac] = out.split(".");
587
+ out = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (frac ? `.${frac}` : "");
588
+ }
589
+ el.textContent = `${prefix}${out}${suffix}`;
590
+ };
591
+ render(0);
592
+ let frame = 0;
593
+ const observer = new IntersectionObserver(
594
+ ([entry]) => {
595
+ if (!entry.isIntersecting) return;
596
+ observer.disconnect();
597
+ const start = performance.now();
598
+ const tick = (now) => {
599
+ const t = Math.min(1, (now - start) / duration);
600
+ render(target * (1 - Math.pow(1 - t, 3)));
601
+ if (t < 1) frame = requestAnimationFrame(tick);
602
+ else el.textContent = value;
603
+ };
604
+ frame = requestAnimationFrame(tick);
605
+ },
606
+ { threshold: 0.1 }
607
+ );
608
+ observer.observe(el);
609
+ return () => {
610
+ observer.disconnect();
611
+ cancelAnimationFrame(frame);
612
+ el.textContent = value;
613
+ };
614
+ }, [value, duration]);
615
+ return /* @__PURE__ */ jsx("span", { ref, className: "tabular-nums", children: value });
616
+ }
617
+ function DeckIcon({
618
+ name,
619
+ className
620
+ }) {
621
+ const { icons } = useDeck();
622
+ if (!name) return null;
623
+ return /* @__PURE__ */ jsx(TemplateIcon, { name, icons, className });
624
+ }
625
+ function IconChip({
626
+ icon,
627
+ accent: accent2 = "accent"
628
+ }) {
629
+ const tone = useTone();
630
+ if (!icon) return null;
631
+ const a = accent(accent2, tone.isLight);
632
+ return /* @__PURE__ */ jsx(
633
+ "span",
634
+ {
635
+ className: cn(
636
+ "inline-flex size-11 items-center justify-center rounded-xl border",
637
+ a.soft,
638
+ a.border,
639
+ a.text
640
+ ),
641
+ children: /* @__PURE__ */ jsx(DeckIcon, { name: icon })
642
+ }
643
+ );
644
+ }
645
+ function Bullet({
646
+ item,
647
+ depth = 0
648
+ }) {
649
+ const tone = useTone();
650
+ const a = accent("accent", tone.isLight);
651
+ const b = typeof item === "string" ? { text: item } : item;
652
+ return /* @__PURE__ */ jsxs("li", { className: cn("flex flex-col", depth > 0 && "ms-5 sm:ms-7"), children: [
653
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
654
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("mt-2 flex-none", a.text), children: b.icon ? /* @__PURE__ */ jsx(DeckIcon, { name: b.icon, className: "size-[1.1em]" }) : /* @__PURE__ */ jsx(
655
+ "span",
656
+ {
657
+ className: cn(
658
+ "block rounded-full",
659
+ depth === 0 ? cn("size-1.5", a.fill) : "size-1 bg-current opacity-60"
660
+ )
661
+ }
662
+ ) }),
663
+ /* @__PURE__ */ jsxs(
664
+ "span",
665
+ {
666
+ className: cn(
667
+ "leading-snug",
668
+ depth === 0 ? cn("text-lg sm:text-xl", tone.text) : cn("text-base", tone.muted)
669
+ ),
670
+ children: [
671
+ b.lead && /* @__PURE__ */ jsxs("span", { className: cn("font-semibold", a.text), children: [
672
+ b.lead,
673
+ " "
674
+ ] }),
675
+ b.text
676
+ ]
677
+ }
678
+ )
679
+ ] }),
680
+ b.children && b.children.length > 0 && /* @__PURE__ */ jsx("ul", { className: "mt-2 flex flex-col gap-2", children: b.children.map((child, i) => /* @__PURE__ */ jsx(Bullet, { item: child, depth: depth + 1 }, i)) })
681
+ ] });
682
+ }
683
+ function SourceLink({
684
+ source,
685
+ className
686
+ }) {
687
+ const tone = useTone();
688
+ const href = safeHref(source.url);
689
+ if (!href)
690
+ return /* @__PURE__ */ jsx("span", { className: cn("text-xs", tone.muted, className), children: source.label });
691
+ return /* @__PURE__ */ jsxs(
692
+ "a",
693
+ {
694
+ href,
695
+ target: "_blank",
696
+ rel: "noopener noreferrer",
697
+ className: cn(
698
+ "inline-flex items-center gap-1 text-xs underline underline-offset-2 hover:opacity-100",
699
+ tone.muted,
700
+ className
701
+ ),
702
+ children: [
703
+ source.label,
704
+ /* @__PURE__ */ jsx(ExternalLink, { "aria-hidden": "true", className: "size-3" })
705
+ ]
706
+ }
707
+ );
708
+ }
709
+ function HighlightFigure({
710
+ value,
711
+ label,
712
+ size = "md"
713
+ }) {
714
+ const tone = useTone();
715
+ return /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
716
+ /* @__PURE__ */ jsx(
717
+ "div",
718
+ {
719
+ className: cn(
720
+ "font-bold",
721
+ accent("accent", tone.isLight).text,
722
+ size === "lg" ? "text-4xl sm:text-5xl" : "text-3xl sm:text-4xl"
723
+ ),
724
+ children: /* @__PURE__ */ jsx(CountUp, { value })
725
+ }
726
+ ),
727
+ /* @__PURE__ */ jsx("div", { className: cn("mt-1 text-xs tracking-wider uppercase", tone.muted), children: label })
728
+ ] });
729
+ }
730
+ function Card({
731
+ children,
732
+ className,
733
+ i
734
+ }) {
735
+ const tone = useTone();
736
+ const r = reveal(i ?? 3);
737
+ return /* @__PURE__ */ jsx(
738
+ "div",
739
+ {
740
+ className: cn(
741
+ r.className,
742
+ "rounded-2xl border p-6",
743
+ tone.card,
744
+ tone.hairline,
745
+ className
746
+ ),
747
+ style: r.style,
748
+ children
749
+ }
750
+ );
751
+ }
752
+ function ChartTable({
753
+ caption,
754
+ headers,
755
+ rows
756
+ }) {
757
+ return /* @__PURE__ */ jsxs("table", { className: "sr-only", children: [
758
+ /* @__PURE__ */ jsx("caption", { children: caption }),
759
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: headers.map(
760
+ (h, i) => h ? /* @__PURE__ */ jsx("th", { scope: "col", children: h }, i) : (
761
+ // The row-label corner cell has no caption of its own.
762
+ /* @__PURE__ */ jsx("td", {}, i)
763
+ )
764
+ ) }) }),
765
+ /* @__PURE__ */ jsx("tbody", { children: rows.map((row, r) => /* @__PURE__ */ jsx("tr", { children: row.map(
766
+ (cell, c) => c === 0 ? /* @__PURE__ */ jsx("th", { scope: "row", children: cell }, c) : /* @__PURE__ */ jsx("td", { children: cell }, c)
767
+ ) }, r)) })
768
+ ] });
769
+ }
770
+ function useFormat() {
771
+ const { locale } = useDeck();
772
+ return React9.useMemo(
773
+ () => new Intl.NumberFormat(locale, { notation: "compact" }),
774
+ [locale]
775
+ );
776
+ }
777
+ function BarChart({ graphic }) {
778
+ const tone = useTone();
779
+ const format = useFormat();
780
+ const max = Math.max(1, ...graphic.bars.map((b) => b.value));
781
+ const hi = accent("accent", tone.isLight);
782
+ return /* @__PURE__ */ jsxs("figure", { "data-slot": "deck-bar-chart", className: "w-full", children: [
783
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "flex h-56 items-end gap-2 sm:h-64", children: graphic.bars.map((bar, i) => /* @__PURE__ */ jsxs(React9.Fragment, { children: [
784
+ graphic.marker?.atIndex === i && /* @__PURE__ */ jsx("div", { className: "relative h-full w-px flex-none border-s border-dashed border-current opacity-40", children: /* @__PURE__ */ jsx("span", { className: "absolute start-1/2 -top-6 -translate-x-1/2 text-[0.65rem] font-semibold tracking-wide whitespace-nowrap uppercase opacity-100", children: graphic.marker.label }) }),
785
+ /* @__PURE__ */ jsxs("div", { className: "flex h-full min-w-0 flex-1 flex-col items-center gap-1", children: [
786
+ /* @__PURE__ */ jsx("div", { className: "w-full flex-1 pt-5", children: /* @__PURE__ */ jsx("div", { className: "relative h-full", children: /* @__PURE__ */ jsx(
787
+ "div",
788
+ {
789
+ className: cn(
790
+ "mie-deck-grow absolute inset-x-0 bottom-0 rounded-t-md",
791
+ bar.highlight ? hi.fill : tone.isLight ? "bg-neutral-300" : "bg-white/25"
792
+ ),
793
+ style: {
794
+ height: `${bar.value / max * 100}%`,
795
+ "--mie-reveal-i": i
796
+ },
797
+ children: /* @__PURE__ */ jsx(
798
+ "span",
799
+ {
800
+ className: cn(
801
+ "absolute inset-x-0 bottom-full mb-1 text-center text-xs font-semibold tabular-nums",
802
+ tone.muted
803
+ ),
804
+ children: format.format(bar.value)
805
+ }
806
+ )
807
+ }
808
+ ) }) }),
809
+ /* @__PURE__ */ jsx(
810
+ "span",
811
+ {
812
+ className: cn(
813
+ "w-full truncate text-center text-xs",
814
+ tone.muted
815
+ ),
816
+ children: bar.label
817
+ }
818
+ )
819
+ ] })
820
+ ] }, bar.label)) }),
821
+ graphic.yAxisLabel && /* @__PURE__ */ jsx("figcaption", { className: cn("mt-2 text-xs", tone.muted), children: graphic.yAxisLabel }),
822
+ /* @__PURE__ */ jsx(
823
+ ChartTable,
824
+ {
825
+ caption: graphic.yAxisLabel ?? "Values",
826
+ headers: ["", graphic.yAxisLabel ?? "Value"],
827
+ rows: graphic.bars.map((b) => [b.label, b.value])
828
+ }
829
+ )
830
+ ] });
831
+ }
832
+ function HorizontalBars({ graphic }) {
833
+ const tone = useTone();
834
+ const format = useFormat();
835
+ const max = Math.max(1, ...graphic.bars.map((b) => b.value));
836
+ const a = accent("accent", tone.isLight);
837
+ return /* @__PURE__ */ jsx("ul", { "data-slot": "deck-horizontal-bars", className: "w-full space-y-3", children: graphic.bars.map((bar, i) => {
838
+ const r = reveal(3 + i);
839
+ return /* @__PURE__ */ jsxs("li", { className: r.className, style: r.style, children: [
840
+ /* @__PURE__ */ jsxs("div", { className: "mb-1 flex justify-between gap-3 text-sm", children: [
841
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: bar.label }),
842
+ /* @__PURE__ */ jsx("span", { className: "font-semibold tabular-nums", children: bar.display ?? format.format(bar.value) })
843
+ ] }),
844
+ /* @__PURE__ */ jsx(
845
+ "div",
846
+ {
847
+ "aria-hidden": "true",
848
+ className: cn(
849
+ "h-2 overflow-hidden rounded-full",
850
+ tone.isLight ? "bg-neutral-200" : "bg-white/10"
851
+ ),
852
+ children: /* @__PURE__ */ jsx(
853
+ "div",
854
+ {
855
+ className: cn("h-full rounded-full", a.fill),
856
+ style: { width: `${bar.value / max * 100}%` }
857
+ }
858
+ )
859
+ }
860
+ )
861
+ ] }, bar.label);
862
+ }) });
863
+ }
864
+ function KpiRow({ graphic }) {
865
+ const tone = useTone();
866
+ return /* @__PURE__ */ jsx(
867
+ "dl",
868
+ {
869
+ "data-slot": "deck-kpi-row",
870
+ className: "grid w-full grid-cols-2 gap-4 sm:grid-cols-4",
871
+ children: graphic.kpis.map((kpi, i) => {
872
+ const Trend = kpi.trend === "up" ? TrendingUp : kpi.trend === "down" ? TrendingDown : Minus;
873
+ const r = reveal(3 + i);
874
+ return /* @__PURE__ */ jsxs(
875
+ "div",
876
+ {
877
+ className: cn(
878
+ r.className,
879
+ "flex flex-col-reverse rounded-xl border p-4",
880
+ tone.card,
881
+ tone.hairline
882
+ ),
883
+ style: r.style,
884
+ children: [
885
+ /* @__PURE__ */ jsx("dt", { className: cn("text-xs", tone.muted), children: kpi.label }),
886
+ /* @__PURE__ */ jsxs("dd", { className: "flex items-center gap-2 text-2xl font-bold tabular-nums", children: [
887
+ kpi.value,
888
+ kpi.trend && /* @__PURE__ */ jsx(
889
+ Trend,
890
+ {
891
+ "aria-hidden": "true",
892
+ className: cn(
893
+ "size-4",
894
+ kpi.trend === "up" ? "text-success" : kpi.trend === "down" ? "text-destructive" : tone.muted
895
+ )
896
+ }
897
+ )
898
+ ] })
899
+ ]
900
+ },
901
+ kpi.label
902
+ );
903
+ })
904
+ }
905
+ );
906
+ }
907
+ function points(values, w, h, y) {
908
+ const step = values.length > 1 ? w / (values.length - 1) : 0;
909
+ return values.map((v, i) => `${(i * step).toFixed(1)},${(h - y(v) * h).toFixed(1)}`).join(" ");
910
+ }
911
+ function Spark({ graphic }) {
912
+ const tone = useTone();
913
+ const a = accent("accent", tone.isLight);
914
+ const max = Math.max(1, ...graphic.values);
915
+ const last = graphic.values[graphic.values.length - 1];
916
+ return /* @__PURE__ */ jsxs("figure", { "data-slot": "deck-spark", className: "w-full", children: [
917
+ /* @__PURE__ */ jsxs(
918
+ "figcaption",
919
+ {
920
+ className: cn(
921
+ "flex items-baseline justify-between text-sm",
922
+ tone.muted
923
+ ),
924
+ children: [
925
+ /* @__PURE__ */ jsx("span", { children: graphic.label }),
926
+ /* @__PURE__ */ jsxs("span", { className: cn("text-2xl font-bold tabular-nums", a.text), children: [
927
+ last,
928
+ graphic.suffix
929
+ ] })
930
+ ]
931
+ }
932
+ ),
933
+ /* @__PURE__ */ jsx(
934
+ "svg",
935
+ {
936
+ "aria-hidden": "true",
937
+ viewBox: "0 0 100 30",
938
+ preserveAspectRatio: "none",
939
+ className: "mt-2 h-12 w-full overflow-visible",
940
+ children: /* @__PURE__ */ jsx(
941
+ "polyline",
942
+ {
943
+ points: points(graphic.values, 100, 30, (v) => v / max),
944
+ fill: "none",
945
+ strokeWidth: 2,
946
+ vectorEffect: "non-scaling-stroke",
947
+ className: a.svgStroke
948
+ }
949
+ )
950
+ }
951
+ ),
952
+ /* @__PURE__ */ jsx(
953
+ ChartTable,
954
+ {
955
+ caption: graphic.label,
956
+ headers: ["#", graphic.label],
957
+ rows: graphic.values.map((v, i) => [i + 1, v])
958
+ }
959
+ )
960
+ ] });
961
+ }
962
+ function MultiLine({ graphic }) {
963
+ const tone = useTone();
964
+ const { labels } = useDeck();
965
+ const format = useFormat();
966
+ const [view, setView] = React9.useState("lines");
967
+ const all = graphic.series.flatMap((s) => s.values);
968
+ const log = (graphic.scale ?? "log") === "log";
969
+ const tx = (v) => log ? Math.log10(Math.max(1, v)) : v;
970
+ const lo = Math.min(...all.map(tx));
971
+ const hi = Math.max(...all.map(tx));
972
+ const y = (v) => hi === lo ? 0.5 : (tx(v) - lo) / (hi - lo);
973
+ const colours = graphic.series.map(
974
+ (_, i) => accent(ACCENT_CYCLE[i % ACCENT_CYCLE.length], tone.isLight)
975
+ );
976
+ const toggle = (active) => cn(
977
+ "rounded-full px-3 py-1 text-xs font-semibold transition-colors",
978
+ active ? tone.isLight ? "bg-neutral-900 text-white" : "bg-white text-neutral-900" : cn(tone.muted, "hover:opacity-100")
979
+ );
980
+ return /* @__PURE__ */ jsxs("figure", { "data-slot": "deck-multi-line", className: "w-full", children: [
981
+ /* @__PURE__ */ jsxs(
982
+ "div",
983
+ {
984
+ role: "group",
985
+ "aria-label": graphic.caption,
986
+ className: "mb-3 flex gap-1",
987
+ children: [
988
+ /* @__PURE__ */ jsx(
989
+ "button",
990
+ {
991
+ type: "button",
992
+ "aria-pressed": view === "lines",
993
+ className: toggle(view === "lines"),
994
+ onClick: () => setView("lines"),
995
+ children: labels.lines
996
+ }
997
+ ),
998
+ /* @__PURE__ */ jsx(
999
+ "button",
1000
+ {
1001
+ type: "button",
1002
+ "aria-pressed": view === "bars",
1003
+ className: toggle(view === "bars"),
1004
+ onClick: () => setView("bars"),
1005
+ children: labels.bars
1006
+ }
1007
+ )
1008
+ ]
1009
+ }
1010
+ ),
1011
+ view === "lines" ? /* @__PURE__ */ jsx(
1012
+ "svg",
1013
+ {
1014
+ "aria-hidden": "true",
1015
+ viewBox: "0 0 100 50",
1016
+ preserveAspectRatio: "none",
1017
+ className: "h-56 w-full overflow-visible",
1018
+ children: graphic.series.map((s, i) => /* @__PURE__ */ jsx(
1019
+ "polyline",
1020
+ {
1021
+ points: points(s.values, 100, 50, y),
1022
+ fill: "none",
1023
+ strokeWidth: 2.5,
1024
+ strokeLinecap: "round",
1025
+ strokeLinejoin: "round",
1026
+ vectorEffect: "non-scaling-stroke",
1027
+ className: colours[i].svgStroke
1028
+ },
1029
+ s.label
1030
+ ))
1031
+ }
1032
+ ) : /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "grid gap-4 sm:grid-cols-2", children: graphic.series.map((s, i) => {
1033
+ const max = Math.max(1, ...s.values);
1034
+ return /* @__PURE__ */ jsxs("div", { children: [
1035
+ /* @__PURE__ */ jsx(
1036
+ "p",
1037
+ {
1038
+ className: cn("mb-1 text-xs font-semibold", colours[i].text),
1039
+ children: s.label
1040
+ }
1041
+ ),
1042
+ /* @__PURE__ */ jsx("div", { className: "flex h-20 items-end gap-1", children: s.values.map((v, j) => /* @__PURE__ */ jsx(
1043
+ "div",
1044
+ {
1045
+ className: cn("flex-1 rounded-t-sm", colours[i].fill),
1046
+ style: { height: `${v / max * 100}%` }
1047
+ },
1048
+ j
1049
+ )) })
1050
+ ] }, s.label);
1051
+ }) }),
1052
+ /* @__PURE__ */ jsx(
1053
+ "div",
1054
+ {
1055
+ "aria-hidden": "true",
1056
+ className: cn("mt-2 flex justify-between text-xs", tone.muted),
1057
+ children: graphic.xLabels.map((l) => /* @__PURE__ */ jsx("span", { children: l }, l))
1058
+ }
1059
+ ),
1060
+ /* @__PURE__ */ jsx("ul", { className: "mt-4 flex flex-wrap gap-x-6 gap-y-2 text-sm", children: graphic.series.map((s, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2", children: [
1061
+ /* @__PURE__ */ jsx(
1062
+ "span",
1063
+ {
1064
+ "aria-hidden": "true",
1065
+ className: cn("size-2.5 rounded-full", colours[i].fill)
1066
+ }
1067
+ ),
1068
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: s.label }),
1069
+ s.summary && /* @__PURE__ */ jsx("span", { className: tone.muted, children: s.summary })
1070
+ ] }, s.label)) }),
1071
+ graphic.caption && /* @__PURE__ */ jsx("figcaption", { className: cn("mt-2 text-xs", tone.muted), children: graphic.caption }),
1072
+ /* @__PURE__ */ jsx(
1073
+ ChartTable,
1074
+ {
1075
+ caption: graphic.caption ?? graphic.series.map((s) => s.label).join(", "),
1076
+ headers: ["", ...graphic.series.map((s) => s.label)],
1077
+ rows: graphic.xLabels.map((x, i) => [
1078
+ x,
1079
+ ...graphic.series.map((s) => format.format(s.values[i] ?? 0))
1080
+ ])
1081
+ }
1082
+ )
1083
+ ] });
1084
+ }
1085
+ function Graphic({ graphic }) {
1086
+ const { graphics } = useDeck();
1087
+ switch (graphic.type) {
1088
+ case "bar":
1089
+ return /* @__PURE__ */ jsx(BarChart, { graphic });
1090
+ case "horizontal-bar":
1091
+ return /* @__PURE__ */ jsx(HorizontalBars, { graphic });
1092
+ case "multi-line":
1093
+ return /* @__PURE__ */ jsx(MultiLine, { graphic });
1094
+ case "kpi-row":
1095
+ return /* @__PURE__ */ jsx(KpiRow, { graphic });
1096
+ case "spark":
1097
+ return /* @__PURE__ */ jsx(Spark, { graphic });
1098
+ case "custom": {
1099
+ const Custom = graphics?.[graphic.component];
1100
+ return Custom ? /* @__PURE__ */ jsx(Custom, { ...graphic.props }) : null;
1101
+ }
1102
+ }
1103
+ }
1104
+ var slideAnchor = (slide, index) => slide.id ?? `slide-${index}`;
1105
+ var widthClass = {
1106
+ sm: "max-w-3xl",
1107
+ md: "max-w-4xl",
1108
+ lg: "max-w-5xl",
1109
+ xl: "max-w-6xl"
1110
+ };
1111
+ function SlideFrame({
1112
+ slide,
1113
+ index,
1114
+ tone: fallback,
1115
+ children,
1116
+ width = "xl",
1117
+ className
1118
+ }) {
1119
+ const { labels } = useDeck();
1120
+ const toneName = slide.tone ?? fallback;
1121
+ const tone = TONES[toneName];
1122
+ const title = "title" in slide ? slide.title : void 0;
1123
+ return /* @__PURE__ */ jsx(ToneContext.Provider, { value: tone, children: /* @__PURE__ */ jsxs(
1124
+ "section",
1125
+ {
1126
+ id: slideAnchor(slide, index),
1127
+ "data-slot": "deck-slide",
1128
+ "data-index": index,
1129
+ "data-tone": toneName,
1130
+ role: "group",
1131
+ "aria-roledescription": labels.slide,
1132
+ "aria-label": slide.navLabel ?? title ?? `${index + 1}`,
1133
+ className: cn(
1134
+ "mie-deck-slide relative isolate flex min-h-dvh w-full snap-start snap-always flex-col items-center justify-center overflow-hidden px-5 py-12 sm:px-8 sm:py-14 md:px-12 lg:px-20",
1135
+ tone.surface,
1136
+ tone.text,
1137
+ className
1138
+ ),
1139
+ children: [
1140
+ !tone.isLight && /* @__PURE__ */ jsxs(
1141
+ "div",
1142
+ {
1143
+ "aria-hidden": "true",
1144
+ className: "pointer-events-none absolute inset-0 -z-10 overflow-hidden print:hidden",
1145
+ children: [
1146
+ /* @__PURE__ */ jsx("div", { className: "bg-accent/15 absolute -end-24 -top-24 size-[28rem] rounded-full blur-3xl" }),
1147
+ /* @__PURE__ */ jsx("div", { className: "bg-primary-500/15 absolute -start-24 -bottom-32 size-[32rem] rounded-full blur-3xl" })
1148
+ ]
1149
+ }
1150
+ ),
1151
+ /* @__PURE__ */ jsx("div", { className: cn("relative w-full", widthClass[width]), children })
1152
+ ]
1153
+ }
1154
+ ) });
1155
+ }
1156
+ var gridCols = (n) => n >= 4 ? "sm:grid-cols-2 lg:grid-cols-4" : n === 3 ? "md:grid-cols-3" : "md:grid-cols-2";
1157
+ function MetricsBody({ slide }) {
1158
+ const tone = useTone();
1159
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1160
+ /* @__PURE__ */ jsx(
1161
+ SlideHeader,
1162
+ {
1163
+ eyebrow: slide.eyebrow,
1164
+ title: slide.title,
1165
+ subtitle: slide.subtitle
1166
+ }
1167
+ ),
1168
+ /* @__PURE__ */ jsx(
1169
+ "div",
1170
+ {
1171
+ className: cn(
1172
+ "mt-10 grid grid-cols-1 gap-5",
1173
+ gridCols(slide.metrics.length)
1174
+ ),
1175
+ children: slide.metrics.map((m, i) => /* @__PURE__ */ jsxs(Card, { i: 3 + i, children: [
1176
+ m.icon && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(IconChip, { icon: m.icon, accent: m.accent }) }),
1177
+ /* @__PURE__ */ jsx(
1178
+ "div",
1179
+ {
1180
+ className: cn(
1181
+ "text-4xl font-bold",
1182
+ accent(m.accent, tone.isLight).text
1183
+ ),
1184
+ children: /* @__PURE__ */ jsx(CountUp, { value: m.value })
1185
+ }
1186
+ ),
1187
+ /* @__PURE__ */ jsx("div", { className: "mt-2 text-sm font-semibold", children: m.label }),
1188
+ m.description && /* @__PURE__ */ jsx("div", { className: cn("mt-1 text-sm leading-snug", tone.muted), children: m.description })
1189
+ ] }, m.label))
1190
+ }
1191
+ )
1192
+ ] });
1193
+ }
1194
+ function MetricsRenderer({
1195
+ slide,
1196
+ index
1197
+ }) {
1198
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "brand", children: /* @__PURE__ */ jsx(MetricsBody, { slide }) });
1199
+ }
1200
+ function ChartBody({ slide }) {
1201
+ const tone = useTone();
1202
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1203
+ /* @__PURE__ */ jsx(
1204
+ SlideHeader,
1205
+ {
1206
+ eyebrow: slide.eyebrow,
1207
+ title: slide.title,
1208
+ subtitle: slide.subtitle
1209
+ }
1210
+ ),
1211
+ /* @__PURE__ */ jsx("div", { ...reveal(3), className: "mie-deck-reveal mt-10", children: /* @__PURE__ */ jsx(Graphic, { graphic: slide.graphic }) }),
1212
+ slide.description && /* @__PURE__ */ jsx("p", { className: cn("mt-6 max-w-3xl text-sm", tone.muted), children: slide.description }),
1213
+ slide.source && /* @__PURE__ */ jsx(SourceLink, { source: slide.source, className: "mt-4" })
1214
+ ] });
1215
+ }
1216
+ function ChartRenderer({
1217
+ slide,
1218
+ index
1219
+ }) {
1220
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "deep", children: /* @__PURE__ */ jsx(ChartBody, { slide }) });
1221
+ }
1222
+ function FeatureHighlightBody({
1223
+ slide
1224
+ }) {
1225
+ const tone = useTone();
1226
+ const a = accent("accent", tone.isLight);
1227
+ const hasGraphic = !!slide.graphic;
1228
+ return /* @__PURE__ */ jsxs(
1229
+ "div",
1230
+ {
1231
+ className: cn(hasGraphic && "grid items-center gap-10 lg:grid-cols-2"),
1232
+ children: [
1233
+ /* @__PURE__ */ jsxs("div", { children: [
1234
+ /* @__PURE__ */ jsx(SlideHeader, { eyebrow: slide.eyebrow, title: slide.title }),
1235
+ /* @__PURE__ */ jsx(
1236
+ "p",
1237
+ {
1238
+ ...reveal(2),
1239
+ className: cn(
1240
+ "mie-deck-reveal mt-4 text-lg leading-relaxed",
1241
+ tone.muted
1242
+ ),
1243
+ children: slide.body
1244
+ }
1245
+ ),
1246
+ slide.stat && /* @__PURE__ */ jsxs("div", { ...reveal(3), className: "mie-deck-reveal mt-8", children: [
1247
+ /* @__PURE__ */ jsx("div", { className: cn("text-5xl font-bold", a.text), children: /* @__PURE__ */ jsx(CountUp, { value: slide.stat.value }) }),
1248
+ /* @__PURE__ */ jsx("div", { className: cn("mt-1 text-sm", tone.muted), children: slide.stat.label })
1249
+ ] }),
1250
+ slide.bullets && slide.bullets.length > 0 && /* @__PURE__ */ jsx("ul", { ...reveal(4), className: "mie-deck-reveal mt-6 space-y-2", children: slide.bullets.map((b) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-3", children: [
1251
+ /* @__PURE__ */ jsx(
1252
+ "span",
1253
+ {
1254
+ "aria-hidden": "true",
1255
+ className: cn("mt-2 size-1.5 flex-none rounded-full", a.fill)
1256
+ }
1257
+ ),
1258
+ b
1259
+ ] }, b)) }),
1260
+ slide.pullQuote && /* @__PURE__ */ jsx(
1261
+ "blockquote",
1262
+ {
1263
+ ...reveal(5),
1264
+ className: cn(
1265
+ "mie-deck-reveal mt-8 border-s-2 ps-4 italic",
1266
+ a.border,
1267
+ tone.muted
1268
+ ),
1269
+ children: slide.pullQuote
1270
+ }
1271
+ )
1272
+ ] }),
1273
+ hasGraphic && /* @__PURE__ */ jsxs("div", { ...reveal(3), className: "mie-deck-reveal flex flex-col gap-8", children: [
1274
+ /* @__PURE__ */ jsx(Graphic, { graphic: slide.graphic }),
1275
+ slide.secondaryGraphic && /* @__PURE__ */ jsx(Graphic, { graphic: slide.secondaryGraphic })
1276
+ ] })
1277
+ ]
1278
+ }
1279
+ );
1280
+ }
1281
+ function FeatureHighlightRenderer({
1282
+ slide,
1283
+ index
1284
+ }) {
1285
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "deep", children: /* @__PURE__ */ jsx(FeatureHighlightBody, { slide }) });
1286
+ }
1287
+ function DeckTable({
1288
+ headers,
1289
+ rows
1290
+ }) {
1291
+ const tone = useTone();
1292
+ return /* @__PURE__ */ jsx(
1293
+ "div",
1294
+ {
1295
+ ...reveal(3),
1296
+ className: cn(
1297
+ "mie-deck-reveal mt-10 overflow-x-auto rounded-2xl border",
1298
+ tone.hairline,
1299
+ tone.card
1300
+ ),
1301
+ children: /* @__PURE__ */ jsxs("table", { className: "min-w-full text-start text-sm sm:text-base", children: [
1302
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: cn("border-b", tone.hairline), children: headers.map((h, i) => /* @__PURE__ */ jsx(
1303
+ "th",
1304
+ {
1305
+ scope: "col",
1306
+ className: cn(
1307
+ "px-5 py-3 font-semibold",
1308
+ i === 0 ? "text-start" : "text-end",
1309
+ tone.muted
1310
+ ),
1311
+ children: h
1312
+ },
1313
+ h
1314
+ )) }) }),
1315
+ /* @__PURE__ */ jsx("tbody", { children: rows.map((row, r) => /* @__PURE__ */ jsx("tr", { className: cn(r > 0 && "border-t", tone.hairline), children: row.map(
1316
+ (cell, c) => c === 0 ? /* @__PURE__ */ jsx(
1317
+ "th",
1318
+ {
1319
+ scope: "row",
1320
+ className: "px-5 py-3 text-start font-medium",
1321
+ children: cell
1322
+ },
1323
+ c
1324
+ ) : /* @__PURE__ */ jsx("td", { className: "px-5 py-3 text-end tabular-nums", children: cell }, c)
1325
+ ) }, r)) })
1326
+ ] })
1327
+ }
1328
+ );
1329
+ }
1330
+ function ComparisonTableRenderer({
1331
+ slide,
1332
+ index
1333
+ }) {
1334
+ const a = accent("accent", (slide.tone ?? "deep") === "light");
1335
+ const [metric, before, after, change] = slide.headers ?? [
1336
+ "Metric",
1337
+ "Before",
1338
+ "After",
1339
+ "Change"
1340
+ ];
1341
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "deep", width: "lg", children: [
1342
+ /* @__PURE__ */ jsx(
1343
+ SlideHeader,
1344
+ {
1345
+ eyebrow: slide.eyebrow,
1346
+ title: slide.title,
1347
+ subtitle: slide.subtitle
1348
+ }
1349
+ ),
1350
+ /* @__PURE__ */ jsx(
1351
+ DeckTable,
1352
+ {
1353
+ headers: [metric, before, after, change],
1354
+ rows: slide.rows.map((r) => [
1355
+ r.label,
1356
+ /* @__PURE__ */ jsx("span", { className: "opacity-70", children: r.before }, "b"),
1357
+ r.after,
1358
+ /* @__PURE__ */ jsx("span", { className: cn("font-semibold", a.text), children: r.change }, "c")
1359
+ ])
1360
+ }
1361
+ )
1362
+ ] });
1363
+ }
1364
+ function ImpactTableRenderer({
1365
+ slide,
1366
+ index
1367
+ }) {
1368
+ const [item, impact] = slide.headers ?? ["Investment", "Impact"];
1369
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "deep", width: "lg", children: [
1370
+ /* @__PURE__ */ jsx(
1371
+ SlideHeader,
1372
+ {
1373
+ eyebrow: slide.eyebrow,
1374
+ title: slide.title,
1375
+ subtitle: slide.subtitle
1376
+ }
1377
+ ),
1378
+ /* @__PURE__ */ jsx(
1379
+ DeckTable,
1380
+ {
1381
+ headers: [item, impact],
1382
+ rows: slide.rows.map((r) => [
1383
+ /* @__PURE__ */ jsxs("span", { children: [
1384
+ r.item,
1385
+ r.detail && /* @__PURE__ */ jsx("span", { className: "block text-sm font-normal opacity-70", children: r.detail })
1386
+ ] }, "i"),
1387
+ /* @__PURE__ */ jsx("span", { className: "block text-start sm:text-end", children: r.impact }, "m")
1388
+ ])
1389
+ }
1390
+ )
1391
+ ] });
1392
+ }
1393
+ function CardsBody({ slide }) {
1394
+ const tone = useTone();
1395
+ const a = accent("accent", tone.isLight);
1396
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1397
+ /* @__PURE__ */ jsx(
1398
+ SlideHeader,
1399
+ {
1400
+ eyebrow: slide.eyebrow,
1401
+ title: slide.title,
1402
+ subtitle: slide.subtitle
1403
+ }
1404
+ ),
1405
+ /* @__PURE__ */ jsx(
1406
+ "div",
1407
+ {
1408
+ className: cn(
1409
+ "mt-10 grid grid-cols-1 gap-5",
1410
+ gridCols(slide.cards.length)
1411
+ ),
1412
+ children: slide.cards.map((card, i) => /* @__PURE__ */ jsxs(Card, { i: 3 + i, children: [
1413
+ card.icon && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(IconChip, { icon: card.icon }) }),
1414
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: card.title }),
1415
+ /* @__PURE__ */ jsx("p", { className: cn("mt-2 leading-relaxed", tone.muted), children: card.body }),
1416
+ card.stat && /* @__PURE__ */ jsxs("div", { className: "mt-6", children: [
1417
+ /* @__PURE__ */ jsx("div", { className: cn("text-3xl font-bold", a.text), children: /* @__PURE__ */ jsx(CountUp, { value: card.stat }) }),
1418
+ card.statLabel && /* @__PURE__ */ jsx("div", { className: cn("text-sm", tone.muted), children: card.statLabel })
1419
+ ] })
1420
+ ] }, card.title))
1421
+ }
1422
+ ),
1423
+ slide.note && /* @__PURE__ */ jsx("p", { className: cn("mt-8 text-sm italic", tone.muted), children: slide.note })
1424
+ ] });
1425
+ }
1426
+ function CardsRenderer({
1427
+ slide,
1428
+ index
1429
+ }) {
1430
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "brand", children: /* @__PURE__ */ jsx(CardsBody, { slide }) });
1431
+ }
1432
+ function RankedListBody({ slide }) {
1433
+ const tone = useTone();
1434
+ const { locale } = useDeck();
1435
+ const a = accent("accent", tone.isLight);
1436
+ const format = new Intl.NumberFormat(locale);
1437
+ const max = Math.max(1, ...slide.entries.map((e) => e.value));
1438
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1439
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-end justify-between gap-4", children: [
1440
+ /* @__PURE__ */ jsx(
1441
+ SlideHeader,
1442
+ {
1443
+ eyebrow: slide.eyebrow,
1444
+ title: slide.title,
1445
+ subtitle: slide.subtitle
1446
+ }
1447
+ ),
1448
+ slide.outOf && /* @__PURE__ */ jsx("p", { className: cn("text-sm", tone.muted), children: slide.outOf })
1449
+ ] }),
1450
+ /* @__PURE__ */ jsx("ol", { className: "mt-8 flex flex-col gap-2", children: slide.entries.map((e, i) => {
1451
+ const r = reveal(3 + i);
1452
+ return /* @__PURE__ */ jsxs(
1453
+ "li",
1454
+ {
1455
+ className: cn(
1456
+ r.className,
1457
+ "grid grid-cols-[2rem_minmax(0,1fr)_auto] items-center gap-4 rounded-xl border px-4 py-3",
1458
+ e.highlighted ? cn(a.soft, a.border) : cn(tone.card, tone.hairline)
1459
+ ),
1460
+ style: r.style,
1461
+ children: [
1462
+ /* @__PURE__ */ jsx(
1463
+ "span",
1464
+ {
1465
+ className: cn(
1466
+ "text-sm font-bold tabular-nums",
1467
+ e.highlighted ? a.text : tone.muted
1468
+ ),
1469
+ children: i + 1
1470
+ }
1471
+ ),
1472
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
1473
+ /* @__PURE__ */ jsx("span", { className: "block truncate font-medium", children: e.label }),
1474
+ e.sublabel && /* @__PURE__ */ jsx("span", { className: cn("block truncate text-xs", tone.muted), children: e.sublabel }),
1475
+ /* @__PURE__ */ jsx(
1476
+ "span",
1477
+ {
1478
+ "aria-hidden": "true",
1479
+ className: cn(
1480
+ "mt-2 block h-1.5 overflow-hidden rounded-full",
1481
+ tone.isLight ? "bg-neutral-200" : "bg-white/10"
1482
+ ),
1483
+ children: /* @__PURE__ */ jsx(
1484
+ "span",
1485
+ {
1486
+ className: cn(
1487
+ "block h-full rounded-full",
1488
+ e.highlighted ? a.fill : tone.isLight ? "bg-neutral-400" : "bg-white/40"
1489
+ ),
1490
+ style: { width: `${e.value / max * 100}%` }
1491
+ }
1492
+ )
1493
+ }
1494
+ )
1495
+ ] }),
1496
+ /* @__PURE__ */ jsxs("span", { className: "text-end", children: [
1497
+ /* @__PURE__ */ jsx("span", { className: "block font-semibold tabular-nums", children: e.display ?? format.format(e.value) }),
1498
+ e.secondary && /* @__PURE__ */ jsx("span", { className: cn("block text-xs", tone.muted), children: e.secondary }),
1499
+ e.change != null && e.change !== 0 && /* @__PURE__ */ jsxs(
1500
+ "span",
1501
+ {
1502
+ className: cn(
1503
+ "inline-flex items-center text-xs font-semibold",
1504
+ e.change > 0 ? "text-success" : "text-destructive"
1505
+ ),
1506
+ children: [
1507
+ e.change > 0 ? /* @__PURE__ */ jsx(ArrowUp, { "aria-hidden": "true", className: "size-3" }) : /* @__PURE__ */ jsx(ArrowDown, { "aria-hidden": "true", className: "size-3" }),
1508
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: e.change > 0 ? "+" : "\u2212" }),
1509
+ Math.abs(e.change)
1510
+ ]
1511
+ }
1512
+ )
1513
+ ] })
1514
+ ]
1515
+ },
1516
+ e.label
1517
+ );
1518
+ }) }),
1519
+ slide.source && /* @__PURE__ */ jsx(SourceLink, { source: slide.source, className: "mt-4" })
1520
+ ] });
1521
+ }
1522
+ function RankedListRenderer({
1523
+ slide,
1524
+ index
1525
+ }) {
1526
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "deep", width: "lg", children: /* @__PURE__ */ jsx(RankedListBody, { slide }) });
1527
+ }
1528
+ function BreakdownRenderer({
1529
+ slide,
1530
+ index
1531
+ }) {
1532
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "deep", children: /* @__PURE__ */ jsx(BreakdownBody, { slide }) });
1533
+ }
1534
+ function BreakdownBody({ slide }) {
1535
+ const tone = useTone();
1536
+ const a = accent("accent", tone.isLight);
1537
+ const total = slide.breakdown?.reduce((s, b) => s + b.count, 0) || 1;
1538
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-10 lg:grid-cols-2", children: [
1539
+ /* @__PURE__ */ jsxs("div", { children: [
1540
+ /* @__PURE__ */ jsx(SlideHeader, { eyebrow: slide.eyebrow, title: slide.title }),
1541
+ slide.body && /* @__PURE__ */ jsx(
1542
+ "p",
1543
+ {
1544
+ ...reveal(2),
1545
+ className: cn(
1546
+ "mie-deck-reveal mt-4 text-lg leading-relaxed",
1547
+ tone.muted
1548
+ ),
1549
+ children: slide.body
1550
+ }
1551
+ ),
1552
+ slide.callout && /* @__PURE__ */ jsxs(
1553
+ "div",
1554
+ {
1555
+ ...reveal(3),
1556
+ className: cn(
1557
+ "mie-deck-reveal mt-8 inline-flex items-baseline gap-3 rounded-2xl border px-5 py-3",
1558
+ a.soft,
1559
+ a.border
1560
+ ),
1561
+ children: [
1562
+ /* @__PURE__ */ jsx("span", { className: cn("text-4xl font-bold", a.text), children: /* @__PURE__ */ jsx(CountUp, { value: slide.callout.value }) }),
1563
+ /* @__PURE__ */ jsx("span", { className: "text-sm", children: slide.callout.label })
1564
+ ]
1565
+ }
1566
+ ),
1567
+ slide.talkingPoint && /* @__PURE__ */ jsxs("p", { className: cn("mt-6 text-sm italic", tone.muted), children: [
1568
+ "\u201C",
1569
+ slide.talkingPoint,
1570
+ "\u201D"
1571
+ ] }),
1572
+ slide.pullQuote && /* @__PURE__ */ jsx(
1573
+ "blockquote",
1574
+ {
1575
+ className: cn(
1576
+ "mt-6 border-s-2 ps-4 text-lg font-semibold",
1577
+ a.border
1578
+ ),
1579
+ children: slide.pullQuote
1580
+ }
1581
+ )
1582
+ ] }),
1583
+ /* @__PURE__ */ jsxs("div", { ...reveal(3), className: "mie-deck-reveal flex flex-col gap-8", children: [
1584
+ slide.series && /* @__PURE__ */ jsx(Graphic, { graphic: slide.series }),
1585
+ slide.breakdown && slide.breakdown.length > 0 && /* @__PURE__ */ jsx("ul", { className: "space-y-2", children: slide.breakdown.map((b) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-3 text-sm", children: [
1586
+ /* @__PURE__ */ jsx("span", { className: "w-36 flex-none truncate", children: b.label }),
1587
+ /* @__PURE__ */ jsx(
1588
+ "span",
1589
+ {
1590
+ "aria-hidden": "true",
1591
+ className: cn(
1592
+ "h-2 flex-1 overflow-hidden rounded-full",
1593
+ tone.isLight ? "bg-neutral-200" : "bg-white/10"
1594
+ ),
1595
+ children: /* @__PURE__ */ jsx(
1596
+ "span",
1597
+ {
1598
+ className: cn("block h-full rounded-full", a.fill),
1599
+ style: { width: `${b.count / total * 100}%` }
1600
+ }
1601
+ )
1602
+ }
1603
+ ),
1604
+ /* @__PURE__ */ jsx("span", { className: "w-10 flex-none text-end font-semibold tabular-nums", children: b.count })
1605
+ ] }, b.label)) }),
1606
+ slide.entries && slide.entries.length > 0 && /* @__PURE__ */ jsx(
1607
+ "ul",
1608
+ {
1609
+ className: cn(
1610
+ "max-h-64 divide-y overflow-y-auto rounded-xl border",
1611
+ tone.hairline,
1612
+ tone.card
1613
+ ),
1614
+ children: slide.entries.map((e) => /* @__PURE__ */ jsxs(
1615
+ "li",
1616
+ {
1617
+ className: cn(
1618
+ "flex items-center justify-between gap-3 px-4 py-2 text-sm",
1619
+ tone.hairline
1620
+ ),
1621
+ children: [
1622
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
1623
+ /* @__PURE__ */ jsx("span", { className: "block truncate font-medium", children: e.title }),
1624
+ e.meta && /* @__PURE__ */ jsx("span", { className: cn("block truncate text-xs", tone.muted), children: e.meta })
1625
+ ] }),
1626
+ e.date && /* @__PURE__ */ jsx(
1627
+ "span",
1628
+ {
1629
+ className: cn("flex-none text-xs tabular-nums", tone.muted),
1630
+ children: e.date
1631
+ }
1632
+ )
1633
+ ]
1634
+ },
1635
+ `${e.title}-${e.date ?? ""}`
1636
+ ))
1637
+ }
1638
+ )
1639
+ ] })
1640
+ ] });
1641
+ }
1642
+ function TabsRenderer({ slide, index }) {
1643
+ const [active, setActive] = React9.useState(0);
1644
+ const baseId = React9.useId();
1645
+ const tabs = React9.useRef([]);
1646
+ const current = slide.tabs[active]?.slide;
1647
+ const onKey = (e) => {
1648
+ const n = slide.tabs.length;
1649
+ const next = e.key === "ArrowRight" ? (active + 1) % n : e.key === "ArrowLeft" ? (active - 1 + n) % n : e.key === "Home" ? 0 : e.key === "End" ? n - 1 : -1;
1650
+ if (next < 0) return;
1651
+ e.preventDefault();
1652
+ e.stopPropagation();
1653
+ setActive(next);
1654
+ tabs.current[next]?.focus();
1655
+ };
1656
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "deep", children: [
1657
+ /* @__PURE__ */ jsx(SlideHeader, { eyebrow: slide.eyebrow, title: slide.title }),
1658
+ /* @__PURE__ */ jsx(
1659
+ "div",
1660
+ {
1661
+ role: "tablist",
1662
+ "aria-label": slide.title,
1663
+ className: "mt-6 flex flex-wrap gap-2",
1664
+ children: slide.tabs.map((tab, i) => /* @__PURE__ */ jsx(
1665
+ TabButton,
1666
+ {
1667
+ ref: (el) => {
1668
+ tabs.current[i] = el;
1669
+ },
1670
+ id: `${baseId}-tab-${i}`,
1671
+ panelId: `${baseId}-panel`,
1672
+ selected: i === active,
1673
+ icon: tab.icon,
1674
+ onClick: () => setActive(i),
1675
+ onKeyDown: onKey,
1676
+ children: tab.label
1677
+ },
1678
+ tab.label
1679
+ ))
1680
+ }
1681
+ ),
1682
+ /* @__PURE__ */ jsxs(
1683
+ "div",
1684
+ {
1685
+ role: "tabpanel",
1686
+ id: `${baseId}-panel`,
1687
+ "aria-labelledby": `${baseId}-tab-${active}`,
1688
+ className: "mt-8",
1689
+ children: [
1690
+ current?.type === "metrics" && /* @__PURE__ */ jsx(MetricsBody, { slide: current }),
1691
+ current?.type === "chart" && /* @__PURE__ */ jsx(ChartBody, { slide: current }),
1692
+ current?.type === "feature-highlight" && /* @__PURE__ */ jsx(FeatureHighlightBody, { slide: current }),
1693
+ current?.type === "cards" && /* @__PURE__ */ jsx(CardsBody, { slide: current }),
1694
+ current?.type === "ranked-list" && /* @__PURE__ */ jsx(RankedListBody, { slide: current })
1695
+ ]
1696
+ }
1697
+ )
1698
+ ] });
1699
+ }
1700
+ var TabButton = React9.forwardRef(({ id, panelId, selected, icon, onClick, onKeyDown, children }, ref) => {
1701
+ const tone = useTone();
1702
+ return /* @__PURE__ */ jsxs(
1703
+ "button",
1704
+ {
1705
+ ref,
1706
+ type: "button",
1707
+ role: "tab",
1708
+ id,
1709
+ "aria-selected": selected,
1710
+ "aria-controls": panelId,
1711
+ tabIndex: selected ? 0 : -1,
1712
+ onClick,
1713
+ onKeyDown,
1714
+ className: cn(
1715
+ "inline-flex items-center gap-2 rounded-full border px-4 py-1.5 text-sm font-semibold transition-colors",
1716
+ selected ? tone.isLight ? "border-neutral-900 bg-neutral-900 text-white" : "border-white bg-white text-neutral-900" : cn(
1717
+ tone.hairline,
1718
+ tone.muted,
1719
+ tone.isLight ? "hover:bg-neutral-100" : "hover:bg-white/10"
1720
+ )
1721
+ ),
1722
+ children: [
1723
+ icon && /* @__PURE__ */ jsx(DeckIcon, { name: icon, className: "size-4" }),
1724
+ children
1725
+ ]
1726
+ }
1727
+ );
1728
+ });
1729
+ TabButton.displayName = "TabButton";
1730
+ function CycleRenderer({
1731
+ slide,
1732
+ index
1733
+ }) {
1734
+ const tone = toneOf(slide, "deep");
1735
+ const n = slide.nodes.length;
1736
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "deep", children: /* @__PURE__ */ jsxs("div", { className: "grid items-center gap-10 lg:grid-cols-2", children: [
1737
+ /* @__PURE__ */ jsxs("div", { children: [
1738
+ slide.eyebrow && /* @__PURE__ */ jsx(Eyebrow, { children: slide.eyebrow }),
1739
+ /* @__PURE__ */ jsx(SlideTitle, { children: slide.title }),
1740
+ slide.body && /* @__PURE__ */ jsx(
1741
+ "p",
1742
+ {
1743
+ ...reveal(2),
1744
+ className: cn(
1745
+ "mie-deck-reveal mt-6 text-lg leading-relaxed",
1746
+ tone.muted
1747
+ ),
1748
+ children: slide.body
1749
+ }
1750
+ ),
1751
+ slide.talkingPoint && /* @__PURE__ */ jsxs("p", { className: cn("mt-6 italic", tone.muted), children: [
1752
+ "\u201C",
1753
+ slide.talkingPoint,
1754
+ "\u201D"
1755
+ ] })
1756
+ ] }),
1757
+ /* @__PURE__ */ jsx(CycleWheel, { nodes: slide.nodes, n })
1758
+ ] }) });
1759
+ }
1760
+ function CycleWheel({ nodes, n }) {
1761
+ const tone = useTone();
1762
+ const a = accent("accent", tone.isLight);
1763
+ return /* @__PURE__ */ jsxs(
1764
+ "ol",
1765
+ {
1766
+ ...reveal(3),
1767
+ className: "mie-deck-reveal relative mx-auto aspect-square w-64 sm:w-80 md:w-96",
1768
+ children: [
1769
+ /* @__PURE__ */ jsxs(
1770
+ "svg",
1771
+ {
1772
+ "aria-hidden": "true",
1773
+ viewBox: "0 0 400 400",
1774
+ className: "mie-deck-spin absolute inset-0 size-full",
1775
+ children: [
1776
+ /* @__PURE__ */ jsx(
1777
+ "circle",
1778
+ {
1779
+ cx: "200",
1780
+ cy: "200",
1781
+ r: "150",
1782
+ fill: "none",
1783
+ strokeWidth: "2",
1784
+ className: tone.isLight ? "stroke-neutral-200" : "stroke-white/10"
1785
+ }
1786
+ ),
1787
+ /* @__PURE__ */ jsx(
1788
+ "circle",
1789
+ {
1790
+ cx: "200",
1791
+ cy: "200",
1792
+ r: "150",
1793
+ fill: "none",
1794
+ strokeWidth: "2",
1795
+ strokeDasharray: "50 200",
1796
+ strokeLinecap: "round",
1797
+ className: a.svgStroke
1798
+ }
1799
+ ),
1800
+ nodes.map((_, i) => /* @__PURE__ */ jsx(
1801
+ "polygon",
1802
+ {
1803
+ points: "200,47 207,60 193,60",
1804
+ transform: `rotate(${360 / n * i + 180 / n} 200 200)`,
1805
+ className: a.svgFill,
1806
+ opacity: 0.8
1807
+ },
1808
+ i
1809
+ ))
1810
+ ]
1811
+ }
1812
+ ),
1813
+ nodes.map((node, i) => {
1814
+ const angle = 2 * Math.PI * i / n - Math.PI / 2;
1815
+ return /* @__PURE__ */ jsxs(
1816
+ "li",
1817
+ {
1818
+ className: cn(
1819
+ "absolute z-10 w-28 -translate-x-1/2 -translate-y-1/2 rounded-xl border px-3 py-2 text-center shadow-lg backdrop-blur sm:w-32",
1820
+ tone.hairline,
1821
+ tone.isLight ? "bg-white" : "bg-neutral-900/90"
1822
+ ),
1823
+ style: {
1824
+ left: `${50 + 37.5 * Math.cos(angle)}%`,
1825
+ top: `${50 + 37.5 * Math.sin(angle)}%`
1826
+ },
1827
+ children: [
1828
+ node.icon && /* @__PURE__ */ jsx(
1829
+ DeckIcon,
1830
+ {
1831
+ name: node.icon,
1832
+ className: cn("mx-auto mb-1 size-4", a.text)
1833
+ }
1834
+ ),
1835
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-bold sm:text-sm", children: node.label }),
1836
+ node.metric && /* @__PURE__ */ jsx("p", { className: cn("text-sm font-bold sm:text-lg", a.text), children: node.metric })
1837
+ ]
1838
+ },
1839
+ node.label
1840
+ );
1841
+ })
1842
+ ]
1843
+ }
1844
+ );
1845
+ }
1846
+ function RoadmapRenderer({
1847
+ slide,
1848
+ index
1849
+ }) {
1850
+ const { labels } = useDeck();
1851
+ const tone = toneOf(slide, "ink");
1852
+ const a = accent("accent", tone.isLight);
1853
+ const status = {
1854
+ now: labels.statusNow,
1855
+ next: labels.statusNext,
1856
+ later: labels.statusLater
1857
+ };
1858
+ const statusTag = {
1859
+ now: cn(a.soft, a.border, a.text),
1860
+ next: cn(
1861
+ accent("primary", tone.isLight).soft,
1862
+ accent("primary", tone.isLight).border,
1863
+ accent("primary", tone.isLight).text
1864
+ ),
1865
+ later: cn(tone.hairline, tone.muted)
1866
+ };
1867
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "ink", children: [
1868
+ /* @__PURE__ */ jsx(
1869
+ SlideHeader,
1870
+ {
1871
+ eyebrow: slide.eyebrow,
1872
+ title: slide.title,
1873
+ subtitle: slide.subtitle
1874
+ }
1875
+ ),
1876
+ /* @__PURE__ */ jsx(
1877
+ "ol",
1878
+ {
1879
+ className: cn(
1880
+ "relative mt-10 flex flex-col gap-6 border-s ps-8",
1881
+ a.border
1882
+ ),
1883
+ children: slide.items.map((item, i) => {
1884
+ const r = reveal(3 + i);
1885
+ return /* @__PURE__ */ jsxs(
1886
+ "li",
1887
+ {
1888
+ className: cn(r.className, "relative"),
1889
+ style: r.style,
1890
+ children: [
1891
+ /* @__PURE__ */ jsx(
1892
+ "span",
1893
+ {
1894
+ "aria-hidden": "true",
1895
+ className: cn(
1896
+ "absolute -start-[2.35rem] top-1.5 flex size-4 items-center justify-center rounded-full border-2",
1897
+ a.border,
1898
+ tone.isLight ? "bg-white" : "bg-neutral-950"
1899
+ ),
1900
+ children: /* @__PURE__ */ jsx("span", { className: cn("size-1.5 rounded-full", a.fill) })
1901
+ }
1902
+ ),
1903
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
1904
+ item.icon && /* @__PURE__ */ jsx(
1905
+ IconChip,
1906
+ {
1907
+ icon: item.icon,
1908
+ accent: item.status === "later" ? "primary" : "accent"
1909
+ }
1910
+ ),
1911
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold sm:text-xl", children: item.title }),
1912
+ item.status && /* @__PURE__ */ jsx(
1913
+ "span",
1914
+ {
1915
+ className: cn(
1916
+ "rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold tracking-wider uppercase",
1917
+ statusTag[item.status]
1918
+ ),
1919
+ children: status[item.status]
1920
+ }
1921
+ )
1922
+ ] }),
1923
+ item.children && item.children.length > 0 && /* @__PURE__ */ jsx("ul", { className: "mt-2 flex flex-wrap gap-x-6 gap-y-1.5", children: item.children.map((child) => /* @__PURE__ */ jsxs(
1924
+ "li",
1925
+ {
1926
+ className: cn(
1927
+ "flex items-center gap-2 text-sm",
1928
+ tone.muted
1929
+ ),
1930
+ children: [
1931
+ /* @__PURE__ */ jsx(
1932
+ "span",
1933
+ {
1934
+ "aria-hidden": "true",
1935
+ className: "size-1 rounded-full bg-current"
1936
+ }
1937
+ ),
1938
+ child
1939
+ ]
1940
+ },
1941
+ child
1942
+ )) })
1943
+ ]
1944
+ },
1945
+ item.title
1946
+ );
1947
+ })
1948
+ }
1949
+ )
1950
+ ] });
1951
+ }
1952
+ var BASE = 50;
1953
+ var PEAK = 6;
1954
+ var SIGMA = 15;
1955
+ var gaussY = (x) => BASE - (BASE - PEAK) * Math.exp(-((x - 50) ** 2) / (2 * SIGMA * SIGMA));
1956
+ function AdoptionCurveRenderer({
1957
+ slide,
1958
+ index
1959
+ }) {
1960
+ const tone = toneOf(slide, "ink");
1961
+ const clipId = React9.useId();
1962
+ const pts = [];
1963
+ for (let x = 0; x <= 100; x += 1.5) pts.push(`${x},${gaussY(x).toFixed(2)}`);
1964
+ const area = `M 0,${BASE} L ${pts.join(" L ")} L 100,${BASE} Z`;
1965
+ const values = slide.segments.map((s) => parseFloat(s.pct) || 0);
1966
+ const sum = values.reduce((x, y) => x + y, 0) || 1;
1967
+ const widths = values.map((v) => v / sum * 100);
1968
+ const bands = slide.segments.map((s, i) => ({
1969
+ ...s,
1970
+ x0: widths.slice(0, i).reduce((x, y) => x + y, 0),
1971
+ w: widths[i],
1972
+ spec: accent(
1973
+ s.accent ?? ACCENT_CYCLE[i % ACCENT_CYCLE.length],
1974
+ tone.isLight
1975
+ )
1976
+ }));
1977
+ const hi = accent("accent", tone.isLight);
1978
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "ink", width: "lg", children: [
1979
+ /* @__PURE__ */ jsx(
1980
+ SlideHeader,
1981
+ {
1982
+ eyebrow: slide.eyebrow,
1983
+ title: slide.title,
1984
+ subtitle: slide.subtitle
1985
+ }
1986
+ ),
1987
+ /* @__PURE__ */ jsxs("div", { ...reveal(3), className: "mie-deck-reveal relative mt-8 pb-10", children: [
1988
+ slide.annotations?.map((note) => /* @__PURE__ */ jsx(
1989
+ "span",
1990
+ {
1991
+ className: cn(
1992
+ "absolute z-20 w-40 max-w-[42vw] -translate-x-1/2 rounded-lg border px-3 py-1.5 text-center text-xs leading-snug font-semibold",
1993
+ note.emphasis ? cn(hi.soft, hi.border, hi.text) : cn(tone.hairline, tone.card)
1994
+ ),
1995
+ style: {
1996
+ left: `${note.atPct}%`,
1997
+ [note.side === "bottom" ? "bottom" : "top"]: 0
1998
+ },
1999
+ children: note.text
2000
+ },
2001
+ note.text
2002
+ )),
2003
+ /* @__PURE__ */ jsx("div", { className: "h-[clamp(180px,30vh,300px)] w-full", children: /* @__PURE__ */ jsxs(
2004
+ "svg",
2005
+ {
2006
+ viewBox: "0 0 100 56",
2007
+ preserveAspectRatio: "none",
2008
+ className: "size-full overflow-visible",
2009
+ role: "img",
2010
+ "aria-label": slide.segments.map((s) => `${s.label} ${s.pct}`).join(", "),
2011
+ children: [
2012
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: clipId, children: /* @__PURE__ */ jsx("path", { d: area }) }) }),
2013
+ /* @__PURE__ */ jsx("g", { clipPath: `url(#${clipId})`, children: bands.map((b) => /* @__PURE__ */ jsx(
2014
+ "rect",
2015
+ {
2016
+ x: b.x0,
2017
+ y: 0,
2018
+ width: b.w,
2019
+ height: BASE,
2020
+ className: b.spec.svgFill,
2021
+ opacity: 0.8
2022
+ },
2023
+ b.label
2024
+ )) }),
2025
+ /* @__PURE__ */ jsx(
2026
+ "path",
2027
+ {
2028
+ d: `M ${pts.join(" L ")}`,
2029
+ fill: "none",
2030
+ strokeWidth: 1,
2031
+ vectorEffect: "non-scaling-stroke",
2032
+ className: tone.isLight ? "stroke-neutral-900" : "stroke-white"
2033
+ }
2034
+ ),
2035
+ /* @__PURE__ */ jsx(
2036
+ "line",
2037
+ {
2038
+ x1: 0,
2039
+ y1: BASE,
2040
+ x2: 100,
2041
+ y2: BASE,
2042
+ strokeWidth: 0.5,
2043
+ vectorEffect: "non-scaling-stroke",
2044
+ className: tone.isLight ? "stroke-neutral-400" : "stroke-white/25"
2045
+ }
2046
+ )
2047
+ ]
2048
+ }
2049
+ ) }),
2050
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "mt-2 flex w-full", children: bands.map((b) => /* @__PURE__ */ jsxs(
2051
+ "div",
2052
+ {
2053
+ className: "min-w-0 px-1 text-center",
2054
+ style: { flexBasis: `${b.w}%` },
2055
+ children: [
2056
+ /* @__PURE__ */ jsx(
2057
+ "div",
2058
+ {
2059
+ className: cn("text-sm font-bold sm:text-base", b.spec.text),
2060
+ children: b.pct
2061
+ }
2062
+ ),
2063
+ /* @__PURE__ */ jsx(
2064
+ "div",
2065
+ {
2066
+ className: cn(
2067
+ "truncate text-[0.7rem] tracking-wide uppercase sm:text-xs",
2068
+ tone.muted
2069
+ ),
2070
+ children: b.label
2071
+ }
2072
+ )
2073
+ ]
2074
+ },
2075
+ b.label
2076
+ )) }),
2077
+ slide.marker && /* @__PURE__ */ jsxs(
2078
+ "div",
2079
+ {
2080
+ className: "absolute bottom-0 z-20 -translate-x-1/2 text-center",
2081
+ style: { left: `${slide.marker.atPct}%` },
2082
+ children: [
2083
+ /* @__PURE__ */ jsx(
2084
+ "div",
2085
+ {
2086
+ "aria-hidden": "true",
2087
+ className: cn("mx-auto h-4 w-px", hi.fill)
2088
+ }
2089
+ ),
2090
+ /* @__PURE__ */ jsx(
2091
+ "span",
2092
+ {
2093
+ className: cn(
2094
+ "mt-1 inline-block rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase",
2095
+ hi.soft,
2096
+ hi.border,
2097
+ hi.text
2098
+ ),
2099
+ children: slide.marker.label
2100
+ }
2101
+ )
2102
+ ]
2103
+ }
2104
+ )
2105
+ ] }),
2106
+ slide.source && /* @__PURE__ */ jsx(SourceLink, { source: slide.source, className: "mt-4" })
2107
+ ] });
2108
+ }
2109
+ function DiagramRenderer({
2110
+ slide,
2111
+ index
2112
+ }) {
2113
+ const { components } = useDeck();
2114
+ const tone = toneOf(slide, "deep");
2115
+ const center = new Map(slide.nodes.map((n) => [n.id, n]));
2116
+ const left = slide.callouts?.filter((c) => c.side === "left") ?? [];
2117
+ const right = slide.callouts?.filter((c) => c.side === "right") ?? [];
2118
+ const cols = left.length && right.length ? "lg:grid-cols-[minmax(0,1fr)_minmax(0,2.4fr)_minmax(0,1fr)]" : right.length ? "lg:grid-cols-[minmax(0,2.7fr)_minmax(0,1.25fr)]" : left.length ? "lg:grid-cols-[minmax(0,1.25fr)_minmax(0,2.7fr)]" : "";
2119
+ const stageBg = tone.isLight ? "bg-white" : "bg-neutral-900";
2120
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "deep", children: [
2121
+ /* @__PURE__ */ jsx(
2122
+ SlideHeader,
2123
+ {
2124
+ eyebrow: slide.eyebrow,
2125
+ title: slide.title,
2126
+ subtitle: slide.subtitle
2127
+ }
2128
+ ),
2129
+ /* @__PURE__ */ jsxs("div", { className: cn("mt-8", cols && cn("grid items-center gap-6", cols)), children: [
2130
+ left.length > 0 && /* @__PURE__ */ jsx(Callouts, { callouts: left, end: true }),
2131
+ /* @__PURE__ */ jsxs(
2132
+ "div",
2133
+ {
2134
+ ...reveal(3),
2135
+ className: "mie-deck-reveal relative mx-auto h-[clamp(260px,40vh,440px)] w-full max-w-3xl",
2136
+ children: [
2137
+ slide.boundaries?.map((b) => {
2138
+ const xs = b.nodes.map((id) => center.get(id)?.x ?? 50);
2139
+ const ys = b.nodes.map((id) => center.get(id)?.y ?? 50);
2140
+ const l = Math.min(...xs) - 13;
2141
+ const t = Math.min(...ys) - 17;
2142
+ const spec = accent(b.accent ?? "primary", tone.isLight);
2143
+ return /* @__PURE__ */ jsx(
2144
+ "div",
2145
+ {
2146
+ className: cn(
2147
+ "absolute rounded-2xl border border-dashed",
2148
+ tone.hairline
2149
+ ),
2150
+ style: {
2151
+ left: `${l}%`,
2152
+ top: `${t}%`,
2153
+ width: `${Math.max(...xs) + 13 - l}%`,
2154
+ height: `${Math.max(...ys) + 17 - t}%`
2155
+ },
2156
+ children: /* @__PURE__ */ jsx(
2157
+ "span",
2158
+ {
2159
+ className: cn(
2160
+ "absolute start-4 -top-3 rounded-full border px-2.5 py-0.5 text-[0.6rem] font-semibold tracking-wide uppercase",
2161
+ stageBg,
2162
+ spec.border,
2163
+ spec.text
2164
+ ),
2165
+ children: b.label
2166
+ }
2167
+ )
2168
+ },
2169
+ b.label
2170
+ );
2171
+ }),
2172
+ /* @__PURE__ */ jsx(
2173
+ "svg",
2174
+ {
2175
+ "aria-hidden": "true",
2176
+ viewBox: "0 0 100 100",
2177
+ preserveAspectRatio: "none",
2178
+ className: "absolute inset-0 size-full",
2179
+ children: slide.edges.map((e) => {
2180
+ const a = center.get(e.from);
2181
+ const b = center.get(e.to);
2182
+ if (!a || !b) return null;
2183
+ return /* @__PURE__ */ jsx(
2184
+ "line",
2185
+ {
2186
+ x1: a.x,
2187
+ y1: a.y,
2188
+ x2: b.x,
2189
+ y2: b.y,
2190
+ strokeWidth: 1.2,
2191
+ strokeDasharray: e.dashed ? "4 3" : void 0,
2192
+ vectorEffect: "non-scaling-stroke",
2193
+ className: e.accent ? accent(e.accent, tone.isLight).svgStroke : tone.isLight ? "stroke-neutral-400" : "stroke-white/30"
2194
+ },
2195
+ `${e.from}-${e.to}`
2196
+ );
2197
+ })
2198
+ }
2199
+ ),
2200
+ slide.edges.map((e, i) => {
2201
+ const a = center.get(e.from);
2202
+ const b = center.get(e.to);
2203
+ if (!a || !b || !e.flow) return null;
2204
+ return /* @__PURE__ */ jsx(
2205
+ "span",
2206
+ {
2207
+ "aria-hidden": "true",
2208
+ className: cn(
2209
+ "mie-deck-flow absolute size-2 -translate-x-1/2 -translate-y-1/2 rounded-full",
2210
+ accent(e.accent ?? "accent", tone.isLight).fill
2211
+ ),
2212
+ style: {
2213
+ "--mie-from-x": `${a.x}%`,
2214
+ "--mie-from-y": `${a.y}%`,
2215
+ "--mie-to-x": `${b.x}%`,
2216
+ "--mie-to-y": `${b.y}%`,
2217
+ animationDelay: `${i * 0.5}s`
2218
+ }
2219
+ },
2220
+ `flow-${e.from}-${e.to}`
2221
+ );
2222
+ }),
2223
+ slide.edges.map((e) => {
2224
+ const a = center.get(e.from);
2225
+ const b = center.get(e.to);
2226
+ if (!a || !b || !e.label) return null;
2227
+ const at = e.labelAt ?? 0.5;
2228
+ return /* @__PURE__ */ jsx(
2229
+ "span",
2230
+ {
2231
+ className: cn(
2232
+ "absolute z-10 -translate-x-1/2 -translate-y-1/2 rounded-md border px-1.5 py-0.5 text-[0.6rem] font-medium whitespace-nowrap",
2233
+ stageBg,
2234
+ tone.hairline,
2235
+ tone.muted
2236
+ ),
2237
+ style: {
2238
+ left: `${a.x + (b.x - a.x) * at}%`,
2239
+ top: `${a.y + (b.y - a.y) * at}%`
2240
+ },
2241
+ children: e.label
2242
+ },
2243
+ `label-${e.from}-${e.to}`
2244
+ );
2245
+ }),
2246
+ slide.nodes.map((node) => {
2247
+ const spec = accent(node.accent ?? "primary", tone.isLight);
2248
+ return /* @__PURE__ */ jsx(
2249
+ "div",
2250
+ {
2251
+ className: "absolute z-[5] -translate-x-1/2 -translate-y-1/2",
2252
+ style: {
2253
+ left: `${node.x}%`,
2254
+ top: `${node.y}%`,
2255
+ width: `${node.w ?? 20}%`
2256
+ },
2257
+ children: /* @__PURE__ */ jsxs(
2258
+ "div",
2259
+ {
2260
+ className: cn(
2261
+ "flex flex-col items-center gap-1.5 rounded-xl border px-2 py-3 text-center shadow-lg",
2262
+ stageBg,
2263
+ spec.border
2264
+ ),
2265
+ children: [
2266
+ node.image ? /* @__PURE__ */ jsx(
2267
+ TemplateImg,
2268
+ {
2269
+ ...node.image,
2270
+ components,
2271
+ className: "h-7 w-auto object-contain sm:h-9"
2272
+ }
2273
+ ) : node.icon && /* @__PURE__ */ jsx(
2274
+ DeckIcon,
2275
+ {
2276
+ name: node.icon,
2277
+ className: cn("size-5 sm:size-6", spec.text)
2278
+ }
2279
+ ),
2280
+ /* @__PURE__ */ jsx("span", { className: "text-[0.62rem] leading-tight font-semibold sm:text-xs", children: node.label })
2281
+ ]
2282
+ }
2283
+ )
2284
+ },
2285
+ node.id
2286
+ );
2287
+ })
2288
+ ]
2289
+ }
2290
+ ),
2291
+ right.length > 0 && /* @__PURE__ */ jsx(Callouts, { callouts: right })
2292
+ ] })
2293
+ ] });
2294
+ }
2295
+ function Callouts({
2296
+ callouts,
2297
+ end
2298
+ }) {
2299
+ const tone = useTone();
2300
+ const a = accent("accent", tone.isLight);
2301
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-4", end && "lg:text-end"), children: callouts.map((c, i) => /* @__PURE__ */ jsxs(Card, { i: 4 + i, className: "p-4", children: [
2302
+ c.lead && /* @__PURE__ */ jsx("div", { className: cn("text-sm font-bold", a.text), children: c.lead }),
2303
+ /* @__PURE__ */ jsx("p", { className: cn("mt-1 text-sm leading-snug", tone.muted), children: c.text })
2304
+ ] }, c.text)) });
2305
+ }
2306
+ function BadgeCard({ cert, i }) {
2307
+ const { components } = useDeck();
2308
+ const tone = useTone();
2309
+ const a = accent(cert.accent ?? "accent", tone.isLight);
2310
+ return /* @__PURE__ */ jsxs(Card, { i, className: "flex flex-col items-center p-3 text-center", children: [
2311
+ cert.image ? /* @__PURE__ */ jsx("div", { className: "mb-2 flex h-11 items-center justify-center rounded-lg bg-white px-2.5", children: /* @__PURE__ */ jsx(
2312
+ TemplateImg,
2313
+ {
2314
+ ...cert.image,
2315
+ components,
2316
+ className: "h-7 w-auto max-w-[72px] object-contain"
2317
+ }
2318
+ ) }) : /* @__PURE__ */ jsx(
2319
+ "div",
2320
+ {
2321
+ "aria-hidden": "true",
2322
+ className: cn(
2323
+ "mb-2 flex size-10 items-center justify-center rounded-lg border text-sm font-extrabold",
2324
+ a.soft,
2325
+ a.border,
2326
+ a.text
2327
+ ),
2328
+ children: cert.badge ?? cert.name.slice(0, 3).toUpperCase()
2329
+ }
2330
+ ),
2331
+ /* @__PURE__ */ jsx("div", { className: "text-[0.8rem] leading-tight font-bold", children: cert.name }),
2332
+ cert.issuer && /* @__PURE__ */ jsx(
2333
+ "div",
2334
+ {
2335
+ className: cn(
2336
+ "mt-0.5 text-[0.62rem] tracking-wide uppercase",
2337
+ tone.muted
2338
+ ),
2339
+ children: cert.issuer
2340
+ }
2341
+ ),
2342
+ cert.source && /* @__PURE__ */ jsx(SourceLink, { source: cert.source, className: "mt-1.5" })
2343
+ ] });
2344
+ }
2345
+ function CertificationGridRenderer({
2346
+ slide,
2347
+ index
2348
+ }) {
2349
+ const { components } = useDeck();
2350
+ const tone = toneOf(slide, "deep");
2351
+ const count = slide.certifications.length;
2352
+ const featured = slide.featured;
2353
+ const cols = featured ? "sm:grid-cols-3 lg:grid-cols-4" : count >= 5 ? "sm:grid-cols-3 lg:grid-cols-5" : count === 4 ? "sm:grid-cols-2 lg:grid-cols-4" : "sm:grid-cols-3";
2354
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "deep", children: [
2355
+ /* @__PURE__ */ jsx(
2356
+ SlideHeader,
2357
+ {
2358
+ eyebrow: slide.eyebrow,
2359
+ title: slide.title,
2360
+ subtitle: slide.subtitle
2361
+ }
2362
+ ),
2363
+ /* @__PURE__ */ jsxs(
2364
+ "div",
2365
+ {
2366
+ className: featured ? "mt-7 grid items-center gap-8 lg:grid-cols-[auto_minmax(0,1fr)] lg:gap-12" : "mt-6",
2367
+ children: [
2368
+ featured && /* @__PURE__ */ jsxs(
2369
+ "div",
2370
+ {
2371
+ ...reveal(3),
2372
+ className: "mie-deck-reveal flex flex-col items-center text-center",
2373
+ children: [
2374
+ /* @__PURE__ */ jsx("div", { className: "flex size-40 items-center justify-center rounded-full bg-white p-2 shadow-2xl sm:size-48", children: featured.image ? /* @__PURE__ */ jsx(
2375
+ TemplateImg,
2376
+ {
2377
+ ...featured.image,
2378
+ components,
2379
+ className: "size-full object-contain"
2380
+ }
2381
+ ) : /* @__PURE__ */ jsx("span", { className: "text-2xl font-extrabold text-neutral-900", children: featured.badge ?? featured.name }) }),
2382
+ /* @__PURE__ */ jsx("p", { className: "mt-4 font-semibold", children: featured.name }),
2383
+ featured.description && /* @__PURE__ */ jsx(
2384
+ "p",
2385
+ {
2386
+ className: cn(
2387
+ "mt-1 max-w-[15rem] text-sm leading-snug",
2388
+ tone.muted
2389
+ ),
2390
+ children: featured.description
2391
+ }
2392
+ ),
2393
+ featured.source && /* @__PURE__ */ jsx(SourceLink, { source: featured.source, className: "mt-2.5" })
2394
+ ]
2395
+ }
2396
+ ),
2397
+ /* @__PURE__ */ jsx("div", { className: cn("grid grid-cols-2 gap-3", cols), children: slide.certifications.map((cert, i) => /* @__PURE__ */ jsx(BadgeCard, { cert, i: 4 + i }, cert.name)) })
2398
+ ]
2399
+ }
2400
+ ),
2401
+ slide.footnote && /* @__PURE__ */ jsx(SourceLink, { source: slide.footnote, className: "mt-6" })
2402
+ ] });
2403
+ }
2404
+ var VISIBLE = 3;
2405
+ function ShowcaseCategory({
2406
+ category,
2407
+ i
2408
+ }) {
2409
+ const { labels } = useDeck();
2410
+ const tone = useTone();
2411
+ const a = accent("primary", tone.isLight);
2412
+ const [open, setOpen] = React9.useState(false);
2413
+ const listId = React9.useId();
2414
+ const hidden = category.items.length - VISIBLE;
2415
+ return /* @__PURE__ */ jsxs(Card, { i, className: "p-4", children: [
2416
+ /* @__PURE__ */ jsxs(
2417
+ "h3",
2418
+ {
2419
+ className: cn(
2420
+ "mb-3 flex items-center gap-2 text-xs font-bold tracking-wider uppercase",
2421
+ a.text
2422
+ ),
2423
+ children: [
2424
+ category.icon && /* @__PURE__ */ jsx(DeckIcon, { name: category.icon, className: "size-4" }),
2425
+ category.title,
2426
+ /* @__PURE__ */ jsx("span", { className: cn("ms-auto tabular-nums", tone.muted), children: category.items.length })
2427
+ ]
2428
+ }
2429
+ ),
2430
+ /* @__PURE__ */ jsx("ul", { id: listId, className: "space-y-1", children: (open ? category.items : category.items.slice(0, VISIBLE)).map(
2431
+ (item) => /* @__PURE__ */ jsxs(
2432
+ "li",
2433
+ {
2434
+ className: cn("flex gap-2 text-xs leading-relaxed", tone.muted),
2435
+ children: [
2436
+ /* @__PURE__ */ jsx(
2437
+ ChevronRight,
2438
+ {
2439
+ "aria-hidden": "true",
2440
+ className: "mt-0.5 size-3 flex-none rtl:-scale-x-100"
2441
+ }
2442
+ ),
2443
+ item
2444
+ ]
2445
+ },
2446
+ item
2447
+ )
2448
+ ) }),
2449
+ hidden > 0 && /* @__PURE__ */ jsx(
2450
+ "button",
2451
+ {
2452
+ type: "button",
2453
+ "aria-expanded": open,
2454
+ "aria-controls": listId,
2455
+ onClick: () => setOpen((o) => !o),
2456
+ className: cn(
2457
+ "mt-2 text-xs font-medium underline-offset-2 hover:underline",
2458
+ a.text
2459
+ ),
2460
+ children: open ? labels.less : labels.more(hidden)
2461
+ }
2462
+ )
2463
+ ] });
2464
+ }
2465
+ function ShowcaseRenderer({
2466
+ slide,
2467
+ index
2468
+ }) {
2469
+ const { components, labels } = useDeck();
2470
+ const tone = toneOf(slide, "deep");
2471
+ const a = accent("accent", tone.isLight);
2472
+ const video = slide.video;
2473
+ const videoHref = video ? safeHref(video.href) : void 0;
2474
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "deep", children: [
2475
+ /* @__PURE__ */ jsxs("div", { className: "mb-6 flex flex-col items-start gap-4 sm:flex-row sm:items-end sm:justify-between", children: [
2476
+ /* @__PURE__ */ jsx(
2477
+ SlideHeader,
2478
+ {
2479
+ eyebrow: slide.eyebrow,
2480
+ title: slide.title,
2481
+ subtitle: slide.subtitle
2482
+ }
2483
+ ),
2484
+ slide.total && /* @__PURE__ */ jsxs(
2485
+ "div",
2486
+ {
2487
+ ...reveal(2),
2488
+ className: cn(
2489
+ "mie-deck-reveal flex flex-none items-baseline gap-2 rounded-full border px-5 py-2",
2490
+ a.soft,
2491
+ a.border
2492
+ ),
2493
+ children: [
2494
+ /* @__PURE__ */ jsx("span", { className: cn("text-3xl font-bold", a.text), children: /* @__PURE__ */ jsx(CountUp, { value: slide.total.value }) }),
2495
+ /* @__PURE__ */ jsx("span", { className: cn("text-sm", tone.muted), children: slide.total.label })
2496
+ ]
2497
+ }
2498
+ )
2499
+ ] }),
2500
+ /* @__PURE__ */ jsxs(
2501
+ "div",
2502
+ {
2503
+ className: cn("grid gap-6", videoHref && "lg:grid-cols-[1fr_300px]"),
2504
+ children: [
2505
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3", children: slide.categories.map((cat, i) => /* @__PURE__ */ jsx(ShowcaseCategory, { category: cat, i: 3 + i }, cat.title)) }),
2506
+ video && videoHref && /* @__PURE__ */ jsxs(
2507
+ "a",
2508
+ {
2509
+ href: videoHref,
2510
+ target: "_blank",
2511
+ rel: "noopener noreferrer",
2512
+ ...reveal(5),
2513
+ className: cn(
2514
+ "mie-deck-reveal group flex flex-col overflow-hidden rounded-xl border lg:self-start",
2515
+ tone.hairline,
2516
+ tone.card
2517
+ ),
2518
+ children: [
2519
+ /* @__PURE__ */ jsxs("div", { className: "relative flex aspect-video items-center justify-center overflow-hidden bg-neutral-900", children: [
2520
+ video.thumbnail && /* @__PURE__ */ jsx(
2521
+ TemplateImg,
2522
+ {
2523
+ ...video.thumbnail,
2524
+ components,
2525
+ className: "absolute inset-0 size-full object-cover transition-transform duration-300 group-hover:scale-105"
2526
+ }
2527
+ ),
2528
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/30" }),
2529
+ /* @__PURE__ */ jsx("span", { className: "bg-primary-600 relative flex size-14 items-center justify-center rounded-full border-2 border-white/30 shadow-xl transition-transform group-hover:scale-110", children: /* @__PURE__ */ jsx(
2530
+ Play,
2531
+ {
2532
+ "aria-hidden": "true",
2533
+ className: "ms-1 size-6 fill-white text-white"
2534
+ }
2535
+ ) }),
2536
+ video.duration && /* @__PURE__ */ jsx("span", { className: "absolute end-2 bottom-2 rounded bg-black/60 px-2 py-0.5 font-mono text-xs text-white tabular-nums", children: video.duration })
2537
+ ] }),
2538
+ /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
2539
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-sm font-semibold", children: video.title }),
2540
+ video.speaker && /* @__PURE__ */ jsx("p", { className: cn("mb-2 text-xs", tone.muted), children: video.speaker }),
2541
+ /* @__PURE__ */ jsxs(
2542
+ "span",
2543
+ {
2544
+ className: cn(
2545
+ "inline-flex items-center gap-1 text-xs font-medium",
2546
+ a.text
2547
+ ),
2548
+ children: [
2549
+ video.cta ?? labels.watchVideo,
2550
+ /* @__PURE__ */ jsx(ExternalLink, { "aria-hidden": "true", className: "size-3" })
2551
+ ]
2552
+ }
2553
+ )
2554
+ ] })
2555
+ ]
2556
+ }
2557
+ )
2558
+ ]
2559
+ }
2560
+ )
2561
+ ] });
2562
+ }
2563
+ function Highlights({
2564
+ items
2565
+ }) {
2566
+ const r = reveal(3);
2567
+ return /* @__PURE__ */ jsx(
2568
+ "div",
2569
+ {
2570
+ className: cn(
2571
+ r.className,
2572
+ "mt-10 flex flex-wrap items-center justify-center gap-x-10 gap-y-6"
2573
+ ),
2574
+ style: r.style,
2575
+ children: items.map((h) => /* @__PURE__ */ jsx(HighlightFigure, { value: h.value, label: h.label }, h.label))
2576
+ }
2577
+ );
2578
+ }
2579
+ function CoverRenderer({
2580
+ slide,
2581
+ index
2582
+ }) {
2583
+ const { components } = useDeck();
2584
+ const tone = toneOf(slide, "brand");
2585
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "brand", width: "md", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center text-center", children: [
2586
+ slide.image && /* @__PURE__ */ jsx(
2587
+ TemplateImg,
2588
+ {
2589
+ ...slide.image,
2590
+ priority: index === 0,
2591
+ components,
2592
+ className: "mb-8 h-32 w-auto object-contain sm:h-40"
2593
+ }
2594
+ ),
2595
+ slide.eyebrow && /* @__PURE__ */ jsx(Eyebrow, { children: slide.eyebrow }),
2596
+ /* @__PURE__ */ jsx(SlideTitle, { size: "xl", children: slide.title }),
2597
+ slide.subtitle && /* @__PURE__ */ jsx(Subtitle, { className: "mx-auto sm:text-xl", children: slide.subtitle }),
2598
+ slide.highlights && slide.highlights.length > 0 && /* @__PURE__ */ jsx(Highlights, { items: slide.highlights }),
2599
+ (slide.dateline || slide.preparedBy) && /* @__PURE__ */ jsx("p", { className: cn("mt-10 text-sm", tone.muted), children: [slide.preparedBy, slide.dateline].filter(Boolean).join(" \xB7 ") })
2600
+ ] }) });
2601
+ }
2602
+ function SectionDividerRenderer({
2603
+ slide,
2604
+ index
2605
+ }) {
2606
+ const { components } = useDeck();
2607
+ const tone = toneOf(slide, "glow");
2608
+ const a = accent("accent", tone.isLight);
2609
+ const hasImage = !!slide.image;
2610
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "glow", children: /* @__PURE__ */ jsxs(
2611
+ "div",
2612
+ {
2613
+ className: hasImage ? "grid items-center gap-10 md:grid-cols-2 lg:gap-16" : "flex flex-col items-center text-center",
2614
+ children: [
2615
+ slide.image && /* @__PURE__ */ jsx("div", { ...reveal(0), className: "mie-deck-reveal order-2 md:order-1", children: /* @__PURE__ */ jsx(
2616
+ TemplateImg,
2617
+ {
2618
+ ...slide.image,
2619
+ components,
2620
+ className: "mx-auto aspect-[3/4] w-full max-w-sm rounded-2xl object-cover"
2621
+ }
2622
+ ) }),
2623
+ /* @__PURE__ */ jsxs("div", { className: hasImage ? "order-1 md:order-2" : "max-w-4xl", children: [
2624
+ slide.eyebrow && /* @__PURE__ */ jsx(Eyebrow, { children: slide.eyebrow }),
2625
+ slide.statement && /* @__PURE__ */ jsx(
2626
+ "p",
2627
+ {
2628
+ ...reveal(1),
2629
+ className: "mie-deck-reveal text-6xl font-extrabold tracking-tight text-balance sm:text-7xl lg:text-8xl",
2630
+ children: slide.statement
2631
+ }
2632
+ ),
2633
+ /* @__PURE__ */ jsx(
2634
+ SlideTitle,
2635
+ {
2636
+ size: slide.statement ? "md" : "lg",
2637
+ className: cn(slide.statement && "mt-3 font-semibold opacity-80"),
2638
+ children: slide.title
2639
+ }
2640
+ ),
2641
+ slide.description && /* @__PURE__ */ jsx(Subtitle, { className: cn(!hasImage && "mx-auto"), children: slide.description }),
2642
+ /* @__PURE__ */ jsx(
2643
+ "div",
2644
+ {
2645
+ "aria-hidden": "true",
2646
+ className: cn(
2647
+ "mt-8 h-1 w-24 rounded-full",
2648
+ a.fill,
2649
+ !hasImage && "mx-auto"
2650
+ )
2651
+ }
2652
+ )
2653
+ ] })
2654
+ ]
2655
+ }
2656
+ ) });
2657
+ }
2658
+ function TableOfContentsRenderer({
2659
+ slide,
2660
+ index
2661
+ }) {
2662
+ const { slides, activeSlide, goTo, labels } = useDeck();
2663
+ const tone = toneOf(slide, "brand");
2664
+ const a = accent("accent", tone.isLight);
2665
+ const sections = slide.sections ?? Object.entries(
2666
+ slides.reduce((acc, s, i) => {
2667
+ if (i === index || !("title" in s) || !s.title) return acc;
2668
+ (acc[s.section ?? ""] ??= []).push({
2669
+ number: i + 1,
2670
+ title: s.navLabel ?? s.title
2671
+ });
2672
+ return acc;
2673
+ }, {})
2674
+ ).map(([heading, items]) => ({ heading: heading || void 0, items }));
2675
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "brand", children: [
2676
+ /* @__PURE__ */ jsx(
2677
+ SlideHeader,
2678
+ {
2679
+ eyebrow: slide.eyebrow,
2680
+ title: slide.title,
2681
+ subtitle: slide.description
2682
+ }
2683
+ ),
2684
+ /* @__PURE__ */ jsx("nav", { "aria-label": labels.outline, className: "mt-6 md:columns-2 md:gap-12", children: sections.map((section, s) => /* @__PURE__ */ jsxs(
2685
+ "div",
2686
+ {
2687
+ ...reveal(3 + s),
2688
+ className: "mie-deck-reveal mb-5 break-inside-avoid",
2689
+ children: [
2690
+ section.heading && /* @__PURE__ */ jsx(
2691
+ "h3",
2692
+ {
2693
+ className: cn(
2694
+ "mb-1.5 text-xs font-semibold tracking-[0.2em] uppercase",
2695
+ a.text
2696
+ ),
2697
+ children: section.heading
2698
+ }
2699
+ ),
2700
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-0.5", children: section.items.map((entry) => {
2701
+ const target = entry.number - 1;
2702
+ const current = target === activeSlide;
2703
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
2704
+ "button",
2705
+ {
2706
+ type: "button",
2707
+ onClick: () => goTo(target),
2708
+ "aria-current": current ? "true" : void 0,
2709
+ className: cn(
2710
+ "flex w-full items-baseline gap-3 rounded-lg px-3 py-1 text-start transition-colors",
2711
+ current ? a.soft : tone.isLight ? "hover:bg-neutral-100" : "hover:bg-white/5"
2712
+ ),
2713
+ children: [
2714
+ /* @__PURE__ */ jsx(
2715
+ "span",
2716
+ {
2717
+ className: cn(
2718
+ "text-sm font-semibold tabular-nums",
2719
+ a.text
2720
+ ),
2721
+ children: String(entry.number).padStart(2, "0")
2722
+ }
2723
+ ),
2724
+ /* @__PURE__ */ jsxs("span", { children: [
2725
+ entry.title,
2726
+ entry.subtitle && /* @__PURE__ */ jsx("span", { className: cn("block text-xs", tone.muted), children: entry.subtitle })
2727
+ ] })
2728
+ ]
2729
+ }
2730
+ ) }, entry.number);
2731
+ }) })
2732
+ ]
2733
+ },
2734
+ section.heading ?? s
2735
+ )) })
2736
+ ] });
2737
+ }
2738
+ function BulletListRenderer({
2739
+ slide,
2740
+ index
2741
+ }) {
2742
+ const tone = toneOf(slide, "brand");
2743
+ const r = reveal(3);
2744
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "brand", width: "lg", children: [
2745
+ /* @__PURE__ */ jsx(
2746
+ SlideHeader,
2747
+ {
2748
+ eyebrow: slide.eyebrow,
2749
+ title: slide.title,
2750
+ subtitle: slide.subtitle
2751
+ }
2752
+ ),
2753
+ /* @__PURE__ */ jsx(
2754
+ "ul",
2755
+ {
2756
+ className: cn(r.className, "mt-10 flex flex-col gap-4"),
2757
+ style: r.style,
2758
+ children: slide.items.map((item, i) => /* @__PURE__ */ jsx(Bullet, { item }, i))
2759
+ }
2760
+ ),
2761
+ slide.note && /* @__PURE__ */ jsx("p", { className: cn("mt-8 text-sm italic", tone.muted), children: slide.note })
2762
+ ] });
2763
+ }
2764
+ function QuoteRenderer({
2765
+ slide,
2766
+ index
2767
+ }) {
2768
+ const tone = toneOf(slide, "brand");
2769
+ const a = accent("accent", tone.isLight);
2770
+ return /* @__PURE__ */ jsx(
2771
+ SlideFrame,
2772
+ {
2773
+ slide: {
2774
+ ...slide,
2775
+ navLabel: slide.navLabel ?? slide.title ?? slide.attribution
2776
+ },
2777
+ index,
2778
+ tone: "brand",
2779
+ width: "md",
2780
+ children: /* @__PURE__ */ jsxs("figure", { className: "flex flex-col items-center text-center", children: [
2781
+ slide.eyebrow && /* @__PURE__ */ jsx(Eyebrow, { children: slide.eyebrow }),
2782
+ slide.title && /* @__PURE__ */ jsx(SlideTitle, { size: "md", className: "mb-6", children: slide.title }),
2783
+ /* @__PURE__ */ jsx(
2784
+ "span",
2785
+ {
2786
+ "aria-hidden": "true",
2787
+ className: cn("text-7xl leading-none sm:text-8xl", a.text),
2788
+ children: "\u201C"
2789
+ }
2790
+ ),
2791
+ /* @__PURE__ */ jsx(
2792
+ "blockquote",
2793
+ {
2794
+ ...reveal(2),
2795
+ className: "mie-deck-reveal -mt-4 text-2xl leading-snug font-semibold text-balance sm:text-3xl lg:text-4xl",
2796
+ children: slide.quote
2797
+ }
2798
+ ),
2799
+ (slide.attribution || slide.role) && /* @__PURE__ */ jsxs("figcaption", { ...reveal(3), className: "mie-deck-reveal mt-8", children: [
2800
+ slide.attribution && /* @__PURE__ */ jsx("span", { className: cn("text-lg font-semibold", a.text), children: slide.attribution }),
2801
+ slide.role && /* @__PURE__ */ jsx("span", { className: cn("block text-sm", tone.muted), children: slide.role })
2802
+ ] }),
2803
+ slide.source && /* @__PURE__ */ jsx(SourceLink, { source: slide.source, className: "mt-5" })
2804
+ ] })
2805
+ }
2806
+ );
2807
+ }
2808
+ function ImageRenderer({
2809
+ slide,
2810
+ index
2811
+ }) {
2812
+ const { components } = useDeck();
2813
+ const tone = toneOf(slide, "ink");
2814
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "ink", children: [
2815
+ /* @__PURE__ */ jsx(SlideTitle, { className: "mb-8 text-center", children: slide.title }),
2816
+ /* @__PURE__ */ jsxs("figure", { ...reveal(2), className: "mie-deck-reveal", children: [
2817
+ /* @__PURE__ */ jsx(
2818
+ TemplateImg,
2819
+ {
2820
+ ...slide.image,
2821
+ components,
2822
+ className: "mx-auto max-h-[65dvh] w-auto rounded-2xl object-contain shadow-2xl"
2823
+ }
2824
+ ),
2825
+ slide.caption && /* @__PURE__ */ jsx("figcaption", { className: cn("mt-4 text-center text-sm", tone.muted), children: slide.caption })
2826
+ ] })
2827
+ ] });
2828
+ }
2829
+ function DefinitionListRenderer({
2830
+ slide,
2831
+ index
2832
+ }) {
2833
+ const tone = toneOf(slide, "brand");
2834
+ const a = accent("accent", tone.isLight);
2835
+ return /* @__PURE__ */ jsxs(SlideFrame, { slide, index, tone: "brand", children: [
2836
+ /* @__PURE__ */ jsx(
2837
+ SlideHeader,
2838
+ {
2839
+ eyebrow: slide.eyebrow,
2840
+ title: slide.title,
2841
+ subtitle: slide.subtitle
2842
+ }
2843
+ ),
2844
+ /* @__PURE__ */ jsx("dl", { className: "mt-6 flex flex-col gap-2", children: slide.terms.map((term, i) => {
2845
+ const initial = term.term.charAt(0);
2846
+ const r = reveal(3 + i);
2847
+ return (
2848
+ // A <dl> group div may contain only <dt>/<dd> (axe dlitem).
2849
+ /* @__PURE__ */ jsxs(
2850
+ "div",
2851
+ {
2852
+ className: cn(
2853
+ r.className,
2854
+ "rounded-xl border p-3",
2855
+ tone.card,
2856
+ tone.hairline
2857
+ ),
2858
+ style: r.style,
2859
+ children: [
2860
+ /* @__PURE__ */ jsxs("dt", { className: "flex items-center gap-4 text-base font-bold sm:text-lg", children: [
2861
+ /* @__PURE__ */ jsx(
2862
+ "span",
2863
+ {
2864
+ "aria-hidden": "true",
2865
+ className: cn(
2866
+ "flex size-10 flex-none items-center justify-center rounded-lg border text-xl font-extrabold",
2867
+ a.soft,
2868
+ a.border,
2869
+ a.text
2870
+ ),
2871
+ children: initial
2872
+ }
2873
+ ),
2874
+ term.term
2875
+ ] }),
2876
+ /* @__PURE__ */ jsxs(
2877
+ "dd",
2878
+ {
2879
+ className: cn(
2880
+ "ms-14 mt-0.5 text-sm leading-relaxed",
2881
+ tone.muted
2882
+ ),
2883
+ children: [
2884
+ term.lead && /* @__PURE__ */ jsxs("span", { className: cn("font-semibold", tone.text), children: [
2885
+ term.lead,
2886
+ " "
2887
+ ] }),
2888
+ term.definition
2889
+ ]
2890
+ }
2891
+ )
2892
+ ]
2893
+ },
2894
+ term.term
2895
+ )
2896
+ );
2897
+ }) }),
2898
+ slide.source && /* @__PURE__ */ jsx(SourceLink, { source: slide.source, className: "mt-4" })
2899
+ ] });
2900
+ }
2901
+ function CopyLink({ url }) {
2902
+ const { labels } = useDeck();
2903
+ const tone = useTone();
2904
+ const [copied, setCopied] = React9.useState(false);
2905
+ React9.useEffect(() => {
2906
+ if (!copied) return;
2907
+ const t = setTimeout(() => setCopied(false), 2e3);
2908
+ return () => clearTimeout(t);
2909
+ }, [copied]);
2910
+ return /* @__PURE__ */ jsxs(
2911
+ "div",
2912
+ {
2913
+ className: cn(
2914
+ "mt-8 flex w-full max-w-xl items-center gap-2 rounded-xl border p-2",
2915
+ tone.card,
2916
+ tone.hairline
2917
+ ),
2918
+ children: [
2919
+ /* @__PURE__ */ jsx("code", { className: "min-w-0 flex-1 truncate px-2 text-start text-sm", children: url }),
2920
+ /* @__PURE__ */ jsxs(
2921
+ "button",
2922
+ {
2923
+ type: "button",
2924
+ onClick: () => navigator.clipboard?.writeText(url).then(
2925
+ () => setCopied(true),
2926
+ () => {
2927
+ }
2928
+ ),
2929
+ className: cn(
2930
+ "inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-semibold",
2931
+ tone.isLight ? "bg-neutral-900 text-white" : "bg-white text-neutral-900"
2932
+ ),
2933
+ children: [
2934
+ copied ? /* @__PURE__ */ jsx(Check, { "aria-hidden": "true", className: "size-4" }) : /* @__PURE__ */ jsx(Copy, { "aria-hidden": "true", className: "size-4" }),
2935
+ /* @__PURE__ */ jsx("span", { "aria-live": "polite", children: copied ? labels.copied : labels.copy })
2936
+ ]
2937
+ }
2938
+ )
2939
+ ]
2940
+ }
2941
+ );
2942
+ }
2943
+ function CtaButton({ link, primary }) {
2944
+ const { components } = useDeck();
2945
+ const tone = useTone();
2946
+ return /* @__PURE__ */ jsxs(
2947
+ TemplateAnchor,
2948
+ {
2949
+ href: link.href,
2950
+ trackingId: link.trackingId,
2951
+ components,
2952
+ className: cn(
2953
+ "inline-flex items-center gap-2 rounded-full px-6 py-3 text-sm font-semibold transition-colors",
2954
+ primary ? "bg-accent text-neutral-950 hover:opacity-90" : cn(
2955
+ "border",
2956
+ tone.hairline,
2957
+ tone.isLight ? "hover:bg-neutral-100" : "hover:bg-white/10"
2958
+ )
2959
+ ),
2960
+ children: [
2961
+ link.label,
2962
+ primary && /* @__PURE__ */ jsx(ArrowRight, { "aria-hidden": "true", className: "size-4 rtl:-scale-x-100" })
2963
+ ]
2964
+ }
2965
+ );
2966
+ }
2967
+ function ConclusionRenderer({
2968
+ slide,
2969
+ index
2970
+ }) {
2971
+ const tone = toneOf(slide, "brand");
2972
+ return /* @__PURE__ */ jsx(SlideFrame, { slide, index, tone: "brand", width: "sm", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center text-center", children: [
2973
+ slide.eyebrow && /* @__PURE__ */ jsx(Eyebrow, { children: slide.eyebrow }),
2974
+ /* @__PURE__ */ jsx(SlideTitle, { children: slide.title }),
2975
+ slide.body && /* @__PURE__ */ jsx(Subtitle, { className: "mx-auto", children: slide.body }),
2976
+ slide.highlights && slide.highlights.length > 0 && /* @__PURE__ */ jsx(Highlights, { items: slide.highlights }),
2977
+ slide.takeaways && slide.takeaways.length > 0 && /* @__PURE__ */ jsx(
2978
+ "ul",
2979
+ {
2980
+ ...reveal(4),
2981
+ className: "mie-deck-reveal mt-10 flex flex-col gap-3 text-start",
2982
+ children: slide.takeaways.map((t) => /* @__PURE__ */ jsx(Bullet, { item: t }, t))
2983
+ }
2984
+ ),
2985
+ slide.share && /* @__PURE__ */ jsxs(Fragment, { children: [
2986
+ slide.share.instructions && /* @__PURE__ */ jsx("p", { className: cn("mt-10 text-sm", tone.muted), children: slide.share.instructions }),
2987
+ /* @__PURE__ */ jsx(CopyLink, { url: slide.share.url })
2988
+ ] }),
2989
+ (slide.cta || slide.secondaryCta) && /* @__PURE__ */ jsxs(
2990
+ "div",
2991
+ {
2992
+ ...reveal(5),
2993
+ className: "mie-deck-reveal mt-12 flex flex-wrap items-center justify-center gap-4",
2994
+ children: [
2995
+ slide.cta && /* @__PURE__ */ jsx(CtaButton, { link: slide.cta, primary: true }),
2996
+ slide.secondaryCta && /* @__PURE__ */ jsx(CtaButton, { link: slide.secondaryCta })
2997
+ ]
2998
+ }
2999
+ ),
3000
+ (slide.preparedBy || slide.dateline) && /* @__PURE__ */ jsx("p", { className: cn("mt-10 text-sm", tone.muted), children: [slide.preparedBy, slide.dateline].filter(Boolean).join(" \xB7 ") }),
3001
+ slide.confidentiality && /* @__PURE__ */ jsx(
3002
+ "p",
3003
+ {
3004
+ className: cn("mt-3 text-xs tracking-wider uppercase", tone.muted),
3005
+ children: slide.confidentiality
3006
+ }
3007
+ )
3008
+ ] }) });
3009
+ }
3010
+
3011
+ // src/components/Deck/registry.tsx
3012
+ var slideRenderers = {
3013
+ cover: CoverRenderer,
3014
+ "section-divider": SectionDividerRenderer,
3015
+ "table-of-contents": TableOfContentsRenderer,
3016
+ "bullet-list": BulletListRenderer,
3017
+ quote: QuoteRenderer,
3018
+ image: ImageRenderer,
3019
+ "definition-list": DefinitionListRenderer,
3020
+ conclusion: ConclusionRenderer,
3021
+ metrics: MetricsRenderer,
3022
+ chart: ChartRenderer,
3023
+ "feature-highlight": FeatureHighlightRenderer,
3024
+ "comparison-table": ComparisonTableRenderer,
3025
+ "impact-table": ImpactTableRenderer,
3026
+ cards: CardsRenderer,
3027
+ "ranked-list": RankedListRenderer,
3028
+ breakdown: BreakdownRenderer,
3029
+ cycle: CycleRenderer,
3030
+ roadmap: RoadmapRenderer,
3031
+ "adoption-curve": AdoptionCurveRenderer,
3032
+ diagram: DiagramRenderer,
3033
+ "certification-grid": CertificationGridRenderer,
3034
+ showcase: ShowcaseRenderer,
3035
+ tabs: TabsRenderer
3036
+ };
3037
+ var typingTarget = (el) => el instanceof HTMLElement && (["INPUT", "TEXTAREA", "SELECT"].includes(el.tagName) || el.isContentEditable || el.getAttribute("role") === "tab");
3038
+ var spaceActivates = (el) => el instanceof HTMLElement && (el.tagName === "BUTTON" || el.getAttribute("role") === "button");
3039
+ var Deck = React9.forwardRef(
3040
+ ({
3041
+ slides,
3042
+ meta,
3043
+ home,
3044
+ onSlideChange,
3045
+ renderers,
3046
+ graphics,
3047
+ components,
3048
+ icons,
3049
+ labels: labelOverrides,
3050
+ locale,
3051
+ syncHash = true,
3052
+ className,
3053
+ ...rest
3054
+ }, ref) => {
3055
+ const rootRef = React9.useRef(null);
3056
+ const scrollRef = React9.useRef(null);
3057
+ const touchStart = React9.useRef(null);
3058
+ const [active, setActive] = React9.useState(0);
3059
+ const [ready, setReady] = React9.useState(false);
3060
+ const [outline, setOutline] = React9.useState(false);
3061
+ const [fullscreen, setFullscreen] = React9.useState(false);
3062
+ const [hintPulse, setHintPulse] = React9.useState(0);
3063
+ const labels = React9.useMemo(
3064
+ () => ({ ...defaultDeckLabels, ...labelOverrides }),
3065
+ [labelOverrides]
3066
+ );
3067
+ const total = slides.length;
3068
+ React9.useImperativeHandle(ref, () => rootRef.current);
3069
+ const slideEl = React9.useCallback(
3070
+ (i) => scrollRef.current?.querySelector(
3071
+ `[data-slot="deck-slide"][data-index="${i}"]`
3072
+ ),
3073
+ []
3074
+ );
3075
+ const goTo = React9.useCallback(
3076
+ (i) => {
3077
+ const clamped = Math.max(0, Math.min(i, total - 1));
3078
+ const reduce = window.matchMedia?.(
3079
+ "(prefers-reduced-motion: reduce)"
3080
+ ).matches;
3081
+ slideEl(clamped)?.scrollIntoView({
3082
+ behavior: reduce ? "auto" : "smooth"
3083
+ });
3084
+ },
3085
+ [slideEl, total]
3086
+ );
3087
+ React9.useEffect(() => {
3088
+ const root = scrollRef.current;
3089
+ if (!root) return;
3090
+ const observer = new IntersectionObserver(
3091
+ (entries) => {
3092
+ for (const entry of entries) {
3093
+ if (!entry.isIntersecting) continue;
3094
+ const rootHeight = root.clientHeight || window.innerHeight;
3095
+ if (entry.intersectionRatio < 0.5 && entry.intersectionRect.height < rootHeight / 2)
3096
+ continue;
3097
+ const el = entry.target;
3098
+ el.dataset.seen = "";
3099
+ setActive(Number(el.dataset.index));
3100
+ }
3101
+ },
3102
+ { root, threshold: [0.1, 0.25, 0.5] }
3103
+ );
3104
+ root.querySelectorAll('[data-slot="deck-slide"]').forEach((el) => observer.observe(el));
3105
+ setReady(true);
3106
+ return () => observer.disconnect();
3107
+ }, [total]);
3108
+ React9.useEffect(() => {
3109
+ const raw = window.location.hash.slice(1);
3110
+ let hash = raw;
3111
+ try {
3112
+ hash = decodeURIComponent(raw);
3113
+ } catch {
3114
+ }
3115
+ if (!hash) return;
3116
+ const i = slides.findIndex((s, n) => slideAnchor(s, n) === hash);
3117
+ if (i > 0) requestAnimationFrame(() => slideEl(i)?.scrollIntoView());
3118
+ }, []);
3119
+ const reportedSlide = React9.useRef(-1);
3120
+ React9.useEffect(() => {
3121
+ const slide = slides[active];
3122
+ if (!slide) return;
3123
+ if (syncHash && ready) {
3124
+ const hash = `#${slideAnchor(slide, active)}`;
3125
+ if (window.location.hash !== hash)
3126
+ window.history.replaceState(window.history.state, "", hash);
3127
+ }
3128
+ if (reportedSlide.current !== active) {
3129
+ reportedSlide.current = active;
3130
+ onSlideChange?.(slide, active);
3131
+ }
3132
+ }, [active, slides, syncHash, ready]);
3133
+ const toggleFullscreen = React9.useCallback(() => {
3134
+ if (!document.fullscreenElement)
3135
+ rootRef.current?.requestFullscreen?.().catch(() => {
3136
+ });
3137
+ else document.exitFullscreen?.().catch(() => {
3138
+ });
3139
+ }, []);
3140
+ React9.useEffect(() => {
3141
+ const onChange = () => setFullscreen(!!document.fullscreenElement);
3142
+ document.addEventListener("fullscreenchange", onChange);
3143
+ return () => document.removeEventListener("fullscreenchange", onChange);
3144
+ }, []);
3145
+ React9.useEffect(() => {
3146
+ const onKey = (e) => {
3147
+ if (outline || e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey)
3148
+ return;
3149
+ if (typingTarget(e.target)) return;
3150
+ const key = e.key;
3151
+ if (key === " " && spaceActivates(e.target)) return;
3152
+ if (["ArrowDown", "ArrowRight", "PageDown", " "].includes(key)) {
3153
+ e.preventDefault();
3154
+ goTo(active + 1);
3155
+ } else if (["ArrowUp", "ArrowLeft", "PageUp"].includes(key)) {
3156
+ e.preventDefault();
3157
+ goTo(active - 1);
3158
+ } else if (key === "Home") {
3159
+ e.preventDefault();
3160
+ goTo(0);
3161
+ } else if (key === "End") {
3162
+ e.preventDefault();
3163
+ goTo(total - 1);
3164
+ } else if (/^[1-9]$/.test(key)) {
3165
+ goTo(Number(key) - 1);
3166
+ } else if (key.toLowerCase() === "f") {
3167
+ toggleFullscreen();
3168
+ } else if (key === "?") {
3169
+ setHintPulse((p) => p + 1);
3170
+ }
3171
+ };
3172
+ window.addEventListener("keydown", onKey);
3173
+ return () => window.removeEventListener("keydown", onKey);
3174
+ }, [active, goTo, outline, toggleFullscreen, total]);
3175
+ const onTouchEnd = (e) => {
3176
+ if (touchStart.current === null) return;
3177
+ const delta = touchStart.current - e.changedTouches[0].clientY;
3178
+ touchStart.current = null;
3179
+ const el = slideEl(active);
3180
+ if (el && scrollRef.current && el.scrollHeight > scrollRef.current.clientHeight + 20)
3181
+ return;
3182
+ if (Math.abs(delta) > 120) goTo(active + (delta > 0 ? 1 : -1));
3183
+ };
3184
+ const context = React9.useMemo(
3185
+ () => ({
3186
+ slides,
3187
+ activeSlide: active,
3188
+ goTo,
3189
+ labels,
3190
+ components,
3191
+ icons,
3192
+ graphics,
3193
+ renderers,
3194
+ locale
3195
+ }),
3196
+ [
3197
+ slides,
3198
+ active,
3199
+ goTo,
3200
+ labels,
3201
+ components,
3202
+ icons,
3203
+ graphics,
3204
+ renderers,
3205
+ locale
3206
+ ]
3207
+ );
3208
+ const closeOutline = React9.useCallback(() => setOutline(false), []);
3209
+ const progress = total > 1 ? active / (total - 1) * 100 : 0;
3210
+ return /* @__PURE__ */ jsx(DeckProvider, { value: context, children: /* @__PURE__ */ jsxs(
3211
+ "div",
3212
+ {
3213
+ ref: rootRef,
3214
+ role: "region",
3215
+ "aria-roledescription": labels.presentation,
3216
+ "aria-label": meta.title,
3217
+ "data-slot": "deck",
3218
+ "data-ready": ready || void 0,
3219
+ className: cn(
3220
+ "mie-deck relative h-dvh w-full overflow-hidden bg-neutral-950 text-white",
3221
+ className
3222
+ ),
3223
+ ...rest,
3224
+ children: [
3225
+ /* @__PURE__ */ jsxs("h1", { className: "sr-only", children: [
3226
+ meta.title,
3227
+ meta.period ? ` \u2014 ${meta.period}` : ""
3228
+ ] }),
3229
+ home && /* @__PURE__ */ jsxs(
3230
+ TemplateAnchor,
3231
+ {
3232
+ href: home.href,
3233
+ trackingId: home.trackingId,
3234
+ components,
3235
+ className: "mie-deck-chrome absolute start-3 top-3 z-50 inline-flex items-center gap-2 rounded-full border border-white/10 bg-black/25 py-1.5 ps-2 pe-3 text-xs font-semibold text-white/80 backdrop-blur transition-colors hover:bg-white/10 hover:text-white print:hidden",
3236
+ children: [
3237
+ home.logo && /* @__PURE__ */ jsx(
3238
+ TemplateImg,
3239
+ {
3240
+ ...home.logo,
3241
+ alt: "",
3242
+ components,
3243
+ className: "size-[18px] object-contain"
3244
+ }
3245
+ ),
3246
+ home.label
3247
+ ]
3248
+ }
3249
+ ),
3250
+ /* @__PURE__ */ jsx(ProgressBar, { progress }),
3251
+ /* @__PURE__ */ jsx(DotNav, { slides, active, goTo, labels }),
3252
+ /* @__PURE__ */ jsx(
3253
+ SlideCounter,
3254
+ {
3255
+ active,
3256
+ total,
3257
+ section: slides[active]?.section
3258
+ }
3259
+ ),
3260
+ /* @__PURE__ */ jsx(KeyboardHints, { pulse: hintPulse, labels }),
3261
+ /* @__PURE__ */ jsx(
3262
+ Controls,
3263
+ {
3264
+ isFullscreen: fullscreen,
3265
+ onToggleFullscreen: toggleFullscreen,
3266
+ onOpenOutline: () => setOutline(true),
3267
+ labels
3268
+ }
3269
+ ),
3270
+ /* @__PURE__ */ jsx(
3271
+ "div",
3272
+ {
3273
+ ref: scrollRef,
3274
+ onTouchStart: (e) => {
3275
+ touchStart.current = e.touches[0].clientY;
3276
+ },
3277
+ onTouchEnd,
3278
+ className: "mie-deck-scroll size-full snap-y snap-mandatory overflow-y-auto",
3279
+ children: slides.map((slide, i) => {
3280
+ const Renderer = slide.type === "custom" ? renderers?.[slide.component] : renderers?.[slide.type] ?? slideRenderers[slide.type];
3281
+ return Renderer ? /* @__PURE__ */ jsx(Renderer, { slide, index: i }, slideAnchor(slide, i)) : null;
3282
+ })
3283
+ }
3284
+ ),
3285
+ /* @__PURE__ */ jsx(
3286
+ MobileNav,
3287
+ {
3288
+ active,
3289
+ total,
3290
+ onPrev: () => goTo(active - 1),
3291
+ onNext: () => goTo(active + 1),
3292
+ onOpenOutline: () => setOutline(true),
3293
+ labels
3294
+ }
3295
+ ),
3296
+ /* @__PURE__ */ jsx(
3297
+ OutlineDialog,
3298
+ {
3299
+ open: outline,
3300
+ onClose: closeOutline,
3301
+ slides,
3302
+ active,
3303
+ goTo,
3304
+ labels
3305
+ }
3306
+ )
3307
+ ]
3308
+ }
3309
+ ) });
3310
+ }
3311
+ );
3312
+ Deck.displayName = "Deck";
3313
+
3314
+ export { Bullet, CountUp, Deck, DeckIcon, Graphic, HighlightFigure, IconChip, Card as SlideCard, Eyebrow as SlideEyebrow, SlideFrame, SlideHeader, Subtitle as SlideSubtitle, SlideTitle, SourceLink, defaultDeckLabels, reveal, accent as slideAccent, slideAnchor, slideRenderers, TONES as slideTones, toneOf, useDeck, useTone };
3315
+ //# sourceMappingURL=deck.js.map
3316
+ //# sourceMappingURL=deck.js.map