@neowhale/storefront 0.2.8 → 0.2.9

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.
@@ -1264,25 +1264,34 @@ function QRLandingPage({
1264
1264
  if (state === "error") return /* @__PURE__ */ jsxRuntime.jsx(DefaultError, { message: errorMsg });
1265
1265
  if (!data) return null;
1266
1266
  if (renderPage) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderPage(data) });
1267
- return /* @__PURE__ */ jsxRuntime.jsx(DefaultLayout, { data, renderProduct, renderCOA });
1267
+ return /* @__PURE__ */ jsxRuntime.jsx(ProductLanding, { data, renderProduct, renderCOA });
1268
1268
  }
1269
- function DefaultLayout({
1269
+ function extractTheme(data) {
1270
+ const lp = data.qr_code.landing_page;
1271
+ const t = data.store?.theme;
1272
+ return {
1273
+ bg: lp.background_color || t?.background || "#050505",
1274
+ fg: lp.text_color || t?.foreground || "#fafafa",
1275
+ accent: t?.accent || "#E8E2D9",
1276
+ accentDark: t?.accentDark || "#C8BFB2",
1277
+ surface: t?.surface || "#0C0C0C",
1278
+ surfaceLight: t?.surfaceLight || "#141414",
1279
+ muted: t?.muted || "#8A8A8A",
1280
+ border: t?.border || "#1C1C1C",
1281
+ fontDisplay: t?.fontDisplay || "system-ui, -apple-system, sans-serif",
1282
+ fontBody: t?.fontBody || "system-ui, -apple-system, sans-serif",
1283
+ radius: t?.radius || "0px"
1284
+ };
1285
+ }
1286
+ function ProductLanding({
1270
1287
  data,
1271
1288
  renderProduct,
1272
1289
  renderCOA
1273
1290
  }) {
1274
1291
  const { qr_code: qr, store, product, coa } = data;
1275
1292
  const lp = qr.landing_page;
1293
+ const theme = extractTheme(data);
1276
1294
  const [showCOA, setShowCOA] = react.useState(false);
1277
- const bg = lp.background_color || store?.theme?.background || "#050505";
1278
- const fg = lp.text_color || store?.theme?.foreground || "#fafafa";
1279
- const accent = store?.theme?.accent || qr.brand_color || "#E8E2D9";
1280
- const surface = store?.theme?.surface || "#0C0C0C";
1281
- const surfaceLight = store?.theme?.surfaceLight || "#141414";
1282
- const muted = store?.theme?.muted || "#888";
1283
- const border = store?.theme?.border || "#1C1C1C";
1284
- const fontDisplay = store?.theme?.fontDisplay || "system-ui, -apple-system, sans-serif";
1285
- const fontBody = store?.theme?.fontBody || "system-ui, -apple-system, sans-serif";
1286
1295
  const logoUrl = qr.logo_url || store?.logo_url;
1287
1296
  const productImage = lp.image_url || product?.featured_image || null;
1288
1297
  const productName = lp.title || product?.name || qr.name;
@@ -1306,292 +1315,363 @@ function DefaultLayout({
1306
1315
  const handleCOAClick = react.useCallback(() => {
1307
1316
  if (coa) setShowCOA(true);
1308
1317
  }, [coa]);
1309
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minHeight: "100dvh", background: bg, color: fg, fontFamily: fontBody }, children: [
1310
- /* @__PURE__ */ jsxRuntime.jsxs("header", { style: {
1311
- padding: "1rem 1.5rem",
1318
+ const labelStyle = {
1319
+ fontSize: 11,
1320
+ fontWeight: 500,
1321
+ textTransform: "uppercase",
1322
+ letterSpacing: "0.25em",
1323
+ color: `${theme.fg}40`
1324
+ // 40 = 25% opacity
1325
+ };
1326
+ const dividerStyle = {
1327
+ border: "none",
1328
+ borderTop: `1px solid ${theme.fg}0A`,
1329
+ // 0A = 4% opacity
1330
+ margin: 0
1331
+ };
1332
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1333
+ minHeight: "100dvh",
1334
+ background: theme.bg,
1335
+ color: theme.fg,
1336
+ fontFamily: theme.fontBody
1337
+ }, children: [
1338
+ /* @__PURE__ */ jsxRuntime.jsxs("nav", { style: {
1339
+ padding: "1.25rem 1.5rem",
1312
1340
  display: "flex",
1313
1341
  alignItems: "center",
1314
1342
  justifyContent: "space-between",
1315
- borderBottom: `1px solid ${border}`
1343
+ maxWidth: 1280,
1344
+ margin: "0 auto"
1316
1345
  }, children: [
1317
- logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl, alt: store?.name || "Store", style: { height: 32, objectFit: "contain" } }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontFamily: fontDisplay, fontWeight: 600, fontSize: "1.1rem" }, children: store?.name || "" }),
1318
- store?.name && logoUrl && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.75rem", color: muted, fontWeight: 500 }, children: store.name })
1346
+ logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl, alt: store?.name || "", style: { height: 28, objectFit: "contain" } }) : store?.name ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontFamily: theme.fontDisplay, fontWeight: 600, fontSize: "1rem", letterSpacing: "-0.02em" }, children: store.name }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
1347
+ /* @__PURE__ */ jsxRuntime.jsx(
1348
+ "a",
1349
+ {
1350
+ href: ctaUrl,
1351
+ style: {
1352
+ fontSize: 11,
1353
+ fontWeight: 500,
1354
+ textTransform: "uppercase",
1355
+ letterSpacing: "0.15em",
1356
+ color: theme.fg,
1357
+ textDecoration: "none",
1358
+ padding: "0.5rem 1.25rem",
1359
+ border: `1px solid ${theme.fg}10`,
1360
+ transition: "border-color 0.3s"
1361
+ },
1362
+ children: "Shop"
1363
+ }
1364
+ )
1319
1365
  ] }),
