@spectare-personalisation/react 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,15 +1,61 @@
1
- 'use strict';
2
-
3
- var react = require('react');
4
- var marked = require('marked');
5
- var DOMPurify = require('isomorphic-dompurify');
6
- var jsxRuntime = require('react/jsx-runtime');
7
-
8
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
1
+ 'use client';
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
9
30
 
10
- var DOMPurify__default = /*#__PURE__*/_interopDefault(DOMPurify);
31
+ // src/index.ts
32
+ var src_exports = {};
33
+ __export(src_exports, {
34
+ AnnouncementBar: () => AnnouncementBar,
35
+ AtomCard: () => AtomCard,
36
+ CodeBlock: () => CodeBlock,
37
+ ComparisonTable: () => ComparisonTable,
38
+ ComponentRenderer: () => ComponentRenderer,
39
+ CtaStrip: () => CtaStrip,
40
+ DEFAULT_ACCENT: () => DEFAULT_ACCENT,
41
+ FeatureList: () => FeatureList,
42
+ HeroStatement: () => HeroStatement,
43
+ ImageCtaHero: () => ImageCtaHero,
44
+ PersonalisedSection: () => PersonalisedSection,
45
+ SP_ROOT: () => SP_ROOT,
46
+ StatGrid: () => StatGrid,
47
+ TestimonialCard: () => TestimonialCard,
48
+ buildTokenCss: () => buildTokenCss,
49
+ filterAssemblyByZone: () => filterAssemblyByZone
50
+ });
51
+ module.exports = __toCommonJS(src_exports);
11
52
 
12
53
  // src/PersonalisedSection.tsx
54
+ var import_react = require("react");
55
+
56
+ // src/ComponentRenderer.tsx
57
+ var import_marked = require("marked");
58
+ var import_isomorphic_dompurify = __toESM(require("isomorphic-dompurify"), 1);
13
59
 
14
60
  // src/types.ts
15
61
  var COMPONENT_ZONES = {
@@ -31,10 +77,23 @@ function filterAssemblyByZone(assembly, zone) {
31
77
  return effectiveZone === zone;
32
78
  });
33
79
  }
80
+ var COMPONENT_CATEGORIES = {
81
+ AnnouncementBar: "conversion",
82
+ HeroStatement: "hero",
83
+ AtomCard: "content",
84
+ StatGrid: "content",
85
+ CodeBlock: "technical",
86
+ ComparisonTable: "evaluation",
87
+ FeatureList: "content",
88
+ TestimonialCard: "social-proof",
89
+ ImageCtaHero: "hero",
90
+ CtaStrip: "conversion"
91
+ };
34
92
 
35
93
  // src/tokens.ts
36
94
  var DEFAULT_ACCENT = "#60a5fa";
37
95
  var SP_ROOT = "sp-root";
