/* store-shop.jsx — shop UI: product cards, filter bar, product grid, category
   grid, featured bundle, gallery, quick-view modal. Interaction handlers come
   from the app via props. Exported to window. */
const { Button: SBtn, Card: SCard, Tag: STag } = window.FluvexDesignsDesignSystem_072666;
const { Reveal: SReveal, CountUp: SCountUp, useTilt: sUseTilt, useCountdown: sUseCountdown, Magnetic: SMag, useSpotlight: sUseSpot } = window;
const { StoreIcon: SIcon } = window;

const PREVIEW_BG = "linear-gradient(155deg, #f7f5ff 0%, #efe9ff 55%, #f4ecff 100%)";

function Stars({ value = 5, size = 13, color = "var(--primary)" }) {
  return <span style={{ color, fontSize: size, letterSpacing: 1 }}>{"★★★★★".slice(0, Math.round(value))}<span style={{ color: "#d9dcec" }}>{"★★★★★".slice(Math.round(value))}</span></span>;
}

function BadgePill({ children }) {
  if (!children) return null;
  return <span className="fx-badge" style={{ position: "absolute", top: 12, left: 12, zIndex: 3, fontSize: "var(--micro-cap-size)", textTransform: "uppercase", letterSpacing: "0.5px", background: "var(--primary)", color: "#fff", padding: "5px 10px", borderRadius: 9999, boxShadow: "0 4px 12px rgba(83,58,253,0.35)" }}>{children}</span>;
}

function Heart({ on, onClick }) {
  return (
    <button onClick={onClick} aria-label="Wishlist" className="fx-heart" style={{ position: "absolute", top: 10, right: 10, zIndex: 3, width: 34, height: 34, borderRadius: 9999, border: "1px solid var(--hairline)", background: "rgba(255,255,255,0.9)", backdropFilter: "blur(6px)", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", transition: "transform 160ms ease" }}>
      <svg width="17" height="17" viewBox="0 0 24 24" fill={on ? "var(--ruby)" : "none"} stroke={on ? "var(--ruby)" : "var(--ink-mute)"} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" style={{ transition: "fill 160ms ease, stroke 160ms ease" }}><path d="M12 21s-7-4.5-9.5-9A5 5 0 0112 5.5 5 5 0 0121.5 12c-2.5 4.5-9.5 9-9.5 9z" /></svg>
    </button>
  );
}

function ProductCard({ p, onQuick, onAdd, wished, onWish, delay = 0 }) {
  const Mock = window.MOCKS[p.mock];
  const tiltRef = sUseTilt(6, 1.04);
  const [added, setAdded] = React.useState(false);
  const doAdd = () => { onAdd(p); setAdded(true); setTimeout(() => setAdded(false), 1400); };
  return (
    <SReveal y={28} delay={delay} style={{ height: "100%" }}>
      <div className="fx-prod" style={{ background: "#fff", border: "1px solid var(--hairline)", borderRadius: "var(--radius-xl)", overflow: "hidden", height: "100%", display: "flex", flexDirection: "column" }}>
        <div className="fx-prod-preview" style={{ position: "relative", background: PREVIEW_BG, height: 210, perspective: 900 }}>
          <BadgePill>{p.badge}</BadgePill>
          <Heart on={wished} onClick={() => onWish(p.id)} />
          <div ref={tiltRef} className="fx-prod-mock" onClick={() => onQuick(p)} role="button" tabIndex={0} onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && onQuick(p)} aria-label={`View ${p.title}`} style={{ position: "absolute", inset: 0, transition: "transform 300ms ease", cursor: "pointer" }}><Mock /></div>
          <button onClick={() => onQuick(p)} className="fx-quick fx-shine" style={{ position: "absolute", left: "50%", bottom: 14, transform: "translateX(-50%) translateY(10px)", zIndex: 5, opacity: 0, fontSize: 13, padding: "8px 18px", borderRadius: 9999, border: "none", background: "var(--brand-dark-900)", color: "#fff", cursor: "pointer", whiteSpace: "nowrap", transition: "opacity 220ms ease, transform 220ms ease", pointerEvents: "auto" }}>Quick view</button>
        </div>
        <div style={{ padding: 18, display: "flex", flexDirection: "column", flex: 1 }}>
          <div style={{ fontSize: "var(--caption-size)", color: "var(--primary-deep)", marginBottom: 6 }}>{p.catLabel}</div>
          <h3 style={{ fontWeight: 400, fontSize: "var(--heading-sm-size)", letterSpacing: "-0.2px", margin: "0 0 8px", color: "var(--ink)" }}>{p.title}</h3>
          {p.reviews > 0 ? (
            <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 16 }}>
              <Stars value={p.rating} />
              <span className="tnum" style={{ fontSize: "var(--caption-size)", color: "var(--ink-mute)" }}>{p.rating.toFixed(1)} · {p.reviews.toLocaleString()}</span>
            </div>
          ) : (
            <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 16 }}>
              <span style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: "0.6px", color: "var(--primary-deep)", background: "var(--primary-bg-subdued-hover)", padding: "4px 10px", borderRadius: 9999 }}>New release</span>
            </div>
          )}
          <div style={{ marginTop: "auto", display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10 }}>
            <div className="tnum" style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
              <span style={{ fontSize: 22, fontWeight: 300, letterSpacing: "-0.6px", color: "var(--ink)" }}>${p.price}</span>
              {p.oldPrice ? <span style={{ fontSize: 13, color: "var(--ink-mute)", textDecoration: "line-through" }}>${p.oldPrice}</span> : null}
            </div>
            <div style={{ display: "flex", gap: 8 }}>
              <button type="button" onClick={() => onQuick(p)} className="fx-view-btn fx-btn-lift" style={{ position: "relative", zIndex: 2, fontSize: 14, fontWeight: 400, padding: "9px 18px", borderRadius: 9999, border: "1px solid var(--primary)", background: "#fff", color: "var(--primary)", cursor: "pointer", fontFamily: "var(--font-sans)", transition: "background 180ms ease, color 180ms ease, box-shadow 180ms ease" }}>View</button>
              {p.isDemoAvailable && p.demoLink ? (
                <a href={p.demoLink} onClick={(e) => { e.stopPropagation(); if (window.FluvexTracking) window.FluvexTracking.trackDemoView(p); }} title="Preview this product safely" className="fx-view-btn fx-btn-lift" style={{ position: "relative", zIndex: 2, fontSize: 14, fontWeight: 400, padding: "9px 14px", borderRadius: 9999, border: "1px solid var(--hairline)", background: "#fff", color: "var(--ink)", cursor: "pointer", fontFamily: "var(--font-sans)", textDecoration: "none", display: "inline-flex", alignItems: "center", gap: 6 }}>
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="3" /><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z" /></svg>
                  Demo
                </a>
              ) : null}
              <button onClick={doAdd} aria-label="Add to cart" className={"fx-addbtn fx-shine" + (added ? " fx-added" : "")} style={{ width: 38, height: 38, borderRadius: 9999, border: "none", background: added ? "#1f8a5b" : "var(--primary)", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", transition: "background 200ms ease, transform 160ms ease" }}>
                {added
                  ? <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5" /></svg>
                  : <SIcon name="cart" size={17} stroke="#fff" sw={1.7} />}
              </button>
            </div>
          </div>
        </div>
      </div>
    </SReveal>
  );
}