1320
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1321
- display: "flex",
1322
- flexDirection: "column",
1323
- maxWidth: 640,
1324
- margin: "0 auto",
1325
- padding: "0 1.5rem"
1326
- }, children: [
1366
+ /* @__PURE__ */ jsxRuntime.jsxs("main", { style: { maxWidth: 560, margin: "0 auto", padding: "0 1.5rem 3rem" }, children: [
1327
1367
  productImage && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1328
- marginTop: "1.5rem",
1329
- borderRadius: 8,
1368
+ width: "100%",
1369
+ aspectRatio: "1",
1330
1370
  overflow: "hidden",
1331
- background: surface,
1332
- aspectRatio: "4/3",
1333
- maxHeight: 320,
1371
+ background: theme.surfaceLight,
1334
1372
  display: "flex",
1335
1373
  alignItems: "center",
1336
- justifyContent: "center"
1374
+ justifyContent: "center",
1375
+ padding: "2rem"
1337
1376
  }, children: /* @__PURE__ */ jsxRuntime.jsx(
1338
1377
  "img",
1339
1378
  {
1340
1379
  src: productImage,
1341
1380
  alt: productName,
1342
- style: { width: "100%", height: "100%", objectFit: "cover" }
1381
+ style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" }
1343
1382
  }
1344
1383
  ) }),
1345
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "0.5rem", marginTop: "1.25rem", flexWrap: "wrap", alignItems: "center" }, children: [
1346
- categoryName && /* @__PURE__ */ jsxRuntime.jsx(Badge, { text: categoryName, bg: surfaceLight, color: accent }),
1347
- strainType && /* @__PURE__ */ jsxRuntime.jsx(Badge, { text: strainType, bg: strainBadgeColor(strainType), color: "#fff", bold: true }),
1348
- coa && /* @__PURE__ */ jsxRuntime.jsx(Badge, { text: "Lab Tested", bg: "rgba(34,197,94,0.15)", color: "#22c55e" })
1349
- ] }),
1350
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "0.75rem" }, children: [
1351
- /* @__PURE__ */ jsxRuntime.jsx("h1", { style: {
1352
- fontFamily: fontDisplay,
1353
- fontSize: "1.75rem",
1354
- fontWeight: 600,
1355
- margin: 0,
1356
- lineHeight: 1.2,
1357
- letterSpacing: "-0.02em"
1358
- }, children: productName }),
1359
- lowestPrice != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: {
1360
- fontSize: "1.25rem",
1384
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1.5rem", display: "flex", gap: "0.75rem", alignItems: "center" }, children: [
1385
+ categoryName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1386
+ fontSize: 11,
1361
1387
  fontWeight: 500,
1362
- color: accent,
1363
- margin: "0.375rem 0 0"
1364
- }, children: [
1365
- "From $",
1366
- lowestPrice.toFixed(2)
1367
- ] }),
1368
- tagline && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: muted, fontSize: "0.9rem", margin: "0.5rem 0 0", fontStyle: "italic" }, children: tagline })
1369
- ] }),
1370
- description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: muted, lineHeight: 1.6, margin: "1rem 0 0", fontSize: "0.9rem" }, children: description }),
1371
- renderProduct ? renderProduct(data) : null,
1372
- (thca != null || thc != null || cbd != null) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1373
- marginTop: "1.25rem",
1374
- background: surface,
1375
- border: `1px solid ${border}`,
1376
- borderRadius: 8,
1377
- padding: "1rem"
1378
- }, children: [
1379
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1380
- fontSize: "0.65rem",
1388
+ color: theme.accent,
1389
+ textTransform: "uppercase",
1390
+ letterSpacing: "0.15em"
1391
+ }, children: categoryName }),
1392
+ strainType && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1393
+ fontSize: 10,
1381
1394
  fontWeight: 600,
