@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.d.ts CHANGED
@@ -50,6 +50,7 @@ interface PersonalisedSectionProps {
50
50
  }
51
51
  declare function PersonalisedSection({ orgSlug, baseUrl, brand, pageHint, className, style, initialAssembly, initialIntent, initialVariantId, directSummary, zone, align, accent, }: PersonalisedSectionProps): react_jsx_runtime.JSX.Element | null;
52
52
 
53
+ type Unit = 'px' | 'rem';
53
54
  type Align = 'left' | 'center' | 'right';
54
55
  /**
55
56
  * A single line above everything else. Deliberately the plainest component in the set: no
@@ -60,19 +61,21 @@ type Align = 'left' | 'center' | 'right';
60
61
  * warning, and a venue putting "members book from Thursday" in an alarm colour reads as a problem
61
62
  * rather than an offer.
62
63
  */
63
- declare function AnnouncementBar({ text, link }: {
64
+ declare function AnnouncementBar({ text, link, unit }: {
64
65
  text?: string;
65
66
  link?: {
66
67
  label: string;
67
68
  href: string;
68
69
  };
70
+ unit?: Unit;
69
71
  }): react_jsx_runtime.JSX.Element | null;
70
- declare function HeroStatement({ headline, subheading, align }: {
72
+ declare function HeroStatement({ headline, subheading, align, unit }: {
71
73
  headline: string;
72
74
  subheading?: string;
73
75
  align?: Align;
76
+ unit?: Unit;
74
77
  }): react_jsx_runtime.JSX.Element;
75
- declare function AtomCard({ title, content, layout, stats, ctaText, ctaUrl, full }: {
78
+ declare function AtomCard({ title, content, layout, stats, ctaText, ctaUrl, full, unit }: {
76
79
  title?: string;
77
80
  content?: string;
78
81
  layout?: string[];
@@ -83,20 +86,23 @@ declare function AtomCard({ title, content, layout, stats, ctaText, ctaUrl, full
83
86
  ctaText?: string;
84
87
  ctaUrl?: string;
85
88
  full?: boolean;
89
+ unit?: Unit;
86
90
  }): react_jsx_runtime.JSX.Element;
87
- declare function StatGrid({ stats, caption }: {
91
+ declare function StatGrid({ stats, caption, unit }: {
88
92
  stats?: {
89
93
  value: string;
90
94
  label: string;
91
95
  }[];
92
96
  caption?: string;
97
+ unit?: Unit;
93
98
  }): react_jsx_runtime.JSX.Element;
94
- declare function CodeBlock({ code, lang, caption }: {
99
+ declare function CodeBlock({ code, lang, caption, unit }: {
95
100
  code: string;
96
101
  lang?: string;
97
102
  caption?: string;
103
+ unit?: Unit;
98
104
  }): react_jsx_runtime.JSX.Element;
99
- declare function ComparisonTable({ brand, competitor, rows }: {
105
+ declare function ComparisonTable({ brand, competitor, rows, unit }: {
100
106
  brand?: string;
101
107
  competitor: string;
102
108
  rows?: {
@@ -104,20 +110,23 @@ declare function ComparisonTable({ brand, competitor, rows }: {
104
110
  spectare: string;
105
111
  them: string;
106
112
  }[];
113
+ unit?: Unit;
107
114
  }): react_jsx_runtime.JSX.Element;
108
- declare function FeatureList({ items }: {
115
+ declare function FeatureList({ items, unit }: {
109
116
  items?: {
110
117
  text: string;
111
118
  sub?: string;
112
119
  }[];
120
+ unit?: Unit;
113
121
  }): react_jsx_runtime.JSX.Element;
114
- declare function TestimonialCard({ quote, name, role, company }: {
122
+ declare function TestimonialCard({ quote, name, role, company, unit }: {
115
123
  quote: string;
116
124
  name: string;
117
125
  role: string;
118
126
  company?: string;
127
+ unit?: Unit;
119
128
  }): react_jsx_runtime.JSX.Element;
120
- declare function ImageCtaHero({ src, alt, headline, subheading, ctaLabel, ctaHref, align }: {
129
+ declare function ImageCtaHero({ src, alt, headline, subheading, ctaLabel, ctaHref, align, unit }: {
121
130
  src?: string;
122
131
  alt?: string;
123
132
  headline?: string;
@@ -125,8 +134,9 @@ declare function ImageCtaHero({ src, alt, headline, subheading, ctaLabel, ctaHre
125
134
  ctaLabel?: string;
126
135
  ctaHref?: string;
127
136
  align?: Align;
137
+ unit?: Unit;
128
138
  }): react_jsx_runtime.JSX.Element | null;
129
- declare function CtaStrip({ headline, primary, secondary, align }: {
139
+ declare function CtaStrip({ headline, primary, secondary, align, unit }: {
130
140
  headline: string;
131
141
  primary: {
132
142
  label: string;
@@ -137,6 +147,7 @@ declare function CtaStrip({ headline, primary, secondary, align }: {
137
147
  href: string;
138
148
  };
139
149
  align?: Align;
150
+ unit?: Unit;
140
151
  }): react_jsx_runtime.JSX.Element;
141
152
  interface ComponentRendererProps {
142
153
  assembly: ComponentAssembly;
@@ -158,8 +169,27 @@ interface ComponentRendererProps {
158
169
  * from it, so one value covers all three. Defaults to #60a5fa.
159
170
  */
160
171
  accent?: string;
172
+ /**
173
+ * px (default) sizes components absolutely, predictable inside arbitrary host pages.
174
+ * rem tracks the reader's font-size preference; the root then also inherits the host's
175
+ * font size instead of pinning 16px.
176
+ */
177
+ unit?: Unit;
178
+ /**
179
+ * Substitute rendering for an item: return a node to replace the built-in renderer
180
+ * (including null to render nothing), or undefined to keep the default. How the Spectare
181
+ * app swaps the card-variant AtomCard for its server-rendered card face.
182
+ */
183
+ renderOverride?: (item: ComponentAssembly[0]) => React.ReactNode | undefined;
184
+ /**
185
+ * Wrap each rendered item, e.g. with source attribution or a debug badge. Receives the
186
+ * assembly item and its rendered node; whatever it returns is placed in the layout.
187
+ */
188
+ renderItem?: (item: ComponentAssembly[0], rendered: React.ReactNode) => React.ReactNode;
189
+ /** Extra attributes for the root element (e.g. a data marker a host overlay targets). */
190
+ rootProps?: Record<string, unknown>;
161
191
  }
162
- declare function ComponentRenderer({ assembly, brand, xray, zone, align, accent }: ComponentRendererProps): react_jsx_runtime.JSX.Element;
192
+ declare function ComponentRenderer({ assembly, brand, xray, zone, align, accent, unit, renderOverride, renderItem, rootProps }: ComponentRendererProps): react_jsx_runtime.JSX.Element;
163
193
 
164
194
  /**
165
195
  * The one place this package's design tokens are defined.
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
- import { useState, useRef, useEffect } from 'react';
2
- import { marked } from 'marked';
3
- import DOMPurify from 'isomorphic-dompurify';
4
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
1
+ 'use client';
5
2
 
6
3
  // src/PersonalisedSection.tsx
4
+ import { useEffect, useRef, useState } from "react";
5
+
6
+ // src/ComponentRenderer.tsx
7
+ import { marked } from "marked";
8
+ import DOMPurify from "isomorphic-dompurify";
7
9
 
8
10
  // src/types.ts
9
11
  var COMPONENT_ZONES = {
@@ -25,10 +27,23 @@ function filterAssemblyByZone(assembly, zone) {
25
27
  return effectiveZone === zone;
26
28
  });
27
29
  }
30
+ var COMPONENT_CATEGORIES = {
31
+ AnnouncementBar: "conversion",
32
+ HeroStatement: "hero",
33
+ AtomCard: "content",
34
+ StatGrid: "content",
35
+ CodeBlock: "technical",
36
+ ComparisonTable: "evaluation",
37
+ FeatureList: "content",
38
+ TestimonialCard: "social-proof",
39
+ ImageCtaHero: "hero",
40
+ CtaStrip: "conversion"
41
+ };
28
42
 
29
43
  // src/tokens.ts
30
44
  var DEFAULT_ACCENT = "#60a5fa";
31
45
  var SP_ROOT = "sp-root";
46
+ var STYLESHEET_SCOPE = `:where(:root),.${SP_ROOT}`;
32
47
  function palette(accent) {
33
48
  return {
34
49
  "--sp-accent": accent,
@@ -72,26 +87,32 @@ function buildTokenCss({ accent = DEFAULT_ACCENT, unit = "px", scope = `.${SP_RO
72
87
  const decls = Object.entries(palette(accent)).map(([k, v]) => `${k}:${v}`).join(";");
73
88
  return `${scope}{${decls}}${rules(unit)}`;
74
89
  }
90
+
91
+ // src/ComponentRenderer.tsx
92
+ import { jsx, jsxs } from "react/jsx-runtime";
75
93
  function renderMarkdown(content) {
76
94
  const raw = marked.parse(content != null ? content : "", { async: false });
77
95
  return DOMPurify.sanitize(raw, { USE_PROFILES: { html: true } });
78
96
  }
97
+ var scaler = (unit) => (n) => unit === "rem" ? `${n / 16}rem` : `${n}px`;
98
+ var PX = scaler("px");
79
99
  var HALF_COMPONENTS = /* @__PURE__ */ new Set(["TestimonialCard"]);
80
100
  var flexItems = (a) => a === "center" ? "center" : a === "right" ? "flex-end" : "flex-start";
81
- function AnnouncementBar({ text, link }) {
101
+ function AnnouncementBar({ text, link, unit = "px" }) {
102
+ const u = scaler(unit);
82
103
  if (!text) return null;
83
104
  return /* @__PURE__ */ jsxs("div", { style: {
84
105
  display: "flex",
85
106
  alignItems: "center",
86
107
  justifyContent: "center",
87
- gap: "10px",
108
+ gap: u(10),
88
109
  flexWrap: "wrap",
89
110
  textAlign: "center",
90
111
  background: "var(--sp-accent-bg)",
91
112
  border: "1px solid var(--sp-accent-border)",
92
- borderRadius: "8px",
93
- padding: "8px 16px",
94
- fontSize: "14px",
113
+ borderRadius: u(8),
114
+ padding: `${u(8)} ${u(16)}`,
115
+ fontSize: u(14),
95
116
  lineHeight: 1.4,
96
117
  color: "var(--sp-text-sub)"
97
118
  }, children: [
@@ -102,10 +123,11 @@ function AnnouncementBar({ text, link }) {
102
123
  ] })
103
124
  ] });
104
125
  }
105
- function HeroStatement({ headline, subheading, align = "left" }) {
106
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: flexItems(align), textAlign: align, paddingTop: "24px", paddingBottom: "24px" }, children: [
107
- /* @__PURE__ */ jsx("h2", { style: { fontSize: "32px", fontWeight: 700, letterSpacing: "-0.025em", lineHeight: 1.2, color: "var(--sp-text)", margin: "0 0 12px" }, children: headline }),
108
- subheading && /* @__PURE__ */ jsx("p", { style: { fontSize: "18px", color: "var(--sp-text-sub)", lineHeight: 1.6, maxWidth: "672px", margin: 0 }, children: subheading })
126
+ function HeroStatement({ headline, subheading, align = "left", unit = "px" }) {
127
+ const u = scaler(unit);
128
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: flexItems(align), textAlign: align, paddingTop: u(24), paddingBottom: u(24) }, children: [
129
+ /* @__PURE__ */ 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 }),
130
+ subheading && /* @__PURE__ */ jsx("p", { style: { fontSize: u(18), color: "var(--sp-text-sub)", lineHeight: 1.6, maxWidth: u(672), margin: 0 }, children: subheading })
109
131
  ] });
110
132
  }
111
133
  var ATOM_LAYOUT_DEFAULT = ["title", "content", "stats", "cta"];
@@ -116,133 +138,142 @@ var clampStyle = {
116
138
  WebkitBoxOrient: "vertical",
117
139
  overflow: "hidden"
118
140
  };
119
- function AtomCard({ title, content, layout, stats = [], ctaText, ctaUrl, full }) {
141
+ function AtomCard({ title, content, layout, stats = [], ctaText, ctaUrl, full, unit = "px" }) {
142
+ const u = scaler(unit);
120
143
  const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;
121
144
  const element = (name) => {
122
- if (name === "title") return title ? /* @__PURE__ */ jsx("h3", { style: { fontSize: "16px", fontWeight: 600, color: "var(--sp-text)", margin: "0 0 12px" }, children: title }, "title") : null;
123
- if (name === "content") return content ? /* @__PURE__ */ jsx("div", { className: "sp-prose", style: { fontSize: "15px", color: "var(--sp-text-sub)", lineHeight: 1.6, ...full ? {} : clampStyle }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } }, "content") : null;
124
- if (name === "stats") return stats.length ? /* @__PURE__ */ 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__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [
125
- /* @__PURE__ */ jsx("span", { style: { fontSize: "22px", fontWeight: 700, color: "var(--sp-text)", lineHeight: 1, fontVariantNumeric: "tabular-nums" }, children: s.value }),
126
- /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: s.label })
145
+ if (name === "title") return title ? /* @__PURE__ */ jsx("h3", { style: { fontSize: u(16), fontWeight: 600, color: "var(--sp-text)", margin: `0 0 ${u(12)}` }, children: title }, "title") : null;
146
+ if (name === "content") return content ? /* @__PURE__ */ 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;
147
+ if (name === "stats") return stats.length ? /* @__PURE__ */ 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__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: u(2) }, children: [
148
+ /* @__PURE__ */ jsx("span", { style: { fontSize: u(22), fontWeight: 700, color: "var(--sp-text)", lineHeight: 1, fontVariantNumeric: "tabular-nums" }, children: s.value }),
149
+ /* @__PURE__ */ jsx("span", { style: { fontSize: u(11), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: s.label })
127
150
  ] }, i)) }, "stats") : null;
128
- if (name === "cta") return ctaText && ctaUrl ? /* @__PURE__ */ 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: [
151
+ if (name === "cta") return ctaText && ctaUrl ? /* @__PURE__ */ 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: [
129
152
  ctaText,
130
153
  " \u2192"
131
154
  ] }, "cta") : null;
132
155
  return null;
133
156
  };
134
- return /* @__PURE__ */ jsx("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "24px", height: "100%" }, children: order.map(element) });
157
+ return /* @__PURE__ */ 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) });
135
158
  }
136
- function StatGrid({ stats = [], caption }) {
159
+ function StatGrid({ stats = [], caption, unit = "px" }) {
160
+ const u = scaler(unit);
137
161
  const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;
138
162
  return /* @__PURE__ */ jsxs("div", { children: [
139
- /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: "12px" }, children: stats.map(({ value, label }) => /* @__PURE__ */ 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: [
140
- /* @__PURE__ */ jsx("p", { style: { fontSize: "11px", color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em", margin: "0 0 12px", lineHeight: 1.3 }, children: label }),
141
- /* @__PURE__ */ jsx("p", { style: { fontSize: "20px", fontWeight: 500, color: "var(--sp-text)", fontVariantNumeric: "tabular-nums", lineHeight: 1, margin: 0 }, children: value })
163
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: u(12) }, children: stats.map(({ value, label }) => /* @__PURE__ */ 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: [
164
+ /* @__PURE__ */ 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 }),
165
+ /* @__PURE__ */ jsx("p", { style: { fontSize: u(20), fontWeight: 500, color: "var(--sp-text)", fontVariantNumeric: "tabular-nums", lineHeight: 1, margin: 0 }, children: value })
142
166
  ] }, label)) }),
143
- caption && /* @__PURE__ */ jsx("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", margin: "12px 0 0" }, children: caption })
167
+ caption && /* @__PURE__ */ jsx("p", { style: { fontSize: u(13), color: "var(--sp-text-muted)", margin: `${u(12)} 0 0` }, children: caption })
144
168
  ] });
145
169
  }
146
- function CodeBlock({ code, lang = "typescript", caption }) {
147
- return /* @__PURE__ */ jsxs("div", { style: { borderRadius: "12px", overflow: "hidden", border: "1px solid var(--sp-border)" }, children: [
148
- /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", padding: "10px 16px", display: "flex", alignItems: "center", justifyContent: "space-between", borderBottom: "1px solid var(--sp-border)" }, children: [
149
- /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "var(--sp-text-muted)", fontFamily: "monospace" }, children: lang }),
150
- caption && /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "var(--sp-text-muted)" }, children: caption })
170
+ function CodeBlock({ code, lang = "typescript", caption, unit = "px" }) {
171
+ const u = scaler(unit);
172
+ return /* @__PURE__ */ jsxs("div", { style: { borderRadius: u(12), overflow: "hidden", border: "1px solid var(--sp-border)" }, children: [
173
+ /* @__PURE__ */ 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: [
174
+ /* @__PURE__ */ jsx("span", { style: { fontSize: u(12), color: "var(--sp-text-muted)", fontFamily: "monospace" }, children: lang }),
175
+ caption && /* @__PURE__ */ jsx("span", { style: { fontSize: u(12), color: "var(--sp-text-muted)" }, children: caption })
151
176
  ] }),
152
- /* @__PURE__ */ 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 })
177
+ /* @__PURE__ */ 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 })
153
178
  ] });
154
179
  }
155
- function ComparisonTable({ brand = "Us", competitor, rows = [] }) {
156
- return /* @__PURE__ */ jsx("div", { style: { border: "1px solid var(--sp-border)", borderRadius: "12px", overflow: "hidden" }, children: /* @__PURE__ */ jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxs("table", { style: { width: "100%", fontSize: "14px", borderCollapse: "collapse" }, children: [
180
+ function ComparisonTable({ brand = "Us", competitor, rows = [], unit = "px" }) {
181
+ const u = scaler(unit);
182
+ const cell = { textAlign: "left", padding: `${u(12)} ${u(16)}` };
183
+ return /* @__PURE__ */ jsx("div", { style: { border: "1px solid var(--sp-border)", borderRadius: u(12), overflow: "hidden" }, children: /* @__PURE__ */ jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxs("table", { style: { width: "100%", fontSize: u(14), borderCollapse: "collapse" }, children: [
157
184
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { style: { borderBottom: "1px solid var(--sp-border)", background: "var(--sp-bg)" }, children: [
158
- /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "12px 16px", color: "var(--sp-text-muted)", fontWeight: 500, fontSize: "12px", width: "33%" } }),
159
- /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "12px 16px", fontWeight: 600, color: "var(--sp-accent)", fontSize: "12px" }, children: brand }),
160
- /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "12px 16px", color: "var(--sp-text-muted)", fontWeight: 500, fontSize: "12px" }, children: competitor })
185
+ /* @__PURE__ */ jsx("th", { style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(12), width: "33%" } }),
186
+ /* @__PURE__ */ jsx("th", { scope: "col", style: { ...cell, fontWeight: 600, color: "var(--sp-accent)", fontSize: u(12) }, children: brand }),
187
+ /* @__PURE__ */ jsx("th", { scope: "col", style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(12) }, children: competitor })
161
188
  ] }) }),
162
189
  /* @__PURE__ */ jsx("tbody", { children: rows.map(({ label, spectare, them }) => /* @__PURE__ */ jsxs("tr", { style: { borderBottom: "1px solid var(--sp-border)" }, children: [
163
- /* @__PURE__ */ jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
164
- /* @__PURE__ */ jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
165
- /* @__PURE__ */ jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-text-muted)" }, children: them })
190
+ /* @__PURE__ */ jsx("th", { scope: "row", style: { ...cell, fontSize: u(13), color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
191
+ /* @__PURE__ */ jsx("td", { style: { ...cell, fontSize: u(13), color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
192
+ /* @__PURE__ */ jsx("td", { style: { ...cell, fontSize: u(13), color: "var(--sp-text-muted)" }, children: them })
166
193
  ] }, label)) })
167
194
  ] }) }) });