/* ---- Best sellers ---- */
function BestSellers({ onQuick, onAdd, wishes, onWish }) {
  const list = window.BEST_IDS.map((id) => window.PRODUCTS.find((p) => p.id === id));
  const spot = sUseSpot();
  return (
    <section id="best" style={{ background: "var(--canvas)", padding: "var(--section-pad-marketing) 0" }}>
      <div className="fx-container">
        <SectionHead tag="Best sellers" title="Best-selling HTML digital products" sub="Our most loved interactive tools for business, content, planning, and productivity — all made to run in your browser." />
        <div ref={spot} className="fx-spotlight" style={{ borderRadius: "var(--radius-xl)" }}>
          <div className="fx-spot-layer" />
          <div className="fx-grid-4" style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 24 }}>
            {list.map((p, i) => <ProductCard key={p.id} p={p} delay={i * 90} onQuick={onQuick} onAdd={onAdd} wished={wishes.has(p.id)} onWish={onWish} />)}
          </div>
        </div>
      </div>
    </section>
  );
}

/* ---- Custom sort dropdown (premium theme, portal-rendered) ----
   The panel is rendered into document.body via ReactDOM.createPortal so it
   escapes ALL parent stacking contexts, transforms, overflows, and filters
   in the shop layout. Placement is computed from the trigger's getBoundingClientRect. */
function SortDropdown({ value, onChange }) {
  const options = [
    { v: "featured", l: "Featured" },
    { v: "new",      l: "Newest" },
    { v: "best",     l: "Best Seller" },
    { v: "low",      l: "Price: Low to High" },
    { v: "high",     l: "Price: High to Low" },
  ];
  const current = options.find((o) => o.v === value) || options[0];
  const [open, setOpen] = React.useState(false);
  const [active, setActive] = React.useState(options.findIndex((o) => o.v === value));
  const [pos, setPos] = React.useState({ top: 0, left: 0, width: 220 });
  const btnRef = React.useRef(null);
  const panelRef = React.useRef(null);

  const measure = React.useCallback(() => {
    const el = btnRef.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    setPos({ top: r.bottom + 8, left: r.right - Math.max(r.width, 220), width: Math.max(r.width, 220) });
  }, []);

  React.useEffect(() => {
    if (!open) return;
    measure();
    const onDoc = (e) => {
      if (btnRef.current && btnRef.current.contains(e.target)) return;
      if (panelRef.current && panelRef.current.contains(e.target)) return;
      setOpen(false);
    };
    const onKey = (e) => {
      if (e.key === "Escape") setOpen(false);
      else if (e.key === "ArrowDown") { e.preventDefault(); setActive((a) => (a + 1) % options.length); }
      else if (e.key === "ArrowUp") { e.preventDefault(); setActive((a) => (a - 1 + options.length) % options.length); }
      else if (e.key === "Enter") { e.preventDefault(); onChange(options[active].v); setOpen(false); }
    };
    const onScroll = () => measure();
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onKey);
    window.addEventListener("scroll", onScroll, true);
    window.addEventListener("resize", onScroll);
    return () => {
      document.removeEventListener("mousedown", onDoc);
      document.removeEventListener("keydown", onKey);
      window.removeEventListener("scroll", onScroll, true);
      window.removeEventListener("resize", onScroll);
    };
  }, [open, active, onChange, options.length, measure]);

  const panel = open ? ReactDOM.createPortal(
    <div
      ref={panelRef}
      role="listbox"
      style={{
        position: "fixed", top: pos.top, left: pos.left, minWidth: pos.width, zIndex: 2147483647,
        background: "#faf8ff", border: "1px solid #e9d5ff", borderRadius: 16,
        boxShadow: "0 20px 48px rgba(83,58,253,0.22), 0 4px 12px rgba(28,30,84,0.1)",
        padding: 6, opacity: 1, transform: "translateY(0)",
        animation: "fx-sort-in 200ms cubic-bezier(.21,.68,.24,1)",
      }}
    >
      {options.map((o, i) => {
        const selected = o.v === value;
        const isActive = i === active;
        return (
          <div
            key={o.v}
            role="option"
            aria-selected={selected}
            onMouseEnter={() => setActive(i)}
            onClick={() => { onChange(o.v); setOpen(false); }}
            style={{
              display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12,
              padding: "10px 14px", borderRadius: 10, cursor: "pointer",
              fontFamily: "var(--font-sans)", fontSize: "var(--body-md-size)",
              color: selected ? "#fff" : "var(--ink)",
              background: selected
                ? "linear-gradient(135deg,#8f79d5,#533afd)"
                : (isActive ? "rgba(83,58,253,0.08)" : "transparent"),
              boxShadow: selected ? "0 6px 14px rgba(83,58,253,0.28)" : "none",
              transition: "background 140ms ease, color 140ms ease",
            }}
          >
            <span>{o.l}</span>
            {selected ? (
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5" /></svg>
            ) : null}
          </div>
        );
      })}
      <style>{`@keyframes fx-sort-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }`}</style>
    </div>,
    document.body
  ) : null;

  return (
    <div style={{ position: "relative", minWidth: 200 }}>
      <button
        ref={btnRef}
        type="button"
        onClick={() => { setActive(options.findIndex((o) => o.v === value)); setOpen((o) => !o); }}
        aria-haspopup="listbox"
        aria-expanded={open}
        className="fx-btn-lift"
        style={{
          display: "flex", alignItems: "center", gap: 10, width: "100%",
          fontFamily: "var(--font-sans)", fontSize: "var(--body-md-size)", color: "var(--ink)",
          background: "#fff", border: "1px solid " + (open ? "var(--primary)" : "var(--hairline)"),
          borderRadius: 9999, padding: "10px 16px", cursor: "pointer", outline: "none",
          boxShadow: open ? "0 0 0 3px rgba(83,58,253,0.14)" : "0 1px 3px rgba(0,55,112,0.05)",
          transition: "border-color 180ms ease, box-shadow 180ms ease",
        }}
      >
        <span style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: "0.7px", color: "var(--ink-mute)" }}>Sort</span>
        <span style={{ flex: 1, textAlign: "left", color: "var(--ink)" }}>{current.l}</span>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--primary)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ transform: open ? "rotate(180deg)" : "rotate(0)", transition: "transform 200ms cubic-bezier(.21,.68,.24,1)" }}>
          <path d="M6 9l6 6 6-6" />
        </svg>
      </button>
      {panel}
    </div>
  );
}

