@neowhale/storefront 0.2.7 → 0.2.8

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.
@@ -1277,69 +1277,171 @@ function DefaultLayout({
1277
1277
  const bg = lp.background_color || store?.theme?.background || "#050505";
1278
1278
  const fg = lp.text_color || store?.theme?.foreground || "#fafafa";
1279
1279
  const accent = store?.theme?.accent || qr.brand_color || "#E8E2D9";
1280
- const surface = store?.theme?.surface || "#111";
1280
+ const surface = store?.theme?.surface || "#0C0C0C";
1281
+ const surfaceLight = store?.theme?.surfaceLight || "#141414";
1281
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";
1282
1286
  const logoUrl = qr.logo_url || store?.logo_url;
1283
- const productImage = lp.image_url || product?.featured_image || product?.image_gallery?.[0] || null;
1287
+ const productImage = lp.image_url || product?.featured_image || null;
1284
1288
  const productName = lp.title || product?.name || qr.name;
1285
1289
  const description = lp.description || product?.description || "";
1286
- const ctaText = lp.cta_text || (coa ? "View Lab Results" : "Learn More");
1287
1290
  const ctaUrl = lp.cta_url || qr.destination_url;
1291
+ const categoryName = product?.category_name ?? null;
1288
1292
  const cf = product?.custom_fields;
1289
1293
  const thca = cf?.thca_percentage ?? null;
1290
1294
  const thc = cf?.d9_percentage ?? null;
1291
1295
  const cbd = cf?.cbd_total ?? null;
1292
1296
  const strainType = cf?.strain_type ?? null;
1293
- const categoryName = product?.category_name ?? null;
1297
+ const batchNumber = cf?.batch_number ?? null;
1298
+ const dateTested = cf?.date_tested ?? null;
1299
+ const terpenes = cf?.terpenes ?? null;
1300
+ const effects = cf?.effects ?? null;
1301
+ const genetics = cf?.genetics ?? null;
1302
+ const tagline = cf?.tagline ?? null;
1303
+ const pricingData = product?.pricing_data;
1304
+ const tiers = pricingData?.tiers?.sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)) ?? [];
1305
+ const lowestPrice = tiers.length > 0 ? Math.min(...tiers.map((t) => t.default_price)) : null;
1294
1306
  const handleCOAClick = react.useCallback(() => {
1295
1307
  if (coa) setShowCOA(true);
1296
1308
  }, [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: [
1316
- strainType && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1317
- padding: "0.25rem 0.75rem",
1318
- borderRadius: 999,
1319
- fontSize: "0.75rem",
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",
1312
+ display: "flex",
1313
+ alignItems: "center",
1314
+ justifyContent: "space-between",
1315
+ borderBottom: `1px solid ${border}`
1316
+ }, 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 })
1319
+ ] }),
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: [
1327
+ productImage && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1328
+ marginTop: "1.5rem",
1329
+ borderRadius: 8,
1330
+ overflow: "hidden",
1331
+ background: surface,
1332
+ aspectRatio: "4/3",
1333
+ maxHeight: 320,
1334
+ display: "flex",
1335
+ alignItems: "center",
1336
+ justifyContent: "center"
1337
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(
1338
+ "img",
1339
+ {
1340
+ src: productImage,
1341
+ alt: productName,
1342
+ style: { width: "100%", height: "100%", objectFit: "cover" }
1343
+ }
1344
+ ) }),
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",
1320
1354
  fontWeight: 600,
1321
- textTransform: "uppercase",
1322
- letterSpacing: "0.05em",
1323
- background: strainBadgeColor(strainType),
1324
- 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 })
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",
1361
+ 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 })
1333
1369
  ] }),
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 }),
1370
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: muted, lineHeight: 1.6, margin: "1rem 0 0", fontSize: "0.9rem" }, children: description }),
1336
1371
  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 })
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",
1381
+ fontWeight: 600,
1382
+ textTransform: "uppercase",
1383
+ 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
+ ] })
1392
+ ] }),
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"
1399
+ }, 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
+ ] })
1341
1415
  ] }),