96
+ var STYLESHEET_SCOPE = `:where(:root),.${SP_ROOT}`;
38
97
  function palette(accent) {
39
98
  return {
40
99
  "--sp-accent": accent,
@@ -78,40 +137,47 @@ function buildTokenCss({ accent = DEFAULT_ACCENT, unit = "px", scope = `.${SP_RO
78
137
  const decls = Object.entries(palette(accent)).map(([k, v]) => `${k}:${v}`).join(";");
79
138
  return `${scope}{${decls}}${rules(unit)}`;
80
139
  }
140
+
141
+ // src/ComponentRenderer.tsx
142
+ var import_jsx_runtime = require("react/jsx-runtime");
81
143
  function renderMarkdown(content) {
82
- const raw = marked.marked.parse(content != null ? content : "", { async: false });
83
- return DOMPurify__default.default.sanitize(raw, { USE_PROFILES: { html: true } });
144
+ const raw = import_marked.marked.parse(content != null ? content : "", { async: false });
145
+ return import_isomorphic_dompurify.default.sanitize(raw, { USE_PROFILES: { html: true } });
84
146
  }
147
+ var scaler = (unit) => (n) => unit === "rem" ? `${n / 16}rem` : `${n}px`;
148
+ var PX = scaler("px");
85
149
  var HALF_COMPONENTS = /* @__PURE__ */ new Set(["TestimonialCard"]);
86
150
  var flexItems = (a) => a === "center" ? "center" : a === "right" ? "flex-end" : "flex-start";
87
- function AnnouncementBar({ text, link }) {
151
+ function AnnouncementBar({ text, link, unit = "px" }) {
152
+ const u = scaler(unit);
88
153
  if (!text) return null;
89
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
154
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
90
155
  display: "flex",
91
156
  alignItems: "center",
92
157
  justifyContent: "center",
93
- gap: "10px",
158
+ gap: u(10),
94
159
  flexWrap: "wrap",
95
160
  textAlign: "center",
96
161
  background: "var(--sp-accent-bg)",
97
162
  border: "1px solid var(--sp-accent-border)",
98
- borderRadius: "8px",
99
- padding: "8px 16px",
100
- fontSize: "14px",
163
+ borderRadius: u(8),
164
+ padding: `${u(8)} ${u(16)}`,
165
+ fontSize: u(14),
101
166
  lineHeight: 1.4,
102
167
  color: "var(--sp-text-sub)"
103
168
  }, children: [
104
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: text }),
105
- (link == null ? void 0 : link.href) && (link == null ? void 0 : link.label) && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: link.href, style: { color: "var(--sp-accent)", fontWeight: 600, textDecoration: "none", whiteSpace: "nowrap" }, children: [
169
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: text }),
170
+ (link == null ? void 0 : link.href) && (link == null ? void 0 : link.label) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: link.href, style: { color: "var(--sp-accent)", fontWeight: 600, textDecoration: "none", whiteSpace: "nowrap" }, children: [
106
171
  link.label,
107
172
  " \u2192"
108
173
  ] })
109
174
  ] });
110
175
  }
111
- function HeroStatement({ headline, subheading, align = "left" }) {
112
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: flexItems(align), textAlign: align, paddingTop: "24px", paddingBottom: "24px" }, children: [
113
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "32px", fontWeight: 700, letterSpacing: "-0.025em", lineHeight: 1.2, color: "var(--sp-text)", margin: "0 0 12px" }, children: headline }),
114
- subheading && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "18px", color: "var(--sp-text-sub)", lineHeight: 1.6, maxWidth: "672px", margin: 0 }, children: subheading })
176
+ function HeroStatement({ headline, subheading, align = "left", unit = "px" }) {
177
+ const u = scaler(unit);
178
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: flexItems(align), textAlign: align, paddingTop: u(24), paddingBottom: u(24) }, children: [
179
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { fontSize: u(32), fontWeight: 700, letterSpacing: "-0.025em", lineHeight: 1.2, color: "var(--sp-text)", margin: `0 0 ${u(12)}` }, children: headline }),
180
+ subheading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(18), color: "var(--sp-text-sub)", lineHeight: 1.6, maxWidth: u(672), margin: 0 }, children: subheading })
115
181
  ] });
116
182
  }
117
183
  var ATOM_LAYOUT_DEFAULT = ["title", "content", "stats", "cta"];
@@ -122,133 +188,142 @@ var clampStyle = {
122
188
  WebkitBoxOrient: "vertical",
123
189
  overflow: "hidden"
124
190
  };
125
- function AtomCard({ title, content, layout, stats = [], ctaText, ctaUrl, full }) {
191
+ function AtomCard({ title, content, layout, stats = [], ctaText, ctaUrl, full, unit = "px" }) {
192
+ const u = scaler(unit);
126
193
  const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;
127
194
  const element = (name) => {
128
- if (name === "title") return title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { fontSize: "16px", fontWeight: 600, color: "var(--sp-text)", margin: "0 0 12px" }, children: title }, "title") : null;
129
- if (name === "content") return content ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sp-prose", style: { fontSize: "15px", color: "var(--sp-text-sub)", lineHeight: 1.6, ...full ? {} : clampStyle }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } }, "content") : null;
130
- if (name === "stats") return stats.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "20px", margin: "0 0 12px", paddingBottom: "12px", borderBottom: "1px solid var(--sp-border)" }, children: stats.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [
131
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "22px", fontWeight: 700, color: "var(--sp-text)", lineHeight: 1, fontVariantNumeric: "tabular-nums" }, children: s.value }),
132
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "11px", color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: s.label })
195
+ if (name === "title") return title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(16), fontWeight: 600, color: "var(--sp-text)", margin: `0 0 ${u(12)}` }, children: title }, "title") : null;
196
+ if (name === "content") return content ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sp-prose", style: { fontSize: u(15), color: "var(--sp-text-sub)", lineHeight: 1.6, ...full ? {} : clampStyle }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } }, "content") : null;
197
+ if (name === "stats") return stats.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: u(20), margin: `0 0 ${u(12)}`, paddingBottom: u(12), borderBottom: "1px solid var(--sp-border)" }, children: stats.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: u(2) }, children: [
198
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(22), fontWeight: 700, color: "var(--sp-text)", lineHeight: 1, fontVariantNumeric: "tabular-nums" }, children: s.value }),
199
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(11), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: s.label })
133
200
  ] }, i)) }, "stats") : null;
134
- if (name === "cta") return ctaText && ctaUrl ? /* @__PURE__ */ jsxRuntime.jsxs("a", { href: ctaUrl, style: { display: "inline-flex", alignItems: "center", gap: "4px", marginTop: "12px", fontSize: "13px", fontWeight: 600, color: "var(--sp-accent)", textDecoration: "none" }, children: [
201
+ if (name === "cta") return ctaText && ctaUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: ctaUrl, style: { display: "inline-flex", alignItems: "center", gap: u(4), marginTop: u(12), fontSize: u(13), fontWeight: 600, color: "var(--sp-accent)", textDecoration: "none" }, children: [
135
202
  ctaText,
136
203
  " \u2192"
137
204
  ] }, "cta") : null;
138
205
  return null;
139
206
  };
140
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "24px", height: "100%" }, children: order.map(element) });
207
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(24), height: "100%" }, children: order.map(element) });
141
208
  }
142
- function StatGrid({ stats = [], caption }) {
209
+ function StatGrid({ stats = [], caption, unit = "px" }) {
210
+ const u = scaler(unit);
143
211
  const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;
144
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
145
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: "12px" }, children: stats.map(({ value, label }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "10px", padding: "16px 20px", display: "flex", flexDirection: "column", justifyContent: "space-between", minHeight: "88px" }, children: [
146
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "11px", color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em", margin: "0 0 12px", lineHeight: 1.3 }, children: label }),
147
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "20px", fontWeight: 500, color: "var(--sp-text)", fontVariantNumeric: "tabular-nums", lineHeight: 1, margin: 0 }, children: value })
212
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
213
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: u(12) }, children: stats.map(({ value, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(10), padding: `${u(16)} ${u(20)}`, display: "flex", flexDirection: "column", justifyContent: "space-between", minHeight: u(88) }, children: [
214
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(11), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em", margin: `0 0 ${u(12)}`, lineHeight: 1.3 }, children: label }),
215
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(20), fontWeight: 500, color: "var(--sp-text)", fontVariantNumeric: "tabular-nums", lineHeight: 1, margin: 0 }, children: value })
148
216
  ] }, label)) }),
149
- caption && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", margin: "12px 0 0" }, children: caption })
217
+ caption && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(13), color: "var(--sp-text-muted)", margin: `${u(12)} 0 0` }, children: caption })
150
218
  ] });
151
219
  }
152
- function CodeBlock({ code, lang = "typescript", caption }) {
153
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { borderRadius: "12px", overflow: "hidden", border: "1px solid var(--sp-border)" }, children: [
154
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { background: "var(--sp-bg)", padding: "10px 16px", display: "flex", alignItems: "center", justifyContent: "space-between", borderBottom: "1px solid var(--sp-border)" }, children: [
155
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "12px", color: "var(--sp-text-muted)", fontFamily: "monospace" }, children: lang }),
156
- caption && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "12px", color: "var(--sp-text-muted)" }, children: caption })
220
+ function CodeBlock({ code, lang = "typescript", caption, unit = "px" }) {
221
+ const u = scaler(unit);
222
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderRadius: u(12), overflow: "hidden", border: "1px solid var(--sp-border)" }, children: [
223
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { background: "var(--sp-bg)", padding: `${u(10)} ${u(16)}`, display: "flex", alignItems: "center", justifyContent: "space-between", borderBottom: "1px solid var(--sp-border)" }, children: [
224
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(12), color: "var(--sp-text-muted)", fontFamily: "monospace" }, children: lang }),
225
+ caption && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(12), color: "var(--sp-text-muted)" }, children: caption })
157
226
  ] }),
158
- /* @__PURE__ */ jsxRuntime.jsx("pre", { style: { background: "var(--sp-surface)", padding: "20px", fontSize: "13px", color: "var(--sp-text-sub)", overflowX: "auto", lineHeight: 1.6, fontFamily: "monospace", whiteSpace: "pre", margin: 0 }, children: code })
227
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { style: { background: "var(--sp-surface)", padding: u(20), fontSize: u(13), color: "var(--sp-text-sub)", overflowX: "auto", lineHeight: 1.6, fontFamily: "monospace", whiteSpace: "pre", margin: 0 }, children: code })
159
228
  ] });
160
229
  }
161
- function ComparisonTable({ brand = "Us", competitor, rows = [] }) {
162
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { border: "1px solid var(--sp-border)", borderRadius: "12px", overflow: "hidden" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", fontSize: "14px", borderCollapse: "collapse" }, children: [
163
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { style: { borderBottom: "1px solid var(--sp-border)", background: "var(--sp-bg)" }, children: [
164
- /* @__PURE__ */ jsxRuntime.jsx("th", { style: { textAlign: "left", padding: "12px 16px", color: "var(--sp-text-muted)", fontWeight: 500, fontSize: "12px", width: "33%" } }),
165
- /* @__PURE__ */ jsxRuntime.jsx("th", { style: { textAlign: "left", padding: "12px 16px", fontWeight: 600, color: "var(--sp-accent)", fontSize: "12px" }, children: brand }),
166
- /* @__PURE__ */ jsxRuntime.jsx("th", { style: { textAlign: "left", padding: "12px 16px", color: "var(--sp-text-muted)", fontWeight: 500, fontSize: "12px" }, children: competitor })
230
+ function ComparisonTable({ brand = "Us", competitor, rows = [], unit = "px" }) {
231
+ const u = scaler(unit);
232
+ const cell = { textAlign: "left", padding: `${u(12)} ${u(16)}` };
233
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { border: "1px solid var(--sp-border)", borderRadius: u(12), overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { style: { width: "100%", fontSize: u(14), borderCollapse: "collapse" }, children: [
234
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { style: { borderBottom: "1px solid var(--sp-border)", background: "var(--sp-bg)" }, children: [
235
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(12), width: "33%" } }),
236
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, fontWeight: 600, color: "var(--sp-accent)", fontSize: u(12) }, children: brand }),
237
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(12) }, children: competitor })
167
238
  ] }) }),
168
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map(({ label, spectare, them }) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { style: { borderBottom: "1px solid var(--sp-border)" }, children: [
169
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
170
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
171
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-text-muted)" }, children: them })
239
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: rows.map(({ label, spectare, them }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { style: { borderBottom: "1px solid var(--sp-border)" }, children: [
240
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "row", style: { ...cell, fontSize: u(13), color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
241
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(13), color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
242
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(13), color: "var(--sp-text-muted)" }, children: them })
172
243
  ] }, label)) })
173
244
  ] }) }) });
174
245
  }
175
- function FeatureList({ items = [] }) {
176
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "24px" }, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "16px" }, children: items.map(({ text, sub }) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: { display: "flex", gap: "12px" }, children: [
177
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: "15px", marginTop: "2px" }, children: "\u2713" }),
178
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
179
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "15px", fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
180
- sub && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", lineHeight: 1.5, margin: "4px 0 0" }, children: sub })
246
+ function FeatureList({ items = [], unit = "px" }) {
247
+ const u = scaler(unit);
248
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(24) }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: u(16) }, children: items.map(({ text, sub }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { style: { display: "flex", gap: u(12) }, children: [
249
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: u(15), marginTop: u(2) }, children: "\u2713" }),
250
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
251
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(15), fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
252
+ sub && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(13), color: "var(--sp-text-muted)", lineHeight: 1.5, margin: `${u(4)} 0 0` }, children: sub })
181
253
  ] })
182
254
  ] }, text)) }) });
183
255
  }
184
- function TestimonialCard({ quote, name, role, company }) {
185
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "24px", display: "flex", flexDirection: "column", gap: "20px", height: "100%" }, children: [
186
- /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "15px", color: "var(--sp-text-sub)", lineHeight: 1.6, flex: 1, margin: 0 }, children: [
187
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: "18px", lineHeight: 1, marginRight: "4px" }, children: '"' }),
256
+ function TestimonialCard({ quote, name, role, company, unit = "px" }) {
257
+ const u = scaler(unit);
258
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(24), display: "flex", flexDirection: "column", gap: u(20), height: "100%" }, children: [
259
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { fontSize: u(15), color: "var(--sp-text-sub)", lineHeight: 1.6, flex: 1, margin: 0 }, children: [
260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "var(--sp-text-dim)", fontSize: u(18), lineHeight: 1, marginRight: u(4) }, children: '"' }),
188
261
  quote,
189
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: "18px", lineHeight: 1, marginLeft: "4px" }, children: '"' })
262
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "var(--sp-text-dim)", fontSize: u(18), lineHeight: 1, marginLeft: u(4) }, children: '"' })
190
263
  ] }),
191
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: "16px" }, children: [
192
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "14px", fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
193
- /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", margin: "2px 0 0" }, children: [
264
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: u(16) }, children: [
265
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(14), fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
266
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { fontSize: u(13), color: "var(--sp-text-muted)", margin: `${u(2)} 0 0` }, children: [
194
267
  role,
195
268
  company ? `, ${company}` : ""
196
269
  ] })
197
270
  ] })
198
271
  ] });
199
272
  }
200
- function ImageCtaHero({ src, alt = "", headline, subheading, ctaLabel, ctaHref, align = "left" }) {
273
+ function ImageCtaHero({ src, alt = "", headline, subheading, ctaLabel, ctaHref, align = "left", unit = "px" }) {
274
+ const u = scaler(unit);
201
275
  if (!src) return null;
202
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { borderRadius: "12px", overflow: "hidden", position: "relative", width: "100%", paddingBottom: "56.25%" }, children: [
203
- /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt, style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" } }),
204
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.45)" } }),
205
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, background: "linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.2) 60%, transparent 100%)" } }),
206
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "absolute", bottom: 0, left: 0, right: 0, padding: "28px", textAlign: align }, children: [
207
- headline && /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "24px", fontWeight: 700, color: "#fff", lineHeight: 1.2, margin: "0 0 8px", letterSpacing: "-0.02em" }, children: headline }),
208
- subheading && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "15px", color: "rgba(255,255,255,0.75)", lineHeight: 1.5, margin: "0 0 20px" }, children: subheading }),
209
- ctaHref && ctaLabel && /* @__PURE__ */ jsxRuntime.jsx("a", { href: ctaHref, style: { display: "inline-block", background: "#fff", color: "#09090b", padding: "8px 20px", borderRadius: "8px", fontWeight: 600, fontSize: "14px", textDecoration: "none" }, children: ctaLabel })
276
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderRadius: u(12), overflow: "hidden", position: "relative", width: "100%", paddingBottom: "56.25%" }, children: [
277
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src, alt, style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" } }),
278
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.45)" } }),
279
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: "linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.2) 60%, transparent 100%)" } }),
280
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "absolute", bottom: 0, left: 0, right: 0, padding: u(28), textAlign: align }, children: [
281
+ headline && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { fontSize: u(24), fontWeight: 700, color: "#fff", lineHeight: 1.2, margin: `0 0 ${u(8)}`, letterSpacing: "-0.02em" }, children: headline }),
282
+ subheading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(15), color: "rgba(255,255,255,0.75)", lineHeight: 1.5, margin: `0 0 ${u(20)}` }, children: subheading }),
283
+ ctaHref && ctaLabel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: ctaHref, style: { display: "inline-block", background: "#fff", color: "#09090b", padding: `${u(8)} ${u(20)}`, borderRadius: u(8), fontWeight: 600, fontSize: u(14), textDecoration: "none" }, children: ctaLabel })
210
284
  ] })
211
285
  ] });
212
286
  }
213
- function CtaStrip({ headline, primary, secondary, align = "center" }) {
214
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "32px", textAlign: align, background: "var(--sp-bg)" }, children: [
215
- /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { fontSize: "24px", fontWeight: 700, color: "var(--sp-text)", margin: "0 0 24px" }, children: headline }),
216
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: flexItems(align), gap: "16px", flexWrap: "wrap" }, children: [
217
- /* @__PURE__ */ jsxRuntime.jsx("a", { href: primary.href, style: { background: "var(--sp-cta-bg)", color: "var(--sp-cta-text)", padding: "10px 24px", borderRadius: "12px", fontWeight: 600, fontSize: "15px", textDecoration: "none" }, children: primary.label }),
218
- secondary && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: secondary.href, style: { fontSize: "15px", color: "var(--sp-text-sub)", textDecoration: "none" }, children: [
287
+ function CtaStrip({ headline, primary, secondary, align = "center", unit = "px" }) {
288
+ const u = scaler(unit);
289
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(32), textAlign: align, background: "var(--sp-bg)" }, children: [
290
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(24), fontWeight: 700, color: "var(--sp-text)", margin: `0 0 ${u(24)}` }, children: headline }),
291
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: flexItems(align), gap: u(16), flexWrap: "wrap" }, children: [
292
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: primary.href, style: { background: "var(--sp-cta-bg)", color: "var(--sp-cta-text)", padding: `${u(10)} ${u(24)}`, borderRadius: u(12), fontWeight: 600, fontSize: u(15), textDecoration: "none" }, children: primary.label }),
293
+ secondary && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: secondary.href, style: { fontSize: u(15), color: "var(--sp-text-sub)", textDecoration: "none" }, children: [
219
294
  secondary.label,
220
295
  " \u2192"
221
296
  ] })
222
297
  ] })
223
298
  ] });
224
299
  }
225
- function renderSingle(item, brand, align) {
300
+ function renderSingle(item, brand, align, unit = "px") {
226
301
  var _a, _b;
227
302
  const s = (_a = item.slots) != null ? _a : {};
228
303
  switch (item.component) {
229
304
  case "AnnouncementBar":
230
- return /* @__PURE__ */ jsxRuntime.jsx(AnnouncementBar, { text: s.text, link: s.link });
305
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AnnouncementBar, { text: s.text, link: s.link, unit });
231
306
  case "HeroStatement":
232
- return /* @__PURE__ */ jsxRuntime.jsx(HeroStatement, { headline: s.headline, subheading: s.subheading, align });
307
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeroStatement, { headline: s.headline, subheading: s.subheading, align, unit });
233
308
  // A full-width card has nothing beside it, so there is nothing for a clamp to protect.
234
309
  case "AtomCard":
235
- return /* @__PURE__ */ jsxRuntime.jsx(AtomCard, { title: s.title, content: s.content, layout: s.layout, stats: s.stats, ctaText: s.ctaText, ctaUrl: s.ctaUrl, full: s.full || resolvedSize(item) === "full" });
310
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AtomCard, { title: s.title, content: s.content, layout: s.layout, stats: s.stats, ctaText: s.ctaText, ctaUrl: s.ctaUrl, full: s.full || resolvedSize(item) === "full", unit });
236
311
  case "StatGrid":
237
- return /* @__PURE__ */ jsxRuntime.jsx(StatGrid, { stats: s.stats, caption: s.caption });
312
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatGrid, { stats: s.stats, caption: s.caption, unit });
238
313
  case "CodeBlock":
239
- return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: s.code, lang: s.lang, caption: s.caption });
314
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CodeBlock, { code: s.code, lang: s.lang, caption: s.caption, unit });
240
315
  case "ComparisonTable":
241
- return /* @__PURE__ */ jsxRuntime.jsx(ComparisonTable, { brand: (_b = s.brand) != null ? _b : brand, competitor: s.competitor, rows: s.rows });
316
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComparisonTable, { brand: (_b = s.brand) != null ? _b : brand, competitor: s.competitor, rows: s.rows, unit });
242
317
  case "FeatureList":
243
- return /* @__PURE__ */ jsxRuntime.jsx(FeatureList, { items: s.items });
318
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FeatureList, { items: s.items, unit });
244
319
  case "TestimonialCard":
245
- return /* @__PURE__ */ jsxRuntime.jsx(TestimonialCard, { quote: s.quote, name: s.name, role: s.role, company: s.company });
320
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TestimonialCard, { quote: s.quote, name: s.name, role: s.role, company: s.company, unit });
246
321
  case "ImageCtaHero":
247
- return /* @__PURE__ */ jsxRuntime.jsx(ImageCtaHero, { src: s.src, alt: s.alt, headline: s.headline, subheading: s.subheading, ctaLabel: s.ctaLabel, ctaHref: s.ctaHref, align });
322
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageCtaHero, { src: s.src, alt: s.alt, headline: s.headline, subheading: s.subheading, ctaLabel: s.ctaLabel, ctaHref: s.ctaHref, align, unit });
248
323
  case "CtaStrip":
249
- return /* @__PURE__ */ jsxRuntime.jsx(CtaStrip, { headline: s.headline, primary: s.primary, secondary: s.secondary, align });
324
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CtaStrip, { headline: s.headline, primary: s.primary, secondary: s.secondary, align, unit });
250
325
  // An unrecognised component name used to render nothing at all. A component needs a
251
- // renderer in three places plus the WordPress plugin, so missing one made its content
326
+ // renderer here plus spectare.js plus the WordPress plugin, so missing one made its content
252
327
  // silently absent on that surface only: no error, no warning, just a shorter page that
253
328
  // looks deliberate. That is the failure mode to remove before the registry grows.
254
329
  //
@@ -259,7 +334,7 @@ function renderSingle(item, brand, align) {
259
334
  default: {
260
335
  console.warn(`[spectare] ComponentRenderer: no renderer for "${item.component}", falling back to AtomCard`);
261
336
  if (!s.title && !s.content) return null;
262
- return /* @__PURE__ */ jsxRuntime.jsx(AtomCard, { title: s.title, content: s.content, stats: s.stats, ctaText: s.ctaText, ctaUrl: s.ctaUrl, full: true });
337
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AtomCard, { title: s.title, content: s.content, stats: s.stats, ctaText: s.ctaText, ctaUrl: s.ctaUrl, full: true, unit });
263
338
  }
264
339
  }
265
340
  }
@@ -267,13 +342,19 @@ function resolvedSize(item) {
267
342
  if (item.size) return item.size;
268
343
  return HALF_COMPONENTS.has(item.component) ? "half" : "full";
269
344
  }
345
+ function pairable(a, b) {
346
+ const catOf = (x) => COMPONENT_CATEGORIES[x.component];
347
+ const ca = catOf(a);
348
+ const cb = catOf(b);
349
+ return ca !== void 0 && ca === cb;
350
+ }
270
351
  function buildLayout(assembly) {
271
352
  const groups = [];
272
353
  let i = 0;
273
354
  while (i < assembly.length) {
274
355
  const cur = assembly[i];
275
356
  const next = assembly[i + 1];
276
- if (resolvedSize(cur) === "half" && next && resolvedSize(next) === "half") {
357
+ if (resolvedSize(cur) === "half" && next && resolvedSize(next) === "half" && pairable(cur, next)) {
277
358
  groups.push({ type: "pair", items: [cur, next] });
278
359
  i += 2;
279
360
  } else if (resolvedSize(cur) === "half") {
@@ -287,42 +368,46 @@ function buildLayout(assembly) {
287
368
  return groups;
288
369
  }
289
370
  function XrayBadge({ name, size }) {
290
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "absolute", top: "8px", left: "8px", zIndex: 10, display: "flex", alignItems: "center", gap: "6px", pointerEvents: "none", userSelect: "none" }, children: [
291
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "10px", fontFamily: "monospace", background: "rgba(59,130,246,0.9)", color: "#fff", padding: "2px 6px", borderRadius: "4px", lineHeight: 1 }, children: name }),
292
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "10px", fontFamily: "monospace", color: "#71717a", lineHeight: 1 }, children: size })
371
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "absolute", top: PX(8), left: PX(8), zIndex: 10, display: "flex", alignItems: "center", gap: PX(6), pointerEvents: "none", userSelect: "none" }, children: [
372
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: PX(10), fontFamily: "monospace", background: "rgba(59,130,246,0.9)", color: "#fff", padding: `${PX(2)} ${PX(6)}`, borderRadius: PX(4), lineHeight: 1 }, children: name }),
373
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: PX(10), fontFamily: "monospace", color: "#71717a", lineHeight: 1 }, children: size })
293
374
  ] });
294
375
  }
295
- function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent }) {
376
+ function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent, unit = "px", renderOverride, renderItem, rootProps }) {
377
+ const u = scaler(unit);
296
378
  const filtered = zone ? filterAssemblyByZone(assembly, zone) : assembly;
297
379
  const layout = buildLayout(filtered);
298
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: SP_ROOT, style: { display: "flex", flexDirection: "column", gap: "20px", fontSize: "16px" }, children: [
299
- /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: buildTokenCss({ accent }) } }),
380
+ const { className: extraClass, style: extraStyle, ...restRoot } = rootProps != null ? rootProps : {};
381
+ const renderOne = (item) => {
382
+ const override = renderOverride == null ? void 0 : renderOverride(item);
383
+ const node = override === void 0 ? renderSingle(item, brand, align, unit) : override;
384
+ return renderItem ? renderItem(item, node) : node;
385
+ };
386
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: extraClass ? `${SP_ROOT} ${extraClass}` : SP_ROOT, ...restRoot, style: { ...extraStyle, display: "flex", flexDirection: "column", gap: u(20), ...unit === "px" ? { fontSize: "16px" } : {} }, children: [
387
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { dangerouslySetInnerHTML: { __html: buildTokenCss({ accent, unit }) } }),
300
388
  layout.map((group, i) => {
301
- if (group.type === "full") {
302
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
303
- xray && /* @__PURE__ */ jsxRuntime.jsx(XrayBadge, { name: group.item.component, size: "full" }),
304
- renderSingle(group.item, brand, align)
305
- ] }, i);
306
- }
307
389
  if (group.type === "pair") {
308
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sp-pair", children: [
309
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
310
- xray && /* @__PURE__ */ jsxRuntime.jsx(XrayBadge, { name: group.items[0].component, size: "half" }),
311
- renderSingle(group.items[0], brand, align)
390
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sp-pair", children: [
391
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: xray ? { position: "relative" } : void 0, children: [
392
+ xray && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XrayBadge, { name: group.items[0].component, size: "half" }),
393
+ renderOne(group.items[0])
312
394
  ] }),
313
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
314
- xray && /* @__PURE__ */ jsxRuntime.jsx(XrayBadge, { name: group.items[1].component, size: "half" }),
315
- renderSingle(group.items[1], brand, align)
395
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: xray ? { position: "relative" } : void 0, children: [
396
+ xray && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XrayBadge, { name: group.items[1].component, size: "half" }),
397
+ renderOne(group.items[1])
316
398
  ] })
317
399
  ] }, i);
318
400
  }
319
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
320
- xray && /* @__PURE__ */ jsxRuntime.jsx(XrayBadge, { name: group.item.component, size: "full" }),
321
- renderSingle(group.item, brand, align)
401
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: xray ? { position: "relative" } : void 0, children: [
402
+ xray && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XrayBadge, { name: group.item.component, size: group.type === "half-solo" ? "half" : "full" }),
403
+ renderOne(group.item)
322
404
  ] }, i);
323
405
  })
324
406
  ] });
325
407
  }
408
+
409
+ // src/PersonalisedSection.tsx
410
+ var import_jsx_runtime2 = require("react/jsx-runtime");
326
411
  var VARIANT_KEY = (orgSlug) => `_spectare_variant_${orgSlug}`;
327
412
  function readVariantId(orgSlug) {
328
413
  try {
@@ -372,11 +457,11 @@ function readVisitPath(orgSlug) {
372
457
  }
373
458
  }
374
459
  function Shimmer() {
375
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
376
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "20px", background: "rgba(39,39,42,0.6)", borderRadius: "8px", width: "75%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
377
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "100%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
378
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "83%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
379
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "67%", animation: "sp-pulse 1.5s ease-in-out infinite" } })
460
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
461
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { height: "20px", background: "rgba(39,39,42,0.6)", borderRadius: "8px", width: "75%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
462
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "100%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
463
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "83%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
464
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "67%", animation: "sp-pulse 1.5s ease-in-out infinite" } })
380
465
  ] });
381
466
  }
382
467
  function PersonalisedSection({
@@ -394,21 +479,21 @@ function PersonalisedSection({
394
479
  align,
395
480
  accent
396
481
  }) {
397
- const [assembly, setAssembly] = react.useState(initialAssembly != null ? initialAssembly : []);
398
- const [loading, setLoading] = react.useState(!initialAssembly);
399
- const [orgName, setOrgName] = react.useState(void 0);
400
- const [debugMode, setDebugMode] = react.useState(false);
401
- const [debugIntent, setDebugIntent] = react.useState(null);
402
- const tokenRef = react.useRef(null);
403
- const conversionFiredRef = react.useRef(false);
404
- react.useEffect(() => {
482
+ const [assembly, setAssembly] = (0, import_react.useState)(initialAssembly != null ? initialAssembly : []);
483
+ const [loading, setLoading] = (0, import_react.useState)(!initialAssembly);
484
+ const [orgName, setOrgName] = (0, import_react.useState)(void 0);
485
+ const [debugMode, setDebugMode] = (0, import_react.useState)(false);
486
+ const [debugIntent, setDebugIntent] = (0, import_react.useState)(null);
487
+ const tokenRef = (0, import_react.useRef)(null);
488
+ const conversionFiredRef = (0, import_react.useRef)(false);
489
+ (0, import_react.useEffect)(() => {
405
490
  setDebugMode(new URLSearchParams(window.location.search).has("spectare_debug"));
406
491
  if (initialIntent) setDebugIntent(initialIntent);
407
492
  }, [initialIntent]);
408
- react.useEffect(() => {
493
+ (0, import_react.useEffect)(() => {
409
494
  if (initialVariantId) writeVariantId(orgSlug, initialVariantId);
410
495
  }, [orgSlug, initialVariantId]);
411
- react.useEffect(() => {
496
+ (0, import_react.useEffect)(() => {
412
497
  let cancelled = false;
413
498
  async function load() {
414
499
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
@@ -574,7 +659,7 @@ function PersonalisedSection({
574
659
  cancelled = true;
575
660
  };
576
661
  }, [orgSlug, baseUrl, pageHint, initialAssembly, initialIntent, directSummary]);
577
- react.useEffect(() => {
662
+ (0, import_react.useEffect)(() => {
578
663
  if (!assembly.length || conversionFiredRef.current) return;
579
664
  const token = tokenRef.current;
580
665
  if (!token) return;
@@ -631,38 +716,39 @@ function PersonalisedSection({
631
716
  }, [assembly, orgSlug, baseUrl]);
632
717
  if (!loading && assembly.length === 0) return null;
633
718
  const debugStyle = debugMode ? { outline: "2px solid rgba(96,165,250,0.5)", borderRadius: "0.5rem", position: "relative", padding: "0.5rem", ...style } : style;
634
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
635
- /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: "@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}" } }),
636
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: debugStyle, children: [
637
- debugMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "absolute", top: "-1px", right: "-1px", zIndex: 20, display: "flex", alignItems: "center", gap: "0.375rem", background: "rgba(96,165,250,0.9)", borderRadius: "0 0.5rem 0 0.375rem", padding: "0.25rem 0.625rem", fontSize: "0.625rem", fontFamily: "monospace", color: "#fff", pointerEvents: "none", userSelect: "none" }, children: [
719
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
720
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { dangerouslySetInnerHTML: { __html: "@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}" } }),
721
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className, style: debugStyle, children: [
722
+ debugMode && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "absolute", top: "-1px", right: "-1px", zIndex: 20, display: "flex", alignItems: "center", gap: "0.375rem", background: "rgba(96,165,250,0.9)", borderRadius: "0 0.5rem 0 0.375rem", padding: "0.25rem 0.625rem", fontSize: "0.625rem", fontFamily: "monospace", color: "#fff", pointerEvents: "none", userSelect: "none" }, children: [
638
723
  "Personalised by Spectare",
639
- debugIntent && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { opacity: 0.75 }, children: [
724
+ debugIntent && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { opacity: 0.75 }, children: [
640
725
  " ",
641
726
  debugIntent.audience,
642
727
  "/",
643
728
  debugIntent.stage
644
729
  ] })
645
730
  ] }),
646
- loading && assembly.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(Shimmer, {}) : /* @__PURE__ */ jsxRuntime.jsx(ComponentRenderer, { assembly: zone ? filterAssemblyByZone(assembly, zone) : assembly, brand: brand != null ? brand : orgName, align, accent })
731
+ loading && assembly.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Shimmer, {}) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ComponentRenderer, { assembly: zone ? filterAssemblyByZone(assembly, zone) : assembly, brand: brand != null ? brand : orgName, align, accent })
647
732
  ] })
648
733
  ] });
649
734
  }
650
-
651
- exports.AnnouncementBar = AnnouncementBar;
652
- exports.AtomCard = AtomCard;
653
- exports.CodeBlock = CodeBlock;
654
- exports.ComparisonTable = ComparisonTable;
655
- exports.ComponentRenderer = ComponentRenderer;
656
- exports.CtaStrip = CtaStrip;
657
- exports.DEFAULT_ACCENT = DEFAULT_ACCENT;
658
- exports.FeatureList = FeatureList;
659
- exports.HeroStatement = HeroStatement;
660
- exports.ImageCtaHero = ImageCtaHero;
661
- exports.PersonalisedSection = PersonalisedSection;
662
- exports.SP_ROOT = SP_ROOT;
663
- exports.StatGrid = StatGrid;
664
- exports.TestimonialCard = TestimonialCard;
665
- exports.buildTokenCss = buildTokenCss;
666
- exports.filterAssemblyByZone = filterAssemblyByZone;
667
- //# sourceMappingURL=index.cjs.map
735
+ // Annotate the CommonJS export names for ESM import in node:
736
+ 0 && (module.exports = {
737
+ AnnouncementBar,
738
+ AtomCard,
739
+ CodeBlock,
740
+ ComparisonTable,
741
+ ComponentRenderer,
742
+ CtaStrip,
743
+ DEFAULT_ACCENT,
744
+ FeatureList,
745
+ HeroStatement,
746
+ ImageCtaHero,
747
+ PersonalisedSection,
748
+ SP_ROOT,
749
+ StatGrid,
750
+ TestimonialCard,
751
+ buildTokenCss,
752
+ filterAssemblyByZone
753
+ });
668
754
  //# sourceMappingURL=index.cjs.map