1382
1395
  textTransform: "uppercase",
1383
1396
  letterSpacing: "0.08em",
1384
- color: muted,
1385
- marginBottom: "0.75rem"
1386
- }, children: "Potency" }),
1387
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gridTemplateColumns: `repeat(${[thca, thc, cbd].filter((v) => v != null).length}, 1fr)`, gap: "0.5rem" }, children: [
1388
- thca != null && /* @__PURE__ */ jsxRuntime.jsx(PotencyStat, { label: "THCa", value: thca, accent, fg }),
1389
- thc != null && /* @__PURE__ */ jsxRuntime.jsx(PotencyStat, { label: "\u03949 THC", value: thc, accent, fg }),
1390
- cbd != null && /* @__PURE__ */ jsxRuntime.jsx(PotencyStat, { label: "CBD", value: cbd, accent, fg })
1391
- ] })
1397
+ padding: "0.2rem 0.5rem",
1398
+ background: strainBadgeColor(strainType),
1399
+ color: "#fff"
1400
+ }, children: strainType })
1392
1401
  ] }),
1393
- (batchNumber || dateTested || genetics || terpenes || effects) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1394
- marginTop: "0.75rem",
1395
- background: surface,
1396
- border: `1px solid ${border}`,
1397
- borderRadius: 8,
1398
- padding: "1rem"
1402
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { style: {
1403
+ fontFamily: theme.fontDisplay,
1404
+ fontSize: "clamp(2rem, 8vw, 3rem)",
1405
+ fontWeight: 300,
1406
+ margin: "0.5rem 0 0",
1407
+ lineHeight: 1.1,
1408
+ letterSpacing: "-0.02em"
1409
+ }, children: productName }),
1410
+ tagline && /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
1411
+ fontFamily: theme.fontDisplay,
1412
+ fontSize: "1.1rem",
1413
+ fontWeight: 300,
1414
+ color: `${theme.fg}80`,
1415
+ margin: "0.5rem 0 0"
1416
+ }, children: tagline }),
1417
+ lowestPrice != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: {
1418
+ fontFamily: theme.fontDisplay,
1419
+ fontSize: "1.5rem",
1420
+ fontWeight: 300,
1421
+ margin: "0.75rem 0 0"
1399
1422
  }, children: [
1400
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1401
- fontSize: "0.65rem",
1402
- fontWeight: 600,
1403
- textTransform: "uppercase",
1404
- letterSpacing: "0.08em",
1405
- color: muted,
1406
- marginBottom: "0.75rem"
1407
- }, children: "Details" }),
1408
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
1409
- genetics && /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Genetics", value: genetics, fg, muted }),
1410
- terpenes && /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Terpenes", value: terpenes, fg, muted }),
1411
- effects && /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Effects", value: effects, fg, muted }),
1412
- batchNumber && /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Batch", value: batchNumber, fg, muted }),
1413
- dateTested && /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Tested", value: formatDate(dateTested), fg, muted })
1414
- ] })
1423
+ "$",
1424
+ lowestPrice.toFixed(2),
1425
+ tiers.length > 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.8rem", color: `${theme.fg}50`, marginLeft: "0.5rem", fontWeight: 400 }, children: "and up" })
1415
1426
  ] }),