/* ---- Filterable shop grid ---- */
function Shop({ onQuick, onAdd, wishes, onWish }) {
  const [filter, setFilter] = React.useState("all");
  const [sort, setSort] = React.useState("featured");
  const [q, setQ] = React.useState("");
  const shopSpot = sUseSpot();
  React.useEffect(() => {
    if (!q.trim() || !window.FluvexTracking) return;
    const t = setTimeout(() => window.FluvexTracking.trackSearch(q), 700);
    return () => clearTimeout(t);
  }, [q]);
  let list = window.PRODUCTS.filter((p) => (filter === "all" || p.cat.includes(filter)) && (p.title + " " + (p.keywords || "") + " " + (p.category || "") + " " + (p.shortDescription || "")).toLowerCase().includes(q.trim().toLowerCase()));
  if (sort === "low") list = [...list].sort((a, b) => a.price - b.price);
  else if (sort === "high") list = [...list].sort((a, b) => b.price - a.price);
  else if (sort === "best") list = [...list].sort((a, b) => b.reviews - a.reviews);
  else if (sort === "new") list = [...list].reverse();
  return (
    <section id="shop" style={{ background: "var(--canvas-soft)", padding: "var(--section-pad-marketing) 0" }}>
      <div className="fx-container">
        <SectionHead tag="Shop" title="Shop all HTML digital products" sub="Filter, search, and sort premium browser-based tools made to save you time." />
        <SReveal y={16}>
          <div className="fx-shopbar" style={{ position: "relative", zIndex: 50, display: "flex", flexWrap: "wrap", gap: 14, alignItems: "center", justifyContent: "space-between", marginBottom: 32 }}>
            <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
              {window.FILTERS.map((f) => {
                const on = filter === f.key;
                return <button key={f.key} onClick={() => setFilter(f.key)} className="fx-filter" style={{ position: "relative", fontSize: "var(--body-md-size)", padding: "8px 16px", borderRadius: 9999, border: "1px solid " + (on ? "var(--primary)" : "var(--hairline)"), background: on ? "var(--primary)" : "#fff", color: on ? "#fff" : "var(--ink-secondary)", cursor: "pointer", transition: "all 200ms ease" }}>{f.label}</button>;
              })}
            </div>
            <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
              <div className="fx-search" style={{ display: "flex", alignItems: "center", gap: 8, background: "#fff", border: "1px solid var(--hairline)", borderRadius: 9999, padding: "8px 14px" }}>
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--ink-mute)" strokeWidth="1.7" strokeLinecap="round"><circle cx="11" cy="11" r="7" /><path d="M21 21l-4-4" /></svg>
                <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search products" style={{ border: "none", outline: "none", fontSize: "var(--body-md-size)", fontFamily: "var(--font-sans)", background: "transparent", width: 130, color: "var(--ink)" }} />
              </div>
              <SortDropdown value={sort} onChange={setSort} />
            </div>
          </div>
        </SReveal>
        <div ref={shopSpot} className="fx-spotlight" style={{ borderRadius: "var(--radius-xl)" }}>
          <div className="fx-spot-layer" />
          <div className="fx-grid-4" style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 24 }}>
            {list.map((p, i) => <ProductCard key={p.id} p={p} delay={(i % 4) * 70} onQuick={onQuick} onAdd={onAdd} wished={wishes.has(p.id)} onWish={onWish} />)}
          </div>
        </div>
        {list.length === 0 && <p style={{ textAlign: "center", color: "var(--ink-mute)", marginTop: 40 }}>No products match your search.</p>}
      </div>
    </section>
  );
}

