const require_chunk = require("./chunk-9hOWP6kD.cjs");
const require_use_account = require("./use-account-CPOGOGl6.cjs");
const require_FluidProvider = require("./FluidProvider-DRyFjZ6v.cjs");
const require_translation_adapter = require("./translation-adapter-Bi65zBvS.cjs");
const require_PortalTenantClientProvider = require("./PortalTenantClientProvider-Ct2vdZPi.cjs");
const require_src = require("./src-BRyZgUFh.cjs");
const require_src$1 = require("./src-CfWQyJTB.cjs");
const require_ShopWidget = require("./ShopWidget-B9NX-1jS.cjs");
const require_AppNavigationContext = require("./AppNavigationContext-BTP4s7dH.cjs");
const require_use_store = require("./use-store-D89j_R7T.cjs");
const require_use_navigation_parent = require("./use-navigation-parent-CZlbt0kp.cjs");
const require_ScreenHeaderContext = require("./ScreenHeaderContext-BnxDDgZR.cjs");
let react = require("react");
react = require_chunk.__toESM(react);
let _tanstack_react_query = require("@tanstack/react-query");
let react_jsx_runtime = require("react/jsx-runtime");
let lucide_react = require("lucide-react");
let react_dom = require("react-dom");
let _fluid_app_ui_components_components_SearchSort = require("@fluid-app/ui-components/components/SearchSort");
//#region ../../shop/ui/src/components/product-card.tsx
function tagPortalProduct(product) {
	return {
		...product,
		__portalProduct: true
	};
}
function isPortalProduct(product) {
	return "__portalProduct" in product && product.__portalProduct === true;
}
function getPortalProductCoverImage(product) {
	if (product.images && product.images.length > 0) return product.images[0]?.url ?? null;
	return null;
}
function defaultRenderImage$2({ src, alt, fill, className, onError }) {
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
		src,
		alt,
		className: `${fill ? "absolute inset-0 h-full w-full" : ""} ${className ?? ""}`,
		onError
	});
}
function ProductCardContent({ product, countryIso, companyLogoUrl, renderImage = defaultRenderImage$2 }) {
	const [isHovered, setIsHovered] = (0, react.useState)(false);
	const { t } = require_FluidProvider.useShopTranslation();
	const isPortal = isPortalProduct(product);
	const coverImage = isPortal ? getPortalProductCoverImage(product) : require_src.getProductImageUrl(product);
	const isVideo = require_ShopWidget.isVideoUrl(coverImage);
	const productName = isPortal ? product.name || t("no_title") : product.title || t("no_title");
	const isBundle = isPortal && product.is_bundle === true;
	let repPrice = null;
	let price = null;
	if (isPortal) if (product.wholesale_price) {
		repPrice = require_src.formatPortalPrice(product.wholesale_price, product.currency);
		const retailFormatted = require_src.formatPortalPrice(product.price, product.currency);
		if (retailFormatted !== repPrice) price = retailFormatted;
	} else repPrice = require_src.formatPortalPrice(product.price, product.currency);
	else if (countryIso) {
		const prices = require_src.determineProductPrice(product, countryIso);
		repPrice = prices.repPrice;
		price = prices.price;
	}
	const bundlePrice = isBundle ? require_src.formatPortalPriceRange(product.price_range, product.currency) ?? require_src.formatPortalPrice(product.price, product.currency) : null;
	const resolvedCoverImage = isVideo && coverImage ? require_ShopWidget.getVideoThumbnailUrl(coverImage) : coverImage || "https://ik.imagekit.io/fluid/tr:w-1500,h-1500,cm-pad_resize,bg-FFFFFF/980191006/images/WJHL8V/WeCommerce_Logotype-Black_NcO-MzatB.png";
	return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
		className: "bg-muted/40 relative aspect-square overflow-hidden rounded-lg",
		onMouseEnter: () => isVideo && setIsHovered(true),
		onMouseLeave: () => isVideo && setIsHovered(false),
		children: [
			isVideo && isHovered ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
				src: coverImage || "",
				className: "absolute inset-0 h-full w-full object-cover",
				autoPlay: true,
				muted: true,
				loop: true,
				playsInline: true
			}) : renderImage({
				src: resolvedCoverImage,
				alt: productName,
				fill: true,
				className: "object-cover transition-transform duration-300 hover:scale-[1.02]",
				onError: (e) => {
					e.currentTarget.src = companyLogoUrl || "https://ik.imagekit.io/fluid/tr:w-1500,h-1500,cm-pad_resize,bg-FFFFFF/980191006/images/WJHL8V/WeCommerce_Logotype-Black_NcO-MzatB.png";
				},
				unoptimized: true
			}),
			isVideo && !isHovered && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				className: "absolute inset-0 flex items-center justify-center",
				children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
					className: "flex size-16 items-center justify-center rounded-full bg-black/50 backdrop-blur-sm",
					children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.CirclePlay, { className: "size-12 text-white" })
				})
			}),
			isBundle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Badge, {
				variant: "secondary",
				className: "absolute top-2 left-2",
				children: t("bundle_badge")
			})
		]
	}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
		className: "px-0.5 pt-2 pb-1",
		children: [
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
				className: "text-foreground line-clamp-1 text-sm leading-snug font-semibold",
				children: productName
			}),
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				className: "flex items-center gap-2",
				children: isBundle ? bundlePrice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
					className: "text-foreground text-sm leading-none font-semibold",
					children: bundlePrice
				}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [repPrice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
					className: "text-foreground text-sm leading-none font-semibold",
					children: repPrice
				}), price && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
					className: "text-muted-foreground text-sm leading-none line-through",
					children: price
				})] })
			}),
			!isPortal && countryIso && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "text-muted-foreground mt-1 text-xs",
				children: [
					"CV",
					" ",
					getVariantCountryValue(getSelectedVariant(product), countryIso, "cv") || "-",
					" ",
					"| QV",
					" ",
					getVariantCountryValue(getSelectedVariant(product), countryIso, "qv") || "-"
				]
			}),
			isPortal && product.wholesale_price != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "text-muted-foreground mt-1 text-xs",
				children: [
					"CV ",
					product.cv ?? "-",
					" | QV ",
					product.qv ?? "-"
				]
			})
		]
	})] });
}
function getSelectedVariant(product) {
	if (!product.variants || product.variants.length === 0) return null;
	const masterVariant = product.variants.find((v) => {
		return "is_master" in v && v.is_master;
	});
	if (masterVariant) return masterVariant;
	return product.variants[0] || null;
}
function getVariantCountryValue(variant, countryIso, field) {
	if (!variant || !variant.variant_countries) return null;
	if (typeof variant.variant_countries === "object" && !Array.isArray(variant.variant_countries)) return variant.variant_countries[countryIso]?.[field] ?? null;
	if (Array.isArray(variant.variant_countries)) return variant.variant_countries.find((vc) => vc.country_iso === countryIso)?.[field] ?? null;
	return null;
}
function ProductCard({ product, countryIso, companyLogoUrl, showShareModal = false, setShareModalOpen, setSelectedProduct, renderLink, renderImage, onClick }) {
	const cardContent = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductCardContent, {
		product,
		...countryIso !== void 0 && { countryIso },
		...companyLogoUrl !== void 0 && { companyLogoUrl },
		...renderImage !== void 0 && { renderImage }
	});
	const cardClassName = "bg-transparent overflow-hidden border-0 shadow-none pt-0 gap-0";
	if (showShareModal && !isPortalProduct(product)) {
		const handleShareClick = () => {
			if (setSelectedProduct && setShareModalOpen) {
				setSelectedProduct(product);
				setShareModalOpen(true);
			}
		};
		return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Card, {
			className: cardClassName,
			children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
				onClick: handleShareClick,
				className: "group block w-full cursor-pointer text-left",
				children: cardContent
			})
		});
	}
	if (onClick) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Card, {
		className: cardClassName,
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
			onClick,
			className: "group block w-full cursor-pointer text-left",
			children: cardContent
		})
	});
	const href = `/portal/shop/${product.id}`;
	if (renderLink) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Card, {
		className: cardClassName,
		children: renderLink({
			href,
			children: cardContent
		})
	});
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Card, {
		className: cardClassName,
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
			href,
			className: "group block cursor-pointer",
			children: cardContent
		})
	});
}
//#endregion
//#region ../../shop/ui/src/components/image-gallery.tsx
function defaultRenderImage$1({ src, alt, fill, className, onError }) {
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
		src,
		alt,
		className: `${fill ? "absolute inset-0 h-full w-full" : ""} ${className ?? ""}`,
		onError
	});
}
function ImageGallery({ images, fallbackImageUrl, productTitle, renderImage = defaultRenderImage$1 }) {
	const { t } = require_FluidProvider.useShopTranslation();
	const [currentImageIndex, setCurrentImageIndex] = (0, react.useState)(0);
	const [viewerOpen, setViewerOpen] = (0, react.useState)(false);
	const hasMultipleImages = images && images.length > 0;
	const displayImages = (0, react.useMemo)(() => hasMultipleImages ? images.toSorted((a, b) => a.position - b.position) : [{
		id: 0,
		image_url: fallbackImageUrl,
		position: 0
	}], [
		images,
		hasMultipleImages,
		fallbackImageUrl
	]);
	(0, react.useEffect)(() => {
		setCurrentImageIndex(0);
	}, [displayImages]);
	const nextImage = () => {
		if (displayImages.length > 1) setCurrentImageIndex((prev) => (prev + 1) % displayImages.length);
	};
	const prevImage = () => {
		if (displayImages.length > 1) setCurrentImageIndex((prev) => (prev - 1 + displayImages.length) % displayImages.length);
	};
	return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
		className: "flex flex-col gap-3 md:flex-row-reverse md:items-start",
		children: [
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				className: "min-w-0 flex-1",
				children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
					className: "bg-muted/30 group relative aspect-[3/4] max-h-[760px] overflow-hidden rounded-xl shadow-sm",
					children: [require_ShopWidget.isVideoUrl(displayImages[currentImageIndex]?.image_url) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
						src: displayImages[currentImageIndex]?.image_url,
						className: "absolute inset-0 h-full w-full object-cover",
						controls: true,
						loop: true,
						playsInline: true
					}, displayImages[currentImageIndex]?.id) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
						type: "button",
						onClick: () => setViewerOpen(true),
						className: "group absolute inset-0 z-[1] cursor-pointer border-0 bg-transparent p-0",
						"aria-label": t("open_image_viewer"),
						children: [renderImage({
							src: displayImages[currentImageIndex]?.image_url || fallbackImageUrl,
							alt: productTitle,
							fill: true,
							className: "rounded-xl object-cover md:shadow-sm",
							onError: (e) => {
								e.currentTarget.src = "https://ik.imagekit.io/fluid/tr:w-1500,h-1500,cm-pad_resize,bg-FFFFFF/980191006/images/WJHL8V/WeCommerce_Logotype-Black_NcO-MzatB.png";
							},
							unoptimized: true
						}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "group-focus-visible:ring-ring pointer-events-none absolute inset-0 rounded-xl group-focus-visible:ring-2 group-focus-visible:ring-inset" })]
					}), displayImages.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
						type: "button",
						"aria-label": t("previous_image"),
						className: "bg-background/80 text-foreground hover:bg-background absolute top-1/2 left-3 z-10 flex size-10 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full shadow-md transition-opacity md:opacity-0 md:group-hover:opacity-100",
						onClick: prevImage,
						children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronLeft, { className: "size-5" })
					}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
						type: "button",
						"aria-label": t("next_image"),
						className: "bg-background/80 text-foreground hover:bg-background absolute top-1/2 right-3 z-10 flex size-10 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full shadow-md transition-opacity md:opacity-0 md:group-hover:opacity-100",
						onClick: nextImage,
						children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRight, { className: "size-5" })
					})] })]
				})
			}),
			displayImages.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				className: "grid grid-cols-5 gap-2 sm:grid-cols-6 md:w-14 md:grid-cols-1",
				children: displayImages.map((image, index) => {
					const imageUrl = image.image_url || fallbackImageUrl;
					const isSelected = index === currentImageIndex;
					return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
						type: "button",
						"aria-label": t("go_to_image", { index: String(index + 1) }),
						className: `bg-background relative aspect-square overflow-hidden rounded-lg border-2 transition ${isSelected ? "border-foreground" : "hover:border-border border-transparent"}`,
						onClick: () => setCurrentImageIndex(index),
						children: renderImage({
							src: imageUrl,
							alt: productTitle,
							fill: true,
							className: "object-cover",
							onError: (e) => {
								e.currentTarget.src = "https://ik.imagekit.io/fluid/tr:w-1500,h-1500,cm-pad_resize,bg-FFFFFF/980191006/images/WJHL8V/WeCommerce_Logotype-Black_NcO-MzatB.png";
							},
							unoptimized: true
						})
					}, `${image.id}-${imageUrl}`);
				})
			}),
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Dialog, {
				open: viewerOpen,
				onOpenChange: setViewerOpen,
				children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.DialogContent, {
					className: "h-[95vh] w-[95vw] max-w-none border-0 bg-transparent p-0 shadow-none sm:max-w-none",
					showCloseButton: false,
					overlayClassName: "bg-foreground/90",
					children: [
						/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.DialogTitle, {
							className: "sr-only",
							children: productTitle
						}),
						/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.DialogDescription, {
							className: "sr-only",
							children: t("image_viewer_description")
						}),
						/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.DialogClose, {
							"aria-label": t("close_image_viewer"),
							className: "bg-foreground/60 text-background hover:bg-foreground/80 focus-visible:ring-ring focus-visible:ring-offset-background absolute top-4 right-4 z-10 flex size-10 cursor-pointer items-center justify-center rounded-full transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none",
							children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "size-5" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
								className: "sr-only",
								children: t("close_image_viewer")
							})]
						}),
						/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
							className: "relative flex h-full w-full items-center justify-center",
							children: renderImage({
								src: displayImages[currentImageIndex]?.image_url || fallbackImageUrl,
								alt: productTitle,
								fill: true,
								className: "object-contain",
								onError: (e) => {
									e.currentTarget.src = "https://ik.imagekit.io/fluid/tr:w-1500,h-1500,cm-pad_resize,bg-FFFFFF/980191006/images/WJHL8V/WeCommerce_Logotype-Black_NcO-MzatB.png";
								},
								unoptimized: true
							})
						})
					]
				})
			})
		]
	});
}
//#endregion
//#region ../../shop/ui/src/components/quantity-selector.tsx
function QuantitySelector({ quantity, setQuantity, disabled = false }) {
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "inline-flex items-center",
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "border-border bg-background inline-flex items-center rounded-full border p-1",
			children: [
				/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Button, {
					variant: "ghost",
					onClick: () => setQuantity(Math.max(1, quantity - 1)),
					className: "text-foreground size-8 rounded-full border-0 p-0 shadow-none",
					disabled,
					children: "−"
				}),
				/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
					className: "text-foreground min-w-9 px-2 text-center text-sm font-semibold",
					children: quantity
				}),
				/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Button, {
					variant: "ghost",
					onClick: () => setQuantity(quantity + 1),
					className: "text-foreground size-8 rounded-full border-0 p-0 shadow-none",
					disabled,
					children: "+"
				})
			]
		})
	});
}
//#endregion
//#region ../../shop/ui/src/components/purchase-options.tsx
function PurchaseOptions({ showBuyOnce, showSubscribe, isSubscribe, onSubscribeChange, product_subscription_plans, selectedSubscriptionPlan, onSubscriptionPlanChange, wholesalePrice, wholesaleSubscriptionPrice, currency }) {
	const { t, locale } = require_FluidProvider.useShopTranslation();
	const defaultSubscriptionPlan = (0, react.useMemo)(() => {
		if (!product_subscription_plans?.length) return null;
		return product_subscription_plans.find((plan) => plan.default) || product_subscription_plans[0];
	}, [product_subscription_plans]);
	const currentSubscriptionPlan = selectedSubscriptionPlan || defaultSubscriptionPlan;
	const savingsMode = currentSubscriptionPlan?.subscription_plan.savings_display_mode ?? "percent";
	const savingsText = (0, react.useMemo)(() => require_src.formatSavings({
		wholesalePrice,
		wholesaleSubscriptionPrice,
		mode: currency !== void 0 ? savingsMode : "percent",
		currency: currency ?? "USD",
		locale
	}), [
		wholesalePrice,
		wholesaleSubscriptionPrice,
		savingsMode,
		currency,
		locale
	]);
	const formatSubscriptionPlan = (plan) => {
		return `${plan.subscription_plan.billing_interval} ${plan.subscription_plan.billing_interval_unit} (${plan.subscription_plan.name})`;
	};
	const subscriptionPlanOptions = (0, react.useMemo)(() => {
		if (!product_subscription_plans?.length) return [];
		return product_subscription_plans.map((plan) => ({
			value: plan.subscription_plan.id.toString(),
			label: formatSubscriptionPlan(plan)
		}));
	}, [product_subscription_plans]);
	if (showBuyOnce && !showSubscribe) return null;
	const handleSubscriptionPlanChange = (planId) => {
		const selectedPlan = product_subscription_plans?.find((plan) => plan.subscription_plan.id.toString() === planId);
		if (selectedPlan && onSubscriptionPlanChange) onSubscriptionPlanChange(selectedPlan);
	};
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "mb-3 flex flex-col",
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.RadioGroup, {
			value: isSubscribe ? "subscribe" : "once",
			onValueChange: (value) => onSubscribeChange(value === "subscribe"),
			className: "gap-0 space-y-0",
			children: [showSubscribe && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				onClick: () => onSubscribeChange(true),
				className: `cursor-pointer rounded-t-lg p-4 text-left transition-all duration-200 ${showBuyOnce ? "border border-b-0" : "rounded-b-lg"} ${isSubscribe ? "bg-muted" : "bg-background"}`,
				children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
					className: "flex items-start gap-x-3",
					children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.RadioGroupItem, {
						value: "subscribe",
						onClick: (e) => e.stopPropagation(),
						className: `flex items-center justify-center [&_svg]:h-1.5 [&_svg]:w-1.5 [&_svg]:fill-white ${isSubscribe ? "border-contrast bg-contrast text-foreground" : "border-border bg-background text-muted-foreground"}`
					}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
						className: "flex-1",
						children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
							className: "text-foreground mb-1 text-sm leading-tight font-medium",
							children: savingsText ? t("subscribe_and_save", { savings: savingsText }) : t("subscribe")
						}), product_subscription_plans?.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
							className: "bg-muted mt-3 rounded-lg p-2",
							onClick: (e) => e.stopPropagation(),
							children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
								className: "text-foreground mb-1 text-xs font-medium",
								children: t("delivery_frequency")
							}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.Select, {
								value: currentSubscriptionPlan?.subscription_plan.id.toString() || "",
								onValueChange: handleSubscriptionPlanChange,
								disabled: product_subscription_plans?.length === 1,
								children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectTrigger, {
									className: "bg-background text-foreground! w-full text-xs",
									children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectValue, { placeholder: t("select_delivery_schedule") })
								}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectContent, { children: subscriptionPlanOptions.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectItem, {
									value: option.value,
									children: option.label
								}, option.value)) })]
							})]
						})]
					})]
				})
			}), showBuyOnce && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				onClick: () => onSubscribeChange(false),
				className: `cursor-pointer rounded-b-lg border p-4 text-left transition-all duration-200 ${showSubscribe ? "border-t-0" : "rounded-t-lg"} ${!isSubscribe ? "bg-muted" : "bg-background"}`,
				children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
					className: "flex items-center gap-x-3",
					children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.RadioGroupItem, {
						value: "once",
						onClick: (e) => e.stopPropagation(),
						className: `flex items-center justify-center [&_svg]:h-1.5 [&_svg]:w-1.5 [&_svg]:fill-white ${!isSubscribe ? "border-contrast bg-contrast text-foreground" : "border-border bg-background text-muted-foreground"}`
					}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
						className: "text-foreground mb-1 text-sm leading-tight font-medium",
						children: t("one_time_purchase")
					})]
				})
			})]
		})
	});
}
//#endregion
//#region ../../shop/ui/src/components/bundle-group-item.tsx
function defaultRenderImage({ src, alt, className }) {
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
		src,
		alt,
		className
	});
}
function BundleGroupItem({ item, control, selected, quantity, canAddMore, forceSubscription, onToggle, onQuantityChange, renderImage = defaultRenderImage }) {
	const { t } = require_FluidProvider.useShopTranslation();
	const label = item.title ?? t("no_title");
	const unavailable = item.available === false;
	const imageUrl = item.image_url ?? item.variant_image_url;
	const variantTitle = item.variant_title && item.variant_title !== label ? item.variant_title : null;
	const primaryLabel = variantTitle ?? label;
	const secondaryLabel = variantTitle ? label : null;
	const accessibleLabel = secondaryLabel ? `${primaryLabel}, ${secondaryLabel}` : primaryLabel;
	const rowClickable = !unavailable && control === "radio";
	return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(rowClickable ? "label" : "div", {
		className: require_src$1.cn("flex items-center gap-3 py-3", rowClickable && "cursor-pointer", unavailable && "opacity-50"),
		children: [
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				className: "bg-muted/40 size-14 shrink-0 overflow-hidden rounded-md",
				children: imageUrl ? renderImage({
					src: imageUrl,
					alt: label,
					className: "size-full object-cover"
				}) : null
			}),
			/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "min-w-0 flex-1",
				children: [
					/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
						className: "text-foreground truncate text-sm font-medium",
						children: primaryLabel
					}),
					secondaryLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
						className: "text-muted-foreground truncate text-xs",
						children: secondaryLabel
					}),
					forceSubscription && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
						className: "text-muted-foreground text-xs",
						children: t("bundle_subscription_required")
					})
				]
			}),
			/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "shrink-0",
				children: [
					control === "locked" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
						className: "text-foreground text-sm font-medium",
						children: ["×", quantity]
					}),
					control === "radio" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.RadioGroupItem, {
						value: String(item.variant_id),
						disabled: unavailable,
						"aria-label": accessibleLabel
					}),
					control === "add" && (selected ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
						className: "border-border bg-background inline-flex items-center rounded-full border p-1",
						children: [
							/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Button, {
								variant: "ghost",
								className: "text-foreground size-8 rounded-full border-0 p-0 shadow-none",
								disabled: unavailable,
								onClick: () => quantity <= 1 ? onToggle() : onQuantityChange(quantity - 1),
								children: "−"
							}),
							/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
								className: "text-foreground min-w-9 px-2 text-center text-sm font-semibold",
								children: quantity
							}),
							/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Button, {
								variant: "ghost",
								className: "text-foreground size-8 rounded-full border-0 p-0 shadow-none",
								disabled: unavailable || !canAddMore || item.max_quantity != null && quantity >= item.max_quantity,
								onClick: () => onQuantityChange(quantity + 1),
								children: "+"
							})
						]
					}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Button, {
						variant: "outline",
						className: "rounded-full",
						disabled: unavailable || !canAddMore,
						onClick: onToggle,
						children: t("bundle_add")
					}))
				]
			})
		]
	});
}
//#endregion
//#region ../../shop/ui/src/components/bundle-group.tsx
function BundleGroup({ group, status, isSelected, getQuantity, onToggle, onQuantityChange, renderImage, exclusive = false, active = false, onChoose }) {
	const { t } = require_FluidProvider.useShopTranslation();
	const included = require_src.isIncludedGroup(group);
	const singleSelect = require_src.isSingleSelectGroup(group);
	const control = included ? "locked" : singleSelect ? "radio" : "add";
	const items = require_src.sortItems(group.bundle_group_items);
	const forceGroup = group.force_subscriptions === true;
	const wholeGroup = exclusive && included;
	const target = group.max_selections ?? group.min_selections ?? null;
	const selectedVariantId = singleSelect ? items.find((item) => isSelected(item.variant_id))?.variant_id : void 0;
	const renderedItems = items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BundleGroupItem, {
		item,
		control,
		selected: isSelected(item.variant_id),
		quantity: wholeGroup ? item.quantity : getQuantity(item.variant_id),
		canAddMore: status.canAddMore,
		forceSubscription: forceGroup || item.force_subscription === true,
		onToggle: () => onToggle(item.variant_id),
		onQuantityChange: (quantity) => onQuantityChange(item.variant_id, quantity),
		...renderImage !== void 0 && { renderImage }
	}, item.id));
	return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
		className: "py-2",
		children: [
			/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "flex items-start justify-between gap-3",
				children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
					className: "flex items-center gap-2",
					children: [
						exclusive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
							type: "button",
							role: "radio",
							"aria-checked": active,
							onClick: active ? void 0 : onChoose,
							"aria-label": t("bundle_choose_this_group"),
							className: require_src$1.cn("flex size-5 shrink-0 items-center justify-center rounded-full border transition-colors", active ? "border-foreground bg-foreground text-background" : "border-input cursor-pointer"),
							children: active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "size-3" })
						}),
						/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
							className: "text-foreground text-base font-semibold",
							children: group.title ?? ""
						}),
						included && !wholeGroup && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Badge, {
							variant: "secondary",
							className: "text-[10px] uppercase",
							children: t("bundle_included")
						})
					]
				}), !included && target != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
					className: require_src$1.cn("flex shrink-0 items-center gap-1 text-sm font-medium", status.isComplete ? "text-foreground" : "text-muted-foreground"),
					children: [status.isComplete ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.CircleCheck, { className: "size-4 text-green-600" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.TriangleAlert, { className: "size-4 text-amber-500" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
						status.count,
						"/",
						target
					] })]
				})]
			}),
			group.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
				className: "text-muted-foreground mt-1 text-sm",
				children: group.description
			}),
			singleSelect ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.RadioGroup, {
				className: "divide-border/60 mt-2 divide-y",
				value: selectedVariantId != null ? String(selectedVariantId) : "",
				onValueChange: (value) => onToggle(Number(value)),
				children: renderedItems
			}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				className: "divide-border/60 mt-2 divide-y",
				children: renderedItems
			})
		]
	});
}
//#endregion
//#region ../../shop/ui/src/components/bundle-selector.tsx
/**
* Presentational body: renders a dynamic bundle's configuration (CURRENT-1394)
* — included, customizable, single-select, and mutually-exclusive groups —
* against a caller-owned selector. Holds no selection state of its own.
* Pricing (CURRENT-1834) and add-to-cart + validation messaging (CURRENT-1894)
* are layered on separately.
*/
function BundleSelectorView({ product, selector, renderImage }) {
	const { t } = require_FluidProvider.useShopTranslation();
	const groups = product.product_bundle_groups ?? [];
	const bundleConfig = product.bundle_config ?? null;
	if (groups.length === 0) return null;
	const sorted = require_src.sortGroups(groups);
	const exclusiveSets = require_src.resolveExclusiveSets(bundleConfig);
	const setBySortOrder = /* @__PURE__ */ new Map();
	exclusiveSets.forEach((set, index) => {
		for (const sortOrder of set) setBySortOrder.set(sortOrder, index);
	});
	const renderGroup = (group, exclusiveOpts) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BundleGroup, {
		group,
		status: selector.groupStatus(group),
		isSelected: (variantId) => selector.isSelected(group.id, variantId),
		getQuantity: (variantId) => selector.getQuantity(group.id, variantId),
		onToggle: (variantId) => selector.toggleItem(group.id, variantId),
		onQuantityChange: (variantId, quantity) => selector.setQuantity(group.id, variantId, quantity),
		...exclusiveOpts && {
			exclusive: true,
			active: exclusiveOpts.active,
			onChoose: () => selector.selectGroup(group.id)
		},
		...renderImage !== void 0 && { renderImage }
	}, group.id);
	const blocks = [];
	const renderedSets = /* @__PURE__ */ new Set();
	for (const group of sorted) {
		const setIndex = setBySortOrder.get(group.sort_order);
		if (setIndex === void 0) {
			blocks.push(renderGroup(group));
			continue;
		}
		if (renderedSets.has(setIndex)) continue;
		renderedSets.add(setIndex);
		const memberSortOrders = exclusiveSets[setIndex] ?? [];
		const members = sorted.filter((candidate) => memberSortOrders.includes(candidate.sort_order));
		blocks.push(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "space-y-3",
			role: "radiogroup",
			"aria-label": t("bundle_choose_one"),
			children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
				className: "text-muted-foreground text-xs font-medium",
				children: t("bundle_choose_one")
			}), members.map((member) => {
				const active = selector.groupStatus(member).count > 0;
				const pickBranch = (event) => {
					if (event.target.closest("button, a, input, select, label, [role=\"radio\"]")) return;
					selector.selectGroup(member.id);
				};
				return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
					className: require_src$1.cn("rounded-xl border p-4 transition-colors", active ? "border-foreground" : "border-border cursor-pointer"),
					...!active && { onClick: pickBranch },
					children: renderGroup(member, { active })
				}, member.id);
			})]
		}, `exclusive-${setIndex}`));
	}
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "space-y-6",
		children: blocks
	});
}
//#endregion
//#region ../../shop/ui/src/components/dynamic-bundle.tsx
/**
* Native dynamic-bundle experience for the Portal shop (CURRENT-1834 pricing +
* subscribe toggle layered on the CURRENT-1394 configurator). Owns the shared
* selection state so the running Total reflects the same picks the group list
* renders; mounted only for a loaded dynamic bundle, so the selector seeds from
* real groups. Add-to-cart submit + validation is CURRENT-1894.
*/
function DynamicBundle({ product, subscriptionPlans, cartVariantId, subscriptionPlanId, currency, renderImage, imageSlot, titleSlot, descriptionSlot, accountForPortalHeader }) {
	const { t } = require_FluidProvider.useShopTranslation();
	const groups = product.product_bundle_groups ?? [];
	const selector = require_src.useBundleSelector({
		groups,
		bundleConfig: product.bundle_config ?? null
	});
	const [userSelectedSubscribe, setUserSelectedSubscribe] = (0, react.useState)(null);
	const [selectedSubscriptionPlan, setSelectedSubscriptionPlan] = (0, react.useState)(void 0);
	const planAdjustment = (selectedSubscriptionPlan ?? subscriptionPlans.find((p) => p.default) ?? subscriptionPlans[0])?.subscription_plan;
	const totals = require_src.computeBundleTotals(product, groups, selector.state, planAdjustment ? {
		price_adjustment_type: planAdjustment.price_adjustment_type === "percentage" || planAdjustment.price_adjustment_type === "fixed_amount" ? planAdjustment.price_adjustment_type : null,
		price_adjustment_amount: planAdjustment.price_adjustment_amount == null ? null : String(planAdjustment.price_adjustment_amount)
	} : null);
	const forceSubscribe = groups.some((g) => g.force_subscriptions === true && (require_src.isIncludedGroup(g) || require_src.selectedCountForGroup(selector.state, g.id) > 0));
	const showSubscribe = subscriptionPlans.length > 0 || totals.recurring != null || forceSubscribe;
	const isSubscribe = forceSubscribe || (userSelectedSubscribe ?? false);
	const oneOffDisplay = require_src.formatPortalPrice(totals.oneOff?.toFixed(2), currency);
	const recurringDisplay = require_src.formatPortalPrice(totals.recurring?.toFixed(2), currency);
	const showRecurring = isSubscribe && recurringDisplay != null;
	const planId = selectedSubscriptionPlan?.subscription_plan.id ?? subscriptionPlanId;
	const canAddToCart = selector.allComplete && cartVariantId !== "";
	const bundledItems = JSON.stringify(selector.cartItems.map((item) => ({
		variant_id: item.variant_id,
		quantity: item.quantity,
		product_bundle_group_id: item.product_bundle_group_id
	})));
	const stickyClass = accountForPortalHeader ? "lg:sticky lg:top-20 lg:self-start" : "lg:sticky lg:top-8 lg:self-start";
	const purchasePanel = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
		className: "space-y-5",
		children: [
			/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "flex items-baseline justify-between gap-3",
				children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
					className: "text-muted-foreground text-sm font-medium",
					children: t("bundle_total")
				}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
					className: "flex items-baseline gap-2",
					children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
						className: "text-foreground text-2xl font-bold",
						children: showRecurring ? recurringDisplay : oneOffDisplay
					}), showRecurring && recurringDisplay !== oneOffDisplay && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
						className: "text-muted-foreground text-sm line-through",
						children: oneOffDisplay
					})]
				})]
			}), (totals.cv != null || totals.qv != null) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				className: "text-muted-foreground bg-muted/50 mt-3 inline-flex rounded-full px-3 py-1 text-xs font-medium",
				children: t("bundle_volume_summary", {
					cv: totals.cv ?? "-",
					qv: totals.qv ?? "-"
				})
			})] }),
			showSubscribe && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PurchaseOptions, {
				showBuyOnce: !forceSubscribe,
				showSubscribe,
				isSubscribe,
				onSubscribeChange: setUserSelectedSubscribe,
				product_subscription_plans: subscriptionPlans,
				...selectedSubscriptionPlan !== void 0 && { selectedSubscriptionPlan },
				onSubscriptionPlanChange: setSelectedSubscriptionPlan,
				...totals.oneOff !== void 0 && { wholesalePrice: totals.oneOff },
				...totals.recurring !== void 0 && { wholesaleSubscriptionPrice: totals.recurring },
				...currency !== void 0 && { currency }
			}),
			/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "pt-2",
				children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.Button, {
					variant: "default",
					className: "h-12 w-full gap-2 rounded-full text-base font-semibold",
					disabled: !canAddToCart,
					...canAddToCart && {
						"data-fluid-add-to-cart": cartVariantId,
						"data-fluid-quantity": 1,
						"data-fluid-bundled-items": bundledItems,
						"data-fluid-subscribe": isSubscribe,
						"data-fluid-subscription-plan-id": isSubscribe && planId != null ? String(planId) : "",
						"data-fluid-open-cart-after-add": "true"
					},
					children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ShoppingCart, { className: "size-4" }), isSubscribe ? t("subscribe") : t("bundle_add_to_cart")]
				}), !selector.allComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
					className: "text-muted-foreground mt-2 text-center text-sm",
					children: t("bundle_complete_selections")
				})]
			})
		]
	});
	return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
		className: "grid grid-cols-1 gap-8 lg:grid-cols-[minmax(0,570px)_minmax(0,1fr)] xl:gap-12",
		children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: stickyClass,
			children: [imageSlot, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: imageSlot != null ? "mt-6 space-y-5" : "space-y-5",
				children: [(titleSlot != null || descriptionSlot != null) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
					className: "space-y-2",
					children: [titleSlot, descriptionSlot]
				}), purchasePanel]
			})]
		}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
			className: "self-start",
			children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BundleSelectorView, {
				product,
				selector,
				...renderImage !== void 0 && { renderImage }
			})
		})]
	});
}
//#endregion
//#region ../../shop/ui/src/utils/dynamic-bundle-flag.ts
const PARAM = "dynamic_bundle";
const STORAGE_KEY = "fluid_dynamic_bundle";
/**
* Temporary feature gate for the dynamic-bundle configurator.
*
* Off by default — dynamic (customizable) bundles link out to the storefront as
* they do today. Turned on with `?dynamic_bundle=true` and made **sticky** via
* `sessionStorage`, because the portal navigates by slug with
* `history.pushState(null, "", targetPath)` (AppShell) which drops the query
* string — so a bare query param would evaporate the moment you click from the
* shop listing into a product. `?dynamic_bundle=false` clears it.
*
* Read once per mount (the sessionStorage write is idempotent). Remove this
* gate — and the `?dynamic_bundle` handling — once dynamic bundles ship on by
* default.
*/
function isDynamicBundlesEnabled() {
	if (typeof window === "undefined") return false;
	try {
		const param = new URLSearchParams(window.location.search).get(PARAM);
		if (param === "true") {
			window.sessionStorage.setItem(STORAGE_KEY, "true");
			return true;
		}
		if (param === "false") {
			window.sessionStorage.removeItem(STORAGE_KEY);
			return false;
		}
		return window.sessionStorage.getItem(STORAGE_KEY) === "true";
	} catch {
		return new URLSearchParams(window.location.search).get(PARAM) === "true";
	}
}
//#endregion
//#region ../../shop/ui/src/utils/is-variant-unavailable.ts
/**
* Decides whether a product variant should disable its purchase CTA on the
* portal shop page.
*/
function isVariantUnavailable(variant, product) {
	if (!variant) return true;
	if (variant.available === false) return true;
	if (variant.subscription_only) return !require_src.isVariantSubscribable(variant);
	const rawPrice = variant.price ?? product?.price;
	if (rawPrice == null || rawPrice === "") return true;
	const numericPrice = Number(rawPrice);
	if (Number.isNaN(numericPrice)) return true;
	if (numericPrice <= 0) return true;
	return false;
}
//#endregion
//#region ../../shop/ui/src/components/shop-app.tsx
const PAGE_SIZE = 25;
const RELATED_PRODUCTS_LIMIT = 5;
const RELATED_PRODUCTS_GRID_CLASS = "grid grid-cols-2 gap-x-4 gap-y-8 sm:grid-cols-3 lg:grid-cols-5";
function sanitizeHtml(html) {
	const doc = new DOMParser().parseFromString(html, "text/html");
	for (const el of doc.querySelectorAll("script, iframe, object, embed, form, base, meta, link, style")) el.remove();
	for (const el of doc.querySelectorAll("*")) for (const attr of [...el.attributes]) if (attr.name.toLowerCase().startsWith("on") || attr.value.toLowerCase().trim().startsWith("javascript:")) el.removeAttribute(attr.name);
	return doc.body.innerHTML;
}
const GRID_CLASS = "grid grid-cols-2 gap-x-3 gap-y-6 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5";
function SkeletonGrid({ count = 8, className = GRID_CLASS }) {
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className,
		children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "space-y-2",
			children: [
				/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "aspect-square w-full rounded-lg" }),
				/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "h-4 w-3/4" }),
				/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "h-4 w-1/2" }),
				/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "h-3 w-1/3" })
			]
		}, i))
	});
}
function ProductListing({ companyLogoUrl, renderImage, onSelectProduct, cartButton }) {
	const observerTarget = (0, react.useRef)(null);
	const { t } = require_FluidProvider.useShopTranslation();
	const catalog = require_src.usePortalProductCatalog({ perPage: PAGE_SIZE });
	const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage, error, isFetched } = (0, _tanstack_react_query.useInfiniteQuery)({
		queryKey: catalog.queryKey,
		queryFn: ({ pageParam, signal }) => catalog.fetchProducts(pageParam, signal),
		getNextPageParam: catalog.getNextPageParam,
		initialPageParam: void 0
	});
	const handleIntersect = (0, react.useCallback)((entries) => {
		if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage) fetchNextPage();
	}, [
		hasNextPage,
		isFetchingNextPage,
		fetchNextPage
	]);
	(0, react.useEffect)(() => {
		const target = observerTarget.current;
		if (!target) return;
		const observer = new IntersectionObserver(handleIntersect, {
			threshold: .1,
			rootMargin: "200px"
		});
		observer.observe(target);
		return () => observer.disconnect();
	}, [handleIntersect]);
	const allProducts = data?.pages.flatMap((page) => page.products) ?? [];
	const sortOptions = (0, react.useMemo)(() => [
		{
			id: "title_asc",
			label: t("sort_title_asc")
		},
		{
			id: "title_desc",
			label: t("sort_title_desc")
		},
		{
			id: "price_asc",
			label: t("sort_price_asc")
		},
		{
			id: "price_desc",
			label: t("sort_price_desc")
		},
		{
			id: "created_at_desc",
			label: t("sort_recent")
		},
		{
			id: "created_at_asc",
			label: t("sort_oldest")
		}
	], [t]);
	return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "mx-auto px-2 md:px-10",
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "flex flex-col gap-3 py-4 sm:flex-row sm:items-center sm:justify-between",
			children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
				className: "text-foreground text-3xl leading-tight font-semibold tracking-tight",
				children: t("shop_all")
			}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "flex items-center gap-2 sm:ml-auto",
				children: [
					/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
						className: "w-full max-w-sm sm:w-80 md:w-96",
						children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_fluid_app_ui_components_components_SearchSort.SearchSort, {
							searchValue: catalog.searchTerm,
							onSearchChange: catalog.setSearchTerm,
							placeholder: t("search_placeholder")
						})
					}),
					/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.DropdownMenuTrigger, {
						asChild: true,
						children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Button, {
							variant: "outline",
							size: "icon",
							className: "border-foreground/10 shadow-input size-9 shrink-0",
							children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ArrowUpDown, { className: "size-3" })
						})
					}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.DropdownMenuContent, {
						align: "end",
						className: "w-60",
						children: [
							/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.DropdownMenuLabel, { children: t("sort_by") }),
							/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.DropdownMenuSeparator, {}),
							/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.DropdownMenuRadioGroup, {
								value: catalog.currentSort,
								onValueChange: catalog.setCurrentSort,
								children: sortOptions.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.DropdownMenuRadioItem, {
									value: opt.id,
									children: opt.label
								}, opt.id))
							})
						]
					})] }),
					cartButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
						className: "flex shrink-0 items-center gap-3",
						children: cartButton
					})
				]
			})]
		})
	}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "mx-auto space-y-8 px-2 md:px-10 md:py-8",
		children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkeletonGrid, {}) : error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
			className: "mx-auto my-6 rounded-lg bg-red-100 px-3 py-2 text-red-500",
			children: t("error_generic")
		}) : isFetched && allProducts.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
			className: "flex flex-col items-center justify-center py-8 text-center",
			children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
				className: "text-muted-foreground text-sm",
				children: catalog.searchTerm ? t("no_search_results", { term: catalog.searchTerm }) : t("no_products")
			})
		}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
				className: GRID_CLASS,
				children: allProducts.map((product) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductCard, {
					product: tagPortalProduct(product),
					...companyLogoUrl !== void 0 && { companyLogoUrl },
					...renderImage !== void 0 && { renderImage },
					onClick: () => onSelectProduct(String(product.id))
				}, product.id))
			}),
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { ref: observerTarget }),
			isFetchingNextPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkeletonGrid, { count: 4 })
		] })
	})] });
}
/**
* Build the variant options map by grouping option_values across all variants.
* Master variants can represent real selectable options in portal product
* responses, so include them when they carry option_values.
* Groups by option_id, collecting unique value entries.
*/
function buildOptionGroups(variants) {
	const groupMap = /* @__PURE__ */ new Map();
	for (const variant of variants) for (const ov of variant.option_values ?? []) {
		if (ov.option_id == null || ov.id == null) continue;
		if (!groupMap.has(ov.option_id)) groupMap.set(ov.option_id, {
			name: ov.option_name ?? `Option ${ov.option_id}`,
			values: /* @__PURE__ */ new Map()
		});
		groupMap.get(ov.option_id).values.set(ov.id, ov.name ?? String(ov.id));
	}
	return [...groupMap.entries()].map(([optionId, group]) => ({
		optionId,
		name: group.name,
		values: [...group.values.entries()].map(([id, name]) => ({
			id,
			name
		}))
	}));
}
/**
* Find the variant matching a set of selected option value IDs.
* selections is a map of optionId → selected value id.
*/
function findVariantBySelections(variants, selections) {
	const entries = Object.entries(selections).map(([k, v]) => [Number(k), v]);
	if (entries.length === 0) return void 0;
	const matchingVariants = variants.filter((v) => entries.every(([optionId, valueId]) => v.option_values?.some((ov) => ov.option_id === optionId && ov.id === valueId)));
	return matchingVariants.find((v) => v.is_master !== true) ?? matchingVariants[0];
}
/**
* Map BFF flat subscription plans to the legacy ProductSubscriptionPlan shape
* expected by the PurchaseOptions component.
*/
function mapToLegacySubscriptionPlans(plans) {
	return plans.map((plan, idx) => ({
		...plan.id !== void 0 && { id: plan.id },
		default: idx === 0,
		products_count: null,
		subscribers_count: null,
		active: true,
		subscription_plan: {
			id: plan.id ?? 0,
			name: plan.name ?? "",
			billing_interval: plan.billing_interval ?? 1,
			billing_interval_unit: plan.billing_interval_unit ?? "month",
			billing_frequency_in_words: plan.billing_frequency ?? `${plan.billing_interval} ${plan.billing_interval_unit}`,
			active: true,
			price_adjustment_amount: null,
			price_adjustment_type: null,
			...plan.savings_display_mode !== void 0 && { savings_display_mode: plan.savings_display_mode }
		}
	}));
}
function ProductDetail({ companyLogoUrl, productId, renderImage, onSelectProduct, accountForPortalHeader }) {
	const [quantity, setQuantity] = (0, react.useState)(1);
	const [selections, setSelections] = (0, react.useState)({});
	const [userSelectedSubscribe, setUserSelectedSubscribe] = (0, react.useState)(null);
	const [selectedSubscriptionPlan, setSelectedSubscriptionPlan] = (0, react.useState)(void 0);
	const { t } = require_FluidProvider.useShopTranslation();
	const dynamicBundlesEnabled = (0, react.useMemo)(() => isDynamicBundlesEnabled(), []);
	const { product, isLoading, error, images } = require_src.usePortalProductDetail({ productId });
	const { data: relatedProductsData, isLoading: isRelatedProductsLoading } = require_src.usePortalProducts((0, react.useMemo)(() => ({
		limit: RELATED_PRODUCTS_LIMIT + 1,
		sort: "created_at_desc"
	}), []));
	const variants = (0, react.useMemo)(() => product?.variants ?? [], [product?.variants]);
	const subscriptionPlans = (0, react.useMemo)(() => product?.subscription_plans ?? [], [product?.subscription_plans]);
	const masterVariant = (0, react.useMemo)(() => variants.find((v) => v.is_master) ?? variants[0], [variants]);
	const optionGroups = (0, react.useMemo)(() => buildOptionGroups(variants), [variants]);
	const showVariantChoices = optionGroups.length === 0 && variants.length > 1;
	const [selectedVariantId, setSelectedVariantId] = (0, react.useState)(null);
	(0, react.useEffect)(() => {
		if (optionGroups.length === 0) return;
		const source = masterVariant?.option_values?.length ? masterVariant : variants.find((v) => v.option_values?.length);
		if (!source?.option_values?.length) return;
		const defaults = {};
		for (const ov of source.option_values) if (ov.option_id != null && ov.id != null) defaults[ov.option_id] = ov.id;
		setSelections(defaults);
	}, [
		optionGroups,
		variants,
		masterVariant
	]);
	(0, react.useEffect)(() => {
		if (!showVariantChoices) return;
		if (selectedVariantId != null) return;
		if (masterVariant?.id == null) return;
		setSelectedVariantId(masterVariant.id);
	}, [
		showVariantChoices,
		selectedVariantId,
		masterVariant?.id
	]);
	const selectedVariant = (0, react.useMemo)(() => {
		if (showVariantChoices) return variants.find((v) => v.id === selectedVariantId) ?? masterVariant;
		if (optionGroups.length === 0) return masterVariant;
		return findVariantBySelections(variants, selections) ?? masterVariant;
	}, [
		variants,
		optionGroups,
		selections,
		masterVariant,
		showVariantChoices,
		selectedVariantId
	]);
	const legacySubscriptionPlans = (0, react.useMemo)(() => mapToLegacySubscriptionPlans(subscriptionPlans), [subscriptionPlans]);
	const showSubscribe = legacySubscriptionPlans.length > 0;
	const showBuyOnce = selectedVariant?.subscription_only !== true;
	const isSubscribe = selectedVariant?.subscription_only === true || (userSelectedSubscribe ?? showSubscribe);
	const galleryImages = (0, react.useMemo)(() => {
		const variantImages = selectedVariant?.images;
		if (variantImages && variantImages.length > 0) return variantImages.map((img, idx) => ({
			id: idx,
			image_url: img.url ?? "",
			image_path: null,
			position: idx
		}));
		return images.map((img, idx) => ({
			id: img.id ?? idx,
			image_url: img.url,
			image_path: null,
			position: idx
		}));
	}, [selectedVariant?.images, images]);
	const coverImage = galleryImages[0]?.image_url ?? null;
	const relatedProducts = (0, react.useMemo)(() => (relatedProductsData?.products ?? []).filter((relatedProduct) => String(relatedProduct.id) !== productId).slice(0, RELATED_PRODUCTS_LIMIT), [productId, relatedProductsData?.products]);
	const selectedPricing = selectedVariant?.subscription_pricing?.find((sp) => sp.plan_id === (selectedSubscriptionPlan?.subscription_plan.id ?? legacySubscriptionPlans[0]?.subscription_plan.id));
	const wholesalePrice = selectedVariant?.wholesale_price ? Number(selectedVariant.wholesale_price) : void 0;
	const wholesaleSubscriptionPrice = selectedPricing?.wholesale_price ? Number(selectedPricing.wholesale_price) : void 0;
	const currency = selectedVariant?.currency ?? product?.currency;
	const displayPrice = require_src.formatPortalPrice(selectedVariant?.price ?? product?.price, currency);
	const displayWholesalePrice = require_src.formatPortalPrice(selectedVariant?.wholesale_price ?? selectedVariant?.price ?? product?.price, currency);
	const displayWholesaleSubscriptionPrice = require_src.formatPortalPrice(selectedPricing?.wholesale_price ?? selectedPricing?.price ?? selectedVariant?.wholesale_price ?? void 0, currency);
	const resolvedPlanId = selectedSubscriptionPlan?.subscription_plan.id ?? legacySubscriptionPlans.find((p) => p.default)?.subscription_plan.id ?? legacySubscriptionPlans[0]?.subscription_plan.id;
	const cartVariantId = String(selectedVariant?.id ?? product?.id ?? "");
	if (isLoading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "mx-auto max-w-7xl py-8 pr-4 pl-0 md:pr-6 lg:pr-8 lg:pl-0",
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "grid grid-cols-1 gap-5 lg:grid-cols-2",
			children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "aspect-square w-full rounded-lg" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "space-y-4 pl-2 lg:pl-20",
				children: [
					/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "h-8 w-3/4" }),
					/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "h-5 w-1/4" }),
					/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "h-20 w-full" }),
					/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "h-10 w-1/2" }),
					/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Skeleton, { className: "h-10 w-full" })
				]
			})]
		})
	});
	if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "flex min-h-[400px] items-center justify-center",
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "text-center",
			children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
				className: "text-foreground mb-2 text-lg font-medium",
				children: t("error_loading")
			}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
				className: "text-muted-foreground",
				children: t("error_generic")
			})]
		})
	});
	if (!product) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "flex min-h-[400px] items-center justify-center",
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "text-center",
			children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
				className: "text-foreground mb-2 text-lg font-medium",
				children: t("product_not_found")
			}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
				className: "text-muted-foreground",
				children: t("product_not_found_description")
			})]
		})
	});
	const title = product.name || t("product_fallback_name");
	const isBundle = product.is_bundle === true;
	const bundleUrl = isBundle && product.shop_link ? product.shop_link : null;
	const staticBundle = isBundle && require_src.isStaticBundle(product) && selectedVariant?.id != null;
	const hasDynamicConfig = dynamicBundlesEnabled && isBundle && !staticBundle && (product.product_bundle_groups?.length ?? 0) > 0;
	const displayCv = isBundle ? product.cv : selectedVariant?.cv;
	const displayQv = isBundle ? product.qv : selectedVariant?.qv;
	const bundlePriceDisplay = isBundle ? require_src.formatPortalPriceRange(product.price_range, currency) ?? require_src.formatPortalPrice(product.price, currency) : null;
	const bundleBasePrice = product.price_range?.min != null ? Number(product.price_range.min) : void 0;
	const selectedBundlePlan = subscriptionPlans.find((p) => p.id === resolvedPlanId) ?? subscriptionPlans[0];
	const bundleSubPrice = staticBundle ? require_src.bundleSubscriptionPrice(bundleBasePrice, product.subscription_price_range, selectedBundlePlan) : void 0;
	const staticBundleSubDisplay = bundleSubPrice !== void 0 ? require_src.formatPortalPrice(bundleSubPrice.toFixed(2), currency) : null;
	const isUnavailable = !isBundle && isVariantUnavailable(selectedVariant, product);
	const imageGallery = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImageGallery, {
		images: galleryImages,
		fallbackImageUrl: coverImage ?? "https://ik.imagekit.io/fluid/tr:w-1500,h-1500,cm-pad_resize,bg-FFFFFF/980191006/images/WJHL8V/WeCommerce_Logotype-Black_NcO-MzatB.png",
		productTitle: title,
		...renderImage !== void 0 && { renderImage }
	});
	const productTitle = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
		className: "flex flex-wrap items-start gap-2",
		children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
			className: "text-foreground flex-1 text-4xl leading-tight font-bold tracking-normal",
			children: title
		}), isBundle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Badge, {
			variant: "secondary",
			children: t("bundle_badge")
		})]
	});
	const productDescription = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
		className: "border-border/70 mt-8 border-t pt-6",
		children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
			className: "text-foreground mb-2 text-lg font-bold",
			children: t("product_description")
		}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
			className: "text-muted-foreground [&_a]:text-foreground space-y-3 text-sm leading-6 [&_a]:underline [&_li]:ml-4 [&_li]:list-disc",
			dangerouslySetInnerHTML: { __html: sanitizeHtml(product.description ?? "") }
		})]
	});
	const bundleDescription = product.description ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "text-muted-foreground [&_a]:text-foreground space-y-3 text-sm leading-6 [&_a]:underline [&_li]:ml-4 [&_li]:list-disc",
		dangerouslySetInnerHTML: { __html: sanitizeHtml(product.description) }
	}) : null;
	const relatedProductsSection = isRelatedProductsLoading || relatedProducts.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
		className: "border-border/70 mt-12 border-t pt-8",
		children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
			className: "text-foreground mb-5 text-2xl font-bold",
			children: t("more_to_shop")
		}), isRelatedProductsLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkeletonGrid, {
			count: RELATED_PRODUCTS_LIMIT,
			className: RELATED_PRODUCTS_GRID_CLASS
		}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
			className: RELATED_PRODUCTS_GRID_CLASS,
			children: relatedProducts.map((relatedProduct) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductCard, {
				product: tagPortalProduct(relatedProduct),
				...companyLogoUrl !== void 0 && { companyLogoUrl },
				...renderImage !== void 0 && { renderImage },
				onClick: () => onSelectProduct(String(relatedProduct.id))
			}, relatedProduct.id))
		})]
	}) : null;
	if (hasDynamicConfig) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "pb-8 md:pl-8",
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "mx-auto max-w-7xl px-4 py-8 md:pr-6 md:pl-0 lg:pr-8 lg:pl-0",
			children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DynamicBundle, {
				product,
				subscriptionPlans: legacySubscriptionPlans,
				cartVariantId,
				...resolvedPlanId != null && { subscriptionPlanId: resolvedPlanId },
				...currency !== void 0 && { currency },
				imageSlot: imageGallery,
				titleSlot: productTitle,
				descriptionSlot: bundleDescription,
				...accountForPortalHeader !== void 0 && { accountForPortalHeader }
			}), relatedProductsSection]
		})
	});
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		className: "pb-8 md:pl-8",
		children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "mx-auto max-w-7xl px-4 py-8 md:pr-6 md:pl-0 lg:pr-8 lg:pl-0",
			children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
				className: "grid grid-cols-1 gap-8 lg:grid-cols-[minmax(0,1.12fr)_minmax(320px,0.88fr)] xl:gap-12",
				children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
					className: accountForPortalHeader ? "lg:sticky lg:top-20 lg:self-start" : "lg:sticky lg:top-8 lg:self-start",
					children: imageGallery
				}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
					className: "self-start lg:pt-4",
					children: [
						productTitle,
						isBundle && !staticBundle && !hasDynamicConfig && bundlePriceDisplay && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
							className: "mt-5 mb-2 flex items-center gap-2",
							children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
								className: "text-foreground text-xl font-semibold",
								children: bundlePriceDisplay
							})
						}),
						staticBundle && bundlePriceDisplay && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
							className: "mt-5 mb-2 flex items-center gap-2",
							children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
								className: "text-foreground text-xl font-semibold",
								children: isSubscribe && staticBundleSubDisplay ? staticBundleSubDisplay : bundlePriceDisplay
							}), isSubscribe && staticBundleSubDisplay && staticBundleSubDisplay !== bundlePriceDisplay && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
								className: "text-muted-foreground text-sm line-through",
								children: bundlePriceDisplay
							})]
						}),
						!isBundle && !isUnavailable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
							className: "mt-5 mb-2 flex items-center gap-2",
							children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
								className: "text-foreground text-xl font-semibold",
								children: isSubscribe ? displayWholesaleSubscriptionPrice : displayWholesalePrice
							}), (isSubscribe && displayWholesaleSubscriptionPrice !== displayWholesalePrice || !isSubscribe && displayWholesalePrice !== displayPrice) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
								className: "text-muted-foreground text-sm line-through",
								children: isSubscribe ? displayWholesalePrice : displayPrice
							})]
						}),
						product.wholesale_price != null && !hasDynamicConfig && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
							className: "text-muted-foreground bg-muted/50 mt-3 mb-5 inline-flex rounded-full px-3 py-1 text-xs font-medium",
							children: [
								"CV ",
								displayCv ?? "-",
								" | QV ",
								displayQv ?? "-"
							]
						}),
						isBundle && !staticBundle ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
							className: "pt-4",
							children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.Button, {
								variant: "default",
								className: "h-12 w-full rounded-full text-base font-semibold",
								disabled: !bundleUrl,
								onClick: () => {
									if (bundleUrl) window.open(bundleUrl, "_blank", "noopener,noreferrer");
								},
								children: [t("purchase_bundle"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ExternalLink, { className: "size-4" })]
							}), !bundleUrl && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
								className: "text-muted-foreground mt-2 text-center text-xs",
								children: t("bundle_unavailable")
							})]
						}) : staticBundle ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
							className: "pt-4",
							children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PurchaseOptions, {
								showBuyOnce,
								showSubscribe,
								isSubscribe,
								onSubscribeChange: setUserSelectedSubscribe,
								...bundleBasePrice !== void 0 && { wholesalePrice: bundleBasePrice },
								...bundleSubPrice !== void 0 && { wholesaleSubscriptionPrice: bundleSubPrice },
								...currency !== void 0 && { currency },
								product_subscription_plans: legacySubscriptionPlans,
								...selectedSubscriptionPlan !== void 0 && { selectedSubscriptionPlan },
								onSubscriptionPlanChange: setSelectedSubscriptionPlan
							}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
								className: "mt-5 space-y-4",
								children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
									className: "text-foreground mb-2 text-sm font-semibold",
									children: t("quantity")
								}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuantitySelector, {
									quantity,
									setQuantity,
									disabled: isUnavailable
								})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.Button, {
									variant: "default",
									className: "h-12 w-full rounded-full text-base font-semibold",
									disabled: isUnavailable,
									...!isUnavailable && {
										"data-fluid-add-to-cart": cartVariantId,
										"data-fluid-quantity": quantity,
										"data-fluid-subscribe": isSubscribe,
										"data-fluid-subscription-plan-id": isSubscribe ? String(resolvedPlanId ?? "") : "",
										"data-fluid-open-cart-after-add": "true"
									},
									children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ShoppingCart, { className: "size-4" }), isSubscribe ? t("subscribe") : t("add_to_cart")]
								})]
							})]
						}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
							/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PurchaseOptions, {
								showBuyOnce,
								showSubscribe,
								isSubscribe,
								onSubscribeChange: setUserSelectedSubscribe,
								...wholesalePrice !== void 0 && { wholesalePrice },
								...wholesaleSubscriptionPrice !== void 0 && { wholesaleSubscriptionPrice },
								...currency !== void 0 && { currency },
								product_subscription_plans: legacySubscriptionPlans,
								...selectedSubscriptionPlan !== void 0 && { selectedSubscriptionPlan },
								onSubscriptionPlanChange: setSelectedSubscriptionPlan
							}),
							optionGroups.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
								className: "mb-4 pt-4",
								children: optionGroups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
									className: "mb-3 flex items-center",
									children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
										className: "text-md text-foreground w-24 font-bold",
										children: group.name.charAt(0).toUpperCase() + group.name.slice(1)
									}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.Select, {
										value: String(selections[group.optionId] ?? ""),
										onValueChange: (value) => setSelections((prev) => ({
											...prev,
											[group.optionId]: Number(value)
										})),
										children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectTrigger, {
											className: "w-48 max-w-full",
											children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectValue, { placeholder: t("select_option", { name: group.name }) })
										}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectContent, {
											position: "popper",
											className: "max-h-60",
											children: group.values.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectItem, {
												value: String(v.id),
												children: v.name
											}, v.id))
										})]
									})]
								}, group.optionId))
							}),
							showVariantChoices && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
								className: "mb-4 pt-4",
								children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
									className: "mb-3 flex items-center",
									children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
										className: "text-md text-foreground w-24 font-bold",
										children: t("variant_label")
									}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.Select, {
										value: selectedVariantId != null ? String(selectedVariantId) : "",
										onValueChange: (value) => setSelectedVariantId(Number(value)),
										children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectTrigger, {
											className: "w-48 max-w-full",
											children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectValue, { placeholder: t("select_variant") })
										}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectContent, {
											position: "popper",
											className: "max-h-60",
											children: variants.map((v, idx) => v.id == null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.SelectItem, {
												value: String(v.id),
												children: v.title || t("variant_fallback_name", { index: String(idx + 1) })
											}, v.id))
										})]
									})]
								})
							}),
							isUnavailable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
								className: "text-muted-foreground text-sm",
								children: t("product_unavailable")
							}),
							/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
								className: "mt-5 space-y-4",
								children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
									className: "text-foreground mb-2 text-sm font-semibold",
									children: t("quantity")
								}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuantitySelector, {
									quantity,
									setQuantity,
									disabled: isUnavailable
								})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.Button, {
									variant: "default",
									className: "h-12 w-full rounded-full text-base font-semibold",
									disabled: isUnavailable,
									...!isUnavailable && {
										"data-fluid-add-to-cart": cartVariantId,
										"data-fluid-quantity": quantity,
										"data-fluid-subscribe": isSubscribe,
										"data-fluid-subscription-plan-id": isSubscribe ? String(resolvedPlanId ?? "") : "",
										"data-fluid-open-cart-after-add": "true"
									},
									children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ShoppingCart, { className: "size-4" }), isSubscribe ? t("subscribe") : t("add_to_cart")]
								})]
							})
						] }),
						productDescription
					]
				})]
			}), relatedProductsSection]
		})
	});
}
function ShopApp({ companyLogoUrl, renderImage, productId: controlledProductId, onSelectProduct: onSelectProductProp, onBack: _onBack, cartButton, accountForPortalHeader }) {
	const [internalProductId, setInternalProductId] = (0, react.useState)(null);
	const activeProductId = controlledProductId !== void 0 ? controlledProductId : internalProductId;
	const handleSelectProduct = onSelectProductProp ?? setInternalProductId;
	if (activeProductId) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductDetail, {
		...companyLogoUrl !== void 0 && { companyLogoUrl },
		productId: activeProductId,
		...renderImage !== void 0 && { renderImage },
		onSelectProduct: handleSelectProduct,
		...accountForPortalHeader !== void 0 && { accountForPortalHeader }
	}, activeProductId);
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductListing, {
		...companyLogoUrl !== void 0 && { companyLogoUrl },
		...renderImage !== void 0 && { renderImage },
		onSelectProduct: handleSelectProduct,
		cartButton
	});
}
//#endregion
//#region ../../cart/ui/src/components/cart-script.tsx
const SCRIPT_ID = "fluid-cdn-script";
const LEAD_CAPTURE_ID = "fluid-lead-capture-suppress";
const DEFAULT_SCRIPT_SRC = "https://assets.fluid.app/scripts/fluid-sdk/latest/web-widgets/index.js";
function CartScript({ subdomain, authJwt, bffMode, scriptSrc, apiBaseUrl, debug, country, cookieDomain, shareGuid }) {
	const authJwtRef = (0, react.useRef)(authJwt);
	authJwtRef.current = authJwt;
	const countryRef = (0, react.useRef)(country);
	countryRef.current = country;
	const cookieDomainRef = (0, react.useRef)(cookieDomain);
	cookieDomainRef.current = cookieDomain;
	const shareGuidRef = (0, react.useRef)(shareGuid);
	shareGuidRef.current = shareGuid;
	(0, react.useEffect)(() => {
		if (!subdomain) return;
		if (document.getElementById(SCRIPT_ID)) return;
		const script = document.createElement("script");
		script.id = SCRIPT_ID;
		script.src = scriptSrc ?? DEFAULT_SCRIPT_SRC;
		script.type = "module";
		script.crossOrigin = "anonymous";
		script.dataset.fluidShop = subdomain;
		if (bffMode) script.dataset.bffMode = "true";
		else if (authJwtRef.current) script.dataset.authJwt = authJwtRef.current;
		if (apiBaseUrl) script.dataset.fluidApiBaseUrl = apiBaseUrl;
		if (debug) script.dataset.debug = "true";
		if (countryRef.current) script.dataset.fluidCountry = countryRef.current;
		if (cookieDomainRef.current) script.dataset.fluidCookieDomain = cookieDomainRef.current;
		if (shareGuidRef.current) script.dataset.shareGuid = shareGuidRef.current;
		document.head.appendChild(script);
		const leadCapture = document.createElement("fluid-lead-capture-widget");
		leadCapture.id = LEAD_CAPTURE_ID;
		leadCapture.setAttribute("hide-widget", "true");
		document.body.appendChild(leadCapture);
		return () => {
			const existing = document.getElementById(SCRIPT_ID);
			if (existing) existing.remove();
			const existingLeadCapture = document.getElementById(LEAD_CAPTURE_ID);
			if (existingLeadCapture) existingLeadCapture.remove();
		};
	}, [
		subdomain,
		bffMode,
		scriptSrc,
		apiBaseUrl,
		debug
	]);
	return null;
}
//#endregion
//#region ../../cart/ui/src/components/cart-widget.tsx
function CartWidget({ theme }) {
	const [mounted, setMounted] = (0, react.useState)(false);
	const widgetRef = (0, react.useRef)(null);
	(0, react.useEffect)(() => {
		setMounted(true);
	}, []);
	(0, react.useEffect)(() => {
		if (!mounted) return;
		const el = widgetRef.current;
		if (!el) return;
		if (theme) el.setAttribute("theme", JSON.stringify(theme));
		else el.removeAttribute("theme");
	}, [theme, mounted]);
	const widget = react.default.createElement("fluid-cart-widget", {
		ref: (el) => {
			widgetRef.current = el;
		},
		"data-fluid-widget": "true",
		"hide-widget": "true",
		"is-primary": "true"
	});
	if (mounted) return (0, react_dom.createPortal)(widget, document.body);
	return null;
}
//#endregion
//#region ../../cart/ui/src/components/cart-button.tsx
const MAX_SDK_POLL_ATTEMPTS = 50;
function CartButton({ onCheckout }) {
	const { t } = require_FluidProvider.useShopTranslation();
	const [initialCount, setInitialCount] = (0, react.useState)(0);
	const navigateToCheckout = (0, react.useCallback)(() => {
		if (!window.FluidCommerceSDK) {
			console.error("FluidCommerceSDK not available");
			return;
		}
		try {
			const checkoutUrl = window.FluidCommerceSDK.getCheckoutUrl();
			if (!checkoutUrl) {
				console.error("No checkout URL available");
				return;
			}
			onCheckout?.(checkoutUrl);
		} catch (error) {
			console.error("Error getting checkout URL:", error);
		}
	}, [onCheckout]);
	(0, react.useEffect)(() => {
		let timeoutId = null;
		let attempts = 0;
		let cancelled = false;
		const setupSDK = () => {
			if (cancelled) return;
			if (window.FluidCommerceSDK) {
				if (onCheckout) window.FluidCommerceSDK.setOnCheckout(navigateToCheckout);
				const count = window.FairShareSDK?.getCartItemCount?.();
				if (count != null) setInitialCount(count);
			} else if (attempts < MAX_SDK_POLL_ATTEMPTS) {
				attempts++;
				timeoutId = setTimeout(setupSDK, 100);
			}
		};
		setupSDK();
		return () => {
			cancelled = true;
			if (timeoutId) clearTimeout(timeoutId);
		};
	}, [navigateToCheckout, onCheckout]);
	return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.Button, {
		className: "bg-primary text-primary-foreground hover:bg-primary/70 relative flex h-8 items-center gap-2 rounded-sm px-3 py-1 text-xs",
		onClick: () => {
			window.fluidCart?.open();
		},
		children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
			className: "relative",
			children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ShoppingCart, { className: "size-4" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
				id: "fluid-cart-count",
				className: "bg-primary-foreground text-primary absolute -top-1 -right-2 flex size-3.5 items-center justify-center rounded-full text-[8px] font-bold",
				children: initialCount
			})]
		}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("cart") })]
	});
}
//#endregion
//#region ../../cart/ui/src/components/shop-container.tsx
function ShopContainer({ children, className = "", cartScript, cartWidget }) {
	const containerRef = (0, react.useRef)(null);
	const [portalContainer, setPortalContainer] = (0, react.useState)(null);
	(0, react.useEffect)(() => {
		const currentContainer = containerRef.current;
		if (!currentContainer) return;
		const reactContentWrapper = document.createElement("div");
		reactContentWrapper.id = "react-content-wrapper";
		reactContentWrapper.style.cssText = `
      position: relative;
    `;
		reactContentWrapper.className = "min-h-full";
		currentContainer.appendChild(reactContentWrapper);
		setPortalContainer(reactContentWrapper);
		return () => {
			if (currentContainer && reactContentWrapper) try {
				currentContainer.removeChild(reactContentWrapper);
			} catch (e) {
				console.warn("Failed to cleanup isolated container:", e);
			}
			setPortalContainer(null);
		};
	}, []);
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
		ref: containerRef,
		className: `isolated-shop-wrapper ${className} h-full`,
		children: portalContainer && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
			cartScript,
			cartWidget,
			children
		] }), portalContainer)
	}) });
}
//#endregion
//#region src/screens/ShopScreen.tsx
/**
* Extract the cart token (e.g. "ct_abc123") from a checkout URL such as
* https://checkout.fluid.app/checkouts/ct_abc123?fluid_shop=oliabo — the URL
* the FairShare SDK returns from getCheckoutUrl(). Returns null when the URL
* has no recognizable token.
*/
function parseCartToken(checkoutUrl) {
	try {
		const base = typeof window === "undefined" ? void 0 : window.location.href;
		const { pathname } = new URL(checkoutUrl, base);
		return /\/checkouts\/([^/?#]+)/.exec(pathname)?.[1] ?? null;
	} catch {
		return null;
	}
}
const CART_CLAIM_TIMEOUT_MS = 3e3;
function ShopScreen(props) {
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShopScreenContent, { ...props });
}
function ShopScreenContent({ background, textColor, accentColor, padding, borderRadius, ...divProps }) {
	const { config } = require_FluidProvider.useFluidContext();
	const { t } = require_FluidProvider.useShopTranslation();
	const { data: store } = require_use_store.useStore();
	const { data: account, isPending: accountPending } = require_use_account.useAccount();
	const client = require_PortalTenantClientProvider.usePortalTenantClient();
	const { currentSlug, navigate } = require_AppNavigationContext.useAppNavigation();
	const handleCheckout = (0, react.useCallback)(async (checkoutUrl) => {
		const token = parseCartToken(checkoutUrl);
		let destination = checkoutUrl;
		if (token) {
			let timeoutId;
			try {
				destination = (await Promise.race([require_translation_adapter.carts_claim(client, token), new Promise((_, reject) => {
					timeoutId = setTimeout(() => reject(/* @__PURE__ */ new Error("cart claim timed out")), CART_CLAIM_TIMEOUT_MS);
				})]))?.checkout_url ?? checkoutUrl;
			} catch (error) {
				console.error("Failed to claim cart:", error);
			} finally {
				if (timeoutId) clearTimeout(timeoutId);
			}
		}
		window.location.assign(destination);
	}, [client]);
	const countryCode = config.countryIso ?? "US";
	const subdomain = store?.subdomain;
	const productId = currentSlug.split("/")[1] ?? null;
	const tenantHost = typeof window !== "undefined" ? window.location.hostname : void 0;
	return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
		!productId && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ScreenHeaderContext.ScreenHeaderBreadcrumbs, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Breadcrumb, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.BreadcrumbList, {
			className: "text-lg",
			children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.BreadcrumbItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.BreadcrumbPage, {
				className: "font-semibold",
				children: t("breadcrumb")
			}) })
		}) }) }),
		/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ScreenHeaderContext.ScreenHeaderActions, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
			className: "flex items-center gap-4",
			children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CartButton, { onCheckout: handleCheckout })
		}) }),
		/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
			...divProps,
			className: divProps.className ?? "",
			children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ShopContainer, {
				cartScript: subdomain && !accountPending ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CartScript, {
					subdomain,
					bffMode: true,
					scriptSrc: {}.env.DEV ? String({}.env.VITE_FAIRSHARE_SDK_URL || "http://localhost:4444/index.js") : void 0,
					apiBaseUrl: {}.env.DEV ? String({}.env.VITE_FAIRSHARE_API_BASE_URL || "http://api.fluid.localhost:3000") : void 0,
					debug: {}.env.DEV,
					country: countryCode,
					cookieDomain: tenantHost,
					shareGuid: account?.share_guid ?? void 0
				}) : null,
				cartWidget: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CartWidget, {}),
				children: [productId && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductBreadcrumb, { productId }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShopApp, {
					companyLogoUrl: store?.logo_url ?? void 0,
					productId,
					accountForPortalHeader: true,
					onSelectProduct: (id) => navigate(`shop/${id}`),
					onBack: () => navigate("shop")
				})]
			})
		})
	] });
}
const shopScreenPropertySchema = {
	widgetType: "ShopScreen",
	displayName: "Shop Screen",
	tabsConfig: [{
		id: "styling",
		label: "Styling"
	}],
	fields: []
};
/**
* Renders inside PortalProductsCoreProvider to set breadcrumbs with the
* product name: "Shop > {product name}". Overrides the parent's "Shop"
* breadcrumb once product data loads.
*/
function ProductBreadcrumb({ productId }) {
	const { navigate } = require_AppNavigationContext.useAppNavigation();
	const parentBreadcrumb = require_use_navigation_parent.useNavigationParent();
	const { t } = require_FluidProvider.useShopTranslation();
	const { product } = require_src.usePortalProductDetail({ productId });
	const productName = product?.name ?? t("product_fallback_name");
	const parentLabel = parentBreadcrumb?.label ?? t("breadcrumb");
	return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ScreenHeaderContext.ScreenHeaderBreadcrumbs, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.Breadcrumb, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src$1.BreadcrumbList, {
		className: "text-lg",
		children: [
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.BreadcrumbItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.BreadcrumbLink, {
				onClick: parentBreadcrumb?.onClick ?? (() => navigate("shop")),
				className: "cursor-pointer font-semibold",
				children: parentLabel
			}) }),
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.BreadcrumbSeparator, {}),
			/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.BreadcrumbItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src$1.BreadcrumbPage, {
				className: "font-semibold",
				children: productName
			}) })
		]
	}) }) });
}
//#endregion
Object.defineProperty(exports, "ShopScreen", {
	enumerable: true,
	get: function() {
		return ShopScreen;
	}
});
Object.defineProperty(exports, "parseCartToken", {
	enumerable: true,
	get: function() {
		return parseCartToken;
	}
});
Object.defineProperty(exports, "shopScreenPropertySchema", {
	enumerable: true,
	get: function() {
		return shopScreenPropertySchema;
	}
});

//# sourceMappingURL=ShopScreen-IBpCfhLT.cjs.map