1416
- tiers.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1417
- marginTop: "0.75rem",
1418
- background: surface,
1419
- border: `1px solid ${border}`,
1420
- borderRadius: 8,
1421
- padding: "1rem"
1427
+ renderProduct ? renderProduct(data) : null,
1428
+ (thca != null || thc != null || cbd != null) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1429
+ marginTop: "1.75rem",
1430
+ border: `1px solid ${theme.fg}0F`,
1431
+ display: "grid",
1432
+ gridTemplateColumns: `repeat(${[thca, thc, cbd].filter((v) => v != null).length}, 1fr)`
1422
1433
  }, children: [
1423
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1424
- fontSize: "0.65rem",
1425
- fontWeight: 600,
1426
- textTransform: "uppercase",
1427
- letterSpacing: "0.08em",
1428
- color: muted,
1429
- marginBottom: "0.75rem"
1430
- }, children: "Pricing" }),
1431
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(100px, 1fr))", gap: "0.5rem" }, children: tiers.map((tier) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1432
- background: surfaceLight,
1433
- borderRadius: 6,
1434
- padding: "0.625rem",
1434
+ thca != null && /* @__PURE__ */ jsxRuntime.jsx(CannabinoidStat, { label: "THCa", value: thca, theme, showBorder: thc != null || cbd != null }),
1435
+ thc != null && /* @__PURE__ */ jsxRuntime.jsx(CannabinoidStat, { label: "\u03949 THC", value: thc, theme, showBorder: cbd != null }),
1436
+ cbd != null && /* @__PURE__ */ jsxRuntime.jsx(CannabinoidStat, { label: "CBD", value: cbd, theme, showBorder: false })
1437
+ ] }),
1438
+ tiers.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1.5rem" }, children: [
1439
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...labelStyle, marginBottom: "0.75rem" }, children: "Pricing" }),
1440
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 1 }, children: tiers.map((tier) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1441
+ flex: "1 1 0",
1442
+ minWidth: 90,
1443
+ padding: "0.75rem 0.5rem",
1444
+ background: theme.surfaceLight,
1435
1445
  textAlign: "center"
1436
1446
  }, children: [
1437
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "1rem", fontWeight: 600, color: fg }, children: [
1447
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "1rem", fontWeight: 300, fontFamily: theme.fontDisplay }, children: [
1438
1448
  "$",
1439
1449
  tier.default_price.toFixed(2)
1440
1450
  ] }),
1441
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.7rem", color: muted, marginTop: "0.125rem" }, children: tier.label })
1451
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 10, color: `${theme.fg}60`, letterSpacing: "0.1em", textTransform: "uppercase", marginTop: 2 }, children: tier.label })
1442
1452
  ] }, tier.id)) })
1443
1453
  ] }),
