@playruo/embed 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +1106 -336
  2. package/dist/index.js +1106 -336
  3. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -82,7 +82,6 @@ var PlayruoEmbed = ({
82
82
  const internalIframeRef = (0, import_react.useRef)(null);
83
83
  const iframeRef = externalIframeRef || internalIframeRef;
84
84
  const wasEmbedFullscreenRef = (0, import_react.useRef)(false);
85
- const wasEmbedPointerLockedRef = (0, import_react.useRef)(false);
86
85
  const [isIframeLoaded, setIsIframeLoaded] = (0, import_react.useState)(false);
87
86
  const [hasPlayedOnce, setHasPlayedOnce] = (0, import_react.useState)(false);
88
87
  const [showGameIframe, setShowGameIframe] = (0, import_react.useState)(false);
@@ -164,55 +163,8 @@ var PlayruoEmbed = ({
164
163
  console.warn("[PlayruoEmbed] Failed to lock Escape key:", error);
165
164
  }
166
165
  }, [getKeyboardApi]);
167
- const getPointerLockElement = (0, import_react.useCallback)(() => {
168
- const doc = document;
169
- return doc.pointerLockElement || doc.mozPointerLockElement || doc.webkitPointerLockElement || null;
170
- }, []);
171
- const releasePointerLock = (0, import_react.useCallback)(() => {
172
- const doc = document;
173
- const exitPointerLock = doc.exitPointerLock?.bind(doc) || doc.mozExitPointerLock?.bind(doc) || doc.webkitExitPointerLock?.bind(doc);
174
- try {
175
- exitPointerLock?.();
176
- wasEmbedPointerLockedRef.current = false;
177
- } catch (error) {
178
- console.warn("[PlayruoEmbed] Failed to release pointer lock:", error);
179
- }
180
- }, []);
181
166
  const requestImmersiveMode = (0, import_react.useCallback)(
182
167
  async (iframe) => {
183
- const pointerTarget = iframe;
184
- if (pointerTarget.requestPointerLock) {
185
- try {
186
- const pointerLockResult = pointerTarget.requestPointerLock({ unadjustedMovement: true });
187
- if (pointerLockResult && typeof pointerLockResult.then === "function") {
188
- void pointerLockResult.then(() => {
189
- wasEmbedPointerLockedRef.current = true;
190
- console.log("[PlayruoEmbed] Pointer locked on iframe");
191
- }).catch(async (error) => {
192
- if (error instanceof DOMException && error.name === "NotSupportedError") {
193
- try {
194
- const fallbackResult = pointerTarget.requestPointerLock?.();
195
- if (fallbackResult && typeof fallbackResult.then === "function") {
196
- await fallbackResult;
197
- }
198
- wasEmbedPointerLockedRef.current = true;
199
- console.log("[PlayruoEmbed] Pointer locked on iframe without raw input");
200
- return;
201
- } catch (fallbackError) {
202
- console.warn("[PlayruoEmbed] Failed to lock pointer without raw input:", fallbackError);
203
- return;
204
- }
205
- }
206
- console.warn("[PlayruoEmbed] Failed to lock pointer:", error);
207
- });
208
- } else {
209
- wasEmbedPointerLockedRef.current = true;
210
- console.log("[PlayruoEmbed] Pointer lock requested on iframe");
211
- }
212
- } catch (error) {
213
- console.warn("[PlayruoEmbed] Failed to request pointer lock:", error);
214
- }
215
- }
216
168
  const fullscreenPromise = iframe.requestFullscreen();
217
169
  try {
218
170
  await fullscreenPromise;
@@ -220,11 +172,10 @@ var PlayruoEmbed = ({
220
172
  console.log("[PlayruoEmbed] Fullscreen granted");
221
173
  } catch (error) {
222
174
  releaseEscapeKeyLock();
223
- releasePointerLock();
224
175
  throw error;
225
176
  }
226
177
  },
227
- [releaseEscapeKeyLock, releasePointerLock]
178
+ [releaseEscapeKeyLock]
228
179
  );
229
180
  const handleTryNow = (0, import_react.useCallback)(async () => {
230
181
  if (!isCompatible) {
@@ -411,10 +362,6 @@ var PlayruoEmbed = ({
411
362
  releaseEscapeKeyLock();
412
363
  if (wasEmbedFullscreenRef.current) {
413
364
  wasEmbedFullscreenRef.current = false;
414
- const isEmbedPointerLocked = Boolean(iframe && getPointerLockElement() === iframe);
415
- if (wasEmbedPointerLockedRef.current || isEmbedPointerLocked) {
416
- releasePointerLock();
417
- }
418
365
  if (iframe) {
419
366
  try {
420
367
  iframe.contentWindow?.postMessage({
@@ -446,33 +393,12 @@ var PlayruoEmbed = ({
446
393
  document.removeEventListener("mozfullscreenchange", handleFullscreenChange);
447
394
  document.removeEventListener("MSFullscreenChange", handleFullscreenChange);
448
395
  };
449
- }, [storeUrl, onDemoCompleted, iframeRef, getPointerLockElement, lockEscapeKey, releaseEscapeKeyLock, releasePointerLock]);
450
- (0, import_react.useEffect)(() => {
451
- const handlePointerLockChange = () => {
452
- const iframe = iframeRef.current;
453
- wasEmbedPointerLockedRef.current = Boolean(iframe && getPointerLockElement() === iframe);
454
- };
455
- const handlePointerLockError = () => {
456
- wasEmbedPointerLockedRef.current = false;
457
- console.warn("[PlayruoEmbed] Pointer lock request was rejected");
458
- };
459
- document.addEventListener("pointerlockchange", handlePointerLockChange);
460
- document.addEventListener("pointerlockerror", handlePointerLockError);
461
- return () => {
462
- document.removeEventListener("pointerlockchange", handlePointerLockChange);
463
- document.removeEventListener("pointerlockerror", handlePointerLockError);
464
- };
465
- }, [getPointerLockElement, iframeRef]);
396
+ }, [storeUrl, onDemoCompleted, iframeRef, lockEscapeKey, releaseEscapeKeyLock]);
466
397
  (0, import_react.useEffect)(() => {
467
398
  return () => {
468
399
  releaseEscapeKeyLock();
469
- const iframe = iframeRef.current;
470
- const isEmbedPointerLocked = Boolean(iframe && getPointerLockElement() === iframe);
471
- if (wasEmbedPointerLockedRef.current || isEmbedPointerLocked) {
472
- releasePointerLock();
473
- }
474
400
  };
475
- }, [getPointerLockElement, iframeRef, releaseEscapeKeyLock, releasePointerLock]);
401
+ }, [releaseEscapeKeyLock]);
476
402
  (0, import_react.useEffect)(() => {
477
403
  const logCrossOriginStatus = () => {
478
404
  const isIsolated = self.crossOriginIsolated;
@@ -622,36 +548,61 @@ var PlayruoEmbed = ({
622
548
  // src/react/embed-tester.tsx
623
549
  var import_react2 = __toESM(require("react"), 1);
624
550
  var import_jsx_runtime2 = require("react/jsx-runtime");
551
+ var createInitialEmbedState = () => ({
552
+ buyNow: { available: false, status: "Not ready" },
553
+ hasPlayedOnce: false,
554
+ isReady: false,
555
+ tryNow: { available: false, status: "Not ready" }
556
+ });
557
+ var createInitialDiagnostics = () => ({
558
+ chromiumBrowser: false,
559
+ crossOriginIsolation: false,
560
+ desktopBrowser: false,
561
+ fullscreenSupported: false,
562
+ gamepadSupported: false,
563
+ iframeAllowsFullscreen: false,
564
+ iframeAllowsGamepad: false,
565
+ iframeAllowsPointerLock: false,
566
+ keyboardLockSupported: false,
567
+ localStorageSupported: false,
568
+ pointerLockSupported: false,
569
+ secureContext: false,
570
+ sharedArrayBufferSupported: false,
571
+ topLevelContext: false,
572
+ webAssemblySupported: false,
573
+ webgl2Supported: false
574
+ });
625
575
  var EmbedTester = (props = {}) => {
626
- const [operation, setOperation] = (0, import_react2.useState)(props.operation ?? "iframe");
627
- const [storeUrl, setStoreUrl] = (0, import_react2.useState)(
576
+ const [operationDraft, setOperationDraft] = (0, import_react2.useState)(props.operation ?? "iframe");
577
+ const [storeUrlDraft, setStoreUrlDraft] = (0, import_react2.useState)(
578
+ props.storeUrl ?? "https://store.steampowered.com/app/123456"
579
+ );
580
+ const [appliedOperation, setAppliedOperation] = (0, import_react2.useState)(props.operation ?? "iframe");
581
+ const [appliedStoreUrl, setAppliedStoreUrl] = (0, import_react2.useState)(
628
582
  props.storeUrl ?? "https://store.steampowered.com/app/123456"
629
583
  );
630
584
  const [key, setKey] = (0, import_react2.useState)(0);
631
585
  const [hasUserClicked, setHasUserClicked] = (0, import_react2.useState)(false);
632
586
  const [showIframe, setShowIframe] = (0, import_react2.useState)(false);
633
- const [embedState, setEmbedState] = (0, import_react2.useState)({
634
- buyNow: { available: false, status: "Not ready" },
635
- hasPlayedOnce: false,
636
- isReady: false,
637
- tryNow: { available: false, status: "Not ready" }
638
- });
587
+ const [embedState, setEmbedState] = (0, import_react2.useState)(createInitialEmbedState);
639
588
  const [eventLog, setEventLog] = (0, import_react2.useState)([]);
640
- const [diagnostics, setDiagnostics] = (0, import_react2.useState)({
641
- crossOriginIsolation: false,
642
- gamepadSupported: false,
643
- fullscreenSupported: false,
644
- keyboardLockSupported: false
645
- });
589
+ const [diagnostics, setDiagnostics] = (0, import_react2.useState)(createInitialDiagnostics);
646
590
  const displayHost = props.baseUrl ? new URL(props.baseUrl).host : "playruo.live";
647
591
  const enableConsoleLog = props.enableConsoleLog ?? false;
648
592
  const hasReadyBeenCalled = (0, import_react2.useRef)(false);
593
+ const nextEventIdRef = (0, import_react2.useRef)(0);
649
594
  const previousStateRef = (0, import_react2.useRef)("");
650
595
  const iframeRef = (0, import_react2.useRef)(null);
596
+ const isOperationPending = operationDraft !== appliedOperation;
597
+ const isStoreUrlPending = storeUrlDraft !== appliedStoreUrl;
598
+ const hasPendingConfigChanges = isOperationPending || isStoreUrlPending;
599
+ const pendingChangeCount = Number(isOperationPending) + Number(isStoreUrlPending);
651
600
  const addEvent = (0, import_react2.useCallback)(
652
601
  (message) => {
653
602
  const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString();
654
- setEventLog((prev) => [...prev.slice(-10), { message, timestamp }]);
603
+ const id = nextEventIdRef.current;
604
+ nextEventIdRef.current += 1;
605
+ setEventLog((prev) => [...prev.slice(-10), { id, message, timestamp }]);
655
606
  if (enableConsoleLog) {
656
607
  console.log(`[EmbedTester] ${timestamp}: ${message}`);
657
608
  }
@@ -659,18 +610,48 @@ var EmbedTester = (props = {}) => {
659
610
  [enableConsoleLog]
660
611
  );
661
612
  const runDiagnostics = (0, import_react2.useCallback)(() => {
613
+ const userAgent = navigator.userAgent || navigator.vendor || window.opera || "";
614
+ const isMobileDevice = /android|iPad|iPhone|iPod/i.test(userAgent);
615
+ const hasChrome = !!window.chrome;
616
+ const isChromium = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
617
+ const iframeAllow = iframeRef.current?.getAttribute("allow") ?? "";
618
+ const iframeSandbox = iframeRef.current?.getAttribute("sandbox") ?? "";
619
+ const canvas = document.createElement("canvas");
620
+ let localStorageSupported = false;
621
+ try {
622
+ const storageKey = "__playruo_embed_tester__";
623
+ window.localStorage.setItem(storageKey, "1");
624
+ window.localStorage.removeItem(storageKey);
625
+ localStorageSupported = true;
626
+ } catch {
627
+ localStorageSupported = false;
628
+ }
662
629
  const newDiagnostics = {
630
+ chromiumBrowser: hasChrome || isChromium,
663
631
  crossOriginIsolation: !!(window.crossOriginIsolated || window.crossOriginIsolated),
664
- gamepadSupported: "getGamepads" in navigator,
632
+ desktopBrowser: !isMobileDevice,
665
633
  fullscreenSupported: !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled),
666
- keyboardLockSupported: "keyboard" in navigator && "lock" in navigator.keyboard
634
+ gamepadSupported: "getGamepads" in navigator,
635
+ iframeAllowsFullscreen: iframeAllow.includes("fullscreen"),
636
+ iframeAllowsGamepad: iframeAllow.includes("gamepad"),
637
+ iframeAllowsPointerLock: iframeSandbox.includes("allow-pointer-lock"),
638
+ keyboardLockSupported: "keyboard" in navigator && "lock" in navigator.keyboard,
639
+ localStorageSupported,
640
+ pointerLockSupported: "requestPointerLock" in HTMLIFrameElement.prototype || "requestPointerLock" in HTMLElement.prototype || "pointerLockElement" in document,
641
+ secureContext: window.isSecureContext,
642
+ sharedArrayBufferSupported: typeof SharedArrayBuffer !== "undefined",
643
+ topLevelContext: window.self === window.top,
644
+ webAssemblySupported: typeof WebAssembly !== "undefined",
645
+ webgl2Supported: !!canvas.getContext("webgl2")
667
646
  };
668
647
  setDiagnostics(newDiagnostics);
669
- addEvent(`\u{1F50D} Diagnostics updated - COI: ${newDiagnostics.crossOriginIsolation}, Gamepad: ${newDiagnostics.gamepadSupported}`);
670
- }, [addEvent]);
648
+ addEvent(
649
+ `\u{1F50D} Diagnostics updated - Browser: ${newDiagnostics.desktopBrowser && newDiagnostics.chromiumBrowser}, COI: ${newDiagnostics.crossOriginIsolation}, Fullscreen: ${newDiagnostics.fullscreenSupported}`
650
+ );
651
+ }, [addEvent, iframeRef]);
671
652
  import_react2.default.useEffect(() => {
672
653
  runDiagnostics();
673
- }, [runDiagnostics]);
654
+ }, [key, runDiagnostics]);
674
655
  const handleReady = (0, import_react2.useCallback)(() => {
675
656
  if (!hasReadyBeenCalled.current) {
676
657
  hasReadyBeenCalled.current = true;
@@ -704,279 +685,1068 @@ var EmbedTester = (props = {}) => {
704
685
  addEvent(`Opening store: ${data.storeUrl}`);
705
686
  window.open(data.storeUrl, "_blank");
706
687
  }, [addEvent]);
707
- const handleRestart = (0, import_react2.useCallback)(() => {
688
+ const resetEmbedSession = (0, import_react2.useCallback)((message) => {
689
+ setEmbedState(createInitialEmbedState());
708
690
  setKey((prev) => prev + 1);
709
691
  setHasUserClicked(false);
710
692
  setShowIframe(false);
711
693
  hasReadyBeenCalled.current = false;
712
694
  previousStateRef.current = "";
713
- addEvent("Embed restarted");
695
+ addEvent(message);
714
696
  }, [addEvent]);
715
- const buttonStyle = {
716
- padding: "8px 16px",
717
- margin: "4px",
718
- border: "1px solid #404040",
719
- borderRadius: "4px",
720
- backgroundColor: "#2a2a2a",
721
- color: "#e5e5e5",
722
- cursor: "pointer",
723
- fontSize: "14px",
724
- transition: "all 0.2s ease"
697
+ const handleApply = (0, import_react2.useCallback)(() => {
698
+ if (!hasPendingConfigChanges) {
699
+ return;
700
+ }
701
+ setAppliedOperation(operationDraft);
702
+ setAppliedStoreUrl(storeUrlDraft);
703
+ resetEmbedSession("Applied updated embed settings");
704
+ }, [hasPendingConfigChanges, operationDraft, resetEmbedSession, storeUrlDraft]);
705
+ const handleRestartSession = (0, import_react2.useCallback)(() => {
706
+ resetEmbedSession("Embed restarted with applied settings");
707
+ }, [resetEmbedSession]);
708
+ const handleResetDrafts = (0, import_react2.useCallback)(() => {
709
+ setOperationDraft(appliedOperation);
710
+ setStoreUrlDraft(appliedStoreUrl);
711
+ addEvent("Reverted draft changes to the applied configuration");
712
+ }, [addEvent, appliedOperation, appliedStoreUrl]);
713
+ const panelStyle = {
714
+ position: "relative",
715
+ border: "1px solid rgba(148, 163, 184, 0.18)",
716
+ borderRadius: "24px",
717
+ padding: "20px",
718
+ background: "linear-gradient(180deg, rgba(15, 23, 42, 0.88) 0%, rgba(7, 12, 24, 0.96) 100%)",
719
+ boxShadow: "0 24px 80px rgba(0, 0, 0, 0.35)",
720
+ backdropFilter: "blur(18px)"
721
+ };
722
+ const sectionTitleStyle = {
723
+ margin: 0,
724
+ fontSize: "18px",
725
+ fontWeight: 600,
726
+ color: "#f8fafc"
727
+ };
728
+ const labelStyle = {
729
+ display: "flex",
730
+ alignItems: "center",
731
+ justifyContent: "space-between",
732
+ gap: "12px",
733
+ marginBottom: "8px",
734
+ fontSize: "13px",
735
+ fontWeight: 600,
736
+ color: "#dbe7ff"
725
737
  };
738
+ const buildIndicatorStyle = (pending) => ({
739
+ display: "inline-flex",
740
+ alignItems: "center",
741
+ gap: "8px",
742
+ padding: "4px 10px",
743
+ borderRadius: "999px",
744
+ border: pending ? "1px solid rgba(251, 191, 36, 0.28)" : "1px solid rgba(74, 222, 128, 0.22)",
745
+ backgroundColor: pending ? "rgba(245, 158, 11, 0.12)" : "rgba(34, 197, 94, 0.12)",
746
+ color: pending ? "#fbbf24" : "#86efac",
747
+ fontSize: "11px",
748
+ fontWeight: 700,
749
+ letterSpacing: "0.08em",
750
+ textTransform: "uppercase"
751
+ });
752
+ const buildIndicatorDotStyle = (pending) => ({
753
+ width: "8px",
754
+ height: "8px",
755
+ borderRadius: "999px",
756
+ backgroundColor: pending ? "#f59e0b" : "#22c55e",
757
+ boxShadow: pending ? "0 0 0 4px rgba(245, 158, 11, 0.12)" : "0 0 0 4px rgba(34, 197, 94, 0.12)"
758
+ });
759
+ const buildInputShellStyle = (pending) => ({
760
+ display: "flex",
761
+ alignItems: "center",
762
+ gap: "12px",
763
+ border: pending ? "1px solid rgba(245, 158, 11, 0.35)" : "1px solid rgba(148, 163, 184, 0.18)",
764
+ borderRadius: "16px",
765
+ padding: "0 14px",
766
+ background: pending ? "rgba(35, 23, 8, 0.72)" : "rgba(15, 23, 42, 0.7)",
767
+ boxShadow: pending ? "0 0 0 1px rgba(245, 158, 11, 0.08)" : "none"
768
+ });
726
769
  const inputStyle = {
727
770
  width: "100%",
728
- padding: "8px",
729
- margin: "4px 0",
730
- border: "1px solid #404040",
731
- borderRadius: "4px",
732
- backgroundColor: "#1a1a1a",
733
- color: "#e5e5e5",
734
- fontSize: "14px"
771
+ padding: "14px 0",
772
+ border: "none",
773
+ outline: "none",
774
+ backgroundColor: "transparent",
775
+ color: "#f8fafc",
776
+ fontSize: "15px"
735
777
  };
736
- const cardStyle = {
737
- border: "1px solid #333333",
738
- borderRadius: "8px",
739
- padding: "16px",
740
- margin: "8px 0",
741
- backgroundColor: "#1a1a1a"
778
+ const helperTextStyle = {
779
+ margin: "8px 0 0 0",
780
+ color: "#94a3b8",
781
+ fontSize: "12px",
782
+ lineHeight: 1.5
742
783
  };
743
- const statusStyle = {
784
+ const codeStyle = {
744
785
  display: "inline-block",
745
- padding: "4px 8px",
746
- margin: "2px",
747
- borderRadius: "12px",
786
+ padding: "2px 8px",
787
+ borderRadius: "999px",
788
+ backgroundColor: "rgba(148, 163, 184, 0.12)",
789
+ color: "#e2e8f0",
748
790
  fontSize: "12px",
749
- fontWeight: "500"
791
+ fontFamily: '"SF Mono", "Roboto Mono", monospace',
792
+ wordBreak: "break-all"
750
793
  };
751
- const successStatus = { ...statusStyle, backgroundColor: "#0d5d1f", color: "#4ade80" };
752
- const errorStatus = { ...statusStyle, backgroundColor: "#5d1a1a", color: "#f87171" };
753
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: props.className, style: { minHeight: "100vh", padding: "20px", backgroundColor: "#000000", color: "#e5e5e5" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { maxWidth: "1200px", margin: "0 auto" }, children: [
754
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { style: { marginBottom: "20px", fontSize: "24px", fontWeight: "bold", color: "#ffffff" }, children: "\u{1F9EA} Playruo Embed Tester" }),
755
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "20px" }, children: [
756
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
757
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: cardStyle, children: [
758
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: { margin: "0 0 16px 0", fontSize: "18px", fontWeight: "600", color: "#ffffff" }, children: "Test Controls" }),
759
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: "12px" }, children: [
760
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { htmlFor: "operation", style: { display: "block", marginBottom: "4px", fontWeight: "500", color: "#d4d4d4" }, children: "Operation" }),
761
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
762
- "input",
763
- {
764
- style: inputStyle,
765
- onChange: (e) => setOperation(e.target.value),
766
- placeholder: "e.g., iframe",
767
- value: operation
768
- }
769
- )
770
- ] }),
771
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: "12px" }, children: [
772
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { htmlFor: "storeUrl", style: { display: "block", marginBottom: "4px", fontWeight: "500", color: "#d4d4d4" }, children: "Store URL" }),
773
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
774
- "input",
775
- {
776
- style: inputStyle,
777
- onChange: (e) => setStoreUrl(e.target.value),
778
- placeholder: "https://store.example.com",
779
- value: storeUrl
780
- }
781
- )
782
- ] }),
794
+ const buildButtonStyle = (variant, disabled = false) => {
795
+ const palette = {
796
+ ghost: {
797
+ background: "rgba(15, 23, 42, 0.5)",
798
+ border: "1px solid rgba(148, 163, 184, 0.18)",
799
+ color: "#dbe7ff"
800
+ },
801
+ primary: {
802
+ background: "linear-gradient(135deg, #38bdf8 0%, #2563eb 100%)",
803
+ border: "1px solid rgba(125, 211, 252, 0.32)",
804
+ color: "#eff6ff"
805
+ },
806
+ secondary: {
807
+ background: "linear-gradient(135deg, rgba(30, 41, 59, 0.92) 0%, rgba(15, 23, 42, 0.98) 100%)",
808
+ border: "1px solid rgba(148, 163, 184, 0.18)",
809
+ color: "#e2e8f0"
810
+ }
811
+ }[variant];
812
+ return {
813
+ display: "inline-flex",
814
+ alignItems: "center",
815
+ justifyContent: "center",
816
+ gap: "10px",
817
+ minHeight: "44px",
818
+ padding: "0 18px",
819
+ borderRadius: "14px",
820
+ background: palette.background,
821
+ border: palette.border,
822
+ color: palette.color,
823
+ cursor: disabled ? "not-allowed" : "pointer",
824
+ opacity: disabled ? 0.45 : 1,
825
+ fontSize: "14px",
826
+ fontWeight: 700,
827
+ letterSpacing: "0.01em",
828
+ transition: "all 0.2s ease",
829
+ boxShadow: variant === "primary" && !disabled ? "0 16px 32px rgba(37, 99, 235, 0.28)" : "none"
830
+ };
831
+ };
832
+ const buildStatusChipStyle = (active) => ({
833
+ display: "inline-flex",
834
+ alignItems: "center",
835
+ gap: "8px",
836
+ padding: "8px 12px",
837
+ borderRadius: "999px",
838
+ backgroundColor: active ? "rgba(34, 197, 94, 0.12)" : "rgba(248, 113, 113, 0.12)",
839
+ border: active ? "1px solid rgba(34, 197, 94, 0.22)" : "1px solid rgba(248, 113, 113, 0.22)",
840
+ color: active ? "#86efac" : "#fca5a5",
841
+ fontSize: "12px",
842
+ fontWeight: 700
843
+ });
844
+ const statusItems = [
845
+ { label: "Ready", value: Boolean(embedState.isReady) },
846
+ { label: "Played", value: Boolean(embedState.hasPlayedOnce) },
847
+ { label: "Try Now", value: Boolean(embedState.tryNow?.available) },
848
+ { label: "Buy Now", value: Boolean(embedState.buyNow?.available) }
849
+ ];
850
+ const diagnosticGroups = [
851
+ {
852
+ title: "Compatibility",
853
+ items: [
854
+ {
855
+ detail: "Playruo currently expects a non-mobile browser.",
856
+ label: "Desktop browser",
857
+ value: diagnostics.desktopBrowser
858
+ },
859
+ {
860
+ detail: "The embed flow is tuned for Chromium-based browsers.",
861
+ label: "Chromium browser",
862
+ value: diagnostics.chromiumBrowser
863
+ },
864
+ {
865
+ detail: "Keyboard lock works best when the page is not itself embedded.",
866
+ label: "Top-level tab",
867
+ value: diagnostics.topLevelContext
868
+ },
869
+ {
870
+ detail: "HTTPS or localhost unlocks the best browser APIs.",
871
+ label: "Secure context",
872
+ value: diagnostics.secureContext
873
+ }
874
+ ]
875
+ },
876
+ {
877
+ title: "Gameplay APIs",
878
+ items: [
879
+ {
880
+ detail: "Needed for the immersive play flow.",
881
+ label: "Fullscreen API",
882
+ value: diagnostics.fullscreenSupported
883
+ },
884
+ {
885
+ detail: "Needed for raw mouse capture on the iframe.",
886
+ label: "Pointer lock",
887
+ value: diagnostics.pointerLockSupported
888
+ },
889
+ {
890
+ detail: "Used to keep Escape reserved while fullscreen is active.",
891
+ label: "Keyboard lock",
892
+ value: diagnostics.keyboardLockSupported
893
+ },
894
+ {
895
+ detail: "Lets the game read connected controllers.",
896
+ label: "Gamepad API",
897
+ value: diagnostics.gamepadSupported
898
+ }
899
+ ]
900
+ },
901
+ {
902
+ title: "Performance",
903
+ items: [
904
+ {
905
+ detail: "Improves the overall runtime budget for the experience.",
906
+ label: "Cross-origin isolated",
907
+ value: diagnostics.crossOriginIsolation
908
+ },
909
+ {
910
+ detail: "Important for heavier threaded workloads.",
911
+ label: "SharedArrayBuffer",
912
+ value: diagnostics.sharedArrayBufferSupported
913
+ },
914
+ {
915
+ detail: "Confirms modern rendering features are reachable.",
916
+ label: "WebGL2",
917
+ value: diagnostics.webgl2Supported
918
+ },
919
+ {
920
+ detail: "Confirms the runtime can execute compiled game code paths.",
921
+ label: "WebAssembly",
922
+ value: diagnostics.webAssemblySupported
923
+ }
924
+ ]
925
+ },
926
+ {
927
+ title: "Embed wiring",
928
+ items: [
929
+ {
930
+ detail: "The iframe allow list includes fullscreen access.",
931
+ label: "Iframe fullscreen allow",
932
+ value: diagnostics.iframeAllowsFullscreen
933
+ },
934
+ {
935
+ detail: "The iframe allow list includes gamepad access.",
936
+ label: "Iframe gamepad allow",
937
+ value: diagnostics.iframeAllowsGamepad
938
+ },
939
+ {
940
+ detail: "The iframe sandbox includes pointer-lock permission.",
941
+ label: "Iframe pointer-lock allow",
942
+ value: diagnostics.iframeAllowsPointerLock
943
+ },
944
+ {
945
+ detail: "Needed for UUID persistence and session continuity.",
946
+ label: "Local storage",
947
+ value: diagnostics.localStorageSupported
948
+ }
949
+ ]
950
+ }
951
+ ];
952
+ const criticalDiagnosticChecks = [
953
+ { label: "Desktop browser", value: diagnostics.desktopBrowser },
954
+ { label: "Chromium browser", value: diagnostics.chromiumBrowser },
955
+ { label: "Fullscreen API", value: diagnostics.fullscreenSupported },
956
+ { label: "Pointer lock", value: diagnostics.pointerLockSupported }
957
+ ];
958
+ const warningDiagnosticChecks = [
959
+ { label: "Top-level tab", value: diagnostics.topLevelContext },
960
+ { label: "Secure context", value: diagnostics.secureContext },
961
+ { label: "Cross-origin isolation", value: diagnostics.crossOriginIsolation },
962
+ { label: "SharedArrayBuffer", value: diagnostics.sharedArrayBufferSupported },
963
+ { label: "Keyboard lock", value: diagnostics.keyboardLockSupported },
964
+ { label: "Gamepad API", value: diagnostics.gamepadSupported },
965
+ { label: "WebGL2", value: diagnostics.webgl2Supported }
966
+ ];
967
+ const blockingDiagnostics = criticalDiagnosticChecks.filter((item) => !item.value);
968
+ const advisoryDiagnostics = warningDiagnosticChecks.filter((item) => !item.value);
969
+ const diagnosticsVerdict = blockingDiagnostics.length > 0 ? {
970
+ label: "Blocked",
971
+ tone: "#fca5a5",
972
+ background: "rgba(127, 29, 29, 0.28)",
973
+ border: "1px solid rgba(248, 113, 113, 0.24)",
974
+ text: "A core requirement is missing for the intended embed flow."
975
+ } : advisoryDiagnostics.length > 0 ? {
976
+ label: "Limited",
977
+ tone: "#fde68a",
978
+ background: "rgba(120, 53, 15, 0.24)",
979
+ border: "1px solid rgba(245, 158, 11, 0.22)",
980
+ text: "The embed should run, but some features or performance may be reduced."
981
+ } : {
982
+ label: "Ready",
983
+ tone: "#86efac",
984
+ background: "rgba(20, 83, 45, 0.24)",
985
+ border: "1px solid rgba(34, 197, 94, 0.22)",
986
+ text: "All key browser, performance, and iframe capabilities are present."
987
+ };
988
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
989
+ "div",
990
+ {
991
+ className: props.className,
992
+ style: {
993
+ position: "relative",
994
+ minHeight: "100vh",
995
+ overflow: "hidden",
996
+ padding: "32px 20px 48px",
997
+ background: "radial-gradient(circle at top left, rgba(56, 189, 248, 0.18) 0%, rgba(2, 6, 23, 0) 34%), radial-gradient(circle at 85% 10%, rgba(37, 99, 235, 0.18) 0%, rgba(2, 6, 23, 0) 26%), linear-gradient(180deg, #020617 0%, #050816 48%, #020617 100%)",
998
+ color: "#e5e7eb"
999
+ },
1000
+ children: [
1001
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1002
+ "div",
1003
+ {
1004
+ style: {
1005
+ position: "absolute",
1006
+ inset: 0,
1007
+ overflow: "hidden",
1008
+ pointerEvents: "none"
1009
+ },
1010
+ children: [
1011
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1012
+ "div",
1013
+ {
1014
+ style: {
1015
+ position: "absolute",
1016
+ top: "-120px",
1017
+ left: "-120px",
1018
+ width: "320px",
1019
+ height: "320px",
1020
+ borderRadius: "999px",
1021
+ background: "rgba(56, 189, 248, 0.12)",
1022
+ filter: "blur(60px)"
1023
+ }
1024
+ }
1025
+ ),
1026
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1027
+ "div",
1028
+ {
1029
+ style: {
1030
+ position: "absolute",
1031
+ right: "-80px",
1032
+ top: "120px",
1033
+ width: "280px",
1034
+ height: "280px",
1035
+ borderRadius: "999px",
1036
+ background: "rgba(37, 99, 235, 0.12)",
1037
+ filter: "blur(60px)"
1038
+ }
1039
+ }
1040
+ )
1041
+ ]
1042
+ }
1043
+ ),
1044
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", maxWidth: "1280px", margin: "0 auto" }, children: [
783
1045
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
784
- "button",
1046
+ "div",
785
1047
  {
786
- type: "button",
787
1048
  style: {
788
- ...buttonStyle,
789
- backgroundColor: "#0066cc",
790
- color: "#ffffff",
791
- border: "none",
792
- fontWeight: "600"
1049
+ ...panelStyle,
1050
+ marginBottom: "24px",
1051
+ padding: "28px",
1052
+ background: "linear-gradient(135deg, rgba(15, 23, 42, 0.92) 0%, rgba(8, 15, 30, 0.98) 55%, rgba(15, 23, 42, 0.92) 100%)"
793
1053
  },
794
- onClick: handleRestart,
795
- onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "#0052a3",
796
- onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "#0066cc",
797
- children: "\u{1F504} Restart Embed"
1054
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1055
+ "div",
1056
+ {
1057
+ style: {
1058
+ display: "flex",
1059
+ flexWrap: "wrap",
1060
+ gap: "20px",
1061
+ justifyContent: "space-between",
1062
+ alignItems: "flex-start"
1063
+ },
1064
+ children: [
1065
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { maxWidth: "720px" }, children: [
1066
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1067
+ "div",
1068
+ {
1069
+ style: {
1070
+ display: "inline-flex",
1071
+ alignItems: "center",
1072
+ gap: "10px",
1073
+ padding: "6px 12px",
1074
+ borderRadius: "999px",
1075
+ backgroundColor: "rgba(56, 189, 248, 0.12)",
1076
+ border: "1px solid rgba(125, 211, 252, 0.18)",
1077
+ color: "#7dd3fc",
1078
+ fontSize: "11px",
1079
+ fontWeight: 700,
1080
+ letterSpacing: "0.12em",
1081
+ textTransform: "uppercase"
1082
+ },
1083
+ children: "\u{1F9EA} Playruo QA Surface"
1084
+ }
1085
+ ),
1086
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1087
+ "h1",
1088
+ {
1089
+ style: {
1090
+ margin: "16px 0 12px 0",
1091
+ fontSize: "clamp(32px, 4vw, 46px)",
1092
+ lineHeight: 1.05,
1093
+ letterSpacing: "-0.04em",
1094
+ color: "#f8fafc"
1095
+ },
1096
+ children: "Embed Tester"
1097
+ }
1098
+ ),
1099
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1100
+ "p",
1101
+ {
1102
+ style: {
1103
+ margin: 0,
1104
+ maxWidth: "640px",
1105
+ color: "#94a3b8",
1106
+ fontSize: "16px",
1107
+ lineHeight: 1.7
1108
+ },
1109
+ children: "Edit configuration safely, apply changes only when you decide to, and keep runtime feedback visible without the UI fighting your typing."
1110
+ }
1111
+ )
1112
+ ] }),
1113
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1114
+ "div",
1115
+ {
1116
+ style: {
1117
+ display: "grid",
1118
+ gap: "12px",
1119
+ gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))",
1120
+ flex: "1 1 320px"
1121
+ },
1122
+ children: [
1123
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1124
+ "div",
1125
+ {
1126
+ style: {
1127
+ padding: "16px",
1128
+ borderRadius: "18px",
1129
+ backgroundColor: "rgba(15, 23, 42, 0.72)",
1130
+ border: "1px solid rgba(148, 163, 184, 0.14)"
1131
+ },
1132
+ children: [
1133
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: "12px", color: "#94a3b8", marginBottom: "8px" }, children: "Active host" }),
1134
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#f8fafc", fontSize: "16px", fontWeight: 700 }, children: displayHost })
1135
+ ]
1136
+ }
1137
+ ),
1138
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1139
+ "div",
1140
+ {
1141
+ style: {
1142
+ padding: "16px",
1143
+ borderRadius: "18px",
1144
+ backgroundColor: hasPendingConfigChanges ? "rgba(35, 23, 8, 0.72)" : "rgba(15, 23, 42, 0.72)",
1145
+ border: hasPendingConfigChanges ? "1px solid rgba(245, 158, 11, 0.24)" : "1px solid rgba(148, 163, 184, 0.14)"
1146
+ },
1147
+ children: [
1148
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: "12px", color: "#94a3b8", marginBottom: "8px" }, children: "Config state" }),
1149
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1150
+ "div",
1151
+ {
1152
+ style: {
1153
+ display: "flex",
1154
+ alignItems: "center",
1155
+ gap: "10px",
1156
+ color: hasPendingConfigChanges ? "#fbbf24" : "#86efac",
1157
+ fontSize: "16px",
1158
+ fontWeight: 700
1159
+ },
1160
+ children: [
1161
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: buildIndicatorDotStyle(hasPendingConfigChanges) }),
1162
+ hasPendingConfigChanges ? `${pendingChangeCount} pending change(s)` : "Everything applied"
1163
+ ]
1164
+ }
1165
+ )
1166
+ ]
1167
+ }
1168
+ )
1169
+ ]
1170
+ }
1171
+ )
1172
+ ]
1173
+ }
1174
+ )
798
1175
  }