168
195
  }
169
- function FeatureList({ items = [] }) {
170
- return /* @__PURE__ */ jsx("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "24px" }, children: /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "16px" }, children: items.map(({ text, sub }) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", gap: "12px" }, children: [
171
- /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: "15px", marginTop: "2px" }, children: "\u2713" }),
196
+ function FeatureList({ items = [], unit = "px" }) {
197
+ const u = scaler(unit);
198
+ return /* @__PURE__ */ jsx("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(24) }, children: /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: u(16) }, children: items.map(({ text, sub }) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", gap: u(12) }, children: [
199
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: u(15), marginTop: u(2) }, children: "\u2713" }),
172
200
  /* @__PURE__ */ jsxs("div", { children: [
173
- /* @__PURE__ */ jsx("p", { style: { fontSize: "15px", fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
174
- sub && /* @__PURE__ */ jsx("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", lineHeight: 1.5, margin: "4px 0 0" }, children: sub })
201
+ /* @__PURE__ */ jsx("p", { style: { fontSize: u(15), fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
202
+ sub && /* @__PURE__ */ jsx("p", { style: { fontSize: u(13), color: "var(--sp-text-muted)", lineHeight: 1.5, margin: `${u(4)} 0 0` }, children: sub })
175
203
  ] })
176
204
  ] }, text)) }) });