1444
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.625rem", marginTop: "1.5rem" }, children: [
1445
- coa && /* @__PURE__ */ jsxRuntime.jsx(
1454
+ (genetics || terpenes || effects || batchNumber || dateTested) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1.75rem" }, children: [
1455
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...labelStyle, marginBottom: "0.75rem" }, children: "Details" }),
1456
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1457
+ genetics && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1458
+ /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Genetics", value: genetics, theme }),
1459
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { style: dividerStyle })
1460
+ ] }),
1461
+ terpenes && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1462
+ /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Terpenes", value: terpenes, theme }),
1463
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { style: dividerStyle })
1464
+ ] }),
1465
+ effects && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1466
+ /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Effects", value: effects, theme }),
1467
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { style: dividerStyle })
1468
+ ] }),
1469
+ batchNumber && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1470
+ /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Batch", value: batchNumber, theme }),
1471
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { style: dividerStyle })
1472
+ ] }),
1473
+ dateTested && /* @__PURE__ */ jsxRuntime.jsx(DetailRow, { label: "Tested", value: formatDate(dateTested), theme })
1474
+ ] })
1475
+ ] }),
1476
+ description && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1.75rem" }, children: [
1477
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...labelStyle, marginBottom: "0.75rem" }, children: "About" }),
1478
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
1479
+ fontSize: "0.9rem",
1480
+ fontWeight: 300,
1481
+ color: `${theme.fg}99`,
1482
+ lineHeight: 1.7,
1483
+ margin: 0
1484
+ }, children: description })
1485
+ ] }),
1486
+ coa && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1.75rem" }, children: [
1487
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...labelStyle, marginBottom: "0.75rem" }, children: "Lab Results" }),
1488
+ batchNumber && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: 12, color: `${theme.fg}60`, margin: "0 0 0.5rem", letterSpacing: "0.05em" }, children: [
1489
+ "Batch ",
1490
+ batchNumber,
1491
+ dateTested ? ` \xB7 ${formatDate(dateTested)}` : ""
1492
+ ] }),
1493
+ /* @__PURE__ */ jsxRuntime.jsxs(
1446
1494
  "button",
1447
1495
  {
1448
1496
  onClick: handleCOAClick,
1449
1497
  style: {
1450
1498
  width: "100%",
1451
- padding: "0.875rem",
1452
- background: accent,
1453
- color: bg,
1454
- border: "none",
1455
- fontSize: "0.9rem",
1456
- fontWeight: 600,
1457
- fontFamily: fontDisplay,
1499
+ position: "relative",
1500
+ height: 180,
1501
+ border: `1px solid ${theme.fg}0F`,
1502
+ background: theme.surface,
1458
1503
  cursor: "pointer",
1459
- borderRadius: 6,
1460
- letterSpacing: "-0.01em"
1461
- },
1462
- children: "View Lab Results"
1463
- }
1464
- ),
1465
- renderCOA ? renderCOA(data) : null,
1466
- /* @__PURE__ */ jsxRuntime.jsx(
1467
- "a",
1468
- {
1469
- href: ctaUrl,
1470
- style: {
1471
- display: "block",
1472
- width: "100%",
1473
- padding: "0.875rem",
1474
- background: "transparent",
1475
- color: fg,
1476
- border: `1px solid ${border}`,
1477
- fontSize: "0.9rem",
1478
- fontWeight: 500,
1479
- fontFamily: fontDisplay,
1480
- textAlign: "center",
1481
- textDecoration: "none",
1482
- boxSizing: "border-box",
1483
- borderRadius: 6
1504
+ overflow: "hidden",
1505
+ padding: 0,
1506
+ display: "block"
1484
1507
  },
1485
- children: "Shop Online"
1508
+ children: [
1509
+ /* @__PURE__ */ jsxRuntime.jsx(
1510
+ "iframe",
1511
+ {
1512
+ src: coa.url,
1513
+ style: {
1514
+ width: "200%",
1515
+ height: "200%",
1516
+ border: "none",
1517
+ transform: "scale(0.5)",
1518
+ transformOrigin: "top left",
1519
+ pointerEvents: "none"
1520
+ },
1521
+ title: "COA Preview",
1522
+ tabIndex: -1
1523
+ }
1524
+ ),
1525
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1526
+ position: "absolute",
1527
+ inset: 0,
1528
+ background: `linear-gradient(to top, ${theme.bg}E6 0%, transparent 60%)`,
1529
+ display: "flex",
1530
+ alignItems: "flex-end",
1531
+ justifyContent: "center",
1532
+ paddingBottom: "1.25rem"
1533
+ }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1534
+ fontSize: 11,
1535
+ fontWeight: 500,
1536
+ textTransform: "uppercase",
1537
+ letterSpacing: "0.2em",
1538
+ color: theme.accent
1539
+ }, children: "View Certificate of Analysis" }) })
1540
+ ]
1486
1541
  }
1487
1542
  )
1488
1543
  ] }),