1342
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem", marginTop: "1.5rem" }, children: [
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"
1422
+ }, 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",
1435
+ textAlign: "center"
1436
+ }, children: [
1437
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "1rem", fontWeight: 600, color: fg }, children: [
1438
+ "$",
1439
+ tier.default_price.toFixed(2)
1440
+ ] }),
1441
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.7rem", color: muted, marginTop: "0.125rem" }, children: tier.label })
1442
+ ] }, tier.id)) })
1443
+ ] }),
1444
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.625rem", marginTop: "1.5rem" }, children: [
1343
1445
  coa && /* @__PURE__ */ jsxRuntime.jsx(
1344
1446
  "button",
1345
1447
  {
@@ -1350,10 +1452,12 @@ function DefaultLayout({
1350
1452
  background: accent,
1351
1453
  color: bg,
1352
1454
  border: "none",
1353
- fontSize: "0.95rem",
1455
+ fontSize: "0.9rem",
1354
1456
  fontWeight: 600,
1457
+ fontFamily: fontDisplay,
1355
1458
  cursor: "pointer",
1356
- borderRadius: 0
1459
+ borderRadius: 6,
1460
+ letterSpacing: "-0.01em"
1357
1461
  },
1358
1462
  children: "View Lab Results"
1359
1463
  }
@@ -1369,26 +1473,33 @@ function DefaultLayout({
1369
1473
  padding: "0.875rem",
1370
1474
  background: "transparent",
1371
1475
  color: fg,
1372
- border: `1px solid ${muted}`,
1373
- fontSize: "0.95rem",
1476
+ border: `1px solid ${border}`,
1477
+ fontSize: "0.9rem",
1374
1478
  fontWeight: 500,
1479
+ fontFamily: fontDisplay,
1375
1480
  textAlign: "center",
1376
1481
  textDecoration: "none",
1377
1482
  boxSizing: "border-box",
1378
- borderRadius: 0
1483
+ borderRadius: 6
1379
1484
  },
1380
- children: ctaText === "View Lab Results" ? "Shop Online" : ctaText
1485
+ children: "Shop Online"
1381
1486
  }
1382
1487
  )
1383
1488
  ] }),
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" })
1489
+ /* @__PURE__ */ jsxRuntime.jsxs("footer", { style: {
1490
+ marginTop: "2rem",
1491
+ paddingTop: "1.25rem",
1492
+ paddingBottom: "2rem",
1493
+ borderTop: `1px solid ${border}`,
1494
+ textAlign: "center"
1495
+ }, 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 })
1388
1499
  ] }),
1389
- store?.name && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.75rem", color: muted, margin: 0 }, children: [
1390
- "Verified by ",
1391
- store.name
1500
+ store?.name && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.7rem", color: muted, margin: "0.5rem 0 0" }, children: [
1501
+ store.name,
1502
+ store?.tagline ? ` \u2014 ${store.tagline}` : ""
1392
1503
  ] })
1393
1504
  ] })
1394
1505
  ] }),
@@ -1399,18 +1510,32 @@ function DefaultLayout({
1399
1510
  position: "fixed",
1400
1511
  inset: 0,
1401
1512
  zIndex: 9999,
1402
- background: "rgba(0,0,0,0.9)",
1513
+ background: "rgba(0,0,0,0.92)",
1403
1514
  display: "flex",
1404
1515
  flexDirection: "column"
1405
1516
  },
1406
1517
  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" }),
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" }),
1409
1526
  /* @__PURE__ */ jsxRuntime.jsx(
1410
1527
  "button",
1411
1528
  {
1412
1529
  onClick: () => setShowCOA(false),
1413
- style: { background: "none", border: "none", color: "#fff", fontSize: "1.5rem", cursor: "pointer", padding: "0.5rem" },
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
+ },
1414
1539
  children: "\u2715"
1415
1540
  }
1416
1541
  )
@@ -1428,10 +1553,45 @@ function DefaultLayout({
1428
1553
  )
1429
1554
  ] });
1430
1555
  }
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 })
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: [
1571
+ value.toFixed(value >= 1 ? 1 : 2),
1572
+ "%"
1573
+ ] }),
1574
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1575
+ fontSize: "0.65rem",
1576
+ color: accent,
1577
+ textTransform: "uppercase",
1578
+ letterSpacing: "0.06em",
1579
+ marginTop: "0.25rem",
1580
+ fontWeight: 600
1581
+ }, children: label })
1582
+ ] });
1583
+ }
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 })
1588
+ ] });
1589
+ }
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
1435
1595
  ] });
1436
1596
  }
1437
1597
  function strainBadgeColor(strain) {
@@ -1441,6 +1601,14 @@ function strainBadgeColor(strain) {
1441
1601
  if (s === "hybrid") return "#f59e0b";
1442
1602
  return "#6b7280";
1443
1603
  }
1604
+ function formatDate(dateStr) {
1605
+ try {
1606
+ const d = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
1607
+ return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
1608
+ } catch {
1609
+ return dateStr;
1610
+ }
1611
+ }
1444
1612
  var containerStyle = {
1445
1613
  minHeight: "100dvh",
1446
1614
  display: "flex",