@neowhale/storefront 0.2.7 → 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,174 +1264,414 @@ 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 || "#111";
1281
- const muted = store?.theme?.muted || "#888";
1282
1295
  const logoUrl = qr.logo_url || store?.logo_url;
1283
- const productImage = lp.image_url || product?.featured_image || product?.image_gallery?.[0] || null;
1296
+ const productImage = lp.image_url || product?.featured_image || null;
1284
1297
  const productName = lp.title || product?.name || qr.name;
1285
1298
  const description = lp.description || product?.description || "";
1286
- const ctaText = lp.cta_text || (coa ? "View Lab Results" : "Learn More");
1287
1299
  const ctaUrl = lp.cta_url || qr.destination_url;
1300
+ const categoryName = product?.category_name ?? null;
1288
1301
  const cf = product?.custom_fields;
1289
1302
  const thca = cf?.thca_percentage ?? null;
1290
1303
  const thc = cf?.d9_percentage ?? null;
1291
1304
  const cbd = cf?.cbd_total ?? null;
1292
1305
  const strainType = cf?.strain_type ?? null;
1293
- const categoryName = product?.category_name ?? null;
1306
+ const batchNumber = cf?.batch_number ?? null;
1307
+ const dateTested = cf?.date_tested ?? null;
1308
+ const terpenes = cf?.terpenes ?? null;
1309
+ const effects = cf?.effects ?? null;
1310
+ const genetics = cf?.genetics ?? null;
1311
+ const tagline = cf?.tagline ?? null;
1312
+ const pricingData = product?.pricing_data;
1313
+ const tiers = pricingData?.tiers?.sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)) ?? [];
1314
+ const lowestPrice = tiers.length > 0 ? Math.min(...tiers.map((t) => t.default_price)) : null;
1294
1315
  const handleCOAClick = react.useCallback(() => {
1295
1316
  if (coa) setShowCOA(true);
1296
1317
  }, [coa]);
1297
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minHeight: "100dvh", background: bg, color: fg, fontFamily: "system-ui, -apple-system, sans-serif" }, children: [
1298
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "1.5rem", display: "flex", justifyContent: "center" }, children: logoUrl && /* @__PURE__ */ jsxRuntime.jsx(
1299
- "img",
1300
- {
1301
- src: logoUrl,
1302
- alt: store?.name || "Store",
1303
- style: { height: 40, objectFit: "contain" }
1304
- }
1305
- ) }),
1306
- productImage && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", aspectRatio: "1", overflow: "hidden", background: surface }, children: /* @__PURE__ */ jsxRuntime.jsx(
1307
- "img",
1308
- {
1309
- src: productImage,
1310
- alt: productName,
1311
- style: { width: "100%", height: "100%", objectFit: "cover" }
1312
- }
1313
- ) }),
1314
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1.5rem", maxWidth: 480, margin: "0 auto" }, children: [
1315
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "0.5rem", marginBottom: "0.75rem", flexWrap: "wrap" }, children: [
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",
1340
+ display: "flex",
1341
+ alignItems: "center",
1342
+ justifyContent: "space-between",
1343
+ maxWidth: 1280,
1344
+ margin: "0 auto"
1345
+ }, children: [
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
+ )
1365
+ ] }),
1366
+ /* @__PURE__ */ jsxRuntime.jsxs("main", { style: { maxWidth: 560, margin: "0 auto", padding: "0 1.5rem 3rem" }, children: [
1367
+ productImage && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1368
+ width: "100%",
1369
+ aspectRatio: "1",
1370
+ overflow: "hidden",
1371
+ background: theme.surfaceLight,
1372
+ display: "flex",
1373
+ alignItems: "center",
1374
+ justifyContent: "center",
1375
+ padding: "2rem"
1376
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(
1377
+ "img",
1378
+ {
1379
+ src: productImage,
1380
+ alt: productName,
1381
+ style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" }
1382
+ }
1383
+ ) }),
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,
1387
+ fontWeight: 500,
1388
+ color: theme.accent,
1389
+ textTransform: "uppercase",
1390
+ letterSpacing: "0.15em"
1391
+ }, children: categoryName }),
1316
1392
  strainType && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1317
