function createTemplatePreviewScheduler(win = window, doc = document, settleMs = 32) {
    const cards = new Map();
    let timer = null, observer = null, listening = false, pageHidden = false;
    const allowed = () => !doc.hidden && !pageHidden;
    const clearTimer = () => {
        if (timer !== null)
            win.clearTimeout(timer);
        timer = null;
    };
    const setState = (card, mounted, active) => {
        if (card.mounted === mounted && card.active === active)
            return;
        card.mounted = mounted;
        card.active = active;
        card.onState({ mounted, active });
    };
    const pauseAll = () => {
        for (const card of cards.values())
            setState(card, card.mounted, false);
    };
    const position = (element) => {
        if (element.isConnected === false)
            return { visible: false, distance: Infinity };
        const rect = element.getBoundingClientRect();
        const height = win.innerHeight || doc.documentElement.clientHeight;
        const width = win.innerWidth || doc.documentElement.clientWidth;
        if (rect.width <= 0 || rect.height <= 0 || rect.right <= 0 || rect.left >= width)
            return { visible: false, distance: Infinity };
        return { visible: rect.bottom > 0 && rect.top < height, distance: Math.max(0, rect.top - height, -rect.bottom) };
    };
    const settle = () => {
        timer = null;
        if (!allowed()) {
            pauseAll();
            return;
        }
        const positions = new Map([...cards].map(([element, card]) => [card, position(element)]));
        const spare = win.navigator?.deviceMemory <= 2 ? 1 : 2;
        const preload = win.navigator?.connection?.saveData ? -1 : 220;
        const warm = [...positions].filter(([card, pos]) => !pos.visible && Number.isFinite(pos.distance) && (card.mounted || pos.distance < preload))
            .sort((a, b) => a[1].distance - b[1].distance).slice(0, spare).map(([card]) => card);
        for (const [element, card] of cards) {
            const visible = positions.get(card).visible;
            setState(card, visible || warm.includes(card), visible);
        }
    };
    const schedule = () => {
        if (!allowed()) {
            clearTimer();
            pauseAll();
            return;
        }
        if (timer !== null)
            return;
        timer = win.setTimeout(settle, settleMs);
    };
    const onViewportChange = () => {
        schedule();
    };
    const pageHide = () => { pageHidden = true; clearTimer(); pauseAll(); };
    const pageShow = () => { pageHidden = false; onViewportChange(); };
    const start = () => {
        if (listening)
            return;
        listening = true;
        if (win.IntersectionObserver)
            observer = new win.IntersectionObserver(schedule, { threshold: [0, .01], rootMargin: "220px 0px" });
        win.addEventListener("scroll", onViewportChange, { passive: true });
        win.addEventListener("resize", onViewportChange, { passive: true });
        win.addEventListener("pagehide", pageHide);
        win.addEventListener("pageshow", pageShow);
        doc.addEventListener("visibilitychange", onViewportChange);
    };
    const stop = () => {
        clearTimer();
        observer?.disconnect();
        observer = null;
        if (!listening)
            return;
        listening = false;
        win.removeEventListener("scroll", onViewportChange);
        win.removeEventListener("resize", onViewportChange);
        win.removeEventListener("pagehide", pageHide);
        win.removeEventListener("pageshow", pageShow);
        doc.removeEventListener("visibilitychange", onViewportChange);
    };
    return {
        observe(element, onState) {
            cards.set(element, { onState, mounted: false, active: false });
            start();
            if (observer)
                observer.observe(element);
            schedule();
            return () => {
                observer?.unobserve(element);
                cards.delete(element);
                if (cards.size)
                    schedule();
                else
                    stop();
            };
        }
    };
}
let templatePreviewScheduler = null;
function observeTemplatePreview(element, onActive) {
    if (!templatePreviewScheduler)
        templatePreviewScheduler = createTemplatePreviewScheduler();
    return templatePreviewScheduler.observe(element, onActive);
}
const TPHONE_CONFIG = {
    "pocketful-of-sorry": { ink: "#fff0f5", accent: "#87533d" },
    "the-us-archive": { ink: "#f5f0dd", accent: "#3044a0" },
    "patjhad": { ink: "#efe0bd", accent: "#a25227" },
    "amethyst": { ink: "#f5eef9", accent: "#795595" },
    "neelangan": { ink: "#F8F0DF", accent: "#234D79" },
    "sargam": { ink: "#392721", accent: "#782e40" },
    "haveli-dusk": { ink: "#f8efde", accent: "#e0b661" },
    "royal-pichwai": {
        ink: "#fff4dc",
        accent: "#f4c470",
    },
    "moonlit-mehfil": {
        ink: "#f9eedb",
        accent: "#e0b661",
    },
    "vivaha": {
        ink: "#f5f0df",
        accent: "#dedbc8",
    },
    "dear-you": {
        ink: "#f8efde",
        accent: "#f4c470",
    },
};
function templateCardPreviewSrc(template, previewMode = "demo", staticPreview = false) {
    const src = (previewMode === "builder" ? template?.builderTemplatePath : template?.demoPath) || "";
    if (!src)
        return "";
    const sep = src.includes("?") ? "&" : "?";
    const previewPath = (window.EA_APP?.path ? window.EA_APP.path(src) : src) + sep + "demo=1&silentPreview=1&livePreview=1&" + (staticPreview ? "staticPreview=1&" : "");
    if (template && template.id === "royal-pichwai") {
        return previewPath + "cardPreview=1&heroPreview=1&sharpPreview=1&previewV=royal-card-hero-fit-20260522-3";
    }
    return previewPath + "cardPreview=1&skipIntro=1&sharpPreview=1";
}
function sharpenCardPreview(event) {
    const iframe = event.currentTarget;
    try {
        const doc = iframe.contentDocument;
        if (!doc || !doc.head || doc.getElementById("everafter-card-preview-sharp"))
            return;
        doc.documentElement.classList.add("everafter-card-preview-sharp");
        const style = doc.createElement("style");
        style.id = "everafter-card-preview-sharp";
        style.textContent = `
      html,
      body {
        -webkit-font-smoothing: antialiased !important;
        -moz-osx-font-smoothing: grayscale !important;
        text-rendering: geometricPrecision !important;
      }
      .grain,
      .film-grain,
      .screen-grain,
      .vho-grain {
        opacity: .035 !important;
      }
    `;
        doc.head.appendChild(style);
    }
    catch (_) { }
}
function TemplateShowcasePhone({ template, onOpenDemo, previewMode = "demo", paused = false, onReadyChange }) {
    const cfg = TPHONE_CONFIG[template.id] || {};
    const [staticPreview, setStaticPreview] = React.useState(() => Boolean(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches || window.navigator?.connection?.saveData));
    const previewSrc = templateCardPreviewSrc(template, previewMode, staticPreview);
    const canOpenDemo = typeof onOpenDemo === "function";
    const phoneRef = React.useRef(null);
    const iframeRef = React.useRef(null);
    const [{ mounted, active }, setPreviewState] = React.useState({ mounted: false, active: false });
    const [loaded, setLoaded] = React.useState(false);
    const previewActive = active && !paused;
    React.useEffect(() => {
        onReadyChange?.(template.id, loaded);
        return () => onReadyChange?.(template.id, false);
    }, [template.id, loaded, onReadyChange]);
    React.useEffect(() => {
        const motion = window.matchMedia?.("(prefers-reduced-motion: reduce)");
        const connection = window.navigator?.connection;
        const update = () => setStaticPreview(Boolean(motion?.matches || connection?.saveData));
        motion?.addEventListener?.("change", update);
        connection?.addEventListener?.("change", update);
        return () => {
            motion?.removeEventListener?.("change", update);
            connection?.removeEventListener?.("change", update);
        };
    }, []);
    React.useEffect(() => {
        setPreviewState({ mounted: false, active: false });
        setLoaded(false);
        if (!previewSrc || !phoneRef.current)
            return;
        return observeTemplatePreview(phoneRef.current, (next) => {
            if (!next.mounted)
                setLoaded(false);
            setPreviewState(next);
        });
    }, [previewSrc]);
    const syncPlayback = React.useCallback(() => {
        try {
            iframeRef.current?.contentWindow?.EA_CARD_PREVIEW_LIFECYCLE?.setActive(previewActive);
        }
        catch (_) { }
    }, [previewActive]);
    React.useEffect(syncPlayback, [syncPlayback, loaded]);
    const openDemo = React.useCallback((event) => {
        if (!canOpenDemo)
            return;
        event.preventDefault();
        event.stopPropagation();
        onOpenDemo(template);
    }, [canOpenDemo, onOpenDemo, template]);
    return (React.createElement("div", { ref: phoneRef, "data-preview-state": previewActive ? "playing" : mounted ? "cached" : "unloaded", className: "tphone tphone--" + template.id + (canOpenDemo ? " tphone--clickable" : ""), style: { "--tph-ink": cfg.ink || "#f8efde", "--tph-accent": cfg.accent || "#f4c470" }, role: canOpenDemo ? "link" : undefined, tabIndex: canOpenDemo ? 0 : undefined, "aria-label": canOpenDemo ? `Open ${template.name} demo` : undefined, onClick: openDemo, onKeyDown: (event) => {
            if (!canOpenDemo)
                return;
            if (event.key === "Enter" || event.key === " ")
                openDemo(event);
        } },
        React.createElement("div", { className: "tphone-shadow", "aria-hidden": "true" }),
        React.createElement("div", { className: "tphone-bezel" },
            React.createElement("span", { className: "tphone-btn tphone-btn-mute", "aria-hidden": "true" }),
            React.createElement("span", { className: "tphone-btn tphone-btn-vup", "aria-hidden": "true" }),
            React.createElement("span", { className: "tphone-btn tphone-btn-vdown", "aria-hidden": "true" }),
            React.createElement("span", { className: "tphone-btn tphone-btn-power", "aria-hidden": "true" }),
            React.createElement("div", { className: "tphone-screen tphone-screen--live" },
                !loaded && React.createElement("div", { className: "tphone-preview-loading", "aria-hidden": "true" },
                    React.createElement("span", null, template.name),
                    React.createElement("small", null, "Loading preview\u2026")),
                mounted && previewSrc && (React.createElement("iframe", { ref: iframeRef, className: "tphone-live-frame", "data-preview-active": previewActive ? "1" : "0", src: previewSrc, title: `${template.name} first page preview`, loading: "eager", scrolling: "no", tabIndex: -1, sandbox: "allow-scripts allow-same-origin", allow: "autoplay 'none'", onLoad: (event) => { sharpenCardPreview(event); setLoaded(true); syncPlayback(); }, "aria-hidden": "true" }))))));
}
Object.assign(window, { TemplateShowcasePhone, observeTemplatePreview });