1544
+ renderCOA ? renderCOA(data) : null,
1545
+ /* @__PURE__ */ jsxRuntime.jsx(
1546
+ "a",
1547
+ {
1548
+ href: ctaUrl,
1549
+ style: {
1550
+ display: "block",
1551
+ width: "100%",
1552
+ marginTop: "2rem",
1553
+ padding: "1rem",
1554
+ background: theme.fg,
1555
+ color: theme.bg,
1556
+ fontFamily: theme.fontDisplay,
1557
+ fontSize: "0.85rem",
1558
+ fontWeight: 500,
1559
+ textAlign: "center",
1560
+ textDecoration: "none",
1561
+ letterSpacing: "0.08em",
1562
+ textTransform: "uppercase",
1563
+ boxSizing: "border-box"
1564
+ },
1565
+ children: "Shop Online"
1566
+ }
1567
+ ),
1489
1568
  /* @__PURE__ */ jsxRuntime.jsxs("footer", { style: {
1490
- marginTop: "2rem",
1491
- paddingTop: "1.25rem",
1492
- paddingBottom: "2rem",
1493
- borderTop: `1px solid ${border}`,
1569
+ marginTop: "3rem",
1570
+ paddingTop: "1.5rem",
1571
+ borderTop: `1px solid ${theme.fg}0A`,
1494
1572
  textAlign: "center"
1495
1573
  }, children: [
1496
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "center", gap: "1.5rem", marginBottom: "0.5rem" }, children: [
1497
- coa && /* @__PURE__ */ jsxRuntime.jsx(FooterBadge, { icon: "\u2713", text: "Lab Verified", muted }),
1498
- /* @__PURE__ */ jsxRuntime.jsx(FooterBadge, { icon: "\u2726", text: "Authentic Product", muted })
1574
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "center", gap: "2rem", marginBottom: "0.75rem" }, children: [
1575
+ coa && /* @__PURE__ */ jsxRuntime.jsx(FooterLabel, { text: "Lab Verified" }),
1576
+ /* @__PURE__ */ jsxRuntime.jsx(FooterLabel, { text: "Authentic Product" })
1499
1577
  ] }),
1500
- store?.name && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.7rem", color: muted, margin: "0.5rem 0 0" }, children: [
1578
+ store?.name && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: 11, color: `${theme.fg}40`, margin: "0.5rem 0 0", letterSpacing: "0.1em" }, children: [
1501
1579
  store.name,
1502
1580
  store?.tagline ? ` \u2014 ${store.tagline}` : ""
1503
1581
  ] })
1504
1582
  ] })
1505
1583
  ] }),
1506
- showCOA && coa && /* @__PURE__ */ jsxRuntime.jsxs(
1507
- "div",
1508
- {
1509
- style: {
1510
- position: "fixed",
1511
- inset: 0,
1512
- zIndex: 9999,
1513
- background: "rgba(0,0,0,0.92)",
1514
- display: "flex",
1515
- flexDirection: "column"
1516
- },
1517
- children: [
1518
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1519
- display: "flex",
1520
- justifyContent: "space-between",
1521
- alignItems: "center",
1522
- padding: "0.75rem 1rem",
1523
- borderBottom: "1px solid #222"
1524
- }, children: [
1525
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#fff", fontWeight: 600, fontSize: "0.9rem", fontFamily: fontDisplay }, children: coa.document_name || "Lab Results" }),
1526
- /* @__PURE__ */ jsxRuntime.jsx(
1527
- "button",
1528
- {
1529
- onClick: () => setShowCOA(false),
1530
- style: {
1531
- background: "rgba(255,255,255,0.1)",
1532
- border: "none",
1533
- color: "#fff",
1534
- fontSize: "1rem",
1535
- cursor: "pointer",
1536
- padding: "0.375rem 0.75rem",
1537
- borderRadius: 4
1538
- },
1539
- children: "\u2715"
1540
- }
1541
- )
1542
- ] }),
1543
- /* @__PURE__ */ jsxRuntime.jsx(
1544
- "iframe",
1545
- {
1546
- src: coa.url,
1547
- style: { flex: 1, border: "none", background: "#fff" },
1548
- title: "Lab Results"
1549
- }
1550
- )
1551
- ]
1552
- }
1553
- )
1584
+ showCOA && coa && /* @__PURE__ */ jsxRuntime.jsx(COAModal, { coa, theme, onClose: () => setShowCOA(false) })
1554
1585
  ] });
1555
1586
  }
1556
- function Badge({ text, bg, color, bold }) {
1557
- return /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1558
- padding: "0.25rem 0.625rem",
1559
- borderRadius: 4,
1560
- fontSize: "0.7rem",
1561
- fontWeight: bold ? 700 : 500,
1562
- textTransform: "uppercase",
1563
- letterSpacing: "0.04em",
1564
- background: bg,
1565
- color
1566
- }, children: text });
1567
- }
1568
- function PotencyStat({ label, value, accent, fg }) {
1569
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "0.25rem 0" }, children: [
1570
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "1.5rem", fontWeight: 700, color: fg, lineHeight: 1.1 }, children: [
1587
+ function CannabinoidStat({ label, value, theme, showBorder }) {
1588
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1589
+ padding: "1.25rem 0.5rem",
1590
+ textAlign: "center",
1591
+ borderRight: showBorder ? `1px solid ${theme.fg}0F` : void 0
1592
+ }, children: [
1593
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1594
+ fontFamily: theme.fontDisplay,
1595
+ fontSize: "clamp(1.5rem, 5vw, 2rem)",
1596
+ fontWeight: 300,
1597
+ lineHeight: 1,
1598
+ color: theme.fg
1599
+ }, children: [
1571
1600
  value.toFixed(value >= 1 ? 1 : 2),
1572
- "%"
1601
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.6em", marginLeft: 1 }, children: "%" })
1573
1602
  ] }),
