@neowhale/storefront 0.2.52 → 0.2.54

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.
@@ -380,10 +380,15 @@ var WhaleStorefront = (function (exports) {
380
380
  // src/shims/jsx-runtime-global.ts
381
381
  var R2 = globalThis.React;
382
382
  function jsx(type, props, key) {
383
+ if (props == null) props = {};
383
384
  const { children, ...rest } = props;
384
385
  if (key !== void 0) rest.key = key;
385
- if (children === void 0) return R2.createElement(type, rest);
386
- if (Array.isArray(children)) return R2.createElement(type, rest, ...children);
386
+ if (children === void 0 || children === null) {
387
+ return R2.createElement(type, rest);
388
+ }
389
+ if (Array.isArray(children)) {
390
+ return R2.createElement.apply(null, [type, rest].concat(children));
391
+ }
387
392
  return R2.createElement(type, rest, children);
388
393
  }
389
394
  var Fragment2 = R2.Fragment;
@@ -464,8 +469,52 @@ var WhaleStorefront = (function (exports) {
464
469
  }
465
470
 
466
471
  // src/react/components/sections/content-sections.tsx
467
- function HeroSection({ section, theme, tracking, onEvent }) {
468
- const { title, subtitle, background_image, cta_text, cta_url, review_line } = section.content;
472
+ var GOOGLE_G = '<svg width="18" height="18" viewBox="0 0 48 48"><path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/><path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/><path fill="#FBBC05" d="M10.53 28.59a14.5 14.5 0 010-9.18l-7.98-6.19a24.03 24.03 0 000 21.56l7.98-6.19z"/><path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/></svg>';
473
+ function HeroSection({ section, theme, tracking, onEvent, data }) {
474
+ const c = section.content;
475
+ const [formOpen, setFormOpen] = useState(false);
476
+ const [firstName, setFirstName] = useState("");
477
+ const [email, setEmail] = useState("");
478
+ const [status, setStatus] = useState("idle");
479
+ const [errorMsg, setErrorMsg] = useState("");
480
+ const gatewayUrl = data?.gatewayUrl || "https://whale-gateway.fly.dev";
481
+ const storeId = data?.store?.id;
482
+ const slug = data?.landing_page?.slug;
483
+ async function handleSubmit(e) {
484
+ e.preventDefault();
485
+ if (!email || !storeId) return;
486
+ setStatus("loading");
487
+ setErrorMsg("");
488
+ const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
489
+ try {
490
+ const res = await fetch(`${gatewayUrl}/v1/stores/${storeId}/storefront/leads`, {
491
+ method: "POST",
492
+ headers: { "Content-Type": "application/json" },
493
+ body: JSON.stringify({
494
+ email,
495
+ first_name: firstName || void 0,
496
+ source: c.inline_form?.source || "landing_page",
497
+ landing_page_slug: slug || void 0,
498
+ tags: c.inline_form?.tags || void 0,
499
+ visitor_id: data?.analyticsContext?.visitorId || void 0,
500
+ session_id: data?.analyticsContext?.sessionId || void 0,
501
+ utm_source: urlParams?.get("utm_source") || void 0,
502
+ utm_medium: urlParams?.get("utm_medium") || void 0,
503
+ utm_campaign: urlParams?.get("utm_campaign") || void 0
504
+ })
505
+ });
506
+ if (!res.ok) {
507
+ const body = await res.json().catch(() => ({}));
508
+ throw new Error(body?.error?.message || "something went wrong.");
509
+ }
510
+ setStatus("success");
511
+ onEvent?.("lead", { email, first_name: firstName || void 0, source: c.inline_form?.source || "landing_page" });
512
+ } catch (err) {
513
+ setErrorMsg(err instanceof Error ? err.message : "something went wrong.");
514
+ setStatus("error");
515
+ }
516
+ }
517
+ const hasInlineForm = !!c.inline_form;
469
518
  return /* @__PURE__ */ jsx("div", { style: {
470
519
  position: "relative",
471
520
  minHeight: "60vh",
@@ -475,36 +524,56 @@ var WhaleStorefront = (function (exports) {
475
524
  alignItems: "center",
476
525
  textAlign: "center",
477
526
  padding: "3rem 1.5rem",
478
- backgroundImage: background_image ? `url(${background_image})` : void 0,
527
+ backgroundImage: c.background_image ? `url(${c.background_image})` : void 0,
479
528
  backgroundSize: "cover",
480
529
  backgroundPosition: "center"
481
530
  }, children: [
482
- background_image && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)" } }),
483
- /* @__PURE__ */ jsx("div", { style: { position: "relative", zIndex: 1, maxWidth: 640 }, children: [
484
- title && /* @__PURE__ */ jsx("h1", { style: {
485
- fontSize: "clamp(2rem, 8vw, 3rem)",
531
+ c.background_image && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)" } }),
532
+ /* @__PURE__ */ jsx("div", { style: { position: "relative", zIndex: 1, maxWidth: 640, width: "100%" }, children: [
533
+ c.title && /* @__PURE__ */ jsx("h1", { style: {
534
+ fontSize: "clamp(2rem, 7vw, 3.25rem)",
486
535
  fontWeight: 300,
487
536
  fontFamily: theme.fontDisplay || "inherit",
488
- margin: "0 0 1rem",
489
- lineHeight: 1.15,
490
- letterSpacing: "-0.02em",
537
+ margin: "0 0 1.25rem",
538
+ lineHeight: 1.08,
539
+ letterSpacing: "-0.03em",
491
540
  color: theme.fg
492
- }, children: /* @__PURE__ */ jsx(AnimatedText, { text: title }) }),
493
- subtitle && /* @__PURE__ */ jsx("p", { style: {
494
- fontSize: "0.85rem",
541
+ }, children: /* @__PURE__ */ jsx(AnimatedText, { text: c.title }) }),
542
+ c.subtitle && /* @__PURE__ */ jsx("p", { style: {
543
+ fontSize: "clamp(0.9rem, 2.5vw, 1.1rem)",
495
544
  color: theme.accent,
496
545
  margin: "0 0 2rem",
497
546
  lineHeight: 1.6,
498
547
  textTransform: "uppercase",
499
- letterSpacing: "0.15em"
500
- }, children: subtitle }),
501
- cta_text && cta_url && /* @__PURE__ */ jsx(
548
+ letterSpacing: "0.1em"
549
+ }, children: c.subtitle }),
550
+ hasInlineForm ? /* @__PURE__ */ jsx(
551
+ HeroInlineForm,
552
+ {
553
+ ctaText: c.cta_text || "claim it",
554
+ formOpen,
555
+ setFormOpen,
556
+ firstName,
557
+ setFirstName,
558
+ email,
559
+ setEmail,
560
+ status,
561
+ errorMsg,
562
+ onSubmit: handleSubmit,
563
+ successHeading: c.inline_form.success_heading || "you're in.",
564
+ successMessage: c.inline_form.success_message || "check your inbox.",
565
+ submitText: c.inline_form.button_text || "send my code",
566
+ theme,
567
+ onEvent,
568
+ tracking
569
+ }
570
+ ) : c.cta_text && c.cta_url ? /* @__PURE__ */ jsx(
502
571
  "a",
503
572
  {
504
- href: cta_url,
573
+ href: c.cta_url,
505
574
  onClick: () => {
506
- trackClick(tracking, cta_text, cta_url);
507
- onEvent?.("cta_click", { label: cta_text, url: cta_url });
575
+ trackClick(tracking, c.cta_text, c.cta_url);
576
+ onEvent?.("cta_click", { label: c.cta_text, url: c.cta_url });
508
577
  },
509
578
  style: {
510
579
  display: "inline-block",
@@ -517,13 +586,111 @@ var WhaleStorefront = (function (exports) {
517
586
  letterSpacing: "0.08em",
518
587
  textTransform: "uppercase"
519
588
  },
520
- children: cta_text
589
+ children: c.cta_text
521
590
  }
522
- ),
523
- review_line && review_line.count > 0 && /* @__PURE__ */ jsx(ReviewLine, { rating: review_line.rating, count: review_line.count, source: review_line.source, url: review_line.url, accent: theme.accent, fg: theme.fg })
591
+ ) : null,
592
+ c.review_line && c.review_line.count > 0 && /* @__PURE__ */ jsx(ReviewLine, { rating: c.review_line.rating, count: c.review_line.count, source: c.review_line.source, url: c.review_line.url, accent: theme.accent, fg: theme.fg })
524
593
  ] })
525
594
  ] });
526
595
  }
596
+ function HeroInlineForm({ ctaText, formOpen, setFormOpen, firstName, setFirstName, email, setEmail, status, errorMsg, onSubmit, successHeading, successMessage, submitText, theme, onEvent, tracking }) {
597
+ if (status === "success") {
598
+ return /* @__PURE__ */ jsx("div", { style: { padding: "1.25rem 2rem", background: `${theme.fg}08`, border: `1px solid ${theme.fg}15`, maxWidth: 420, margin: "0 auto" }, children: [
599
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "1.1rem", fontWeight: 300, color: theme.fg, margin: "0 0 0.25rem", fontFamily: theme.fontDisplay || "inherit" }, children: successHeading }),
600
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "0.8rem", color: `${theme.fg}80`, margin: 0 }, children: successMessage })
601
+ ] });
602
+ }
603
+ if (!formOpen) {
604
+ return /* @__PURE__ */ jsx(
605
+ "button",
606
+ {
607
+ onClick: () => {
608
+ setFormOpen(true);
609
+ trackClick(tracking, ctaText, "#form");
610
+ onEvent?.("cta_click", { label: ctaText });
611
+ },
612
+ style: {
613
+ display: "inline-block",
614
+ padding: "0.875rem 2rem",
615
+ background: theme.fg,
616
+ color: theme.bg,
617
+ border: "none",
618
+ cursor: "pointer",
619
+ fontSize: "0.85rem",
620
+ fontWeight: 500,
621
+ letterSpacing: "0.08em",
622
+ textTransform: "uppercase",
623
+ fontFamily: "inherit",
624
+ transition: "transform 0.2s"
625
+ },
626
+ children: ctaText
627
+ }
628
+ );
629
+ }
630
+ const inputStyle = {
631
+ flex: 1,
632
+ minWidth: 0,
633
+ padding: "0.875rem 1rem",
634
+ background: theme.surface,
635
+ border: `1px solid ${theme.fg}25`,
636
+ color: theme.fg,
637
+ fontSize: "0.9rem",
638
+ fontWeight: 300,
639
+ outline: "none",
640
+ fontFamily: "inherit",
641
+ boxSizing: "border-box"
642
+ };
643
+ return /* @__PURE__ */ jsx("form", { onSubmit, style: { maxWidth: 480, margin: "0 auto" }, children: [
644
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 0 }, children: [
645
+ /* @__PURE__ */ jsx(
646
+ "input",
647
+ {
648
+ type: "text",
649
+ placeholder: "first name",
650
+ value: firstName,
651
+ autoFocus: true,
652
+ onChange: (e) => setFirstName(e.target.value),
653
+ style: { ...inputStyle, borderRight: "none" }
654
+ }
655
+ ),
656
+ /* @__PURE__ */ jsx(
657
+ "input",
658
+ {
659
+ type: "email",
660
+ placeholder: "email",
661
+ value: email,
662
+ required: true,
663
+ onChange: (e) => setEmail(e.target.value),
664
+ style: { ...inputStyle, borderRight: "none" }
665
+ }
666
+ ),
667
+ /* @__PURE__ */ jsx(
668
+ "button",
669
+ {
670
+ type: "submit",
671
+ disabled: status === "loading",
672
+ style: {
673
+ padding: "0.875rem 1.25rem",
674
+ background: theme.fg,
675
+ color: theme.bg,
676
+ border: "none",
677
+ fontSize: "0.75rem",
678
+ fontWeight: 600,
679
+ letterSpacing: "0.08em",
680
+ textTransform: "uppercase",
681
+ cursor: status === "loading" ? "wait" : "pointer",
682
+ fontFamily: "inherit",
683
+ whiteSpace: "nowrap",
684
+ flexShrink: 0,
685
+ opacity: status === "loading" ? 0.7 : 1
686
+ },
687
+ children: status === "loading" ? "..." : submitText
688
+ }
689
+ )
690
+ ] }),
691
+ status === "error" && errorMsg && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.75rem", color: "#e55", margin: "0.5rem 0 0", textAlign: "left" }, children: errorMsg })
692
+ ] });
693
+ }
527
694
  function TextSection({ section, theme }) {
528
695
  const { heading, body } = section.content;
529
696
  const align = section.config?.align || "left";
@@ -675,25 +842,21 @@ var WhaleStorefront = (function (exports) {
675
842
  }
676
843
  function ReviewLine({ rating, count, source, url, accent, fg }) {
677
844
  const label = `${rating.toFixed(1)} \xB7 ${count} ${source || "reviews"}`;
678
- const stars = /* @__PURE__ */ jsx("span", { style: { display: "inline-flex", gap: "1px" }, children: [1, 2, 3, 4, 5].map((s) => /* @__PURE__ */ jsx("svg", { width: 14, height: 14, viewBox: "0 0 20 20", fill: s <= Math.round(rating) ? accent : `${fg}20`, children: /* @__PURE__ */ jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }, s)) });
679
- const text = /* @__PURE__ */ jsx("span", { style: { fontSize: "0.8rem", color: `${fg}80`, fontWeight: 500 }, children: label });
680
- const inner = /* @__PURE__ */ jsx("span", { style: { display: "inline-flex", alignItems: "center", gap: "0.5rem" }, children: [
681
- stars,
682
- text
845
+ const content = /* @__PURE__ */ jsx("div", { style: {
846
+ marginTop: "1.5rem",
847
+ display: "flex",
848
+ alignItems: "center",
849
+ justifyContent: "center",
850
+ gap: "0.625rem"
851
+ }, children: [
852
+ /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: GOOGLE_G } }),
853
+ /* @__PURE__ */ jsx("span", { style: { display: "inline-flex", gap: "2px" }, children: [1, 2, 3, 4, 5].map((s) => /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 20 20", fill: s <= Math.round(rating) ? "#FBBC05" : `${fg}20`, children: /* @__PURE__ */ jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }, s)) }),
854
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "0.9rem", color: `${fg}AA`, fontWeight: 500 }, children: label })
683
855
  ] });
684
856
  if (url) {
685
- return /* @__PURE__ */ jsx("div", { style: { marginTop: "1.25rem", textAlign: "center" }, children: /* @__PURE__ */ jsx(
686
- "a",
687
- {
688
- href: url,
689
- target: "_blank",
690
- rel: "noopener noreferrer",
691
- style: { textDecoration: "none", display: "inline-flex", alignItems: "center", gap: "0.5rem" },
692
- children: inner
693
- }
694
- ) });
857
+ return /* @__PURE__ */ jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", style: { textDecoration: "none", display: "block" }, children: content });
695
858
  }
696
- return /* @__PURE__ */ jsx("div", { style: { marginTop: "1.25rem", display: "flex", justifyContent: "center" }, children: inner });
859
+ return content;
697
860
  }
698
861
 
699
862
  // src/react/components/sections/interactive-sections.tsx
@@ -1556,7 +1719,7 @@ var WhaleStorefront = (function (exports) {
1556
1719
  const el = (() => {
1557
1720
  switch (section.type) {
1558
1721
  case "hero":
1559
- return /* @__PURE__ */ jsx(HeroSection, { section, theme, tracking, onEvent });
1722
+ return /* @__PURE__ */ jsx(HeroSection, { section, theme, tracking, onEvent, data });
1560
1723
  case "collage_hero":
1561
1724
  return /* @__PURE__ */ jsx(CollageHeroSection, { section, theme, tracking, onEvent });
1562
1725
  case "text":
@@ -2208,8 +2208,52 @@ function AnimatedText({ text }) {
2208
2208
  (part, i) => NUM_TEST.test(part) ? /* @__PURE__ */ jsxRuntime.jsx(AnimatedNumber, { raw: part }, i) : part
2209
2209
  ) });
2210
2210
  }
2211
- function HeroSection({ section, theme, tracking, onEvent }) {
2212
- const { title, subtitle, background_image, cta_text, cta_url, review_line } = section.content;
2211
+ var GOOGLE_G = '<svg width="18" height="18" viewBox="0 0 48 48"><path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/><path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/><path fill="#FBBC05" d="M10.53 28.59a14.5 14.5 0 010-9.18l-7.98-6.19a24.03 24.03 0 000 21.56l7.98-6.19z"/><path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/></svg>';
2212
+ function HeroSection({ section, theme, tracking, onEvent, data }) {
2213
+ const c = section.content;
2214
+ const [formOpen, setFormOpen] = react.useState(false);
2215
+ const [firstName, setFirstName] = react.useState("");
2216
+ const [email, setEmail] = react.useState("");
2217
+ const [status, setStatus] = react.useState("idle");
2218
+ const [errorMsg, setErrorMsg] = react.useState("");
2219
+ const gatewayUrl = data?.gatewayUrl || "https://whale-gateway.fly.dev";
2220
+ const storeId = data?.store?.id;
2221
+ const slug = data?.landing_page?.slug;
2222
+ async function handleSubmit(e) {
2223
+ e.preventDefault();
2224
+ if (!email || !storeId) return;
2225
+ setStatus("loading");
2226
+ setErrorMsg("");
2227
+ const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
2228
+ try {
2229
+ const res = await fetch(`${gatewayUrl}/v1/stores/${storeId}/storefront/leads`, {
2230
+ method: "POST",
2231
+ headers: { "Content-Type": "application/json" },
2232
+ body: JSON.stringify({
2233
+ email,
2234
+ first_name: firstName || void 0,
2235
+ source: c.inline_form?.source || "landing_page",
2236
+ landing_page_slug: slug || void 0,
2237
+ tags: c.inline_form?.tags || void 0,
2238
+ visitor_id: data?.analyticsContext?.visitorId || void 0,
2239
+ session_id: data?.analyticsContext?.sessionId || void 0,
2240
+ utm_source: urlParams?.get("utm_source") || void 0,
2241
+ utm_medium: urlParams?.get("utm_medium") || void 0,
2242
+ utm_campaign: urlParams?.get("utm_campaign") || void 0
2243
+ })
2244
+ });
2245
+ if (!res.ok) {
2246
+ const body = await res.json().catch(() => ({}));
2247
+ throw new Error(body?.error?.message || "something went wrong.");
2248
+ }
2249
+ setStatus("success");
2250
+ onEvent?.("lead", { email, first_name: firstName || void 0, source: c.inline_form?.source || "landing_page" });
2251
+ } catch (err) {
2252
+ setErrorMsg(err instanceof Error ? err.message : "something went wrong.");
2253
+ setStatus("error");
2254
+ }
2255
+ }
2256
+ const hasInlineForm = !!c.inline_form;
2213
2257
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
2214
2258
  position: "relative",
2215
2259
  minHeight: "60vh",
@@ -2219,36 +2263,56 @@ function HeroSection({ section, theme, tracking, onEvent }) {
2219
2263
  alignItems: "center",
2220
2264
  textAlign: "center",
2221
2265
  padding: "3rem 1.5rem",
2222
- backgroundImage: background_image ? `url(${background_image})` : void 0,
2266
+ backgroundImage: c.background_image ? `url(${c.background_image})` : void 0,
2223
2267
  backgroundSize: "cover",
2224
2268
  backgroundPosition: "center"
2225
2269
  }, children: [
2226
- background_image && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)" } }),
2227
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", zIndex: 1, maxWidth: 640 }, children: [
2228
- title && /* @__PURE__ */ jsxRuntime.jsx("h1", { style: {
2229
- fontSize: "clamp(2rem, 8vw, 3rem)",
2270
+ c.background_image && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)" } }),
2271
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", zIndex: 1, maxWidth: 640, width: "100%" }, children: [
2272
+ c.title && /* @__PURE__ */ jsxRuntime.jsx("h1", { style: {
2273
+ fontSize: "clamp(2rem, 7vw, 3.25rem)",
2230
2274
  fontWeight: 300,
2231
2275
  fontFamily: theme.fontDisplay || "inherit",
2232
- margin: "0 0 1rem",
2233
- lineHeight: 1.15,
2234
- letterSpacing: "-0.02em",
2276
+ margin: "0 0 1.25rem",
2277
+ lineHeight: 1.08,
2278
+ letterSpacing: "-0.03em",
2235
2279
  color: theme.fg
2236
- }, children: /* @__PURE__ */ jsxRuntime.jsx(AnimatedText, { text: title }) }),
2237
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
2238
- fontSize: "0.85rem",
2280
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(AnimatedText, { text: c.title }) }),
2281
+ c.subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
2282
+ fontSize: "clamp(0.9rem, 2.5vw, 1.1rem)",
2239
2283
  color: theme.accent,
2240
2284
  margin: "0 0 2rem",
2241
2285
  lineHeight: 1.6,
2242
2286
  textTransform: "uppercase",
2243
- letterSpacing: "0.15em"
2244
- }, children: subtitle }),
2245
- cta_text && cta_url && /* @__PURE__ */ jsxRuntime.jsx(
2287
+ letterSpacing: "0.1em"
2288
+ }, children: c.subtitle }),
2289
+ hasInlineForm ? /* @__PURE__ */ jsxRuntime.jsx(
2290
+ HeroInlineForm,
2291
+ {
2292
+ ctaText: c.cta_text || "claim it",
2293
+ formOpen,
2294
+ setFormOpen,
2295
+ firstName,
2296
+ setFirstName,
2297
+ email,
2298
+ setEmail,
2299
+ status,
2300
+ errorMsg,
2301
+ onSubmit: handleSubmit,
2302
+ successHeading: c.inline_form.success_heading || "you're in.",
2303
+ successMessage: c.inline_form.success_message || "check your inbox.",
2304
+ submitText: c.inline_form.button_text || "send my code",
2305
+ theme,
2306
+ onEvent,
2307
+ tracking
2308
+ }
2309
+ ) : c.cta_text && c.cta_url ? /* @__PURE__ */ jsxRuntime.jsx(
2246
2310
  "a",
2247
2311
  {
2248
- href: cta_url,
2312
+ href: c.cta_url,
2249
2313
  onClick: () => {
2250
- trackClick(tracking, cta_text, cta_url);
2251
- onEvent?.("cta_click", { label: cta_text, url: cta_url });
2314
+ trackClick(tracking, c.cta_text, c.cta_url);
2315
+ onEvent?.("cta_click", { label: c.cta_text, url: c.cta_url });
2252
2316
  },
2253
2317
  style: {
2254
2318
  display: "inline-block",
@@ -2261,13 +2325,111 @@ function HeroSection({ section, theme, tracking, onEvent }) {
2261
2325
  letterSpacing: "0.08em",
2262
2326
  textTransform: "uppercase"
2263
2327
  },
2264
- children: cta_text
2328
+ children: c.cta_text
2265
2329
  }
2266
- ),
2267
- review_line && review_line.count > 0 && /* @__PURE__ */ jsxRuntime.jsx(ReviewLine, { rating: review_line.rating, count: review_line.count, source: review_line.source, url: review_line.url, accent: theme.accent, fg: theme.fg })
2330
+ ) : null,
2331
+ c.review_line && c.review_line.count > 0 && /* @__PURE__ */ jsxRuntime.jsx(ReviewLine, { rating: c.review_line.rating, count: c.review_line.count, source: c.review_line.source, url: c.review_line.url, accent: theme.accent, fg: theme.fg })
2268
2332
  ] })