799
- )
800
- ] }),
801
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: cardStyle, children: [
802
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: { margin: "0 0 16px 0", fontSize: "18px", fontWeight: "600", color: "#ffffff" }, children: "Status" }),
803
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
804
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: embedState.isReady ? successStatus : errorStatus, children: embedState.isReady ? "\u2705 Ready" : "\u274C Not Ready" }),
805
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: embedState.hasPlayedOnce ? successStatus : errorStatus, children: embedState.hasPlayedOnce ? "\u2705 Played" : "\u274C Not Played" }),
806
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: embedState.tryNow?.available ? successStatus : errorStatus, children: embedState.tryNow?.available ? "\u2705 Try Now" : "\u274C Try Now" }),
807
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: embedState.buyNow?.available ? successStatus : errorStatus, children: embedState.buyNow?.available ? "\u2705 Buy Now" : "\u274C Buy Now" })
808
- ] }),
809
- !embedState.tryNow?.available && embedState.tryNow?.status && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: { margin: "8px 0 0 0", fontSize: "12px", color: "#a3a3a3" }, children: [
810
- "Try Now reason: ",
811
- embedState.tryNow.status
812
- ] })
813
- ] }),
814
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: cardStyle, children: [
815
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: { margin: "0 0 16px 0", fontSize: "18px", fontWeight: "600", color: "#ffffff" }, children: "\u{1F50D} Browser Diagnostics" }),
816
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
817
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
818
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: diagnostics.crossOriginIsolation ? successStatus : errorStatus, children: diagnostics.crossOriginIsolation ? "\u2705" : "\u274C" }),
819
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "12px", color: "#d4d4d4" }, children: "Cross-Origin Isolation" })
820
- ] }),
821
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
822
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: diagnostics.gamepadSupported ? successStatus : errorStatus, children: diagnostics.gamepadSupported ? "\u2705" : "\u274C" }),
823
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "12px", color: "#d4d4d4" }, children: "Gamepad API" })
824
- ] }),
825
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
826
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: diagnostics.fullscreenSupported ? successStatus : errorStatus, children: diagnostics.fullscreenSupported ? "\u2705" : "\u274C" }),
827
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "12px", color: "#d4d4d4" }, children: "Fullscreen API" })
828
- ] }),
829
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
830
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: diagnostics.keyboardLockSupported ? successStatus : errorStatus, children: diagnostics.keyboardLockSupported ? "\u2705" : "\u274C" }),
831
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "12px", color: "#d4d4d4" }, children: "Keyboard Lock" })
832
- ] })
833
- ] })
834
- ] }),
835
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: cardStyle, children: [
836
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: { margin: "0 0 16px 0", fontSize: "18px", fontWeight: "600", color: "#ffffff" }, children: "Event Log" }),
837
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
838
- backgroundColor: "#0a0a0a",
839
- padding: "12px",
840
- borderRadius: "4px",
841
- minHeight: "200px",
842
- height: "min(50vh, 480px)",
843
- overflowY: "auto",
844
- fontFamily: "monospace",
845
- fontSize: "12px",
846
- border: "1px solid #333333"
847
- }, children: eventLog.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: eventLog.map((event) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: "4px" }, children: [
848
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: "#737373" }, children: [
849
- "[",
850
- event.timestamp,
851
- "]"
852
- ] }),
853
- " ",
854
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#e5e5e5" }, children: event.message })
855
- ] }, event.timestamp)) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#737373" }, children: "No events yet..." }) })
856
- ] })
857
- ] }),
858
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: cardStyle, children: [
859
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "16px" }, children: [
860
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: { margin: "0", fontSize: "18px", fontWeight: "600", color: "#ffffff" }, children: "Embed Container" }),
861
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: {
862
- backgroundColor: "#2a2a2a",
863
- color: "#e5e5e5",
864
- padding: "4px 8px",
865
- borderRadius: "12px",
866
- fontSize: "12px",
867
- fontWeight: "500",
868
- border: "1px solid #404040"
869
- }, children: [
870
- "\u{1F9EA} ",
871
- displayHost
872
- ] })
873
- ] }),
874
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
875
- position: "relative",
876
- minHeight: "500px",
877
- overflow: "hidden",
878
- borderRadius: "8px",
879
- border: "1px solid #333333",
880
- backgroundColor: "#0a0a0a"
881
- }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
882
- PlayruoEmbed,
883
- {
884
- baseUrl: props.baseUrl,
885
- className: "w-full h-full absolute inset-0",
886
- iframeRef,
887
- onDemoCompleted: handleDemoCompleted,
888
- onError: handleError,
889
- onPurchaseRequest: handlePurchaseRequest,
890
- onReady: handleReady,
891
- onStateChange: handleStateChange,
892
- operation,
893
- renderState: ({ actions, message, status }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: !hasUserClicked && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: {
894
- position: "absolute",
895
- inset: "0",
896
- display: "flex",
897
- flexDirection: "column",
898
- alignItems: "center",
899
- justifyContent: "center",
900
- gap: "16px",
901
- backgroundColor: "rgba(0, 0, 0, 0.85)",
902
- backdropFilter: "blur(8px)",
903
- zIndex: 50,
904
- padding: "20px"
905
- }, children: [
906
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: { margin: "0", fontSize: "14px", color: "#d4d4d4" }, children: [
907
- "Status: ",
908
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#ffffff", fontWeight: "600" }, children: status })
1176
+ ),
1177
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: "24px", alignItems: "flex-start" }, children: [
1178
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { flex: "1 1 380px", minWidth: "320px" }, children: [
1179
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { ...panelStyle, marginBottom: "18px" }, children: [
1180
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1181
+ "div",
1182
+ {
1183
+ style: {
1184
+ display: "flex",
1185
+ flexWrap: "wrap",
1186
+ justifyContent: "space-between",
1187
+ gap: "12px",
1188
+ marginBottom: "18px"
1189
+ },
1190
+ children: [
1191
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1192
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: sectionTitleStyle, children: "Configuration" }),
1193
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: { ...helperTextStyle, marginTop: "6px" }, children: [
1194
+ "Draft values stay local until you press ",
1195
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { style: { color: "#e2e8f0" }, children: "Apply" }),
1196
+ "."
1197
+ ] })
1198
+ ] }),
1199
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: buildIndicatorStyle(hasPendingConfigChanges), children: [
1200
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: buildIndicatorDotStyle(hasPendingConfigChanges) }),
1201
+ hasPendingConfigChanges ? "Not applied" : "Applied"
1202
+ ] })
1203
+ ]
1204
+ }
1205
+ ),
1206
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "grid", gap: "16px" }, children: [
1207
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1208
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { htmlFor: "operation", style: labelStyle, children: [
1209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Operation" }),
1210
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: buildIndicatorStyle(isOperationPending), children: [
1211
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: buildIndicatorDotStyle(isOperationPending) }),
1212
+ isOperationPending ? "Pending" : "Live"
1213
+ ] })
1214
+ ] }),
1215
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: buildInputShellStyle(isOperationPending), children: [
1216
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1217
+ "input",
1218
+ {
1219
+ id: "operation",
1220
+ style: inputStyle,
1221
+ onChange: (e) => setOperationDraft(e.target.value),
1222
+ placeholder: "e.g. iframe",
1223
+ value: operationDraft
1224
+ }
1225
+ ),
1226
+ isOperationPending && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1227
+ "span",
1228
+ {
1229
+ "aria-hidden": "true",
1230
+ style: {
1231
+ fontSize: "16px",
1232
+ color: "#fbbf24",
1233
+ fontWeight: 700
1234
+ },
1235
+ children: "!"
1236
+ }
1237
+ )
1238
+ ] }),
1239
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: helperTextStyle, children: [
1240
+ "Applied value: ",
1241
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { style: codeStyle, children: appliedOperation })
1242
+ ] })
1243
+ ] }),
1244
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1245
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { htmlFor: "storeUrl", style: labelStyle, children: [
1246
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Store URL" }),
1247
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: buildIndicatorStyle(isStoreUrlPending), children: [
1248
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: buildIndicatorDotStyle(isStoreUrlPending) }),
1249
+ isStoreUrlPending ? "Pending" : "Live"
1250
+ ] })
1251
+ ] }),
1252
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: buildInputShellStyle(isStoreUrlPending), children: [
1253
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1254
+ "input",
1255
+ {
1256
+ id: "storeUrl",
1257
+ style: inputStyle,
1258
+ onChange: (e) => setStoreUrlDraft(e.target.value),
1259
+ placeholder: "https://store.example.com",
1260
+ value: storeUrlDraft
1261
+ }
1262
+ ),
1263
+ isStoreUrlPending && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1264
+ "span",
1265
+ {
1266
+ "aria-hidden": "true",
1267
+ style: {
1268
+ fontSize: "16px",
1269
+ color: "#fbbf24",
1270
+ fontWeight: 700
1271
+ },
1272
+ children: "!"
1273
+ }
1274
+ )
1275
+ ] }),
1276
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: helperTextStyle, children: [
1277
+ "Applied value: ",
1278
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { style: codeStyle, children: appliedStoreUrl })
1279
+ ] })
1280
+ ] })
1281
+ ] }),
1282
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1283
+ "div",
1284
+ {
1285
+ style: {
1286
+ display: "flex",
1287
+ flexWrap: "wrap",
1288
+ gap: "12px",
1289
+ marginTop: "20px"
1290
+ },
1291
+ children: [
1292
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1293
+ "button",
1294
+ {
1295
+ type: "button",
1296
+ style: buildButtonStyle("primary", !hasPendingConfigChanges),
1297
+ disabled: !hasPendingConfigChanges,
1298
+ onClick: handleApply,
1299
+ children: "Apply"
1300
+ }
1301
+ ),
1302
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1303
+ "button",
1304
+ {
1305
+ type: "button",
1306
+ style: buildButtonStyle("secondary"),
1307
+ onClick: handleRestartSession,
1308
+ children: "Restart Session"
1309
+ }
1310
+ ),
1311
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1312
+ "button",
1313
+ {
1314
+ type: "button",
1315
+ style: buildButtonStyle("ghost", !hasPendingConfigChanges),
1316
+ disabled: !hasPendingConfigChanges,
1317
+ onClick: handleResetDrafts,
1318
+ children: "Reset Drafts"
1319
+ }
1320
+ )
1321
+ ]
1322
+ }
1323
+ )
1324
+ ] }),
1325
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { ...panelStyle, marginBottom: "18px" }, children: [
1326
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: sectionTitleStyle, children: "Runtime status" }),
1327
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "10px", marginTop: "16px" }, children: statusItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: buildStatusChipStyle(item.value), children: [
1328
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: item.value ? "\u25CF" : "\u25CB" }),
1329
+ item.label
1330
+ ] }, item.label)) }),
1331
+ !embedState.tryNow?.available && embedState.tryNow?.status && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: { ...helperTextStyle, marginTop: "14px" }, children: [
1332
+ "Try Now reason: ",
1333
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#cbd5e1" }, children: embedState.tryNow.status })
1334
+ ] })
909
1335
  ] }),
