@spectare-personalisation/react 0.6.0 → 0.7.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 +24 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +24 -25
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +2 -2
- package/dist/tokens.css.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -128,8 +128,11 @@ function palette(accent, theme) {
|
|
|
128
128
|
"--sp-surface": "#09090b",
|
|
129
129
|
"--sp-border": "#27272a",
|
|
130
130
|
"--sp-text": "#f4f4f5",
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
// Body prose colour. Was #d4d4d8, judged too grey against near-black at reading
|
|
132
|
+
// sizes; one step brighter keeps the hierarchy below --sp-text while reading as
|
|
133
|
+
// text rather than chrome.
|
|
134
|
+
"--sp-text-sub": "#e4e4e7",
|
|
135
|
+
"--sp-text-strong": "#ececee",
|
|
133
136
|
"--sp-text-muted": "#82828b",
|
|
134
137
|
"--sp-text-dim": "#6b6b74",
|
|
135
138
|
"--sp-text-body": "#a1a1aa",
|
|
@@ -219,27 +222,23 @@ function AtomCard({ title, content, summary, layout, stats = [], ctaText, ctaUrl
|
|
|
219
222
|
if (variant === "card") {
|
|
220
223
|
const face = (summary == null ? void 0 : summary.trim()) || (content ? `${content.replace(/\s+/g, " ").split(/(?<=[.!?])\s/)[0]}` : "");
|
|
221
224
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(20) }, children: [
|
|
222
|
-
title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(
|
|
223
|
-
face && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(
|
|
225
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(18), fontWeight: 600, color: "var(--sp-text)", margin: 0, lineHeight: 1.35 }, children: title }),
|
|
226
|
+
face && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, margin: `${u(8)} 0 0` }, children: face }),
|
|
224
227
|
content && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { style: { marginTop: u(10) }, children: [
|
|
225
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { style: { cursor: "pointer", fontSize: u(
|
|
226
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sp-prose", style: { fontSize: u(
|
|
227
|
-
] }),
|
|
228
|
-
ctaText && ctaUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: ctaUrl, style: { display: "inline-flex", alignItems: "center", gap: u(4), marginTop: u(10), fontSize: u(13), fontWeight: 600, color: "var(--sp-accent)", textDecoration: "none" }, children: [
|
|
229
|
-
ctaText,
|
|
230
|
-
" \u2192"
|
|
228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { style: { cursor: "pointer", fontSize: u(14), fontWeight: 600, color: "var(--sp-accent)", listStyle: "none" }, children: "Read more" }),
|
|
229
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sp-prose", style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, marginTop: u(10) }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } })
|
|
231
230
|
] })
|
|
232
231
|
] });
|
|
233
232
|
}
|
|
234
233
|
const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;
|
|
235
234
|
const element = (name) => {
|
|
236
|
-
if (name === "title") return title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(
|
|
237
|
-
if (name === "content") return content ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sp-prose", style: { fontSize: u(
|
|
238
|
-
if (name === "stats") return stats.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: u(20), margin:
|
|
235
|
+
if (name === "title") return title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(18), fontWeight: 600, color: "var(--sp-text)", margin: `0 0 ${u(12)}` }, children: title }, "title") : null;
|
|
236
|
+
if (name === "content") return content ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sp-prose", style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, ...full ? {} : clampStyle }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } }, "content") : null;
|
|
237
|
+
if (name === "stats") return stats.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: u(20), margin: `${u(18)} 0 ${u(12)}`, padding: `0 0 ${u(14)}`, 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: [
|
|
239
238
|
/* @__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 }),
|
|
240
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(
|
|
239
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(12), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: s.label })
|
|
241
240
|
] }, i)) }, "stats") : null;
|
|
242
|
-
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(
|
|
241
|
+
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(14), fontWeight: 600, color: "var(--sp-accent)", textDecoration: "none" }, children: [
|
|
243
242
|
ctaText,
|
|
244
243
|
" \u2192"
|
|
245
244
|
] }, "cta") : null;
|
|
@@ -252,10 +251,10 @@ function StatGrid({ stats = [], caption, unit = "px" }) {
|
|
|
252
251
|
const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;
|
|
253
252
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
254
253
|
/* @__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: [
|
|
255
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(
|
|
254
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(12), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em", margin: `0 0 ${u(12)}`, lineHeight: 1.3 }, children: label }),
|
|
256
255
|
/* @__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 })
|
|
257
256
|
] }, label)) }),
|
|
258
|
-
caption && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(
|
|
257
|
+
caption && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", margin: `${u(12)} 0 0` }, children: caption })
|
|
259
258
|
] });
|
|
260
259
|
}
|
|
261
260
|
function CodeBlock({ code, lang = "typescript", caption, unit = "px" }) {
|
|
@@ -273,14 +272,14 @@ function ComparisonTable({ brand = "Us", competitor, rows = [], unit = "px" }) {
|
|
|
273
272
|
const cell = { textAlign: "left", padding: `${u(12)} ${u(16)}` };
|
|
274
273
|
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: [
|
|
275
274
|
/* @__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: [
|
|
276
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(
|
|
277
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, fontWeight: 600, color: "var(--sp-accent)", fontSize: u(
|
|
278
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(
|
|
275
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(13), width: "33%" } }),
|
|
276
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, fontWeight: 600, color: "var(--sp-accent)", fontSize: u(13) }, children: brand }),
|
|
277
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(13) }, children: competitor })
|
|
279
278
|
] }) }),
|
|
280
279
|
/* @__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: [
|
|
281
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "row", style: { ...cell, fontSize: u(
|
|
282
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(
|
|
283
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "row", style: { ...cell, fontSize: u(14), color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
|
|
281
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(14), color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
|
|
282
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(14), color: "var(--sp-text-muted)" }, children: them })
|
|
284
283
|
] }, label)) })
|
|
285
284
|
] }) }) });
|
|
286
285
|
}
|
|
@@ -290,7 +289,7 @@ function FeatureList({ items = [], unit = "px" }) {
|
|
|
290
289
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: u(15), marginTop: u(2) }, children: "\u2713" }),
|
|
291
290
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
292
291
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(15), fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
|
|
293
|
-
sub && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(
|
|
292
|
+
sub && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", lineHeight: 1.5, margin: `${u(4)} 0 0` }, children: sub })
|
|
294
293
|
] })
|
|
295
294
|
] }, text)) }) });
|
|
296
295
|
}
|
|
@@ -304,7 +303,7 @@ function TestimonialCard({ quote, name, role, company, unit = "px" }) {
|
|
|
304
303
|
] }),
|
|
305
304
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: u(16) }, children: [
|
|
306
305
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(14), fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
|
|
307
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { fontSize: u(
|
|
306
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", margin: `${u(2)} 0 0` }, children: [
|
|
308
307
|
role,
|
|
309
308
|
company ? `, ${company}` : ""
|
|
310
309
|
] })
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/PersonalisedSection.tsx","../src/ComponentRenderer.tsx","../src/types.ts","../src/tokens.ts"],"sourcesContent":["export { PersonalisedSection } from './PersonalisedSection';\nexport { ComponentRenderer } from './ComponentRenderer';\nexport { filterAssemblyByZone } from './types';\n\n// Design tokens. Exported so a host composing the individual components below can emit the same\n// scoped token set the renderer does, and so the Spectare app's server renderer shares one\n// definition with this package rather than mirroring it.\nexport { buildTokenCss, DEFAULT_ACCENT, SP_ROOT } from './tokens';\nexport type { PersonalisedSectionProps } from './PersonalisedSection';\nexport type { ComponentRendererProps } from './ComponentRenderer';\nexport type { ComponentAssembly, ComponentName, AssemblyZone } from './types';\n\n// The nine assembly components, exported individually so a host can compose its own layout\n// rather than handing ComponentRenderer a whole assembly. ComponentRenderer remains the normal\n// path; these are for custom layouts, and for design tooling that needs to place one at a time.\nexport {\n AnnouncementBar,\n HeroStatement,\n AtomCard,\n StatGrid,\n CodeBlock,\n ComparisonTable,\n FeatureList,\n TestimonialCard,\n ImageCtaHero,\n CtaStrip,\n} from './ComponentRenderer';\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { ComponentRenderer } from './ComponentRenderer';\nimport { filterAssemblyByZone } from './types';\nimport type { ComponentAssembly, AssemblyZone } from './types';\n\ntype ConversionCheckResult =\n | { matched: false }\n | { matched: true; goalName: string | null; goalType: string; valueSelector: string | null; currencySelector: string | null; defaultCurrency: string };\n\n// The arrangement this visitor saw, kept per-org in sessionStorage so a conversion fired on a\n// later page can attribute itself to it. Shares its key with spectare.js and the SSR\n// VariantTracker, so whichever surface rendered last wins, which is the arrangement the\n// visitor actually saw.\nconst VARIANT_KEY = (orgSlug: string) => `_spectare_variant_${orgSlug}`;\n\nfunction readVariantId(orgSlug: string): string | null {\n try { return sessionStorage.getItem(VARIANT_KEY(orgSlug)); } catch { return null; }\n}\n\nfunction writeVariantId(orgSlug: string, variantId: string): void {\n try { sessionStorage.setItem(VARIANT_KEY(orgSlug), variantId); } catch { /* private browsing */ }\n}\n\n\nfunction buildSummary(pageHint: string, orgSlug: string): string {\n const parts: string[] = [pageHint];\n const referrer = document.referrer;\n if (referrer) parts.push(`Arrived from: ${referrer}`);\n const p = new URLSearchParams(window.location.search);\n const source = p.get('utm_source');\n const medium = p.get('utm_medium');\n const campaign = p.get('utm_campaign');\n const term = p.get('utm_term');\n if (source) parts.push(`Source: ${source}`);\n if (medium) parts.push(`Medium: ${medium}`);\n if (campaign) parts.push(`Campaign: ${campaign}`);\n if (term) parts.push(`Search term: ${term}`);\n try {\n const history = localStorage.getItem(`_spectare_visits_${orgSlug}`);\n if (history) parts.push(`Previously visited: ${history}`);\n } catch { /* private browsing */ }\n return parts.filter(Boolean).join('. ');\n}\n\n// Reconstructs the visitor's page journey from spectare.js visit history.\nfunction readVisitPath(orgSlug: string): string[] {\n try {\n const raw = JSON.parse(localStorage.getItem(`_spectare_visits_${orgSlug}`) || '[]') as Array<{ path?: string }>;\n const path: string[] = [];\n for (const v of raw) {\n if (typeof v?.path === 'string' && (!path.length || path[path.length - 1] !== v.path)) path.push(v.path);\n }\n const cur = window.location.pathname;\n if (!path.length || path[path.length - 1] !== cur) path.push(cur);\n return path;\n } catch { return []; }\n}\n\nfunction Shimmer() {\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <div style={{ height: '20px', background: 'rgba(39,39,42,0.6)', borderRadius: '8px', width: '75%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '100%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '83%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '67%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n </div>\n );\n}\n\nexport interface PersonalisedSectionProps {\n orgSlug: string;\n /** Base URL of your Spectare instance. Defaults to 'https://spectare.ai'. */\n baseUrl?: string;\n /** Your brand name, used in ComparisonTable column header. */\n brand?: string;\n pageHint?: string;\n className?: string;\n style?: React.CSSProperties;\n initialAssembly?: ComponentAssembly;\n initialIntent?: { audience: string; stage: string };\n /**\n * Seed conversion attribution with a server-rendered arrangement: pass the variantId that\n * /api/assemble/ssr returned alongside initialAssembly. Without it, a visit where the client\n * classification matches the server's (so no client render happens) has no variant for a\n * later conversion to credit.\n */\n initialVariantId?: string;\n /**\n * Explicit visitor-typed context (e.g. a demo input box). Bypasses the session token cache\n * and re-qualifies immediately with the direct flag, which the server cost-caps (cheaper\n * model on a cache miss) and never writes to the shared cache.\n */\n directSummary?: string;\n /** Render only components assigned to this zone. */\n zone?: AssemblyZone;\n /** Alignment for statement-style components, to match the host page. */\n align?: 'left' | 'center' | 'right';\n /**\n * Brand accent. Passed through to ComponentRenderer, which emits it into the scoped\n * token set. Defaults to #60a5fa (dark) or #2563eb (light).\n */\n accent?: string;\n /** dark (default) or light, matching your page's ground. See ComponentRenderer. */\n theme?: 'dark' | 'light';\n}\n\nexport function PersonalisedSection({\n orgSlug,\n baseUrl = 'https://spectare.ai',\n brand,\n pageHint,\n className,\n style,\n initialAssembly,\n initialIntent,\n initialVariantId,\n directSummary,\n zone,\n align,\n accent,\n theme,\n}: PersonalisedSectionProps) {\n const [assembly, setAssembly] = useState<ComponentAssembly>(initialAssembly ?? []);\n const [loading, setLoading] = useState(!initialAssembly);\n const [orgName, setOrgName] = useState<string | undefined>(undefined);\n const [debugMode, setDebugMode] = useState(false);\n const [debugIntent, setDebugIntent] = useState<{ audience: string; stage: string } | null>(null);\n const tokenRef = useRef<string | null>(null);\n const conversionFiredRef = useRef(false);\n\n useEffect(() => {\n setDebugMode(new URLSearchParams(window.location.search).has('spectare_debug'));\n if (initialIntent) setDebugIntent(initialIntent);\n }, [initialIntent]);\n\n // Seed sessionStorage with the server-rendered variantId so conversions attribute correctly\n // even when the client assembly matches the SSR one and no client fetch replaces it.\n useEffect(() => {\n if (initialVariantId) writeVariantId(orgSlug, initialVariantId);\n }, [orgSlug, initialVariantId]);\n\n useEffect(() => {\n let cancelled = false;\n\n async function load() {\n try {\n let token: string | null = null;\n\n if (directSummary) {\n // Explicit visitor input: skip the token cache, re-qualify immediately with direct.\n setLoading(true);\n setAssembly([]);\n const res = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary: directSummary, direct: true }),\n });\n if (!res.ok || cancelled) { setLoading(false); return; }\n const data = await res.json();\n token = (data.token as string | undefined) ?? null;\n } else {\n // Key includes UTM params so a visitor arriving via a campaign link always\n // re-qualifies rather than reusing a token from a prior session context.\n const p = new URLSearchParams(window.location.search);\n const utmSuffix = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term']\n .map(k => p.get(k) ?? '').filter(Boolean).join('_');\n const tokenKey = `_spectare_token_${orgSlug}${utmSuffix ? '_' + utmSuffix : ''}`;\n token = sessionStorage.getItem(tokenKey);\n\n if (!token) {\n const summary = buildSummary(pageHint ?? `Visiting ${document.title}`, orgSlug);\n const res = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary }),\n });\n if (!res.ok || cancelled) { setLoading(false); return; }\n const data = await res.json();\n token = data.token as string | undefined ?? null;\n if (token) sessionStorage.setItem(tokenKey, token);\n if (data.orgName) setOrgName(data.orgName as string);\n }\n }\n\n if (!token || cancelled) { setLoading(false); return; }\n\n tokenRef.current = token;\n let res = await fetch(`${baseUrl}/api/assemble/components`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n // Direct: flag it so the server cost-caps the build, and omit the seen-variant\n // exclusion so it can read the shared cache instead of forcing a fresh build.\n body: JSON.stringify(\n directSummary\n ? { token, orgSlug, direct: true }\n : { token, orgSlug, excludeVariantId: readVariantId(orgSlug) },\n ),\n });\n\n if (res.status === 401 && !cancelled && !directSummary) {\n // Cached token expired: clear it, re-qualify, and retry once.\n const p = new URLSearchParams(window.location.search);\n const utmSuffix = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term']\n .map(k => p.get(k) ?? '').filter(Boolean).join('_');\n const tokenKey = `_spectare_token_${orgSlug}${utmSuffix ? '_' + utmSuffix : ''}`;\n sessionStorage.removeItem(tokenKey);\n const summary = buildSummary(pageHint ?? `Visiting ${document.title}`, orgSlug);\n const qRes = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary }),\n });\n if (!qRes.ok || cancelled) { setLoading(false); return; }\n const qData = await qRes.json();\n token = qData.token as string | undefined ?? null;\n if (token) {\n sessionStorage.setItem(tokenKey, token);\n tokenRef.current = token;\n }\n if (!token || cancelled) { setLoading(false); return; }\n res = await fetch(`${baseUrl}/api/assemble/components`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, orgSlug, excludeVariantId: readVariantId(orgSlug) }),\n });\n }\n\n if (!res.ok || cancelled) { setLoading(false); return; }\n\n const contentType = res.headers.get('content-type') ?? '';\n\n if (contentType.includes('text/event-stream')) {\n // Cold path: stream components as Claude generates them.\n // Render progressively — shimmer shows until the first component arrives.\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n let loadingCleared = false;\n try {\n while (!cancelled) {\n const { done, value } = await reader.read();\n if (done || cancelled) break;\n buf += decoder.decode(value, { stream: true });\n const lines = buf.split('\\n');\n buf = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue;\n const payload = line.slice(6).trim();\n if (payload === '[DONE]') break;\n try {\n const parsed = JSON.parse(payload) as Record<string, unknown>;\n // Control frames: {_variant} carries attribution, {_error} means the stream\n // died server-side. Neither is a component; pushing them into the assembly\n // recorded a phantom entry the renderer silently skipped.\n if (parsed._variant && typeof parsed._variant === 'string') {\n writeVariantId(orgSlug, parsed._variant);\n continue;\n }\n if (parsed._error) {\n if (!loadingCleared) { setLoading(false); loadingCleared = true; }\n continue;\n }\n if (!parsed.component) continue;\n const comp = parsed as unknown as ComponentAssembly[0];\n if (!loadingCleared) { setLoading(false); loadingCleared = true; }\n setAssembly(prev => [...prev, comp]);\n } catch { /* malformed event — skip */ }\n }\n }\n } finally {\n reader.cancel().catch(() => {});\n }\n } else {\n // Warm path: cache hit returns full JSON immediately.\n const data = await res.json() as {\n assembly?: ComponentAssembly;\n intent?: { userContext?: { audience?: string; stage?: string } };\n variantId?: string;\n };\n if (data.variantId) writeVariantId(orgSlug, data.variantId);\n\n if (cancelled) return;\n\n const clientAudience = data.intent?.userContext?.audience;\n const clientStage = data.intent?.userContext?.stage;\n const ssrMatches =\n initialIntent &&\n clientAudience === initialIntent.audience &&\n clientStage === initialIntent.stage;\n\n if (clientAudience && clientStage) {\n setDebugIntent({ audience: clientAudience, stage: clientStage });\n }\n\n if (!ssrMatches && Array.isArray(data.assembly) && data.assembly.length > 0) {\n setAssembly(data.assembly as ComponentAssembly);\n }\n }\n } catch {\n // fail silently\n } finally {\n if (!cancelled) setLoading(false);\n }\n }\n\n load();\n return () => { cancelled = true; };\n }, [orgSlug, baseUrl, pageHint, initialAssembly, initialIntent, directSummary]);\n\n useEffect(() => {\n if (!assembly.length || conversionFiredRef.current) return;\n const token = tokenRef.current;\n if (!token) return;\n const url = window.location.href;\n fetch(`${baseUrl}/api/conversion-check`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ orgSlug, url }),\n }).then(r => r.json() as Promise<ConversionCheckResult>).then(data => {\n if (!data.matched) return;\n conversionFiredRef.current = true;\n let goalValue: number | null = null;\n let goalCurrency: string | null = data.defaultCurrency;\n if (data.valueSelector) {\n try {\n const el = document.querySelector(data.valueSelector);\n if (el) {\n const num = parseFloat((el.textContent ?? '').trim().replace(/[^0-9.]/g, ''));\n if (!isNaN(num)) goalValue = num;\n }\n } catch { /* skip */ }\n }\n if (data.currencySelector) {\n try {\n const el = document.querySelector(data.currencySelector);\n if (el) goalCurrency = (el.textContent ?? '').trim() || goalCurrency;\n } catch { /* skip */ }\n }\n const atomsShown = [...new Set(assembly.flatMap(i => i.sourceAtomIds ?? []))];\n const visitPath = readVisitPath(orgSlug);\n fetch(`${baseUrl}/api/conversion`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n token,\n orgSlug,\n url,\n variantId: readVariantId(orgSlug),\n ...(atomsShown.length ? { atomsShown } : {}),\n ...(visitPath.length > 1 ? { visitPath } : {}),\n ...(data.goalName ? { goalName: data.goalName } : {}),\n ...(goalValue !== null ? { goalValue, goalCurrency } : {}),\n }),\n }).catch(() => {});\n }).catch(() => {});\n }, [assembly, orgSlug, baseUrl]);\n\n if (!loading && assembly.length === 0) return null;\n\n // ?spectare_debug outlines the section and names the classified intent, so anyone checking\n // an integration can see where personalisation lands and what the visitor was read as.\n const debugStyle = debugMode\n ? { outline: '2px solid rgba(96,165,250,0.5)', borderRadius: '0.5rem', position: 'relative' as const, padding: '0.5rem', ...style }\n : style;\n\n return (\n <>\n <style dangerouslySetInnerHTML={{ __html: '@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}' }} />\n <div className={className} style={debugStyle}>\n {debugMode && (\n <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' }}>\n Personalised by Spectare\n {debugIntent && (\n <span style={{ opacity: 0.75 }}>\n {' '}{debugIntent.audience}/{debugIntent.stage}\n </span>\n )}\n </div>\n )}\n {loading && assembly.length === 0\n ? <Shimmer />\n : <ComponentRenderer assembly={zone ? filterAssemblyByZone(assembly, zone) : assembly} brand={brand ?? orgName} align={align} accent={accent} theme={theme} />}\n </div>\n </>\n );\n}\n","// Universal renderer: deliberately NO 'use client' in this source file. Nothing here uses hooks, state, or event\n// handlers, so the same file renders as a React Server Component (zero JS shipped, how the\n// Spectare app uses it via components/ServerAssemblyRenderer.tsx) and inside a client tree\n// (how PersonalisedSection uses it). Adding a hook or handler here would silently force every\n// server consumer to ship and hydrate it: keep interactivity in wrappers.\n//\n// Sizing is numeric, scaled through u(): px for embedded hosts (predictable inside arbitrary\n// pages) or rem for hosts that want to track the reader's font-size preference (the Spectare\n// site). Until 2026-08-31 the rem variant was a hand-maintained mirror of this file, and the\n// two drifted a pixel apart in six places; one number set, one scale function, no mirror.\nimport { marked } from 'marked';\nimport DOMPurify from 'isomorphic-dompurify';\nimport { filterAssemblyByZone, COMPONENT_CATEGORIES } from './types';\nimport { buildTokenCss, SP_ROOT } from './tokens';\nimport type { SpTheme } from './tokens';\nimport type { ComponentAssembly, ComponentName, AssemblyZone } from './types';\n\n// The assembly API returns atom content as raw markdown. marked emits raw HTML,\n// so the output must be sanitised before it reaches dangerouslySetInnerHTML,\n// otherwise a malicious atom can run script in the host site's visitors' browsers.\nfunction renderMarkdown(content: string): string {\n const raw = marked.parse(content ?? '', { async: false }) as string;\n return DOMPurify.sanitize(raw, { USE_PROFILES: { html: true } });\n}\n\nexport type Unit = 'px' | 'rem';\ntype U = (n: number) => string;\nconst scaler = (unit: Unit): U => (n: number) => (unit === 'rem' ? `${n / 16}rem` : `${n}px`);\nconst PX = scaler('px');\n\n// Default half-size components: used when assembly item omits size.\nconst HALF_COMPONENTS = new Set<ComponentName>(['TestimonialCard']);\n\n// ── Individual component renderers ────────────────────────────────────────────\n\n// Alignment is a host decision, not baked into a component: the host passes `align`\n// and statement-style components adopt it. flexItems maps it to a flex alignment so\n// block children (a max-width subheading, an inline CTA) align too, not just the text.\ntype Align = 'left' | 'center' | 'right';\nconst flexItems = (a: Align): 'flex-start' | 'center' | 'flex-end' =>\n a === 'center' ? 'center' : a === 'right' ? 'flex-end' : 'flex-start';\n\n/**\n * A single line above everything else. Deliberately the plainest component in the set: no\n * heading, no image, no padding to speak of. A bar that draws attention to itself competes with\n * the page it is announcing something about.\n *\n * Uses the accent rather than a red or amber alert colour. This is a fact worth knowing, not a\n * warning, and a venue putting \"members book from Thursday\" in an alarm colour reads as a problem\n * rather than an offer.\n */\nexport function AnnouncementBar({ text, link, unit = 'px' }: { text?: string; link?: { label: string; href: string }; unit?: Unit }) {\n const u = scaler(unit);\n if (!text) return null;\n return (\n <div style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center', gap: u(10),\n flexWrap: 'wrap', textAlign: 'center',\n background: 'var(--sp-accent-bg)', border: '1px solid var(--sp-accent-border)',\n borderRadius: u(8), padding: `${u(8)} ${u(16)}`, fontSize: u(14), lineHeight: 1.4,\n color: 'var(--sp-text-sub)',\n }}>\n <span>{text}</span>\n {link?.href && link?.label && (\n <a href={link.href} style={{ color: 'var(--sp-accent)', fontWeight: 600, textDecoration: 'none', whiteSpace: 'nowrap' }}>\n {link.label} →\n </a>\n )}\n </div>\n );\n}\n\nexport function HeroStatement({ headline, subheading, align = 'left', unit = 'px' }: { headline: string; subheading?: string; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: flexItems(align), textAlign: align, paddingTop: u(24), paddingBottom: u(24) }}>\n <h2 style={{ fontSize: u(32), fontWeight: 700, letterSpacing: '-0.025em', lineHeight: 1.2, color: 'var(--sp-text)', margin: `0 0 ${u(12)}` }}>\n {headline}\n </h2>\n {subheading && (\n <p style={{ fontSize: u(18), color: 'var(--sp-text-sub)', lineHeight: 1.6, maxWidth: u(672), margin: 0 }}>{subheading}</p>\n )}\n </div>\n );\n}\n\n// The atom owns title / content / stats / cta; its layout decides which appear and in\n// what order. Default order when the atom has no layout. Mirrors the atom editor.\nconst ATOM_LAYOUT_DEFAULT = ['title', 'content', 'stats', 'cta'];\n\n// Clamp atom prose unless the assembly asked for the full body. CSS rather than an expand\n// toggle, so the identical rule works here (including server-rendered with no JS), in\n// spectare.js and in the WordPress plugin.\nexport const ATOM_CLAMP_LINES = 4;\nconst clampStyle = {\n display: '-webkit-box',\n WebkitLineClamp: ATOM_CLAMP_LINES,\n WebkitBoxOrient: 'vertical' as const,\n overflow: 'hidden',\n};\n\nexport function AtomCard(\n { title, content, summary, layout, stats = [], ctaText, ctaUrl, full, variant, unit = 'px' }:\n { title?: string; content?: string; summary?: string; layout?: string[]; stats?: { value: string; label: string }[]; ctaText?: string; ctaUrl?: string; full?: boolean; variant?: string; unit?: Unit },\n) {\n const u = scaler(unit);\n\n // The card face: title, one-sentence summary, and the full body behind a native <details>\n // disclosure. <details> is the one expand that needs no JavaScript, so it works identically\n // in a server component, a client tree, and any host page; nothing is ever unreachable on a\n // site that has no per-atom pages. The Spectare app substitutes its own card face (which\n // links to the atom's page) via renderOverride, so this is the everywhere-else rendering.\n if (variant === 'card') {\n const face = summary?.trim() || (content ? `${content.replace(/\\s+/g, ' ').split(/(?<=[.!?])\\s/)[0]}` : '');\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(20) }}>\n {title && <h3 style={{ fontSize: u(16), fontWeight: 600, color: 'var(--sp-text)', margin: 0, lineHeight: 1.35 }}>{title}</h3>}\n {face && <p style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, margin: `${u(8)} 0 0` }}>{face}</p>}\n {content && (\n <details style={{ marginTop: u(10) }}>\n <summary style={{ cursor: 'pointer', fontSize: u(13), fontWeight: 600, color: 'var(--sp-accent)', listStyle: 'none' }}>Read more</summary>\n <div className=\"sp-prose\" style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, marginTop: u(10) }} dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} />\n </details>\n )}\n {ctaText && ctaUrl && (\n <a href={ctaUrl} style={{ display: 'inline-flex', alignItems: 'center', gap: u(4), marginTop: u(10), fontSize: u(13), fontWeight: 600, color: 'var(--sp-accent)', textDecoration: 'none' }}>{ctaText} →</a>\n )}\n </div>\n );\n }\n\n const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;\n const element = (name: string) => {\n if (name === 'title') return title\n ? <h3 key=\"title\" style={{ fontSize: u(16), fontWeight: 600, color: 'var(--sp-text)', margin: `0 0 ${u(12)}` }}>{title}</h3> : null;\n if (name === 'content') return content\n ? <div key=\"content\" className=\"sp-prose\" style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, ...(full ? {} : clampStyle) }} dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} /> : null;\n if (name === 'stats') return stats.length\n ? (\n <div key=\"stats\" style={{ display: 'flex', flexWrap: 'wrap', gap: u(20), margin: `0 0 ${u(12)}`, paddingBottom: u(12), borderBottom: '1px solid var(--sp-border)' }}>\n {stats.map((s, i) => (\n <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: u(2) }}>\n <span style={{ fontSize: u(22), fontWeight: 700, color: 'var(--sp-text)', lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>{s.value}</span>\n <span style={{ fontSize: u(11), color: 'var(--sp-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>{s.label}</span>\n </div>\n ))}\n </div>\n ) : null;\n if (name === 'cta') return ctaText && ctaUrl\n ? <a key=\"cta\" 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' }}>{ctaText} →</a> : null;\n return null;\n };\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(24), height: '100%' }}>\n {order.map(element)}\n </div>\n );\n}\n\nexport function StatGrid({ stats = [], caption, unit = 'px' }: { stats?: { value: string; label: string }[]; caption?: string; unit?: Unit }) {\n const u = scaler(unit);\n const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;\n return (\n <div>\n <div style={{ display: 'grid', gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: u(12) }}>\n {stats.map(({ value, label }) => (\n <div key={label} 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) }}>\n <p style={{ fontSize: u(11), color: 'var(--sp-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em', margin: `0 0 ${u(12)}`, lineHeight: 1.3 }}>{label}</p>\n <p style={{ fontSize: u(20), fontWeight: 500, color: 'var(--sp-text)', fontVariantNumeric: 'tabular-nums', lineHeight: 1, margin: 0 }}>{value}</p>\n </div>\n ))}\n </div>\n {caption && (\n <p style={{ fontSize: u(13), color: 'var(--sp-text-muted)', margin: `${u(12)} 0 0` }}>{caption}</p>\n )}\n </div>\n );\n}\n\nexport function CodeBlock({ code, lang = 'typescript', caption, unit = 'px' }: { code: string; lang?: string; caption?: string; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ borderRadius: u(12), overflow: 'hidden', border: '1px solid var(--sp-border)' }}>\n <div style={{ background: 'var(--sp-bg)', padding: `${u(10)} ${u(16)}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: '1px solid var(--sp-border)' }}>\n <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)', fontFamily: 'monospace' }}>{lang}</span>\n {caption && <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)' }}>{caption}</span>}\n </div>\n <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 }}>\n {code}\n </pre>\n </div>\n );\n}\n\nexport function ComparisonTable({ brand = 'Us', competitor, rows = [], unit = 'px' }: { brand?: string; competitor: string; rows?: { label: string; spectare: string; them: string }[]; unit?: Unit }) {\n const u = scaler(unit);\n const cell = { textAlign: 'left' as const, padding: `${u(12)} ${u(16)}` };\n return (\n <div style={{ border: '1px solid var(--sp-border)', borderRadius: u(12), overflow: 'hidden' }}>\n <div style={{ overflowX: 'auto' }}>\n <table style={{ width: '100%', fontSize: u(14), borderCollapse: 'collapse' }}>\n <thead>\n <tr style={{ borderBottom: '1px solid var(--sp-border)', background: 'var(--sp-bg)' }}>\n <th style={{ ...cell, color: 'var(--sp-text-muted)', fontWeight: 500, fontSize: u(12), width: '33%' }} />\n <th scope=\"col\" style={{ ...cell, fontWeight: 600, color: 'var(--sp-accent)', fontSize: u(12) }}>{brand}</th>\n <th scope=\"col\" style={{ ...cell, color: 'var(--sp-text-muted)', fontWeight: 500, fontSize: u(12) }}>{competitor}</th>\n </tr>\n </thead>\n <tbody>\n {rows.map(({ label, spectare, them }) => (\n <tr key={label} style={{ borderBottom: '1px solid var(--sp-border)' }}>\n <th scope=\"row\" style={{ ...cell, fontSize: u(13), color: 'var(--sp-text-muted)', fontWeight: 500 }}>{label}</th>\n <td style={{ ...cell, fontSize: u(13), color: 'var(--sp-positive)', fontWeight: 500 }}>{spectare}</td>\n <td style={{ ...cell, fontSize: u(13), color: 'var(--sp-text-muted)' }}>{them}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nexport function FeatureList({ items = [], unit = 'px' }: { items?: { text: string; sub?: string }[]; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(24) }}>\n <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: u(16) }}>\n {items.map(({ text, sub }) => (\n <li key={text} style={{ display: 'flex', gap: u(12) }}>\n <span style={{ color: 'var(--sp-accent)', flexShrink: 0, fontSize: u(15), marginTop: u(2) }}>✓</span>\n <div>\n <p style={{ fontSize: u(15), fontWeight: 500, color: 'var(--sp-text)', lineHeight: 1.4, margin: 0 }}>{text}</p>\n {sub && <p style={{ fontSize: u(13), color: 'var(--sp-text-muted)', lineHeight: 1.5, margin: `${u(4)} 0 0` }}>{sub}</p>}\n </div>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport function TestimonialCard({ quote, name, role, company, unit = 'px' }: { quote: string; name: string; role: string; company?: string; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <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%' }}>\n <p style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, flex: 1, margin: 0 }}>\n <span style={{ color: 'var(--sp-text-dim)', fontSize: u(18), lineHeight: 1, marginRight: u(4) }}>\"</span>\n {quote}\n <span style={{ color: 'var(--sp-text-dim)', fontSize: u(18), lineHeight: 1, marginLeft: u(4) }}>\"</span>\n </p>\n <div style={{ borderTop: '1px solid var(--sp-border)', paddingTop: u(16) }}>\n <p style={{ fontSize: u(14), fontWeight: 600, color: 'var(--sp-text)', margin: 0 }}>{name}</p>\n <p style={{ fontSize: u(13), color: 'var(--sp-text-muted)', margin: `${u(2)} 0 0` }}>\n {role}{company ? `, ${company}` : ''}\n </p>\n </div>\n </div>\n );\n}\n\nexport function ImageCtaHero({ src, alt = '', headline, subheading, ctaLabel, ctaHref, align = 'left', unit = 'px' }: { src?: string; alt?: string; headline?: string; subheading?: string; ctaLabel?: string; ctaHref?: string; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n if (!src) return null;\n return (\n <div style={{ borderRadius: u(12), overflow: 'hidden', position: 'relative', width: '100%', paddingBottom: '56.25%' }}>\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={src} alt={alt} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />\n <div style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.45)' }} />\n <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%)' }} />\n <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: u(28), textAlign: align }}>\n {headline && (\n <h2 style={{ fontSize: u(24), fontWeight: 700, color: '#fff', lineHeight: 1.2, margin: `0 0 ${u(8)}`, letterSpacing: '-0.02em' }}>{headline}</h2>\n )}\n {subheading && (\n <p style={{ fontSize: u(15), color: 'rgba(255,255,255,0.75)', lineHeight: 1.5, margin: `0 0 ${u(20)}` }}>{subheading}</p>\n )}\n {ctaHref && ctaLabel && (\n <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' }}>\n {ctaLabel}\n </a>\n )}\n </div>\n </div>\n );\n}\n\nexport function CtaStrip({ headline, primary, secondary, align = 'center', unit = 'px' }: { headline: string; primary: { label: string; href: string }; secondary?: { label: string; href: string }; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(32), textAlign: align, background: 'var(--sp-bg)' }}>\n <h3 style={{ fontSize: u(24), fontWeight: 700, color: 'var(--sp-text)', margin: `0 0 ${u(24)}` }}>{headline}</h3>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: flexItems(align), gap: u(16), flexWrap: 'wrap' }}>\n <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' }}>\n {primary.label}\n </a>\n {secondary && (\n <a href={secondary.href} style={{ fontSize: u(15), color: 'var(--sp-text-sub)', textDecoration: 'none' }}>\n {secondary.label} →\n </a>\n )}\n </div>\n </div>\n );\n}\n\n// ── Dispatch ──────────────────────────────────────────────────────────────────\n\nfunction renderSingle(item: ComponentAssembly[0], brand?: string, align?: Align, unit: Unit = 'px'): React.ReactNode {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const s = item.slots as Record<string, any> ?? {};\n\n switch (item.component as ComponentName) {\n case 'AnnouncementBar': return <AnnouncementBar text={s.text} link={s.link} unit={unit} />;\n case 'HeroStatement': return <HeroStatement headline={s.headline} subheading={s.subheading} align={align} unit={unit} />;\n // A full-width card has nothing beside it, so there is nothing for a clamp to protect.\n case 'AtomCard': return <AtomCard title={s.title} content={s.content} summary={s.summary} layout={s.layout} stats={s.stats} ctaText={s.ctaText} ctaUrl={s.ctaUrl} full={s.full || resolvedSize(item) === 'full'} variant={s.variant} unit={unit} />;\n case 'StatGrid': return <StatGrid stats={s.stats} caption={s.caption} unit={unit} />;\n case 'CodeBlock': return <CodeBlock code={s.code} lang={s.lang} caption={s.caption} unit={unit} />;\n case 'ComparisonTable': return <ComparisonTable brand={s.brand ?? brand} competitor={s.competitor} rows={s.rows} unit={unit} />;\n case 'FeatureList': return <FeatureList items={s.items} unit={unit} />;\n case 'TestimonialCard': return <TestimonialCard quote={s.quote} name={s.name} role={s.role} company={s.company} unit={unit} />;\n case 'ImageCtaHero': return <ImageCtaHero src={s.src} alt={s.alt} headline={s.headline} subheading={s.subheading} ctaLabel={s.ctaLabel} ctaHref={s.ctaHref} align={align} unit={unit} />;\n case 'CtaStrip': return <CtaStrip headline={s.headline} primary={s.primary} secondary={s.secondary} align={align} unit={unit} />;\n // An unrecognised component name used to render nothing at all. A component needs a\n // renderer here plus spectare.js plus the WordPress plugin, so missing one made its content\n // silently absent on that surface only: no error, no warning, just a shorter page that\n // looks deliberate. That is the failure mode to remove before the registry grows.\n //\n // Falls back to AtomCard when the slots carry something readable, since almost every\n // component is built from an atom and title/content is the shape they share. When there\n // is genuinely nothing to show it still renders nothing, because an empty card is worse\n // than a gap, but the warning fires either way.\n default: {\n console.warn(`[spectare] ComponentRenderer: no renderer for \"${item.component}\", falling back to AtomCard`);\n if (!s.title && !s.content) return null;\n return <AtomCard title={s.title} content={s.content} stats={s.stats} ctaText={s.ctaText} ctaUrl={s.ctaUrl} full unit={unit} />;\n }\n }\n}\n\n// ── Layout ────────────────────────────────────────────────────────────────────\n\nfunction resolvedSize(item: ComponentAssembly[0]): 'full' | 'half' {\n if (item.size) return item.size;\n return HALF_COMPONENTS.has(item.component as ComponentName) ? 'half' : 'full';\n}\n\ntype LayoutGroup =\n | { type: 'full'; item: ComponentAssembly[0] }\n | { type: 'pair'; items: [ComponentAssembly[0], ComponentAssembly[0]] }\n | { type: 'half-solo'; item: ComponentAssembly[0] };\n\n// Two half-width components only sit side by side well if they read at the same speed. A\n// prose block beside a scannable list forces the eye to switch modes, and the grid stretches\n// the shorter one, leaving dead space. Registry category is the available proxy for reading\n// mode, so pair within a category and give anything else its own row.\nfunction pairable(a: ComponentAssembly[0], b: ComponentAssembly[0]): boolean {\n const catOf = (x: ComponentAssembly[0]) =>\n COMPONENT_CATEGORIES[x.component as ComponentName];\n const ca = catOf(a);\n const cb = catOf(b);\n return ca !== undefined && ca === cb;\n}\n\nfunction buildLayout(assembly: ComponentAssembly): LayoutGroup[] {\n const groups: LayoutGroup[] = [];\n let i = 0;\n while (i < assembly.length) {\n const cur = assembly[i];\n const next = assembly[i + 1];\n if (resolvedSize(cur) === 'half' && next && resolvedSize(next) === 'half' && pairable(cur, next)) {\n groups.push({ type: 'pair', items: [cur, next] });\n i += 2;\n } else if (resolvedSize(cur) === 'half') {\n groups.push({ type: 'half-solo', item: cur });\n i++;\n } else {\n groups.push({ type: 'full', item: cur });\n i++;\n }\n }\n return groups;\n}\n\n// ── X-ray badge ───────────────────────────────────────────────────────────────\n\nfunction XrayBadge({ name, size }: { name: string; size: string }) {\n return (\n <div style={{ position: 'absolute', top: PX(8), left: PX(8), zIndex: 10, display: 'flex', alignItems: 'center', gap: PX(6), pointerEvents: 'none', userSelect: 'none' }}>\n <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 }}>{name}</span>\n <span style={{ fontSize: PX(10), fontFamily: 'monospace', color: '#71717a', lineHeight: 1 }}>{size}</span>\n </div>\n );\n}\n\n// ── Main export ───────────────────────────────────────────────────────────────\n\nexport interface ComponentRendererProps {\n assembly: ComponentAssembly;\n /** Your brand name, used as the left column header in ComparisonTable. Defaults to \"Us\". */\n brand?: string;\n /** Overlay a component name badge on each item. Useful for demos and debugging. */\n xray?: boolean;\n /** Render only components assigned to this zone. */\n zone?: AssemblyZone;\n /**\n * Alignment for statement-style components (HeroStatement, CtaStrip, ImageCtaHero),\n * so assembled content can match the host page. Omit to use each component's natural\n * default (HeroStatement left, CtaStrip centered).\n */\n align?: 'left' | 'center' | 'right';\n /**\n * Brand accent, as an explicit input rather than a custom property you override and hope\n * wins on tag order. Any CSS colour. `--sp-accent-bg` and `--sp-accent-border` are derived\n * from it, so one value covers all three. Defaults to #60a5fa.\n */\n accent?: string;\n /**\n * dark (default) is the package's original near-black card set. light renders white cards\n * with a dark text ramp for light host pages; without it the components paint near-white\n * text and near-black slabs onto a light ground. Both palettes hold the same contrast\n * floors (see tests/unit/token-contrast.test.ts).\n */\n theme?: SpTheme;\n /**\n * px (default) sizes components absolutely, predictable inside arbitrary host pages.\n * rem tracks the reader's font-size preference; the root then also inherits the host's\n * font size instead of pinning 16px.\n */\n unit?: Unit;\n /**\n * Substitute rendering for an item: return a node to replace the built-in renderer\n * (including null to render nothing), or undefined to keep the default. How the Spectare\n * app swaps the card-variant AtomCard for its server-rendered card face.\n */\n renderOverride?: (item: ComponentAssembly[0]) => React.ReactNode | undefined;\n /**\n * Wrap each rendered item, e.g. with source attribution or a debug badge. Receives the\n * assembly item and its rendered node; whatever it returns is placed in the layout.\n */\n renderItem?: (item: ComponentAssembly[0], rendered: React.ReactNode) => React.ReactNode;\n /** Extra attributes for the root element (e.g. a data marker a host overlay targets). */\n rootProps?: Record<string, unknown>;\n}\n\n\nexport function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent, theme, unit = 'px', renderOverride, renderItem, rootProps }: ComponentRendererProps) {\n const u = scaler(unit);\n const filtered = zone ? filterAssemblyByZone(assembly, zone) : assembly;\n const layout = buildLayout(filtered);\n\n // Merge rather than spread-clobber: a host className joins sp-root instead of replacing it\n // (every --sp-* token is scoped to .sp-root, so losing it un-themes every component), and a\n // host style merges under the layout styles rather than being silently discarded.\n const { className: extraClass, style: extraStyle, ...restRoot } = (rootProps ?? {}) as { className?: string; style?: React.CSSProperties } & Record<string, unknown>;\n\n const renderOne = (item: ComponentAssembly[0]): React.ReactNode => {\n const override = renderOverride?.(item);\n const node = override === undefined ? renderSingle(item, brand, align, unit) : override;\n return renderItem ? renderItem(item, node) : node;\n };\n\n return (\n <div className={extraClass ? `${SP_ROOT} ${extraClass}` : SP_ROOT} {...restRoot} style={{ ...extraStyle, display: 'flex', flexDirection: 'column', gap: u(20), ...(unit === 'px' ? { fontSize: '16px' } : {}) }}>\n <style dangerouslySetInnerHTML={{ __html: buildTokenCss({ accent, unit, theme }) }} />\n {layout.map((group, i) => {\n if (group.type === 'pair') {\n return (\n <div key={i} className=\"sp-pair\">\n <div style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.items[0].component} size=\"half\" />}\n {renderOne(group.items[0])}\n </div>\n <div style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.items[1].component} size=\"half\" />}\n {renderOne(group.items[1])}\n </div>\n </div>\n );\n }\n return (\n <div key={i} style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.item.component} size={group.type === 'half-solo' ? 'half' : 'full'} />}\n {renderOne(group.item)}\n </div>\n );\n })}\n </div>\n );\n}\n","export type ComponentName =\n | 'AnnouncementBar'\n | 'HeroStatement'\n | 'AtomCard'\n | 'StatGrid'\n | 'CodeBlock'\n | 'ComparisonTable'\n | 'FeatureList'\n | 'TestimonialCard'\n | 'ImageCtaHero'\n | 'CtaStrip';\n\nexport type AssemblyZone = 'announce' | 'hero' | 'body' | 'proof' | 'cta';\n\nconst COMPONENT_ZONES: Record<ComponentName, AssemblyZone> = {\n AnnouncementBar: 'announce',\n HeroStatement: 'hero',\n ImageCtaHero: 'hero',\n AtomCard: 'body',\n StatGrid: 'body',\n CodeBlock: 'body',\n ComparisonTable: 'body',\n FeatureList: 'body',\n TestimonialCard: 'proof',\n CtaStrip: 'cta',\n};\n\nexport type ComponentAssembly = Array<{\n component: ComponentName;\n slots?: Record<string, unknown>;\n size?: 'full' | 'half';\n zone?: AssemblyZone;\n // Atom IDs this component was built from; drives conversion attribution.\n sourceAtomIds?: number[];\n}>;\n\nexport function filterAssemblyByZone(assembly: ComponentAssembly, zone: AssemblyZone): ComponentAssembly {\n return assembly.filter(item => {\n const effectiveZone = item.zone ?? COMPONENT_ZONES[item.component];\n return effectiveZone === zone;\n });\n}\n\n/**\n * Reading-mode category per component: the layout's pairing key. Two half-width components\n * only sit side by side when they share a category, so a prose block never lands beside a\n * scannable list. Mirrors the `category` field in the app's lib/component-registry.ts (the\n * source of truth, which also drives the assembly prompt);\n * tests/unit/renderer-category-parity.test.ts fails when the two drift.\n */\nexport const COMPONENT_CATEGORIES: Record<ComponentName, string> = {\n AnnouncementBar: 'conversion',\n HeroStatement: 'hero',\n AtomCard: 'content',\n StatGrid: 'content',\n CodeBlock: 'technical',\n ComparisonTable: 'evaluation',\n FeatureList: 'content',\n TestimonialCard: 'social-proof',\n ImageCtaHero: 'hero',\n CtaStrip: 'conversion',\n};\n","/**\n * The one place this package's design tokens are defined.\n *\n * Two things that are easy to get wrong here:\n *\n * 1. Tokens are declared on `.sp-root`, not `:root`. Declaring them at `:root` writes into\n * the host's document, allows only one theme per page, and means a customer overriding\n * `--sp-accent` competes with us at equal specificity so tag order decides the winner.\n * Scoping also lets two differently themed sections sit on one page.\n *\n * 2. `tokens.css` must stay byte-identical to `buildTokenCss({ scope: STYLESHEET_SCOPE })`,\n * which differs from the injected CSS in its selector and in nothing else.\n * tests/unit/react-tokens.test.ts enforces both halves, because a customer who imports the\n * stylesheet and a customer who renders the component must get the same page.\n *\n * components/ServerAssemblyRenderer.tsx in the Spectare app is a deliberate mirror of the\n * values below. It is not the same file: that renderer uses rem, this one uses px.\n */\n\n/** The package default. `spectare.js` and the WordPress plugin default to #2563eb, which is\n * a live inconsistency and a brand decision rather than a technical one, so it is left alone\n * here. Pass `accent` to override on either path. */\nexport const DEFAULT_ACCENT = '#60a5fa';\n\n/** The light theme's default accent. #60a5fa reads at ~2.5:1 on white, far below the 4.5:1\n * body floor, so light gets the deeper blue the widget and plugin already default to. */\nexport const DEFAULT_ACCENT_LIGHT = '#2563eb';\n\nexport type SpTheme = 'dark' | 'light';\n\n/** Class the tokens are scoped to. Applied by ComponentRenderer to its own wrapper. */\nexport const SP_ROOT = 'sp-root';\n\n/**\n * Selector the shipped `tokens.css` declares on.\n *\n * `:where(:root)` has zero specificity, so it gives a host that imports the stylesheet and\n * composes the individual components a working set of defaults without a wrapper, while losing\n * to literally any rule the host writes, including a bare `:root` of their own. `.sp-root` then\n * wins over it wherever both apply, which is what makes a differently themed section on one page\n * work. The runtime CSS the renderer injects uses `.sp-root` alone: it applies the class itself,\n * so it has no reason to touch the host's document.\n */\nexport const STYLESHEET_SCOPE = `:where(:root),.${SP_ROOT}`;\n\n/**\n * Colour tokens, in the order they are emitted.\n *\n * `--sp-text-muted` and `--sp-text-dim` were #71717a (3.67:1) and #52525b (2.29:1) on\n * `--sp-bg`, which fail WCAG AA for body text and, in the case of dim, fail even the 3:1\n * large-text floor. They now measure 4.65:1 and 3.36:1. Every other value is unchanged.\n *\n * `--sp-cta-bg` / `--sp-cta-text` carry the values CtaStrip used to hardcode, so the dark\n * rendering is pixel-identical and a light host can correct a button that would otherwise\n * be white on white.\n */\nfunction palette(accent: string, theme: SpTheme): Record<string, string> {\n const shared = {\n '--sp-accent': accent,\n '--sp-accent-bg': `color-mix(in srgb,${accent} 10%,transparent)`,\n '--sp-accent-border': `color-mix(in srgb,${accent} 20%,transparent)`,\n };\n // The light set mirrors the dark ramp with the same contrast discipline: every text token\n // holds its floor on both --sp-bg and --sp-surface (tests/unit/token-contrast.test.ts runs\n // the identical assertions against both themes), and the ramp stays strictly ordered.\n if (theme === 'light') {\n return {\n ...shared,\n '--sp-bg': '#ffffff',\n '--sp-surface': '#f4f4f5',\n '--sp-border': '#e4e4e7',\n '--sp-text': '#18181b',\n '--sp-text-sub': '#3f3f46',\n '--sp-text-strong': '#27272a',\n '--sp-text-muted': '#6b6b74',\n '--sp-text-dim': '#82828b',\n '--sp-text-body': '#52525b',\n '--sp-positive': '#047857',\n '--sp-cta-bg': '#18181b',\n '--sp-cta-text': '#ffffff',\n '--sp-divider': 'rgba(0,0,0,0.06)',\n '--sp-code-bg': 'rgba(0,0,0,0.05)',\n '--sp-code-border': 'rgba(0,0,0,0.08)',\n '--sp-pre-bg': 'rgba(0,0,0,0.04)',\n };\n }\n return {\n ...shared,\n '--sp-bg': '#18181b',\n '--sp-surface': '#09090b',\n '--sp-border': '#27272a',\n '--sp-text': '#f4f4f5',\n '--sp-text-sub': '#d4d4d8',\n '--sp-text-strong': '#e4e4e7',\n '--sp-text-muted': '#82828b',\n '--sp-text-dim': '#6b6b74',\n '--sp-text-body': '#a1a1aa',\n '--sp-positive': '#6ee7b7',\n '--sp-cta-bg': '#fff',\n '--sp-cta-text': '#09090b',\n '--sp-divider': 'rgba(255,255,255,0.06)',\n '--sp-code-bg': 'rgba(255,255,255,0.07)',\n '--sp-code-border': 'rgba(255,255,255,0.08)',\n '--sp-pre-bg': 'rgba(0,0,0,0.4)',\n };\n}\n\n/**\n * Prose and layout rules, scoped to the same class so the package ships no global classes.\n *\n * `unit` exists because the app's server renderer sizes in rem and this package sizes in px.\n * 20px and 1.25rem are the same length at a 16px base, so this is not a design difference, but\n * the two were separate string literals and separate string literals drift.\n */\nfunction rules(unit: 'px' | 'rem'): string {\n const gap = unit === 'px' ? '20px' : '1.25rem';\n return [\n '.sp-root .sp-prose p{margin-bottom:.625rem}',\n '.sp-root .sp-prose p:last-child{margin-bottom:0}',\n '.sp-root .sp-prose ul{list-style:disc;padding-left:1.25rem;margin-bottom:.625rem}',\n '.sp-root .sp-prose ol{list-style:decimal;padding-left:1.25rem;margin-bottom:.625rem}',\n '.sp-root .sp-prose li{margin-bottom:.25rem}',\n '.sp-root .sp-prose strong{color:var(--sp-text-strong);font-weight:600}',\n '.sp-root .sp-prose h2,.sp-root .sp-prose h3{color:var(--sp-text);font-weight:600;margin:.875rem 0 .375rem;font-size:1rem}',\n '.sp-root .sp-prose code{background:var(--sp-code-bg);border:1px solid var(--sp-code-border);padding:.1rem .35rem;border-radius:.25rem;font-size:.82em;color:var(--sp-text)}',\n '.sp-root .sp-prose blockquote{border-left:3px solid var(--sp-border);padding-left:1rem;color:var(--sp-text-muted);margin:.75rem 0}',\n `.sp-root .sp-pair{display:grid;grid-template-columns:1fr 1fr;gap:${gap}}`,\n '@media(max-width:640px){.sp-root .sp-pair{grid-template-columns:1fr}}',\n ].join('');\n}\n\n/**\n * Returns the stylesheet a renderer injects.\n *\n * @param accent brand colour. Accepts anything CSS does; `--sp-accent-bg` and\n * `--sp-accent-border` are derived from it so a customer sets one value\n * rather than three. Defaults to DEFAULT_ACCENT.\n * @param unit length unit for layout rules. 'px' for this package, 'rem' for the app's\n * server renderer, which sizes in rem throughout.\n * @param scope selector the custom properties are declared on. Defaults to `.sp-root`, which is\n * what a renderer injecting this at runtime wants. `tokens.css` is generated with\n * STYLESHEET_SCOPE instead, so importing it works without a wrapper.\n */\nexport function buildTokenCss({ accent, unit = 'px', scope = `.${SP_ROOT}`, theme = 'dark' }: { accent?: string; unit?: 'px' | 'rem'; scope?: string; theme?: SpTheme } = {}): string {\n const resolved = accent ?? (theme === 'light' ? DEFAULT_ACCENT_LIGHT : DEFAULT_ACCENT);\n const decls = Object.entries(palette(resolved, theme)).map(([k, v]) => `${k}:${v}`).join(';');\n return `${scope}{${decls}}${rules(unit)}`;\n}\n"],"mappings":"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","names":["DOMPurify","import_jsx_runtime","res","_a"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/PersonalisedSection.tsx","../src/ComponentRenderer.tsx","../src/types.ts","../src/tokens.ts"],"sourcesContent":["export { PersonalisedSection } from './PersonalisedSection';\nexport { ComponentRenderer } from './ComponentRenderer';\nexport { filterAssemblyByZone } from './types';\n\n// Design tokens. Exported so a host composing the individual components below can emit the same\n// scoped token set the renderer does, and so the Spectare app's server renderer shares one\n// definition with this package rather than mirroring it.\nexport { buildTokenCss, DEFAULT_ACCENT, SP_ROOT } from './tokens';\nexport type { PersonalisedSectionProps } from './PersonalisedSection';\nexport type { ComponentRendererProps } from './ComponentRenderer';\nexport type { ComponentAssembly, ComponentName, AssemblyZone } from './types';\n\n// The nine assembly components, exported individually so a host can compose its own layout\n// rather than handing ComponentRenderer a whole assembly. ComponentRenderer remains the normal\n// path; these are for custom layouts, and for design tooling that needs to place one at a time.\nexport {\n AnnouncementBar,\n HeroStatement,\n AtomCard,\n StatGrid,\n CodeBlock,\n ComparisonTable,\n FeatureList,\n TestimonialCard,\n ImageCtaHero,\n CtaStrip,\n} from './ComponentRenderer';\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { ComponentRenderer } from './ComponentRenderer';\nimport { filterAssemblyByZone } from './types';\nimport type { ComponentAssembly, AssemblyZone } from './types';\n\ntype ConversionCheckResult =\n | { matched: false }\n | { matched: true; goalName: string | null; goalType: string; valueSelector: string | null; currencySelector: string | null; defaultCurrency: string };\n\n// The arrangement this visitor saw, kept per-org in sessionStorage so a conversion fired on a\n// later page can attribute itself to it. Shares its key with spectare.js and the SSR\n// VariantTracker, so whichever surface rendered last wins, which is the arrangement the\n// visitor actually saw.\nconst VARIANT_KEY = (orgSlug: string) => `_spectare_variant_${orgSlug}`;\n\nfunction readVariantId(orgSlug: string): string | null {\n try { return sessionStorage.getItem(VARIANT_KEY(orgSlug)); } catch { return null; }\n}\n\nfunction writeVariantId(orgSlug: string, variantId: string): void {\n try { sessionStorage.setItem(VARIANT_KEY(orgSlug), variantId); } catch { /* private browsing */ }\n}\n\n\nfunction buildSummary(pageHint: string, orgSlug: string): string {\n const parts: string[] = [pageHint];\n const referrer = document.referrer;\n if (referrer) parts.push(`Arrived from: ${referrer}`);\n const p = new URLSearchParams(window.location.search);\n const source = p.get('utm_source');\n const medium = p.get('utm_medium');\n const campaign = p.get('utm_campaign');\n const term = p.get('utm_term');\n if (source) parts.push(`Source: ${source}`);\n if (medium) parts.push(`Medium: ${medium}`);\n if (campaign) parts.push(`Campaign: ${campaign}`);\n if (term) parts.push(`Search term: ${term}`);\n try {\n const history = localStorage.getItem(`_spectare_visits_${orgSlug}`);\n if (history) parts.push(`Previously visited: ${history}`);\n } catch { /* private browsing */ }\n return parts.filter(Boolean).join('. ');\n}\n\n// Reconstructs the visitor's page journey from spectare.js visit history.\nfunction readVisitPath(orgSlug: string): string[] {\n try {\n const raw = JSON.parse(localStorage.getItem(`_spectare_visits_${orgSlug}`) || '[]') as Array<{ path?: string }>;\n const path: string[] = [];\n for (const v of raw) {\n if (typeof v?.path === 'string' && (!path.length || path[path.length - 1] !== v.path)) path.push(v.path);\n }\n const cur = window.location.pathname;\n if (!path.length || path[path.length - 1] !== cur) path.push(cur);\n return path;\n } catch { return []; }\n}\n\nfunction Shimmer() {\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <div style={{ height: '20px', background: 'rgba(39,39,42,0.6)', borderRadius: '8px', width: '75%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '100%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '83%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '67%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n </div>\n );\n}\n\nexport interface PersonalisedSectionProps {\n orgSlug: string;\n /** Base URL of your Spectare instance. Defaults to 'https://spectare.ai'. */\n baseUrl?: string;\n /** Your brand name, used in ComparisonTable column header. */\n brand?: string;\n pageHint?: string;\n className?: string;\n style?: React.CSSProperties;\n initialAssembly?: ComponentAssembly;\n initialIntent?: { audience: string; stage: string };\n /**\n * Seed conversion attribution with a server-rendered arrangement: pass the variantId that\n * /api/assemble/ssr returned alongside initialAssembly. Without it, a visit where the client\n * classification matches the server's (so no client render happens) has no variant for a\n * later conversion to credit.\n */\n initialVariantId?: string;\n /**\n * Explicit visitor-typed context (e.g. a demo input box). Bypasses the session token cache\n * and re-qualifies immediately with the direct flag, which the server cost-caps (cheaper\n * model on a cache miss) and never writes to the shared cache.\n */\n directSummary?: string;\n /** Render only components assigned to this zone. */\n zone?: AssemblyZone;\n /** Alignment for statement-style components, to match the host page. */\n align?: 'left' | 'center' | 'right';\n /**\n * Brand accent. Passed through to ComponentRenderer, which emits it into the scoped\n * token set. Defaults to #60a5fa (dark) or #2563eb (light).\n */\n accent?: string;\n /** dark (default) or light, matching your page's ground. See ComponentRenderer. */\n theme?: 'dark' | 'light';\n}\n\nexport function PersonalisedSection({\n orgSlug,\n baseUrl = 'https://spectare.ai',\n brand,\n pageHint,\n className,\n style,\n initialAssembly,\n initialIntent,\n initialVariantId,\n directSummary,\n zone,\n align,\n accent,\n theme,\n}: PersonalisedSectionProps) {\n const [assembly, setAssembly] = useState<ComponentAssembly>(initialAssembly ?? []);\n const [loading, setLoading] = useState(!initialAssembly);\n const [orgName, setOrgName] = useState<string | undefined>(undefined);\n const [debugMode, setDebugMode] = useState(false);\n const [debugIntent, setDebugIntent] = useState<{ audience: string; stage: string } | null>(null);\n const tokenRef = useRef<string | null>(null);\n const conversionFiredRef = useRef(false);\n\n useEffect(() => {\n setDebugMode(new URLSearchParams(window.location.search).has('spectare_debug'));\n if (initialIntent) setDebugIntent(initialIntent);\n }, [initialIntent]);\n\n // Seed sessionStorage with the server-rendered variantId so conversions attribute correctly\n // even when the client assembly matches the SSR one and no client fetch replaces it.\n useEffect(() => {\n if (initialVariantId) writeVariantId(orgSlug, initialVariantId);\n }, [orgSlug, initialVariantId]);\n\n useEffect(() => {\n let cancelled = false;\n\n async function load() {\n try {\n let token: string | null = null;\n\n if (directSummary) {\n // Explicit visitor input: skip the token cache, re-qualify immediately with direct.\n setLoading(true);\n setAssembly([]);\n const res = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary: directSummary, direct: true }),\n });\n if (!res.ok || cancelled) { setLoading(false); return; }\n const data = await res.json();\n token = (data.token as string | undefined) ?? null;\n } else {\n // Key includes UTM params so a visitor arriving via a campaign link always\n // re-qualifies rather than reusing a token from a prior session context.\n const p = new URLSearchParams(window.location.search);\n const utmSuffix = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term']\n .map(k => p.get(k) ?? '').filter(Boolean).join('_');\n const tokenKey = `_spectare_token_${orgSlug}${utmSuffix ? '_' + utmSuffix : ''}`;\n token = sessionStorage.getItem(tokenKey);\n\n if (!token) {\n const summary = buildSummary(pageHint ?? `Visiting ${document.title}`, orgSlug);\n const res = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary }),\n });\n if (!res.ok || cancelled) { setLoading(false); return; }\n const data = await res.json();\n token = data.token as string | undefined ?? null;\n if (token) sessionStorage.setItem(tokenKey, token);\n if (data.orgName) setOrgName(data.orgName as string);\n }\n }\n\n if (!token || cancelled) { setLoading(false); return; }\n\n tokenRef.current = token;\n let res = await fetch(`${baseUrl}/api/assemble/components`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n // Direct: flag it so the server cost-caps the build, and omit the seen-variant\n // exclusion so it can read the shared cache instead of forcing a fresh build.\n body: JSON.stringify(\n directSummary\n ? { token, orgSlug, direct: true }\n : { token, orgSlug, excludeVariantId: readVariantId(orgSlug) },\n ),\n });\n\n if (res.status === 401 && !cancelled && !directSummary) {\n // Cached token expired: clear it, re-qualify, and retry once.\n const p = new URLSearchParams(window.location.search);\n const utmSuffix = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term']\n .map(k => p.get(k) ?? '').filter(Boolean).join('_');\n const tokenKey = `_spectare_token_${orgSlug}${utmSuffix ? '_' + utmSuffix : ''}`;\n sessionStorage.removeItem(tokenKey);\n const summary = buildSummary(pageHint ?? `Visiting ${document.title}`, orgSlug);\n const qRes = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary }),\n });\n if (!qRes.ok || cancelled) { setLoading(false); return; }\n const qData = await qRes.json();\n token = qData.token as string | undefined ?? null;\n if (token) {\n sessionStorage.setItem(tokenKey, token);\n tokenRef.current = token;\n }\n if (!token || cancelled) { setLoading(false); return; }\n res = await fetch(`${baseUrl}/api/assemble/components`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, orgSlug, excludeVariantId: readVariantId(orgSlug) }),\n });\n }\n\n if (!res.ok || cancelled) { setLoading(false); return; }\n\n const contentType = res.headers.get('content-type') ?? '';\n\n if (contentType.includes('text/event-stream')) {\n // Cold path: stream components as Claude generates them.\n // Render progressively — shimmer shows until the first component arrives.\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n let loadingCleared = false;\n try {\n while (!cancelled) {\n const { done, value } = await reader.read();\n if (done || cancelled) break;\n buf += decoder.decode(value, { stream: true });\n const lines = buf.split('\\n');\n buf = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue;\n const payload = line.slice(6).trim();\n if (payload === '[DONE]') break;\n try {\n const parsed = JSON.parse(payload) as Record<string, unknown>;\n // Control frames: {_variant} carries attribution, {_error} means the stream\n // died server-side. Neither is a component; pushing them into the assembly\n // recorded a phantom entry the renderer silently skipped.\n if (parsed._variant && typeof parsed._variant === 'string') {\n writeVariantId(orgSlug, parsed._variant);\n continue;\n }\n if (parsed._error) {\n if (!loadingCleared) { setLoading(false); loadingCleared = true; }\n continue;\n }\n if (!parsed.component) continue;\n const comp = parsed as unknown as ComponentAssembly[0];\n if (!loadingCleared) { setLoading(false); loadingCleared = true; }\n setAssembly(prev => [...prev, comp]);\n } catch { /* malformed event — skip */ }\n }\n }\n } finally {\n reader.cancel().catch(() => {});\n }\n } else {\n // Warm path: cache hit returns full JSON immediately.\n const data = await res.json() as {\n assembly?: ComponentAssembly;\n intent?: { userContext?: { audience?: string; stage?: string } };\n variantId?: string;\n };\n if (data.variantId) writeVariantId(orgSlug, data.variantId);\n\n if (cancelled) return;\n\n const clientAudience = data.intent?.userContext?.audience;\n const clientStage = data.intent?.userContext?.stage;\n const ssrMatches =\n initialIntent &&\n clientAudience === initialIntent.audience &&\n clientStage === initialIntent.stage;\n\n if (clientAudience && clientStage) {\n setDebugIntent({ audience: clientAudience, stage: clientStage });\n }\n\n if (!ssrMatches && Array.isArray(data.assembly) && data.assembly.length > 0) {\n setAssembly(data.assembly as ComponentAssembly);\n }\n }\n } catch {\n // fail silently\n } finally {\n if (!cancelled) setLoading(false);\n }\n }\n\n load();\n return () => { cancelled = true; };\n }, [orgSlug, baseUrl, pageHint, initialAssembly, initialIntent, directSummary]);\n\n useEffect(() => {\n if (!assembly.length || conversionFiredRef.current) return;\n const token = tokenRef.current;\n if (!token) return;\n const url = window.location.href;\n fetch(`${baseUrl}/api/conversion-check`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ orgSlug, url }),\n }).then(r => r.json() as Promise<ConversionCheckResult>).then(data => {\n if (!data.matched) return;\n conversionFiredRef.current = true;\n let goalValue: number | null = null;\n let goalCurrency: string | null = data.defaultCurrency;\n if (data.valueSelector) {\n try {\n const el = document.querySelector(data.valueSelector);\n if (el) {\n const num = parseFloat((el.textContent ?? '').trim().replace(/[^0-9.]/g, ''));\n if (!isNaN(num)) goalValue = num;\n }\n } catch { /* skip */ }\n }\n if (data.currencySelector) {\n try {\n const el = document.querySelector(data.currencySelector);\n if (el) goalCurrency = (el.textContent ?? '').trim() || goalCurrency;\n } catch { /* skip */ }\n }\n const atomsShown = [...new Set(assembly.flatMap(i => i.sourceAtomIds ?? []))];\n const visitPath = readVisitPath(orgSlug);\n fetch(`${baseUrl}/api/conversion`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n token,\n orgSlug,\n url,\n variantId: readVariantId(orgSlug),\n ...(atomsShown.length ? { atomsShown } : {}),\n ...(visitPath.length > 1 ? { visitPath } : {}),\n ...(data.goalName ? { goalName: data.goalName } : {}),\n ...(goalValue !== null ? { goalValue, goalCurrency } : {}),\n }),\n }).catch(() => {});\n }).catch(() => {});\n }, [assembly, orgSlug, baseUrl]);\n\n if (!loading && assembly.length === 0) return null;\n\n // ?spectare_debug outlines the section and names the classified intent, so anyone checking\n // an integration can see where personalisation lands and what the visitor was read as.\n const debugStyle = debugMode\n ? { outline: '2px solid rgba(96,165,250,0.5)', borderRadius: '0.5rem', position: 'relative' as const, padding: '0.5rem', ...style }\n : style;\n\n return (\n <>\n <style dangerouslySetInnerHTML={{ __html: '@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}' }} />\n <div className={className} style={debugStyle}>\n {debugMode && (\n <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' }}>\n Personalised by Spectare\n {debugIntent && (\n <span style={{ opacity: 0.75 }}>\n {' '}{debugIntent.audience}/{debugIntent.stage}\n </span>\n )}\n </div>\n )}\n {loading && assembly.length === 0\n ? <Shimmer />\n : <ComponentRenderer assembly={zone ? filterAssemblyByZone(assembly, zone) : assembly} brand={brand ?? orgName} align={align} accent={accent} theme={theme} />}\n </div>\n </>\n );\n}\n","// Universal renderer: deliberately NO 'use client' in this source file. Nothing here uses hooks, state, or event\n// handlers, so the same file renders as a React Server Component (zero JS shipped, how the\n// Spectare app uses it via components/ServerAssemblyRenderer.tsx) and inside a client tree\n// (how PersonalisedSection uses it). Adding a hook or handler here would silently force every\n// server consumer to ship and hydrate it: keep interactivity in wrappers.\n//\n// Sizing is numeric, scaled through u(): px for embedded hosts (predictable inside arbitrary\n// pages) or rem for hosts that want to track the reader's font-size preference (the Spectare\n// site). Until 2026-08-31 the rem variant was a hand-maintained mirror of this file, and the\n// two drifted a pixel apart in six places; one number set, one scale function, no mirror.\nimport { marked } from 'marked';\nimport DOMPurify from 'isomorphic-dompurify';\nimport { filterAssemblyByZone, COMPONENT_CATEGORIES } from './types';\nimport { buildTokenCss, SP_ROOT } from './tokens';\nimport type { SpTheme } from './tokens';\nimport type { ComponentAssembly, ComponentName, AssemblyZone } from './types';\n\n// The assembly API returns atom content as raw markdown. marked emits raw HTML,\n// so the output must be sanitised before it reaches dangerouslySetInnerHTML,\n// otherwise a malicious atom can run script in the host site's visitors' browsers.\nfunction renderMarkdown(content: string): string {\n const raw = marked.parse(content ?? '', { async: false }) as string;\n return DOMPurify.sanitize(raw, { USE_PROFILES: { html: true } });\n}\n\nexport type Unit = 'px' | 'rem';\ntype U = (n: number) => string;\nconst scaler = (unit: Unit): U => (n: number) => (unit === 'rem' ? `${n / 16}rem` : `${n}px`);\nconst PX = scaler('px');\n\n// Default half-size components: used when assembly item omits size.\nconst HALF_COMPONENTS = new Set<ComponentName>(['TestimonialCard']);\n\n// ── Individual component renderers ────────────────────────────────────────────\n\n// Alignment is a host decision, not baked into a component: the host passes `align`\n// and statement-style components adopt it. flexItems maps it to a flex alignment so\n// block children (a max-width subheading, an inline CTA) align too, not just the text.\ntype Align = 'left' | 'center' | 'right';\nconst flexItems = (a: Align): 'flex-start' | 'center' | 'flex-end' =>\n a === 'center' ? 'center' : a === 'right' ? 'flex-end' : 'flex-start';\n\n/**\n * A single line above everything else. Deliberately the plainest component in the set: no\n * heading, no image, no padding to speak of. A bar that draws attention to itself competes with\n * the page it is announcing something about.\n *\n * Uses the accent rather than a red or amber alert colour. This is a fact worth knowing, not a\n * warning, and a venue putting \"members book from Thursday\" in an alarm colour reads as a problem\n * rather than an offer.\n */\nexport function AnnouncementBar({ text, link, unit = 'px' }: { text?: string; link?: { label: string; href: string }; unit?: Unit }) {\n const u = scaler(unit);\n if (!text) return null;\n return (\n <div style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center', gap: u(10),\n flexWrap: 'wrap', textAlign: 'center',\n background: 'var(--sp-accent-bg)', border: '1px solid var(--sp-accent-border)',\n borderRadius: u(8), padding: `${u(8)} ${u(16)}`, fontSize: u(14), lineHeight: 1.4,\n color: 'var(--sp-text-sub)',\n }}>\n <span>{text}</span>\n {link?.href && link?.label && (\n <a href={link.href} style={{ color: 'var(--sp-accent)', fontWeight: 600, textDecoration: 'none', whiteSpace: 'nowrap' }}>\n {link.label} →\n </a>\n )}\n </div>\n );\n}\n\nexport function HeroStatement({ headline, subheading, align = 'left', unit = 'px' }: { headline: string; subheading?: string; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: flexItems(align), textAlign: align, paddingTop: u(24), paddingBottom: u(24) }}>\n <h2 style={{ fontSize: u(32), fontWeight: 700, letterSpacing: '-0.025em', lineHeight: 1.2, color: 'var(--sp-text)', margin: `0 0 ${u(12)}` }}>\n {headline}\n </h2>\n {subheading && (\n <p style={{ fontSize: u(18), color: 'var(--sp-text-sub)', lineHeight: 1.6, maxWidth: u(672), margin: 0 }}>{subheading}</p>\n )}\n </div>\n );\n}\n\n// The atom owns title / content / stats / cta; its layout decides which appear and in\n// what order. Default order when the atom has no layout. Mirrors the atom editor.\nconst ATOM_LAYOUT_DEFAULT = ['title', 'content', 'stats', 'cta'];\n\n// Clamp atom prose unless the assembly asked for the full body. CSS rather than an expand\n// toggle, so the identical rule works here (including server-rendered with no JS), in\n// spectare.js and in the WordPress plugin.\nexport const ATOM_CLAMP_LINES = 4;\nconst clampStyle = {\n display: '-webkit-box',\n WebkitLineClamp: ATOM_CLAMP_LINES,\n WebkitBoxOrient: 'vertical' as const,\n overflow: 'hidden',\n};\n\nexport function AtomCard(\n { title, content, summary, layout, stats = [], ctaText, ctaUrl, full, variant, unit = 'px' }:\n { title?: string; content?: string; summary?: string; layout?: string[]; stats?: { value: string; label: string }[]; ctaText?: string; ctaUrl?: string; full?: boolean; variant?: string; unit?: Unit },\n) {\n const u = scaler(unit);\n\n // The card face: title, one-sentence summary, and the full body behind a native <details>\n // disclosure. <details> is the one expand that needs no JavaScript, so it works identically\n // in a server component, a client tree, and any host page; nothing is ever unreachable on a\n // site that has no per-atom pages. The Spectare app substitutes its own card face (which\n // links to the atom's page) via renderOverride, so this is the everywhere-else rendering.\n if (variant === 'card') {\n const face = summary?.trim() || (content ? `${content.replace(/\\s+/g, ' ').split(/(?<=[.!?])\\s/)[0]}` : '');\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(20) }}>\n {title && <h3 style={{ fontSize: u(18), fontWeight: 600, color: 'var(--sp-text)', margin: 0, lineHeight: 1.35 }}>{title}</h3>}\n {face && <p style={{ fontSize: u(16), color: 'var(--sp-text-sub)', lineHeight: 1.6, margin: `${u(8)} 0 0` }}>{face}</p>}\n {/* One link per face. The atom's own CTA is deliberately NOT rendered here: the\n face's job is the summary and the disclosure, and the guards already treat a\n card face as carrying no inline CTA. Stacked links on a compact card read as\n competing calls to action. */}\n {content && (\n <details style={{ marginTop: u(10) }}>\n <summary style={{ cursor: 'pointer', fontSize: u(14), fontWeight: 600, color: 'var(--sp-accent)', listStyle: 'none' }}>Read more</summary>\n <div className=\"sp-prose\" style={{ fontSize: u(16), color: 'var(--sp-text-sub)', lineHeight: 1.6, marginTop: u(10) }} dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} />\n </details>\n )}\n </div>\n );\n }\n\n const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;\n const element = (name: string) => {\n if (name === 'title') return title\n ? <h3 key=\"title\" style={{ fontSize: u(18), fontWeight: 600, color: 'var(--sp-text)', margin: `0 0 ${u(12)}` }}>{title}</h3> : null;\n if (name === 'content') return content\n ? <div key=\"content\" className=\"sp-prose\" style={{ fontSize: u(16), color: 'var(--sp-text-sub)', lineHeight: 1.6, ...(full ? {} : clampStyle) }} dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} /> : null;\n if (name === 'stats') return stats.length\n ? (\n <div key=\"stats\" style={{ display: 'flex', flexWrap: 'wrap', gap: u(20), margin: `${u(18)} 0 ${u(12)}`, padding: `0 0 ${u(14)}`, borderBottom: '1px solid var(--sp-border)' }}>\n {stats.map((s, i) => (\n <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: u(2) }}>\n <span style={{ fontSize: u(22), fontWeight: 700, color: 'var(--sp-text)', lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>{s.value}</span>\n <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>{s.label}</span>\n </div>\n ))}\n </div>\n ) : null;\n if (name === 'cta') return ctaText && ctaUrl\n ? <a key=\"cta\" href={ctaUrl} style={{ display: 'inline-flex', alignItems: 'center', gap: u(4), marginTop: u(12), fontSize: u(14), fontWeight: 600, color: 'var(--sp-accent)', textDecoration: 'none' }}>{ctaText} →</a> : null;\n return null;\n };\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(24), height: '100%' }}>\n {order.map(element)}\n </div>\n );\n}\n\nexport function StatGrid({ stats = [], caption, unit = 'px' }: { stats?: { value: string; label: string }[]; caption?: string; unit?: Unit }) {\n const u = scaler(unit);\n const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;\n return (\n <div>\n <div style={{ display: 'grid', gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: u(12) }}>\n {stats.map(({ value, label }) => (\n <div key={label} 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) }}>\n <p style={{ fontSize: u(12), color: 'var(--sp-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em', margin: `0 0 ${u(12)}`, lineHeight: 1.3 }}>{label}</p>\n <p style={{ fontSize: u(20), fontWeight: 500, color: 'var(--sp-text)', fontVariantNumeric: 'tabular-nums', lineHeight: 1, margin: 0 }}>{value}</p>\n </div>\n ))}\n </div>\n {caption && (\n <p style={{ fontSize: u(14), color: 'var(--sp-text-muted)', margin: `${u(12)} 0 0` }}>{caption}</p>\n )}\n </div>\n );\n}\n\nexport function CodeBlock({ code, lang = 'typescript', caption, unit = 'px' }: { code: string; lang?: string; caption?: string; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ borderRadius: u(12), overflow: 'hidden', border: '1px solid var(--sp-border)' }}>\n <div style={{ background: 'var(--sp-bg)', padding: `${u(10)} ${u(16)}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: '1px solid var(--sp-border)' }}>\n <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)', fontFamily: 'monospace' }}>{lang}</span>\n {caption && <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)' }}>{caption}</span>}\n </div>\n <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 }}>\n {code}\n </pre>\n </div>\n );\n}\n\nexport function ComparisonTable({ brand = 'Us', competitor, rows = [], unit = 'px' }: { brand?: string; competitor: string; rows?: { label: string; spectare: string; them: string }[]; unit?: Unit }) {\n const u = scaler(unit);\n const cell = { textAlign: 'left' as const, padding: `${u(12)} ${u(16)}` };\n return (\n <div style={{ border: '1px solid var(--sp-border)', borderRadius: u(12), overflow: 'hidden' }}>\n <div style={{ overflowX: 'auto' }}>\n <table style={{ width: '100%', fontSize: u(14), borderCollapse: 'collapse' }}>\n <thead>\n <tr style={{ borderBottom: '1px solid var(--sp-border)', background: 'var(--sp-bg)' }}>\n <th style={{ ...cell, color: 'var(--sp-text-muted)', fontWeight: 500, fontSize: u(13), width: '33%' }} />\n <th scope=\"col\" style={{ ...cell, fontWeight: 600, color: 'var(--sp-accent)', fontSize: u(13) }}>{brand}</th>\n <th scope=\"col\" style={{ ...cell, color: 'var(--sp-text-muted)', fontWeight: 500, fontSize: u(13) }}>{competitor}</th>\n </tr>\n </thead>\n <tbody>\n {rows.map(({ label, spectare, them }) => (\n <tr key={label} style={{ borderBottom: '1px solid var(--sp-border)' }}>\n <th scope=\"row\" style={{ ...cell, fontSize: u(14), color: 'var(--sp-text-muted)', fontWeight: 500 }}>{label}</th>\n <td style={{ ...cell, fontSize: u(14), color: 'var(--sp-positive)', fontWeight: 500 }}>{spectare}</td>\n <td style={{ ...cell, fontSize: u(14), color: 'var(--sp-text-muted)' }}>{them}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nexport function FeatureList({ items = [], unit = 'px' }: { items?: { text: string; sub?: string }[]; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(24) }}>\n <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: u(16) }}>\n {items.map(({ text, sub }) => (\n <li key={text} style={{ display: 'flex', gap: u(12) }}>\n <span style={{ color: 'var(--sp-accent)', flexShrink: 0, fontSize: u(15), marginTop: u(2) }}>✓</span>\n <div>\n <p style={{ fontSize: u(15), fontWeight: 500, color: 'var(--sp-text)', lineHeight: 1.4, margin: 0 }}>{text}</p>\n {sub && <p style={{ fontSize: u(14), color: 'var(--sp-text-muted)', lineHeight: 1.5, margin: `${u(4)} 0 0` }}>{sub}</p>}\n </div>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport function TestimonialCard({ quote, name, role, company, unit = 'px' }: { quote: string; name: string; role: string; company?: string; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <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%' }}>\n <p style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, flex: 1, margin: 0 }}>\n <span style={{ color: 'var(--sp-text-dim)', fontSize: u(18), lineHeight: 1, marginRight: u(4) }}>\"</span>\n {quote}\n <span style={{ color: 'var(--sp-text-dim)', fontSize: u(18), lineHeight: 1, marginLeft: u(4) }}>\"</span>\n </p>\n <div style={{ borderTop: '1px solid var(--sp-border)', paddingTop: u(16) }}>\n <p style={{ fontSize: u(14), fontWeight: 600, color: 'var(--sp-text)', margin: 0 }}>{name}</p>\n <p style={{ fontSize: u(14), color: 'var(--sp-text-muted)', margin: `${u(2)} 0 0` }}>\n {role}{company ? `, ${company}` : ''}\n </p>\n </div>\n </div>\n );\n}\n\nexport function ImageCtaHero({ src, alt = '', headline, subheading, ctaLabel, ctaHref, align = 'left', unit = 'px' }: { src?: string; alt?: string; headline?: string; subheading?: string; ctaLabel?: string; ctaHref?: string; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n if (!src) return null;\n return (\n <div style={{ borderRadius: u(12), overflow: 'hidden', position: 'relative', width: '100%', paddingBottom: '56.25%' }}>\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={src} alt={alt} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />\n <div style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.45)' }} />\n <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%)' }} />\n <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: u(28), textAlign: align }}>\n {headline && (\n <h2 style={{ fontSize: u(24), fontWeight: 700, color: '#fff', lineHeight: 1.2, margin: `0 0 ${u(8)}`, letterSpacing: '-0.02em' }}>{headline}</h2>\n )}\n {subheading && (\n <p style={{ fontSize: u(15), color: 'rgba(255,255,255,0.75)', lineHeight: 1.5, margin: `0 0 ${u(20)}` }}>{subheading}</p>\n )}\n {ctaHref && ctaLabel && (\n <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' }}>\n {ctaLabel}\n </a>\n )}\n </div>\n </div>\n );\n}\n\nexport function CtaStrip({ headline, primary, secondary, align = 'center', unit = 'px' }: { headline: string; primary: { label: string; href: string }; secondary?: { label: string; href: string }; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(32), textAlign: align, background: 'var(--sp-bg)' }}>\n <h3 style={{ fontSize: u(24), fontWeight: 700, color: 'var(--sp-text)', margin: `0 0 ${u(24)}` }}>{headline}</h3>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: flexItems(align), gap: u(16), flexWrap: 'wrap' }}>\n <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' }}>\n {primary.label}\n </a>\n {secondary && (\n <a href={secondary.href} style={{ fontSize: u(15), color: 'var(--sp-text-sub)', textDecoration: 'none' }}>\n {secondary.label} →\n </a>\n )}\n </div>\n </div>\n );\n}\n\n// ── Dispatch ──────────────────────────────────────────────────────────────────\n\nfunction renderSingle(item: ComponentAssembly[0], brand?: string, align?: Align, unit: Unit = 'px'): React.ReactNode {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const s = item.slots as Record<string, any> ?? {};\n\n switch (item.component as ComponentName) {\n case 'AnnouncementBar': return <AnnouncementBar text={s.text} link={s.link} unit={unit} />;\n case 'HeroStatement': return <HeroStatement headline={s.headline} subheading={s.subheading} align={align} unit={unit} />;\n // A full-width card has nothing beside it, so there is nothing for a clamp to protect.\n case 'AtomCard': return <AtomCard title={s.title} content={s.content} summary={s.summary} layout={s.layout} stats={s.stats} ctaText={s.ctaText} ctaUrl={s.ctaUrl} full={s.full || resolvedSize(item) === 'full'} variant={s.variant} unit={unit} />;\n case 'StatGrid': return <StatGrid stats={s.stats} caption={s.caption} unit={unit} />;\n case 'CodeBlock': return <CodeBlock code={s.code} lang={s.lang} caption={s.caption} unit={unit} />;\n case 'ComparisonTable': return <ComparisonTable brand={s.brand ?? brand} competitor={s.competitor} rows={s.rows} unit={unit} />;\n case 'FeatureList': return <FeatureList items={s.items} unit={unit} />;\n case 'TestimonialCard': return <TestimonialCard quote={s.quote} name={s.name} role={s.role} company={s.company} unit={unit} />;\n case 'ImageCtaHero': return <ImageCtaHero src={s.src} alt={s.alt} headline={s.headline} subheading={s.subheading} ctaLabel={s.ctaLabel} ctaHref={s.ctaHref} align={align} unit={unit} />;\n case 'CtaStrip': return <CtaStrip headline={s.headline} primary={s.primary} secondary={s.secondary} align={align} unit={unit} />;\n // An unrecognised component name used to render nothing at all. A component needs a\n // renderer here plus spectare.js plus the WordPress plugin, so missing one made its content\n // silently absent on that surface only: no error, no warning, just a shorter page that\n // looks deliberate. That is the failure mode to remove before the registry grows.\n //\n // Falls back to AtomCard when the slots carry something readable, since almost every\n // component is built from an atom and title/content is the shape they share. When there\n // is genuinely nothing to show it still renders nothing, because an empty card is worse\n // than a gap, but the warning fires either way.\n default: {\n console.warn(`[spectare] ComponentRenderer: no renderer for \"${item.component}\", falling back to AtomCard`);\n if (!s.title && !s.content) return null;\n return <AtomCard title={s.title} content={s.content} stats={s.stats} ctaText={s.ctaText} ctaUrl={s.ctaUrl} full unit={unit} />;\n }\n }\n}\n\n// ── Layout ────────────────────────────────────────────────────────────────────\n\nfunction resolvedSize(item: ComponentAssembly[0]): 'full' | 'half' {\n if (item.size) return item.size;\n return HALF_COMPONENTS.has(item.component as ComponentName) ? 'half' : 'full';\n}\n\ntype LayoutGroup =\n | { type: 'full'; item: ComponentAssembly[0] }\n | { type: 'pair'; items: [ComponentAssembly[0], ComponentAssembly[0]] }\n | { type: 'half-solo'; item: ComponentAssembly[0] };\n\n// Two half-width components only sit side by side well if they read at the same speed. A\n// prose block beside a scannable list forces the eye to switch modes, and the grid stretches\n// the shorter one, leaving dead space. Registry category is the available proxy for reading\n// mode, so pair within a category and give anything else its own row.\nfunction pairable(a: ComponentAssembly[0], b: ComponentAssembly[0]): boolean {\n const catOf = (x: ComponentAssembly[0]) =>\n COMPONENT_CATEGORIES[x.component as ComponentName];\n const ca = catOf(a);\n const cb = catOf(b);\n return ca !== undefined && ca === cb;\n}\n\nfunction buildLayout(assembly: ComponentAssembly): LayoutGroup[] {\n const groups: LayoutGroup[] = [];\n let i = 0;\n while (i < assembly.length) {\n const cur = assembly[i];\n const next = assembly[i + 1];\n if (resolvedSize(cur) === 'half' && next && resolvedSize(next) === 'half' && pairable(cur, next)) {\n groups.push({ type: 'pair', items: [cur, next] });\n i += 2;\n } else if (resolvedSize(cur) === 'half') {\n groups.push({ type: 'half-solo', item: cur });\n i++;\n } else {\n groups.push({ type: 'full', item: cur });\n i++;\n }\n }\n return groups;\n}\n\n// ── X-ray badge ───────────────────────────────────────────────────────────────\n\nfunction XrayBadge({ name, size }: { name: string; size: string }) {\n return (\n <div style={{ position: 'absolute', top: PX(8), left: PX(8), zIndex: 10, display: 'flex', alignItems: 'center', gap: PX(6), pointerEvents: 'none', userSelect: 'none' }}>\n <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 }}>{name}</span>\n <span style={{ fontSize: PX(10), fontFamily: 'monospace', color: '#71717a', lineHeight: 1 }}>{size}</span>\n </div>\n );\n}\n\n// ── Main export ───────────────────────────────────────────────────────────────\n\nexport interface ComponentRendererProps {\n assembly: ComponentAssembly;\n /** Your brand name, used as the left column header in ComparisonTable. Defaults to \"Us\". */\n brand?: string;\n /** Overlay a component name badge on each item. Useful for demos and debugging. */\n xray?: boolean;\n /** Render only components assigned to this zone. */\n zone?: AssemblyZone;\n /**\n * Alignment for statement-style components (HeroStatement, CtaStrip, ImageCtaHero),\n * so assembled content can match the host page. Omit to use each component's natural\n * default (HeroStatement left, CtaStrip centered).\n */\n align?: 'left' | 'center' | 'right';\n /**\n * Brand accent, as an explicit input rather than a custom property you override and hope\n * wins on tag order. Any CSS colour. `--sp-accent-bg` and `--sp-accent-border` are derived\n * from it, so one value covers all three. Defaults to #60a5fa.\n */\n accent?: string;\n /**\n * dark (default) is the package's original near-black card set. light renders white cards\n * with a dark text ramp for light host pages; without it the components paint near-white\n * text and near-black slabs onto a light ground. Both palettes hold the same contrast\n * floors (see tests/unit/token-contrast.test.ts).\n */\n theme?: SpTheme;\n /**\n * px (default) sizes components absolutely, predictable inside arbitrary host pages.\n * rem tracks the reader's font-size preference; the root then also inherits the host's\n * font size instead of pinning 16px.\n */\n unit?: Unit;\n /**\n * Substitute rendering for an item: return a node to replace the built-in renderer\n * (including null to render nothing), or undefined to keep the default. How the Spectare\n * app swaps the card-variant AtomCard for its server-rendered card face.\n */\n renderOverride?: (item: ComponentAssembly[0]) => React.ReactNode | undefined;\n /**\n * Wrap each rendered item, e.g. with source attribution or a debug badge. Receives the\n * assembly item and its rendered node; whatever it returns is placed in the layout.\n */\n renderItem?: (item: ComponentAssembly[0], rendered: React.ReactNode) => React.ReactNode;\n /** Extra attributes for the root element (e.g. a data marker a host overlay targets). */\n rootProps?: Record<string, unknown>;\n}\n\n\nexport function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent, theme, unit = 'px', renderOverride, renderItem, rootProps }: ComponentRendererProps) {\n const u = scaler(unit);\n const filtered = zone ? filterAssemblyByZone(assembly, zone) : assembly;\n const layout = buildLayout(filtered);\n\n // Merge rather than spread-clobber: a host className joins sp-root instead of replacing it\n // (every --sp-* token is scoped to .sp-root, so losing it un-themes every component), and a\n // host style merges under the layout styles rather than being silently discarded.\n const { className: extraClass, style: extraStyle, ...restRoot } = (rootProps ?? {}) as { className?: string; style?: React.CSSProperties } & Record<string, unknown>;\n\n const renderOne = (item: ComponentAssembly[0]): React.ReactNode => {\n const override = renderOverride?.(item);\n const node = override === undefined ? renderSingle(item, brand, align, unit) : override;\n return renderItem ? renderItem(item, node) : node;\n };\n\n return (\n <div className={extraClass ? `${SP_ROOT} ${extraClass}` : SP_ROOT} {...restRoot} style={{ ...extraStyle, display: 'flex', flexDirection: 'column', gap: u(20), ...(unit === 'px' ? { fontSize: '16px' } : {}) }}>\n <style dangerouslySetInnerHTML={{ __html: buildTokenCss({ accent, unit, theme }) }} />\n {layout.map((group, i) => {\n if (group.type === 'pair') {\n return (\n <div key={i} className=\"sp-pair\">\n <div style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.items[0].component} size=\"half\" />}\n {renderOne(group.items[0])}\n </div>\n <div style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.items[1].component} size=\"half\" />}\n {renderOne(group.items[1])}\n </div>\n </div>\n );\n }\n return (\n <div key={i} style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.item.component} size={group.type === 'half-solo' ? 'half' : 'full'} />}\n {renderOne(group.item)}\n </div>\n );\n })}\n </div>\n );\n}\n","export type ComponentName =\n | 'AnnouncementBar'\n | 'HeroStatement'\n | 'AtomCard'\n | 'StatGrid'\n | 'CodeBlock'\n | 'ComparisonTable'\n | 'FeatureList'\n | 'TestimonialCard'\n | 'ImageCtaHero'\n | 'CtaStrip';\n\nexport type AssemblyZone = 'announce' | 'hero' | 'body' | 'proof' | 'cta';\n\nconst COMPONENT_ZONES: Record<ComponentName, AssemblyZone> = {\n AnnouncementBar: 'announce',\n HeroStatement: 'hero',\n ImageCtaHero: 'hero',\n AtomCard: 'body',\n StatGrid: 'body',\n CodeBlock: 'body',\n ComparisonTable: 'body',\n FeatureList: 'body',\n TestimonialCard: 'proof',\n CtaStrip: 'cta',\n};\n\nexport type ComponentAssembly = Array<{\n component: ComponentName;\n slots?: Record<string, unknown>;\n size?: 'full' | 'half';\n zone?: AssemblyZone;\n // Atom IDs this component was built from; drives conversion attribution.\n sourceAtomIds?: number[];\n}>;\n\nexport function filterAssemblyByZone(assembly: ComponentAssembly, zone: AssemblyZone): ComponentAssembly {\n return assembly.filter(item => {\n const effectiveZone = item.zone ?? COMPONENT_ZONES[item.component];\n return effectiveZone === zone;\n });\n}\n\n/**\n * Reading-mode category per component: the layout's pairing key. Two half-width components\n * only sit side by side when they share a category, so a prose block never lands beside a\n * scannable list. Mirrors the `category` field in the app's lib/component-registry.ts (the\n * source of truth, which also drives the assembly prompt);\n * tests/unit/renderer-category-parity.test.ts fails when the two drift.\n */\nexport const COMPONENT_CATEGORIES: Record<ComponentName, string> = {\n AnnouncementBar: 'conversion',\n HeroStatement: 'hero',\n AtomCard: 'content',\n StatGrid: 'content',\n CodeBlock: 'technical',\n ComparisonTable: 'evaluation',\n FeatureList: 'content',\n TestimonialCard: 'social-proof',\n ImageCtaHero: 'hero',\n CtaStrip: 'conversion',\n};\n","/**\n * The one place this package's design tokens are defined.\n *\n * Two things that are easy to get wrong here:\n *\n * 1. Tokens are declared on `.sp-root`, not `:root`. Declaring them at `:root` writes into\n * the host's document, allows only one theme per page, and means a customer overriding\n * `--sp-accent` competes with us at equal specificity so tag order decides the winner.\n * Scoping also lets two differently themed sections sit on one page.\n *\n * 2. `tokens.css` must stay byte-identical to `buildTokenCss({ scope: STYLESHEET_SCOPE })`,\n * which differs from the injected CSS in its selector and in nothing else.\n * tests/unit/react-tokens.test.ts enforces both halves, because a customer who imports the\n * stylesheet and a customer who renders the component must get the same page.\n *\n * components/ServerAssemblyRenderer.tsx in the Spectare app is a deliberate mirror of the\n * values below. It is not the same file: that renderer uses rem, this one uses px.\n */\n\n/** The package default. `spectare.js` and the WordPress plugin default to #2563eb, which is\n * a live inconsistency and a brand decision rather than a technical one, so it is left alone\n * here. Pass `accent` to override on either path. */\nexport const DEFAULT_ACCENT = '#60a5fa';\n\n/** The light theme's default accent. #60a5fa reads at ~2.5:1 on white, far below the 4.5:1\n * body floor, so light gets the deeper blue the widget and plugin already default to. */\nexport const DEFAULT_ACCENT_LIGHT = '#2563eb';\n\nexport type SpTheme = 'dark' | 'light';\n\n/** Class the tokens are scoped to. Applied by ComponentRenderer to its own wrapper. */\nexport const SP_ROOT = 'sp-root';\n\n/**\n * Selector the shipped `tokens.css` declares on.\n *\n * `:where(:root)` has zero specificity, so it gives a host that imports the stylesheet and\n * composes the individual components a working set of defaults without a wrapper, while losing\n * to literally any rule the host writes, including a bare `:root` of their own. `.sp-root` then\n * wins over it wherever both apply, which is what makes a differently themed section on one page\n * work. The runtime CSS the renderer injects uses `.sp-root` alone: it applies the class itself,\n * so it has no reason to touch the host's document.\n */\nexport const STYLESHEET_SCOPE = `:where(:root),.${SP_ROOT}`;\n\n/**\n * Colour tokens, in the order they are emitted.\n *\n * `--sp-text-muted` and `--sp-text-dim` were #71717a (3.67:1) and #52525b (2.29:1) on\n * `--sp-bg`, which fail WCAG AA for body text and, in the case of dim, fail even the 3:1\n * large-text floor. They now measure 4.65:1 and 3.36:1. Every other value is unchanged.\n *\n * `--sp-cta-bg` / `--sp-cta-text` carry the values CtaStrip used to hardcode, so the dark\n * rendering is pixel-identical and a light host can correct a button that would otherwise\n * be white on white.\n */\nfunction palette(accent: string, theme: SpTheme): Record<string, string> {\n const shared = {\n '--sp-accent': accent,\n '--sp-accent-bg': `color-mix(in srgb,${accent} 10%,transparent)`,\n '--sp-accent-border': `color-mix(in srgb,${accent} 20%,transparent)`,\n };\n // The light set mirrors the dark ramp with the same contrast discipline: every text token\n // holds its floor on both --sp-bg and --sp-surface (tests/unit/token-contrast.test.ts runs\n // the identical assertions against both themes), and the ramp stays strictly ordered.\n if (theme === 'light') {\n return {\n ...shared,\n '--sp-bg': '#ffffff',\n '--sp-surface': '#f4f4f5',\n '--sp-border': '#e4e4e7',\n '--sp-text': '#18181b',\n '--sp-text-sub': '#3f3f46',\n '--sp-text-strong': '#27272a',\n '--sp-text-muted': '#6b6b74',\n '--sp-text-dim': '#82828b',\n '--sp-text-body': '#52525b',\n '--sp-positive': '#047857',\n '--sp-cta-bg': '#18181b',\n '--sp-cta-text': '#ffffff',\n '--sp-divider': 'rgba(0,0,0,0.06)',\n '--sp-code-bg': 'rgba(0,0,0,0.05)',\n '--sp-code-border': 'rgba(0,0,0,0.08)',\n '--sp-pre-bg': 'rgba(0,0,0,0.04)',\n };\n }\n return {\n ...shared,\n '--sp-bg': '#18181b',\n '--sp-surface': '#09090b',\n '--sp-border': '#27272a',\n '--sp-text': '#f4f4f5',\n // Body prose colour. Was #d4d4d8, judged too grey against near-black at reading\n // sizes; one step brighter keeps the hierarchy below --sp-text while reading as\n // text rather than chrome.\n '--sp-text-sub': '#e4e4e7',\n '--sp-text-strong': '#ececee',\n '--sp-text-muted': '#82828b',\n '--sp-text-dim': '#6b6b74',\n '--sp-text-body': '#a1a1aa',\n '--sp-positive': '#6ee7b7',\n '--sp-cta-bg': '#fff',\n '--sp-cta-text': '#09090b',\n '--sp-divider': 'rgba(255,255,255,0.06)',\n '--sp-code-bg': 'rgba(255,255,255,0.07)',\n '--sp-code-border': 'rgba(255,255,255,0.08)',\n '--sp-pre-bg': 'rgba(0,0,0,0.4)',\n };\n}\n\n/**\n * Prose and layout rules, scoped to the same class so the package ships no global classes.\n *\n * `unit` exists because the app's server renderer sizes in rem and this package sizes in px.\n * 20px and 1.25rem are the same length at a 16px base, so this is not a design difference, but\n * the two were separate string literals and separate string literals drift.\n */\nfunction rules(unit: 'px' | 'rem'): string {\n const gap = unit === 'px' ? '20px' : '1.25rem';\n return [\n '.sp-root .sp-prose p{margin-bottom:.625rem}',\n '.sp-root .sp-prose p:last-child{margin-bottom:0}',\n '.sp-root .sp-prose ul{list-style:disc;padding-left:1.25rem;margin-bottom:.625rem}',\n '.sp-root .sp-prose ol{list-style:decimal;padding-left:1.25rem;margin-bottom:.625rem}',\n '.sp-root .sp-prose li{margin-bottom:.25rem}',\n '.sp-root .sp-prose strong{color:var(--sp-text-strong);font-weight:600}',\n '.sp-root .sp-prose h2,.sp-root .sp-prose h3{color:var(--sp-text);font-weight:600;margin:.875rem 0 .375rem;font-size:1rem}',\n '.sp-root .sp-prose code{background:var(--sp-code-bg);border:1px solid var(--sp-code-border);padding:.1rem .35rem;border-radius:.25rem;font-size:.82em;color:var(--sp-text)}',\n '.sp-root .sp-prose blockquote{border-left:3px solid var(--sp-border);padding-left:1rem;color:var(--sp-text-muted);margin:.75rem 0}',\n `.sp-root .sp-pair{display:grid;grid-template-columns:1fr 1fr;gap:${gap}}`,\n '@media(max-width:640px){.sp-root .sp-pair{grid-template-columns:1fr}}',\n ].join('');\n}\n\n/**\n * Returns the stylesheet a renderer injects.\n *\n * @param accent brand colour. Accepts anything CSS does; `--sp-accent-bg` and\n * `--sp-accent-border` are derived from it so a customer sets one value\n * rather than three. Defaults to DEFAULT_ACCENT.\n * @param unit length unit for layout rules. 'px' for this package, 'rem' for the app's\n * server renderer, which sizes in rem throughout.\n * @param scope selector the custom properties are declared on. Defaults to `.sp-root`, which is\n * what a renderer injecting this at runtime wants. `tokens.css` is generated with\n * STYLESHEET_SCOPE instead, so importing it works without a wrapper.\n */\nexport function buildTokenCss({ accent, unit = 'px', scope = `.${SP_ROOT}`, theme = 'dark' }: { accent?: string; unit?: 'px' | 'rem'; scope?: string; theme?: SpTheme } = {}): string {\n const resolved = accent ?? (theme === 'light' ? DEFAULT_ACCENT_LIGHT : DEFAULT_ACCENT);\n const decls = Object.entries(palette(resolved, theme)).map(([k, v]) => `${k}:${v}`).join(';');\n return `${scope}{${decls}}${rules(unit)}`;\n}\n"],"mappings":"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","names":["DOMPurify","import_jsx_runtime","res","_a"]}
|
package/dist/index.js
CHANGED
|
@@ -78,8 +78,11 @@ function palette(accent, theme) {
|
|
|
78
78
|
"--sp-surface": "#09090b",
|
|
79
79
|
"--sp-border": "#27272a",
|
|
80
80
|
"--sp-text": "#f4f4f5",
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
// Body prose colour. Was #d4d4d8, judged too grey against near-black at reading
|
|
82
|
+
// sizes; one step brighter keeps the hierarchy below --sp-text while reading as
|
|
83
|
+
// text rather than chrome.
|
|
84
|
+
"--sp-text-sub": "#e4e4e7",
|
|
85
|
+
"--sp-text-strong": "#ececee",
|
|
83
86
|
"--sp-text-muted": "#82828b",
|
|
84
87
|
"--sp-text-dim": "#6b6b74",
|
|
85
88
|
"--sp-text-body": "#a1a1aa",
|
|
@@ -169,27 +172,23 @@ function AtomCard({ title, content, summary, layout, stats = [], ctaText, ctaUrl
|
|
|
169
172
|
if (variant === "card") {
|
|
170
173
|
const face = (summary == null ? void 0 : summary.trim()) || (content ? `${content.replace(/\s+/g, " ").split(/(?<=[.!?])\s/)[0]}` : "");
|
|
171
174
|
return /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(20) }, children: [
|
|
172
|
-
title && /* @__PURE__ */ jsx("h3", { style: { fontSize: u(
|
|
173
|
-
face && /* @__PURE__ */ jsx("p", { style: { fontSize: u(
|
|
175
|
+
title && /* @__PURE__ */ jsx("h3", { style: { fontSize: u(18), fontWeight: 600, color: "var(--sp-text)", margin: 0, lineHeight: 1.35 }, children: title }),
|
|
176
|
+
face && /* @__PURE__ */ jsx("p", { style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, margin: `${u(8)} 0 0` }, children: face }),
|
|
174
177
|
content && /* @__PURE__ */ jsxs("details", { style: { marginTop: u(10) }, children: [
|
|
175
|
-
/* @__PURE__ */ jsx("summary", { style: { cursor: "pointer", fontSize: u(
|
|
176
|
-
/* @__PURE__ */ jsx("div", { className: "sp-prose", style: { fontSize: u(
|
|
177
|
-
] }),
|
|
178
|
-
ctaText && ctaUrl && /* @__PURE__ */ jsxs("a", { href: ctaUrl, style: { display: "inline-flex", alignItems: "center", gap: u(4), marginTop: u(10), fontSize: u(13), fontWeight: 600, color: "var(--sp-accent)", textDecoration: "none" }, children: [
|
|
179
|
-
ctaText,
|
|
180
|
-
" \u2192"
|
|
178
|
+
/* @__PURE__ */ jsx("summary", { style: { cursor: "pointer", fontSize: u(14), fontWeight: 600, color: "var(--sp-accent)", listStyle: "none" }, children: "Read more" }),
|
|
179
|
+
/* @__PURE__ */ jsx("div", { className: "sp-prose", style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, marginTop: u(10) }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } })
|
|
181
180
|
] })
|
|
182
181
|
] });
|
|
183
182
|
}
|
|
184
183
|
const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;
|
|
185
184
|
const element = (name) => {
|
|
186
|
-
if (name === "title") return title ? /* @__PURE__ */ jsx("h3", { style: { fontSize: u(
|
|
187
|
-
if (name === "content") return content ? /* @__PURE__ */ jsx("div", { className: "sp-prose", style: { fontSize: u(
|
|
188
|
-
if (name === "stats") return stats.length ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: u(20), margin:
|
|
185
|
+
if (name === "title") return title ? /* @__PURE__ */ jsx("h3", { style: { fontSize: u(18), fontWeight: 600, color: "var(--sp-text)", margin: `0 0 ${u(12)}` }, children: title }, "title") : null;
|
|
186
|
+
if (name === "content") return content ? /* @__PURE__ */ jsx("div", { className: "sp-prose", style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, ...full ? {} : clampStyle }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } }, "content") : null;
|
|
187
|
+
if (name === "stats") return stats.length ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: u(20), margin: `${u(18)} 0 ${u(12)}`, padding: `0 0 ${u(14)}`, borderBottom: "1px solid var(--sp-border)" }, children: stats.map((s, i) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: u(2) }, children: [
|
|
189
188
|
/* @__PURE__ */ jsx("span", { style: { fontSize: u(22), fontWeight: 700, color: "var(--sp-text)", lineHeight: 1, fontVariantNumeric: "tabular-nums" }, children: s.value }),
|
|
190
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: u(
|
|
189
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: u(12), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: s.label })
|
|
191
190
|
] }, i)) }, "stats") : null;
|
|
192
|
-
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(
|
|
191
|
+
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(14), fontWeight: 600, color: "var(--sp-accent)", textDecoration: "none" }, children: [
|
|
193
192
|
ctaText,
|
|
194
193
|
" \u2192"
|
|
195
194
|
] }, "cta") : null;
|
|
@@ -202,10 +201,10 @@ function StatGrid({ stats = [], caption, unit = "px" }) {
|
|
|
202
201
|
const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;
|
|
203
202
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
204
203
|
/* @__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: [
|
|
205
|
-
/* @__PURE__ */ jsx("p", { style: { fontSize: u(
|
|
204
|
+
/* @__PURE__ */ jsx("p", { style: { fontSize: u(12), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em", margin: `0 0 ${u(12)}`, lineHeight: 1.3 }, children: label }),
|
|
206
205
|
/* @__PURE__ */ jsx("p", { style: { fontSize: u(20), fontWeight: 500, color: "var(--sp-text)", fontVariantNumeric: "tabular-nums", lineHeight: 1, margin: 0 }, children: value })
|
|
207
206
|
] }, label)) }),
|
|
208
|
-
caption && /* @__PURE__ */ jsx("p", { style: { fontSize: u(
|
|
207
|
+
caption && /* @__PURE__ */ jsx("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", margin: `${u(12)} 0 0` }, children: caption })
|
|
209
208
|
] });
|
|
210
209
|
}
|
|
211
210
|
function CodeBlock({ code, lang = "typescript", caption, unit = "px" }) {
|
|
@@ -223,14 +222,14 @@ function ComparisonTable({ brand = "Us", competitor, rows = [], unit = "px" }) {
|
|
|
223
222
|
const cell = { textAlign: "left", padding: `${u(12)} ${u(16)}` };
|
|
224
223
|
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: [
|
|
225
224
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { style: { borderBottom: "1px solid var(--sp-border)", background: "var(--sp-bg)" }, children: [
|
|
226
|
-
/* @__PURE__ */ jsx("th", { style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(
|
|
227
|
-
/* @__PURE__ */ jsx("th", { scope: "col", style: { ...cell, fontWeight: 600, color: "var(--sp-accent)", fontSize: u(
|
|
228
|
-
/* @__PURE__ */ jsx("th", { scope: "col", style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(
|
|
225
|
+
/* @__PURE__ */ jsx("th", { style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(13), width: "33%" } }),
|
|
226
|
+
/* @__PURE__ */ jsx("th", { scope: "col", style: { ...cell, fontWeight: 600, color: "var(--sp-accent)", fontSize: u(13) }, children: brand }),
|
|
227
|
+
/* @__PURE__ */ jsx("th", { scope: "col", style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(13) }, children: competitor })
|
|
229
228
|
] }) }),
|
|
230
229
|
/* @__PURE__ */ jsx("tbody", { children: rows.map(({ label, spectare, them }) => /* @__PURE__ */ jsxs("tr", { style: { borderBottom: "1px solid var(--sp-border)" }, children: [
|
|
231
|
-
/* @__PURE__ */ jsx("th", { scope: "row", style: { ...cell, fontSize: u(
|
|
232
|
-
/* @__PURE__ */ jsx("td", { style: { ...cell, fontSize: u(
|
|
233
|
-
/* @__PURE__ */ jsx("td", { style: { ...cell, fontSize: u(
|
|
230
|
+
/* @__PURE__ */ jsx("th", { scope: "row", style: { ...cell, fontSize: u(14), color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
|
|
231
|
+
/* @__PURE__ */ jsx("td", { style: { ...cell, fontSize: u(14), color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
|
|
232
|
+
/* @__PURE__ */ jsx("td", { style: { ...cell, fontSize: u(14), color: "var(--sp-text-muted)" }, children: them })
|
|
234
233
|
] }, label)) })
|
|
235
234
|
] }) }) });
|
|
236
235
|
}
|
|
@@ -240,7 +239,7 @@ function FeatureList({ items = [], unit = "px" }) {
|
|
|
240
239
|
/* @__PURE__ */ jsx("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: u(15), marginTop: u(2) }, children: "\u2713" }),
|
|
241
240
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
242
241
|
/* @__PURE__ */ jsx("p", { style: { fontSize: u(15), fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
|
|
243
|
-
sub && /* @__PURE__ */ jsx("p", { style: { fontSize: u(
|
|
242
|
+
sub && /* @__PURE__ */ jsx("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", lineHeight: 1.5, margin: `${u(4)} 0 0` }, children: sub })
|
|
244
243
|
] })
|
|
245
244
|
] }, text)) }) });
|
|
246
245
|
}
|
|
@@ -254,7 +253,7 @@ function TestimonialCard({ quote, name, role, company, unit = "px" }) {
|
|
|
254
253
|
] }),
|
|
255
254
|
/* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: u(16) }, children: [
|
|
256
255
|
/* @__PURE__ */ jsx("p", { style: { fontSize: u(14), fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
|
|
257
|
-
/* @__PURE__ */ jsxs("p", { style: { fontSize: u(
|
|
256
|
+
/* @__PURE__ */ jsxs("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", margin: `${u(2)} 0 0` }, children: [
|
|
258
257
|
role,
|
|
259
258
|
company ? `, ${company}` : ""
|
|
260
259
|
] })
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/PersonalisedSection.tsx","../src/ComponentRenderer.tsx","../src/types.ts","../src/tokens.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { ComponentRenderer } from './ComponentRenderer';\nimport { filterAssemblyByZone } from './types';\nimport type { ComponentAssembly, AssemblyZone } from './types';\n\ntype ConversionCheckResult =\n | { matched: false }\n | { matched: true; goalName: string | null; goalType: string; valueSelector: string | null; currencySelector: string | null; defaultCurrency: string };\n\n// The arrangement this visitor saw, kept per-org in sessionStorage so a conversion fired on a\n// later page can attribute itself to it. Shares its key with spectare.js and the SSR\n// VariantTracker, so whichever surface rendered last wins, which is the arrangement the\n// visitor actually saw.\nconst VARIANT_KEY = (orgSlug: string) => `_spectare_variant_${orgSlug}`;\n\nfunction readVariantId(orgSlug: string): string | null {\n try { return sessionStorage.getItem(VARIANT_KEY(orgSlug)); } catch { return null; }\n}\n\nfunction writeVariantId(orgSlug: string, variantId: string): void {\n try { sessionStorage.setItem(VARIANT_KEY(orgSlug), variantId); } catch { /* private browsing */ }\n}\n\n\nfunction buildSummary(pageHint: string, orgSlug: string): string {\n const parts: string[] = [pageHint];\n const referrer = document.referrer;\n if (referrer) parts.push(`Arrived from: ${referrer}`);\n const p = new URLSearchParams(window.location.search);\n const source = p.get('utm_source');\n const medium = p.get('utm_medium');\n const campaign = p.get('utm_campaign');\n const term = p.get('utm_term');\n if (source) parts.push(`Source: ${source}`);\n if (medium) parts.push(`Medium: ${medium}`);\n if (campaign) parts.push(`Campaign: ${campaign}`);\n if (term) parts.push(`Search term: ${term}`);\n try {\n const history = localStorage.getItem(`_spectare_visits_${orgSlug}`);\n if (history) parts.push(`Previously visited: ${history}`);\n } catch { /* private browsing */ }\n return parts.filter(Boolean).join('. ');\n}\n\n// Reconstructs the visitor's page journey from spectare.js visit history.\nfunction readVisitPath(orgSlug: string): string[] {\n try {\n const raw = JSON.parse(localStorage.getItem(`_spectare_visits_${orgSlug}`) || '[]') as Array<{ path?: string }>;\n const path: string[] = [];\n for (const v of raw) {\n if (typeof v?.path === 'string' && (!path.length || path[path.length - 1] !== v.path)) path.push(v.path);\n }\n const cur = window.location.pathname;\n if (!path.length || path[path.length - 1] !== cur) path.push(cur);\n return path;\n } catch { return []; }\n}\n\nfunction Shimmer() {\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <div style={{ height: '20px', background: 'rgba(39,39,42,0.6)', borderRadius: '8px', width: '75%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '100%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '83%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '67%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n </div>\n );\n}\n\nexport interface PersonalisedSectionProps {\n orgSlug: string;\n /** Base URL of your Spectare instance. Defaults to 'https://spectare.ai'. */\n baseUrl?: string;\n /** Your brand name, used in ComparisonTable column header. */\n brand?: string;\n pageHint?: string;\n className?: string;\n style?: React.CSSProperties;\n initialAssembly?: ComponentAssembly;\n initialIntent?: { audience: string; stage: string };\n /**\n * Seed conversion attribution with a server-rendered arrangement: pass the variantId that\n * /api/assemble/ssr returned alongside initialAssembly. Without it, a visit where the client\n * classification matches the server's (so no client render happens) has no variant for a\n * later conversion to credit.\n */\n initialVariantId?: string;\n /**\n * Explicit visitor-typed context (e.g. a demo input box). Bypasses the session token cache\n * and re-qualifies immediately with the direct flag, which the server cost-caps (cheaper\n * model on a cache miss) and never writes to the shared cache.\n */\n directSummary?: string;\n /** Render only components assigned to this zone. */\n zone?: AssemblyZone;\n /** Alignment for statement-style components, to match the host page. */\n align?: 'left' | 'center' | 'right';\n /**\n * Brand accent. Passed through to ComponentRenderer, which emits it into the scoped\n * token set. Defaults to #60a5fa (dark) or #2563eb (light).\n */\n accent?: string;\n /** dark (default) or light, matching your page's ground. See ComponentRenderer. */\n theme?: 'dark' | 'light';\n}\n\nexport function PersonalisedSection({\n orgSlug,\n baseUrl = 'https://spectare.ai',\n brand,\n pageHint,\n className,\n style,\n initialAssembly,\n initialIntent,\n initialVariantId,\n directSummary,\n zone,\n align,\n accent,\n theme,\n}: PersonalisedSectionProps) {\n const [assembly, setAssembly] = useState<ComponentAssembly>(initialAssembly ?? []);\n const [loading, setLoading] = useState(!initialAssembly);\n const [orgName, setOrgName] = useState<string | undefined>(undefined);\n const [debugMode, setDebugMode] = useState(false);\n const [debugIntent, setDebugIntent] = useState<{ audience: string; stage: string } | null>(null);\n const tokenRef = useRef<string | null>(null);\n const conversionFiredRef = useRef(false);\n\n useEffect(() => {\n setDebugMode(new URLSearchParams(window.location.search).has('spectare_debug'));\n if (initialIntent) setDebugIntent(initialIntent);\n }, [initialIntent]);\n\n // Seed sessionStorage with the server-rendered variantId so conversions attribute correctly\n // even when the client assembly matches the SSR one and no client fetch replaces it.\n useEffect(() => {\n if (initialVariantId) writeVariantId(orgSlug, initialVariantId);\n }, [orgSlug, initialVariantId]);\n\n useEffect(() => {\n let cancelled = false;\n\n async function load() {\n try {\n let token: string | null = null;\n\n if (directSummary) {\n // Explicit visitor input: skip the token cache, re-qualify immediately with direct.\n setLoading(true);\n setAssembly([]);\n const res = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary: directSummary, direct: true }),\n });\n if (!res.ok || cancelled) { setLoading(false); return; }\n const data = await res.json();\n token = (data.token as string | undefined) ?? null;\n } else {\n // Key includes UTM params so a visitor arriving via a campaign link always\n // re-qualifies rather than reusing a token from a prior session context.\n const p = new URLSearchParams(window.location.search);\n const utmSuffix = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term']\n .map(k => p.get(k) ?? '').filter(Boolean).join('_');\n const tokenKey = `_spectare_token_${orgSlug}${utmSuffix ? '_' + utmSuffix : ''}`;\n token = sessionStorage.getItem(tokenKey);\n\n if (!token) {\n const summary = buildSummary(pageHint ?? `Visiting ${document.title}`, orgSlug);\n const res = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary }),\n });\n if (!res.ok || cancelled) { setLoading(false); return; }\n const data = await res.json();\n token = data.token as string | undefined ?? null;\n if (token) sessionStorage.setItem(tokenKey, token);\n if (data.orgName) setOrgName(data.orgName as string);\n }\n }\n\n if (!token || cancelled) { setLoading(false); return; }\n\n tokenRef.current = token;\n let res = await fetch(`${baseUrl}/api/assemble/components`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n // Direct: flag it so the server cost-caps the build, and omit the seen-variant\n // exclusion so it can read the shared cache instead of forcing a fresh build.\n body: JSON.stringify(\n directSummary\n ? { token, orgSlug, direct: true }\n : { token, orgSlug, excludeVariantId: readVariantId(orgSlug) },\n ),\n });\n\n if (res.status === 401 && !cancelled && !directSummary) {\n // Cached token expired: clear it, re-qualify, and retry once.\n const p = new URLSearchParams(window.location.search);\n const utmSuffix = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term']\n .map(k => p.get(k) ?? '').filter(Boolean).join('_');\n const tokenKey = `_spectare_token_${orgSlug}${utmSuffix ? '_' + utmSuffix : ''}`;\n sessionStorage.removeItem(tokenKey);\n const summary = buildSummary(pageHint ?? `Visiting ${document.title}`, orgSlug);\n const qRes = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary }),\n });\n if (!qRes.ok || cancelled) { setLoading(false); return; }\n const qData = await qRes.json();\n token = qData.token as string | undefined ?? null;\n if (token) {\n sessionStorage.setItem(tokenKey, token);\n tokenRef.current = token;\n }\n if (!token || cancelled) { setLoading(false); return; }\n res = await fetch(`${baseUrl}/api/assemble/components`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, orgSlug, excludeVariantId: readVariantId(orgSlug) }),\n });\n }\n\n if (!res.ok || cancelled) { setLoading(false); return; }\n\n const contentType = res.headers.get('content-type') ?? '';\n\n if (contentType.includes('text/event-stream')) {\n // Cold path: stream components as Claude generates them.\n // Render progressively — shimmer shows until the first component arrives.\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n let loadingCleared = false;\n try {\n while (!cancelled) {\n const { done, value } = await reader.read();\n if (done || cancelled) break;\n buf += decoder.decode(value, { stream: true });\n const lines = buf.split('\\n');\n buf = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue;\n const payload = line.slice(6).trim();\n if (payload === '[DONE]') break;\n try {\n const parsed = JSON.parse(payload) as Record<string, unknown>;\n // Control frames: {_variant} carries attribution, {_error} means the stream\n // died server-side. Neither is a component; pushing them into the assembly\n // recorded a phantom entry the renderer silently skipped.\n if (parsed._variant && typeof parsed._variant === 'string') {\n writeVariantId(orgSlug, parsed._variant);\n continue;\n }\n if (parsed._error) {\n if (!loadingCleared) { setLoading(false); loadingCleared = true; }\n continue;\n }\n if (!parsed.component) continue;\n const comp = parsed as unknown as ComponentAssembly[0];\n if (!loadingCleared) { setLoading(false); loadingCleared = true; }\n setAssembly(prev => [...prev, comp]);\n } catch { /* malformed event — skip */ }\n }\n }\n } finally {\n reader.cancel().catch(() => {});\n }\n } else {\n // Warm path: cache hit returns full JSON immediately.\n const data = await res.json() as {\n assembly?: ComponentAssembly;\n intent?: { userContext?: { audience?: string; stage?: string } };\n variantId?: string;\n };\n if (data.variantId) writeVariantId(orgSlug, data.variantId);\n\n if (cancelled) return;\n\n const clientAudience = data.intent?.userContext?.audience;\n const clientStage = data.intent?.userContext?.stage;\n const ssrMatches =\n initialIntent &&\n clientAudience === initialIntent.audience &&\n clientStage === initialIntent.stage;\n\n if (clientAudience && clientStage) {\n setDebugIntent({ audience: clientAudience, stage: clientStage });\n }\n\n if (!ssrMatches && Array.isArray(data.assembly) && data.assembly.length > 0) {\n setAssembly(data.assembly as ComponentAssembly);\n }\n }\n } catch {\n // fail silently\n } finally {\n if (!cancelled) setLoading(false);\n }\n }\n\n load();\n return () => { cancelled = true; };\n }, [orgSlug, baseUrl, pageHint, initialAssembly, initialIntent, directSummary]);\n\n useEffect(() => {\n if (!assembly.length || conversionFiredRef.current) return;\n const token = tokenRef.current;\n if (!token) return;\n const url = window.location.href;\n fetch(`${baseUrl}/api/conversion-check`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ orgSlug, url }),\n }).then(r => r.json() as Promise<ConversionCheckResult>).then(data => {\n if (!data.matched) return;\n conversionFiredRef.current = true;\n let goalValue: number | null = null;\n let goalCurrency: string | null = data.defaultCurrency;\n if (data.valueSelector) {\n try {\n const el = document.querySelector(data.valueSelector);\n if (el) {\n const num = parseFloat((el.textContent ?? '').trim().replace(/[^0-9.]/g, ''));\n if (!isNaN(num)) goalValue = num;\n }\n } catch { /* skip */ }\n }\n if (data.currencySelector) {\n try {\n const el = document.querySelector(data.currencySelector);\n if (el) goalCurrency = (el.textContent ?? '').trim() || goalCurrency;\n } catch { /* skip */ }\n }\n const atomsShown = [...new Set(assembly.flatMap(i => i.sourceAtomIds ?? []))];\n const visitPath = readVisitPath(orgSlug);\n fetch(`${baseUrl}/api/conversion`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n token,\n orgSlug,\n url,\n variantId: readVariantId(orgSlug),\n ...(atomsShown.length ? { atomsShown } : {}),\n ...(visitPath.length > 1 ? { visitPath } : {}),\n ...(data.goalName ? { goalName: data.goalName } : {}),\n ...(goalValue !== null ? { goalValue, goalCurrency } : {}),\n }),\n }).catch(() => {});\n }).catch(() => {});\n }, [assembly, orgSlug, baseUrl]);\n\n if (!loading && assembly.length === 0) return null;\n\n // ?spectare_debug outlines the section and names the classified intent, so anyone checking\n // an integration can see where personalisation lands and what the visitor was read as.\n const debugStyle = debugMode\n ? { outline: '2px solid rgba(96,165,250,0.5)', borderRadius: '0.5rem', position: 'relative' as const, padding: '0.5rem', ...style }\n : style;\n\n return (\n <>\n <style dangerouslySetInnerHTML={{ __html: '@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}' }} />\n <div className={className} style={debugStyle}>\n {debugMode && (\n <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' }}>\n Personalised by Spectare\n {debugIntent && (\n <span style={{ opacity: 0.75 }}>\n {' '}{debugIntent.audience}/{debugIntent.stage}\n </span>\n )}\n </div>\n )}\n {loading && assembly.length === 0\n ? <Shimmer />\n : <ComponentRenderer assembly={zone ? filterAssemblyByZone(assembly, zone) : assembly} brand={brand ?? orgName} align={align} accent={accent} theme={theme} />}\n </div>\n </>\n );\n}\n","// Universal renderer: deliberately NO 'use client' in this source file. Nothing here uses hooks, state, or event\n// handlers, so the same file renders as a React Server Component (zero JS shipped, how the\n// Spectare app uses it via components/ServerAssemblyRenderer.tsx) and inside a client tree\n// (how PersonalisedSection uses it). Adding a hook or handler here would silently force every\n// server consumer to ship and hydrate it: keep interactivity in wrappers.\n//\n// Sizing is numeric, scaled through u(): px for embedded hosts (predictable inside arbitrary\n// pages) or rem for hosts that want to track the reader's font-size preference (the Spectare\n// site). Until 2026-08-31 the rem variant was a hand-maintained mirror of this file, and the\n// two drifted a pixel apart in six places; one number set, one scale function, no mirror.\nimport { marked } from 'marked';\nimport DOMPurify from 'isomorphic-dompurify';\nimport { filterAssemblyByZone, COMPONENT_CATEGORIES } from './types';\nimport { buildTokenCss, SP_ROOT } from './tokens';\nimport type { SpTheme } from './tokens';\nimport type { ComponentAssembly, ComponentName, AssemblyZone } from './types';\n\n// The assembly API returns atom content as raw markdown. marked emits raw HTML,\n// so the output must be sanitised before it reaches dangerouslySetInnerHTML,\n// otherwise a malicious atom can run script in the host site's visitors' browsers.\nfunction renderMarkdown(content: string): string {\n const raw = marked.parse(content ?? '', { async: false }) as string;\n return DOMPurify.sanitize(raw, { USE_PROFILES: { html: true } });\n}\n\nexport type Unit = 'px' | 'rem';\ntype U = (n: number) => string;\nconst scaler = (unit: Unit): U => (n: number) => (unit === 'rem' ? `${n / 16}rem` : `${n}px`);\nconst PX = scaler('px');\n\n// Default half-size components: used when assembly item omits size.\nconst HALF_COMPONENTS = new Set<ComponentName>(['TestimonialCard']);\n\n// ── Individual component renderers ────────────────────────────────────────────\n\n// Alignment is a host decision, not baked into a component: the host passes `align`\n// and statement-style components adopt it. flexItems maps it to a flex alignment so\n// block children (a max-width subheading, an inline CTA) align too, not just the text.\ntype Align = 'left' | 'center' | 'right';\nconst flexItems = (a: Align): 'flex-start' | 'center' | 'flex-end' =>\n a === 'center' ? 'center' : a === 'right' ? 'flex-end' : 'flex-start';\n\n/**\n * A single line above everything else. Deliberately the plainest component in the set: no\n * heading, no image, no padding to speak of. A bar that draws attention to itself competes with\n * the page it is announcing something about.\n *\n * Uses the accent rather than a red or amber alert colour. This is a fact worth knowing, not a\n * warning, and a venue putting \"members book from Thursday\" in an alarm colour reads as a problem\n * rather than an offer.\n */\nexport function AnnouncementBar({ text, link, unit = 'px' }: { text?: string; link?: { label: string; href: string }; unit?: Unit }) {\n const u = scaler(unit);\n if (!text) return null;\n return (\n <div style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center', gap: u(10),\n flexWrap: 'wrap', textAlign: 'center',\n background: 'var(--sp-accent-bg)', border: '1px solid var(--sp-accent-border)',\n borderRadius: u(8), padding: `${u(8)} ${u(16)}`, fontSize: u(14), lineHeight: 1.4,\n color: 'var(--sp-text-sub)',\n }}>\n <span>{text}</span>\n {link?.href && link?.label && (\n <a href={link.href} style={{ color: 'var(--sp-accent)', fontWeight: 600, textDecoration: 'none', whiteSpace: 'nowrap' }}>\n {link.label} →\n </a>\n )}\n </div>\n );\n}\n\nexport function HeroStatement({ headline, subheading, align = 'left', unit = 'px' }: { headline: string; subheading?: string; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: flexItems(align), textAlign: align, paddingTop: u(24), paddingBottom: u(24) }}>\n <h2 style={{ fontSize: u(32), fontWeight: 700, letterSpacing: '-0.025em', lineHeight: 1.2, color: 'var(--sp-text)', margin: `0 0 ${u(12)}` }}>\n {headline}\n </h2>\n {subheading && (\n <p style={{ fontSize: u(18), color: 'var(--sp-text-sub)', lineHeight: 1.6, maxWidth: u(672), margin: 0 }}>{subheading}</p>\n )}\n </div>\n );\n}\n\n// The atom owns title / content / stats / cta; its layout decides which appear and in\n// what order. Default order when the atom has no layout. Mirrors the atom editor.\nconst ATOM_LAYOUT_DEFAULT = ['title', 'content', 'stats', 'cta'];\n\n// Clamp atom prose unless the assembly asked for the full body. CSS rather than an expand\n// toggle, so the identical rule works here (including server-rendered with no JS), in\n// spectare.js and in the WordPress plugin.\nexport const ATOM_CLAMP_LINES = 4;\nconst clampStyle = {\n display: '-webkit-box',\n WebkitLineClamp: ATOM_CLAMP_LINES,\n WebkitBoxOrient: 'vertical' as const,\n overflow: 'hidden',\n};\n\nexport function AtomCard(\n { title, content, summary, layout, stats = [], ctaText, ctaUrl, full, variant, unit = 'px' }:\n { title?: string; content?: string; summary?: string; layout?: string[]; stats?: { value: string; label: string }[]; ctaText?: string; ctaUrl?: string; full?: boolean; variant?: string; unit?: Unit },\n) {\n const u = scaler(unit);\n\n // The card face: title, one-sentence summary, and the full body behind a native <details>\n // disclosure. <details> is the one expand that needs no JavaScript, so it works identically\n // in a server component, a client tree, and any host page; nothing is ever unreachable on a\n // site that has no per-atom pages. The Spectare app substitutes its own card face (which\n // links to the atom's page) via renderOverride, so this is the everywhere-else rendering.\n if (variant === 'card') {\n const face = summary?.trim() || (content ? `${content.replace(/\\s+/g, ' ').split(/(?<=[.!?])\\s/)[0]}` : '');\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(20) }}>\n {title && <h3 style={{ fontSize: u(16), fontWeight: 600, color: 'var(--sp-text)', margin: 0, lineHeight: 1.35 }}>{title}</h3>}\n {face && <p style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, margin: `${u(8)} 0 0` }}>{face}</p>}\n {content && (\n <details style={{ marginTop: u(10) }}>\n <summary style={{ cursor: 'pointer', fontSize: u(13), fontWeight: 600, color: 'var(--sp-accent)', listStyle: 'none' }}>Read more</summary>\n <div className=\"sp-prose\" style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, marginTop: u(10) }} dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} />\n </details>\n )}\n {ctaText && ctaUrl && (\n <a href={ctaUrl} style={{ display: 'inline-flex', alignItems: 'center', gap: u(4), marginTop: u(10), fontSize: u(13), fontWeight: 600, color: 'var(--sp-accent)', textDecoration: 'none' }}>{ctaText} →</a>\n )}\n </div>\n );\n }\n\n const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;\n const element = (name: string) => {\n if (name === 'title') return title\n ? <h3 key=\"title\" style={{ fontSize: u(16), fontWeight: 600, color: 'var(--sp-text)', margin: `0 0 ${u(12)}` }}>{title}</h3> : null;\n if (name === 'content') return content\n ? <div key=\"content\" className=\"sp-prose\" style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, ...(full ? {} : clampStyle) }} dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} /> : null;\n if (name === 'stats') return stats.length\n ? (\n <div key=\"stats\" style={{ display: 'flex', flexWrap: 'wrap', gap: u(20), margin: `0 0 ${u(12)}`, paddingBottom: u(12), borderBottom: '1px solid var(--sp-border)' }}>\n {stats.map((s, i) => (\n <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: u(2) }}>\n <span style={{ fontSize: u(22), fontWeight: 700, color: 'var(--sp-text)', lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>{s.value}</span>\n <span style={{ fontSize: u(11), color: 'var(--sp-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>{s.label}</span>\n </div>\n ))}\n </div>\n ) : null;\n if (name === 'cta') return ctaText && ctaUrl\n ? <a key=\"cta\" 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' }}>{ctaText} →</a> : null;\n return null;\n };\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(24), height: '100%' }}>\n {order.map(element)}\n </div>\n );\n}\n\nexport function StatGrid({ stats = [], caption, unit = 'px' }: { stats?: { value: string; label: string }[]; caption?: string; unit?: Unit }) {\n const u = scaler(unit);\n const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;\n return (\n <div>\n <div style={{ display: 'grid', gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: u(12) }}>\n {stats.map(({ value, label }) => (\n <div key={label} 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) }}>\n <p style={{ fontSize: u(11), color: 'var(--sp-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em', margin: `0 0 ${u(12)}`, lineHeight: 1.3 }}>{label}</p>\n <p style={{ fontSize: u(20), fontWeight: 500, color: 'var(--sp-text)', fontVariantNumeric: 'tabular-nums', lineHeight: 1, margin: 0 }}>{value}</p>\n </div>\n ))}\n </div>\n {caption && (\n <p style={{ fontSize: u(13), color: 'var(--sp-text-muted)', margin: `${u(12)} 0 0` }}>{caption}</p>\n )}\n </div>\n );\n}\n\nexport function CodeBlock({ code, lang = 'typescript', caption, unit = 'px' }: { code: string; lang?: string; caption?: string; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ borderRadius: u(12), overflow: 'hidden', border: '1px solid var(--sp-border)' }}>\n <div style={{ background: 'var(--sp-bg)', padding: `${u(10)} ${u(16)}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: '1px solid var(--sp-border)' }}>\n <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)', fontFamily: 'monospace' }}>{lang}</span>\n {caption && <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)' }}>{caption}</span>}\n </div>\n <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 }}>\n {code}\n </pre>\n </div>\n );\n}\n\nexport function ComparisonTable({ brand = 'Us', competitor, rows = [], unit = 'px' }: { brand?: string; competitor: string; rows?: { label: string; spectare: string; them: string }[]; unit?: Unit }) {\n const u = scaler(unit);\n const cell = { textAlign: 'left' as const, padding: `${u(12)} ${u(16)}` };\n return (\n <div style={{ border: '1px solid var(--sp-border)', borderRadius: u(12), overflow: 'hidden' }}>\n <div style={{ overflowX: 'auto' }}>\n <table style={{ width: '100%', fontSize: u(14), borderCollapse: 'collapse' }}>\n <thead>\n <tr style={{ borderBottom: '1px solid var(--sp-border)', background: 'var(--sp-bg)' }}>\n <th style={{ ...cell, color: 'var(--sp-text-muted)', fontWeight: 500, fontSize: u(12), width: '33%' }} />\n <th scope=\"col\" style={{ ...cell, fontWeight: 600, color: 'var(--sp-accent)', fontSize: u(12) }}>{brand}</th>\n <th scope=\"col\" style={{ ...cell, color: 'var(--sp-text-muted)', fontWeight: 500, fontSize: u(12) }}>{competitor}</th>\n </tr>\n </thead>\n <tbody>\n {rows.map(({ label, spectare, them }) => (\n <tr key={label} style={{ borderBottom: '1px solid var(--sp-border)' }}>\n <th scope=\"row\" style={{ ...cell, fontSize: u(13), color: 'var(--sp-text-muted)', fontWeight: 500 }}>{label}</th>\n <td style={{ ...cell, fontSize: u(13), color: 'var(--sp-positive)', fontWeight: 500 }}>{spectare}</td>\n <td style={{ ...cell, fontSize: u(13), color: 'var(--sp-text-muted)' }}>{them}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nexport function FeatureList({ items = [], unit = 'px' }: { items?: { text: string; sub?: string }[]; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(24) }}>\n <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: u(16) }}>\n {items.map(({ text, sub }) => (\n <li key={text} style={{ display: 'flex', gap: u(12) }}>\n <span style={{ color: 'var(--sp-accent)', flexShrink: 0, fontSize: u(15), marginTop: u(2) }}>✓</span>\n <div>\n <p style={{ fontSize: u(15), fontWeight: 500, color: 'var(--sp-text)', lineHeight: 1.4, margin: 0 }}>{text}</p>\n {sub && <p style={{ fontSize: u(13), color: 'var(--sp-text-muted)', lineHeight: 1.5, margin: `${u(4)} 0 0` }}>{sub}</p>}\n </div>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport function TestimonialCard({ quote, name, role, company, unit = 'px' }: { quote: string; name: string; role: string; company?: string; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <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%' }}>\n <p style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, flex: 1, margin: 0 }}>\n <span style={{ color: 'var(--sp-text-dim)', fontSize: u(18), lineHeight: 1, marginRight: u(4) }}>\"</span>\n {quote}\n <span style={{ color: 'var(--sp-text-dim)', fontSize: u(18), lineHeight: 1, marginLeft: u(4) }}>\"</span>\n </p>\n <div style={{ borderTop: '1px solid var(--sp-border)', paddingTop: u(16) }}>\n <p style={{ fontSize: u(14), fontWeight: 600, color: 'var(--sp-text)', margin: 0 }}>{name}</p>\n <p style={{ fontSize: u(13), color: 'var(--sp-text-muted)', margin: `${u(2)} 0 0` }}>\n {role}{company ? `, ${company}` : ''}\n </p>\n </div>\n </div>\n );\n}\n\nexport function ImageCtaHero({ src, alt = '', headline, subheading, ctaLabel, ctaHref, align = 'left', unit = 'px' }: { src?: string; alt?: string; headline?: string; subheading?: string; ctaLabel?: string; ctaHref?: string; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n if (!src) return null;\n return (\n <div style={{ borderRadius: u(12), overflow: 'hidden', position: 'relative', width: '100%', paddingBottom: '56.25%' }}>\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={src} alt={alt} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />\n <div style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.45)' }} />\n <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%)' }} />\n <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: u(28), textAlign: align }}>\n {headline && (\n <h2 style={{ fontSize: u(24), fontWeight: 700, color: '#fff', lineHeight: 1.2, margin: `0 0 ${u(8)}`, letterSpacing: '-0.02em' }}>{headline}</h2>\n )}\n {subheading && (\n <p style={{ fontSize: u(15), color: 'rgba(255,255,255,0.75)', lineHeight: 1.5, margin: `0 0 ${u(20)}` }}>{subheading}</p>\n )}\n {ctaHref && ctaLabel && (\n <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' }}>\n {ctaLabel}\n </a>\n )}\n </div>\n </div>\n );\n}\n\nexport function CtaStrip({ headline, primary, secondary, align = 'center', unit = 'px' }: { headline: string; primary: { label: string; href: string }; secondary?: { label: string; href: string }; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(32), textAlign: align, background: 'var(--sp-bg)' }}>\n <h3 style={{ fontSize: u(24), fontWeight: 700, color: 'var(--sp-text)', margin: `0 0 ${u(24)}` }}>{headline}</h3>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: flexItems(align), gap: u(16), flexWrap: 'wrap' }}>\n <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' }}>\n {primary.label}\n </a>\n {secondary && (\n <a href={secondary.href} style={{ fontSize: u(15), color: 'var(--sp-text-sub)', textDecoration: 'none' }}>\n {secondary.label} →\n </a>\n )}\n </div>\n </div>\n );\n}\n\n// ── Dispatch ──────────────────────────────────────────────────────────────────\n\nfunction renderSingle(item: ComponentAssembly[0], brand?: string, align?: Align, unit: Unit = 'px'): React.ReactNode {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const s = item.slots as Record<string, any> ?? {};\n\n switch (item.component as ComponentName) {\n case 'AnnouncementBar': return <AnnouncementBar text={s.text} link={s.link} unit={unit} />;\n case 'HeroStatement': return <HeroStatement headline={s.headline} subheading={s.subheading} align={align} unit={unit} />;\n // A full-width card has nothing beside it, so there is nothing for a clamp to protect.\n case 'AtomCard': return <AtomCard title={s.title} content={s.content} summary={s.summary} layout={s.layout} stats={s.stats} ctaText={s.ctaText} ctaUrl={s.ctaUrl} full={s.full || resolvedSize(item) === 'full'} variant={s.variant} unit={unit} />;\n case 'StatGrid': return <StatGrid stats={s.stats} caption={s.caption} unit={unit} />;\n case 'CodeBlock': return <CodeBlock code={s.code} lang={s.lang} caption={s.caption} unit={unit} />;\n case 'ComparisonTable': return <ComparisonTable brand={s.brand ?? brand} competitor={s.competitor} rows={s.rows} unit={unit} />;\n case 'FeatureList': return <FeatureList items={s.items} unit={unit} />;\n case 'TestimonialCard': return <TestimonialCard quote={s.quote} name={s.name} role={s.role} company={s.company} unit={unit} />;\n case 'ImageCtaHero': return <ImageCtaHero src={s.src} alt={s.alt} headline={s.headline} subheading={s.subheading} ctaLabel={s.ctaLabel} ctaHref={s.ctaHref} align={align} unit={unit} />;\n case 'CtaStrip': return <CtaStrip headline={s.headline} primary={s.primary} secondary={s.secondary} align={align} unit={unit} />;\n // An unrecognised component name used to render nothing at all. A component needs a\n // renderer here plus spectare.js plus the WordPress plugin, so missing one made its content\n // silently absent on that surface only: no error, no warning, just a shorter page that\n // looks deliberate. That is the failure mode to remove before the registry grows.\n //\n // Falls back to AtomCard when the slots carry something readable, since almost every\n // component is built from an atom and title/content is the shape they share. When there\n // is genuinely nothing to show it still renders nothing, because an empty card is worse\n // than a gap, but the warning fires either way.\n default: {\n console.warn(`[spectare] ComponentRenderer: no renderer for \"${item.component}\", falling back to AtomCard`);\n if (!s.title && !s.content) return null;\n return <AtomCard title={s.title} content={s.content} stats={s.stats} ctaText={s.ctaText} ctaUrl={s.ctaUrl} full unit={unit} />;\n }\n }\n}\n\n// ── Layout ────────────────────────────────────────────────────────────────────\n\nfunction resolvedSize(item: ComponentAssembly[0]): 'full' | 'half' {\n if (item.size) return item.size;\n return HALF_COMPONENTS.has(item.component as ComponentName) ? 'half' : 'full';\n}\n\ntype LayoutGroup =\n | { type: 'full'; item: ComponentAssembly[0] }\n | { type: 'pair'; items: [ComponentAssembly[0], ComponentAssembly[0]] }\n | { type: 'half-solo'; item: ComponentAssembly[0] };\n\n// Two half-width components only sit side by side well if they read at the same speed. A\n// prose block beside a scannable list forces the eye to switch modes, and the grid stretches\n// the shorter one, leaving dead space. Registry category is the available proxy for reading\n// mode, so pair within a category and give anything else its own row.\nfunction pairable(a: ComponentAssembly[0], b: ComponentAssembly[0]): boolean {\n const catOf = (x: ComponentAssembly[0]) =>\n COMPONENT_CATEGORIES[x.component as ComponentName];\n const ca = catOf(a);\n const cb = catOf(b);\n return ca !== undefined && ca === cb;\n}\n\nfunction buildLayout(assembly: ComponentAssembly): LayoutGroup[] {\n const groups: LayoutGroup[] = [];\n let i = 0;\n while (i < assembly.length) {\n const cur = assembly[i];\n const next = assembly[i + 1];\n if (resolvedSize(cur) === 'half' && next && resolvedSize(next) === 'half' && pairable(cur, next)) {\n groups.push({ type: 'pair', items: [cur, next] });\n i += 2;\n } else if (resolvedSize(cur) === 'half') {\n groups.push({ type: 'half-solo', item: cur });\n i++;\n } else {\n groups.push({ type: 'full', item: cur });\n i++;\n }\n }\n return groups;\n}\n\n// ── X-ray badge ───────────────────────────────────────────────────────────────\n\nfunction XrayBadge({ name, size }: { name: string; size: string }) {\n return (\n <div style={{ position: 'absolute', top: PX(8), left: PX(8), zIndex: 10, display: 'flex', alignItems: 'center', gap: PX(6), pointerEvents: 'none', userSelect: 'none' }}>\n <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 }}>{name}</span>\n <span style={{ fontSize: PX(10), fontFamily: 'monospace', color: '#71717a', lineHeight: 1 }}>{size}</span>\n </div>\n );\n}\n\n// ── Main export ───────────────────────────────────────────────────────────────\n\nexport interface ComponentRendererProps {\n assembly: ComponentAssembly;\n /** Your brand name, used as the left column header in ComparisonTable. Defaults to \"Us\". */\n brand?: string;\n /** Overlay a component name badge on each item. Useful for demos and debugging. */\n xray?: boolean;\n /** Render only components assigned to this zone. */\n zone?: AssemblyZone;\n /**\n * Alignment for statement-style components (HeroStatement, CtaStrip, ImageCtaHero),\n * so assembled content can match the host page. Omit to use each component's natural\n * default (HeroStatement left, CtaStrip centered).\n */\n align?: 'left' | 'center' | 'right';\n /**\n * Brand accent, as an explicit input rather than a custom property you override and hope\n * wins on tag order. Any CSS colour. `--sp-accent-bg` and `--sp-accent-border` are derived\n * from it, so one value covers all three. Defaults to #60a5fa.\n */\n accent?: string;\n /**\n * dark (default) is the package's original near-black card set. light renders white cards\n * with a dark text ramp for light host pages; without it the components paint near-white\n * text and near-black slabs onto a light ground. Both palettes hold the same contrast\n * floors (see tests/unit/token-contrast.test.ts).\n */\n theme?: SpTheme;\n /**\n * px (default) sizes components absolutely, predictable inside arbitrary host pages.\n * rem tracks the reader's font-size preference; the root then also inherits the host's\n * font size instead of pinning 16px.\n */\n unit?: Unit;\n /**\n * Substitute rendering for an item: return a node to replace the built-in renderer\n * (including null to render nothing), or undefined to keep the default. How the Spectare\n * app swaps the card-variant AtomCard for its server-rendered card face.\n */\n renderOverride?: (item: ComponentAssembly[0]) => React.ReactNode | undefined;\n /**\n * Wrap each rendered item, e.g. with source attribution or a debug badge. Receives the\n * assembly item and its rendered node; whatever it returns is placed in the layout.\n */\n renderItem?: (item: ComponentAssembly[0], rendered: React.ReactNode) => React.ReactNode;\n /** Extra attributes for the root element (e.g. a data marker a host overlay targets). */\n rootProps?: Record<string, unknown>;\n}\n\n\nexport function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent, theme, unit = 'px', renderOverride, renderItem, rootProps }: ComponentRendererProps) {\n const u = scaler(unit);\n const filtered = zone ? filterAssemblyByZone(assembly, zone) : assembly;\n const layout = buildLayout(filtered);\n\n // Merge rather than spread-clobber: a host className joins sp-root instead of replacing it\n // (every --sp-* token is scoped to .sp-root, so losing it un-themes every component), and a\n // host style merges under the layout styles rather than being silently discarded.\n const { className: extraClass, style: extraStyle, ...restRoot } = (rootProps ?? {}) as { className?: string; style?: React.CSSProperties } & Record<string, unknown>;\n\n const renderOne = (item: ComponentAssembly[0]): React.ReactNode => {\n const override = renderOverride?.(item);\n const node = override === undefined ? renderSingle(item, brand, align, unit) : override;\n return renderItem ? renderItem(item, node) : node;\n };\n\n return (\n <div className={extraClass ? `${SP_ROOT} ${extraClass}` : SP_ROOT} {...restRoot} style={{ ...extraStyle, display: 'flex', flexDirection: 'column', gap: u(20), ...(unit === 'px' ? { fontSize: '16px' } : {}) }}>\n <style dangerouslySetInnerHTML={{ __html: buildTokenCss({ accent, unit, theme }) }} />\n {layout.map((group, i) => {\n if (group.type === 'pair') {\n return (\n <div key={i} className=\"sp-pair\">\n <div style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.items[0].component} size=\"half\" />}\n {renderOne(group.items[0])}\n </div>\n <div style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.items[1].component} size=\"half\" />}\n {renderOne(group.items[1])}\n </div>\n </div>\n );\n }\n return (\n <div key={i} style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.item.component} size={group.type === 'half-solo' ? 'half' : 'full'} />}\n {renderOne(group.item)}\n </div>\n );\n })}\n </div>\n );\n}\n","export type ComponentName =\n | 'AnnouncementBar'\n | 'HeroStatement'\n | 'AtomCard'\n | 'StatGrid'\n | 'CodeBlock'\n | 'ComparisonTable'\n | 'FeatureList'\n | 'TestimonialCard'\n | 'ImageCtaHero'\n | 'CtaStrip';\n\nexport type AssemblyZone = 'announce' | 'hero' | 'body' | 'proof' | 'cta';\n\nconst COMPONENT_ZONES: Record<ComponentName, AssemblyZone> = {\n AnnouncementBar: 'announce',\n HeroStatement: 'hero',\n ImageCtaHero: 'hero',\n AtomCard: 'body',\n StatGrid: 'body',\n CodeBlock: 'body',\n ComparisonTable: 'body',\n FeatureList: 'body',\n TestimonialCard: 'proof',\n CtaStrip: 'cta',\n};\n\nexport type ComponentAssembly = Array<{\n component: ComponentName;\n slots?: Record<string, unknown>;\n size?: 'full' | 'half';\n zone?: AssemblyZone;\n // Atom IDs this component was built from; drives conversion attribution.\n sourceAtomIds?: number[];\n}>;\n\nexport function filterAssemblyByZone(assembly: ComponentAssembly, zone: AssemblyZone): ComponentAssembly {\n return assembly.filter(item => {\n const effectiveZone = item.zone ?? COMPONENT_ZONES[item.component];\n return effectiveZone === zone;\n });\n}\n\n/**\n * Reading-mode category per component: the layout's pairing key. Two half-width components\n * only sit side by side when they share a category, so a prose block never lands beside a\n * scannable list. Mirrors the `category` field in the app's lib/component-registry.ts (the\n * source of truth, which also drives the assembly prompt);\n * tests/unit/renderer-category-parity.test.ts fails when the two drift.\n */\nexport const COMPONENT_CATEGORIES: Record<ComponentName, string> = {\n AnnouncementBar: 'conversion',\n HeroStatement: 'hero',\n AtomCard: 'content',\n StatGrid: 'content',\n CodeBlock: 'technical',\n ComparisonTable: 'evaluation',\n FeatureList: 'content',\n TestimonialCard: 'social-proof',\n ImageCtaHero: 'hero',\n CtaStrip: 'conversion',\n};\n","/**\n * The one place this package's design tokens are defined.\n *\n * Two things that are easy to get wrong here:\n *\n * 1. Tokens are declared on `.sp-root`, not `:root`. Declaring them at `:root` writes into\n * the host's document, allows only one theme per page, and means a customer overriding\n * `--sp-accent` competes with us at equal specificity so tag order decides the winner.\n * Scoping also lets two differently themed sections sit on one page.\n *\n * 2. `tokens.css` must stay byte-identical to `buildTokenCss({ scope: STYLESHEET_SCOPE })`,\n * which differs from the injected CSS in its selector and in nothing else.\n * tests/unit/react-tokens.test.ts enforces both halves, because a customer who imports the\n * stylesheet and a customer who renders the component must get the same page.\n *\n * components/ServerAssemblyRenderer.tsx in the Spectare app is a deliberate mirror of the\n * values below. It is not the same file: that renderer uses rem, this one uses px.\n */\n\n/** The package default. `spectare.js` and the WordPress plugin default to #2563eb, which is\n * a live inconsistency and a brand decision rather than a technical one, so it is left alone\n * here. Pass `accent` to override on either path. */\nexport const DEFAULT_ACCENT = '#60a5fa';\n\n/** The light theme's default accent. #60a5fa reads at ~2.5:1 on white, far below the 4.5:1\n * body floor, so light gets the deeper blue the widget and plugin already default to. */\nexport const DEFAULT_ACCENT_LIGHT = '#2563eb';\n\nexport type SpTheme = 'dark' | 'light';\n\n/** Class the tokens are scoped to. Applied by ComponentRenderer to its own wrapper. */\nexport const SP_ROOT = 'sp-root';\n\n/**\n * Selector the shipped `tokens.css` declares on.\n *\n * `:where(:root)` has zero specificity, so it gives a host that imports the stylesheet and\n * composes the individual components a working set of defaults without a wrapper, while losing\n * to literally any rule the host writes, including a bare `:root` of their own. `.sp-root` then\n * wins over it wherever both apply, which is what makes a differently themed section on one page\n * work. The runtime CSS the renderer injects uses `.sp-root` alone: it applies the class itself,\n * so it has no reason to touch the host's document.\n */\nexport const STYLESHEET_SCOPE = `:where(:root),.${SP_ROOT}`;\n\n/**\n * Colour tokens, in the order they are emitted.\n *\n * `--sp-text-muted` and `--sp-text-dim` were #71717a (3.67:1) and #52525b (2.29:1) on\n * `--sp-bg`, which fail WCAG AA for body text and, in the case of dim, fail even the 3:1\n * large-text floor. They now measure 4.65:1 and 3.36:1. Every other value is unchanged.\n *\n * `--sp-cta-bg` / `--sp-cta-text` carry the values CtaStrip used to hardcode, so the dark\n * rendering is pixel-identical and a light host can correct a button that would otherwise\n * be white on white.\n */\nfunction palette(accent: string, theme: SpTheme): Record<string, string> {\n const shared = {\n '--sp-accent': accent,\n '--sp-accent-bg': `color-mix(in srgb,${accent} 10%,transparent)`,\n '--sp-accent-border': `color-mix(in srgb,${accent} 20%,transparent)`,\n };\n // The light set mirrors the dark ramp with the same contrast discipline: every text token\n // holds its floor on both --sp-bg and --sp-surface (tests/unit/token-contrast.test.ts runs\n // the identical assertions against both themes), and the ramp stays strictly ordered.\n if (theme === 'light') {\n return {\n ...shared,\n '--sp-bg': '#ffffff',\n '--sp-surface': '#f4f4f5',\n '--sp-border': '#e4e4e7',\n '--sp-text': '#18181b',\n '--sp-text-sub': '#3f3f46',\n '--sp-text-strong': '#27272a',\n '--sp-text-muted': '#6b6b74',\n '--sp-text-dim': '#82828b',\n '--sp-text-body': '#52525b',\n '--sp-positive': '#047857',\n '--sp-cta-bg': '#18181b',\n '--sp-cta-text': '#ffffff',\n '--sp-divider': 'rgba(0,0,0,0.06)',\n '--sp-code-bg': 'rgba(0,0,0,0.05)',\n '--sp-code-border': 'rgba(0,0,0,0.08)',\n '--sp-pre-bg': 'rgba(0,0,0,0.04)',\n };\n }\n return {\n ...shared,\n '--sp-bg': '#18181b',\n '--sp-surface': '#09090b',\n '--sp-border': '#27272a',\n '--sp-text': '#f4f4f5',\n '--sp-text-sub': '#d4d4d8',\n '--sp-text-strong': '#e4e4e7',\n '--sp-text-muted': '#82828b',\n '--sp-text-dim': '#6b6b74',\n '--sp-text-body': '#a1a1aa',\n '--sp-positive': '#6ee7b7',\n '--sp-cta-bg': '#fff',\n '--sp-cta-text': '#09090b',\n '--sp-divider': 'rgba(255,255,255,0.06)',\n '--sp-code-bg': 'rgba(255,255,255,0.07)',\n '--sp-code-border': 'rgba(255,255,255,0.08)',\n '--sp-pre-bg': 'rgba(0,0,0,0.4)',\n };\n}\n\n/**\n * Prose and layout rules, scoped to the same class so the package ships no global classes.\n *\n * `unit` exists because the app's server renderer sizes in rem and this package sizes in px.\n * 20px and 1.25rem are the same length at a 16px base, so this is not a design difference, but\n * the two were separate string literals and separate string literals drift.\n */\nfunction rules(unit: 'px' | 'rem'): string {\n const gap = unit === 'px' ? '20px' : '1.25rem';\n return [\n '.sp-root .sp-prose p{margin-bottom:.625rem}',\n '.sp-root .sp-prose p:last-child{margin-bottom:0}',\n '.sp-root .sp-prose ul{list-style:disc;padding-left:1.25rem;margin-bottom:.625rem}',\n '.sp-root .sp-prose ol{list-style:decimal;padding-left:1.25rem;margin-bottom:.625rem}',\n '.sp-root .sp-prose li{margin-bottom:.25rem}',\n '.sp-root .sp-prose strong{color:var(--sp-text-strong);font-weight:600}',\n '.sp-root .sp-prose h2,.sp-root .sp-prose h3{color:var(--sp-text);font-weight:600;margin:.875rem 0 .375rem;font-size:1rem}',\n '.sp-root .sp-prose code{background:var(--sp-code-bg);border:1px solid var(--sp-code-border);padding:.1rem .35rem;border-radius:.25rem;font-size:.82em;color:var(--sp-text)}',\n '.sp-root .sp-prose blockquote{border-left:3px solid var(--sp-border);padding-left:1rem;color:var(--sp-text-muted);margin:.75rem 0}',\n `.sp-root .sp-pair{display:grid;grid-template-columns:1fr 1fr;gap:${gap}}`,\n '@media(max-width:640px){.sp-root .sp-pair{grid-template-columns:1fr}}',\n ].join('');\n}\n\n/**\n * Returns the stylesheet a renderer injects.\n *\n * @param accent brand colour. Accepts anything CSS does; `--sp-accent-bg` and\n * `--sp-accent-border` are derived from it so a customer sets one value\n * rather than three. Defaults to DEFAULT_ACCENT.\n * @param unit length unit for layout rules. 'px' for this package, 'rem' for the app's\n * server renderer, which sizes in rem throughout.\n * @param scope selector the custom properties are declared on. Defaults to `.sp-root`, which is\n * what a renderer injecting this at runtime wants. `tokens.css` is generated with\n * STYLESHEET_SCOPE instead, so importing it works without a wrapper.\n */\nexport function buildTokenCss({ accent, unit = 'px', scope = `.${SP_ROOT}`, theme = 'dark' }: { accent?: string; unit?: 'px' | 'rem'; scope?: string; theme?: SpTheme } = {}): string {\n const resolved = accent ?? (theme === 'light' ? DEFAULT_ACCENT_LIGHT : DEFAULT_ACCENT);\n const decls = Object.entries(palette(resolved, theme)).map(([k, v]) => `${k}:${v}`).join(';');\n return `${scope}{${decls}}${rules(unit)}`;\n}\n"],"mappings":"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","names":["jsx","jsxs","res","_a"]}
|
|
1
|
+
{"version":3,"sources":["../src/PersonalisedSection.tsx","../src/ComponentRenderer.tsx","../src/types.ts","../src/tokens.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { ComponentRenderer } from './ComponentRenderer';\nimport { filterAssemblyByZone } from './types';\nimport type { ComponentAssembly, AssemblyZone } from './types';\n\ntype ConversionCheckResult =\n | { matched: false }\n | { matched: true; goalName: string | null; goalType: string; valueSelector: string | null; currencySelector: string | null; defaultCurrency: string };\n\n// The arrangement this visitor saw, kept per-org in sessionStorage so a conversion fired on a\n// later page can attribute itself to it. Shares its key with spectare.js and the SSR\n// VariantTracker, so whichever surface rendered last wins, which is the arrangement the\n// visitor actually saw.\nconst VARIANT_KEY = (orgSlug: string) => `_spectare_variant_${orgSlug}`;\n\nfunction readVariantId(orgSlug: string): string | null {\n try { return sessionStorage.getItem(VARIANT_KEY(orgSlug)); } catch { return null; }\n}\n\nfunction writeVariantId(orgSlug: string, variantId: string): void {\n try { sessionStorage.setItem(VARIANT_KEY(orgSlug), variantId); } catch { /* private browsing */ }\n}\n\n\nfunction buildSummary(pageHint: string, orgSlug: string): string {\n const parts: string[] = [pageHint];\n const referrer = document.referrer;\n if (referrer) parts.push(`Arrived from: ${referrer}`);\n const p = new URLSearchParams(window.location.search);\n const source = p.get('utm_source');\n const medium = p.get('utm_medium');\n const campaign = p.get('utm_campaign');\n const term = p.get('utm_term');\n if (source) parts.push(`Source: ${source}`);\n if (medium) parts.push(`Medium: ${medium}`);\n if (campaign) parts.push(`Campaign: ${campaign}`);\n if (term) parts.push(`Search term: ${term}`);\n try {\n const history = localStorage.getItem(`_spectare_visits_${orgSlug}`);\n if (history) parts.push(`Previously visited: ${history}`);\n } catch { /* private browsing */ }\n return parts.filter(Boolean).join('. ');\n}\n\n// Reconstructs the visitor's page journey from spectare.js visit history.\nfunction readVisitPath(orgSlug: string): string[] {\n try {\n const raw = JSON.parse(localStorage.getItem(`_spectare_visits_${orgSlug}`) || '[]') as Array<{ path?: string }>;\n const path: string[] = [];\n for (const v of raw) {\n if (typeof v?.path === 'string' && (!path.length || path[path.length - 1] !== v.path)) path.push(v.path);\n }\n const cur = window.location.pathname;\n if (!path.length || path[path.length - 1] !== cur) path.push(cur);\n return path;\n } catch { return []; }\n}\n\nfunction Shimmer() {\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <div style={{ height: '20px', background: 'rgba(39,39,42,0.6)', borderRadius: '8px', width: '75%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '100%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '83%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n <div style={{ height: '14px', background: 'rgba(39,39,42,0.4)', borderRadius: '8px', width: '67%', animation: 'sp-pulse 1.5s ease-in-out infinite' }} />\n </div>\n );\n}\n\nexport interface PersonalisedSectionProps {\n orgSlug: string;\n /** Base URL of your Spectare instance. Defaults to 'https://spectare.ai'. */\n baseUrl?: string;\n /** Your brand name, used in ComparisonTable column header. */\n brand?: string;\n pageHint?: string;\n className?: string;\n style?: React.CSSProperties;\n initialAssembly?: ComponentAssembly;\n initialIntent?: { audience: string; stage: string };\n /**\n * Seed conversion attribution with a server-rendered arrangement: pass the variantId that\n * /api/assemble/ssr returned alongside initialAssembly. Without it, a visit where the client\n * classification matches the server's (so no client render happens) has no variant for a\n * later conversion to credit.\n */\n initialVariantId?: string;\n /**\n * Explicit visitor-typed context (e.g. a demo input box). Bypasses the session token cache\n * and re-qualifies immediately with the direct flag, which the server cost-caps (cheaper\n * model on a cache miss) and never writes to the shared cache.\n */\n directSummary?: string;\n /** Render only components assigned to this zone. */\n zone?: AssemblyZone;\n /** Alignment for statement-style components, to match the host page. */\n align?: 'left' | 'center' | 'right';\n /**\n * Brand accent. Passed through to ComponentRenderer, which emits it into the scoped\n * token set. Defaults to #60a5fa (dark) or #2563eb (light).\n */\n accent?: string;\n /** dark (default) or light, matching your page's ground. See ComponentRenderer. */\n theme?: 'dark' | 'light';\n}\n\nexport function PersonalisedSection({\n orgSlug,\n baseUrl = 'https://spectare.ai',\n brand,\n pageHint,\n className,\n style,\n initialAssembly,\n initialIntent,\n initialVariantId,\n directSummary,\n zone,\n align,\n accent,\n theme,\n}: PersonalisedSectionProps) {\n const [assembly, setAssembly] = useState<ComponentAssembly>(initialAssembly ?? []);\n const [loading, setLoading] = useState(!initialAssembly);\n const [orgName, setOrgName] = useState<string | undefined>(undefined);\n const [debugMode, setDebugMode] = useState(false);\n const [debugIntent, setDebugIntent] = useState<{ audience: string; stage: string } | null>(null);\n const tokenRef = useRef<string | null>(null);\n const conversionFiredRef = useRef(false);\n\n useEffect(() => {\n setDebugMode(new URLSearchParams(window.location.search).has('spectare_debug'));\n if (initialIntent) setDebugIntent(initialIntent);\n }, [initialIntent]);\n\n // Seed sessionStorage with the server-rendered variantId so conversions attribute correctly\n // even when the client assembly matches the SSR one and no client fetch replaces it.\n useEffect(() => {\n if (initialVariantId) writeVariantId(orgSlug, initialVariantId);\n }, [orgSlug, initialVariantId]);\n\n useEffect(() => {\n let cancelled = false;\n\n async function load() {\n try {\n let token: string | null = null;\n\n if (directSummary) {\n // Explicit visitor input: skip the token cache, re-qualify immediately with direct.\n setLoading(true);\n setAssembly([]);\n const res = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary: directSummary, direct: true }),\n });\n if (!res.ok || cancelled) { setLoading(false); return; }\n const data = await res.json();\n token = (data.token as string | undefined) ?? null;\n } else {\n // Key includes UTM params so a visitor arriving via a campaign link always\n // re-qualifies rather than reusing a token from a prior session context.\n const p = new URLSearchParams(window.location.search);\n const utmSuffix = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term']\n .map(k => p.get(k) ?? '').filter(Boolean).join('_');\n const tokenKey = `_spectare_token_${orgSlug}${utmSuffix ? '_' + utmSuffix : ''}`;\n token = sessionStorage.getItem(tokenKey);\n\n if (!token) {\n const summary = buildSummary(pageHint ?? `Visiting ${document.title}`, orgSlug);\n const res = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary }),\n });\n if (!res.ok || cancelled) { setLoading(false); return; }\n const data = await res.json();\n token = data.token as string | undefined ?? null;\n if (token) sessionStorage.setItem(tokenKey, token);\n if (data.orgName) setOrgName(data.orgName as string);\n }\n }\n\n if (!token || cancelled) { setLoading(false); return; }\n\n tokenRef.current = token;\n let res = await fetch(`${baseUrl}/api/assemble/components`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n // Direct: flag it so the server cost-caps the build, and omit the seen-variant\n // exclusion so it can read the shared cache instead of forcing a fresh build.\n body: JSON.stringify(\n directSummary\n ? { token, orgSlug, direct: true }\n : { token, orgSlug, excludeVariantId: readVariantId(orgSlug) },\n ),\n });\n\n if (res.status === 401 && !cancelled && !directSummary) {\n // Cached token expired: clear it, re-qualify, and retry once.\n const p = new URLSearchParams(window.location.search);\n const utmSuffix = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term']\n .map(k => p.get(k) ?? '').filter(Boolean).join('_');\n const tokenKey = `_spectare_token_${orgSlug}${utmSuffix ? '_' + utmSuffix : ''}`;\n sessionStorage.removeItem(tokenKey);\n const summary = buildSummary(pageHint ?? `Visiting ${document.title}`, orgSlug);\n const qRes = await fetch(`${baseUrl}/api/qualify/${orgSlug}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ summary }),\n });\n if (!qRes.ok || cancelled) { setLoading(false); return; }\n const qData = await qRes.json();\n token = qData.token as string | undefined ?? null;\n if (token) {\n sessionStorage.setItem(tokenKey, token);\n tokenRef.current = token;\n }\n if (!token || cancelled) { setLoading(false); return; }\n res = await fetch(`${baseUrl}/api/assemble/components`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, orgSlug, excludeVariantId: readVariantId(orgSlug) }),\n });\n }\n\n if (!res.ok || cancelled) { setLoading(false); return; }\n\n const contentType = res.headers.get('content-type') ?? '';\n\n if (contentType.includes('text/event-stream')) {\n // Cold path: stream components as Claude generates them.\n // Render progressively — shimmer shows until the first component arrives.\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n let loadingCleared = false;\n try {\n while (!cancelled) {\n const { done, value } = await reader.read();\n if (done || cancelled) break;\n buf += decoder.decode(value, { stream: true });\n const lines = buf.split('\\n');\n buf = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue;\n const payload = line.slice(6).trim();\n if (payload === '[DONE]') break;\n try {\n const parsed = JSON.parse(payload) as Record<string, unknown>;\n // Control frames: {_variant} carries attribution, {_error} means the stream\n // died server-side. Neither is a component; pushing them into the assembly\n // recorded a phantom entry the renderer silently skipped.\n if (parsed._variant && typeof parsed._variant === 'string') {\n writeVariantId(orgSlug, parsed._variant);\n continue;\n }\n if (parsed._error) {\n if (!loadingCleared) { setLoading(false); loadingCleared = true; }\n continue;\n }\n if (!parsed.component) continue;\n const comp = parsed as unknown as ComponentAssembly[0];\n if (!loadingCleared) { setLoading(false); loadingCleared = true; }\n setAssembly(prev => [...prev, comp]);\n } catch { /* malformed event — skip */ }\n }\n }\n } finally {\n reader.cancel().catch(() => {});\n }\n } else {\n // Warm path: cache hit returns full JSON immediately.\n const data = await res.json() as {\n assembly?: ComponentAssembly;\n intent?: { userContext?: { audience?: string; stage?: string } };\n variantId?: string;\n };\n if (data.variantId) writeVariantId(orgSlug, data.variantId);\n\n if (cancelled) return;\n\n const clientAudience = data.intent?.userContext?.audience;\n const clientStage = data.intent?.userContext?.stage;\n const ssrMatches =\n initialIntent &&\n clientAudience === initialIntent.audience &&\n clientStage === initialIntent.stage;\n\n if (clientAudience && clientStage) {\n setDebugIntent({ audience: clientAudience, stage: clientStage });\n }\n\n if (!ssrMatches && Array.isArray(data.assembly) && data.assembly.length > 0) {\n setAssembly(data.assembly as ComponentAssembly);\n }\n }\n } catch {\n // fail silently\n } finally {\n if (!cancelled) setLoading(false);\n }\n }\n\n load();\n return () => { cancelled = true; };\n }, [orgSlug, baseUrl, pageHint, initialAssembly, initialIntent, directSummary]);\n\n useEffect(() => {\n if (!assembly.length || conversionFiredRef.current) return;\n const token = tokenRef.current;\n if (!token) return;\n const url = window.location.href;\n fetch(`${baseUrl}/api/conversion-check`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ orgSlug, url }),\n }).then(r => r.json() as Promise<ConversionCheckResult>).then(data => {\n if (!data.matched) return;\n conversionFiredRef.current = true;\n let goalValue: number | null = null;\n let goalCurrency: string | null = data.defaultCurrency;\n if (data.valueSelector) {\n try {\n const el = document.querySelector(data.valueSelector);\n if (el) {\n const num = parseFloat((el.textContent ?? '').trim().replace(/[^0-9.]/g, ''));\n if (!isNaN(num)) goalValue = num;\n }\n } catch { /* skip */ }\n }\n if (data.currencySelector) {\n try {\n const el = document.querySelector(data.currencySelector);\n if (el) goalCurrency = (el.textContent ?? '').trim() || goalCurrency;\n } catch { /* skip */ }\n }\n const atomsShown = [...new Set(assembly.flatMap(i => i.sourceAtomIds ?? []))];\n const visitPath = readVisitPath(orgSlug);\n fetch(`${baseUrl}/api/conversion`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n token,\n orgSlug,\n url,\n variantId: readVariantId(orgSlug),\n ...(atomsShown.length ? { atomsShown } : {}),\n ...(visitPath.length > 1 ? { visitPath } : {}),\n ...(data.goalName ? { goalName: data.goalName } : {}),\n ...(goalValue !== null ? { goalValue, goalCurrency } : {}),\n }),\n }).catch(() => {});\n }).catch(() => {});\n }, [assembly, orgSlug, baseUrl]);\n\n if (!loading && assembly.length === 0) return null;\n\n // ?spectare_debug outlines the section and names the classified intent, so anyone checking\n // an integration can see where personalisation lands and what the visitor was read as.\n const debugStyle = debugMode\n ? { outline: '2px solid rgba(96,165,250,0.5)', borderRadius: '0.5rem', position: 'relative' as const, padding: '0.5rem', ...style }\n : style;\n\n return (\n <>\n <style dangerouslySetInnerHTML={{ __html: '@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}' }} />\n <div className={className} style={debugStyle}>\n {debugMode && (\n <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' }}>\n Personalised by Spectare\n {debugIntent && (\n <span style={{ opacity: 0.75 }}>\n {' '}{debugIntent.audience}/{debugIntent.stage}\n </span>\n )}\n </div>\n )}\n {loading && assembly.length === 0\n ? <Shimmer />\n : <ComponentRenderer assembly={zone ? filterAssemblyByZone(assembly, zone) : assembly} brand={brand ?? orgName} align={align} accent={accent} theme={theme} />}\n </div>\n </>\n );\n}\n","// Universal renderer: deliberately NO 'use client' in this source file. Nothing here uses hooks, state, or event\n// handlers, so the same file renders as a React Server Component (zero JS shipped, how the\n// Spectare app uses it via components/ServerAssemblyRenderer.tsx) and inside a client tree\n// (how PersonalisedSection uses it). Adding a hook or handler here would silently force every\n// server consumer to ship and hydrate it: keep interactivity in wrappers.\n//\n// Sizing is numeric, scaled through u(): px for embedded hosts (predictable inside arbitrary\n// pages) or rem for hosts that want to track the reader's font-size preference (the Spectare\n// site). Until 2026-08-31 the rem variant was a hand-maintained mirror of this file, and the\n// two drifted a pixel apart in six places; one number set, one scale function, no mirror.\nimport { marked } from 'marked';\nimport DOMPurify from 'isomorphic-dompurify';\nimport { filterAssemblyByZone, COMPONENT_CATEGORIES } from './types';\nimport { buildTokenCss, SP_ROOT } from './tokens';\nimport type { SpTheme } from './tokens';\nimport type { ComponentAssembly, ComponentName, AssemblyZone } from './types';\n\n// The assembly API returns atom content as raw markdown. marked emits raw HTML,\n// so the output must be sanitised before it reaches dangerouslySetInnerHTML,\n// otherwise a malicious atom can run script in the host site's visitors' browsers.\nfunction renderMarkdown(content: string): string {\n const raw = marked.parse(content ?? '', { async: false }) as string;\n return DOMPurify.sanitize(raw, { USE_PROFILES: { html: true } });\n}\n\nexport type Unit = 'px' | 'rem';\ntype U = (n: number) => string;\nconst scaler = (unit: Unit): U => (n: number) => (unit === 'rem' ? `${n / 16}rem` : `${n}px`);\nconst PX = scaler('px');\n\n// Default half-size components: used when assembly item omits size.\nconst HALF_COMPONENTS = new Set<ComponentName>(['TestimonialCard']);\n\n// ── Individual component renderers ────────────────────────────────────────────\n\n// Alignment is a host decision, not baked into a component: the host passes `align`\n// and statement-style components adopt it. flexItems maps it to a flex alignment so\n// block children (a max-width subheading, an inline CTA) align too, not just the text.\ntype Align = 'left' | 'center' | 'right';\nconst flexItems = (a: Align): 'flex-start' | 'center' | 'flex-end' =>\n a === 'center' ? 'center' : a === 'right' ? 'flex-end' : 'flex-start';\n\n/**\n * A single line above everything else. Deliberately the plainest component in the set: no\n * heading, no image, no padding to speak of. A bar that draws attention to itself competes with\n * the page it is announcing something about.\n *\n * Uses the accent rather than a red or amber alert colour. This is a fact worth knowing, not a\n * warning, and a venue putting \"members book from Thursday\" in an alarm colour reads as a problem\n * rather than an offer.\n */\nexport function AnnouncementBar({ text, link, unit = 'px' }: { text?: string; link?: { label: string; href: string }; unit?: Unit }) {\n const u = scaler(unit);\n if (!text) return null;\n return (\n <div style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center', gap: u(10),\n flexWrap: 'wrap', textAlign: 'center',\n background: 'var(--sp-accent-bg)', border: '1px solid var(--sp-accent-border)',\n borderRadius: u(8), padding: `${u(8)} ${u(16)}`, fontSize: u(14), lineHeight: 1.4,\n color: 'var(--sp-text-sub)',\n }}>\n <span>{text}</span>\n {link?.href && link?.label && (\n <a href={link.href} style={{ color: 'var(--sp-accent)', fontWeight: 600, textDecoration: 'none', whiteSpace: 'nowrap' }}>\n {link.label} →\n </a>\n )}\n </div>\n );\n}\n\nexport function HeroStatement({ headline, subheading, align = 'left', unit = 'px' }: { headline: string; subheading?: string; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: flexItems(align), textAlign: align, paddingTop: u(24), paddingBottom: u(24) }}>\n <h2 style={{ fontSize: u(32), fontWeight: 700, letterSpacing: '-0.025em', lineHeight: 1.2, color: 'var(--sp-text)', margin: `0 0 ${u(12)}` }}>\n {headline}\n </h2>\n {subheading && (\n <p style={{ fontSize: u(18), color: 'var(--sp-text-sub)', lineHeight: 1.6, maxWidth: u(672), margin: 0 }}>{subheading}</p>\n )}\n </div>\n );\n}\n\n// The atom owns title / content / stats / cta; its layout decides which appear and in\n// what order. Default order when the atom has no layout. Mirrors the atom editor.\nconst ATOM_LAYOUT_DEFAULT = ['title', 'content', 'stats', 'cta'];\n\n// Clamp atom prose unless the assembly asked for the full body. CSS rather than an expand\n// toggle, so the identical rule works here (including server-rendered with no JS), in\n// spectare.js and in the WordPress plugin.\nexport const ATOM_CLAMP_LINES = 4;\nconst clampStyle = {\n display: '-webkit-box',\n WebkitLineClamp: ATOM_CLAMP_LINES,\n WebkitBoxOrient: 'vertical' as const,\n overflow: 'hidden',\n};\n\nexport function AtomCard(\n { title, content, summary, layout, stats = [], ctaText, ctaUrl, full, variant, unit = 'px' }:\n { title?: string; content?: string; summary?: string; layout?: string[]; stats?: { value: string; label: string }[]; ctaText?: string; ctaUrl?: string; full?: boolean; variant?: string; unit?: Unit },\n) {\n const u = scaler(unit);\n\n // The card face: title, one-sentence summary, and the full body behind a native <details>\n // disclosure. <details> is the one expand that needs no JavaScript, so it works identically\n // in a server component, a client tree, and any host page; nothing is ever unreachable on a\n // site that has no per-atom pages. The Spectare app substitutes its own card face (which\n // links to the atom's page) via renderOverride, so this is the everywhere-else rendering.\n if (variant === 'card') {\n const face = summary?.trim() || (content ? `${content.replace(/\\s+/g, ' ').split(/(?<=[.!?])\\s/)[0]}` : '');\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(20) }}>\n {title && <h3 style={{ fontSize: u(18), fontWeight: 600, color: 'var(--sp-text)', margin: 0, lineHeight: 1.35 }}>{title}</h3>}\n {face && <p style={{ fontSize: u(16), color: 'var(--sp-text-sub)', lineHeight: 1.6, margin: `${u(8)} 0 0` }}>{face}</p>}\n {/* One link per face. The atom's own CTA is deliberately NOT rendered here: the\n face's job is the summary and the disclosure, and the guards already treat a\n card face as carrying no inline CTA. Stacked links on a compact card read as\n competing calls to action. */}\n {content && (\n <details style={{ marginTop: u(10) }}>\n <summary style={{ cursor: 'pointer', fontSize: u(14), fontWeight: 600, color: 'var(--sp-accent)', listStyle: 'none' }}>Read more</summary>\n <div className=\"sp-prose\" style={{ fontSize: u(16), color: 'var(--sp-text-sub)', lineHeight: 1.6, marginTop: u(10) }} dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} />\n </details>\n )}\n </div>\n );\n }\n\n const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;\n const element = (name: string) => {\n if (name === 'title') return title\n ? <h3 key=\"title\" style={{ fontSize: u(18), fontWeight: 600, color: 'var(--sp-text)', margin: `0 0 ${u(12)}` }}>{title}</h3> : null;\n if (name === 'content') return content\n ? <div key=\"content\" className=\"sp-prose\" style={{ fontSize: u(16), color: 'var(--sp-text-sub)', lineHeight: 1.6, ...(full ? {} : clampStyle) }} dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} /> : null;\n if (name === 'stats') return stats.length\n ? (\n <div key=\"stats\" style={{ display: 'flex', flexWrap: 'wrap', gap: u(20), margin: `${u(18)} 0 ${u(12)}`, padding: `0 0 ${u(14)}`, borderBottom: '1px solid var(--sp-border)' }}>\n {stats.map((s, i) => (\n <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: u(2) }}>\n <span style={{ fontSize: u(22), fontWeight: 700, color: 'var(--sp-text)', lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>{s.value}</span>\n <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>{s.label}</span>\n </div>\n ))}\n </div>\n ) : null;\n if (name === 'cta') return ctaText && ctaUrl\n ? <a key=\"cta\" href={ctaUrl} style={{ display: 'inline-flex', alignItems: 'center', gap: u(4), marginTop: u(12), fontSize: u(14), fontWeight: 600, color: 'var(--sp-accent)', textDecoration: 'none' }}>{ctaText} →</a> : null;\n return null;\n };\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(24), height: '100%' }}>\n {order.map(element)}\n </div>\n );\n}\n\nexport function StatGrid({ stats = [], caption, unit = 'px' }: { stats?: { value: string; label: string }[]; caption?: string; unit?: Unit }) {\n const u = scaler(unit);\n const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;\n return (\n <div>\n <div style={{ display: 'grid', gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: u(12) }}>\n {stats.map(({ value, label }) => (\n <div key={label} 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) }}>\n <p style={{ fontSize: u(12), color: 'var(--sp-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em', margin: `0 0 ${u(12)}`, lineHeight: 1.3 }}>{label}</p>\n <p style={{ fontSize: u(20), fontWeight: 500, color: 'var(--sp-text)', fontVariantNumeric: 'tabular-nums', lineHeight: 1, margin: 0 }}>{value}</p>\n </div>\n ))}\n </div>\n {caption && (\n <p style={{ fontSize: u(14), color: 'var(--sp-text-muted)', margin: `${u(12)} 0 0` }}>{caption}</p>\n )}\n </div>\n );\n}\n\nexport function CodeBlock({ code, lang = 'typescript', caption, unit = 'px' }: { code: string; lang?: string; caption?: string; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ borderRadius: u(12), overflow: 'hidden', border: '1px solid var(--sp-border)' }}>\n <div style={{ background: 'var(--sp-bg)', padding: `${u(10)} ${u(16)}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: '1px solid var(--sp-border)' }}>\n <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)', fontFamily: 'monospace' }}>{lang}</span>\n {caption && <span style={{ fontSize: u(12), color: 'var(--sp-text-muted)' }}>{caption}</span>}\n </div>\n <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 }}>\n {code}\n </pre>\n </div>\n );\n}\n\nexport function ComparisonTable({ brand = 'Us', competitor, rows = [], unit = 'px' }: { brand?: string; competitor: string; rows?: { label: string; spectare: string; them: string }[]; unit?: Unit }) {\n const u = scaler(unit);\n const cell = { textAlign: 'left' as const, padding: `${u(12)} ${u(16)}` };\n return (\n <div style={{ border: '1px solid var(--sp-border)', borderRadius: u(12), overflow: 'hidden' }}>\n <div style={{ overflowX: 'auto' }}>\n <table style={{ width: '100%', fontSize: u(14), borderCollapse: 'collapse' }}>\n <thead>\n <tr style={{ borderBottom: '1px solid var(--sp-border)', background: 'var(--sp-bg)' }}>\n <th style={{ ...cell, color: 'var(--sp-text-muted)', fontWeight: 500, fontSize: u(13), width: '33%' }} />\n <th scope=\"col\" style={{ ...cell, fontWeight: 600, color: 'var(--sp-accent)', fontSize: u(13) }}>{brand}</th>\n <th scope=\"col\" style={{ ...cell, color: 'var(--sp-text-muted)', fontWeight: 500, fontSize: u(13) }}>{competitor}</th>\n </tr>\n </thead>\n <tbody>\n {rows.map(({ label, spectare, them }) => (\n <tr key={label} style={{ borderBottom: '1px solid var(--sp-border)' }}>\n <th scope=\"row\" style={{ ...cell, fontSize: u(14), color: 'var(--sp-text-muted)', fontWeight: 500 }}>{label}</th>\n <td style={{ ...cell, fontSize: u(14), color: 'var(--sp-positive)', fontWeight: 500 }}>{spectare}</td>\n <td style={{ ...cell, fontSize: u(14), color: 'var(--sp-text-muted)' }}>{them}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nexport function FeatureList({ items = [], unit = 'px' }: { items?: { text: string; sub?: string }[]; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ background: 'var(--sp-bg)', border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(24) }}>\n <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: u(16) }}>\n {items.map(({ text, sub }) => (\n <li key={text} style={{ display: 'flex', gap: u(12) }}>\n <span style={{ color: 'var(--sp-accent)', flexShrink: 0, fontSize: u(15), marginTop: u(2) }}>✓</span>\n <div>\n <p style={{ fontSize: u(15), fontWeight: 500, color: 'var(--sp-text)', lineHeight: 1.4, margin: 0 }}>{text}</p>\n {sub && <p style={{ fontSize: u(14), color: 'var(--sp-text-muted)', lineHeight: 1.5, margin: `${u(4)} 0 0` }}>{sub}</p>}\n </div>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport function TestimonialCard({ quote, name, role, company, unit = 'px' }: { quote: string; name: string; role: string; company?: string; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <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%' }}>\n <p style={{ fontSize: u(15), color: 'var(--sp-text-sub)', lineHeight: 1.6, flex: 1, margin: 0 }}>\n <span style={{ color: 'var(--sp-text-dim)', fontSize: u(18), lineHeight: 1, marginRight: u(4) }}>\"</span>\n {quote}\n <span style={{ color: 'var(--sp-text-dim)', fontSize: u(18), lineHeight: 1, marginLeft: u(4) }}>\"</span>\n </p>\n <div style={{ borderTop: '1px solid var(--sp-border)', paddingTop: u(16) }}>\n <p style={{ fontSize: u(14), fontWeight: 600, color: 'var(--sp-text)', margin: 0 }}>{name}</p>\n <p style={{ fontSize: u(14), color: 'var(--sp-text-muted)', margin: `${u(2)} 0 0` }}>\n {role}{company ? `, ${company}` : ''}\n </p>\n </div>\n </div>\n );\n}\n\nexport function ImageCtaHero({ src, alt = '', headline, subheading, ctaLabel, ctaHref, align = 'left', unit = 'px' }: { src?: string; alt?: string; headline?: string; subheading?: string; ctaLabel?: string; ctaHref?: string; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n if (!src) return null;\n return (\n <div style={{ borderRadius: u(12), overflow: 'hidden', position: 'relative', width: '100%', paddingBottom: '56.25%' }}>\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={src} alt={alt} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />\n <div style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.45)' }} />\n <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%)' }} />\n <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: u(28), textAlign: align }}>\n {headline && (\n <h2 style={{ fontSize: u(24), fontWeight: 700, color: '#fff', lineHeight: 1.2, margin: `0 0 ${u(8)}`, letterSpacing: '-0.02em' }}>{headline}</h2>\n )}\n {subheading && (\n <p style={{ fontSize: u(15), color: 'rgba(255,255,255,0.75)', lineHeight: 1.5, margin: `0 0 ${u(20)}` }}>{subheading}</p>\n )}\n {ctaHref && ctaLabel && (\n <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' }}>\n {ctaLabel}\n </a>\n )}\n </div>\n </div>\n );\n}\n\nexport function CtaStrip({ headline, primary, secondary, align = 'center', unit = 'px' }: { headline: string; primary: { label: string; href: string }; secondary?: { label: string; href: string }; align?: Align; unit?: Unit }) {\n const u = scaler(unit);\n return (\n <div style={{ border: '1px solid var(--sp-border)', borderRadius: u(12), padding: u(32), textAlign: align, background: 'var(--sp-bg)' }}>\n <h3 style={{ fontSize: u(24), fontWeight: 700, color: 'var(--sp-text)', margin: `0 0 ${u(24)}` }}>{headline}</h3>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: flexItems(align), gap: u(16), flexWrap: 'wrap' }}>\n <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' }}>\n {primary.label}\n </a>\n {secondary && (\n <a href={secondary.href} style={{ fontSize: u(15), color: 'var(--sp-text-sub)', textDecoration: 'none' }}>\n {secondary.label} →\n </a>\n )}\n </div>\n </div>\n );\n}\n\n// ── Dispatch ──────────────────────────────────────────────────────────────────\n\nfunction renderSingle(item: ComponentAssembly[0], brand?: string, align?: Align, unit: Unit = 'px'): React.ReactNode {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const s = item.slots as Record<string, any> ?? {};\n\n switch (item.component as ComponentName) {\n case 'AnnouncementBar': return <AnnouncementBar text={s.text} link={s.link} unit={unit} />;\n case 'HeroStatement': return <HeroStatement headline={s.headline} subheading={s.subheading} align={align} unit={unit} />;\n // A full-width card has nothing beside it, so there is nothing for a clamp to protect.\n case 'AtomCard': return <AtomCard title={s.title} content={s.content} summary={s.summary} layout={s.layout} stats={s.stats} ctaText={s.ctaText} ctaUrl={s.ctaUrl} full={s.full || resolvedSize(item) === 'full'} variant={s.variant} unit={unit} />;\n case 'StatGrid': return <StatGrid stats={s.stats} caption={s.caption} unit={unit} />;\n case 'CodeBlock': return <CodeBlock code={s.code} lang={s.lang} caption={s.caption} unit={unit} />;\n case 'ComparisonTable': return <ComparisonTable brand={s.brand ?? brand} competitor={s.competitor} rows={s.rows} unit={unit} />;\n case 'FeatureList': return <FeatureList items={s.items} unit={unit} />;\n case 'TestimonialCard': return <TestimonialCard quote={s.quote} name={s.name} role={s.role} company={s.company} unit={unit} />;\n case 'ImageCtaHero': return <ImageCtaHero src={s.src} alt={s.alt} headline={s.headline} subheading={s.subheading} ctaLabel={s.ctaLabel} ctaHref={s.ctaHref} align={align} unit={unit} />;\n case 'CtaStrip': return <CtaStrip headline={s.headline} primary={s.primary} secondary={s.secondary} align={align} unit={unit} />;\n // An unrecognised component name used to render nothing at all. A component needs a\n // renderer here plus spectare.js plus the WordPress plugin, so missing one made its content\n // silently absent on that surface only: no error, no warning, just a shorter page that\n // looks deliberate. That is the failure mode to remove before the registry grows.\n //\n // Falls back to AtomCard when the slots carry something readable, since almost every\n // component is built from an atom and title/content is the shape they share. When there\n // is genuinely nothing to show it still renders nothing, because an empty card is worse\n // than a gap, but the warning fires either way.\n default: {\n console.warn(`[spectare] ComponentRenderer: no renderer for \"${item.component}\", falling back to AtomCard`);\n if (!s.title && !s.content) return null;\n return <AtomCard title={s.title} content={s.content} stats={s.stats} ctaText={s.ctaText} ctaUrl={s.ctaUrl} full unit={unit} />;\n }\n }\n}\n\n// ── Layout ────────────────────────────────────────────────────────────────────\n\nfunction resolvedSize(item: ComponentAssembly[0]): 'full' | 'half' {\n if (item.size) return item.size;\n return HALF_COMPONENTS.has(item.component as ComponentName) ? 'half' : 'full';\n}\n\ntype LayoutGroup =\n | { type: 'full'; item: ComponentAssembly[0] }\n | { type: 'pair'; items: [ComponentAssembly[0], ComponentAssembly[0]] }\n | { type: 'half-solo'; item: ComponentAssembly[0] };\n\n// Two half-width components only sit side by side well if they read at the same speed. A\n// prose block beside a scannable list forces the eye to switch modes, and the grid stretches\n// the shorter one, leaving dead space. Registry category is the available proxy for reading\n// mode, so pair within a category and give anything else its own row.\nfunction pairable(a: ComponentAssembly[0], b: ComponentAssembly[0]): boolean {\n const catOf = (x: ComponentAssembly[0]) =>\n COMPONENT_CATEGORIES[x.component as ComponentName];\n const ca = catOf(a);\n const cb = catOf(b);\n return ca !== undefined && ca === cb;\n}\n\nfunction buildLayout(assembly: ComponentAssembly): LayoutGroup[] {\n const groups: LayoutGroup[] = [];\n let i = 0;\n while (i < assembly.length) {\n const cur = assembly[i];\n const next = assembly[i + 1];\n if (resolvedSize(cur) === 'half' && next && resolvedSize(next) === 'half' && pairable(cur, next)) {\n groups.push({ type: 'pair', items: [cur, next] });\n i += 2;\n } else if (resolvedSize(cur) === 'half') {\n groups.push({ type: 'half-solo', item: cur });\n i++;\n } else {\n groups.push({ type: 'full', item: cur });\n i++;\n }\n }\n return groups;\n}\n\n// ── X-ray badge ───────────────────────────────────────────────────────────────\n\nfunction XrayBadge({ name, size }: { name: string; size: string }) {\n return (\n <div style={{ position: 'absolute', top: PX(8), left: PX(8), zIndex: 10, display: 'flex', alignItems: 'center', gap: PX(6), pointerEvents: 'none', userSelect: 'none' }}>\n <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 }}>{name}</span>\n <span style={{ fontSize: PX(10), fontFamily: 'monospace', color: '#71717a', lineHeight: 1 }}>{size}</span>\n </div>\n );\n}\n\n// ── Main export ───────────────────────────────────────────────────────────────\n\nexport interface ComponentRendererProps {\n assembly: ComponentAssembly;\n /** Your brand name, used as the left column header in ComparisonTable. Defaults to \"Us\". */\n brand?: string;\n /** Overlay a component name badge on each item. Useful for demos and debugging. */\n xray?: boolean;\n /** Render only components assigned to this zone. */\n zone?: AssemblyZone;\n /**\n * Alignment for statement-style components (HeroStatement, CtaStrip, ImageCtaHero),\n * so assembled content can match the host page. Omit to use each component's natural\n * default (HeroStatement left, CtaStrip centered).\n */\n align?: 'left' | 'center' | 'right';\n /**\n * Brand accent, as an explicit input rather than a custom property you override and hope\n * wins on tag order. Any CSS colour. `--sp-accent-bg` and `--sp-accent-border` are derived\n * from it, so one value covers all three. Defaults to #60a5fa.\n */\n accent?: string;\n /**\n * dark (default) is the package's original near-black card set. light renders white cards\n * with a dark text ramp for light host pages; without it the components paint near-white\n * text and near-black slabs onto a light ground. Both palettes hold the same contrast\n * floors (see tests/unit/token-contrast.test.ts).\n */\n theme?: SpTheme;\n /**\n * px (default) sizes components absolutely, predictable inside arbitrary host pages.\n * rem tracks the reader's font-size preference; the root then also inherits the host's\n * font size instead of pinning 16px.\n */\n unit?: Unit;\n /**\n * Substitute rendering for an item: return a node to replace the built-in renderer\n * (including null to render nothing), or undefined to keep the default. How the Spectare\n * app swaps the card-variant AtomCard for its server-rendered card face.\n */\n renderOverride?: (item: ComponentAssembly[0]) => React.ReactNode | undefined;\n /**\n * Wrap each rendered item, e.g. with source attribution or a debug badge. Receives the\n * assembly item and its rendered node; whatever it returns is placed in the layout.\n */\n renderItem?: (item: ComponentAssembly[0], rendered: React.ReactNode) => React.ReactNode;\n /** Extra attributes for the root element (e.g. a data marker a host overlay targets). */\n rootProps?: Record<string, unknown>;\n}\n\n\nexport function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent, theme, unit = 'px', renderOverride, renderItem, rootProps }: ComponentRendererProps) {\n const u = scaler(unit);\n const filtered = zone ? filterAssemblyByZone(assembly, zone) : assembly;\n const layout = buildLayout(filtered);\n\n // Merge rather than spread-clobber: a host className joins sp-root instead of replacing it\n // (every --sp-* token is scoped to .sp-root, so losing it un-themes every component), and a\n // host style merges under the layout styles rather than being silently discarded.\n const { className: extraClass, style: extraStyle, ...restRoot } = (rootProps ?? {}) as { className?: string; style?: React.CSSProperties } & Record<string, unknown>;\n\n const renderOne = (item: ComponentAssembly[0]): React.ReactNode => {\n const override = renderOverride?.(item);\n const node = override === undefined ? renderSingle(item, brand, align, unit) : override;\n return renderItem ? renderItem(item, node) : node;\n };\n\n return (\n <div className={extraClass ? `${SP_ROOT} ${extraClass}` : SP_ROOT} {...restRoot} style={{ ...extraStyle, display: 'flex', flexDirection: 'column', gap: u(20), ...(unit === 'px' ? { fontSize: '16px' } : {}) }}>\n <style dangerouslySetInnerHTML={{ __html: buildTokenCss({ accent, unit, theme }) }} />\n {layout.map((group, i) => {\n if (group.type === 'pair') {\n return (\n <div key={i} className=\"sp-pair\">\n <div style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.items[0].component} size=\"half\" />}\n {renderOne(group.items[0])}\n </div>\n <div style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.items[1].component} size=\"half\" />}\n {renderOne(group.items[1])}\n </div>\n </div>\n );\n }\n return (\n <div key={i} style={xray ? { position: 'relative' } : undefined}>\n {xray && <XrayBadge name={group.item.component} size={group.type === 'half-solo' ? 'half' : 'full'} />}\n {renderOne(group.item)}\n </div>\n );\n })}\n </div>\n );\n}\n","export type ComponentName =\n | 'AnnouncementBar'\n | 'HeroStatement'\n | 'AtomCard'\n | 'StatGrid'\n | 'CodeBlock'\n | 'ComparisonTable'\n | 'FeatureList'\n | 'TestimonialCard'\n | 'ImageCtaHero'\n | 'CtaStrip';\n\nexport type AssemblyZone = 'announce' | 'hero' | 'body' | 'proof' | 'cta';\n\nconst COMPONENT_ZONES: Record<ComponentName, AssemblyZone> = {\n AnnouncementBar: 'announce',\n HeroStatement: 'hero',\n ImageCtaHero: 'hero',\n AtomCard: 'body',\n StatGrid: 'body',\n CodeBlock: 'body',\n ComparisonTable: 'body',\n FeatureList: 'body',\n TestimonialCard: 'proof',\n CtaStrip: 'cta',\n};\n\nexport type ComponentAssembly = Array<{\n component: ComponentName;\n slots?: Record<string, unknown>;\n size?: 'full' | 'half';\n zone?: AssemblyZone;\n // Atom IDs this component was built from; drives conversion attribution.\n sourceAtomIds?: number[];\n}>;\n\nexport function filterAssemblyByZone(assembly: ComponentAssembly, zone: AssemblyZone): ComponentAssembly {\n return assembly.filter(item => {\n const effectiveZone = item.zone ?? COMPONENT_ZONES[item.component];\n return effectiveZone === zone;\n });\n}\n\n/**\n * Reading-mode category per component: the layout's pairing key. Two half-width components\n * only sit side by side when they share a category, so a prose block never lands beside a\n * scannable list. Mirrors the `category` field in the app's lib/component-registry.ts (the\n * source of truth, which also drives the assembly prompt);\n * tests/unit/renderer-category-parity.test.ts fails when the two drift.\n */\nexport const COMPONENT_CATEGORIES: Record<ComponentName, string> = {\n AnnouncementBar: 'conversion',\n HeroStatement: 'hero',\n AtomCard: 'content',\n StatGrid: 'content',\n CodeBlock: 'technical',\n ComparisonTable: 'evaluation',\n FeatureList: 'content',\n TestimonialCard: 'social-proof',\n ImageCtaHero: 'hero',\n CtaStrip: 'conversion',\n};\n","/**\n * The one place this package's design tokens are defined.\n *\n * Two things that are easy to get wrong here:\n *\n * 1. Tokens are declared on `.sp-root`, not `:root`. Declaring them at `:root` writes into\n * the host's document, allows only one theme per page, and means a customer overriding\n * `--sp-accent` competes with us at equal specificity so tag order decides the winner.\n * Scoping also lets two differently themed sections sit on one page.\n *\n * 2. `tokens.css` must stay byte-identical to `buildTokenCss({ scope: STYLESHEET_SCOPE })`,\n * which differs from the injected CSS in its selector and in nothing else.\n * tests/unit/react-tokens.test.ts enforces both halves, because a customer who imports the\n * stylesheet and a customer who renders the component must get the same page.\n *\n * components/ServerAssemblyRenderer.tsx in the Spectare app is a deliberate mirror of the\n * values below. It is not the same file: that renderer uses rem, this one uses px.\n */\n\n/** The package default. `spectare.js` and the WordPress plugin default to #2563eb, which is\n * a live inconsistency and a brand decision rather than a technical one, so it is left alone\n * here. Pass `accent` to override on either path. */\nexport const DEFAULT_ACCENT = '#60a5fa';\n\n/** The light theme's default accent. #60a5fa reads at ~2.5:1 on white, far below the 4.5:1\n * body floor, so light gets the deeper blue the widget and plugin already default to. */\nexport const DEFAULT_ACCENT_LIGHT = '#2563eb';\n\nexport type SpTheme = 'dark' | 'light';\n\n/** Class the tokens are scoped to. Applied by ComponentRenderer to its own wrapper. */\nexport const SP_ROOT = 'sp-root';\n\n/**\n * Selector the shipped `tokens.css` declares on.\n *\n * `:where(:root)` has zero specificity, so it gives a host that imports the stylesheet and\n * composes the individual components a working set of defaults without a wrapper, while losing\n * to literally any rule the host writes, including a bare `:root` of their own. `.sp-root` then\n * wins over it wherever both apply, which is what makes a differently themed section on one page\n * work. The runtime CSS the renderer injects uses `.sp-root` alone: it applies the class itself,\n * so it has no reason to touch the host's document.\n */\nexport const STYLESHEET_SCOPE = `:where(:root),.${SP_ROOT}`;\n\n/**\n * Colour tokens, in the order they are emitted.\n *\n * `--sp-text-muted` and `--sp-text-dim` were #71717a (3.67:1) and #52525b (2.29:1) on\n * `--sp-bg`, which fail WCAG AA for body text and, in the case of dim, fail even the 3:1\n * large-text floor. They now measure 4.65:1 and 3.36:1. Every other value is unchanged.\n *\n * `--sp-cta-bg` / `--sp-cta-text` carry the values CtaStrip used to hardcode, so the dark\n * rendering is pixel-identical and a light host can correct a button that would otherwise\n * be white on white.\n */\nfunction palette(accent: string, theme: SpTheme): Record<string, string> {\n const shared = {\n '--sp-accent': accent,\n '--sp-accent-bg': `color-mix(in srgb,${accent} 10%,transparent)`,\n '--sp-accent-border': `color-mix(in srgb,${accent} 20%,transparent)`,\n };\n // The light set mirrors the dark ramp with the same contrast discipline: every text token\n // holds its floor on both --sp-bg and --sp-surface (tests/unit/token-contrast.test.ts runs\n // the identical assertions against both themes), and the ramp stays strictly ordered.\n if (theme === 'light') {\n return {\n ...shared,\n '--sp-bg': '#ffffff',\n '--sp-surface': '#f4f4f5',\n '--sp-border': '#e4e4e7',\n '--sp-text': '#18181b',\n '--sp-text-sub': '#3f3f46',\n '--sp-text-strong': '#27272a',\n '--sp-text-muted': '#6b6b74',\n '--sp-text-dim': '#82828b',\n '--sp-text-body': '#52525b',\n '--sp-positive': '#047857',\n '--sp-cta-bg': '#18181b',\n '--sp-cta-text': '#ffffff',\n '--sp-divider': 'rgba(0,0,0,0.06)',\n '--sp-code-bg': 'rgba(0,0,0,0.05)',\n '--sp-code-border': 'rgba(0,0,0,0.08)',\n '--sp-pre-bg': 'rgba(0,0,0,0.04)',\n };\n }\n return {\n ...shared,\n '--sp-bg': '#18181b',\n '--sp-surface': '#09090b',\n '--sp-border': '#27272a',\n '--sp-text': '#f4f4f5',\n // Body prose colour. Was #d4d4d8, judged too grey against near-black at reading\n // sizes; one step brighter keeps the hierarchy below --sp-text while reading as\n // text rather than chrome.\n '--sp-text-sub': '#e4e4e7',\n '--sp-text-strong': '#ececee',\n '--sp-text-muted': '#82828b',\n '--sp-text-dim': '#6b6b74',\n '--sp-text-body': '#a1a1aa',\n '--sp-positive': '#6ee7b7',\n '--sp-cta-bg': '#fff',\n '--sp-cta-text': '#09090b',\n '--sp-divider': 'rgba(255,255,255,0.06)',\n '--sp-code-bg': 'rgba(255,255,255,0.07)',\n '--sp-code-border': 'rgba(255,255,255,0.08)',\n '--sp-pre-bg': 'rgba(0,0,0,0.4)',\n };\n}\n\n/**\n * Prose and layout rules, scoped to the same class so the package ships no global classes.\n *\n * `unit` exists because the app's server renderer sizes in rem and this package sizes in px.\n * 20px and 1.25rem are the same length at a 16px base, so this is not a design difference, but\n * the two were separate string literals and separate string literals drift.\n */\nfunction rules(unit: 'px' | 'rem'): string {\n const gap = unit === 'px' ? '20px' : '1.25rem';\n return [\n '.sp-root .sp-prose p{margin-bottom:.625rem}',\n '.sp-root .sp-prose p:last-child{margin-bottom:0}',\n '.sp-root .sp-prose ul{list-style:disc;padding-left:1.25rem;margin-bottom:.625rem}',\n '.sp-root .sp-prose ol{list-style:decimal;padding-left:1.25rem;margin-bottom:.625rem}',\n '.sp-root .sp-prose li{margin-bottom:.25rem}',\n '.sp-root .sp-prose strong{color:var(--sp-text-strong);font-weight:600}',\n '.sp-root .sp-prose h2,.sp-root .sp-prose h3{color:var(--sp-text);font-weight:600;margin:.875rem 0 .375rem;font-size:1rem}',\n '.sp-root .sp-prose code{background:var(--sp-code-bg);border:1px solid var(--sp-code-border);padding:.1rem .35rem;border-radius:.25rem;font-size:.82em;color:var(--sp-text)}',\n '.sp-root .sp-prose blockquote{border-left:3px solid var(--sp-border);padding-left:1rem;color:var(--sp-text-muted);margin:.75rem 0}',\n `.sp-root .sp-pair{display:grid;grid-template-columns:1fr 1fr;gap:${gap}}`,\n '@media(max-width:640px){.sp-root .sp-pair{grid-template-columns:1fr}}',\n ].join('');\n}\n\n/**\n * Returns the stylesheet a renderer injects.\n *\n * @param accent brand colour. Accepts anything CSS does; `--sp-accent-bg` and\n * `--sp-accent-border` are derived from it so a customer sets one value\n * rather than three. Defaults to DEFAULT_ACCENT.\n * @param unit length unit for layout rules. 'px' for this package, 'rem' for the app's\n * server renderer, which sizes in rem throughout.\n * @param scope selector the custom properties are declared on. Defaults to `.sp-root`, which is\n * what a renderer injecting this at runtime wants. `tokens.css` is generated with\n * STYLESHEET_SCOPE instead, so importing it works without a wrapper.\n */\nexport function buildTokenCss({ accent, unit = 'px', scope = `.${SP_ROOT}`, theme = 'dark' }: { accent?: string; unit?: 'px' | 'rem'; scope?: string; theme?: SpTheme } = {}): string {\n const resolved = accent ?? (theme === 'light' ? DEFAULT_ACCENT_LIGHT : DEFAULT_ACCENT);\n const decls = Object.entries(palette(resolved, theme)).map(([k, v]) => `${k}:${v}`).join(';');\n return `${scope}{${decls}}${rules(unit)}`;\n}\n"],"mappings":"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","names":["jsx","jsxs","res","_a"]}
|
package/dist/tokens.css
CHANGED
package/dist/tokens.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tokens.css"],"sourcesContent":["/* Generated by scripts/gen-tokens-css.ts from src/tokens.ts. Do not edit by hand. */\n/* Import with: import '@spectare-personalisation/react/tokens.css' */\n/* Only needed when composing the exported components directly. ComponentRenderer injects the */\n/* same CSS at runtime, so a PersonalisedSection host needs nothing. */\n/* */\n/* Declared on :where(:root) as well as .sp-root, so composing a single component needs no */\n/* wrapper. :where() carries no specificity, so any rule you write beats these defaults. */\n\n:where(:root),.sp-root{--sp-accent:#60a5fa;--sp-accent-bg:color-mix(in srgb,#60a5fa 10%,transparent);--sp-accent-border:color-mix(in srgb,#60a5fa 20%,transparent);--sp-bg:#18181b;--sp-surface:#09090b;--sp-border:#27272a;--sp-text:#f4f4f5;--sp-text-sub:#
|
|
1
|
+
{"version":3,"sources":["../src/tokens.css"],"sourcesContent":["/* Generated by scripts/gen-tokens-css.ts from src/tokens.ts. Do not edit by hand. */\n/* Import with: import '@spectare-personalisation/react/tokens.css' */\n/* Only needed when composing the exported components directly. ComponentRenderer injects the */\n/* same CSS at runtime, so a PersonalisedSection host needs nothing. */\n/* */\n/* Declared on :where(:root) as well as .sp-root, so composing a single component needs no */\n/* wrapper. :where() carries no specificity, so any rule you write beats these defaults. */\n\n:where(:root),.sp-root{--sp-accent:#60a5fa;--sp-accent-bg:color-mix(in srgb,#60a5fa 10%,transparent);--sp-accent-border:color-mix(in srgb,#60a5fa 20%,transparent);--sp-bg:#18181b;--sp-surface:#09090b;--sp-border:#27272a;--sp-text:#f4f4f5;--sp-text-sub:#e4e4e7;--sp-text-strong:#ececee;--sp-text-muted:#82828b;--sp-text-dim:#6b6b74;--sp-text-body:#a1a1aa;--sp-positive:#6ee7b7;--sp-cta-bg:#fff;--sp-cta-text:#09090b;--sp-divider:rgba(255,255,255,0.06);--sp-code-bg:rgba(255,255,255,0.07);--sp-code-border:rgba(255,255,255,0.08);--sp-pre-bg:rgba(0,0,0,0.4)}.sp-root .sp-prose p{margin-bottom:.625rem}.sp-root .sp-prose p:last-child{margin-bottom:0}.sp-root .sp-prose ul{list-style:disc;padding-left:1.25rem;margin-bottom:.625rem}.sp-root .sp-prose ol{list-style:decimal;padding-left:1.25rem;margin-bottom:.625rem}.sp-root .sp-prose li{margin-bottom:.25rem}.sp-root .sp-prose strong{color:var(--sp-text-strong);font-weight:600}.sp-root .sp-prose h2,.sp-root .sp-prose h3{color:var(--sp-text);font-weight:600;margin:.875rem 0 .375rem;font-size:1rem}.sp-root .sp-prose code{background:var(--sp-code-bg);border:1px solid var(--sp-code-border);padding:.1rem .35rem;border-radius:.25rem;font-size:.82em;color:var(--sp-text)}.sp-root .sp-prose blockquote{border-left:3px solid var(--sp-border);padding-left:1rem;color:var(--sp-text-muted);margin:.75rem 0}.sp-root .sp-pair{display:grid;grid-template-columns:1fr 1fr;gap:20px}@media(max-width:640px){.sp-root .sp-pair{grid-template-columns:1fr}}\n"],"mappings":";AAQA,OAAO;AAAO,CAAC;AAAQ,cAAY;AAAQ,iBAAe,UAAU,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC;AAAa,qBAAmB,UAAU,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC;AAAa,UAAQ;AAAQ,eAAa;AAAQ,cAAY;AAAQ,YAAU;AAAQ,gBAAc;AAAQ,mBAAiB;AAAQ,kBAAgB;AAAQ,gBAAc;AAAQ,iBAAe;AAAQ,gBAAc;AAAQ,cAAY;AAAK,gBAAc;AAAQ,eAAa,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;AAAM,eAAa,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;AAAM,mBAAiB,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;AAAM,cAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAAI;AAAC,CAA5hB,QAAqiB,CAAC,SAAS;AAAE,iBAAc;AAAO;AAAC,CAAvkB,QAAglB,CAA1C,SAAoD,CAAC;AAAY,iBAAc;AAAC;AAAC,CAAvnB,QAAgoB,CAA1F,SAAoG;AAAG,cAAW;AAAK,gBAAa;AAAQ,iBAAc;AAAO;AAAC,CAAxsB,QAAitB,CAA3K,SAAqL;AAAG,cAAW;AAAQ,gBAAa;AAAQ,iBAAc;AAAO;AAAC,CAA5xB,QAAqyB,CAA/P,SAAyQ;AAAG,iBAAc;AAAM;AAAC,CAAv0B,QAAg1B,CAA1S,SAAoT;AAAO,SAAM,IAAI;AAAkB,eAAY;AAAG;AAAC,CAA74B,QAAs5B,CAAhX,SAA0X;AAAG,CAAn6B,QAA46B,CAAtY,SAAgZ;AAAG,SAAM,IAAI;AAAW,eAAY;AAAI,UAAO,QAAQ,EAAE;AAAQ,aAAU;AAAI;AAAC,CAAtgC,QAA+gC,CAAze,SAAmf;AAAK,cAAW,IAAI;AAAc,UAAO,IAAI,MAAM,IAAI;AAAkB,WAAQ,MAAM;AAAO,iBAAc;AAAO,aAAU;AAAM,SAAM,IAAI;AAAU;AAAC,CAAjrC,QAA0rC,CAAppB,SAA8pB;AAAW,eAAY,IAAI,MAAM,IAAI;AAAa,gBAAa;AAAK,SAAM,IAAI;AAAiB,UAAO,OAAO;AAAC;AAAC,CAAnzC,QAA4zC,CAAC;AAAQ,WAAQ;AAAK,yBAAsB,IAAI;AAAI,OAAI;AAAI;AAAC,QAAM,WAAW;AAAO,GAAj5C,QAA05C,CAA7F;AAAsG,2BAAsB;AAAG;AAAC;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spectare-personalisation/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "React components for Spectare AI website personalisation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"spectare",
|
|
@@ -45,4 +45,4 @@
|
|
|
45
45
|
"tsup": "^8.0.0",
|
|
46
46
|
"typescript": "^5"
|
|
47
47
|
}
|
|
48
|
-
}
|
|
48
|
+
}
|