1574
1603
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1575
- fontSize: "0.65rem",
1576
- color: accent,
1604
+ fontSize: 11,
1605
+ fontWeight: 500,
1577
1606
  textTransform: "uppercase",
1578
- letterSpacing: "0.06em",
1579
- marginTop: "0.25rem",
1580
- fontWeight: 600
1607
+ letterSpacing: "0.25em",
1608
+ color: theme.accent,
1609
+ marginTop: "0.5rem"
1581
1610
  }, children: label })
1582
1611
  ] });
1583
1612
  }
1584
- function DetailRow({ label, value, fg, muted }) {
1585
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "baseline" }, children: [
1586
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.8rem", color: muted }, children: label }),
1587
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.8rem", color: fg, fontWeight: 500 }, children: value })
1613
+ function DetailRow({ label, value, theme }) {
1614
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1615
+ display: "flex",
1616
+ justifyContent: "space-between",
1617
+ alignItems: "baseline",
1618
+ padding: "0.625rem 0"
1619
+ }, children: [
1620
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1621
+ fontSize: 12,
1622
+ textTransform: "uppercase",
1623
+ letterSpacing: "0.15em",
1624
+ color: `${theme.fg}66`
1625
+ }, children: label }),
1626
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1627
+ fontSize: 14,
1628
+ fontWeight: 300,
1629
+ color: `${theme.fg}CC`
1630
+ }, children: value })
1588
1631
  ] });
1589
1632
  }
1590
- function FooterBadge({ icon, text, muted }) {
1591
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "0.7rem", color: muted, display: "flex", alignItems: "center", gap: "0.25rem" }, children: [
1592
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.6rem" }, children: icon }),
1593
- " ",
1594
- text
1633
+ function FooterLabel({ text }) {
1634
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1635
+ fontSize: 10,
1636
+ textTransform: "uppercase",
1637
+ letterSpacing: "0.15em",
1638
+ color: "rgba(255,255,255,0.25)"
1639
+ }, children: text });
1640
+ }
1641
+ function COAModal({ coa, theme, onClose }) {
1642
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "fixed", inset: 0, zIndex: 9999, background: "rgba(0,0,0,0.95)", display: "flex", flexDirection: "column" }, children: [
1643
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1644
+ display: "flex",
1645
+ justifyContent: "space-between",
1646
+ alignItems: "center",
1647
+ padding: "0.75rem 1rem",
1648
+ borderBottom: `1px solid ${theme.fg}10`
1649
+ }, children: [
1650
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1651
+ color: "#fff",
1652
+ fontFamily: theme.fontDisplay,
1653
+ fontWeight: 500,
1654
+ fontSize: "0.85rem",
1655
+ letterSpacing: "-0.01em"
1656
+ }, children: coa.document_name || "Lab Results" }),
1657
+ /* @__PURE__ */ jsxRuntime.jsx(
1658
+ "button",
1659
+ {
1660
+ onClick: onClose,
1661
+ style: {
1662
+ background: `${theme.fg}10`,
1663
+ border: "none",
1664
+ color: "#fff",
1665
+ fontSize: "0.85rem",
1666
+ cursor: "pointer",
1667
+ padding: "0.375rem 0.75rem",
1668
+ letterSpacing: "0.05em"
1669
+ },
1670
+ children: "Close"
1671
+ }
1672
+ )
1673
+ ] }),
1674
+ /* @__PURE__ */ jsxRuntime.jsx("iframe", { src: coa.url, style: { flex: 1, border: "none", background: "#fff" }, title: "Lab Results" })
1595
1675
  ] });
1596
1676
  }
1597
1677
  function strainBadgeColor(strain) {