910
- message && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { margin: "0", fontSize: "14px", color: "#d4d4d4" }, children: message }),
1336
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { ...panelStyle, marginBottom: "18px" }, children: [
1337
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: sectionTitleStyle, children: "Browser diagnostics" }),
1338
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1339
+ "div",
1340
+ {
1341
+ style: {
1342
+ marginTop: "16px",
1343
+ padding: "16px 18px",
1344
+ borderRadius: "20px",
1345
+ background: diagnosticsVerdict.background,
1346
+ border: diagnosticsVerdict.border
1347
+ },
1348
+ children: [
1349
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1350
+ "div",
1351
+ {
1352
+ style: {
1353
+ display: "flex",
1354
+ flexWrap: "wrap",
1355
+ justifyContent: "space-between",
1356
+ gap: "12px",
1357
+ alignItems: "center"
1358
+ },
1359
+ children: [
1360
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1361
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1362
+ "div",
1363
+ {
1364
+ style: {
1365
+ color: diagnosticsVerdict.tone,
1366
+ fontSize: "12px",
1367
+ fontWeight: 700,
1368
+ letterSpacing: "0.1em",
1369
+ textTransform: "uppercase"
1370
+ },
1371
+ children: "Diagnostics verdict"
1372
+ }
1373
+ ),
1374
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#f8fafc", fontSize: "20px", fontWeight: 700, marginTop: "6px" }, children: diagnosticsVerdict.label })
1375
+ ] }),
1376
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#cbd5e1", fontSize: "13px", maxWidth: "420px", lineHeight: 1.6 }, children: diagnosticsVerdict.text })
1377
+ ]
1378
+ }
1379
+ ),
1380
+ (blockingDiagnostics.length > 0 || advisoryDiagnostics.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1381
+ "div",
1382
+ {
1383
+ style: {
1384
+ display: "grid",
1385
+ gap: "10px",
1386
+ marginTop: "16px"
1387
+ },
1388
+ children: [
1389
+ blockingDiagnostics.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { color: "#fca5a5", fontSize: "13px", lineHeight: 1.6 }, children: [
1390
+ "Blocking: ",
1391
+ blockingDiagnostics.map((item) => item.label).join(", ")
1392
+ ] }),
1393
+ advisoryDiagnostics.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { color: "#fde68a", fontSize: "13px", lineHeight: 1.6 }, children: [
1394
+ "Worth checking: ",
1395
+ advisoryDiagnostics.map((item) => item.label).join(", ")
1396
+ ] })
1397
+ ]
1398
+ }
1399
+ )
1400
+ ]
1401
+ }
1402
+ ),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1404
+ "div",
1405
+ {
1406
+ style: {
1407
+ display: "grid",
1408
+ gap: "14px",
1409
+ marginTop: "18px"
1410
+ },
1411
+ children: diagnosticGroups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1412
+ "div",
1413
+ {
1414
+ style: {
1415
+ padding: "16px",
1416
+ borderRadius: "20px",
1417
+ backgroundColor: "rgba(15, 23, 42, 0.42)",
1418
+ border: "1px solid rgba(148, 163, 184, 0.12)"
1419
+ },
1420
+ children: [
1421
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1422
+ "div",
1423
+ {
1424
+ style: {
1425
+ color: "#e2e8f0",
1426
+ fontSize: "14px",
1427
+ fontWeight: 700,
1428
+ marginBottom: "14px"
1429
+ },
1430
+ children: group.title
1431
+ }
1432
+ ),
1433
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1434
+ "div",
1435
+ {
1436
+ style: {
1437
+ display: "grid",
1438
+ gridTemplateColumns: "repeat(auto-fit, minmax(190px, 1fr))",
1439
+ gap: "12px"
1440
+ },
1441
+ children: group.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1442
+ "div",
1443
+ {
1444
+ style: {
1445
+ padding: "14px 16px",
1446
+ borderRadius: "18px",
1447
+ backgroundColor: item.value ? "rgba(8, 31, 17, 0.72)" : "rgba(42, 12, 12, 0.52)",
1448
+ border: item.value ? "1px solid rgba(34, 197, 94, 0.18)" : "1px solid rgba(248, 113, 113, 0.18)"
1449
+ },
1450
+ children: [
1451
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#94a3b8", fontSize: "12px", marginBottom: "8px" }, children: item.label }),
1452
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1453
+ "div",
1454
+ {
1455
+ style: {
1456
+ display: "flex",
1457
+ alignItems: "center",
1458
+ gap: "8px",
1459
+ color: item.value ? "#86efac" : "#fca5a5",
1460
+ fontWeight: 700
1461
+ },
1462
+ children: [
1463
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: item.value ? "\u2713" : "\u2715" }),
1464
+ item.value ? "Available" : "Missing"
1465
+ ]
1466
+ }
1467
+ ),
1468
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#94a3b8", fontSize: "12px", lineHeight: 1.5, marginTop: "10px" }, children: item.detail })
1469
+ ]
1470
+ },
1471
+ item.label
1472
+ ))
1473
+ }
1474
+ )
1475
+ ]
1476
+ },
1477
+ group.title
1478
+ ))
1479
+ }
1480
+ )
1481
+ ] }),
1482
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: panelStyle, children: [
1483
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1484
+ "div",
1485
+ {
1486
+ style: {
1487
+ display: "flex",
1488
+ justifyContent: "space-between",
1489
+ alignItems: "center",
1490
+ gap: "12px",
1491
+ marginBottom: "16px"
1492
+ },
1493
+ children: [
1494
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: sectionTitleStyle, children: "Event log" }),
1495
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { ...codeStyle, padding: "4px 10px" }, children: [
1496
+ eventLog.length,
1497
+ " recent events"
1498
+ ] })
1499
+ ]
1500
+ }
1501
+ ),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1503
+ "div",
1504
+ {
1505
+ style: {
1506
+ background: "linear-gradient(180deg, rgba(2, 6, 23, 0.88) 0%, rgba(2, 6, 23, 0.64) 100%)",
1507
+ padding: "14px",
1508
+ borderRadius: "18px",
1509
+ minHeight: "220px",
1510
+ height: "min(46vh, 420px)",
1511
+ overflowY: "auto",
1512
+ fontFamily: '"SF Mono", "Roboto Mono", monospace',
1513
+ fontSize: "12px",
1514
+ border: "1px solid rgba(148, 163, 184, 0.12)"
1515
+ },
1516
+ children: eventLog.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "grid", gap: "10px" }, children: eventLog.map((event) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1517
+ "div",
1518
+ {
1519
+ style: {
1520
+ paddingBottom: "10px",
1521
+ borderBottom: "1px solid rgba(148, 163, 184, 0.08)"
1522
+ },
1523
+ children: [
1524
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#64748b", marginBottom: "4px" }, children: event.timestamp }),
1525
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#e2e8f0", lineHeight: 1.6 }, children: event.message })
1526
+ ]
1527
+ },
1528
+ event.id
1529
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#64748b" }, children: "No events yet. Start a session or apply a config change." })
1530
+ }
1531
+ )
1532
+ ] })
1533
+ ] }),
1534
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { flex: "1 1 560px", minWidth: "320px" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { ...panelStyle, padding: "24px" }, children: [
911
1535
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
912
- "button",
1536
+ "div",
913
1537
  {
914
- type: "button",
915
1538
  style: {
916
- ...buttonStyle,
917
- backgroundColor: "#16a34a",
918
- color: "#ffffff",
919
- border: "none",
920
- padding: "12px 24px",
921
- fontSize: "16px",
922
- fontWeight: "600",
923
- cursor: actions.canTryNow ? "pointer" : "not-allowed",
924
- opacity: actions.canTryNow ? 1 : 0.5
925
- },
926
- disabled: !actions.canTryNow,
927
- onMouseEnter: (e) => {
928
- if (actions.canTryNow) {
929
- e.currentTarget.style.backgroundColor = "#15803d";
930
- }
931
- },
932
- onMouseLeave: (e) => {
933
- if (actions.canTryNow) {
934
- e.currentTarget.style.backgroundColor = "#16a34a";
935
- }
936
- },
937
- onClick: () => {
938
- setHasUserClicked(true);
939
- setShowIframe(true);
940
- addEvent(embedState.hasPlayedOnce ? "User clicked - Resuming game" : "User clicked - Starting game with tryNow");
941
- actions.tryNow();
1539
+ display: "flex",
1540
+ flexWrap: "wrap",
1541
+ justifyContent: "space-between",
1542
+ alignItems: "center",
1543
+ gap: "12px",
1544
+ marginBottom: "16px"
942
1545
  },
943
1546
  children: [
944
- "\u{1F3AE} ",
945
- embedState.hasPlayedOnce ? "Resume Game" : "Try Demo Now"
1547
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1548
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: sectionTitleStyle, children: "Embed preview" }),
1549
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { ...helperTextStyle, marginTop: "6px" }, children: "The live iframe always reflects the applied configuration." })
1550
+ ] }),
1551
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: "10px" }, children: [
1552
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { ...codeStyle, padding: "6px 10px" }, children: [
1553
+ "Host: ",
1554
+ displayHost
1555
+ ] }),
1556
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { ...codeStyle, padding: "6px 10px" }, children: [
1557
+ "Operation: ",
1558
+ appliedOperation
1559
+ ] })
1560
+ ] })
946
1561
  ]