/* ---- Categories ---- */
function Categories({ onPick }) {
  return (
    <section id="categories" style={{ background: "var(--canvas)", padding: "var(--section-pad-marketing) 0" }}>
      <div className="fx-container">
        <SectionHead tag="Categories" title="Shop by category" />
        <div className="fx-grid-3" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 24 }}>
          {window.CATEGORIES.map((c, i) => (
            <SReveal key={c.title} y={26} delay={(i % 3) * 80}>
              <a href="#shop" onClick={() => onPick && onPick(c.filter)} className="fx-cat fx-card-hover" style={{ display: "flex", alignItems: "center", gap: 18, padding: 24, borderRadius: "var(--radius-xl)", border: "1px solid var(--hairline)", background: "#fff", textDecoration: "none", height: "100%" }}>
                <span className="fx-cat-icon" style={{ flexShrink: 0, width: 56, height: 56, borderRadius: 16, background: "var(--primary-bg-subdued-hover)", display: "flex", alignItems: "center", justifyContent: "center", transition: "transform 300ms ease" }}><SIcon name={c.icon} size={26} /></span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: "var(--heading-sm-size)", fontWeight: 400, color: "var(--ink)", marginBottom: 3 }}>{c.title}</div>
                  <div className="tnum" style={{ fontSize: "var(--caption-size)", color: "var(--ink-mute)" }}>{c.count} products</div>
                </div>
                <span className="fx-cat-arrow" style={{ color: "var(--primary)", fontSize: 20, transition: "transform 260ms ease" }}>→</span>
              </a>
            </SReveal>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---- Featured bundle: The Complete Fluvex Digital Toolkit ----
   High-converting premium offer. EDIT copy / price / links here.
   Replace `checkoutLink` with your Stripe / Gumroad / Shopify / Payhip /
   Lemon Squeezy checkout URL. Do not put a direct download file here unless
   payment protection is handled by the checkout provider. */
function Bundle({ onAdd }) {
  const target = React.useRef(Date.now() + (2 * 864e5 + 14 * 36e5 + 37 * 6e4)).current;
  const t = sUseCountdown(target);
  const bundleSpot = sUseSpot();
  const collageTilt = sUseTilt(6, 1);
  const paraA = window.useParallax(24);
  const paraB = window.useParallax(-18);
  const paraC = window.useParallax(32);
  const paraD = window.useParallax(-26);

  // The 13 real FluvexDesigns products included in this bundle. `mock` = collage art, `icon`/`grad` = tile art.
  const bundleItems = [
    { name: "Editable Teacher Planner Studio 2026–2027", mock: "MkPlanner",       icon: "planner",   grad: "linear-gradient(135deg,#c9b6f5,#533afd)" },
    { name: "Fluvex Business Card Studio",             mock: "MkCard",          icon: "briefcase", grad: "linear-gradient(135deg,#1c1e54,#533afd)" },
    { name: "Content Calendar & Growth Dashboard",     mock: "MkCalendar",      icon: "grid",      grad: "linear-gradient(135deg,#b9b9f9,#665efd)" },
    { name: "Fluvex Life Tracker Pro",                 mock: "MkDashboard",     icon: "sparkle",   grad: "linear-gradient(135deg,#9ad1c9,#533afd)" },
    { name: "Fluvex Budget Tracker Studio",            mock: "MkBudget",        icon: "clock",     grad: "linear-gradient(135deg,#f7b986,#ea2261)" },
    { name: "Wedding Invitation Studio — Rose Edition", mock: "MkWeddingBundle",       icon: "heart",     grad: "linear-gradient(135deg,#f96bee,#c9b6f5)" },
    { name: "Editable Floral Wedding Invitation Studio", mock: "MkFloralWedding", icon: "heart",     grad: "linear-gradient(135deg,#f7b986,#f96bee)" },
    { name: "Fluvex Photo Resume Studio",              mock: "MkResume",        icon: "doc",       grad: "linear-gradient(135deg,#b9b9f9,#533afd)" },
    { name: "Fluvex Media Kit Studio",                 mock: "MkMediaKit",      icon: "share",     grad: "linear-gradient(135deg,#c9b6f5,#f96bee)" },
    { name: "Fluvex Invoice Studio",                   mock: "MkInvoice",       icon: "briefcase", grad: "linear-gradient(135deg,#533afd,#ea2261)" },
    { name: "Fluvex Cover Letter Studio",              mock: "MkCoverLetter",   icon: "edit",      grad: "linear-gradient(135deg,#f7e7cb,#f7b986)" },
    { name: "Fluvex Resume Studio",                    mock: "MkResume",        icon: "doc",       grad: "linear-gradient(135deg,#665efd,#c9b6f5)" },
    { name: "AI Academic Mastery Prompt Pack (PDF)",   mock: "MkAIPromptsBundle",     icon: "sparkle",   grad: "linear-gradient(135deg,#665efd,#9ad1c9)", aspect: "1 / 1" },
  ];
  const perks = [
    "Instant digital download", "Video demos included", "Editable files",
    "Beginner friendly", "Lifetime access", "Future updates included", "No physical product shipped",
  ];
  const bundleProduct = {
    id: "complete-toolkit",
    title: "The Complete Fluvex Digital Toolkit",
    price: 29.99,
    productType: "HTML + PDF Bundle",
    // ⛑ Replace this checkoutLink with your Stripe, Gumroad, Shopify, Payhip, or Lemon Squeezy checkout link.
    checkoutLink: (window.BUNDLE && window.BUNDLE.checkoutLink) || "#checkout-complete-toolkit",
    link: (window.BUNDLE && window.BUNDLE.checkoutLink) || "#checkout-complete-toolkit",
    includedProducts: bundleItems.map((b) => b.name),
    // ⛑ Do not expose the raw ZIP here — deliver via the checkout provider after payment.
    bundleDownloadFile: (window.BUNDLE && window.BUNDLE.deliveryFile) || "protected-download-after-payment/Complete-Fluvex-Digital-Toolkit.zip",
  };
  const check = <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="var(--primary-soft)" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}><path d="M20 6L9 17l-5-5" /></svg>;

  const collageCards = [
    { mock: "MkCalendar",  ref: paraA, top: "2%",    left: "5%",    w: "46%", rot: -6, dur: "8s",   d: "0s",    z: 4 },
    { mock: "MkDashboard", ref: paraB, top: "0%",    right: "5%",   w: "42%", rot: 5,  dur: "7s",   d: "-2s",   z: 3 },
    { mock: "MkWeddingBundle",   ref: paraC, top: "30%",   left: "26%",   w: "48%", rot: 2,  dur: "9.5s", d: "-3s",   z: 6 },
    { mock: "MkPlanner",   ref: paraA, bottom: "20%",left: "2%",    w: "42%", rot: 4,  dur: "9s",   d: "-4s",   z: 5 },
    { mock: "MkBudget",    ref: paraD, bottom: "14%", right: "3%",  w: "44%", rot: -4, dur: "8.5s", d: "-1s",   z: 7 },
    { mock: "MkResume",    ref: paraB, bottom: "2%", left: "34%",   w: "30%", rot: -3, dur: "7.5s", d: "-2.5s", z: 6 },
  ];
  const labels = [
    { txt: "13 Products Included",   top: "2%",     left: "32%",  dur: "6s",   d: "0s" },
    { txt: "Save 75%",                top: "38%",    right: "12%", dur: "7s",   d: "-1s", hot: true },
    { txt: "Instant Download",       top: "58%",    left: "6%",   dur: "6.5s", d: "-2s", hideSm: true },
    { txt: "Video Demo Included",    bottom: "4%",  left: "34%",  dur: "7.5s", d: "-3s" },
    { txt: "Limited Offer",          top: "14%",    right: "18%", dur: "6.8s", d: "-1.5s", hideSm: true },
  ];

  return (
    <section id="bundles" style={{ background: "var(--canvas)", padding: "var(--section-pad-marketing) 0" }}>
      <div className="fx-container">
        <SReveal y={30}>
          <div ref={bundleSpot} className="fx-bundle-card fx-spotlight" style={{ position: "relative", overflow: "hidden", borderRadius: "var(--radius-xl)", background: "var(--brand-dark-900)", boxShadow: "0 40px 90px rgba(28,30,84,0.4)" }}>
            <div className="fx-spot-layer" style={{ background: "radial-gradient(circle 360px at var(--sx,50%) var(--sy,50%), rgba(150,118,255,0.26), rgba(150,118,255,0) 60%)" }} />
            <div aria-hidden="true" className="fx-drift" style={{ position: "absolute", inset: 0, opacity: 0.6, filter: "blur(84px)", backgroundImage: "radial-gradient(40% 80% at 12% 22%, #533afd 0%, rgba(83,58,253,0) 70%), radial-gradient(45% 90% at 92% 86%, #f96bee 0%, rgba(249,107,238,0) 70%), radial-gradient(42% 82% at 74% 8%, #c9b6f5 0%, rgba(201,182,245,0) 70%)" }} />

            {/* ---- top: two-column offer ---- */}
            <div className="fx-bundle" style={{ position: "relative", display: "grid", gridTemplateColumns: "1.06fr 0.94fr", alignItems: "stretch" }}>
              {/* left column */}
              <div style={{ position: "relative", padding: "52px 44px" }}>
                <span style={{ display: "inline-block", fontSize: "var(--micro-cap-size)", textTransform: "uppercase", letterSpacing: "0.7px", fontWeight: 400, background: "linear-gradient(90deg, var(--primary), #b98bff)", color: "#fff", padding: "6px 14px", borderRadius: 9999, boxShadow: "0 6px 18px rgba(83,58,253,0.4)" }}>Best Value — Limited Launch Offer</span>
                <h2 style={{ fontWeight: 300, fontSize: "var(--display-lg-size)", letterSpacing: "var(--display-lg-ls)", color: "#fff", margin: "18px 0 12px", lineHeight: 1.06 }}>The Complete Fluvex Digital Toolkit</h2>
                <p style={{ fontSize: "var(--body-lg-size)", lineHeight: 1.55, color: "rgba(255,255,255,0.74)", margin: "0 0 26px", maxWidth: 480 }}>Get every premium FluvexDesigns digital product in one powerful bundle made for business, content, productivity, career, students, planning, and professional design.</p>

                <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "11px 22px", marginBottom: 30 }}>
                  {perks.map((f) => (
                    <div key={f} style={{ display: "flex", gap: 9, alignItems: "center", color: "rgba(255,255,255,0.9)", fontSize: "var(--body-md-size)" }}>{check}{f}</div>
                  ))}
                </div>

                {/* price card */}
                <div className="fx-price-pop" style={{ display: "inline-flex", alignItems: "center", gap: 16, background: "rgba(255,255,255,0.06)", border: "1px solid rgba(255,255,255,0.14)", borderRadius: "var(--radius-lg)", padding: "16px 22px", marginBottom: 22, boxShadow: "0 10px 30px rgba(83,58,253,0.22)" }}>
                  <div className="tnum" style={{ display: "flex", alignItems: "baseline", gap: 10 }}>
                    <span style={{ fontSize: 46, fontWeight: 300, letterSpacing: "-1.6px", color: "#fff", lineHeight: 1 }}>$29.99</span>
                    <span style={{ fontSize: 19, color: "rgba(255,255,255,0.5)", textDecoration: "line-through" }}>$128+</span>
                  </div>
                  <span className="fx-savebadge" style={{ fontSize: 12, fontWeight: 400, color: "#fff", background: "var(--ruby)", padding: "6px 12px", borderRadius: 9999, whiteSpace: "nowrap", boxShadow: "0 6px 16px rgba(234,34,97,0.45)" }}>Save 75% Today</span>
                </div>

                <div style={{ display: "flex", alignItems: "center", gap: 20, flexWrap: "wrap", marginBottom: 18 }}>
                  <SMag><a href={bundleProduct.checkoutLink} target="_blank" rel="noopener noreferrer" onClick={(e) => { if ((bundleProduct.checkoutLink || "").startsWith("#")) { e.preventDefault(); window.alert("Checkout link not connected yet."); } }} style={{ textDecoration: "none" }}><button className="fx-shine fx-btn-lift fx-cta-glow" style={{ fontSize: 16, fontWeight: 400, padding: "14px 28px", borderRadius: 9999, border: "none", background: "var(--primary)", color: "#fff", cursor: "pointer", fontFamily: "var(--font-sans)" }}>Get Complete Bundle →</button></a></SMag>
                  <a href="#bundle-included" className="fx-navlink" style={{ color: "rgba(255,255,255,0.82)", fontSize: "var(--body-md-size)" }}>See what's included</a>
                </div>

                <div style={{ fontSize: "var(--caption-size)", color: "rgba(255,255,255,0.66)", marginBottom: 4 }}>Secure checkout · Instant access after purchase · Digital files only</div>
                <div style={{ fontSize: "var(--caption-size)", color: "rgba(255,255,255,0.44)", marginBottom: 26 }}>All products are digital downloads. No physical product will be shipped.</div>

                <div>
                  <div style={{ fontSize: "var(--caption-size)", color: "rgba(255,255,255,0.62)", marginBottom: 9 }}>Launch offer ends in:</div>
                  <div className="tnum" style={{ display: "flex", gap: 10 }}>
                    {[[t.d, "Days"], [t.h, "Hours"], [t.m, "Minutes"], [t.s, "Seconds"]].map(([v, l]) => (
                      <div key={l} className="fx-glass" style={{ textAlign: "center", background: "rgba(255,255,255,0.08)", border: "1px solid rgba(179,150,255,0.28)", borderRadius: 14, padding: "12px 14px", minWidth: 62, boxShadow: "0 8px 22px rgba(83,58,253,0.22)" }}>
                        <div key={v} className="fx-tick" style={{ fontSize: 26, fontWeight: 300, color: "#fff", letterSpacing: "-0.5px" }}>{v}</div>
                        <div style={{ fontSize: 9, textTransform: "uppercase", letterSpacing: "0.6px", color: "rgba(255,255,255,0.55)" }}>{l}</div>
                      </div>
                    ))}
                  </div>
                </div>
              </div>

              {/* right column — floating collage (safe-bounded) */}
              <div className="fx-bundle-art" style={{ position: "relative", minHeight: 560, overflow: "hidden", padding: "18px" }}>
                <div aria-hidden="true" className="fx-drift" style={{ position: "absolute", top: "18%", left: "22%", width: "60%", height: "60%", borderRadius: "50%", filter: "blur(70px)", background: "radial-gradient(circle, rgba(150,118,255,0.55), rgba(150,118,255,0) 68%)" }} />
                <div ref={collageTilt} style={{ position: "absolute", inset: 18, transformStyle: "preserve-3d", transition: "transform 300ms cubic-bezier(.21,.68,.24,1)" }}>
                  {collageCards.map((c, i) => {
                    const Mock = window.MOCKS[c.mock];
                    return (
                      <div key={i} ref={c.ref} style={{ position: "absolute", top: c.top, bottom: c.bottom, left: c.left, right: c.right, width: c.w, aspectRatio: "4 / 3", zIndex: c.z }}>
                        <div className="fx-float" style={{ position: "relative", width: "100%", height: "100%", animationDuration: c.dur, animationDelay: c.d }}>
                          <div style={{ position: "relative", width: "100%", height: "100%", transform: `rotate(${c.rot}deg)`, borderRadius: 14, overflow: "hidden", boxShadow: "0 26px 60px rgba(13,10,40,0.5)", border: "1px solid rgba(255,255,255,0.5)", background: "#fff" }}><Mock /></div>
                        </div>
                      </div>
                    );
                  })}
                  {labels.map((l, i) => (
                    <div key={i} className={"fx-float fx-blabel" + (l.hideSm ? " fx-hide-sm" : "")} style={{ position: "absolute", top: l.top, bottom: l.bottom, left: l.left, right: l.right, zIndex: 8, animationDuration: l.dur, animationDelay: l.d, background: l.hot ? "var(--ruby)" : "rgba(255,255,255,0.95)", color: l.hot ? "#fff" : "var(--ink)", fontSize: 12, fontWeight: 400, padding: "7px 13px", borderRadius: 9999, boxShadow: l.hot ? "0 10px 24px rgba(234,34,97,0.5)" : "0 10px 24px rgba(13,10,40,0.35)", whiteSpace: "nowrap", maxWidth: "max-content" }}>{l.txt}</div>
                  ))}
                </div>
              </div>
            </div>

            {/* ---- included products strip ---- */}
            <div id="bundle-included" style={{ position: "relative", padding: "34px 44px 46px", borderTop: "1px solid rgba(255,255,255,0.12)" }}>
              <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 16, flexWrap: "wrap", marginBottom: 22 }}>
                <div style={{ fontSize: "var(--heading-sm-size)", fontWeight: 400, color: "#fff" }}>Included in this bundle</div>
                <div className="tnum" style={{ fontSize: "var(--body-md-size)", color: "var(--primary-soft)" }}>13 premium digital products included</div>
              </div>
              <div className="fx-bundle-tiles" style={{ display: "grid", gridTemplateColumns: "repeat(6, minmax(0, 1fr))", gap: 14 }}>
                {bundleItems.map((it, i) => {
                  const Mock = window.MOCKS[it.mock];
                  return (
                    <SReveal key={i} y={18} delay={i * 55}>
                      <div className="fx-bundle-tile" style={{ borderRadius: "var(--radius-md)", overflow: "hidden", background: "rgba(255,255,255,0.05)", border: "1px solid rgba(255,255,255,0.12)", height: "100%", minWidth: 0 }}>
                        <div style={{ position: "relative", width: "100%", aspectRatio: it.aspect || "4 / 3", background: "#fff", overflow: "hidden" }}><Mock /></div>
                        <div style={{ padding: "11px 12px 13px", display: "flex", flexDirection: "column", gap: 6 }}>
                          <div style={{ fontSize: 12, lineHeight: 1.3, color: "rgba(255,255,255,0.92)", minHeight: 31, overflowWrap: "anywhere" }}>{it.name}</div>
                          <div style={{ display: "flex", alignItems: "center", gap: 5, fontSize: 10, color: "var(--primary-soft)" }}>{check}<span style={{ textTransform: "uppercase", letterSpacing: "0.4px" }}>Included</span></div>
                        </div>
                      </div>
                    </SReveal>
                  );
                })}
              </div>
              <div style={{ marginTop: 24, fontSize: "var(--caption-size)", color: "rgba(255,255,255,0.5)" }}>Limited-time launch offer. Price may increase soon.</div>
            </div>
          </div>
        </SReveal>
      </div>
    </section>
  );
}