177
205
  }
178
- function TestimonialCard({ quote, name, role, company }) {
179
- return /* @__PURE__ */ 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: [
180
- /* @__PURE__ */ jsxs("p", { style: { fontSize: "15px", color: "var(--sp-text-sub)", lineHeight: 1.6, flex: 1, margin: 0 }, children: [
181
- /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: "18px", lineHeight: 1, marginRight: "4px" }, children: '"' }),
206
+ function TestimonialCard({ quote, name, role, company, unit = "px" }) {
207
+ const u = scaler(unit);
208
+ return /* @__PURE__ */ 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: [
209
+ /* @__PURE__ */ jsxs("p", { style: { fontSize: u(15), color: "var(--sp-text-sub)", lineHeight: 1.6, flex: 1, margin: 0 }, children: [
210
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: u(18), lineHeight: 1, marginRight: u(4) }, children: '"' }),
182
211
  quote,
183
- /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: "18px", lineHeight: 1, marginLeft: "4px" }, children: '"' })
212
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: u(18), lineHeight: 1, marginLeft: u(4) }, children: '"' })
184
213
  ] }),
185
- /* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: "16px" }, children: [
186
- /* @__PURE__ */ jsx("p", { style: { fontSize: "14px", fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
187
- /* @__PURE__ */ jsxs("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", margin: "2px 0 0" }, children: [
214
+ /* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: u(16) }, children: [
215
+ /* @__PURE__ */ jsx("p", { style: { fontSize: u(14), fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
216
+ /* @__PURE__ */ jsxs("p", { style: { fontSize: u(13), color: "var(--sp-text-muted)", margin: `${u(2)} 0 0` }, children: [
188
217
  role,
189
218
  company ? `, ${company}` : ""
190
219
  ] })
191
220
  ] })
192
221
  ] });
193
222
  }