947
1562
  }
948
1563
  ),
949
- actions.canBuyNow && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
950
- "button",
1564
+ hasPendingConfigChanges && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1565
+ "div",
951
1566
  {
952
- type: "button",
953
1567
  style: {
954
- ...buttonStyle,
955
- backgroundColor: "#525252",
956
- color: "#ffffff",
957
- border: "none",
958
- padding: "8px 16px",
959
- fontSize: "14px",
960
- fontWeight: "500"
1568
+ display: "flex",
1569
+ alignItems: "center",
1570
+ gap: "12px",
1571
+ padding: "14px 16px",
1572
+ marginBottom: "16px",
1573
+ borderRadius: "18px",
1574
+ backgroundColor: "rgba(35, 23, 8, 0.72)",
1575
+ border: "1px solid rgba(245, 158, 11, 0.22)",
1576
+ color: "#fde68a"
961
1577
  },
962
- onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "#404040",
963
- onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "#525252",
964
- onClick: () => {
965
- addEvent("Buy Now clicked");
966
- actions.buyNow();
1578
+ children: [
1579
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: buildIndicatorDotStyle(true) }),
1580
+ "Draft values are ready but not applied to the iframe yet."
1581
+ ]
1582
+ }
1583
+ ),
1584
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1585
+ "div",
1586
+ {
1587
+ style: {
1588
+ position: "relative",
1589
+ minHeight: "640px",
1590
+ overflow: "hidden",
1591
+ borderRadius: "24px",
1592
+ border: "1px solid rgba(148, 163, 184, 0.14)",
1593
+ background: "linear-gradient(180deg, rgba(3, 7, 18, 0.86) 0%, rgba(2, 6, 23, 1) 100%)",
1594
+ boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.04)"
967
1595
  },