/* ---- Gallery (masonry-ish) ---- */
function Gallery({ onQuick }) {
  const items = ["MkPlanner", "MkInvoice", "MkDashboard", "MkMediaKit", "MkResume", "MkCalendar", "MkCard", "MkBudget"];
  const spans = [1, 1, 1, 1, 1, 1, 1, 1];
  return (
    <section style={{ background: "var(--canvas-soft)", padding: "var(--section-pad-marketing) 0" }}>
      <div className="fx-container">
        <SectionHead tag="Preview" title="A closer look inside" sub="Every product is designed with clean layouts, real structure, and premium detail." />
        <div className="fx-gallery" style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 20 }}>
          {items.map((m, i) => {
            const Mock = window.MOCKS[m];
            return (
              <SReveal key={i} y={26} delay={(i % 4) * 70}>
                <div className="fx-gal-item" style={{ position: "relative", height: 220, borderRadius: "var(--radius-lg)", overflow: "hidden", background: PREVIEW_BG, border: "1px solid var(--hairline)" }}>
                  <div className="fx-gal-mock" style={{ position: "absolute", inset: 0, transition: "transform 400ms ease" }}><Mock /></div>
                  <div className="fx-gal-overlay" style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", background: "rgba(28,30,84,0.55)", opacity: 0, transition: "opacity 260ms ease" }}>
                    <button onClick={() => onQuick(window.PRODUCTS[i % window.PRODUCTS.length])} className="fx-shine" style={{ fontSize: 13, padding: "9px 18px", borderRadius: 9999, border: "1px solid rgba(255,255,255,0.4)", background: "rgba(255,255,255,0.12)", color: "#fff", backdropFilter: "blur(6px)", cursor: "pointer" }}>Preview Product</button>
                  </div>
                </div>
              </SReveal>
            );
          })}
        </div>
      </div>
    </section>
  );
}