194
- function ImageCtaHero({ src, alt = "", headline, subheading, ctaLabel, ctaHref, align = "left" }) {
223
+ function ImageCtaHero({ src, alt = "", headline, subheading, ctaLabel, ctaHref, align = "left", unit = "px" }) {
224
+ const u = scaler(unit);
195
225
  if (!src) return null;
196
- return /* @__PURE__ */ jsxs("div", { style: { borderRadius: "12px", overflow: "hidden", position: "relative", width: "100%", paddingBottom: "56.25%" }, children: [
226
+ return /* @__PURE__ */ jsxs("div", { style: { borderRadius: u(12), overflow: "hidden", position: "relative", width: "100%", paddingBottom: "56.25%" }, children: [
197
227
  /* @__PURE__ */ jsx("img", { src, alt, style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" } }),
198
228
  /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.45)" } }),
199
229
  /* @__PURE__ */ 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%)" } }),
200
- /* @__PURE__ */ jsxs("div", { style: { position: "absolute", bottom: 0, left: 0, right: 0, padding: "28px", textAlign: align }, children: [
201
- headline && /* @__PURE__ */ jsx("h2", { style: { fontSize: "24px", fontWeight: 700, color: "#fff", lineHeight: 1.2, margin: "0 0 8px", letterSpacing: "-0.02em" }, children: headline }),
202
- subheading && /* @__PURE__ */ jsx("p", { style: { fontSize: "15px", color: "rgba(255,255,255,0.75)", lineHeight: 1.5, margin: "0 0 20px" }, children: subheading }),
203
- ctaHref && ctaLabel && /* @__PURE__ */ 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 })
230
+ /* @__PURE__ */ jsxs("div", { style: { position: "absolute", bottom: 0, left: 0, right: 0, padding: u(28), textAlign: align }, children: [
231
+ headline && /* @__PURE__ */ jsx("h2", { style: { fontSize: u(24), fontWeight: 700, color: "#fff", lineHeight: 1.2, margin: `0 0 ${u(8)}`, letterSpacing: "-0.02em" }, children: headline }),
232
+ subheading && /* @__PURE__ */ jsx("p", { style: { fontSize: u(15), color: "rgba(255,255,255,0.75)", lineHeight: 1.5, margin: `0 0 ${u(20)}` }, children: subheading }),
233
+ ctaHref && ctaLabel && /* @__PURE__ */ 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 })
204
234
  ] })
205
235
  ] });
206
236
  }
207
- function CtaStrip({ headline, primary, secondary, align = "center" }) {
208
- return /* @__PURE__ */ jsxs("div", { style: { border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "32px", textAlign: align, background: "var(--sp-bg)" }, children: [
209
- /* @__PURE__ */ jsx("h3", { style: { fontSize: "24px", fontWeight: 700, color: "var(--sp-text)", margin: "0 0 24px" }, children: headline }),
210
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: flexItems(align), gap: "16px", flexWrap: "wrap" }, children: [
211
- /* @__PURE__ */ 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 }),
212
- secondary && /* @__PURE__ */ jsxs("a", { href: secondary.href, style: { fontSize: "15px", color: "var(--sp-text-sub)", textDecoration: "none" }, children: [
237
+ function CtaStrip({ headline, primary, secondary, align = "center", unit = "px" }) {
238
+ const u = scaler(unit);
239
+ return /* @__PURE__ */ jsxs("div", { style: { border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(32), textAlign: align, background: "var(--sp-bg)" }, children: [
240
+ /* @__PURE__ */ jsx("h3", { style: { fontSize: u(24), fontWeight: 700, color: "var(--sp-text)", margin: `0 0 ${u(24)}` }, children: headline }),
241
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: flexItems(align), gap: u(16), flexWrap: "wrap" }, children: [
242
+ /* @__PURE__ */ 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 }),
243
+ secondary && /* @__PURE__ */ jsxs("a", { href: secondary.href, style: { fontSize: u(15), color: "var(--sp-text-sub)", textDecoration: "none" }, children: [
213
244
  secondary.label,
214
245
  " \u2192"
215
246
  ] })
216
247
  ] })
217
248
  ] });
218
249
  }
219
- function renderSingle(item, brand, align) {
250
+ function renderSingle(item, brand, align, unit = "px") {
220
251
  var _a, _b;
221
252
  const s = (_a = item.slots) != null ? _a : {};
222
253
  switch (item.component) {
223
254
  case "AnnouncementBar":
224
- return /* @__PURE__ */ jsx(AnnouncementBar, { text: s.text, link: s.link });
255
+ return /* @__PURE__ */ jsx(AnnouncementBar, { text: s.text, link: s.link, unit });
225
256
  case "HeroStatement":
226
- return /* @__PURE__ */ jsx(HeroStatement, { headline: s.headline, subheading: s.subheading, align });
257
+ return /* @__PURE__ */ jsx(HeroStatement, { headline: s.headline, subheading: s.subheading, align, unit });
227
258
  // A full-width card has nothing beside it, so there is nothing for a clamp to protect.
228
259
  case "AtomCard":
229
- return /* @__PURE__ */ 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" });
260
+ return /* @__PURE__ */ 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 });
230
261
  case "StatGrid":
231
- return /* @__PURE__ */ jsx(StatGrid, { stats: s.stats, caption: s.caption });
262
+ return /* @__PURE__ */ jsx(StatGrid, { stats: s.stats, caption: s.caption, unit });
232
263
  case "CodeBlock":
233
- return /* @__PURE__ */ jsx(CodeBlock, { code: s.code, lang: s.lang, caption: s.caption });
264
+ return /* @__PURE__ */ jsx(CodeBlock, { code: s.code, lang: s.lang, caption: s.caption, unit });
234
265
  case "ComparisonTable":
235
- return /* @__PURE__ */ jsx(ComparisonTable, { brand: (_b = s.brand) != null ? _b : brand, competitor: s.competitor, rows: s.rows });
266
+ return /* @__PURE__ */ jsx(ComparisonTable, { brand: (_b = s.brand) != null ? _b : brand, competitor: s.competitor, rows: s.rows, unit });
236
267
  case "FeatureList":
237
- return /* @__PURE__ */ jsx(FeatureList, { items: s.items });
268
+ return /* @__PURE__ */ jsx(FeatureList, { items: s.items, unit });
238
269
  case "TestimonialCard":
239
- return /* @__PURE__ */ jsx(TestimonialCard, { quote: s.quote, name: s.name, role: s.role, company: s.company });
270
+ return /* @__PURE__ */ jsx(TestimonialCard, { quote: s.quote, name: s.name, role: s.role, company: s.company, unit });
240
271
  case "ImageCtaHero":
241
- return /* @__PURE__ */ jsx(ImageCtaHero, { src: s.src, alt: s.alt, headline: s.headline, subheading: s.subheading, ctaLabel: s.ctaLabel, ctaHref: s.ctaHref, align });
272
+ return /* @__PURE__ */ jsx(ImageCtaHero, { src: s.src, alt: s.alt, headline: s.headline, subheading: s.subheading, ctaLabel: s.ctaLabel, ctaHref: s.ctaHref, align, unit });
242
273
  case "CtaStrip":
243
- return /* @__PURE__ */ jsx(CtaStrip, { headline: s.headline, primary: s.primary, secondary: s.secondary, align });
274
+ return /* @__PURE__ */ jsx(CtaStrip, { headline: s.headline, primary: s.primary, secondary: s.secondary, align, unit });
244
275
  // An unrecognised component name used to render nothing at all. A component needs a
245
- // renderer in three places plus the WordPress plugin, so missing one made its content
276
+ // renderer here plus spectare.js plus the WordPress plugin, so missing one made its content
246
277
  // silently absent on that surface only: no error, no warning, just a shorter page that
247
278
  // looks deliberate. That is the failure mode to remove before the registry grows.
248
279
  //
@@ -253,7 +284,7 @@ function renderSingle(item, brand, align) {
253
284
  default: {
254
285
  console.warn(`[spectare] ComponentRenderer: no renderer for "${item.component}", falling back to AtomCard`);
255
286
  if (!s.title && !s.content) return null;
256
- return /* @__PURE__ */ jsx(AtomCard, { title: s.title, content: s.content, stats: s.stats, ctaText: s.ctaText, ctaUrl: s.ctaUrl, full: true });
287
+ return /* @__PURE__ */ jsx(AtomCard, { title: s.title, content: s.content, stats: s.stats, ctaText: s.ctaText, ctaUrl: s.ctaUrl, full: true, unit });
257
288
  }
258
289
  }
259
290
  }
@@ -261,13 +292,19 @@ function resolvedSize(item) {
261
292
  if (item.size) return item.size;
262
293
  return HALF_COMPONENTS.has(item.component) ? "half" : "full";
263
294
  }
295
+ function pairable(a, b) {
296
+ const catOf = (x) => COMPONENT_CATEGORIES[x.component];
297
+ const ca = catOf(a);
298
+ const cb = catOf(b);
299
+ return ca !== void 0 && ca === cb;
300
+ }
264
301
  function buildLayout(assembly) {
265
302
  const groups = [];
266
303
  let i = 0;
267
304
  while (i < assembly.length) {
268
305
  const cur = assembly[i];
269
306
  const next = assembly[i + 1];
270
- if (resolvedSize(cur) === "half" && next && resolvedSize(next) === "half") {
307
+ if (resolvedSize(cur) === "half" && next && resolvedSize(next) === "half" && pairable(cur, next)) {
271
308
  groups.push({ type: "pair", items: [cur, next] });
272
309
  i += 2;
273
310
  } else if (resolvedSize(cur) === "half") {
@@ -281,42 +318,46 @@ function buildLayout(assembly) {
281
318
  return groups;
282
319
  }
283
320
  function XrayBadge({ name, size }) {
284
- return /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: "8px", left: "8px", zIndex: 10, display: "flex", alignItems: "center", gap: "6px", pointerEvents: "none", userSelect: "none" }, children: [
285
- /* @__PURE__ */ 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 }),
286
- /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", fontFamily: "monospace", color: "#71717a", lineHeight: 1 }, children: size })
321
+ return /* @__PURE__ */ 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: [
322
+ /* @__PURE__ */ 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 }),
323
+ /* @__PURE__ */ jsx("span", { style: { fontSize: PX(10), fontFamily: "monospace", color: "#71717a", lineHeight: 1 }, children: size })
287
324
  ] });
288
325
  }
289
- function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent }) {
326
+ function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent, unit = "px", renderOverride, renderItem, rootProps }) {
327
+ const u = scaler(unit);
290
328
  const filtered = zone ? filterAssemblyByZone(assembly, zone) : assembly;
291
329
  const layout = buildLayout(filtered);
292
- return /* @__PURE__ */ jsxs("div", { className: SP_ROOT, style: { display: "flex", flexDirection: "column", gap: "20px", fontSize: "16px" }, children: [
293
- /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: buildTokenCss({ accent }) } }),
330
+ const { className: extraClass, style: extraStyle, ...restRoot } = rootProps != null ? rootProps : {};
331
+ const renderOne = (item) => {
332
+ const override = renderOverride == null ? void 0 : renderOverride(item);
333
+ const node = override === void 0 ? renderSingle(item, brand, align, unit) : override;
334
+ return renderItem ? renderItem(item, node) : node;
335
+ };
336
+ return /* @__PURE__ */ jsxs("div", { className: extraClass ? `${SP_ROOT} ${extraClass}` : SP_ROOT, ...restRoot, style: { ...extraStyle, display: "flex", flexDirection: "column", gap: u(20), ...unit === "px" ? { fontSize: "16px" } : {} }, children: [
337
+ /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: buildTokenCss({ accent, unit }) } }),
294
338
  layout.map((group, i) => {
295
- if (group.type === "full") {
296
- return /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
297
- xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.item.component, size: "full" }),
298
- renderSingle(group.item, brand, align)
299
- ] }, i);
300
- }
301
339
  if (group.type === "pair") {
302
340
  return /* @__PURE__ */ jsxs("div", { className: "sp-pair", children: [
303
341
  /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
304
342
  xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.items[0].component, size: "half" }),
305
- renderSingle(group.items[0], brand, align)
343
+ renderOne(group.items[0])
306
344
  ] }),