968
- children: "Buy Now"
1596
+ children: [
1597
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1598
+ "div",
1599
+ {
1600
+ style: {
1601
+ display: "flex",
1602
+ alignItems: "center",
1603
+ justifyContent: "space-between",
1604
+ gap: "12px",
1605
+ padding: "14px 18px",
1606
+ borderBottom: "1px solid rgba(148, 163, 184, 0.08)",
1607
+ backgroundColor: "rgba(15, 23, 42, 0.52)"
1608
+ },
1609
+ children: [
1610
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
1611
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { width: "10px", height: "10px", borderRadius: "999px", backgroundColor: "#f97316" } }),
1612
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { width: "10px", height: "10px", borderRadius: "999px", backgroundColor: "#facc15" } }),
1613
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { width: "10px", height: "10px", borderRadius: "999px", backgroundColor: "#4ade80" } })
1614
+ ] }),
1615
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: "#94a3b8", fontSize: "12px", fontFamily: '"SF Mono", "Roboto Mono", monospace' }, children: [
1616
+ "/embed?operation=",
1617
+ appliedOperation
1618
+ ] })
1619
+ ]
1620
+ }
1621
+ ),
1622
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1623
+ PlayruoEmbed,
1624
+ {
1625
+ baseUrl: props.baseUrl,
1626
+ className: "w-full h-full absolute inset-0",
1627
+ iframeRef,
1628
+ onDemoCompleted: handleDemoCompleted,
1629
+ onError: handleError,
1630
+ onPurchaseRequest: handlePurchaseRequest,
1631
+ onReady: handleReady,
1632
+ onStateChange: handleStateChange,
1633
+ operation: appliedOperation,
1634
+ renderState: ({ actions, message, status }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: !hasUserClicked && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1635
+ "div",
1636
+ {
1637
+ style: {
1638
+ position: "absolute",
1639
+ inset: "53px 0 0 0",
1640
+ display: "flex",
1641
+ alignItems: "center",
1642
+ justifyContent: "center",
1643
+ padding: "24px",
1644
+ background: "linear-gradient(180deg, rgba(2, 6, 23, 0.4) 0%, rgba(2, 6, 23, 0.84) 70%, rgba(2, 6, 23, 0.9) 100%)",
1645
+ backdropFilter: "blur(12px)",
1646
+ zIndex: 50
1647
+ },
1648
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1649
+ "div",
1650
+ {
1651
+ style: {
1652
+ width: "min(100%, 420px)",
1653
+ padding: "28px",
1654
+ borderRadius: "28px",
1655
+ border: "1px solid rgba(148, 163, 184, 0.18)",
1656
+ background: "linear-gradient(180deg, rgba(15, 23, 42, 0.94) 0%, rgba(7, 12, 24, 0.98) 100%)",
1657
+ boxShadow: "0 32px 72px rgba(0, 0, 0, 0.35)"
1658
+ },
1659
+ children: [
1660
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1661
+ "div",
1662
+ {
1663
+ style: {
1664
+ display: "inline-flex",
1665
+ alignItems: "center",
1666
+ gap: "10px",
1667
+ padding: "6px 12px",
1668
+ borderRadius: "999px",
1669
+ backgroundColor: "rgba(56, 189, 248, 0.12)",
1670
+ border: "1px solid rgba(125, 211, 252, 0.18)",
1671
+ color: "#7dd3fc",
1672
+ fontSize: "11px",
1673
+ fontWeight: 700,
1674
+ letterSpacing: "0.08em",
1675
+ textTransform: "uppercase"
1676
+ },
1677
+ children: "Live overlay"
1678
+ }
1679
+ ),
1680
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1681
+ "h4",
1682
+ {
1683
+ style: {
1684
+ margin: "18px 0 10px 0",
1685
+ color: "#f8fafc",
1686
+ fontSize: "28px",
1687
+ letterSpacing: "-0.03em"
1688
+ },
1689
+ children: embedState.hasPlayedOnce ? "Resume the session" : "Start the demo"
1690
+ }
1691
+ ),
1692
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: { margin: 0, color: "#94a3b8", lineHeight: 1.7 }, children: [
1693
+ "Status: ",
1694
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#f8fafc", fontWeight: 700 }, children: status })
1695
+ ] }),
1696
+ message && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { margin: "10px 0 0 0", color: "#cbd5e1", lineHeight: 1.7 }, children: message }),
1697
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: "12px", marginTop: "24px" }, children: [
1698
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1699
+ "button",
1700
+ {
1701
+ type: "button",
1702
+ style: buildButtonStyle("primary", !actions.canTryNow),
1703
+ disabled: !actions.canTryNow,
1704
+ onClick: () => {
1705
+ setHasUserClicked(true);
1706
+ setShowIframe(true);
1707
+ addEvent(
1708
+ embedState.hasPlayedOnce ? "User clicked - Resuming game" : "User clicked - Starting game with tryNow"
1709
+ );
1710
+ actions.tryNow();
1711
+ },
1712
+ children: [
1713
+ "\u{1F3AE} ",
1714
+ embedState.hasPlayedOnce ? "Resume game" : "Try demo now"
1715
+ ]
1716
+ }
1717
+ ),
1718
+ actions.canBuyNow && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1719
+ "button",
1720
+ {
1721
+ type: "button",
1722
+ style: buildButtonStyle("secondary"),
1723
+ onClick: () => {
1724
+ addEvent("Buy Now clicked");
1725
+ actions.buyNow();
1726
+ },
1727
+ children: "Buy Now"
1728
+ }
1729
+ )
1730
+ ] })
1731
+ ]
1732
+ }
1733
+ )
1734
+ }
1735
+ ) }),
1736
+ showIframe,
1737
+ storeUrl: appliedStoreUrl
1738
+ },
1739
+ key
1740
+ )
1741
+ ]
969
1742
  }
970
1743
  )
971
- ] }) }),
972
- showIframe,
973
- storeUrl
974
- },
975
- key
976
- ) })
977
- ] }) })
978
- ] })
979
- ] }) });
1744
+ ] }) })
1745
+ ] })
1746
+ ] })
1747
+ ]
1748
+ }
1749
+ );
980
1750
  };
981
1751
 
982
1752
  // src/post-message-types.ts