2269
2333
  ] });
2270
2334
  }
2335
+ function HeroInlineForm({ ctaText, formOpen, setFormOpen, firstName, setFirstName, email, setEmail, status, errorMsg, onSubmit, successHeading, successMessage, submitText, theme, onEvent, tracking }) {
2336
+ if (status === "success") {
2337
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1.25rem 2rem", background: `${theme.fg}08`, border: `1px solid ${theme.fg}15`, maxWidth: 420, margin: "0 auto" }, children: [
2338
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "1.1rem", fontWeight: 300, color: theme.fg, margin: "0 0 0.25rem", fontFamily: theme.fontDisplay || "inherit" }, children: successHeading }),
2339
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.8rem", color: `${theme.fg}80`, margin: 0 }, children: successMessage })
2340
+ ] });
2341
+ }
2342
+ if (!formOpen) {
2343
+ return /* @__PURE__ */ jsxRuntime.jsx(
2344
+ "button",
2345
+ {
2346
+ onClick: () => {
2347
+ setFormOpen(true);
2348
+ trackClick(tracking, ctaText, "#form");
2349
+ onEvent?.("cta_click", { label: ctaText });
2350
+ },
2351
+ style: {
2352
+ display: "inline-block",
2353
+ padding: "0.875rem 2rem",
2354
+ background: theme.fg,
2355
+ color: theme.bg,
2356
+ border: "none",
2357
+ cursor: "pointer",
2358
+ fontSize: "0.85rem",
2359
+ fontWeight: 500,
2360
+ letterSpacing: "0.08em",
2361
+ textTransform: "uppercase",
2362
+ fontFamily: "inherit",
2363
+ transition: "transform 0.2s"
2364
+ },
2365
+ children: ctaText
2366
+ }
2367
+ );
2368
+ }
2369
+ const inputStyle = {
2370
+ flex: 1,
2371
+ minWidth: 0,
2372
+ padding: "0.875rem 1rem",
2373
+ background: theme.surface,
2374
+ border: `1px solid ${theme.fg}25`,
2375
+ color: theme.fg,
2376
+ fontSize: "0.9rem",
2377
+ fontWeight: 300,
2378
+ outline: "none",
2379
+ fontFamily: "inherit",
2380
+ boxSizing: "border-box"
2381
+ };
2382
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, style: { maxWidth: 480, margin: "0 auto" }, children: [
2383
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 0 }, children: [
2384
+ /* @__PURE__ */ jsxRuntime.jsx(
2385
+ "input",
2386
+ {
2387
+ type: "text",
2388
+ placeholder: "first name",
2389
+ value: firstName,
2390
+ autoFocus: true,
2391
+ onChange: (e) => setFirstName(e.target.value),
2392
+ style: { ...inputStyle, borderRight: "none" }
2393
+ }
2394
+ ),
2395
+ /* @__PURE__ */ jsxRuntime.jsx(
2396
+ "input",
2397
+ {
2398
+ type: "email",
2399
+ placeholder: "email",
2400
+ value: email,
2401
+ required: true,
2402
+ onChange: (e) => setEmail(e.target.value),
2403
+ style: { ...inputStyle, borderRight: "none" }
2404
+ }
2405
+ ),
2406
+ /* @__PURE__ */ jsxRuntime.jsx(
2407
+ "button",
2408
+ {
2409
+ type: "submit",
2410
+ disabled: status === "loading",
2411
+ style: {
2412
+ padding: "0.875rem 1.25rem",
2413
+ background: theme.fg,
2414
+ color: theme.bg,
2415
+ border: "none",
2416
+ fontSize: "0.75rem",
2417
+ fontWeight: 600,
2418
+ letterSpacing: "0.08em",
2419
+ textTransform: "uppercase",
2420
+ cursor: status === "loading" ? "wait" : "pointer",
2421
+ fontFamily: "inherit",
2422
+ whiteSpace: "nowrap",
2423
+ flexShrink: 0,
2424
+ opacity: status === "loading" ? 0.7 : 1
2425
+ },
2426
+ children: status === "loading" ? "..." : submitText
2427
+ }
2428
+ )
2429
+ ] }),
2430
+ status === "error" && errorMsg && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.75rem", color: "#e55", margin: "0.5rem 0 0", textAlign: "left" }, children: errorMsg })
2431
+ ] });
2432
+ }
2271
2433
  function TextSection({ section, theme }) {
2272
2434
  const { heading, body } = section.content;
2273
2435
  const align = section.config?.align || "left";
@@ -2419,25 +2581,21 @@ function toEmbedUrl(url) {
2419
2581
  }
2420
2582
  function ReviewLine({ rating, count, source, url, accent, fg }) {
2421
2583
  const label = `${rating.toFixed(1)} \xB7 ${count} ${source || "reviews"}`;
2422
- const stars = /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-flex", gap: "1px" }, children: [1, 2, 3, 4, 5].map((s) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 14, height: 14, viewBox: "0 0 20 20", fill: s <= Math.round(rating) ? accent : `${fg}20`, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }, s)) });
2423
- const text = /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.8rem", color: `${fg}80`, fontWeight: 500 }, children: label });
2424
- const inner = /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: "0.5rem" }, children: [
2425
- stars,
2426
- text
2584
+ const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
2585
+ marginTop: "1.5rem",
2586
+ display: "flex",
2587
+ alignItems: "center",
2588
+ justifyContent: "center",
2589
+ gap: "0.625rem"
2590
+ }, children: [
2591
+ /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: GOOGLE_G } }),
2592
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-flex", gap: "2px" }, children: [1, 2, 3, 4, 5].map((s) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 16, height: 16, viewBox: "0 0 20 20", fill: s <= Math.round(rating) ? "#FBBC05" : `${fg}20`, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }, s)) }),
2593
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.9rem", color: `${fg}AA`, fontWeight: 500 }, children: label })
2427
2594
  ] });