307
345
  /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
308
346
  xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.items[1].component, size: "half" }),
309
- renderSingle(group.items[1], brand, align)
347
+ renderOne(group.items[1])
310
348
  ] })
311
349
  ] }, i);
312
350
  }
313
351
  return /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
314
- xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.item.component, size: "full" }),
315
- renderSingle(group.item, brand, align)
352
+ xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.item.component, size: group.type === "half-solo" ? "half" : "full" }),
353
+ renderOne(group.item)
316
354
  ] }, i);
317
355
  })
318
356
  ] });
319
357
  }
358
+
359
+ // src/PersonalisedSection.tsx
360
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
320
361
  var VARIANT_KEY = (orgSlug) => `_spectare_variant_${orgSlug}`;
321
362
  function readVariantId(orgSlug) {
322
363
  try {
@@ -366,11 +407,11 @@ function readVisitPath(orgSlug) {
366
407
  }
367
408
  }
368
409
  function Shimmer() {
369
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
370
- /* @__PURE__ */ 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" } }),
371
- /* @__PURE__ */ 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" } }),
372
- /* @__PURE__ */ 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" } }),
373
- /* @__PURE__ */ 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" } })
410
+ return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
411
+ /* @__PURE__ */ jsx2("div", { style: { height: "20px", background: "rgba(39,39,42,0.6)", borderRadius: "8px", width: "75%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
412
+ /* @__PURE__ */ jsx2("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "100%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
413
+ /* @__PURE__ */ jsx2("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "83%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
414
+ /* @__PURE__ */ jsx2("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "67%", animation: "sp-pulse 1.5s ease-in-out infinite" } })
374
415
  ] });
375
416
  }
376
417
  function PersonalisedSection({
@@ -625,23 +666,38 @@ function PersonalisedSection({
625
666
  }, [assembly, orgSlug, baseUrl]);
626
667
  if (!loading && assembly.length === 0) return null;
627
668
  const debugStyle = debugMode ? { outline: "2px solid rgba(96,165,250,0.5)", borderRadius: "0.5rem", position: "relative", padding: "0.5rem", ...style } : style;
628
- return /* @__PURE__ */ jsxs(Fragment, { children: [
629
- /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: "@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}" } }),
630
- /* @__PURE__ */ jsxs("div", { className, style: debugStyle, children: [
631
- debugMode && /* @__PURE__ */ 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: [
669
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
670
+ /* @__PURE__ */ jsx2("style", { dangerouslySetInnerHTML: { __html: "@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}" } }),
671
+ /* @__PURE__ */ jsxs2("div", { className, style: debugStyle, children: [
672
+ debugMode && /* @__PURE__ */ jsxs2("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: [
632
673
  "Personalised by Spectare",
633
- debugIntent && /* @__PURE__ */ jsxs("span", { style: { opacity: 0.75 }, children: [
674
+ debugIntent && /* @__PURE__ */ jsxs2("span", { style: { opacity: 0.75 }, children: [
634
675
  " ",
635
676
  debugIntent.audience,
636
677
  "/",
637
678
  debugIntent.stage
638
679
  ] })
639
680
  ] }),
640
- loading && assembly.length === 0 ? /* @__PURE__ */ jsx(Shimmer, {}) : /* @__PURE__ */ jsx(ComponentRenderer, { assembly: zone ? filterAssemblyByZone(assembly, zone) : assembly, brand: brand != null ? brand : orgName, align, accent })
681
+ loading && assembly.length === 0 ? /* @__PURE__ */ jsx2(Shimmer, {}) : /* @__PURE__ */ jsx2(ComponentRenderer, { assembly: zone ? filterAssemblyByZone(assembly, zone) : assembly, brand: brand != null ? brand : orgName, align, accent })
641
682
  ] })
642
683
  ] });
643
684
  }
644
-
645
- export { AnnouncementBar, AtomCard, CodeBlock, ComparisonTable, ComponentRenderer, CtaStrip, DEFAULT_ACCENT, FeatureList, HeroStatement, ImageCtaHero, PersonalisedSection, SP_ROOT, StatGrid, TestimonialCard, buildTokenCss, filterAssemblyByZone };
646
- //# sourceMappingURL=index.js.map
685
+ export {
686
+ AnnouncementBar,
687
+ AtomCard,
688
+ CodeBlock,
689
+ ComparisonTable,
690
+ ComponentRenderer,
691
+ CtaStrip,
692
+ DEFAULT_ACCENT,
693
+ FeatureList,
694
+ HeroStatement,
695
+ ImageCtaHero,
696
+ PersonalisedSection,
697
+ SP_ROOT,
698
+ StatGrid,
699
+ TestimonialCard,
700
+ buildTokenCss,
701
+ filterAssemblyByZone
702
+ };
647
703
  //# sourceMappingURL=index.js.map