- padding: "0.25rem 0.75rem",
1318
- borderRadius: 999,
1319
- fontSize: "0.75rem",
1393
+ fontSize: 10,
1320
1394
  fontWeight: 600,
1321
1395
  textTransform: "uppercase",
1322
- letterSpacing: "0.05em",
1396
+ letterSpacing: "0.08em",
1397
+ padding: "0.2rem 0.5rem",
1323
1398
  background: strainBadgeColor(strainType),
1324
1399
  color: "#fff"
1325
- }, children: strainType }),
1326
- categoryName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1327
- padding: "0.25rem 0.75rem",
1328
- borderRadius: 999,
1329
- fontSize: "0.75rem",
1330
- background: surface,
1331
- color: muted
1332
- }, children: categoryName })
1400
+ }, children: strainType })
1401
+ ] }),
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"
1422
+ }, children: [
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" })
1333
1426
  ] }),
1334
- /* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: "1.75rem", fontWeight: 600, margin: "0 0 0.5rem", lineHeight: 1.2 }, children: productName }),
1335
- description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: muted, lineHeight: 1.6, margin: "0 0 1.5rem", fontSize: "0.95rem" }, children: description }),
1336
1427
  renderProduct ? renderProduct(data) : null,
1337
- (thca || thc || cbd) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: "0.75rem", margin: "1.5rem 0" }, children: [
1338
- thca != null && /* @__PURE__ */ jsxRuntime.jsx(StatCard, { label: "THCa", value: `${thca.toFixed(1)}%`, bg: surface, fg, accent }),
1339
- thc != null && /* @__PURE__ */ jsxRuntime.jsx(StatCard, { label: "D9 THC", value: `${thc.toFixed(1)}%`, bg: surface, fg, accent }),
1340
- cbd != null && /* @__PURE__ */ jsxRuntime.jsx(StatCard, { label: "CBD", value: `${cbd.toFixed(1)}%`, bg: surface, fg, accent })
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)`
1433
+ }, children: [
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,
1445
+ textAlign: "center"
1446
+ }, children: [
1447
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "1rem", fontWeight: 300, fontFamily: theme.fontDisplay }, children: [
1448
+ "$",
1449
+ tier.default_price.toFixed(2)
1450
+ ] }),
1451
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 10, color: `${theme.fg}60`, letterSpacing: "0.1em", textTransform: "uppercase", marginTop: 2 }, children: tier.label })
1452
+ ] }, tier.id)) })
1341
1453
  ] }),
1342
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem", marginTop: "1.5rem" }, children: [
1343
- 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(
1344
1494
  "button",
1345
1495
  {
1346
1496
  onClick: handleCOAClick,
1347
1497
  style: {
1348
1498
  width: "100%",
1349
- padding: "0.875rem",
1350
- background: accent,
1351
- color: bg,
1352
- border: "none",
1353
- fontSize: "0.95rem",
1354
- fontWeight: 600,
1499
+ position: "relative",
1500
+ height: 180,
1501
+ border: `1px solid ${theme.fg}0F`,
1502
+ background: theme.surface,
1355
1503
  cursor: "pointer",
1356
- borderRadius: 0
1504
+ overflow: "hidden",
1505
+ padding: 0,
1506
+ display: "block"
1357
1507
  },
1358
- children: "View Lab Results"
1359
- }
1360
- ),
1361
- renderCOA ? renderCOA(data) : null,
1362
- /* @__PURE__ */ jsxRuntime.jsx(
1363
- "a",
1364
- {
1365
- href: ctaUrl,
1366
- style: {
1367
- display: "block",
1368
- width: "100%",
1369
- padding: "0.875rem",
1370
- background: "transparent",
1371
- color: fg,
1372
- border: `1px solid ${muted}`,
1373
- fontSize: "0.95rem",
1374
- fontWeight: 500,
1375
- textAlign: "center",
1376
- textDecoration: "none",
1377
- boxSizing: "border-box",
1378
- borderRadius: 0
1379
- },
1380
- children: ctaText === "View Lab Results" ? "Shop Online" : ctaText
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
+ ]
1381
1541
  }
1382
1542
  )
1383
1543
  ] }),
1384
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "2rem", paddingTop: "1.5rem", borderTop: `1px solid ${surface}`, textAlign: "center" }, children: [
1385
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "center", gap: "1.5rem", marginBottom: "0.75rem" }, children: [
1386
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.75rem", color: muted, textTransform: "uppercase", letterSpacing: "0.05em" }, children: "Lab Tested" }),
1387
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.75rem", color: muted, textTransform: "uppercase", letterSpacing: "0.05em" }, children: "Authentic" })
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
+ ),
1568
+ /* @__PURE__ */ jsxRuntime.jsxs("footer", { style: {
1569
+ marginTop: "3rem",
1570
+ paddingTop: "1.5rem",
1571
+ borderTop: `1px solid ${theme.fg}0A`,
1572
+ textAlign: "center"
1573
+ }, children: [
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" })
1388
1577
  ] }),
1389
- store?.name && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.75rem", color: muted, margin: 0 }, children: [
1390
- "Verified by ",
1391
- store.name
1578
+ store?.name && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: 11, color: `${theme.fg}40`, margin: "0.5rem 0 0", letterSpacing: "0.1em" }, children: [
1579
+ store.name,
1580
+ store?.tagline ? ` \u2014 ${store.tagline}` : ""
1392
1581
  ] })
1393
1582
  ] })
1394
1583
  ] }),
1395
- showCOA && coa && /* @__PURE__ */ jsxRuntime.jsxs(
1396
- "div",
1397
- {
1398
- style: {
1399
- position: "fixed",
1400
- inset: 0,
1401
- zIndex: 9999,
1402
- background: "rgba(0,0,0,0.9)",
1403
- display: "flex",
1404
- flexDirection: "column"
1405
- },
1406
- children: [
1407
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "1rem" }, children: [
1408
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#fff", fontWeight: 600 }, children: coa.document_name || "Lab Results" }),
1409
- /* @__PURE__ */ jsxRuntime.jsx(
1410
- "button",
1411
- {
1412
- onClick: () => setShowCOA(false),
1413
- style: { background: "none", border: "none", color: "#fff", fontSize: "1.5rem", cursor: "pointer", padding: "0.5rem" },
1414
- children: "\u2715"
1415
- }
1416
- )
1417
- ] }),
1418
- /* @__PURE__ */ jsxRuntime.jsx(
1419
- "iframe",
1420
- {
1421
- src: coa.url,
1422
- style: { flex: 1, border: "none", background: "#fff" },
1423
- title: "Lab Results"
1424
- }
1425
- )
1426
- ]
1427
- }
1428
- )
1584
+ showCOA && coa && /* @__PURE__ */ jsxRuntime.jsx(COAModal, { coa, theme, onClose: () => setShowCOA(false) })
1585
+ ] });
1586
+ }
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: [
1600
+ value.toFixed(value >= 1 ? 1 : 2),
1601
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.6em", marginLeft: 1 }, children: "%" })
1602
+ ] }),
1603
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1604
+ fontSize: 11,
1605
+ fontWeight: 500,
1606
+ textTransform: "uppercase",
1607
+ letterSpacing: "0.25em",
1608
+ color: theme.accent,
1609
+ marginTop: "0.5rem"
1610
+ }, children: label })
1429
1611
  ] });
1430
1612
  }
1431
- function StatCard({ label, value, bg, fg, accent }) {
1432
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { background: bg, padding: "1rem", textAlign: "center" }, children: [
1433
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "1.25rem", fontWeight: 700, color: fg }, children: value }),
1434
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.7rem", color: accent, textTransform: "uppercase", letterSpacing: "0.05em", marginTop: "0.25rem" }, children: label })
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 })
1631
+ ] });
1632
+ }
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" })
1435
1675
  ] });
1436
1676
  }
1437
1677
  function strainBadgeColor(strain) {
@@ -1441,6 +1681,14 @@ function strainBadgeColor(strain) {
1441
1681
  if (s === "hybrid") return "#f59e0b";
1442
1682
  return "#6b7280";
1443
1683
  }
1684
+ function formatDate(dateStr) {
1685
+ try {
1686
+ const d = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
1687
+ return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
1688
+ } catch {
1689
+ return dateStr;
1690
+ }
1691
+ }
1444
1692
  var containerStyle = {
1445
1693
  minHeight: "100dvh",
1446
1694
  display: "flex",