/* ---- Quick view modal ---- */
function QuickView({ product, onClose, onAdd }) {
  const [show, setShow] = React.useState(false);
  React.useEffect(() => { const id = requestAnimationFrame(() => setShow(true)); return () => cancelAnimationFrame(id); }, []);
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, []);
  if (!product) return null;
  const Mock = window.MOCKS[product.mock];
  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 200, display: "flex", alignItems: "center", justifyContent: "center", padding: 20, background: "rgba(13,37,61,0.5)", backdropFilter: "blur(6px)", opacity: show ? 1 : 0, transition: "opacity 260ms ease" }}>
      <div onClick={(e) => e.stopPropagation()} style={{ width: "min(860px, 100%)", maxHeight: "90vh", overflow: "auto", background: "#fff", borderRadius: "var(--radius-xl)", boxShadow: "var(--shadow-2)", display: "grid", gridTemplateColumns: "1fr 1fr", transform: show ? "scale(1) translateY(0)" : "scale(0.94) translateY(12px)", transition: "transform 300ms cubic-bezier(.21,.68,.24,1)" }} className="fx-modal">
        <div style={{ position: "relative", background: PREVIEW_BG, minHeight: 320 }}>
          <BadgePill>{product.badge}</BadgePill>
          <div style={{ position: "absolute", inset: 0 }}><Mock /></div>
        </div>
        <div style={{ padding: 32, position: "relative" }}>
          <button onClick={onClose} aria-label="Close" style={{ position: "absolute", top: 16, right: 16, width: 34, height: 34, borderRadius: 9999, border: "1px solid var(--hairline)", background: "#fff", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--ink)" strokeWidth="1.7" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18" /></svg>
          </button>
          <div style={{ fontSize: "var(--caption-size)", color: "var(--primary-deep)", marginBottom: 8 }}>{product.catLabel}</div>
          <h3 style={{ fontWeight: 300, fontSize: "var(--display-md-size)", letterSpacing: "var(--display-md-ls)", margin: "0 0 12px" }}>{product.title}</h3>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 18 }}>{product.reviews > 0 ? (<><Stars value={product.rating} /><span className="tnum" style={{ fontSize: "var(--caption-size)", color: "var(--ink-mute)" }}>{product.rating.toFixed(1)} · {product.reviews.toLocaleString()} reviews</span></>) : (<span style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: "0.6px", color: "var(--primary-deep)", background: "var(--primary-bg-subdued-hover)", padding: "4px 10px", borderRadius: 9999 }}>New release</span>)}</div>
          <p style={{ fontSize: "var(--body-md-size)", color: "var(--ink-secondary)", lineHeight: 1.6, margin: "0 0 18px" }}>{product.longDescription || product.shortDescription || "A premium FluvexDesigns digital product. Open in your browser or PDF reader and start using it immediately — no software required."}</p>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginBottom: 16 }}>
            <span style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: "0.6px", padding: "4px 10px", borderRadius: 9999, background: "var(--primary-bg-subdued-hover)", color: "var(--primary-deep)" }}>{product.productType || "HTML Product"}</span>
            <span style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: "0.6px", padding: "4px 10px", borderRadius: 9999, background: "var(--canvas-soft)", color: "var(--ink-secondary)", border: "1px solid var(--hairline)" }}>{product.category || "Digital Product"}</span>
            <span style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: "0.6px", padding: "4px 10px", borderRadius: 9999, background: "var(--canvas-soft)", color: "var(--ink-secondary)", border: "1px solid var(--hairline)" }}>Instant Digital Download</span>
          </div>
          <div style={{ background: "var(--canvas-soft)", border: "1px solid var(--hairline)", borderRadius: "var(--radius-md)", padding: "12px 16px", marginBottom: 14 }}>
            <div style={{ fontSize: "var(--caption-size)", color: "var(--primary-deep)", textTransform: "uppercase", letterSpacing: "0.6px", marginBottom: 6 }}>What's included</div>
            <ul style={{ margin: 0, padding: 0, listStyle: "none", fontSize: "var(--body-md-size)", color: "var(--ink)", lineHeight: 1.55 }}>
              {(product.includedFiles || ["Interactive HTML file", "Works in your browser"]).map((f, i) => (
                <li key={i} style={{ display: "flex", gap: 8, alignItems: "flex-start" }}><span style={{ color: "var(--primary)", flexShrink: 0 }}>✓</span><span>{f}</span></li>
              ))}
            </ul>
          </div>
          <div style={{ background: "var(--canvas-soft)", border: "1px solid var(--hairline)", borderRadius: "var(--radius-md)", padding: "12px 16px", marginBottom: 20 }}>
            <div style={{ fontSize: "var(--caption-size)", color: "var(--primary-deep)", textTransform: "uppercase", letterSpacing: "0.6px", marginBottom: 6 }}>Delivery</div>
            <div style={{ fontSize: "var(--body-md-size)", color: "var(--ink)", lineHeight: 1.5 }}>{product.deliveryInstructions || "Instant digital download delivered by the connected checkout platform after payment."}</div>
          </div>
          <div className="tnum" style={{ display: "flex", alignItems: "baseline", gap: 10, marginBottom: 24 }}>
            <span style={{ fontSize: 32, fontWeight: 300, letterSpacing: "-1px" }}>${product.price}</span>
            {product.oldPrice ? <span style={{ fontSize: 16, color: "var(--ink-mute)", textDecoration: "line-through" }}>${product.oldPrice}</span> : null}
          </div>
          <div style={{ display: "flex", gap: 12, flexWrap: "wrap" }}>
            {/* Buy Now → sends customer straight to the product checkoutLink. Replace with your Stripe/Gumroad/Payhip/Lemon Squeezy link in store-data.jsx. */}
            <a href={product.checkoutLink || "#checkout"} target="_blank" rel="noopener noreferrer" onClick={(e) => { if (!product.checkoutLink || product.checkoutLink.startsWith("#")) { e.preventDefault(); window.alert("Checkout link not connected yet."); } }} style={{ flex: "1 1 200px", textDecoration: "none" }}>
              <button className="fx-shine fx-btn-lift" style={{ width: "100%", fontSize: 16, padding: "12px 20px", borderRadius: 9999, border: "none", background: "var(--primary)", color: "#fff", cursor: "pointer", fontFamily: "var(--font-sans)" }}>Buy Now →</button>
            </a>
            <button onClick={() => onAdd(product)} className="fx-btn-lift" style={{ fontSize: 15, padding: "12px 18px", borderRadius: 9999, border: "1px solid var(--primary)", background: "#fff", color: "var(--primary)", cursor: "pointer", fontFamily: "var(--font-sans)" }}>Add to Cart</button>
            {product.isDemoAvailable && product.demoLink ? (
              <a href={product.demoLink} onClick={() => { if (window.FluvexTracking) window.FluvexTracking.trackDemoView(product); }} style={{ textDecoration: "none" }}><SBtn variant="secondary" className="fx-btn-lift">View Demo</SBtn></a>
            ) : null}
          </div>
          <div style={{ marginTop: 18, fontSize: "var(--caption-size)", color: "var(--ink-mute)" }}>After purchase, you will receive instant access to your digital files. No physical product will be shipped.</div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Stars, ProductCard, BestSellers, Shop, Categories, Bundle, Gallery, QuickView });