2428
2595
  if (url) {
2429
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "1.25rem", textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(
2430
- "a",
2431
- {
2432
- href: url,
2433
- target: "_blank",
2434
- rel: "noopener noreferrer",
2435
- style: { textDecoration: "none", display: "inline-flex", alignItems: "center", gap: "0.5rem" },
2436
- children: inner
2437
- }
2438
- ) });
2596
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", style: { textDecoration: "none", display: "block" }, children: content });
2439
2597
  }
2440
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "1.25rem", display: "flex", justifyContent: "center" }, children: inner });
2598
+ return content;
2441
2599
  }
2442
2600
  function CTASection({ section, theme, tracking, onEvent }) {
2443
2601
  const { title, subtitle, buttons } = section.content;
@@ -3292,7 +3450,7 @@ function SectionRenderer({
3292
3450
  const el = (() => {
3293
3451
  switch (section.type) {
3294
3452
  case "hero":
3295
- return /* @__PURE__ */ jsxRuntime.jsx(HeroSection, { section, theme, tracking, onEvent });
3453
+ return /* @__PURE__ */ jsxRuntime.jsx(HeroSection, { section, theme, tracking, onEvent, data });
3296
3454
  case "collage_hero":
3297
3455
  return /* @__PURE__ */ jsxRuntime.jsx(CollageHeroSection, { section, theme, tracking, onEvent });
3298
3456
  case "text":