Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save westonruter/f2fa3a7e69ff58965027e87eaf496f21 to your computer and use it in GitHub Desktop.
Save westonruter/f2fa3a7e69ff58965027e87eaf496f21 to your computer and use it in GitHub Desktop.

auto-sizes

Warning

Stable tag is unchanged at 1.3.0, so no plugin release will occur.

svn status:

M       readme.txt
svn diff
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -1,7 +1,7 @@
 === Enhanced Responsive Images ===
 
 Contributors: wordpressdotorg
-Tested up to: 6.6
+Tested up to: 6.7
 Stable tag:   1.3.0
 License:      GPLv2 or later
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html

dominant-color-images

Warning

Stable tag is unchanged at 1.1.2, so no plugin release will occur.

svn status:

M       readme.txt
svn diff
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -1,7 +1,7 @@
 === Image Placeholders ===
 
 Contributors: wordpressdotorg
-Tested up to: 6.6
+Tested up to: 6.7
 Stable tag:   1.1.2
 License:      GPLv2 or later
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html

embed-optimizer

Warning

Stable tag is unchanged at 0.3.0, so no plugin release will occur.

svn status:

M       class-embed-optimizer-tag-visitor.php
M       detect.js
?       detect.min.js
M       hooks.php
M       lazy-load.js
?       lazy-load.min.js
M       load.php
M       readme.txt
svn diff
Index: class-embed-optimizer-tag-visitor.php
===================================================================
--- class-embed-optimizer-tag-visitor.php	(revision 3189893)
+++ class-embed-optimizer-tag-visitor.php	(working copy)
@@ -50,7 +50,7 @@
 	 * @since 0.3.0
 	 *
 	 * @param OD_HTML_Tag_Processor $processor Processor.
-	 * @return bool Whether the tag should be measured and stored in URL metrics.
+	 * @return bool Whether the tag should be measured and stored in URL Metrics.
 	 */
 	private function is_embed_wrapper( OD_HTML_Tag_Processor $processor ): bool {
 		return (
@@ -83,7 +83,7 @@
 	 * @since 0.2.0
 	 *
 	 * @param OD_Tag_Visitor_Context $context Tag visitor context.
-	 * @return bool Whether the tag should be tracked in URL metrics.
+	 * @return bool Whether the tag should be tracked in URL Metrics.
 	 */
 	public function __invoke( OD_Tag_Visitor_Context $context ): bool {
 		$processor = $context->processor;
@@ -103,7 +103,7 @@
 
 		$this->reduce_layout_shifts( $context );
 
-		// Preconnect links and lazy-loading can only be done once there are URL metrics collected for both mobile and desktop.
+		// Preconnect links and lazy-loading can only be done once there are URL Metrics collected for both mobile and desktop.
 		if (
 			$context->url_metric_group_collection->get_first_group()->count() > 0
 			&&
Index: detect.js
===================================================================
--- detect.js	(revision 3189893)
+++ detect.js	(working copy)
@@ -1 +1,123 @@
-const consoleLogPrefix="[Embed Optimizer]";function log(...e){console.log(consoleLogPrefix,...e)}function error(...e){console.error(consoleLogPrefix,...e)}const loadedElementContentRects=new Map;export function initialize({isDebug:e}){const t=document.querySelectorAll(".wp-block-embed > .wp-block-embed__wrapper[data-od-xpath]");for(const o of t)monitorEmbedWrapperForResizes(o,e);e&&log("Loaded embed content rects:",loadedElementContentRects)}export async function finalize({isDebug:e,getElementData:t,extendElementData:o}){for(const[n,r]of loadedElementContentRects.entries())try{o(n,{resizedBoundingClientRect:r}),e&&log(`boundingClientRect for ${n} resized:`,t(n).boundingClientRect,"=>",r)}catch(e){error(`Failed to extend element data for ${n} with resizedBoundingClientRect:`,r,e)}}function monitorEmbedWrapperForResizes(e,t){if(!("odXpath"in e.dataset))throw new Error("Embed wrapper missing data-od-xpath attribute.");const o=e.dataset.odXpath;new ResizeObserver((e=>{const[n]=e;loadedElementContentRects.set(o,n.contentRect),t&&log(`Resized element ${o}:`,n.contentRect)})).observe(e,{box:"content-box"})}
\ No newline at end of file
+/**
+ * Embed Optimizer module for Optimization Detective
+ *
+ * When a URL Metric is being collected by Optimization Detective, this module adds a ResizeObserver to keep track of
+ * the changed heights for embed blocks. This data is extended/amended onto the element data of the pending URL Metric
+ * when it is submitted for storage.
+ */
+
+const consoleLogPrefix = '[Embed Optimizer]';
+
+/**
+ * @typedef {import("../optimization-detective/types.ts").URLMetric} URLMetric
+ * @typedef {import("../optimization-detective/types.ts").Extension} Extension
+ * @typedef {import("../optimization-detective/types.ts").InitializeCallback} InitializeCallback
+ * @typedef {import("../optimization-detective/types.ts").InitializeArgs} InitializeArgs
+ * @typedef {import("../optimization-detective/types.ts").FinalizeArgs} FinalizeArgs
+ * @typedef {import("../optimization-detective/types.ts").FinalizeCallback} FinalizeCallback
+ * @typedef {import("../optimization-detective/types.ts").ExtendedElementData} ExtendedElementData
+ */
+
+/**
+ * Logs a message.
+ *
+ * @param {...*} message
+ */
+function log( ...message ) {
+	// eslint-disable-next-line no-console
+	console.log( consoleLogPrefix, ...message );
+}
+
+/**
+ * Logs an error.
+ *
+ * @param {...*} message
+ */
+function error( ...message ) {
+	// eslint-disable-next-line no-console
+	console.error( consoleLogPrefix, ...message );
+}
+
+/**
+ * Embed element heights.
+ *
+ * @type {Map<string, DOMRectReadOnly>}
+ */
+const loadedElementContentRects = new Map();
+
+/**
+ * Initializes extension.
+ *
+ * @type {InitializeCallback}
+ * @param {InitializeArgs} args Args.
+ */
+export function initialize( { isDebug } ) {
+	/** @type NodeListOf<HTMLDivElement> */
+	const embedWrappers = document.querySelectorAll(
+		'.wp-block-embed > .wp-block-embed__wrapper[data-od-xpath]'
+	);
+
+	for ( const embedWrapper of embedWrappers ) {
+		monitorEmbedWrapperForResizes( embedWrapper, isDebug );
+	}
+
+	if ( isDebug ) {
+		log( 'Loaded embed content rects:', loadedElementContentRects );
+	}
+}
+
+/**
+ * Finalizes extension.
+ *
+ * @type {FinalizeCallback}
+ * @param {FinalizeArgs} args Args.
+ */
+export async function finalize( {
+	isDebug,
+	getElementData,
+	extendElementData,
+} ) {
+	for ( const [ xpath, domRect ] of loadedElementContentRects.entries() ) {
+		try {
+			extendElementData( xpath, {
+				resizedBoundingClientRect: domRect,
+			} );
+			if ( isDebug ) {
+				const elementData = getElementData( xpath );
+				log(
+					`boundingClientRect for ${ xpath } resized:`,
+					elementData.boundingClientRect,
+					'=>',
+					domRect
+				);
+			}
+		} catch ( err ) {
+			error(
+				`Failed to extend element data for ${ xpath } with resizedBoundingClientRect:`,
+				domRect,
+				err
+			);
+		}
+	}
+}
+
+/**
+ * Monitors embed wrapper for resizes.
+ *
+ * @param {HTMLDivElement} embedWrapper Embed wrapper DIV.
+ * @param {boolean}        isDebug      Whether debug.
+ */
+function monitorEmbedWrapperForResizes( embedWrapper, isDebug ) {
+	if ( ! ( 'odXpath' in embedWrapper.dataset ) ) {
+		throw new Error( 'Embed wrapper missing data-od-xpath attribute.' );
+	}
+	const xpath = embedWrapper.dataset.odXpath;
+	const observer = new ResizeObserver( ( entries ) => {
+		const [ entry ] = entries;
+		loadedElementContentRects.set( xpath, entry.contentRect );
+		if ( isDebug ) {
+			log( `Resized element ${ xpath }:`, entry.contentRect );
+		}
+	} );
+	observer.observe( embedWrapper, { box: 'content-box' } );
+}
Index: hooks.php
===================================================================
--- hooks.php	(revision 3189893)
+++ hooks.php	(working copy)
@@ -121,7 +121,7 @@
 	if ( ! is_array( $extension_module_urls ) ) {
 		$extension_module_urls = array();
 	}
-	$extension_module_urls[] = add_query_arg( 'ver', EMBED_OPTIMIZER_VERSION, plugin_dir_url( __FILE__ ) . 'detect.js' );
+	$extension_module_urls[] = add_query_arg( 'ver', EMBED_OPTIMIZER_VERSION, plugin_dir_url( __FILE__ ) . sprintf( 'detect%s.js', wp_scripts_get_suffix() ) );
 	return $extension_module_urls;
 }
 
@@ -181,8 +181,9 @@
 		'script' => 'embed_optimizer_script',
 		'iframe' => 'embed_optimizer_iframe',
 	);
-	$trigger_error  = static function ( string $message ): void {
-		wp_trigger_error( __FUNCTION__, esc_html( $message ) );
+	$function_name  = __FUNCTION__;
+	$trigger_error  = static function ( string $message ) use ( $function_name ): void {
+		wp_trigger_error( $function_name, esc_html( $message ) );
 	};
 	try {
 		/*
@@ -325,7 +326,7 @@
  * @since 0.2.0
  */
 function embed_optimizer_get_lazy_load_script(): string {
-	$script = file_get_contents( __DIR__ . '/lazy-load.js' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- It's a local filesystem path not a remote request.
+	$script = file_get_contents( __DIR__ . sprintf( '/lazy-load%s.js', wp_scripts_get_suffix() ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- It's a local filesystem path not a remote request.
 
 	if ( false === $script ) {
 		return '';
Index: lazy-load.js
===================================================================
--- lazy-load.js	(revision 3189893)
+++ lazy-load.js	(working copy)
@@ -1 +1,55 @@
-const lazyEmbedsScripts=document.querySelectorAll('script[type="application/vnd.embed-optimizer.javascript"]'),lazyEmbedScriptsByParents=new Map,lazyEmbedObserver=new IntersectionObserver((e=>{for(const t of e)if(t.isIntersecting){const e=t.target,r=lazyEmbedScriptsByParents.get(e),s=document.createElement("script");for(const e of r.attributes)"type"!==e.nodeName&&s.setAttribute("data-original-type"===e.nodeName?"type":e.nodeName,e.nodeValue);r.replaceWith(s),lazyEmbedObserver.unobserve(e)}}),{rootMargin:"100% 0% 100% 0%",threshold:0});for(const e of lazyEmbedsScripts){const t=e.parentNode;t instanceof HTMLElement&&(lazyEmbedScriptsByParents.set(t,e),lazyEmbedObserver.observe(t))}
\ No newline at end of file
+/**
+ * Lazy load embeds
+ *
+ * When an embed block is lazy loaded, the script tag is replaced with a script tag that has the original attributes
+ */
+
+const lazyEmbedsScripts = document.querySelectorAll(
+	'script[type="application/vnd.embed-optimizer.javascript"]'
+);
+const lazyEmbedScriptsByParents = new Map();
+
+const lazyEmbedObserver = new IntersectionObserver(
+	( entries ) => {
+		for ( const entry of entries ) {
+			if ( entry.isIntersecting ) {
+				const lazyEmbedParent = entry.target;
+				const lazyEmbedScript =
+					/** @type {HTMLScriptElement} */ lazyEmbedScriptsByParents.get(
+						lazyEmbedParent
+					);
+				const embedScript =
+					/** @type {HTMLScriptElement} */ document.createElement(
+						'script'
+					);
+				for ( const attr of lazyEmbedScript.attributes ) {
+					if ( attr.nodeName === 'type' ) {
+						// Omit type=application/vnd.embed-optimizer.javascript type.
+						continue;
+					}
+					embedScript.setAttribute(
+						attr.nodeName === 'data-original-type'
+							? 'type'
+							: attr.nodeName,
+						attr.nodeValue
+					);
+				}
+				lazyEmbedScript.replaceWith( embedScript );
+				lazyEmbedObserver.unobserve( lazyEmbedParent );
+			}
+		}
+	},
+	{
+		rootMargin: '100% 0% 100% 0%',
+		threshold: 0,
+	}
+);
+
+for ( const lazyEmbedScript of lazyEmbedsScripts ) {
+	const lazyEmbedParent =
+		/** @type {HTMLElement} */ lazyEmbedScript.parentNode;
+	if ( lazyEmbedParent instanceof HTMLElement ) {
+		lazyEmbedScriptsByParents.set( lazyEmbedParent, lazyEmbedScript );
+		lazyEmbedObserver.observe( lazyEmbedParent );
+	}
+}
Index: load.php
===================================================================
--- load.php	(revision 3189893)
+++ load.php	(working copy)
@@ -2,7 +2,7 @@
 /**
  * Plugin Name: Embed Optimizer
  * Plugin URI: https://github.com/WordPress/performance/tree/trunk/plugins/embed-optimizer
- * Description: Optimizes the performance of embeds by lazy-loading iframes and scripts.
+ * Description: Optimizes the performance of embeds through lazy-loading, preconnecting, and reserving space to reduce layout shifts.
  * Requires at least: 6.5
  * Requires PHP: 7.2
  * Version: 0.3.0
@@ -76,6 +76,24 @@
 			return;
 		}
 
+		if (
+			( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) &&
+			! file_exists( __DIR__ . '/detect.min.js' )
+		) {
+			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
+			trigger_error(
+				esc_html(
+					sprintf(
+						/* translators: 1: File path. 2: CLI command. */
+						'[Embed Optimizer] ' . __( 'Unable to load %1$s. Please make sure you have run %2$s.', 'embed-optimizer' ),
+						'detect.min.js',
+						'`npm install && npm run build:plugin:embed-optimizer`'
+					)
+				),
+				E_USER_ERROR
+			);
+		}
+
 		define( 'EMBED_OPTIMIZER_VERSION', $version );
 
 		// Load in the Embed Optimizer plugin hooks.
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -7,14 +7,30 @@
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 Tags:         performance, embeds
 
-Optimizes the performance of embeds by lazy-loading iframes and scripts.
+Optimizes the performance of embeds through lazy-loading, preconnecting, and reserving space to reduce layout shifts.
 
 == Description ==
 
-This plugin's purpose is to optimize the performance of [embeds in WordPress](https://wordpress.org/documentation/article/embeds/), such as YouTube videos, TikToks, and so on. Initially this is achieved by lazy-loading them only when they come into view. This improves performance because embeds are generally very resource-intensive and so lazy-loading them ensures that they don't compete with resources when the page is loading. [Other optimizations](https://github.com/WordPress/performance/issues?q=is%3Aissue+is%3Aopen+label%3A%22%5BPlugin%5D+Embed+Optimizer%22) are planned for the future.
+This plugin's purpose is to optimize the performance of [embeds in WordPress](https://wordpress.org/documentation/article/embeds/), such as Tweets, YouTube videos, TikToks, and others.
 
-This plugin also recommends that you install and activate the [Optimization Detective](https://wordpress.org/plugins/optimization-detective/) plugin. When it is active, it will start recording which embeds appear in the initial viewport based on actual visitors to your site. With this information in hand, Embed Optimizer will then avoid lazy-loading embeds which appear in the initial viewport (above the fold). This is important because lazy-loading adds a delay which can hurt the user experience and even degrade the Largest Contentful Paint (LCP) score for the page. In addition to not lazy-loading such above-the-fold embeds, Embed Optimizer will add preconnect links for the hosts of network resources known to be required for the most popular embeds (e.g. YouTube, Twitter, Vimeo, Spotify, VideoPress); this can further speed up the loading of critical embeds. Again, these performance enhancements are only enabled when Optimization Detective is active.
+The current optimizations include:
 
+1. Lazy loading embeds just before they come into view
+2. Adding preconnect links for embeds in the initial viewport
+3. Reserving space for embeds that resize to reduce layout shifting
+
+**Lazy loading embeds** improves performance because embeds are generally very resource-intensive, so lazy loading them ensures that they don't compete with resources when the page is loading. Lazy loading of `IFRAME`\-based embeds is handled simply by adding the `loading=lazy` attribute. Lazy loading embeds that include `SCRIPT` tags is handled by using an Intersection Observer to watch for when the embed’s `FIGURE` container is going to enter the viewport and then it dynamically inserts the `SCRIPT` tag.
+
+**This plugin also recommends that you install and activate the [Optimization Detective](https://wordpress.org/plugins/optimization-detective/) plugin**, which unlocks several optimizations beyond just lazy loading. Without Optimization Detective, lazy loading can actually degrade performance *when an embed is positioned in the initial viewport*. This is because lazy loading such viewport-initial elements can degrade LCP since rendering is delayed by the logic to determine whether the element is visible. This is why WordPress Core tries its best to [avoid](https://make.wordpress.org/core/2021/07/15/refining-wordpress-cores-lazy-loading-implementation/) [lazy loading](https://make.wordpress.org/core/2021/07/15/refining-wordpress-cores-lazy-loading-implementation/) `IMG` tags which appear in the initial viewport, although the server-side heuristics aren’t perfect. This is where Optimization Detective comes in since it detects whether an embed appears in any breakpoint-specific viewports, like mobile, tablet, and desktop. (See also the [Image Prioritizer](https://wordpress.org/plugins/image-prioritizer/) plugin which extends Optimization Detective to ensure lazy loading is correctly applied based on whether an IMG is in the initial viewport.)
+
+When Optimization Detective is active, it will start keeping track of which embeds appear in the initial viewport based on actual visits to your site. With this information in hand, Embed Optimizer will then avoid lazy loading embeds which appear in the initial viewport. Furthermore, for such above-the-fold embeds Embed Optimizer will also **add preconnect links** for resources known to be used by those embeds. For example, if a YouTube embed appears in the initial viewport, Embed Optimizer with Optimization Detective will omit `loading=lazy` while also adding a preconnect link for `https://i.ytimg.com` which is the domain from which YouTube video poster images are served. Such preconnect links cause the initial-viewport embeds to load even faster.
+
+The other major feature in Embed Optimizer enabled by Optimization Detective is the **reduction of layout shifts** caused by embeds that resize when they load. This is seen commonly in WordPress post embeds or Tweet embeds. Embed Optimizer keeps track of the resized heights of these embeds. With these resized heights stored, Embed Optimizer sets the appropriate height on the container FIGURE element as the viewport-specific `min-height` so that when the embed loads it does not cause a layout shift.
+
+Since Optimization Detective relies on page visits to learn how the page is laid out, you’ll need to wait until you have visits from a mobile and desktop device to start seeing optimizations applied. Also, note that Optimization Detective does not apply optimizations by default for logged-in admin users.
+
+Please note that the optimizations are intended to apply to Embed blocks. So if you do not see optimizations applied, make sure that your embeds are not inside of a Classic Block.
+
 There are currently **no settings** and no user interface for this plugin since it is designed to work without any configuration.
 
 == Installation ==
@@ -51,11 +67,17 @@
 
 == Changelog ==
 
+= n.e.x.t =
+
+**Enhancements**
+
+* Serve unminified scripts when `SCRIPT_DEBUG` is enabled. ([1643](https://github.com/WordPress/performance/pull/1643))
+
 = 0.3.0 =
 
 **Enhancements**
 
-* Leverage URL metrics to reserve space for embeds to reduce CLS. ([1373](https://github.com/WordPress/performance/pull/1373))
+* Leverage URL Metrics to reserve space for embeds to reduce CLS. ([1373](https://github.com/WordPress/performance/pull/1373))
 * Avoid lazy-loading images and embeds unless there are URL Metrics for both mobile and desktop. ([1604](https://github.com/WordPress/performance/pull/1604))
 
 = 0.2.0 =

image-prioritizer

Warning

Stable tag is unchanged at 0.2.0, so no plugin release will occur.

svn status:

M       class-image-prioritizer-background-image-styled-tag-visitor.php
M       class-image-prioritizer-img-tag-visitor.php
M       class-image-prioritizer-tag-visitor.php
M       class-image-prioritizer-video-tag-visitor.php
M       hooks.php
M       lazy-load.js
?       lazy-load.min.js
M       load.php
M       readme.txt
svn diff
Index: class-image-prioritizer-background-image-styled-tag-visitor.php
===================================================================
--- class-image-prioritizer-background-image-styled-tag-visitor.php	(revision 3189893)
+++ class-image-prioritizer-background-image-styled-tag-visitor.php	(working copy)
@@ -23,7 +23,7 @@
 	 * Visits a tag.
 	 *
 	 * @param OD_Tag_Visitor_Context $context Tag visitor context.
-	 * @return bool Whether the tag should be tracked in URL metrics.
+	 * @return bool Whether the tag should be tracked in URL Metrics.
 	 */
 	public function __invoke( OD_Tag_Visitor_Context $context ): bool {
 		$processor = $context->processor;
Index: class-image-prioritizer-img-tag-visitor.php
===================================================================
--- class-image-prioritizer-img-tag-visitor.php	(revision 3189893)
+++ class-image-prioritizer-img-tag-visitor.php	(working copy)
@@ -24,7 +24,7 @@
 	 *
 	 * @param OD_Tag_Visitor_Context $context Tag visitor context.
 	 *
-	 * @return bool Whether the tag should be tracked in URL metrics.
+	 * @return bool Whether the tag should be tracked in URL Metrics.
 	 */
 	public function __invoke( OD_Tag_Visitor_Context $context ): bool {
 		$processor = $context->processor;
@@ -61,7 +61,7 @@
 			 * At this point, the element is not the shared LCP across all viewport groups. Nevertheless, server-side
 			 * heuristics have added fetchpriority=high to the element, but this is not warranted either due to a lack
 			 * of data or because the LCP element is not common across all viewport groups. Since we have collected at
-			 * least some URL metrics (per is_any_group_populated), further below a fetchpriority=high preload link will
+			 * least some URL Metrics (per is_any_group_populated), further below a fetchpriority=high preload link will
 			 * be added for the viewport(s) for which this is actually the LCP element. Some viewport groups may never
 			 * get populated due to a lack of traffic (e.g. from tablets or phablets), so it is important to remove
 			 * fetchpriority=high in such case to prevent server-side heuristics from prioritizing loading the image
@@ -71,10 +71,10 @@
 		}
 
 		/*
-		 * Do not do any lazy-loading if the mobile and desktop viewport groups lack URL metrics. This is important
+		 * Do not do any lazy-loading if the mobile and desktop viewport groups lack URL Metrics. This is important
 		 * because if there is an IMG in the initial viewport on desktop but not mobile, if then there are only URL
 		 * metrics collected for mobile then the IMG will get lazy-loaded which is good for mobile but for desktop
-		 * it will hurt performance. So this is why it is important to have URL metrics collected for both desktop and
+		 * it will hurt performance. So this is why it is important to have URL Metrics collected for both desktop and
 		 * mobile to verify whether maximum intersectionRatio is accounting for both screen sizes.
 		 */
 		$element_max_intersection_ratio = $context->url_metric_group_collection->get_element_max_intersection_ratio( $xpath );
Index: class-image-prioritizer-tag-visitor.php
===================================================================
--- class-image-prioritizer-tag-visitor.php	(revision 3189893)
+++ class-image-prioritizer-tag-visitor.php	(working copy)
@@ -25,7 +25,7 @@
 	 * Visits a tag.
 	 *
 	 * @param OD_Tag_Visitor_Context $context Tag visitor context.
-	 * @return bool Whether the tag should be tracked in URL metrics.
+	 * @return bool Whether the tag should be tracked in URL Metrics.
 	 */
 	abstract public function __invoke( OD_Tag_Visitor_Context $context ): bool;
 
Index: class-image-prioritizer-video-tag-visitor.php
===================================================================
--- class-image-prioritizer-video-tag-visitor.php	(revision 3189893)
+++ class-image-prioritizer-video-tag-visitor.php	(working copy)
@@ -44,7 +44,7 @@
 	 * @since 0.2.0
 	 *
 	 * @param OD_Tag_Visitor_Context $context Tag visitor context.
-	 * @return bool Whether the tag should be tracked in URL metrics.
+	 * @return bool Whether the tag should be tracked in URL Metrics.
 	 */
 	public function __invoke( OD_Tag_Visitor_Context $context ): bool {
 		$processor = $context->processor;
@@ -96,8 +96,8 @@
 		$xpath = $processor->get_xpath();
 
 		/*
-		 * Obtain maximum width of the element exclusively from the URL metrics group with the widest viewport width,
-		 * which would be desktop. This prevents the situation where if URL metrics have only so far been gathered for
+		 * Obtain maximum width of the element exclusively from the URL Metrics group with the widest viewport width,
+		 * which would be desktop. This prevents the situation where if URL Metrics have only so far been gathered for
 		 * mobile viewports that an excessively-small poster would end up getting served to the first desktop visitor.
 		 */
 		$max_element_width = 0;
@@ -173,10 +173,10 @@
 		$processor = $context->processor;
 
 		/*
-		 * Do not do any lazy-loading if the mobile and desktop viewport groups lack URL metrics. This is important
+		 * Do not do any lazy-loading if the mobile and desktop viewport groups lack URL Metrics. This is important
 		 * because if there is a VIDEO in the initial viewport on desktop but not mobile, if then there are only URL
 		 * metrics collected for mobile then the VIDEO will get lazy-loaded which is good for mobile but for desktop
-		 * it will hurt performance. So this is why it is important to have URL metrics collected for both desktop and
+		 * it will hurt performance. So this is why it is important to have URL Metrics collected for both desktop and
 		 * mobile to verify whether maximum intersectionRatio is accounting for both screen sizes.
 		 */
 		if (
Index: hooks.php
===================================================================
--- hooks.php	(revision 3189893)
+++ hooks.php	(working copy)
@@ -22,7 +22,7 @@
  * @since 0.2.0
  */
 function image_prioritizer_get_lazy_load_script(): string {
-	$script = file_get_contents( __DIR__ . '/lazy-load.js' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- It's a local filesystem path not a remote request.
+	$script = file_get_contents( __DIR__ . sprintf( '/lazy-load%s.js', wp_scripts_get_suffix() ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- It's a local filesystem path not a remote request.
 
 	if ( false === $script ) {
 		return '';
Index: lazy-load.js
===================================================================
--- lazy-load.js	(revision 3189893)
+++ lazy-load.js	(working copy)
@@ -1 +1,42 @@
-const lazyVideoObserver=new IntersectionObserver((t=>{for(const e of t)if(e.isIntersecting){const t=e.target;if(t.hasAttribute("data-original-poster")&&t.setAttribute("poster",t.getAttribute("data-original-poster")),t.hasAttribute("data-original-autoplay")&&t.setAttribute("autoplay","autoplay"),t.hasAttribute("data-original-preload")){const e=t.getAttribute("data-original-preload");"default"===e?t.removeAttribute("preload"):t.setAttribute("preload",e)}lazyVideoObserver.unobserve(t)}}),{rootMargin:"100% 0% 100% 0%",threshold:0}),videos=document.querySelectorAll("video.od-lazy-video");for(const t of videos)lazyVideoObserver.observe(t);
\ No newline at end of file
+const lazyVideoObserver = new IntersectionObserver(
+	( entries ) => {
+		for ( const entry of entries ) {
+			if ( entry.isIntersecting ) {
+				const video = /** @type {HTMLVideoElement} */ entry.target;
+
+				if ( video.hasAttribute( 'data-original-poster' ) ) {
+					video.setAttribute(
+						'poster',
+						video.getAttribute( 'data-original-poster' )
+					);
+				}
+
+				if ( video.hasAttribute( 'data-original-autoplay' ) ) {
+					video.setAttribute( 'autoplay', 'autoplay' );
+				}
+
+				if ( video.hasAttribute( 'data-original-preload' ) ) {
+					const preload = video.getAttribute(
+						'data-original-preload'
+					);
+					if ( 'default' === preload ) {
+						video.removeAttribute( 'preload' );
+					} else {
+						video.setAttribute( 'preload', preload );
+					}
+				}
+
+				lazyVideoObserver.unobserve( video );
+			}
+		}
+	},
+	{
+		rootMargin: '100% 0% 100% 0%',
+		threshold: 0,
+	}
+);
+
+const videos = document.querySelectorAll( 'video.od-lazy-video' );
+for ( const video of videos ) {
+	lazyVideoObserver.observe( video );
+}
Index: load.php
===================================================================
--- load.php	(revision 3189893)
+++ load.php	(working copy)
@@ -2,7 +2,7 @@
 /**
  * Plugin Name: Image Prioritizer
  * Plugin URI: https://github.com/WordPress/performance/tree/trunk/plugins/image-prioritizer
- * Description: Optimizes LCP image loading with <code>fetchpriority=high</code> and applies image lazy-loading by leveraging client-side detection with real user metrics.
+ * Description: Prioritizes the loading of images and videos based on how visible they are to actual visitors; adds <code>fetchpriority</code> and applies lazy-loading.
  * Requires at least: 6.5
  * Requires PHP: 7.2
  * Requires Plugins: optimization-detective
@@ -77,6 +77,24 @@
 			return;
 		}
 
+		if (
+			( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) &&
+			! file_exists( __DIR__ . '/lazy-load.min.js' )
+		) {
+			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
+			trigger_error(
+				esc_html(
+					sprintf(
+						/* translators: 1: File path. 2: CLI command. */
+						'[Image Prioritizer] ' . __( 'Unable to load %1$s. Please make sure you have run %2$s.', 'image-prioritizer' ),
+						'lazy-load.min.js',
+						'`npm install && npm run build:plugin:image-prioritizer`'
+					)
+				),
+				E_USER_ERROR
+			);
+		}
+
 		define( 'IMAGE_PRIORITIZER_VERSION', $version );
 
 		require_once __DIR__ . '/helper.php';
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -7,27 +7,27 @@
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 Tags:         performance, optimization, image, lcp, lazy-load
 
-Optimizes LCP image loading with `fetchpriority=high` and applies image lazy-loading by leveraging client-side detection with real user metrics.
+Prioritizes the loading of images and videos based on how visible they are to actual visitors; adds fetchpriority and applies lazy-loading.
 
 == Description ==
 
-This plugin optimizes the loading of images which are the LCP (Largest Contentful Paint) element, including both `img` elements and elements with CSS background images (where there is a `style` attribute with an `background-image` property). Different breakpoints in a theme's responsive design may result in differing elements being the LCP element. Therefore, the LCP element for each breakpoint is captured so that high-fetchpriority preload links with media queries are added which prioritize loading the LCP image specific to the viewport of the visitor.
+This plugin optimizes the loading of images (and videos) with prioritization, lazy loading, and more accurate image size selection.
 
-In addition to prioritizing the loading of the LCP image, this plugin also optimizes image loading by ensuring that `loading=lazy` is omitted from any image that appears in the initial viewport for any of the breakpoints, which by default include:
+The current optimizations include:
 
-1. 0-320 (small smartphone)
-2. 321-480 (normal smartphone)
-3. 481-576 (phablets)
-4. >576 (desktop)
+1. Ensuring `fetchpriority=high` is only added to an `IMG` when it is the Largest Contentful Paint (LCP) element across all responsive breakpoints.
+2. Adding breakpoint-specific `fetchpriority=high` preload links for the LCP elements which are `IMG` elements or elements with a CSS `background-image` inline style.
+3. Applying lazy-loading to `IMG` tags based on whether they appear in any breakpoint’s initial viewport. (Additionally, [`sizes=auto`](https://make.wordpress.org/core/2024/10/18/auto-sizes-for-lazy-loaded-images-in-wordpress-6-7/) is then also correctly applied.)
+4. Adding `fetchpriority=low` to `IMG` tags which appear in the initial viewport but are not visible, such as when they are subsequent carousel slides.
+5. Reducing the size of the `poster` image of a `VIDEO` from full size to the size appropriate for the maximum width of the video (on desktop).
+6. Lazy-loading `VIDEO` tags by setting the appropriate attributes based on whether they appear in the initial viewport. If a `VIDEO` is the LCP element, it gets `preload=auto`; if it is in an initial viewport, the `preload=metadata` default is left; if it is not in an initial viewport, it gets `preload=none`. Lazy-loaded videos also get initial `preload`, `autoplay`, and `poster` attributes restored when the `VIDEO` is going to enter the viewport.
 
-If an image does not appear in the initial viewport for any of these viewport groups, then `loading=lazy` is added to the `img` element. 
+**This plugin requires the [Optimization Detective](https://wordpress.org/plugins/optimization-detective/) plugin as a dependency.** Please refer to that plugin for additional background on how this plugin works as well as additional developer options.
 
-👉 **Note:** This plugin optimizes pages for actual visitors, and it depends on visitors to optimize pages (since URL metrics need to be collected). As such, you won't see optimizations applied immediately after activating the plugin. And since administrator users are not normal visitors typically, optimizations are not applied for admins by default.
+👉 **Note:** This plugin optimizes pages for actual visitors, and it depends on visitors to optimize pages. As such, you won't see optimizations applied immediately after activating the plugin. Please wait for URL Metrics to be gathered for both mobile and desktop visits. And since administrator users are not normal visitors typically, optimizations are not applied for admins by default.
 
 There are currently **no settings** and no user interface for this plugin since it is designed to work without any configuration.
 
-This plugin requires the [Optimization Detective](https://wordpress.org/plugins/optimization-detective/) plugin as a dependency. Please refer to that plugin for additional background on how this plugin works as well as additional developer options. 
-
 == Installation ==
 
 = Installation from within WordPress =
@@ -62,6 +62,12 @@
 
 == Changelog ==
 
+= n.e.x.t =
+
+**Enhancements**
+
+* Serve unminified scripts when `SCRIPT_DEBUG` is enabled. ([1643](https://github.com/WordPress/performance/pull/1643))
+
 = 0.2.0 =
 
 **Enhancements**

optimization-detective

Important

Stable tag change: 0.7.0 → 0.8.0

svn status:

M       build/web-vitals.asset.php
M       build/web-vitals.js
M       class-od-data-validation-exception.php
M       class-od-element.php
M       class-od-html-tag-processor.php
M       class-od-strict-url-metric.php
M       class-od-tag-visitor-context.php
M       class-od-tag-visitor-registry.php
M       class-od-url-metric-group-collection.php
M       class-od-url-metric-group.php
M       class-od-url-metric.php
M       detect.js
?       detect.min.js
M       detection.php
M       load.php
M       optimization.php
M       readme.txt
M       storage/class-od-storage-lock.php
M       storage/class-od-url-metric-store-request-context.php
M       storage/class-od-url-metrics-post-type.php
M       storage/data.php
M       storage/rest-api.php
svn diff
Index: build/web-vitals.asset.php
===================================================================
--- build/web-vitals.asset.php	(revision 3189893)
+++ build/web-vitals.asset.php	(working copy)
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '4.2.3');
\ No newline at end of file
+<?php return array('dependencies' => array(), 'version' => '4.2.4');
\ No newline at end of file
Index: build/web-vitals.js
===================================================================
--- build/web-vitals.js	(revision 3189893)
+++ build/web-vitals.js	(working copy)
@@ -1 +1 @@
-var e,n,t,r,i,o=-1,a=function(e){addEventListener("pageshow",(function(n){n.persisted&&(o=n.timeStamp,e(n))}),!0)},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r="navigate";return o>=0?r="back-forward-cache":t&&(document.prerendering||u()>0?r="prerender":document.wasDiscarded?r="restore":t.type&&(r=t.type.replace(/_/g,"-"))),{name:e,value:void 0===n?-1:n,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,a;return function(o){n.value>=0&&(o||r)&&((a=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=a,n.rating=function(e,n){return e>n[1]?"poor":e>n[0]?"needs-improvement":"good"}(n.value,t),e(n))}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},p=function(e){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e()}))},v=function(e){var n=!1;return function(){n||(e(),n=!0)}},m=-1,h=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){"hidden"===document.visibilityState&&m>-1&&(m="visibilitychange"===e.type?e.timeStamp:0,T())},y=function(){addEventListener("visibilitychange",g,!0),addEventListener("prerenderingchange",g,!0)},T=function(){removeEventListener("visibilitychange",g,!0),removeEventListener("prerenderingchange",g,!0)},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y()}),0)}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),!0):e()},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("FCP"),o=s("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(!0)))}))}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f("FCP"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f("CLS",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=s("layout-shift",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(!0)})),a((function(){i=0,r=f("CLS",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}))})),setTimeout(t,0))})))},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0)}))},k=function(){return e?A:performance.interactionCount||0},F=function(){"interactionCount"in performance||e||(e=s("event",M,{type:"event",buffered:!0,durationThreshold:0}))},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||"first-input"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}))}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),"hidden"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f("INP"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},c=s("event",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:"first-input",buffered:!0}),p((function(){o(c.takeRecords()),r(!0)})),a((function(){R=k(),D.length=0,x.clear(),i=f("INP"),r=d(e,i,N,n.reportAllChanges)})))})))},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("LCP"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t())}))},c=s("largest-contentful-paint",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=!0,t(!0))}));["keydown","click"].forEach((function(e){addEventListener(e,(function(){return O(m)}),!0)})),p(m),a((function(r){i=f("LCP"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=!0,t(!0)}))}))}}))},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):"complete"!==document.readyState?addEventListener("load",(function(){return e(n)}),!0):setTimeout(n,0)},Q=function(e,n){n=n||{};var t=f("TTFB"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(!0),a((function(){t=f("TTFB",0),(r=d(e,t,J,n.reportAllChanges))(!0)})))}))},U={passive:!0,capture:!0},V=new Date,W=function(e,i){n||(n=i,t=e,r=new Date,Z(removeEventListener),X())},X=function(){if(t>=0&&t<r-V){var e={entryType:"first-input",name:n.type,target:n.target,cancelable:n.cancelable,startTime:n.timeStamp,processingStart:n.timeStamp+t};i.forEach((function(n){n(e)})),i=[]}},Y=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,n){var t=function(){W(e,n),i()},r=function(){i()},i=function(){removeEventListener("pointerup",t,U),removeEventListener("pointercancel",r,U)};addEventListener("pointerup",t,U),addEventListener("pointercancel",r,U)}(n,e):W(n,e)}},Z=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(n){return e(n,Y,U)}))},$=[100,300],ee=function(e,r){r=r||{},C((function(){var o,c=E(),u=f("FID"),l=function(e){e.startTime<c.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),o(!0))},m=function(e){e.forEach(l)},h=s("first-input",m);o=d(e,u,$,r.reportAllChanges),h&&(p(v((function(){m(h.takeRecords()),h.disconnect()}))),a((function(){var a;u=f("FID"),o=d(e,u,$,r.reportAllChanges),i=[],t=-1,n=null,Z(addEventListener),a=l,i.push(a),X()})))}))};export{L as CLSThresholds,b as FCPThresholds,$ as FIDThresholds,N as INPThresholds,_ as LCPThresholds,J as TTFBThresholds,w as onCLS,S as onFCP,ee as onFID,j as onINP,G as onLCP,Q as onTTFB};
\ No newline at end of file
+var e,n,t,r,i,o=-1,a=function(e){addEventListener("pageshow",(function(n){n.persisted&&(o=n.timeStamp,e(n))}),!0)},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r="navigate";o>=0?r="back-forward-cache":t&&(document.prerendering||u()>0?r="prerender":document.wasDiscarded?r="restore":t.type&&(r=t.type.replace(/_/g,"-")));return{name:e,value:void 0===n?-1:n,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?"poor":e>n[0]?"needs-improvement":"good"}(n.value,t),e(n))}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},p=function(e){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e()}))},v=function(e){var n=!1;return function(){n||(e(),n=!0)}},m=-1,h=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){"hidden"===document.visibilityState&&m>-1&&(m="visibilitychange"===e.type?e.timeStamp:0,T())},y=function(){addEventListener("visibilitychange",g,!0),addEventListener("prerenderingchange",g,!0)},T=function(){removeEventListener("visibilitychange",g,!0),removeEventListener("prerenderingchange",g,!0)},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y()}),0)}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),!0):e()},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("FCP"),o=s("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(!0)))}))}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f("FCP"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f("CLS",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=s("layout-shift",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(!0)})),a((function(){i=0,r=f("CLS",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}))})),setTimeout(t,0))})))},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0)}))},k=function(){return e?A:performance.interactionCount||0},F=function(){"interactionCount"in performance||e||(e=s("event",M,{type:"event",buffered:!0,durationThreshold:0}))},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||"first-input"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}))}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),"hidden"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f("INP"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},c=s("event",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:"first-input",buffered:!0}),p((function(){o(c.takeRecords()),r(!0)})),a((function(){R=k(),D.length=0,x.clear(),i=f("INP"),r=d(e,i,N,n.reportAllChanges)})))})))},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("LCP"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t())}))},c=s("largest-contentful-paint",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=!0,t(!0))}));["keydown","click"].forEach((function(e){addEventListener(e,(function(){return O(m)}),{once:!0,capture:!0})})),p(m),a((function(r){i=f("LCP"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=!0,t(!0)}))}))}}))},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):"complete"!==document.readyState?addEventListener("load",(function(){return e(n)}),!0):setTimeout(n,0)},Q=function(e,n){n=n||{};var t=f("TTFB"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(!0),a((function(){t=f("TTFB",0),(r=d(e,t,J,n.reportAllChanges))(!0)})))}))},U={passive:!0,capture:!0},V=new Date,W=function(e,i){n||(n=i,t=e,r=new Date,Z(removeEventListener),X())},X=function(){if(t>=0&&t<r-V){var e={entryType:"first-input",name:n.type,target:n.target,cancelable:n.cancelable,startTime:n.timeStamp,processingStart:n.timeStamp+t};i.forEach((function(n){n(e)})),i=[]}},Y=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,n){var t=function(){W(e,n),i()},r=function(){i()},i=function(){removeEventListener("pointerup",t,U),removeEventListener("pointercancel",r,U)};addEventListener("pointerup",t,U),addEventListener("pointercancel",r,U)}(n,e):W(n,e)}},Z=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(n){return e(n,Y,U)}))},$=[100,300],ee=function(e,r){r=r||{},C((function(){var o,c=E(),u=f("FID"),l=function(e){e.startTime<c.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),o(!0))},m=function(e){e.forEach(l)},h=s("first-input",m);o=d(e,u,$,r.reportAllChanges),h&&(p(v((function(){m(h.takeRecords()),h.disconnect()}))),a((function(){var a;u=f("FID"),o=d(e,u,$,r.reportAllChanges),i=[],t=-1,n=null,Z(addEventListener),a=l,i.push(a),X()})))}))};export{L as CLSThresholds,b as FCPThresholds,$ as FIDThresholds,N as INPThresholds,_ as LCPThresholds,J as TTFBThresholds,w as onCLS,S as onFCP,ee as onFID,j as onINP,G as onLCP,Q as onTTFB};
Index: class-od-data-validation-exception.php
===================================================================
--- class-od-data-validation-exception.php	(revision 3189893)
+++ class-od-data-validation-exception.php	(working copy)
@@ -12,7 +12,7 @@
 }
 
 /**
- * Exception thrown when failing to validate URL metrics data.
+ * Exception thrown when failing to validate URL Metrics data.
  *
  * @since 0.1.0
  * @access private
Index: class-od-element.php
===================================================================
--- class-od-element.php	(revision 3189893)
+++ class-od-element.php	(working copy)
@@ -12,7 +12,7 @@
 }
 
 /**
- * Data for a single element in a URL metric.
+ * Data for a single element in a URL Metric.
  *
  * @phpstan-import-type ElementData from OD_URL_Metric
  * @phpstan-import-type DOMRect from OD_URL_Metric
@@ -33,7 +33,7 @@
 	protected $data;
 
 	/**
-	 * URL metric that this element belongs to.
+	 * URL Metric that this element belongs to.
 	 *
 	 * @since 0.7.0
 	 * @var OD_URL_Metric
@@ -48,7 +48,7 @@
 	 * @phpstan-param ElementData $data
 	 *
 	 * @param array<string, mixed> $data       Element data.
-	 * @param OD_URL_Metric        $url_metric URL metric.
+	 * @param OD_URL_Metric        $url_metric URL Metric.
 	 */
 	public function __construct( array $data, OD_URL_Metric $url_metric ) {
 		$this->data       = $data;
@@ -56,7 +56,7 @@
 	}
 
 	/**
-	 * Gets the URL metric that this element belongs to.
+	 * Gets the URL Metric that this element belongs to.
 	 *
 	 * @since 0.7.0
 	 *
@@ -67,7 +67,7 @@
 	}
 
 	/**
-	 * Gets the group that this element's URL metric is a part of (which may not be any).
+	 * Gets the group that this element's URL Metric is a part of (which may not be any).
 	 *
 	 * @since 0.7.0
 	 *
Index: class-od-html-tag-processor.php
===================================================================
--- class-od-html-tag-processor.php	(revision 3189893)
+++ class-od-html-tag-processor.php	(working copy)
@@ -625,6 +625,8 @@
 	 *
 	 * @since 0.4.0
 	 *
+	 * @phpstan-param callable-string $function_name
+	 *
 	 * @param string $function_name Function name.
 	 * @param string $message       Warning message.
 	 */
Index: class-od-strict-url-metric.php
===================================================================
--- class-od-strict-url-metric.php	(revision 3189893)
+++ class-od-strict-url-metric.php	(working copy)
@@ -14,8 +14,8 @@
 /**
  * Representation of the measurements taken from a single client's visit to a specific URL without additionalProperties allowed.
  *
- * This is used exclusively in the REST API endpoint for capturing new URL metrics to prevent invalid additional data from being
- * submitted in the request. For URL metrics which have been stored the looser OD_URL_Metric class is used instead.
+ * This is used exclusively in the REST API endpoint for capturing new URL Metrics to prevent invalid additional data from being
+ * submitted in the request. For URL Metrics which have been stored the looser OD_URL_Metric class is used instead.
  *
  * @since 0.6.0
  * @access private
Index: class-od-tag-visitor-context.php
===================================================================
--- class-od-tag-visitor-context.php	(revision 3189893)
+++ class-od-tag-visitor-context.php	(working copy)
@@ -30,7 +30,7 @@
 	public $processor;
 
 	/**
-	 * URL metric group collection.
+	 * URL Metric group collection.
 	 *
 	 * @var OD_URL_Metric_Group_Collection
 	 * @readonly
@@ -49,7 +49,7 @@
 	 * Constructor.
 	 *
 	 * @param OD_HTML_Tag_Processor          $processor                   HTML tag processor.
-	 * @param OD_URL_Metric_Group_Collection $url_metric_group_collection URL metric group collection.
+	 * @param OD_URL_Metric_Group_Collection $url_metric_group_collection URL Metric group collection.
 	 * @param OD_Link_Collection             $link_collection             Link collection.
 	 */
 	public function __construct( OD_HTML_Tag_Processor $processor, OD_URL_Metric_Group_Collection $url_metric_group_collection, OD_Link_Collection $link_collection ) {
@@ -65,7 +65,7 @@
 	 * @todo Remove this when no plugins are possibly referring to the url_metrics_group_collection property anymore.
 	 *
 	 * @param string $name Property name.
-	 * @return OD_URL_Metric_Group_Collection URL metric group collection.
+	 * @return OD_URL_Metric_Group_Collection URL Metric group collection.
 	 *
 	 * @throws Error When property is unknown.
 	 */
Index: class-od-tag-visitor-registry.php
===================================================================
--- class-od-tag-visitor-registry.php	(revision 3189893)
+++ class-od-tag-visitor-registry.php	(working copy)
@@ -80,7 +80,7 @@
 	}
 
 	/**
-	 * Returns an iterator for the URL metrics in the group.
+	 * Returns an iterator for the URL Metrics in the group.
 	 *
 	 * @return ArrayIterator<string, TagVisitorCallback> ArrayIterator for tag visitors.
 	 */
@@ -89,9 +89,9 @@
 	}
 
 	/**
-	 * Counts the URL metrics in the group.
+	 * Counts the URL Metrics in the group.
 	 *
-	 * @return int<0, max> URL metric count.
+	 * @return int<0, max> URL Metric count.
 	 */
 	public function count(): int {
 		return count( $this->visitors );
Index: class-od-url-metric-group-collection.php
===================================================================
--- class-od-url-metric-group-collection.php	(revision 3189893)
+++ class-od-url-metric-group-collection.php	(working copy)
@@ -22,13 +22,13 @@
 final class OD_URL_Metric_Group_Collection implements Countable, IteratorAggregate, JsonSerializable {
 
 	/**
-	 * URL metric groups.
+	 * URL Metric groups.
 	 *
 	 * The number of groups corresponds to one greater than the number of
 	 * breakpoints. This is because breakpoints are the dividing line between
-	 * the groups of URL metrics with specific viewport widths. This extends
+	 * the groups of URL Metrics with specific viewport widths. This extends
 	 * even to when there are zero breakpoints: there will still be one group
-	 * in this case, in which every single URL metric is added.
+	 * in this case, in which every single URL Metric is added.
 	 *
 	 * @var OD_URL_Metric_Group[]
 	 * @phpstan-var non-empty-array<OD_URL_Metric_Group>
@@ -54,7 +54,7 @@
 	private $breakpoints;
 
 	/**
-	 * Sample size for URL metrics for a given breakpoint.
+	 * Sample size for URL Metrics for a given breakpoint.
 	 *
 	 * @var int
 	 * @phpstan-var positive-int
@@ -62,9 +62,9 @@
 	private $sample_size;
 
 	/**
-	 * Freshness age (TTL) for a given URL metric.
+	 * Freshness age (TTL) for a given URL Metric.
 	 *
-	 * A freshness age of zero means a URL metric will always be considered stale.
+	 * A freshness age of zero means a URL Metric will always be considered stale.
 	 *
 	 * @var int
 	 * @phpstan-var 0|positive-int
@@ -93,10 +93,10 @@
 	 *
 	 * @throws InvalidArgumentException When an invalid argument is supplied.
 	 *
-	 * @param OD_URL_Metric[] $url_metrics   URL metrics.
+	 * @param OD_URL_Metric[] $url_metrics   URL Metrics.
 	 * @param int[]           $breakpoints   Breakpoints in max widths.
 	 * @param int             $sample_size   Sample size for the maximum number of viewports in a group between breakpoints.
-	 * @param int             $freshness_ttl Freshness age (TTL) for a given URL metric.
+	 * @param int             $freshness_ttl Freshness age (TTL) for a given URL Metric.
 	 */
 	public function __construct( array $url_metrics, array $breakpoints, int $sample_size, int $freshness_ttl ) {
 		// Set breakpoints.
@@ -153,7 +153,7 @@
 		}
 		$this->freshness_ttl = $freshness_ttl;
 
-		// Create groups and the URL metrics to them.
+		// Create groups and the URL Metrics to them.
 		$this->groups = $this->create_groups();
 		foreach ( $url_metrics as $url_metric ) {
 			$this->add_url_metric( $url_metric );
@@ -220,14 +220,14 @@
 	}
 
 	/**
-	 * Adds a new URL metric to a group.
+	 * Adds a new URL Metric to a group.
 	 *
-	 * Once a group reaches the sample size, the oldest URL metric is pushed out.
+	 * Once a group reaches the sample size, the oldest URL Metric is pushed out.
 	 *
 	 * @since 0.1.0
-	 * @throws InvalidArgumentException If there is no group available to add a URL metric to.
+	 * @throws InvalidArgumentException If there is no group available to add a URL Metric to.
 	 *
-	 * @param OD_URL_Metric $new_url_metric New URL metric.
+	 * @param OD_URL_Metric $new_url_metric New URL Metric.
 	 */
 	public function add_url_metric( OD_URL_Metric $new_url_metric ): void {
 		foreach ( $this->groups as $group ) {
@@ -237,7 +237,7 @@
 			}
 		}
 		throw new InvalidArgumentException(
-			esc_html__( 'No group available to add URL metric to.', 'optimization-detective' )
+			esc_html__( 'No group available to add URL Metric to.', 'optimization-detective' )
 		);
 	}
 
@@ -248,7 +248,7 @@
 	 * @throws InvalidArgumentException When there is no group for the provided viewport width. This would only happen if a negative width is provided.
 	 *
 	 * @param int $viewport_width Viewport width.
-	 * @return OD_URL_Metric_Group URL metric group for the viewport width.
+	 * @return OD_URL_Metric_Group URL Metric group for the viewport width.
 	 */
 	public function get_group_for_viewport_width( int $viewport_width ): OD_URL_Metric_Group {
 		if ( array_key_exists( __FUNCTION__, $this->result_cache ) && array_key_exists( $viewport_width, $this->result_cache[ __FUNCTION__ ] ) ) {
@@ -265,7 +265,7 @@
 				esc_html(
 					sprintf(
 						/* translators: %d is viewport width */
-						__( 'No URL metric group found for viewport width: %d', 'optimization-detective' ),
+						__( 'No URL Metric group found for viewport width: %d', 'optimization-detective' ),
 						$viewport_width
 					)
 				)
@@ -277,11 +277,11 @@
 	}
 
 	/**
-	 * Checks whether any group is populated with at least one URL metric.
+	 * Checks whether any group is populated with at least one URL Metric.
 	 *
 	 * @since 0.5.0
 	 *
-	 * @return bool Whether at least one group has some URL metrics.
+	 * @return bool Whether at least one group has some URL Metrics.
 	 */
 	public function is_any_group_populated(): bool {
 		if ( array_key_exists( __FUNCTION__, $this->result_cache ) ) {
@@ -302,10 +302,10 @@
 	}
 
 	/**
-	 * Checks whether every group is populated with at least one URL metric each.
+	 * Checks whether every group is populated with at least one URL Metric each.
 	 *
 	 * They aren't necessarily filled to the sample size, however.
-	 * The URL metrics may also be stale (non-fresh). This method
+	 * The URL Metrics may also be stale (non-fresh). This method
 	 * should be contrasted with the `is_every_group_complete()`
 	 * method below.
 	 *
@@ -312,7 +312,7 @@
 	 * @since 0.1.0
 	 * @see OD_URL_Metric_Group_Collection::is_every_group_complete()
 	 *
-	 * @return bool Whether all groups have some URL metrics.
+	 * @return bool Whether all groups have some URL Metrics.
 	 */
 	public function is_every_group_populated(): bool {
 		if ( array_key_exists( __FUNCTION__, $this->result_cache ) ) {
@@ -442,10 +442,10 @@
 	}
 
 	/**
-	 * Gets all elements from all URL metrics from all groups keyed by the elements' XPaths.
+	 * Gets all elements from all URL Metrics from all groups keyed by the elements' XPaths.
 	 *
 	 * This is an O(n^3) function so its results must be cached. This being said, the number of groups should be 4 (one
-	 * more than the default number of breakpoints) and the number of URL metrics for each group should be 3
+	 * more than the default number of breakpoints) and the number of URL Metrics for each group should be 3
 	 * (the default sample size). Therefore, given the number (n) of visited elements on the page this will only
 	 * end up running n*4*3 times.
 	 *
@@ -475,7 +475,7 @@
 	}
 
 	/**
-	 * Gets the max intersection ratios of all elements across all groups and their captured URL metrics.
+	 * Gets the max intersection ratios of all elements across all groups and their captured URL Metrics.
 	 *
 	 * @since 0.3.0
 	 *
@@ -506,7 +506,7 @@
 	 * Gets all elements' status for whether they are positioned in any initial viewport.
 	 *
 	 * An element is positioned in the initial viewport if its `boundingClientRect.top` is less than the
-	 * `viewport.height` for any of its recorded URL metrics. Note that even though the element may be positioned in the
+	 * `viewport.height` for any of its recorded URL Metrics. Note that even though the element may be positioned in the
 	 * initial viewport, it may not actually be visible. It could be occluded as a latter slide in a carousel in which
 	 * case it will have intersectionRatio of 0. Or the element may not be visible due to it or an ancestor having the
 	 * `visibility:hidden` style, such as in the case of a dropdown navigation menu. When, for example, an IMG element
@@ -542,7 +542,7 @@
 	}
 
 	/**
-	 * Gets the max intersection ratio of an element across all groups and their captured URL metrics.
+	 * Gets the max intersection ratio of an element across all groups and their captured URL Metrics.
 	 *
 	 * @since 0.3.0
 	 *
@@ -566,11 +566,11 @@
 	}
 
 	/**
-	 * Gets URL metrics from all groups flattened into one list.
+	 * Gets URL Metrics from all groups flattened into one list.
 	 *
 	 * @since 0.1.0
 	 *
-	 * @return OD_URL_Metric[] All URL metrics.
+	 * @return OD_URL_Metric[] All URL Metrics.
 	 */
 	public function get_flattened_url_metrics(): array {
 		// The duplication of iterator_to_array is not a mistake. This collection is an
@@ -585,7 +585,7 @@
 	}
 
 	/**
-	 * Returns an iterator for the groups of URL metrics.
+	 * Returns an iterator for the groups of URL Metrics.
 	 *
 	 * @since 0.1.0
 	 *
@@ -596,7 +596,7 @@
 	}
 
 	/**
-	 * Counts the URL metric groups in the collection.
+	 * Counts the URL Metric groups in the collection.
 	 *
 	 * @since 0.1.0
 	 *
Index: class-od-url-metric-group.php
===================================================================
--- class-od-url-metric-group.php	(revision 3189893)
+++ class-od-url-metric-group.php	(working copy)
@@ -12,7 +12,7 @@
 }
 
 /**
- * URL metrics grouped by viewport according to breakpoints.
+ * URL Metrics grouped by viewport according to breakpoints.
  *
  * @implements IteratorAggregate<int, OD_URL_Metric>
  *
@@ -22,7 +22,7 @@
 final class OD_URL_Metric_Group implements IteratorAggregate, Countable, JsonSerializable {
 
 	/**
-	 * URL metrics.
+	 * URL Metrics.
 	 *
 	 * @var OD_URL_Metric[]
 	 */
@@ -45,7 +45,7 @@
 	private $maximum_viewport_width;
 
 	/**
-	 * Sample size for URL metrics for a given breakpoint.
+	 * Sample size for URL Metrics for a given breakpoint.
 	 *
 	 * @var int
 	 * @phpstan-var positive-int
@@ -53,7 +53,7 @@
 	private $sample_size;
 
 	/**
-	 * Freshness age (TTL) for a given URL metric.
+	 * Freshness age (TTL) for a given URL Metric.
 	 *
 	 * @var int
 	 * @phpstan-var 0|positive-int
@@ -82,11 +82,11 @@
 	 *
 	 * @throws InvalidArgumentException If arguments are invalid.
 	 *
-	 * @param OD_URL_Metric[]                     $url_metrics            URL metrics to add to the group.
+	 * @param OD_URL_Metric[]                     $url_metrics            URL Metrics to add to the group.
 	 * @param int                                 $minimum_viewport_width Minimum possible viewport width for the group. Must be zero or greater.
 	 * @param int                                 $maximum_viewport_width Maximum possible viewport width for the group. Must be greater than zero and the minimum viewport width.
 	 * @param int                                 $sample_size            Sample size for the maximum number of viewports in a group between breakpoints.
-	 * @param int                                 $freshness_ttl          Freshness age (TTL) for a given URL metric.
+	 * @param int                                 $freshness_ttl          Freshness age (TTL) for a given URL Metric.
 	 * @param OD_URL_Metric_Group_Collection|null $collection             Collection that this instance belongs to. Optional.
 	 */
 	public function __construct( array $url_metrics, int $minimum_viewport_width, int $maximum_viewport_width, int $sample_size, int $freshness_ttl, ?OD_URL_Metric_Group_Collection $collection = null ) {
@@ -175,16 +175,16 @@
 	}
 
 	/**
-	 * Adds a URL metric to the group.
+	 * Adds a URL Metric to the group.
 	 *
-	 * @throws InvalidArgumentException If the viewport width of the URL metric is not within the min/max bounds of the group.
+	 * @throws InvalidArgumentException If the viewport width of the URL Metric is not within the min/max bounds of the group.
 	 *
-	 * @param OD_URL_Metric $url_metric URL metric.
+	 * @param OD_URL_Metric $url_metric URL Metric.
 	 */
 	public function add_url_metric( OD_URL_Metric $url_metric ): void {
 		if ( ! $this->is_viewport_width_in_range( $url_metric->get_viewport_width() ) ) {
 			throw new InvalidArgumentException(
-				esc_html__( 'URL metric is not in the viewport range for group.', 'optimization-detective' )
+				esc_html__( 'URL Metric is not in the viewport range for group.', 'optimization-detective' )
 			);
 		}
 
@@ -196,10 +196,10 @@
 		$url_metric->set_group( $this );
 		$this->url_metrics[] = $url_metric;
 
-		// If we have too many URL metrics now, remove the oldest ones up to the sample size.
+		// If we have too many URL Metrics now, remove the oldest ones up to the sample size.
 		if ( count( $this->url_metrics ) > $this->sample_size ) {
 
-			// Sort URL metrics in descending order by timestamp.
+			// Sort URL Metrics in descending order by timestamp.
 			usort(
 				$this->url_metrics,
 				static function ( OD_URL_Metric $a, OD_URL_Metric $b ): int {
@@ -207,16 +207,16 @@
 				}
 			);
 
-			// Only keep the sample size of the newest URL metrics.
+			// Only keep the sample size of the newest URL Metrics.
 			$this->url_metrics = array_slice( $this->url_metrics, 0, $this->sample_size );
 		}
 	}
 
 	/**
-	 * Determines whether the URL metric group is complete.
+	 * Determines whether the URL Metric group is complete.
 	 *
-	 * A group is complete if it has the full sample size of URL metrics
-	 * and all of these URL metrics are fresh.
+	 * A group is complete if it has the full sample size of URL Metrics
+	 * and all of these URL Metrics are fresh.
 	 *
 	 * @return bool Whether complete.
 	 */
@@ -246,7 +246,7 @@
 	/**
 	 * Gets the LCP element in the viewport group.
 	 *
-	 * @return OD_Element|null LCP element data or null if not available, either because there are no URL metrics or
+	 * @return OD_Element|null LCP element data or null if not available, either because there are no URL Metrics or
 	 *                          the LCP element type is not supported.
 	 */
 	public function get_lcp_element(): ?OD_Element {
@@ -299,7 +299,7 @@
 
 					$breadcrumb_counts[ $i ] += 1;
 					$breadcrumb_element[ $i ] = $element;
-					break; // We found the LCP element for the URL metric, go to the next URL metric.
+					break; // We found the LCP element for the URL Metric, go to the next URL Metric.
 				}
 			}
 
@@ -321,7 +321,7 @@
 	}
 
 	/**
-	 * Returns an iterator for the URL metrics in the group.
+	 * Returns an iterator for the URL Metrics in the group.
 	 *
 	 * @return ArrayIterator<int, OD_URL_Metric> ArrayIterator for OD_URL_Metric instances.
 	 */
@@ -330,9 +330,9 @@
 	}
 
 	/**
-	 * Counts the URL metrics in the group.
+	 * Counts the URL Metrics in the group.
 	 *
-	 * @return int<0, max> URL metric count.
+	 * @return int<0, max> URL Metric count.
 	 */
 	public function count(): int {
 		return count( $this->url_metrics );
Index: class-od-url-metric.php
===================================================================
--- class-od-url-metric.php	(revision 3189893)
+++ class-od-url-metric.php	(working copy)
@@ -78,7 +78,7 @@
 	 *
 	 * @throws OD_Data_Validation_Exception When the input is invalid.
 	 *
-	 * @param array<string, mixed> $data URL metric data.
+	 * @param array<string, mixed> $data URL Metric data.
 	 */
 	public function __construct( array $data ) {
 		if ( ! isset( $data['uuid'] ) ) {
@@ -125,7 +125,7 @@
 	}
 
 	/**
-	 * Gets the group that this URL metric is a part of (which may not be any).
+	 * Gets the group that this URL Metric is a part of (which may not be any).
 	 *
 	 * @since 0.7.0
 	 *
@@ -136,7 +136,7 @@
 	}
 
 	/**
-	 * Sets the group that this URL metric is a part of.
+	 * Sets the group that this URL Metric is a part of.
 	 *
 	 * @since 0.7.0
 	 *
@@ -154,6 +154,8 @@
 	/**
 	 * Gets JSON schema for URL Metric.
 	 *
+	 * @since 0.1.0
+	 *
 	 * @todo Cache the return value?
 	 *
 	 * @return array<string, mixed> Schema.
@@ -200,7 +202,7 @@
 			'required'             => true,
 			'properties'           => array(
 				'uuid'      => array(
-					'description' => __( 'The UUID for the URL metric.', 'optimization-detective' ),
+					'description' => __( 'The UUID for the URL Metric.', 'optimization-detective' ),
 					'type'        => 'string',
 					'format'      => 'uuid',
 					'required'    => true,
@@ -232,7 +234,7 @@
 					'additionalProperties' => false,
 				),
 				'timestamp' => array(
-					'description' => __( 'Timestamp at which the URL metric was captured.', 'optimization-detective' ),
+					'description' => __( 'Timestamp at which the URL Metric was captured.', 'optimization-detective' ),
 					'type'        => 'number',
 					'required'    => true,
 					'readonly'    => true, // Omit from REST API.
@@ -284,7 +286,7 @@
 		);
 
 		/**
-		 * Filters additional schema properties which should be allowed at the root of a URL metric.
+		 * Filters additional schema properties which should be allowed at the root of a URL Metric.
 		 *
 		 * @since 0.6.0
 		 *
@@ -296,7 +298,7 @@
 		}
 
 		/**
-		 * Filters additional schema properties which should be allowed for an elements item in a URL metric.
+		 * Filters additional schema properties which should be allowed for an element's item in a URL Metric.
 		 *
 		 * @since 0.6.0
 		 *
@@ -407,6 +409,8 @@
 	/**
 	 * Gets UUID.
 	 *
+	 * @since 0.6.0
+	 *
 	 * @return string UUID.
 	 */
 	public function get_uuid(): string {
@@ -416,6 +420,8 @@
 	/**
 	 * Gets URL.
 	 *
+	 * @since 0.1.0
+	 *
 	 * @return string URL.
 	 */
 	public function get_url(): string {
@@ -425,6 +431,8 @@
 	/**
 	 * Gets viewport data.
 	 *
+	 * @since 0.1.0
+	 *
 	 * @return ViewportRect Viewport data.
 	 */
 	public function get_viewport(): array {
@@ -434,6 +442,8 @@
 	/**
 	 * Gets viewport width.
 	 *
+	 * @since 0.1.0
+	 *
 	 * @return int Viewport width.
 	 */
 	public function get_viewport_width(): int {
@@ -443,6 +453,8 @@
 	/**
 	 * Gets timestamp.
 	 *
+	 * @since 0.1.0
+	 *
 	 * @return float Timestamp.
 	 */
 	public function get_timestamp(): float {
@@ -452,6 +464,8 @@
 	/**
 	 * Gets elements.
 	 *
+	 * @since 0.1.0
+	 *
 	 * @return OD_Element[] Elements.
 	 */
 	public function get_elements(): array {
@@ -469,6 +483,8 @@
 	/**
 	 * Specifies data which should be serialized to JSON.
 	 *
+	 * @since 0.1.0
+	 *
 	 * @return Data Exports to be serialized by json_encode().
 	 */
 	public function jsonSerialize(): array {
Index: detect.js
===================================================================
--- detect.js	(revision 3189893)
+++ detect.js	(working copy)
@@ -1 +1,558 @@
-const win=window,doc=win.document,consoleLogPrefix="[Optimization Detective]",storageLockTimeSessionKey="odStorageLockTime";function isStorageLocked(e,t){if(0===t)return!1;try{const n=parseInt(sessionStorage.getItem(storageLockTimeSessionKey));return!isNaN(n)&&e<n+1e3*t}catch(e){return!1}}function setStorageLock(e){try{sessionStorage.setItem(storageLockTimeSessionKey,String(e))}catch(e){}}function log(...e){console.log(consoleLogPrefix,...e)}function warn(...e){console.warn(consoleLogPrefix,...e)}function error(...e){console.error(consoleLogPrefix,...e)}function isViewportNeeded(e,t){let n=!1;for(const{minimumViewportWidth:o,complete:i}of t){if(!(e>=o))break;n=!i}return n}function getCurrentTime(){return Date.now()}function recursiveFreeze(e){for(const t of Object.getOwnPropertyNames(e)){const n=e[t];null!==n&&"object"==typeof n&&recursiveFreeze(n)}Object.freeze(e)}let urlMetric;const reservedRootPropertyKeys=new Set(["url","viewport","elements"]);function getRootData(){const e=structuredClone(urlMetric);return recursiveFreeze(e),e}function extendRootData(e){for(const t of Object.getOwnPropertyNames(e))if(reservedRootPropertyKeys.has(t))throw new Error(`Disallowed setting of key '${t}' on root.`);Object.assign(urlMetric,e)}const elementsByXPath=new Map,reservedElementPropertyKeys=new Set(["isLCP","isLCPCandidate","xpath","intersectionRatio","intersectionRect","boundingClientRect"]);function getElementData(e){const t=elementsByXPath.get(e);if(t){const e=structuredClone(t);return recursiveFreeze(e),e}return null}function extendElementData(e,t){if(!elementsByXPath.has(e))throw new Error(`Unknown element with XPath: ${e}`);for(const e of Object.getOwnPropertyNames(t))if(reservedElementPropertyKeys.has(e))throw new Error(`Disallowed setting of key '${e}' on element.`);const n=elementsByXPath.get(e);Object.assign(n,t)}export default async function detect({serveTime:e,detectionTimeWindow:t,minViewportAspectRatio:n,maxViewportAspectRatio:o,isDebug:i,extensionModuleUrls:r,restApiEndpoint:s,restApiNonce:c,currentUrl:a,urlMetricSlug:l,urlMetricNonce:d,urlMetricGroupStatuses:u,storageLockTTL:g,webVitalsLibrarySrc:w,urlMetricGroupCollection:f}){const m=getCurrentTime();if(i&&log("Stored URL metric group collection:",f),m-e>t)return void(i&&warn("Aborted detection due to being outside detection time window."));if(!isViewportNeeded(win.innerWidth,u))return void(i&&log("No need for URL metrics from the current viewport."));const p=win.innerWidth/win.innerHeight;if(p<n||p>o)return void(i&&warn(`Viewport aspect ratio (${p}) is not in the accepted range of ${n} to ${o}.`));if(await new Promise((e=>{"loading"!==doc.readyState?e():doc.addEventListener("DOMContentLoaded",e,{once:!0})})),await new Promise((e=>{"complete"===doc.readyState?e():win.addEventListener("load",e,{once:!0})})),"function"==typeof requestIdleCallback&&await new Promise((e=>{requestIdleCallback(e)})),isStorageLocked(m,g))return void(i&&warn("Aborted detection due to storage being locked."));if(doc.documentElement.scrollTop>0)return void(i&&warn("Aborted detection since initial scroll position of page is not at the top."));i&&log("Proceeding with detection");const h=new Map;for(const e of r)try{const t=await import(e);h.set(e,t),t.initialize instanceof Function&&t.initialize({isDebug:i})}catch(t){error(`Failed to initialize extension '${e}':`,t)}const y=doc.body.querySelectorAll("[data-od-xpath]"),v=new Map([...y].map((e=>[e,e.dataset.odXpath]))),L=[];let P;function b(){P instanceof IntersectionObserver&&(P.disconnect(),win.removeEventListener("scroll",b))}v.size>0&&(await new Promise((e=>{P=new IntersectionObserver((t=>{for(const e of t)L.push(e);e()}),{root:null,threshold:0});for(const e of v.keys())P.observe(e)})),win.addEventListener("scroll",b,{once:!0,passive:!0}));const{onLCP:R}=await import(w),S=[];await new Promise((e=>{R((t=>{S.push(t),e()}),{reportAllChanges:!0})})),b(),i&&log("Detection is stopping."),urlMetric={url:a,viewport:{width:win.innerWidth,height:win.innerHeight},elements:[]};const C=S.at(-1);for(const e of L){const t=v.get(e.target);if(!t){i&&error("Unable to look up XPath for element");continue}const n={isLCP:e.target===C?.entries[0]?.element,isLCPCandidate:!!S.find((t=>t.entries[0]?.element===e.target)),xpath:t,intersectionRatio:e.intersectionRatio,intersectionRect:e.intersectionRect,boundingClientRect:e.boundingClientRect};urlMetric.elements.push(n),elementsByXPath.set(n.xpath,n)}if(i&&log("Current URL metric:",urlMetric),await new Promise((e=>{win.addEventListener("pagehide",e,{once:!0}),win.addEventListener("pageswap",e,{once:!0}),doc.addEventListener("visibilitychange",(()=>{"hidden"===document.visibilityState&&e()}),{once:!0})})),h.size>0)for(const[e,t]of h.entries())if(t.finalize instanceof Function)try{await t.finalize({isDebug:i,getRootData,getElementData,extendElementData,extendRootData})}catch(t){error(`Unable to finalize module '${e}':`,t)}setStorageLock(getCurrentTime()),i&&log("Sending URL metric:",urlMetric);const D=new URL(s);D.searchParams.set("_wpnonce",c),D.searchParams.set("slug",l),D.searchParams.set("nonce",d),navigator.sendBeacon(D,new Blob([JSON.stringify(urlMetric)],{type:"application/json"})),v.clear()}
\ No newline at end of file
+/**
+ * @typedef {import("web-vitals").LCPMetric} LCPMetric
+ * @typedef {import("./types.ts").ElementData} ElementData
+ * @typedef {import("./types.ts").URLMetric} URLMetric
+ * @typedef {import("./types.ts").URLMetricGroupStatus} URLMetricGroupStatus
+ * @typedef {import("./types.ts").Extension} Extension
+ * @typedef {import("./types.ts").ExtendedRootData} ExtendedRootData
+ * @typedef {import("./types.ts").ExtendedElementData} ExtendedElementData
+ */
+
+const win = window;
+const doc = win.document;
+
+const consoleLogPrefix = '[Optimization Detective]';
+
+const storageLockTimeSessionKey = 'odStorageLockTime';
+
+/**
+ * Checks whether storage is locked.
+ *
+ * @param {number} currentTime    - Current time in milliseconds.
+ * @param {number} storageLockTTL - Storage lock TTL in seconds.
+ * @return {boolean} Whether storage is locked.
+ */
+function isStorageLocked( currentTime, storageLockTTL ) {
+	if ( storageLockTTL === 0 ) {
+		return false;
+	}
+
+	try {
+		const storageLockTime = parseInt(
+			sessionStorage.getItem( storageLockTimeSessionKey )
+		);
+		return (
+			! isNaN( storageLockTime ) &&
+			currentTime < storageLockTime + storageLockTTL * 1000
+		);
+	} catch ( e ) {
+		return false;
+	}
+}
+
+/**
+ * Sets the storage lock.
+ *
+ * @param {number} currentTime - Current time in milliseconds.
+ */
+function setStorageLock( currentTime ) {
+	try {
+		sessionStorage.setItem(
+			storageLockTimeSessionKey,
+			String( currentTime )
+		);
+	} catch ( e ) {}
+}
+
+/**
+ * Logs a message.
+ *
+ * @param {...*} message
+ */
+function log( ...message ) {
+	// eslint-disable-next-line no-console
+	console.log( consoleLogPrefix, ...message );
+}
+
+/**
+ * Logs a warning.
+ *
+ * @param {...*} message
+ */
+function warn( ...message ) {
+	// eslint-disable-next-line no-console
+	console.warn( consoleLogPrefix, ...message );
+}
+
+/**
+ * Logs an error.
+ *
+ * @param {...*} message
+ */
+function error( ...message ) {
+	// eslint-disable-next-line no-console
+	console.error( consoleLogPrefix, ...message );
+}
+
+/**
+ * Checks whether the URL Metric(s) for the provided viewport width is needed.
+ *
+ * @param {number}                 viewportWidth          - Current viewport width.
+ * @param {URLMetricGroupStatus[]} urlMetricGroupStatuses - Viewport group statuses.
+ * @return {boolean} Whether URL Metrics are needed.
+ */
+function isViewportNeeded( viewportWidth, urlMetricGroupStatuses ) {
+	let lastWasLacking = false;
+	for ( const { minimumViewportWidth, complete } of urlMetricGroupStatuses ) {
+		if ( viewportWidth >= minimumViewportWidth ) {
+			lastWasLacking = ! complete;
+		} else {
+			break;
+		}
+	}
+	return lastWasLacking;
+}
+
+/**
+ * Gets the current time in milliseconds.
+ *
+ * @return {number} Current time in milliseconds.
+ */
+function getCurrentTime() {
+	return Date.now();
+}
+
+/**
+ * Recursively freezes an object to prevent mutation.
+ *
+ * @param {Object} obj Object to recursively freeze.
+ */
+function recursiveFreeze( obj ) {
+	for ( const prop of Object.getOwnPropertyNames( obj ) ) {
+		const value = obj[ prop ];
+		if ( null !== value && typeof value === 'object' ) {
+			recursiveFreeze( value );
+		}
+	}
+	Object.freeze( obj );
+}
+
+/**
+ * URL Metric being assembled for submission.
+ *
+ * @type {URLMetric}
+ */
+let urlMetric;
+
+/**
+ * Reserved root property keys.
+ *
+ * @see {URLMetric}
+ * @see {ExtendedElementData}
+ * @type {Set<string>}
+ */
+const reservedRootPropertyKeys = new Set( [ 'url', 'viewport', 'elements' ] );
+
+/**
+ * Gets root URL Metric data.
+ *
+ * @return {URLMetric} URL Metric.
+ */
+function getRootData() {
+	const immutableUrlMetric = structuredClone( urlMetric );
+	recursiveFreeze( immutableUrlMetric );
+	return immutableUrlMetric;
+}
+
+/**
+ * Extends root URL Metric data.
+ *
+ * @param {ExtendedRootData} properties
+ */
+function extendRootData( properties ) {
+	for ( const key of Object.getOwnPropertyNames( properties ) ) {
+		if ( reservedRootPropertyKeys.has( key ) ) {
+			throw new Error( `Disallowed setting of key '${ key }' on root.` );
+		}
+	}
+	Object.assign( urlMetric, properties );
+}
+
+/**
+ * Mapping of XPath to element data.
+ *
+ * @type {Map<string, ElementData>}
+ */
+const elementsByXPath = new Map();
+
+/**
+ * Reserved element property keys.
+ *
+ * @see {ElementData}
+ * @see {ExtendedRootData}
+ * @type {Set<string>}
+ */
+const reservedElementPropertyKeys = new Set( [
+	'isLCP',
+	'isLCPCandidate',
+	'xpath',
+	'intersectionRatio',
+	'intersectionRect',
+	'boundingClientRect',
+] );
+
+/**
+ * Gets element data.
+ *
+ * @param {string} xpath XPath.
+ * @return {ElementData|null} Element data, or null if no element for the XPath exists.
+ */
+function getElementData( xpath ) {
+	const elementData = elementsByXPath.get( xpath );
+	if ( elementData ) {
+		const cloned = structuredClone( elementData );
+		recursiveFreeze( cloned );
+		return cloned;
+	}
+	return null;
+}
+
+/**
+ * Extends element data.
+ *
+ * @param {string}              xpath      XPath.
+ * @param {ExtendedElementData} properties Properties.
+ */
+function extendElementData( xpath, properties ) {
+	if ( ! elementsByXPath.has( xpath ) ) {
+		throw new Error( `Unknown element with XPath: ${ xpath }` );
+	}
+	for ( const key of Object.getOwnPropertyNames( properties ) ) {
+		if ( reservedElementPropertyKeys.has( key ) ) {
+			throw new Error(
+				`Disallowed setting of key '${ key }' on element.`
+			);
+		}
+	}
+	const elementData = elementsByXPath.get( xpath );
+	Object.assign( elementData, properties );
+}
+
+/**
+ * Detects the LCP element, loaded images, client viewport and store for future optimizations.
+ *
+ * @param {Object}                 args                            Args.
+ * @param {string[]}               args.extensionModuleUrls        URLs for extension script modules to import.
+ * @param {number}                 args.minViewportAspectRatio     Minimum aspect ratio allowed for the viewport.
+ * @param {number}                 args.maxViewportAspectRatio     Maximum aspect ratio allowed for the viewport.
+ * @param {boolean}                args.isDebug                    Whether to show debug messages.
+ * @param {string}                 args.restApiEndpoint            URL for where to send the detection data.
+ * @param {string}                 args.currentUrl                 Current URL.
+ * @param {string}                 args.urlMetricSlug              Slug for URL Metric.
+ * @param {number|null}            args.cachePurgePostId           Cache purge post ID.
+ * @param {string}                 args.urlMetricHMAC              HMAC for URL Metric storage.
+ * @param {URLMetricGroupStatus[]} args.urlMetricGroupStatuses     URL Metric group statuses.
+ * @param {number}                 args.storageLockTTL             The TTL (in seconds) for the URL Metric storage lock.
+ * @param {string}                 args.webVitalsLibrarySrc        The URL for the web-vitals library.
+ * @param {Object}                 [args.urlMetricGroupCollection] URL Metric group collection, when in debug mode.
+ */
+export default async function detect( {
+	minViewportAspectRatio,
+	maxViewportAspectRatio,
+	isDebug,
+	extensionModuleUrls,
+	restApiEndpoint,
+	currentUrl,
+	urlMetricSlug,
+	cachePurgePostId,
+	urlMetricHMAC,
+	urlMetricGroupStatuses,
+	storageLockTTL,
+	webVitalsLibrarySrc,
+	urlMetricGroupCollection,
+} ) {
+	if ( isDebug ) {
+		log( 'Stored URL Metric group collection:', urlMetricGroupCollection );
+	}
+
+	// Abort if the current viewport is not among those which need URL Metrics.
+	if ( ! isViewportNeeded( win.innerWidth, urlMetricGroupStatuses ) ) {
+		if ( isDebug ) {
+			log( 'No need for URL Metrics from the current viewport.' );
+		}
+		return;
+	}
+
+	// Abort if the viewport aspect ratio is not in a common range.
+	const aspectRatio = win.innerWidth / win.innerHeight;
+	if (
+		aspectRatio < minViewportAspectRatio ||
+		aspectRatio > maxViewportAspectRatio
+	) {
+		if ( isDebug ) {
+			warn(
+				`Viewport aspect ratio (${ aspectRatio }) is not in the accepted range of ${ minViewportAspectRatio } to ${ maxViewportAspectRatio }.`
+			);
+		}
+		return;
+	}
+
+	// Ensure the DOM is loaded (although it surely already is since we're executing in a module).
+	await new Promise( ( resolve ) => {
+		if ( doc.readyState !== 'loading' ) {
+			resolve();
+		} else {
+			doc.addEventListener( 'DOMContentLoaded', resolve, { once: true } );
+		}
+	} );
+
+	// Wait until the resources on the page have fully loaded.
+	await new Promise( ( resolve ) => {
+		if ( doc.readyState === 'complete' ) {
+			resolve();
+		} else {
+			win.addEventListener( 'load', resolve, { once: true } );
+		}
+	} );
+
+	// Wait yet further until idle.
+	if ( typeof requestIdleCallback === 'function' ) {
+		await new Promise( ( resolve ) => {
+			requestIdleCallback( resolve );
+		} );
+	}
+
+	// TODO: Does this make sense here? Should it be moved up above the isViewportNeeded condition?
+	// As an alternative to this, the od_print_detection_script() function can short-circuit if the
+	// od_is_url_metric_storage_locked() function returns true. However, the downside with that is page caching could
+	// result in metrics missed from being gathered when a user navigates around a site and primes the page cache.
+	if ( isStorageLocked( getCurrentTime(), storageLockTTL ) ) {
+		if ( isDebug ) {
+			warn( 'Aborted detection due to storage being locked.' );
+		}
+		return;
+	}
+
+	// TODO: Does this make sense here?
+	// Prevent detection when page is not scrolled to the initial viewport.
+	if ( doc.documentElement.scrollTop > 0 ) {
+		if ( isDebug ) {
+			warn(
+				'Aborted detection since initial scroll position of page is not at the top.'
+			);
+		}
+		return;
+	}
+
+	if ( isDebug ) {
+		log( 'Proceeding with detection' );
+	}
+
+	/** @type {Map<string, Extension>} */
+	const extensions = new Map();
+	for ( const extensionModuleUrl of extensionModuleUrls ) {
+		try {
+			/** @type {Extension} */
+			const extension = await import( extensionModuleUrl );
+			extensions.set( extensionModuleUrl, extension );
+			// TODO: There should to be a way to pass additional args into the module. Perhaps extensionModuleUrls should be a mapping of URLs to args. It's important to pass webVitalsLibrarySrc to the extension so that onLCP, onCLS, or onINP can be obtained.
+			if ( extension.initialize instanceof Function ) {
+				extension.initialize( { isDebug } );
+			}
+		} catch ( err ) {
+			error(
+				`Failed to initialize extension '${ extensionModuleUrl }':`,
+				err
+			);
+		}
+	}
+
+	const breadcrumbedElements = doc.body.querySelectorAll( '[data-od-xpath]' );
+
+	/** @type {Map<Element, string>} */
+	const breadcrumbedElementsMap = new Map(
+		[ ...breadcrumbedElements ].map(
+			/**
+			 * @param {HTMLElement} element
+			 * @return {[HTMLElement, string]} Tuple of element and its XPath.
+			 */
+			( element ) => [ element, element.dataset.odXpath ]
+		)
+	);
+
+	/** @type {IntersectionObserverEntry[]} */
+	const elementIntersections = [];
+
+	/** @type {?IntersectionObserver} */
+	let intersectionObserver;
+
+	function disconnectIntersectionObserver() {
+		if ( intersectionObserver instanceof IntersectionObserver ) {
+			intersectionObserver.disconnect();
+			win.removeEventListener( 'scroll', disconnectIntersectionObserver ); // Clean up, even though this is registered with once:true.
+		}
+	}
+
+	// Wait for the intersection observer to report back on the initially-visible elements.
+	// Note that the first callback will include _all_ observed entries per <https://github.com/w3c/IntersectionObserver/issues/476>.
+	if ( breadcrumbedElementsMap.size > 0 ) {
+		await new Promise( ( resolve ) => {
+			intersectionObserver = new IntersectionObserver(
+				( entries ) => {
+					for ( const entry of entries ) {
+						elementIntersections.push( entry );
+					}
+					resolve();
+				},
+				{
+					root: null, // To watch for intersection relative to the device's viewport.
+					threshold: 0.0, // As soon as even one pixel is visible.
+				}
+			);
+
+			for ( const element of breadcrumbedElementsMap.keys() ) {
+				intersectionObserver.observe( element );
+			}
+		} );
+
+		// Stop observing as soon as the page scrolls since we only want initial-viewport elements.
+		win.addEventListener( 'scroll', disconnectIntersectionObserver, {
+			once: true,
+			passive: true,
+		} );
+	}
+
+	const { onLCP } = await import( webVitalsLibrarySrc );
+
+	/** @type {LCPMetric[]} */
+	const lcpMetricCandidates = [];
+
+	// Obtain at least one LCP candidate. More may be reported before the page finishes loading.
+	await new Promise( ( resolve ) => {
+		onLCP(
+			( /** @type LCPMetric */ metric ) => {
+				lcpMetricCandidates.push( metric );
+				resolve();
+			},
+			{
+				// This avoids needing to click to finalize LCP candidate. While this is helpful for testing, it also
+				// ensures that we always get an LCP candidate reported. Otherwise, the callback may never fire if the
+				// user never does a click or keydown, per <https://github.com/GoogleChrome/web-vitals/blob/07f6f96/src/onLCP.ts#L99-L107>.
+				reportAllChanges: true,
+			}
+		);
+	} );
+
+	// Stop observing.
+	disconnectIntersectionObserver();
+	if ( isDebug ) {
+		log( 'Detection is stopping.' );
+	}
+
+	urlMetric = {
+		url: currentUrl,
+		viewport: {
+			width: win.innerWidth,
+			height: win.innerHeight,
+		},
+		elements: [],
+	};
+
+	const lcpMetric = lcpMetricCandidates.at( -1 );
+
+	for ( const elementIntersection of elementIntersections ) {
+		const xpath = breadcrumbedElementsMap.get( elementIntersection.target );
+		if ( ! xpath ) {
+			if ( isDebug ) {
+				error( 'Unable to look up XPath for element' );
+			}
+			continue;
+		}
+
+		const element = /** @type {Element|null} */ (
+			lcpMetric?.entries[ 0 ]?.element
+		);
+		const isLCP = elementIntersection.target === element;
+
+		/** @type {ElementData} */
+		const elementData = {
+			isLCP,
+			isLCPCandidate: !! lcpMetricCandidates.find(
+				( lcpMetricCandidate ) => {
+					const candidateElement = /** @type {Element|null} */ (
+						lcpMetricCandidate.entries[ 0 ]?.element
+					);
+					return candidateElement === elementIntersection.target;
+				}
+			),
+			xpath,
+			intersectionRatio: elementIntersection.intersectionRatio,
+			intersectionRect: elementIntersection.intersectionRect,
+			boundingClientRect: elementIntersection.boundingClientRect,
+		};
+
+		urlMetric.elements.push( elementData );
+		elementsByXPath.set( elementData.xpath, elementData );
+	}
+
+	if ( isDebug ) {
+		log( 'Current URL Metric:', urlMetric );
+	}
+
+	// Wait for the page to be hidden.
+	await new Promise( ( resolve ) => {
+		win.addEventListener( 'pagehide', resolve, { once: true } );
+		win.addEventListener( 'pageswap', resolve, { once: true } );
+		doc.addEventListener(
+			'visibilitychange',
+			() => {
+				if ( document.visibilityState === 'hidden' ) {
+					// TODO: This will fire even when switching tabs.
+					resolve();
+				}
+			},
+			{ once: true }
+		);
+	} );
+
+	if ( extensions.size > 0 ) {
+		for ( const [
+			extensionModuleUrl,
+			extension,
+		] of extensions.entries() ) {
+			if ( extension.finalize instanceof Function ) {
+				try {
+					await extension.finalize( {
+						isDebug,
+						getRootData,
+						getElementData,
+						extendElementData,
+						extendRootData,
+					} );
+				} catch ( err ) {
+					error(
+						`Unable to finalize module '${ extensionModuleUrl }':`,
+						err
+					);
+				}
+			}
+		}
+	}
+
+	// Even though the server may reject the REST API request, we still have to set the storage lock
+	// because we can't look at the response when sending a beacon.
+	setStorageLock( getCurrentTime() );
+
+	if ( isDebug ) {
+		log( 'Sending URL Metric:', urlMetric );
+	}
+
+	const url = new URL( restApiEndpoint );
+	url.searchParams.set( 'slug', urlMetricSlug );
+	if ( typeof cachePurgePostId === 'number' ) {
+		url.searchParams.set(
+			'cache_purge_post_id',
+			cachePurgePostId.toString()
+		);
+	}
+	url.searchParams.set( 'hmac', urlMetricHMAC );
+	navigator.sendBeacon(
+		url,
+		new Blob( [ JSON.stringify( urlMetric ) ], {
+			type: 'application/json',
+		} )
+	);
+
+	// Clean up.
+	breadcrumbedElementsMap.clear();
+}
Index: detection.php
===================================================================
--- detection.php	(revision 3189893)
+++ detection.php	(working copy)
@@ -11,30 +11,63 @@
 }
 
 /**
+ * Obtains the ID for a post related to this response so that page caches can be told to invalidate their cache.
+ *
+ * If the queried object for the response is a post, then that post's ID is used. Otherwise, it uses the ID of the first
+ * post in The Loop.
+ *
+ * When the queried object is a post (e.g. is_singular, is_posts_page, is_front_page w/ show_on_front=page), then this
+ * is the perfect match. A page caching plugin will be able to most reliably invalidate the cache for a URL via
+ * this ID if the relevant actions are triggered for the post (e.g. clean_post_cache, save_post, transition_post_status).
+ *
+ * Otherwise, if the response is an archive page or the front page where show_on_front=posts (i.e. is_home), then
+ * there is no singular post object that represents the URL. In this case, we obtain the first post in the main
+ * loop. By triggering the relevant actions for this post ID, page caches will have their best shot at invalidating
+ * the related URLs. Page caching plugins which leverage surrogate keys will be the most reliable here. Otherwise,
+ * caching plugins may just resort to automatically purging the cache for the homepage whenever any post is edited,
+ * which is better than nothing.
+ *
+ * There should not be any situation by default in which a page optimized with Optimization Detective does not have such
+ * a post available for cache purging. As seen in {@see od_can_optimize_response()}, when such a post ID is not
+ * available for cache purging then it returns false, as it also does in another case like if is_404().
+ *
+ * @since n.e.x.t
+ * @access private
+ *
+ * @return int|null Post ID or null if none found.
+ */
+function od_get_cache_purge_post_id(): ?int {
+	$queried_object = get_queried_object();
+	if ( $queried_object instanceof WP_Post ) {
+		return $queried_object->ID;
+	}
+
+	global $wp_query;
+	if (
+		$wp_query instanceof WP_Query
+		&&
+		$wp_query->post_count > 0
+		&&
+		isset( $wp_query->posts[0] )
+		&&
+		$wp_query->posts[0] instanceof WP_Post
+	) {
+		return $wp_query->posts[0]->ID;
+	}
+
+	return null;
+}
+
+/**
  * Prints the script for detecting loaded images and the LCP element.
  *
  * @since 0.1.0
  * @access private
  *
- * @param string                         $slug             URL metrics slug.
- * @param OD_URL_Metric_Group_Collection $group_collection URL metric group collection.
+ * @param string                         $slug             URL Metrics slug.
+ * @param OD_URL_Metric_Group_Collection $group_collection URL Metric group collection.
  */
 function od_get_detection_script( string $slug, OD_URL_Metric_Group_Collection $group_collection ): string {
-	/**
-	 * Filters the time window between serve time and run time in which loading detection is allowed to run.
-	 *
-	 * This is the allowance of milliseconds between when the page was first generated (and perhaps cached) and when the
-	 * detect function on the page is allowed to perform its detection logic and submit the request to store the results.
-	 * This avoids situations in which there is missing URL Metrics in which case a site with page caching which
-	 * also has a lot of traffic could result in a cache stampede.
-	 *
-	 * @since 0.1.0
-	 * @todo The value should probably be something like the 99th percentile of Time To Last Byte (TTLB) for WordPress sites in CrUX.
-	 *
-	 * @param int $detection_time_window Detection time window in milliseconds.
-	 */
-	$detection_time_window = apply_filters( 'od_detection_time_window', 5000 );
-
 	$web_vitals_lib_data = require __DIR__ . '/build/web-vitals.asset.php';
 	$web_vitals_lib_src  = add_query_arg( 'ver', $web_vitals_lib_data['version'], plugin_dir_url( __FILE__ ) . 'build/web-vitals.js' );
 
@@ -47,19 +80,19 @@
 	 */
 	$extension_module_urls = (array) apply_filters( 'od_extension_module_urls', array() );
 
+	$cache_purge_post_id = od_get_cache_purge_post_id();
+
 	$current_url = od_get_current_url();
 	$detect_args = array(
-		'serveTime'              => microtime( true ) * 1000, // In milliseconds for comparison with `Date.now()` in JavaScript.
-		'detectionTimeWindow'    => $detection_time_window,
 		'minViewportAspectRatio' => od_get_minimum_viewport_aspect_ratio(),
 		'maxViewportAspectRatio' => od_get_maximum_viewport_aspect_ratio(),
 		'isDebug'                => WP_DEBUG,
 		'extensionModuleUrls'    => $extension_module_urls,
 		'restApiEndpoint'        => rest_url( OD_REST_API_NAMESPACE . OD_URL_METRICS_ROUTE ),
-		'restApiNonce'           => wp_create_nonce( 'wp_rest' ),
 		'currentUrl'             => $current_url,
 		'urlMetricSlug'          => $slug,
-		'urlMetricNonce'         => od_get_url_metrics_storage_nonce( $slug, $current_url ),
+		'cachePurgePostId'       => od_get_cache_purge_post_id(),
+		'urlMetricHMAC'          => od_get_url_metrics_storage_hmac( $slug, $current_url, $cache_purge_post_id ),
 		'urlMetricGroupStatuses' => array_map(
 			static function ( OD_URL_Metric_Group $group ): array {
 				return array(
@@ -79,7 +112,7 @@
 	return wp_get_inline_script_tag(
 		sprintf(
 			'import detect from %s; detect( %s );',
-			wp_json_encode( add_query_arg( 'ver', OPTIMIZATION_DETECTIVE_VERSION, plugin_dir_url( __FILE__ ) . 'detect.js' ) ),
+			wp_json_encode( add_query_arg( 'ver', OPTIMIZATION_DETECTIVE_VERSION, plugin_dir_url( __FILE__ ) . sprintf( 'detect%s.js', wp_scripts_get_suffix() ) ) ),
 			wp_json_encode( $detect_args )
 		),
 		array( 'type' => 'module' )
Index: load.php
===================================================================
--- load.php	(revision 3189893)
+++ load.php	(working copy)
@@ -5,7 +5,7 @@
  * Description: Provides an API for leveraging real user metrics to detect optimizations to apply on the frontend to improve page performance.
  * Requires at least: 6.5
  * Requires PHP: 7.2
- * Version: 0.7.0
+ * Version: 0.8.0
  * Author: WordPress Performance Team
  * Author URI: https://make.wordpress.org/performance/
  * License: GPLv2 or later
@@ -70,7 +70,7 @@
 	}
 )(
 	'optimization_detective_pending_plugin',
-	'0.7.0',
+	'0.8.0',
 	static function ( string $version ): void {
 		if ( defined( 'OPTIMIZATION_DETECTIVE_VERSION' ) ) {
 			return;
Index: optimization.php
===================================================================
--- optimization.php	(revision 3189893)
+++ optimization.php	(working copy)
@@ -120,7 +120,10 @@
 		// users, additional elements will be present like the script from wp_customize_support_script() which will
 		// interfere with the XPath indices. Note that od_get_normalized_query_vars() is varied by is_user_logged_in()
 		// so membership sites and e-commerce sites will still be able to be optimized for their normal visitors.
-		current_user_can( 'customize' )
+		current_user_can( 'customize' ) ||
+		// Page caching plugins can only reliably be told to invalidate a cached page when a post is available to trigger
+		// the relevant actions on.
+		null !== od_get_cache_purge_post_id()
 	);
 
 	/**
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -2,7 +2,7 @@
 
 Contributors: wordpressdotorg
 Tested up to: 6.7
-Stable tag:   0.7.0
+Stable tag:   0.8.0
 License:      GPLv2 or later
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 Tags:         performance, optimization, rum
@@ -11,8 +11,10 @@
 
 == Description ==
 
-This plugin captures real user metrics about what elements are displayed on the page across a variety of device form factors (e.g. desktop, tablet, and phone) in order to apply loading optimizations which are not possible with WordPress’s current server-side heuristics. This plugin is a dependency which does not provide end-user functionality on its own. For that, please install the dependent plugin [Image Prioritizer](https://wordpress.org/plugins/image-prioritizer/) (among [others](https://github.com/WordPress/performance/labels/%5BPlugin%5D%20Optimization%20Detective) to come from the WordPress Core Performance team).
+This plugin captures real user metrics about what elements are displayed on the page across a variety of device form factors (e.g. desktop, tablet, and phone) in order to apply loading optimizations which are not possible with WordPress’s current server-side heuristics.
 
+This plugin is a dependency which does not provide end-user functionality on its own. For that, please install the dependent plugin [Image Prioritizer](https://wordpress.org/plugins/image-prioritizer/) or [Embed Optimizer](https://wordpress.org/plugins/embed-optimizer/) (among [others](https://github.com/WordPress/performance/labels/%5BPlugin%5D%20Optimization%20Detective) to come from the WordPress Core Performance team).
+
 = Background =
 
 WordPress uses [server-side heuristics](https://make.wordpress.org/core/2023/07/13/image-performance-enhancements-in-wordpress-6-3/) to make educated guesses about which images are likely to be in the initial viewport. Likewise, it uses server-side heuristics to identify a hero image which is likely to be the Largest Contentful Paint (LCP) element. To optimize page loading, it avoids lazy-loading any of these images while also adding `fetchpriority=high` to the hero image. When these heuristics are applied successfully, the LCP metric for page loading can be improved 5-10%. Unfortunately, however, there are limitations to the heuristics that make the correct identification of which image is the LCP element only about 50% effective. See [Analyzing the Core Web Vitals performance impact of WordPress 6.3 in the field](https://make.wordpress.org/core/2023/09/19/analyzing-the-core-web-vitals-performance-impact-of-wordpress-6-3-in-the-field/). For example, it is [common](https://github.com/GoogleChromeLabs/wpp-research/pull/73) for the LCP element to vary between different viewport widths, such as desktop versus mobile. Since WordPress's heuristics are completely server-side it has no knowledge of how the page is actually laid out, and it cannot prioritize loading of images according to the client's viewport width.
@@ -21,11 +23,18 @@
 
 = Technical Foundation =
 
-At the core of Optimization Detective is the “URL Metric”, information about a page according to how it was loaded by a client with a specific viewport width. This includes which elements were visible in the initial viewport and which one was the LCP element. Each URL on a site can have an associated set of these URL Metrics (stored in a custom post type) which are gathered from real users. It gathers a sample of URL Metrics according to common responsive breakpoints (e.g. mobile, tablet, and desktop). When no more URL Metrics are needed for a URL due to the sample size being obtained for the breakpoints, it discontinues serving the JavaScript to gather the metrics (leveraging the [web-vitals.js](https://github.com/GoogleChrome/web-vitals) library). With the URL Metrics in hand, the output-buffered page is sent through the HTML Tag Processor and--when the [Image Prioritizer](https://wordpress.org/plugins/image-prioritizer/) dependent plugin is installed--the images which were the LCP element for various breakpoints will get prioritized with high-priority preload links (along with `fetchpriority=high` on the actual `img` tag when it is the common LCP element across all breakpoints). LCP elements with background images added via inline `background-image` styles are also prioritized with preload links.
+At the core of Optimization Detective is the “URL Metric”, information about a page according to how it was loaded by a client with a specific viewport width. This includes which elements were visible in the initial viewport and which one was the LCP element. The URL Metric data is also extensible. Each URL on a site can have an associated set of these URL Metrics (stored in a custom post type) which are gathered from the visits of real users. It gathers samples of URL Metrics which are grouped according to WordPress's default responsive breakpoints:
 
+1. Mobile: 0-480px
+2. Phablet: 481-600px
+3. Tablet: 601-782px
+4. Desktop: \>782px
+
+When no more URL Metrics are needed for a URL due to the sample size being obtained for the viewport group, it discontinues serving the JavaScript to gather the metrics (leveraging the [web-vitals.js](https://github.com/GoogleChrome/web-vitals) library). With the URL Metrics in hand, the output-buffered page is sent through the HTML Tag Processor and--when the [Image Prioritizer](https://wordpress.org/plugins/image-prioritizer/) dependent plugin is installed--the images which were the LCP element for various breakpoints will get prioritized with high-priority preload links (along with `fetchpriority=high` on the actual `img` tag when it is the common LCP element across all breakpoints). LCP elements with background images added via inline `background-image` styles are also prioritized with preload links.
+
 URL Metrics have a “freshness TTL” after which they will be stale and the JavaScript will be served again to start gathering metrics again to ensure that the right elements continue to get their loading prioritized. When a URL Metrics custom post type hasn't been touched in a while, it is automatically garbage-collected.
 
-👉 **Note:** This plugin optimizes pages for actual visitors, and it depends on visitors to optimize pages (since URL metrics need to be collected). As such, you won't see optimizations applied immediately after activating the plugin (and dependent plugin(s)). And since administrator users are not normal visitors typically, optimizations are not applied for admins by default (but this can be overridden with the `od_can_optimize_response` filter below). URL metrics are not collected for administrators because it is likely that additional elements will be present on the page which are not also shown to non-administrators, meaning the URL metrics could not reliably be reused between them. 
+👉 **Note:** This plugin optimizes pages for actual visitors, and it depends on visitors to optimize pages (since URL Metrics need to be collected). As such, you won't see optimizations applied immediately after activating the plugin (and dependent plugin(s)). And since administrator users are not normal visitors typically, optimizations are not applied for admins by default (but this can be overridden with the `od_can_optimize_response` filter below). URL Metrics are not collected for administrators because it is likely that additional elements will be present on the page which are not also shown to non-administrators, meaning the URL Metrics could not reliably be reused between them.
 
 There are currently **no settings** and no user interface for this plugin since it is designed to work without any configuration.
 
@@ -37,17 +46,44 @@
 
 Fires when the Optimization Detective is initializing. This action is useful for loading extension code that depends on Optimization Detective to be running. The version of the plugin is passed as the sole argument so that if the required version is not present, the callback can short circuit.
 
-**Filter:** `od_breakpoint_max_widths` (default: [480, 600, 782])
+**Action:** `od_register_tag_visitors` (argument: `OD_Tag_Visitor_Registry`)
 
-Filters the breakpoint max widths to group URL metrics for various viewports. Each number represents the maximum width (inclusive) for a given breakpoint. So if there is one number, 480, then this means there will be two viewport groupings, one for 0<=480, and another >480. If instead there were three provided breakpoints (320, 480, 576) then this means there will be four groups:
+Fires to register tag visitors before walking over the document to perform optimizations.
 
- 1. 0-320 (small smartphone)
- 2. 321-480 (normal smartphone)
- 3. 481-576 (phablets)
- 4. >576 (desktop)
+For example, to register a new tag visitor that targets `H1` elements:
 
-The default breakpoints are reused from Gutenberg which appear to be used the most in media queries that affect frontend styles.
+`
+<?php
+add_action(
+	'od_register_tag_visitors',
+	static function ( OD_Tag_Visitor_Registry $registry ) {
+		$registry->register(
+			'my-plugin/h1',
+			static function ( OD_Tag_Visitor_Context $context ): bool {
+				if ( $context->processor->get_tag() !== 'H1' ) {
+					return false;
+				}
+				// Now optimize based on stored URL Metrics in $context->url_metric_group_collection.
+				// ...
 
+				// Returning true causes the tag to be tracked in URL Metrics. If there is no need
+				// for this, as in there is no reference to $context->url_metric_group_collection
+				// in a tag visitor, then this can instead return false.
+				return true;
+			}
+		);
+	}
+);
+`
+
+Refer to [Image Prioritizer](https://github.com/WordPress/performance/tree/trunk/plugins/image-prioritizer) and [Embed Optimizer](https://github.com/WordPress/performance/tree/trunk/plugins/embed-optimizer) for real world examples of how tag visitors are used. Registered tag visitors need only be callables, so in addition to providing a closure you may provide a `callable-string` or even a class which has an `__invoke()` method.
+
+**Filter:** `od_breakpoint_max_widths` (default: `array(480, 600, 782)`)
+
+Filters the breakpoint max widths to group URL Metrics for various viewports. Each number represents the maximum width (inclusive) for a given breakpoint. So if there is one number, 480, then this means there will be two viewport groupings, one for 0\<=480, and another \>480. If instead there are the two breakpoints defined, 480 and 782, then this means there will be three viewport groups of URL Metrics, one for 0\<=480 (i.e. mobile), another 481\<=782 (i.e. phablet/tablet), and another \>782 (i.e. desktop).
+
+These default breakpoints are reused from Gutenberg which appear to be used the most in media queries that affect frontend styles.
+
 **Filter:** `od_can_optimize_response` (default: boolean condition, see below)
 
 Filters whether the current response can be optimized. By default, detection and optimization are only performed when:
@@ -67,7 +103,7 @@
 
 **Filter:** `od_url_metrics_breakpoint_sample_size` (default: 3)
 
-Filters the sample size for a breakpoint's URL metrics on a given URL. The sample size must be greater than zero. During development, it may be helpful to reduce the sample size to 1:
+Filters the sample size for a breakpoint's URL Metrics on a given URL. The sample size must be greater than zero. During development, it may be helpful to reduce the sample size to 1:
 
 `
 <?php
@@ -76,7 +112,7 @@
 } );
 `
 
-**Filter:** `od_url_metric_storage_lock_ttl` (default: 1 minute)
+**Filter:** `od_url_metric_storage_lock_ttl` (default: 1 minute in seconds)
 
 Filters how long a given IP is locked from submitting another metric-storage REST API request. Filtering the TTL to zero will disable any metric storage locking. This is useful, for example, to disable locking when a user is logged-in with code like the following:
 
@@ -87,9 +123,9 @@
 } );
 `
 
-**Filter:** `od_url_metric_freshness_ttl` (default: 1 day)
+**Filter:** `od_url_metric_freshness_ttl` (default: 1 day in seconds)
 
-Filters the freshness age (TTL) for a given URL metric. The freshness TTL must be at least zero, in which it considers URL metrics to always be stale. In practice, the value should be at least an hour. During development, this can be useful to set to zero:
+Filters the freshness age (TTL) for a given URL Metric. The freshness TTL must be at least zero, in which it considers URL Metrics to always be stale. In practice, the value should be at least an hour. During development, this can be useful to set to zero:
 
 `
 <?php
@@ -96,23 +132,17 @@
 add_filter( 'od_url_metric_freshness_ttl', '__return_zero' );
 `
 
-**Filter:** `od_detection_time_window` (default: 5 seconds)
-
-Filters the time window between serve time and run time in which loading detection is allowed to run. This amount is the allowance between when the page was first generated (and perhaps cached) and when the detect function on the page is allowed to perform its detection logic and submit the request to store the results. This avoids situations in which there are missing URL Metrics in which case a site with page caching which also has a lot of traffic could result in a cache stampede.
-
 **Filter:** `od_minimum_viewport_aspect_ratio` (default: 0.4)
 
-Filters the minimum allowed viewport aspect ratio for URL metrics.
+Filters the minimum allowed viewport aspect ratio for URL Metrics.
 
-The 0.4 value is intended to accommodate the phone with the greatest known aspect
-ratio at 21:9 when rotated 90 degrees to 9:21 (0.429).
+The 0.4 value is intended to accommodate the phone with the greatest known aspect ratio at 21:9 when rotated 90 degrees to 9:21 (0.429).
 
 **Filter:** `od_maximum_viewport_aspect_ratio` (default: 2.5)
 
-Filters the maximum allowed viewport aspect ratio for URL metrics.
+Filters the maximum allowed viewport aspect ratio for URL Metrics.
 
-The 2.5 value is intended to accommodate the phone with the greatest known aspect
-ratio at 21:9 (2.333).
+The 2.5 value is intended to accommodate the phone with the greatest known aspect ratio at 21:9 (2.333).
 
 During development when you have the DevTools console open, for example, the viewport aspect ratio will be wider than normal. In this case, you may want to increase the maximum aspect ratio:
 
@@ -125,8 +155,82 @@
 
 **Filter:** `od_template_output_buffer` (default: the HTML response)
 
-Filters the template output buffer prior to sending to the client. This filter is added to implement [#43258](https://core.trac.wordpress.org/ticket/43258) in WordPress core.
+Filters the template output buffer prior to sending to the client. This filter is added to implement [\#43258](https://core.trac.wordpress.org/ticket/43258) in WordPress core.
 
+**Filter:** `od_url_metric_schema_element_item_additional_properties` (default: empty array)
+
+Filters additional schema properties which should be allowed for an element's item in a URL Metric.
+
+For example to add a `resizedBoundingClientRect` property:
+
+`
+<?php
+add_filter(
+	'od_url_metric_schema_element_item_additional_properties',
+	static function ( array $additional_properties ): array {
+		$additional_properties['resizedBoundingClientRect'] = array(
+			'type'       => 'object',
+			'properties' => array_fill_keys(
+				array(
+					'width',
+					'height',
+					'x',
+					'y',
+					'top',
+					'right',
+					'bottom',
+					'left',
+				),
+				array(
+					'type'     => 'number',
+					'required' => true,
+				)
+			),
+		);
+		return $additional_properties;
+	}
+);
+`
+
+See also [example usage](https://github.com/WordPress/performance/blob/6bb8405c5c446e3b66c2bfa3ae03ba61b188bca2/plugins/embed-optimizer/hooks.php#L81-L110) in Embed Optimizer.
+
+**Filter:** `od_url_metric_schema_root_additional_properties` (default: empty array)
+
+Filters additional schema properties which should be allowed at the root of a URL Metric.
+
+The usage here is the same as the previous filter, except it allows new properties to be added to the root of the URL Metric and not just to one of the object items in the `elements` property.
+
+**Filter:** `od_extension_module_urls` (default: empty array of strings)
+
+Filters the list of extension script module URLs to import when performing detection.
+
+For example:
+
+`
+<?php
+add_filter(
+	'od_extension_module_urls',
+	static function ( array $extension_module_urls ): array {
+		$extension_module_urls[] = add_query_arg( 'ver', '1.0', plugin_dir_url( __FILE__ ) . 'detect.js' );
+		return $extension_module_urls;
+	}
+);
+`
+
+See also [example usage](https://github.com/WordPress/performance/blob/6bb8405c5c446e3b66c2bfa3ae03ba61b188bca2/plugins/embed-optimizer/hooks.php#L128-L144) in Embed Optimizer. Note in particular the structure of the plugin’s [detect.js](https://github.com/WordPress/performance/blob/trunk/plugins/embed-optimizer/detect.js) script module, how it exports `initialize` and `finalize` functions which Optimization Detective then calls when the page loads and when the page unloads, at which time the URL Metric is constructed and sent to the server for storage. Refer also to the [TypeScript type definitions](https://github.com/WordPress/performance/blob/trunk/plugins/optimization-detective/types.ts).
+
+**Action:** `od_url_metric_stored` (argument: `OD_URL_Metric_Store_Request_Context`)
+
+Fires whenever a URL Metric was successfully stored.
+
+The supplied context object includes these properties:
+
+* `$request`: The `WP_REST_Request` for storing the URL Metric.
+* `$post_id`: The post ID for the `od_url_metric` post.
+* `$url_metric`: The newly-stored URL Metric.
+* `$url_metric_group`: The viewport group that the URL Metric was added to.
+* `$url_metric_group_collection`: The `OD_URL_Metric_Group_Collection` instance to which the URL Metric was added.
+
 == Installation ==
 
 = Installation from within WordPress =
@@ -161,11 +265,17 @@
 
 == Changelog ==
 
+= n.e.x.t =
+
+**Enhancements**
+
+* Serve unminified scripts when `SCRIPT_DEBUG` is enabled. ([1643](https://github.com/WordPress/performance/pull/1643))
+
 = 0.7.0 =
 
 **Enhancements**
 
-* Send gathered URL metric data when the page is hidden/unloaded as opposed to once the page has loaded; this enables the ability to track layout shifts and INP scores over the life of the page. ([1373](https://github.com/WordPress/performance/pull/1373))
+* Send gathered URL Metric data when the page is hidden/unloaded as opposed to once the page has loaded; this enables the ability to track layout shifts and INP scores over the life of the page. ([1373](https://github.com/WordPress/performance/pull/1373))
 * Introduce client-side extensions in the form of script modules which are loaded when the detection logic runs. ([1373](https://github.com/WordPress/performance/pull/1373))
 * Add an `od_init` action for extensions to load their code. ([1373](https://github.com/WordPress/performance/pull/1373))
 * Introduce `OD_Element` class and improve PHP API. ([1585](https://github.com/WordPress/performance/pull/1585))
@@ -180,9 +290,9 @@
 
 **Enhancements**
 
-* Allow URL metric schema to be extended. ([1492](https://github.com/WordPress/performance/pull/1492))
+* Allow URL Metric schema to be extended. ([1492](https://github.com/WordPress/performance/pull/1492))
 * Clarify docs around a tag visitor's boolean return value. ([1479](https://github.com/WordPress/performance/pull/1479))
-* Include UUID with each URL metric. ([1489](https://github.com/WordPress/performance/pull/1489))
+* Include UUID with each URL Metric. ([1489](https://github.com/WordPress/performance/pull/1489))
 * Introduce get_cursor_move_count() to use instead of get_seek_count() and get_next_token_count(). ([1478](https://github.com/WordPress/performance/pull/1478))
 
 **Bug Fixes**
@@ -224,11 +334,11 @@
 
 **Enhancements**
 
-* Log URL metrics group collection to console when debugging is enabled (`WP_DEBUG` is true). ([1295](https://github.com/WordPress/performance/pull/1295))
+* Log URL Metrics group collection to console when debugging is enabled (`WP_DEBUG` is true). ([1295](https://github.com/WordPress/performance/pull/1295))
 
 **Bug Fixes**
 
-* Include non-intersecting elements in URL metrics to fix lazy-load optimization. ([1293](https://github.com/WordPress/performance/pull/1293))
+* Include non-intersecting elements in URL Metrics to fix lazy-load optimization. ([1293](https://github.com/WordPress/performance/pull/1293))
 
 = 0.3.0 =
 
Index: storage/class-od-storage-lock.php
===================================================================
--- storage/class-od-storage-lock.php	(revision 3189893)
+++ storage/class-od-storage-lock.php	(working copy)
@@ -12,7 +12,7 @@
 }
 
 /**
- * Class containing logic for locking storage for new URL metrics.
+ * Class containing logic for locking storage for new URL Metrics.
  *
  * @since 0.1.0
  * @access private
@@ -20,7 +20,7 @@
 final class OD_Storage_Lock {
 
 	/**
-	 * Gets the TTL (in seconds) for the URL metric storage lock.
+	 * Gets the TTL (in seconds) for the URL Metric storage lock.
 	 *
 	 * @since 0.1.0
 	 * @access private
@@ -48,7 +48,7 @@
 	}
 
 	/**
-	 * Gets transient key for locking URL metric storage (for the current IP).
+	 * Gets transient key for locking URL Metric storage (for the current IP).
 	 *
 	 * @todo Should the URL be included in the key? Or should a user only be allowed to store one metric?
 	 * @return string Transient key.
@@ -59,7 +59,7 @@
 	}
 
 	/**
-	 * Sets URL metric storage lock (for the current IP).
+	 * Sets URL Metric storage lock (for the current IP).
 	 *
 	 * If the storage lock TTL is greater than zero, then a transient is set with the current timestamp and expiring at TTL
 	 * seconds. Otherwise, if the current TTL is zero, then any transient is deleted.
@@ -78,7 +78,7 @@
 	}
 
 	/**
-	 * Checks whether URL metric storage is locked (for the current IP).
+	 * Checks whether URL Metric storage is locked (for the current IP).
 	 *
 	 * @since 0.1.0
 	 * @access private
Index: storage/class-od-url-metric-store-request-context.php
===================================================================
--- storage/class-od-url-metric-store-request-context.php	(revision 3189893)
+++ storage/class-od-url-metric-store-request-context.php	(working copy)
@@ -12,7 +12,7 @@
 }
 
 /**
- * Context for when a URL metric is successfully stored via the REST API.
+ * Context for when a URL Metric is successfully stored via the REST API.
  *
  * @since 0.7.0
  * @access private
@@ -28,7 +28,7 @@
 	public $request;
 
 	/**
-	 * ID for the URL metric post.
+	 * ID for the URL Metric post.
 	 *
 	 * @var int
 	 * @readonly
@@ -36,7 +36,7 @@
 	public $post_id;
 
 	/**
-	 * URL metric group collection.
+	 * URL Metric group collection.
 	 *
 	 * @var OD_URL_Metric_Group_Collection
 	 * @readonly
@@ -44,7 +44,7 @@
 	public $url_metric_group_collection;
 
 	/**
-	 * URL metric group.
+	 * URL Metric group.
 	 *
 	 * @var OD_URL_Metric_Group
 	 * @readonly
@@ -52,7 +52,7 @@
 	public $url_metric_group;
 
 	/**
-	 * URL metric.
+	 * URL Metric.
 	 *
 	 * @var OD_URL_Metric
 	 * @readonly
@@ -65,10 +65,10 @@
 	 * @phpstan-param WP_REST_Request<array<string, mixed>> $request
 	 *
 	 * @param WP_REST_Request                $request                     REST API request.
-	 * @param int                            $post_id                     ID for the URL metric post.
-	 * @param OD_URL_Metric_Group_Collection $url_metric_group_collection URL metric group collection.
-	 * @param OD_URL_Metric_Group            $url_metric_group            URL metric group.
-	 * @param OD_URL_Metric                  $url_metric                  URL metric.
+	 * @param int                            $post_id                     ID for the URL Metric post.
+	 * @param OD_URL_Metric_Group_Collection $url_metric_group_collection URL Metric group collection.
+	 * @param OD_URL_Metric_Group            $url_metric_group            URL Metric group.
+	 * @param OD_URL_Metric                  $url_metric                  URL Metric.
 	 */
 	public function __construct( WP_REST_Request $request, int $post_id, OD_URL_Metric_Group_Collection $url_metric_group_collection, OD_URL_Metric_Group $url_metric_group, OD_URL_Metric $url_metric ) {
 		$this->request                     = $request;
Index: storage/class-od-url-metrics-post-type.php
===================================================================
--- storage/class-od-url-metrics-post-type.php	(revision 3189893)
+++ storage/class-od-url-metrics-post-type.php	(working copy)
@@ -51,7 +51,7 @@
 	}
 
 	/**
-	 * Registers post type for URL metrics storage.
+	 * Registers post type for URL Metrics storage.
 	 *
 	 * This the configuration for this post type is similar to the oembed_cache in core.
 	 *
@@ -78,11 +78,11 @@
 	}
 
 	/**
-	 * Gets URL metrics post.
+	 * Gets URL Metrics post.
 	 *
 	 * @since 0.1.0
 	 *
-	 * @param string $slug URL metrics slug.
+	 * @param string $slug URL Metrics slug.
 	 * @return WP_Post|null Post object if exists.
 	 */
 	public static function get_post( string $slug ): ?WP_Post {
@@ -109,16 +109,20 @@
 	}
 
 	/**
-	 * Parses post content in URL metrics post.
+	 * Parses post content in URL Metrics post.
 	 *
 	 * @since 0.1.0
 	 *
-	 * @param WP_Post $post URL metrics post.
-	 * @return OD_URL_Metric[] URL metrics.
+	 * @param WP_Post $post URL Metrics post.
+	 * @return OD_URL_Metric[] URL Metrics.
 	 */
 	public static function get_url_metrics_from_post( WP_Post $post ): array {
 		$this_function = __METHOD__;
 		$trigger_error = static function ( string $message, int $error_level = E_USER_NOTICE ) use ( $this_function ): void {
+			// Default to E_USER_NOTICE.
+			if ( ! in_array( $error_level, array( E_USER_NOTICE, E_USER_WARNING, E_USER_ERROR, E_USER_DEPRECATED ), true ) ) {
+				$error_level = E_USER_NOTICE;
+			}
 			wp_trigger_error( $this_function, esc_html( $message ), $error_level );
 		};
 
@@ -171,7 +175,7 @@
 									$e->getMessage() . $suffix
 								),
 								// This is not a warning because schema changes will happen, and so it is expected
-								// that this will result in existing URL metrics being invalidated.
+								// that this will result in existing URL Metrics being invalidated.
 								E_USER_NOTICE
 							);
 
@@ -185,13 +189,13 @@
 	}
 
 	/**
-	 * Stores URL metric by merging it with the other URL metrics which share the same normalized query vars.
+	 * Stores URL Metric by merging it with the other URL Metrics which share the same normalized query vars.
 	 *
 	 * @since 0.1.0
 	 * @todo There is duplicate logic here with od_handle_rest_request().
 	 *
 	 * @param string        $slug           Slug (hash of normalized query vars).
-	 * @param OD_URL_Metric $new_url_metric New URL metric.
+	 * @param OD_URL_Metric $new_url_metric New URL Metric.
 	 * @return int|WP_Error Post ID or WP_Error otherwise.
 	 */
 	public static function store_url_metric( string $slug, OD_URL_Metric $new_url_metric ) {
Index: storage/data.php
===================================================================
--- storage/data.php	(revision 3189893)
+++ storage/data.php	(working copy)
@@ -11,9 +11,9 @@
 }
 
 /**
- * Gets the freshness age (TTL) for a given URL metric.
+ * Gets the freshness age (TTL) for a given URL Metric.
  *
- * When a URL metric expires it is eligible to be replaced by a newer one if its viewport lies within the same breakpoint.
+ * When a URL Metric expires it is eligible to be replaced by a newer one if its viewport lies within the same breakpoint.
  *
  * @since 0.1.0
  * @access private
@@ -22,9 +22,9 @@
  */
 function od_get_url_metric_freshness_ttl(): int {
 	/**
-	 * Filters the freshness age (TTL) for a given URL metric.
+	 * Filters the freshness age (TTL) for a given URL Metric.
 	 *
-	 * The freshness TTL must be at least zero, in which it considers URL metrics to always be stale.
+	 * The freshness TTL must be at least zero, in which it considers URL Metrics to always be stale.
 	 * In practice, the value should be at least an hour.
 	 *
 	 * @since 0.1.0
@@ -54,7 +54,7 @@
 /**
  * Gets the normalized query vars for the current request.
  *
- * This is used as a cache key for stored URL metrics.
+ * This is used as a cache key for stored URL Metrics.
  *
  * TODO: For non-singular requests, consider adding the post IDs from The Loop to ensure publishing a new post will invalidate the cache.
  *
@@ -77,7 +77,7 @@
 		);
 	}
 
-	// Vary URL metrics by whether the user is logged in since additional elements may be present.
+	// Vary URL Metrics by whether the user is logged in since additional elements may be present.
 	if ( is_user_logged_in() ) {
 		$normalized_query_vars['user_logged_in'] = true;
 	}
@@ -124,7 +124,7 @@
 }
 
 /**
- * Gets slug for URL metrics.
+ * Gets slug for URL Metrics.
  *
  * A slug is the hash of the normalized query vars.
  *
@@ -141,55 +141,57 @@
 }
 
 /**
- * Computes nonce for storing URL metrics for a specific slug.
+ * Computes HMAC for storing URL Metrics for a specific slug.
  *
- * This is used in the REST API to authenticate the storage of new URL metrics from a given URL.
+ * This is used in the REST API to authenticate the storage of new URL Metrics from a given URL.
  *
- * @since 0.1.0
+ * @since n.e.x.t
  * @access private
  *
- * @see wp_create_nonce()
- * @see od_verify_url_metrics_storage_nonce()
+ * @see od_verify_url_metrics_storage_hmac()
  * @see od_get_url_metrics_slug()
+ * @todo This should also include an ETag as a parameter. See <https://github.com/WordPress/performance/issues/1466>.
  *
- * @param string $slug Slug (hash of normalized query vars).
- * @param string $url  URL.
- * @return string Nonce.
+ * @param string   $slug                Slug (hash of normalized query vars).
+ * @param string   $url                 URL.
+ * @param int|null $cache_purge_post_id Cache purge post ID.
+ * @return string HMAC.
  */
-function od_get_url_metrics_storage_nonce( string $slug, string $url ): string {
-	return wp_create_nonce( "store_url_metrics:$slug:$url" );
+function od_get_url_metrics_storage_hmac( string $slug, string $url, ?int $cache_purge_post_id = null ): string {
+	$action = "store_url_metric:$slug:$url:$cache_purge_post_id";
+	return wp_hash( $action, 'nonce' );
 }
 
 /**
- * Verifies nonce for storing URL metrics for a specific slug.
+ * Verifies HMAC for storing URL Metrics for a specific slug.
  *
- * @since 0.1.0
+ * @since n.e.x.t
  * @access private
  *
- * @see wp_verify_nonce()
- * @see od_get_url_metrics_storage_nonce()
+ * @see od_get_url_metrics_storage_hmac()
  * @see od_get_url_metrics_slug()
  *
- * @param string $nonce Nonce.
- * @param string $slug  Slug (hash of normalized query vars).
- * @param String $url   URL.
- * @return bool Whether the nonce is valid.
+ * @param string   $hmac                HMAC.
+ * @param string   $slug                Slug (hash of normalized query vars).
+ * @param String   $url                 URL.
+ * @param int|null $cache_purge_post_id Cache purge post ID.
+ * @return bool Whether the HMAC is valid.
  */
-function od_verify_url_metrics_storage_nonce( string $nonce, string $slug, string $url ): bool {
-	return (bool) wp_verify_nonce( $nonce, "store_url_metrics:$slug:$url" );
+function od_verify_url_metrics_storage_hmac( string $hmac, string $slug, string $url, ?int $cache_purge_post_id = null ): bool {
+	return hash_equals( od_get_url_metrics_storage_hmac( $slug, $url, $cache_purge_post_id ), $hmac );
 }
 
 /**
- * Gets the minimum allowed viewport aspect ratio for URL metrics.
+ * Gets the minimum allowed viewport aspect ratio for URL Metrics.
  *
  * @since 0.6.0
  * @access private
  *
- * @return float Minimum viewport aspect ratio for URL metrics.
+ * @return float Minimum viewport aspect ratio for URL Metrics.
  */
 function od_get_minimum_viewport_aspect_ratio(): float {
 	/**
-	 * Filters the minimum allowed viewport aspect ratio for URL metrics.
+	 * Filters the minimum allowed viewport aspect ratio for URL Metrics.
 	 *
 	 * The 0.4 default value is intended to accommodate the phone with the greatest known aspect
 	 * ratio at 21:9 when rotated 90 degrees to 9:21 (0.429).
@@ -202,16 +204,16 @@
 }
 
 /**
- * Gets the maximum allowed viewport aspect ratio for URL metrics.
+ * Gets the maximum allowed viewport aspect ratio for URL Metrics.
  *
  * @since 0.6.0
  * @access private
  *
- * @return float Maximum viewport aspect ratio for URL metrics.
+ * @return float Maximum viewport aspect ratio for URL Metrics.
  */
 function od_get_maximum_viewport_aspect_ratio(): float {
 	/**
-	 * Filters the maximum allowed viewport aspect ratio for URL metrics.
+	 * Filters the maximum allowed viewport aspect ratio for URL Metrics.
 	 *
 	 * The 2.5 default value is intended to accommodate the phone with the greatest known aspect
 	 * ratio at 21:9 (2.333).
@@ -224,7 +226,7 @@
 }
 
 /**
- * Gets the breakpoint max widths to group URL metrics for various viewports.
+ * Gets the breakpoint max widths to group URL Metrics for various viewports.
  *
  * Each number represents the maximum width (inclusive) for a given breakpoint. So if there is one number, 480, then
  * this means there will be two viewport groupings, one for 0<=480, and another >480. If instead there were three
@@ -288,7 +290,7 @@
 			return $breakpoint;
 		},
 		/**
-		 * Filters the breakpoint max widths to group URL metrics for various viewports.
+		 * Filters the breakpoint max widths to group URL Metrics for various viewports.
 		 *
 		 * A breakpoint must be greater than zero and less than PHP_INT_MAX. This array may be empty in which case there
 		 * are no responsive breakpoints and all URL Metrics are collected in a single group.
@@ -306,11 +308,11 @@
 }
 
 /**
- * Gets the sample size for a breakpoint's URL metrics on a given URL.
+ * Gets the sample size for a breakpoint's URL Metrics on a given URL.
  *
- * A breakpoint divides URL metrics for viewports which are smaller and those which are larger. Given the default
+ * A breakpoint divides URL Metrics for viewports which are smaller and those which are larger. Given the default
  * sample size of 3 and there being just a single breakpoint (480) by default, for a given URL, there would be a maximum
- * total of 6 URL metrics stored for a given URL: 3 for mobile and 3 for desktop.
+ * total of 6 URL Metrics stored for a given URL: 3 for mobile and 3 for desktop.
  *
  * @since 0.1.0
  * @access private
@@ -319,7 +321,7 @@
  */
 function od_get_url_metrics_breakpoint_sample_size(): int {
 	/**
-	 * Filters the sample size for a breakpoint's URL metrics on a given URL.
+	 * Filters the sample size for a breakpoint's URL Metrics on a given URL.
 	 *
 	 * The sample size must be greater than zero.
 	 *
Index: storage/rest-api.php
===================================================================
--- storage/rest-api.php	(revision 3189893)
+++ storage/rest-api.php	(working copy)
@@ -18,7 +18,7 @@
 const OD_REST_API_NAMESPACE = 'optimization-detective/v1';
 
 /**
- * Route for storing a URL metric.
+ * Route for storing a URL Metric.
  *
  * Note the `:store` art of the endpoint follows Google's guidance in AIP-136 for the use of the POST method in a way
  * that does not strictly follow the standard usage. Namely, submitting a POST request to this endpoint will either
@@ -30,7 +30,7 @@
 const OD_URL_METRICS_ROUTE = '/url-metrics:store';
 
 /**
- * Registers endpoint for storage of URL metric.
+ * Registers endpoint for storage of URL Metric.
  *
  * @since 0.1.0
  * @access private
@@ -37,23 +37,29 @@
  */
 function od_register_endpoint(): void {
 
+	// The slug and cache_purge_post_id args are further validated via the validate_callback for the 'hmac' parameter,
+	// they are provided as input with the 'url' argument to create the HMAC by the server.
 	$args = array(
-		'slug'  => array(
+		'slug'                => array(
 			'type'        => 'string',
 			'description' => __( 'An MD5 hash of the query args.', 'optimization-detective' ),
 			'required'    => true,
 			'pattern'     => '^[0-9a-f]{32}$',
-			// This is further validated via the validate_callback for the nonce argument, as it is provided as input
-			// with the 'url' argument to create the nonce by the server. which then is verified to match in the REST API request.
 		),
-		'nonce' => array(
+		'cache_purge_post_id' => array(
+			'type'        => 'integer',
+			'description' => __( 'Cache purge post ID.', 'optimization-detective' ),
+			'required'    => false,
+			'minimum'     => 1,
+		),
+		'hmac'                => array(
 			'type'              => 'string',
-			'description'       => __( 'Nonce originally computed by server required to authorize the request.', 'optimization-detective' ),
+			'description'       => __( 'HMAC originally computed by server required to authorize the request.', 'optimization-detective' ),
 			'required'          => true,
 			'pattern'           => '^[0-9a-f]+$',
-			'validate_callback' => static function ( string $nonce, WP_REST_Request $request ) {
-				if ( ! od_verify_url_metrics_storage_nonce( $nonce, $request->get_param( 'slug' ), $request->get_param( 'url' ) ) ) {
-					return new WP_Error( 'invalid_nonce', __( 'URL metrics nonce verification failure.', 'optimization-detective' ) );
+			'validate_callback' => static function ( string $hmac, WP_REST_Request $request ) {
+				if ( ! od_verify_url_metrics_storage_hmac( $hmac, $request['slug'], $request['url'], $request['cache_purge_post_id'] ?? null ) ) {
+					return new WP_Error( 'invalid_hmac', __( 'URL Metrics HMAC verification failure.', 'optimization-detective' ) );
 				}
 				return true;
 			},
@@ -77,7 +83,7 @@
 				if ( OD_Storage_Lock::is_locked() ) {
 					return new WP_Error(
 						'url_metric_storage_locked',
-						__( 'URL metric storage is presently locked for the current IP.', 'optimization-detective' ),
+						__( 'URL Metric storage is presently locked for the current IP.', 'optimization-detective' ),
 						array( 'status' => 403 )
 					);
 				}
@@ -89,6 +95,27 @@
 add_action( 'rest_api_init', 'od_register_endpoint' );
 
 /**
+ * Determines if the HTTP origin is an authorized one.
+ *
+ * Note that `is_allowed_http_origin()` is not used directly because the underlying `get_allowed_http_origins()` does
+ * not account for the URL port (although there is a to-do comment committed in core to address this). Additionally,
+ * the `is_allowed_http_origin()` function in core for some reason returns a string rather than a boolean.
+ *
+ * @since n.e.x.t
+ * @access private
+ *
+ * @see is_allowed_http_origin()
+ *
+ * @param string $origin Origin to check.
+ * @return bool Whether the origin is allowed.
+ */
+function od_is_allowed_http_origin( string $origin ): bool {
+	// Strip out the port number since core does not account for it yet as noted in get_allowed_http_origins().
+	$origin = preg_replace( '/:\d+$/', '', $origin );
+	return '' !== is_allowed_http_origin( $origin );
+}
+
+/**
  * Handles REST API request to store metrics.
  *
  * @since 0.1.0
@@ -100,6 +127,16 @@
  * @return WP_REST_Response|WP_Error Response.
  */
 function od_handle_rest_request( WP_REST_Request $request ) {
+	// Block cross-origin storage requests since by definition URL Metrics data can only be sourced from the frontend of the site.
+	$origin = $request->get_header( 'origin' );
+	if ( null === $origin || ! od_is_allowed_http_origin( $origin ) ) {
+		return new WP_Error(
+			'rest_cross_origin_forbidden',
+			__( 'Cross-origin requests are not allowed for this endpoint.', 'optimization-detective' ),
+			array( 'status' => 403 )
+		);
+	}
+
 	$post = OD_URL_Metrics_Post_Type::get_post( $request->get_param( 'slug' ) );
 
 	$url_metric_group_collection = new OD_URL_Metric_Group_Collection(
@@ -109,7 +146,7 @@
 		od_get_url_metric_freshness_ttl()
 	);
 
-	// Block the request if URL metrics aren't needed for the provided viewport width.
+	// Block the request if URL Metrics aren't needed for the provided viewport width.
 	try {
 		$url_metric_group = $url_metric_group_collection->get_group_for_viewport_width(
 			$request->get_param( 'viewport' )['width']
@@ -120,7 +157,7 @@
 	if ( $url_metric_group->is_complete() ) {
 		return new WP_Error(
 			'url_metric_group_complete',
-			__( 'The URL metric group for the provided viewport is already complete.', 'optimization-detective' ),
+			__( 'The URL Metric group for the provided viewport is already complete.', 'optimization-detective' ),
 			array( 'status' => 403 )
 		);
 	}
@@ -153,7 +190,7 @@
 			'rest_invalid_param',
 			sprintf(
 				/* translators: %s is exception name */
-				__( 'Failed to validate URL metric: %s', 'optimization-detective' ),
+				__( 'Failed to validate URL Metric: %s', 'optimization-detective' ),
 				$e->getMessage()
 			),
 			array( 'status' => 400 )
@@ -171,6 +208,16 @@
 	}
 	$post_id = $result;
 
+	// Schedule an event in 10 minutes to trigger an invalidation of the page cache (hopefully).
+	$cache_purge_post_id = $request->get_param( 'cache_purge_post_id' );
+	if ( is_int( $cache_purge_post_id ) && false === wp_next_scheduled( 'od_trigger_page_cache_invalidation', array( $cache_purge_post_id ) ) ) {
+		wp_schedule_single_event(
+			time() + 10 * MINUTE_IN_SECONDS,
+			'od_trigger_page_cache_invalidation',
+			array( $cache_purge_post_id )
+		);
+	}
+
 	/**
 	 * Fires whenever a URL Metric was successfully stored.
 	 *
@@ -195,3 +242,49 @@
 		)
 	);
 }
+
+/**
+ * Triggers actions for page caches to invalidate their caches related to the supplied cache purge post ID.
+ *
+ * This is intended to flush any page cache for the URL after the new URL Metric was submitted so that the optimizations
+ * which depend on that URL Metric can start to take effect.
+ *
+ * @since n.e.x.t
+ * @access private
+ *
+ * @param int $cache_purge_post_id Cache purge post ID.
+ */
+function od_trigger_page_cache_invalidation( int $cache_purge_post_id ): void {
+	$post = get_post( $cache_purge_post_id );
+	if ( ! ( $post instanceof WP_Post ) ) {
+		return;
+	}
+
+	// Fire actions that page caching plugins listen to flush caches.
+
+	/*
+	 * The clean_post_cache action is used to flush page caches by:
+	 * - Pantheon Advanced Cache <https://github.com/pantheon-systems/pantheon-advanced-page-cache/blob/e3b5552b0cb9268d9b696cb200af56cc044920d9/pantheon-advanced-page-cache.php#L185>
+	 * - WP Super Cache <https://github.com/Automattic/wp-super-cache/blob/73b428d2fce397fd874b3056ad3120c343bc1a0c/wp-cache-phase2.php#L1615>
+	 * - Batcache <https://github.com/Automattic/batcache/blob/ed0e6b2d9bcbab3924c49a6c3247646fb87a0957/batcache.php#L18>
+	 */
+	/** This action is documented in wp-includes/post.php. */
+	do_action( 'clean_post_cache', $post->ID, $post );
+
+	/*
+	 * The transition_post_status action is used to flush page caches by:
+	 * - Jetpack Boost <https://github.com/Automattic/jetpack-boost-production/blob/4090a3f9414c2171cd52d8a397f00b0d1151475f/app/modules/optimizations/page-cache/pre-wordpress/Boost_Cache.php#L76>
+	 * - WP Super Cache <https://github.com/Automattic/wp-super-cache/blob/73b428d2fce397fd874b3056ad3120c343bc1a0c/wp-cache-phase2.php#L1616>
+	 * - LightSpeed Cache <https://github.com/litespeedtech/lscache_wp/blob/7c707469b3c88b4f45d9955593b92f9aeaed54c3/src/purge.cls.php#L68>
+	 */
+	/** This action is documented in wp-includes/post.php. */
+	do_action( 'transition_post_status', $post->post_status, $post->post_status, $post );
+
+	/*
+	 * The clean_post_cache action is used to flush page caches by:
+	 * - W3 Total Cache <https://github.com/BoldGrid/w3-total-cache/blob/ab08f104294c6a8dcb00f1c66aaacd0615c42850/Util_AttachToActions.php#L32>
+	 * - WP Rocket <https://github.com/wp-media/wp-rocket/blob/e5bca6673a3669827f3998edebc0c785210fe561/inc/common/purge.php#L283>
+	 */
+	/** This action is documented in wp-includes/post.php. */
+	do_action( 'save_post', $post->ID, $post, /* $update */ true );
+}

performance-lab

Important

Stable tag change: 3.5.1 → 3.6.0

svn status:

M       includes/admin/load.php
?       includes/admin/plugin-activate-ajax.js
M       includes/admin/plugins.php
?       includes/admin/rest-api.php
?       includes/site-health/avif-headers
M       includes/site-health/load.php
M       load.php
M       readme.txt
svn diff
Index: includes/admin/load.php
===================================================================
--- includes/admin/load.php	(revision 3189893)
+++ includes/admin/load.php	(working copy)
@@ -49,9 +49,6 @@
 
 	// Handle style for settings page.
 	add_action( 'admin_head', 'perflab_print_features_page_style' );
-
-	// Handle script for settings page.
-	add_action( 'admin_footer', 'perflab_print_plugin_progress_indicator_script' );
 }
 
 /**
@@ -228,8 +225,14 @@
 	wp_enqueue_style( 'thickbox' );
 	wp_enqueue_script( 'plugin-install' );
 
-	// Enqueue the a11y script.
-	wp_enqueue_script( 'wp-a11y' );
+	// Enqueue plugin activate AJAX script and localize script data.
+	wp_enqueue_script(
+		'perflab-plugin-activate-ajax',
+		plugin_dir_url( PERFLAB_MAIN_FILE ) . 'includes/admin/plugin-activate-ajax.js',
+		array( 'wp-i18n', 'wp-a11y', 'wp-api-fetch' ),
+		PERFLAB_VERSION,
+		true
+	);
 }
 
 /**
@@ -397,42 +400,6 @@
 }
 
 /**
- * Callback function that print plugin progress indicator script.
- *
- * @since 3.1.0
- */
-function perflab_print_plugin_progress_indicator_script(): void {
-	$js_function = <<<JS
-		function addPluginProgressIndicator( message ) {
-			document.addEventListener( 'DOMContentLoaded', function () {
-				document.addEventListener( 'click', function ( event ) {
-					if (
-						event.target.classList.contains(
-							'perflab-install-active-plugin'
-						)
-					) {
-						const target = event.target;
-						target.classList.add( 'updating-message' );
-						target.textContent = message;
-
-						wp.a11y.speak( message );
-					}
-				} );
-			} );
-		}
-JS;
-
-	wp_print_inline_script_tag(
-		sprintf(
-			'( %s )( %s );',
-			$js_function,
-			wp_json_encode( __( 'Activating...', 'default' ) )
-		),
-		array( 'type' => 'module' )
-	);
-}
-
-/**
  * Gets the URL to the plugin settings screen if one exists.
  *
  * @since 3.1.0
Index: includes/admin/plugins.php
===================================================================
--- includes/admin/plugins.php	(revision 3189893)
+++ includes/admin/plugins.php	(working copy)
@@ -19,13 +19,16 @@
  * @return array{name: string, slug: string, short_description: string, requires: string|false, requires_php: string|false, requires_plugins: string[], download_link: string, version: string}|WP_Error Array of plugin data or WP_Error if failed.
  */
 function perflab_query_plugin_info( string $plugin_slug ) {
-	$transient_key = 'perflab_plugins_info-v2';
+	$transient_key = 'perflab_plugins_info';
 	$plugins       = get_transient( $transient_key );
 
 	if ( is_array( $plugins ) ) {
 		// If the specific plugin_slug is not in the cache, return an error.
 		if ( ! isset( $plugins[ $plugin_slug ] ) ) {
-			return new WP_Error( 'plugin_not_found', __( 'Plugin not found.', 'performance-lab' ) );
+			return new WP_Error(
+				'plugin_not_found',
+				__( 'Plugin not found in cached API response.', 'performance-lab' )
+			);
 		}
 		return $plugins[ $plugin_slug ]; // Return cached plugin info if found.
 	}
@@ -71,7 +74,7 @@
 	$plugins            = array();
 	$standalone_plugins = array_merge(
 		array_flip( perflab_get_standalone_plugins() ),
-		array( 'optimization-detective' => array() ) // TODO: Programmatically discover the plugin dependencies and add them here.
+		array( 'optimization-detective' => array() ) // TODO: Programmatically discover the plugin dependencies and add them here. See <https://github.com/WordPress/performance/issues/1616>.
 	);
 	foreach ( $response->plugins as $plugin_data ) {
 		if ( ! isset( $standalone_plugins[ $plugin_data['slug'] ] ) ) {
@@ -83,7 +86,10 @@
 	set_transient( $transient_key, $plugins, HOUR_IN_SECONDS );
 
 	if ( ! isset( $plugins[ $plugin_slug ] ) ) {
-		return new WP_Error( 'plugin_not_found', __( 'Plugin not found.', 'performance-lab' ) );
+		return new WP_Error(
+			'plugin_not_found',
+			__( 'Plugin not found in API response.', 'performance-lab' )
+		);
 	}
 
 	/**
@@ -324,6 +330,11 @@
 		return $plugin_data;
 	}
 
+	// Add recommended plugins (soft dependencies) to the list of plugins installed and activated.
+	if ( 'embed-optimizer' === $plugin_slug ) {
+		$plugin_data['requires_plugins'][] = 'optimization-detective';
+	}
+
 	// Install and activate plugin dependencies first.
 	foreach ( $plugin_data['requires_plugins'] as $requires_plugin_slug ) {
 		$result = perflab_install_and_activate_plugin( $requires_plugin_slug );
@@ -354,8 +365,11 @@
 		}
 
 		$plugins = get_plugins( '/' . $plugin_slug );
-		if ( empty( $plugins ) ) {
-			return new WP_Error( 'plugin_not_found', __( 'Plugin not found.', 'default' ) );
+		if ( count( $plugins ) === 0 ) {
+			return new WP_Error(
+				'plugin_not_found',
+				__( 'Plugin not found among installed plugins.', 'performance-lab' )
+			);
 		}
 
 		$plugin_file_names = array_keys( $plugins );
@@ -426,8 +440,9 @@
 		);
 
 		$action_links[] = sprintf(
-			'<a class="button perflab-install-active-plugin" href="%s">%s</a>',
+			'<a class="button perflab-install-active-plugin" href="%s" data-plugin-slug="%s">%s</a>',
 			esc_url( $url ),
+			esc_attr( $plugin_data['slug'] ),
 			esc_html__( 'Activate', 'default' )
 		);
 	} else {
Index: includes/site-health/load.php
===================================================================
--- includes/site-health/load.php	(revision 3189893)
+++ includes/site-health/load.php	(working copy)
@@ -25,3 +25,7 @@
 // AVIF Support site health check.
 require_once __DIR__ . '/avif-support/helper.php';
 require_once __DIR__ . '/avif-support/hooks.php';
+
+// AVIF headers site health check.
+require_once __DIR__ . '/avif-headers/helper.php';
+require_once __DIR__ . '/avif-headers/hooks.php';
Index: load.php
===================================================================
--- load.php	(revision 3189893)
+++ load.php	(working copy)
@@ -5,7 +5,7 @@
  * Description: Performance plugin from the WordPress Performance Team, which is a collection of standalone performance features.
  * Requires at least: 6.5
  * Requires PHP: 7.2
- * Version: 3.5.1
+ * Version: 3.6.0
  * Author: WordPress Performance Team
  * Author URI: https://make.wordpress.org/performance/
  * License: GPLv2 or later
@@ -19,7 +19,7 @@
 	exit; // Exit if accessed directly.
 }
 
-define( 'PERFLAB_VERSION', '3.5.1' );
+define( 'PERFLAB_VERSION', '3.6.0' );
 define( 'PERFLAB_MAIN_FILE', __FILE__ );
 define( 'PERFLAB_PLUGIN_DIR_PATH', plugin_dir_path( PERFLAB_MAIN_FILE ) );
 define( 'PERFLAB_SCREEN', 'performance-lab' );
@@ -339,3 +339,6 @@
 	require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/server-timing.php';
 	require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/plugins.php';
 }
+
+// Load REST API.
+require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/rest-api.php';
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -2,7 +2,7 @@
 
 Contributors: wordpressdotorg
 Tested up to: 6.7
-Stable tag:   3.5.1
+Stable tag:   3.6.0
 License:      GPLv2 or later
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 Tags:         performance, site health, measurement, optimization, diagnostics

speculation-rules

Warning

Stable tag is unchanged at 1.3.1, so no plugin release will occur.

svn status:

M       class-plsr-url-pattern-prefixer.php
M       helper.php
M       hooks.php
M       load.php
M       readme.txt
M       settings.php
svn diff
Index: class-plsr-url-pattern-prefixer.php
===================================================================
--- class-plsr-url-pattern-prefixer.php	(revision 3189893)
+++ class-plsr-url-pattern-prefixer.php	(working copy)
@@ -35,7 +35,7 @@
 	 *                                        by the {@see PLSR_URL_Pattern_Prefixer::get_default_contexts()} method.
 	 */
 	public function __construct( array $contexts = array() ) {
-		if ( $contexts ) {
+		if ( count( $contexts ) > 0 ) {
 			$this->contexts = array_map(
 				static function ( string $str ): string {
 					return self::escape_pattern_string( trailingslashit( $str ) );
Index: helper.php
===================================================================
--- helper.php	(revision 3189893)
+++ helper.php	(working copy)
@@ -19,22 +19,11 @@
  *
  * @since 1.0.0
  *
- * @return array<string, array<int, array<string, mixed>>> Associative array of speculation rules by type.
+ * @return non-empty-array<string, array<int, array<string, mixed>>> Associative array of speculation rules by type.
  */
 function plsr_get_speculation_rules(): array {
-	$option = get_option( 'plsr_speculation_rules' );
-
-	/*
-	 * This logic is only relevant for edge-cases where the setting may not be registered,
-	 * a.k.a. defensive coding.
-	 */
-	if ( ! $option || ! is_array( $option ) ) {
-		$option = plsr_get_setting_default();
-	} else {
-		$option = array_merge( plsr_get_setting_default(), $option );
-	}
-
-	$mode      = (string) $option['mode'];
+	$option    = plsr_get_stored_setting_value();
+	$mode      = $option['mode'];
 	$eagerness = $option['eagerness'];
 
 	$prefixer = new PLSR_URL_Pattern_Prefixer();
Index: hooks.php
===================================================================
--- hooks.php	(revision 3189893)
+++ hooks.php	(working copy)
@@ -19,30 +19,10 @@
  * @since 1.0.0
  */
 function plsr_print_speculation_rules(): void {
-	$rules = plsr_get_speculation_rules();
-	if ( empty( $rules ) ) {
-		return;
-	}
-
-	// This workaround is needed for WP 6.4. See <https://core.trac.wordpress.org/ticket/60320>.
-	$needs_html5_workaround = (
-		! current_theme_supports( 'html5', 'script' ) &&
-		version_compare( (string) strtok( (string) get_bloginfo( 'version' ), '-' ), '6.4', '>=' ) &&
-		version_compare( (string) strtok( (string) get_bloginfo( 'version' ), '-' ), '6.5', '<' )
-	);
-	if ( $needs_html5_workaround ) {
-		$backup_wp_theme_features = $GLOBALS['_wp_theme_features'];
-		add_theme_support( 'html5', array( 'script' ) );
-	}
-
 	wp_print_inline_script_tag(
-		(string) wp_json_encode( $rules ),
+		(string) wp_json_encode( plsr_get_speculation_rules() ),
 		array( 'type' => 'speculationrules' )
 	);
-
-	if ( $needs_html5_workaround ) {
-		$GLOBALS['_wp_theme_features'] = $backup_wp_theme_features; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
-	}
 }
 add_action( 'wp_footer', 'plsr_print_speculation_rules' );
 
Index: load.php
===================================================================
--- load.php	(revision 3189893)
+++ load.php	(working copy)
@@ -2,8 +2,8 @@
 /**
  * Plugin Name: Speculative Loading
  * Plugin URI: https://github.com/WordPress/performance/tree/trunk/plugins/speculation-rules
- * Description: Enables browsers to speculatively prerender or prefetch pages when hovering over links.
- * Requires at least: 6.4
+ * Description: Enables browsers to speculatively prerender or prefetch pages to achieve near-instant loads based on user interaction.
+ * Requires at least: 6.5
  * Requires PHP: 7.2
  * Version: 1.3.1
  * Author: WordPress Performance Team
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -1,34 +1,30 @@
 === Speculative Loading ===
 
-Contributors:      wordpressdotorg
-Requires at least: 6.4
-Tested up to:      6.5
-Requires PHP:      7.2
-Stable tag:        1.3.1
-License:           GPLv2 or later
-License URI:       https://www.gnu.org/licenses/gpl-2.0.html
-Tags:              performance, javascript, speculation rules, prerender, prefetch
+Contributors: wordpressdotorg
+Tested up to: 6.7
+Stable tag:   1.3.1
+License:      GPLv2 or later
+License URI:  https://www.gnu.org/licenses/gpl-2.0.html
+Tags:         performance, javascript, speculation rules, prerender, prefetch
 
-Enables browsers to speculatively prerender or prefetch pages when hovering over links.
+Enables browsers to speculatively prerender or prefetch pages to achieve near-instant loads based on user interaction.
 
 == Description ==
 
-This plugin adds support for the [Speculation Rules API](https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API), which allows defining rules by which certain URLs are dynamically prefetched or prerendered based on user interaction.
+This plugin adds support for the [Speculation Rules API](https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API), which allows defining rules by which certain URLs are dynamically prefetched or prerendered.
 
 See the [Speculation Rules WICG specification draft](https://wicg.github.io/nav-speculation/speculation-rules.html).
 
-By default, the plugin is configured to prerender WordPress frontend URLs when the user hovers over a relevant link. This can be customized via the "Speculative Loading" section under _Settings > Reading_.
+By default, the plugin is configured to prerender WordPress frontend URLs when the user interacts with a relevant link. This can be customized via the "Speculative Loading" section in the _Settings > Reading_ admin screen.
 
-A filter can be used to exclude certain URL paths from being eligible for prefetching and prerendering (see FAQ section). Alternatively, you can add the 'no-prerender' CSS class to any link (`<a>` tag) that should not be prerendered. See FAQ for more information.
+A filter can be used to exclude certain URL paths from being eligible for prefetching and prerendering (see FAQ section). Alternatively, you can add the `no-prerender` CSS class to any link (`<a>` tag) that should not be prerendered. See FAQ for more information.
 
 = Browser support =
 
-The Speculation Rules API is a new web API, and the functionality used by the plugin is supported in Chromium-based browsers such as Chrome, Edge, or Opera using version 121 or above. Other browsers such as Safari and Firefox will ignore the functionality with no ill effects but will not benefit from the speculative loading. Note that extensions may disable preloading by default (for example, uBlock Origin does this).
+The Speculation Rules API is a new web API, and the functionality used by the plugin is supported in Chromium-based browsers such as Chrome, Edge, or Opera using version 121 or above. Other browsers such as Safari and Firefox will ignore the functionality with no ill effects; they will simply not benefit from the speculative loading. Note that certain browser extensions may disable preloading by default.
 
-Other browsers will not see any adverse effects, however the feature will not work for those clients.
-
 * [Browser support for the Speculation Rules API in general](https://caniuse.com/mdn-html_elements_script_type_speculationrules)
-* [Information on document rules syntax support used by the plugin](https://developer.chrome.com/blog/chrome-121-beta#speculation_rules_api)
+* [Information on document rules syntax support used by the plugin](https://developer.chrome.com/docs/web-platform/prerender-pages)
 
 _This plugin was formerly known as Speculation Rules._
 
@@ -50,12 +46,11 @@
 
 = How can I prevent certain URLs from being prefetched and prerendered? =
 
-Not every URL can be reasonably prerendered. Prerendering static content is typically reliable, however prerendering interactive content, such as a logout URL, can lead to issues. For this reason, certain WordPress core URLs such as `/wp-login.php` and `/wp-admin/*` are excluded from prefetching and prerendering. Additionally, any URL generated with `wp_nonce_url()` (or which contain the `_wpnonce` query var) is also ignored. You can exclude additional URL patterns by using the `plsr_speculation_rules_href_exclude_paths` filter.
+Not every URL can be reasonably prerendered. Prerendering static content is typically reliable, however prerendering interactive content, such as a logout URL, can lead to issues. For this reason, certain WordPress core URLs such as `/wp-login.php` and `/wp-admin/*` are excluded from prefetching and prerendering. Additionally, any URLs generated with `wp_nonce_url()` (or which contains the `_wpnonce` query var) and `nofollow` links are also ignored. You can exclude additional URL patterns by using the `plsr_speculation_rules_href_exclude_paths` filter.
 
-This example would ensure that URLs like `https://example.com/cart/` or `https://example.com/cart/foo` would be excluded from prefetching and prerendering.
+The following example ensures that URLs like `https://example.com/cart/` or `https://example.com/cart/foo` are excluded from prefetching and prerendering:
 `
 <?php
-
 add_filter(
 	'plsr_speculation_rules_href_exclude_paths',
 	function ( array $exclude_paths ): array {
@@ -69,10 +64,9 @@
 
 For this purpose, the `plsr_speculation_rules_href_exclude_paths` filter receives the current mode (either "prefetch" or "prerender") to provide conditional exclusions.
 
-The following example would ensure that URLs like `https://example.com/products/...` cannot be prerendered, while still allowing them to be prefetched.
+The following example ensures that URLs like `https://example.com/products/...` cannot be prerendered, while still allowing them to be prefetched:
 `
 <?php
-
 add_filter(
 	'plsr_speculation_rules_href_exclude_paths',
 	function ( array $exclude_paths, string $mode ): array {
@@ -92,11 +86,11 @@
 
 Prerendering can affect analytics and personalization.
 
-For client-side JavaScript, is recommended to delay these until the page clicks and some solutions (like Google Analytics) already do this automatically for prerender. See [Impact on Analytics](https://developer.chrome.com/docs/web-platform/prerender-pages#impact-on-analytics). Additionally, cross-origin iframes are not loaded until activation which can further avoid issues here.
+For client-side JavaScript, is recommended to delay these until the prerender is activated (for example by clicking on the link). Some solutions (like Google Analytics) already do this automatically, see [Impact on Analytics](https://developer.chrome.com/docs/web-platform/prerender-pages#impact-on-analytics). Additionally, cross-origin iframes are not loaded until activation which can further avoid issues here.
 
-Speculating on hover (moderate) increases the chance the page will be loaded, over preloading without this signal, and thus reduces the risk here. Alternatively, the plugin offers to only speculate on mouse/pointer down (conservative) which further reduces the risk here and is an option for sites which are concerned about this, at the cost of having less of a lead time and so less of a performance gain.
+Speculating with the default `moderate` eagerness decreases the risk that the prerendered page will not be visited by the user and therefore will avoid any side effects of loading such a link in advance. In contrast, `eager` speculation increases the risk that prerendered pages may not be loaded. Alternatively, the plugin offers to only speculate on mouse/pointer down (conservative) which reduces the risk even further and is an option for sites which are concerned about this, at the cost of having less of a lead time and so less of a performance gain.
 
-A prerendered page is linked to the page that prerenders it, so personalisation may already be known by this point and changes (e.g. browsing other products, or logging in/out) may require a new page load, and hence a new prerender anyway, which will take these into account. But it definitely is something to be aware of and test!
+A prerendered page is linked to the page that prerenders it, so personalisation may already be known by this point and changes (e.g. browsing other products, or logging in/out) often require a new page load, and hence a new prerender, which will then take these into account. But it definitely is something to be aware of and test! Prerendered pages can be canceled by removing the speculation rules `<script>` element from the page using standard JavaScript DOM APIs should this be needed when state changes without a new page load.
 
 = Where can I submit my plugin feedback? =
 
Index: settings.php
===================================================================
--- settings.php	(revision 3189893)
+++ settings.php	(working copy)
@@ -16,7 +16,7 @@
  *
  * @since 1.0.0
  *
- * @return array<string, string> Associative array of `$mode => $label` pairs.
+ * @return array{ prefetch: string, prerender: string } Associative array of `$mode => $label` pairs.
  */
 function plsr_get_mode_labels(): array {
 	return array(
@@ -30,7 +30,7 @@
  *
  * @since 1.0.0
  *
- * @return array<string, string> Associative array of `$eagerness => $label` pairs.
+ * @return array{ conservative: string, moderate: string, eager: string } Associative array of `$eagerness => $label` pairs.
  */
 function plsr_get_eagerness_labels(): array {
 	return array(
@@ -45,7 +45,7 @@
  *
  * @since 1.0.0
  *
- * @return array<string, string> {
+ * @return array{ mode: 'prerender', eagerness: 'moderate' } {
  *     Default setting value.
  *
  *     @type string $mode      Mode.
@@ -60,12 +60,29 @@
 }
 
 /**
+ * Returns the stored setting value for Speculative Loading configuration.
+ *
+ * @since n.e.x.t
+ *
+ * @return array{ mode: 'prefetch'|'prerender', eagerness: 'conservative'|'moderate'|'eager' } {
+ *     Stored setting value.
+ *
+ *     @type string $mode      Mode.
+ *     @type string $eagerness Eagerness.
+ * }
+ */
+function plsr_get_stored_setting_value(): array {
+	return plsr_sanitize_setting( get_option( 'plsr_speculation_rules' ) );
+}
+
+/**
  * Sanitizes the setting for Speculative Loading configuration.
  *
  * @since 1.0.0
+ * @todo  Consider whether the JSON schema for the setting could be reused here.
  *
  * @param mixed $input Setting to sanitize.
- * @return array<string, string> {
+ * @return array{ mode: 'prefetch'|'prerender', eagerness: 'conservative'|'moderate'|'eager' } {
  *     Sanitized setting.
  *
  *     @type string $mode      Mode.
@@ -79,17 +96,14 @@
 		return $default_value;
 	}
 
-	$mode_labels      = plsr_get_mode_labels();
-	$eagerness_labels = plsr_get_eagerness_labels();
-
 	// Ensure only valid keys are present.
-	$value = array_intersect_key( $input, $default_value );
+	$value = array_intersect_key( array_merge( $default_value, $input ), $default_value );
 
-	// Set any missing or invalid values to their defaults.
-	if ( ! isset( $value['mode'] ) || ! isset( $mode_labels[ $value['mode'] ] ) ) {
+	// Constrain values to what is allowed.
+	if ( ! in_array( $value['mode'], array_keys( plsr_get_mode_labels() ), true ) ) {
 		$value['mode'] = $default_value['mode'];
 	}
-	if ( ! isset( $value['eagerness'] ) || ! isset( $eagerness_labels[ $value['eagerness'] ] ) ) {
+	if ( ! in_array( $value['eagerness'], array_keys( plsr_get_eagerness_labels() ), true ) ) {
 		$value['eagerness'] = $default_value['eagerness'];
 	}
 
@@ -113,7 +127,8 @@
 			'default'           => plsr_get_setting_default(),
 			'show_in_rest'      => array(
 				'schema' => array(
-					'properties' => array(
+					'type'                 => 'object',
+					'properties'           => array(
 						'mode'      => array(
 							'description' => __( 'Whether to prefetch or prerender URLs.', 'speculation-rules' ),
 							'type'        => 'string',
@@ -125,6 +140,7 @@
 							'enum'        => array_keys( plsr_get_eagerness_labels() ),
 						),
 					),
+					'additionalProperties' => false,
 				),
 			),
 		)
@@ -188,7 +204,7 @@
  * @since 1.0.0
  * @access private
  *
- * @param array<string, string> $args {
+ * @param array{ field: 'mode'|'eagerness', title: non-empty-string, description: non-empty-string } $args {
  *     Associative array of arguments.
  *
  *     @type string $field       The slug of the sub setting controlled by the field.
@@ -197,28 +213,24 @@
  * }
  */
 function plsr_render_settings_field( array $args ): void {
-	if ( empty( $args['field'] ) || empty( $args['title'] ) ) { // Invalid.
-		return;
-	}
+	$option = plsr_get_stored_setting_value();
 
-	$option = get_option( 'plsr_speculation_rules' );
-	if ( ! isset( $option[ $args['field'] ] ) ) { // Invalid.
-		return;
+	switch ( $args['field'] ) {
+		case 'mode':
+			$choices = plsr_get_mode_labels();
+			break;
+		case 'eagerness':
+			$choices = plsr_get_eagerness_labels();
+			break;
+		default:
+			return; // Invalid (and this case should never occur).
 	}
 
-	$value    = $option[ $args['field'] ];
-	$callback = "plsr_get_{$args['field']}_labels";
-	if ( ! is_callable( $callback ) ) {
-		return;
-	}
-	$choices = call_user_func( $callback );
-
+	$value = $option[ $args['field'] ];
 	?>
 	<fieldset>
 		<legend class="screen-reader-text"><?php echo esc_html( $args['title'] ); ?></legend>
-		<?php
-		foreach ( $choices as $slug => $label ) {
-			?>
+		<?php foreach ( $choices as $slug => $label ) : ?>
 			<p>
 				<label>
 					<input
@@ -230,17 +242,11 @@
 					<?php echo esc_html( $label ); ?>
 				</label>
 			</p>
-			<?php
-		}
+		<?php endforeach; ?>
 
-		if ( ! empty( $args['description'] ) ) {
-			?>
-			<p class="description" style="max-width: 800px;">
-				<?php echo esc_html( $args['description'] ); ?>
-			</p>
-			<?php
-		}
-		?>
+		<p class="description" style="max-width: 800px;">
+			<?php echo esc_html( $args['description'] ); ?>
+		</p>
 	</fieldset>
 	<?php
 }

web-worker-offloading

Warning

Stable tag is unchanged at 0.1.1, so no plugin release will occur.

svn status:

M       build/debug/partytown-atomics.js
M       build/debug/partytown-media.js
M       build/debug/partytown-sandbox-sw.js
M       build/debug/partytown-sw.js
M       build/debug/partytown-ww-atomics.js
M       build/debug/partytown-ww-sw.js
M       build/debug/partytown.js
M       build/partytown-atomics.js
M       build/partytown-media.js
M       build/partytown-sw.js
M       build/partytown.js
M       hooks.php
M       readme.txt
svn diff
Index: build/debug/partytown-atomics.js
===================================================================
--- build/debug/partytown-atomics.js	(revision 3189893)
+++ build/debug/partytown-atomics.js	(working copy)
@@ -1 +1,613 @@
-(e=>{const t=()=>{},n=e=>e.length,r=e=>{var t,n,r;try{const n=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(n)return n}catch(e){}try{const t=null===(r=null===(n=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===n?void 0:n.constructor)||void 0===r?void 0:r.name;if(t)return t}catch(e){}return""},o=(e,t)=>e.startsWith(t),i=e=>!(o(e,"webkit")||o(e,"toJSON")||o(e,"constructor")||o(e,"toString")||o(e,"_")&&!["__","_n","_x","_nx"].includes(e)),a=e=>11===e.nodeType&&e.host?"#s":e.nodeName,s=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),d={Anchor:"a",DList:"dl",Image:"img",OList:"ol",Paragraph:"p",Quote:"q",TableCaption:"caption",TableCell:"td",TableCol:"colgroup",TableRow:"tr",TableSection:"tbody",UList:"ul"},c={Graphics:"g",SVG:"svg"},l={preserveBehavior:!1},p=Object.freeze((e=>{const t=new Set;let n=[];do{Object.getOwnPropertyNames(n).forEach((e=>{"function"==typeof n[e]&&t.add(e)}))}while((n=Object.getPrototypeOf(n))!==Object.prototype);return Array.from(t)})()),$=Symbol(),u=Symbol(),f=new Map,m=new Map,w={},y=new WeakMap,g=(e,t)=>{if(e)return(t=y.get(e))||(t=e[$])||b(e,t=s()),t},h=(e,t,n,r,o)=>{if((n=w[e])&&n.$window$){if(e===t)return n.$window$;if(r=n.$window$.document,"d"===(o=t.split(".").pop()))return r;if("e"===o)return r.documentElement;if("h"===o)return r.head;if("b"===o)return r.body}return f.get(t)},b=(e,t,n)=>{e&&(f.set(t,e),e[$]=t,e[u]=n=Date.now(),n>v+5e3&&(f.forEach(((e,t)=>{e[u]<v&&e.nodeType&&!e.isConnected&&f.delete(t)})),v=n))};let v=0;const I=e.parent,S=document.implementation.createHTMLDocument(),O=I.partytown||{},E=(O.lib||"/~partytown/")+"debug/",M=e=>{console.debug.apply(console,["%cMain 🌎","background: #717171; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;",e])},A=[],T=e=>(A.includes(e)||A.push(e),A.indexOf(e)+1),C=(e,t,n)=>{const r=((e,t)=>{return n=e,r={value:t},Object.defineProperty(n,"name",{...r,configurable:!0});var n,r})(class extends w[e].$window$.HTMLElement{},n[0]);return"connectedCallback,disconnectedCallback,attributeChangedCallback,adoptedCallback".split(",").map((n=>r.prototype[n]=function(...r){t.postMessage([15,e,g(this),n,r])})),r.observedAttributes=n[1],r},L=(e,t,n,i,s,d)=>void 0!==t&&(i=typeof t)?"string"===i||"number"===i||"boolean"===i||null==t?[0,t]:"function"===i?[6]:(n=n||new Set)&&Array.isArray(t)?n.has(t)?[1,[]]:n.add(t)&&[1,t.map((t=>L(e,t,n)))]:"object"===i?x(t)?[14,{name:t.name,message:t.message,stack:t.stack}]:""===(s=r(t))?[2,{}]:"Window"===s?[3,[e,e]]:"HTMLCollection"===s||"NodeList"===s?[7,Array.from(t).map((t=>L(e,t,n)[1]))]:s.endsWith("Event")?[5,j(e,t,n)]:"CSSRuleList"===s?[12,Array.from(t).map(P)]:o(s,"CSS")&&s.endsWith("Rule")?[11,P(t)]:"CSSStyleDeclaration"===s?[13,j(e,t,n)]:"Attr"===s?[10,[t.name,t.value]]:t.nodeType?[3,[e,g(t),a(t),d]]:[2,j(e,t,n,!0,!0)]:void 0:t,j=(e,t,n,o,a,s,d,c)=>{if(s={},!n.has(t))for(d in n.add(t),t)i(d)&&(c="path"===d&&r(t).endsWith("Event")?t.composedPath():t[d],(o||"function"!=typeof c)&&(a||""!==c)&&(s[d]=L(e,c,n)));return s},P=e=>{let t,n={};for(t in e)U.includes(t)&&(n[t]=String(e[t]));return n};let k=null;const x=t=>{var n;return k=(null===(n=e.top)||void 0===n?void 0:n.Error)||k,t instanceof k},_=(t,n,r,o)=>{if(n)return r=n[0],o=n[1],0===r?o:4===r?R(t,o):1===r?o.map((e=>_(t,e))):3===r?h(o[0],o[1]):5===r?N(W(t,o)):2===r?W(t,o):8===r?o:9===r?new e[n[2]](o):void 0},R=(e,{$winId$:t,$instanceId$:n,$refId$:r},o)=>((o=m.get(r))||(o=function(...o){e.postMessage([9,{$winId$:t,$instanceId$:n,$refId$:r,$thisArg$:L(t,this),$args$:L(t,o)}])},m.set(r,o)),o),N=e=>new("detail"in e?CustomEvent:Event)(e.type,e),W=(e,t,n,r)=>{for(r in n={},t)n[r]=_(e,t[r]);return n},U="cssText,selectorText,href,media,namespaceURI,prefix,name,conditionText".split(","),q=async(e,t)=>{let r,o,i,a,s,d,c={$msgId$:t.$msgId$},l=n(t.$tasks$),p=0;for(;p<l;p++)try{d=p===l-1,r=t.$tasks$[p],o=r.$winId$,i=r.$applyPath$,!w[o]&&o.startsWith("f_")&&await new Promise((e=>{let t=0,n=()=>{w[o]||t++>1e3?e():requestAnimationFrame(n)};n()})),1===i[0]&&i[1]in w[o].$window$?b(new w[o].$window$[i[1]](..._(e,i[2])),r.$instanceId$):(a=h(o,r.$instanceId$),a?(s=D(e,o,a,i,d,r.$groupedGetters$),r.$assignInstanceId$&&("string"==typeof r.$assignInstanceId$?b(s,r.$assignInstanceId$):w[r.$assignInstanceId$.$winId$]={$winId$:r.$assignInstanceId$.$winId$,$window$:{document:s}}),"object"==typeof($=s)&&$&&$.then&&(s=await s,d&&(c.$isPromise$=!0)),d&&(c.$rtnValue$=L(o,s,void 0,void 0,void 0,r.$instanceId$))):(c.$error$=`Error finding instance "${r.$instanceId$}" on window ${T(o)}`,console.error(c.$error$,r)))}catch(e){d?c.$error$=String(e.stack||e):console.error(e)}var $;return c},D=(e,t,o,i,a,s)=>{let d,c,l,p,$,u=0,f=n(i);for(;u<f;u++){c=i[u],d=i[u+1],l=i[u-1];try{if(!Array.isArray(d))if("string"==typeof c||"number"==typeof c){if(u+1===f&&s)return $={},s.map((e=>$[e]=o[e])),$;o=o[c]}else{if(0===d)return void(o[l]=_(e,c));if("function"==typeof o[l]&&(p=_(e,c),"define"===l&&"CustomElementRegistry"===r(o)&&(p[1]=C(t,e,p[1])),"insertRule"===l&&p[1]>n(o.cssRules)&&(p[1]=n(o.cssRules)),o=o[l].apply(o,p),"play"===l))return Promise.resolve()}}catch(e){if(a)throw e;console.debug("Non-blocking setter error:",e)}}return o},F=(e,t)=>{let r,o,i,a=t.$winId$,s=t.$window$,d=s.document,c='script[type="text/partytown"]:not([data-ptid]):not([data-pterror])',$=c+":not([async]):not([defer])";if(d&&d.body)if(r=d.querySelector($),r||(r=d.querySelector(c)),r)r.dataset.ptid=o=g(r,a),i={$winId$:a,$instanceId$:o},r.src?(i.$url$=r.src,i.$orgUrl$=r.dataset.ptsrc||r.src):i.$content$=r.innerHTML,e.postMessage([7,i]);else{if(!t.$isInitialized$){t.$isInitialized$=1,((e,t,r)=>{let o,i,a=r._ptf,s=(r.partytown||{}).forward||[],d=(n,r)=>e.postMessage([10,{$winId$:t,$forward$:n,$args$:L(t,Array.from(r))}]);if(r._ptf=void 0,s.map((e=>{const[t,{preserveBehavior:o}]=(e=>{if("string"==typeof e)return[e,l];const[t,n=l]=e;return[t,{...l,...n}]})(e);i=r,t.split(".").map(((e,t,a)=>{var s;i=i[a[t]]=t+1<n(a)?i[a[t]]||(s=a[t+1],p.includes(s)?[]:{}):(()=>{let e=null;if(o){const{methodOrProperty:t,thisObject:n}=((e,t)=>{let n=e;for(let e=0;e<t.length-1;e+=1)n=n[t[e]];return{thisObject:n,methodOrProperty:t.length>0?n[t[t.length-1]]:void 0}})(r,a);"function"==typeof t&&(e=(...e)=>t.apply(n,...e))}return(...t)=>{let n;return e&&(n=e(t)),d(a,t),n}})()}))})),a)for(o=0;o<n(a);o+=2)d(a[o],a[o+1])})(e,a,s),d.dispatchEvent(new CustomEvent("pt0"));{const e=s===s.top?"top":"iframe";M(`Executed ${e} window ${T(a)} environment scripts in ${(performance.now()-t.$startTime$).toFixed(1)}ms`)}}e.postMessage([8,a])}else requestAnimationFrame((()=>F(e,t)))},z=(e,t,n)=>{if(!y.has(n)){y.set(n,t);const r=n.document,o=n.history,i=y.get(n.parent);let a=!1;const s=[],d=e=>{a?e():s.push(e)},c=()=>{e.postMessage([5,{$winId$:t,$parentWinId$:i,$url$:r.baseURI,$visibilityState$:r.visibilityState}]),setTimeout((()=>{a=!0,s.forEach((e=>{e()}))}))},l=o.pushState.bind(o),p=o.replaceState.bind(o),$=(n,o,i,a)=>()=>{e.postMessage([13,{$winId$:t,type:n,state:o,url:r.baseURI,newUrl:i,oldUrl:a}])};o.pushState=(e,t,n)=>{l(e,t,n),d($(0,e,null==n?void 0:n.toString()))},o.replaceState=(e,t,n)=>{p(e,t,n),d($(1,e,null==n?void 0:n.toString()))},n.addEventListener("popstate",(e=>{d($(2,e.state))})),n.addEventListener("hashchange",(e=>{d($(3,{},e.newURL,e.oldURL))})),n.addEventListener("ptupdate",(()=>{F(e,w[t])})),r.addEventListener("visibilitychange",(()=>e.postMessage([14,t,r.visibilityState]))),w[t]={$winId$:t,$window$:n},w[t].$startTime$=performance.now(),M(`Registered ${t===i?"top":"iframe"} window ${T(t)}`),"complete"===r.readyState?c():n.addEventListener("load",c)}},G=()=>{const e=Object.getOwnPropertyNames(I).map((e=>((e,t,n,r)=>{if(n=t.match(/^(HTML|SVG)(.+)Element$/))return r=n[2],"S"==t[0]?e.createElementNS("http://www.w3.org/2000/svg",c[r]||r.slice(0,2).toLowerCase()+r.slice(2)):e.createElement(d[r]||r)})(S,e))).filter((e=>e)).map((e=>[e]));return H(e,[])},H=(e,t)=>{const n=new Set(["Object"]);return e.filter((e=>e[0])).map((e=>{const t=e[0],n=e[1],o=r(t);return[o,I[o].prototype,t,n]})).map((([e,r,o,i])=>V(n,t,e,r,o,i))),t},B=(e,t,n)=>{let r=[],o=[e,"Object",r];for(n in t)J(r,t,n);return o},V=(e,t,n,o,i,s)=>{if(!e.has(n)){e.add(n);const d=Object.getPrototypeOf(o),c=r(d),l=[],p=Object.getOwnPropertyDescriptors(o);V(e,t,c,d,i,s);for(const e in p)J(l,i,e);t.push([n,c,l,s,a(i)])}},J=(e,t,n,o,a,s)=>{try{i(n)&&isNaN(n[0])&&"all"!==n&&("function"==(a=typeof(o=t[n]))?(String(o).includes("[native")||Object.getPrototypeOf(t)[n])&&e.push([n,5]):"object"===a&&null!=o?"Object"!==(s=r(o))&&"Function"!==s&&self[s]&&e.push([n,o.nodeType||s]):"symbol"!==a&&(n.toUpperCase()===n?e.push([n,6,o]):e.push([n,6])))}catch(e){console.warn(e)}},Q=(e,n)=>void 0!==e[n]?new e[n](t):0;let X;(async e=>{const t=new SharedArrayBuffer(1073741824),n=new Int32Array(t);return(e,r)=>{const o=r[0],i=r[1];if(0===o){const n=(()=>{const e=S.createElement("i"),t=S.createTextNode(""),n=S.createComment(""),r=S.createDocumentFragment(),o=S.createElement("p").attachShadow({mode:"open"}),i=Q(I,"IntersectionObserver"),a=Q(I,"MutationObserver"),s=Q(I,"ResizeObserver"),d=I.performance,c=I.screen,l=[[I.history],[d],[d.navigation],[d.timing],[c],[c.orientation],[I.visualViewport],[i,12],[a,12],[s,12],[t],[n],[r],[o],[e],[e.attributes],[e.classList],[e.dataset],[e.style],[S],[S.doctype]],p=[B("Window",I),B("Node",t)],$=function(e){return JSON.stringify(e,((e,t)=>("function"==typeof t&&(t=String(t)).startsWith(e+"(")&&(t="function "+t),"loadScriptsOnMainThread"===e&&(t=t.map((e=>Array.isArray(e)?e:["string"==typeof e?"string":"regexp","string"==typeof e?e:e.source]))),t)))}(O),u={$config$:$,$interfaces$:H(l,p),$libPath$:new URL(E,I.location)+"",$origin$:origin,$tabId$:I._pttab};return((e,t,n)=>{void 0!==t[n]&&e.push([n,"Object",Object.keys(t[n].prototype).map((e=>[e,6])),12])})(u.$interfaces$,I,"IntersectionObserverEntry"),u})();n.$sharedDataBuffer$=t,e.postMessage([1,n])}else 2===r[0]?e.postMessage([3,G()]):11===o?((e,t)=>{q(X,e).then((e=>{const t=JSON.stringify(e),r=t.length;for(let e=0;e<r;e++)n[e+1]=t.charCodeAt(e);n[0]=r,Atomics.notify(n,0)}))})(i):((e,t,n)=>{4===t[0]?z(e,s(),I):(n=w[t[1]])&&(7===t[0]?requestAnimationFrame((()=>F(e,n))):6===t[0]&&((e,t,n,r,o)=>{(o=t.$window$.document.querySelector(`[data-ptid="${n}"]`))&&(r?o.dataset.pterror=r:o.type+="-x",delete o.dataset.ptid),F(e,t)})(e,n,t[2],t[3]))})(e,r)}})().then((e=>{e&&(X=new Worker(E+"partytown-ww-atomics.js?v=0.10.2-dev1727590485751",{name:"Partytown 🎉"}),X.onmessage=t=>{const n=t.data;12===n[0]?q(X,n[1]):e(X,n)},M("Created Partytown web worker (0.10.2-dev1727590485751)"),X.onerror=e=>console.error("Web Worker Error",e),I.addEventListener("pt1",(e=>z(X,g(e.detail.frameElement),e.detail))))}))})(window);
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+(window => {
+    const isPromise = v => "object" == typeof v && v && v.then;
+    const noop = () => {};
+    const len = obj => obj.length;
+    const getConstructorName = obj => {
+        var _a, _b, _c;
+        try {
+            const constructorName = null === (_a = null == obj ? void 0 : obj.constructor) || void 0 === _a ? void 0 : _a.name;
+            if (constructorName) {
+                return constructorName;
+            }
+        } catch (e) {}
+        try {
+            const zoneJsConstructorName = null === (_c = null === (_b = null == obj ? void 0 : obj.__zone_symbol__originalInstance) || void 0 === _b ? void 0 : _b.constructor) || void 0 === _c ? void 0 : _c.name;
+            if (zoneJsConstructorName) {
+                return zoneJsConstructorName;
+            }
+        } catch (e) {}
+        return "";
+    };
+    const startsWith = (str, val) => str.startsWith(val);
+    const isValidMemberName = memberName => !(startsWith(memberName, "webkit") || startsWith(memberName, "toJSON") || startsWith(memberName, "constructor") || startsWith(memberName, "toString") || startsWith(memberName, "_") && ![ "__", "_n", "_x", "_nx" ].includes(memberName));
+    const getNodeName = node => 11 === node.nodeType && node.host ? "#s" : node.nodeName;
+    const randomId = () => Math.round(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);
+    const defineConstructorName = (Cstr, value) => ((obj, memberName, descriptor) => Object.defineProperty(obj, memberName, {
+        ...descriptor,
+        configurable: true
+    }))(Cstr, "name", {
+        value: value
+    });
+    const htmlConstructorTags = {
+        Anchor: "a",
+        DList: "dl",
+        Image: "img",
+        OList: "ol",
+        Paragraph: "p",
+        Quote: "q",
+        TableCaption: "caption",
+        TableCell: "td",
+        TableCol: "colgroup",
+        TableRow: "tr",
+        TableSection: "tbody",
+        UList: "ul"
+    };
+    const svgConstructorTags = {
+        Graphics: "g",
+        SVG: "svg"
+    };
+    const defaultPartytownForwardPropertySettings = {
+        preserveBehavior: false
+    };
+    const arrayMethods = Object.freeze((obj => {
+        const properties = new Set;
+        let currentObj = obj;
+        do {
+            Object.getOwnPropertyNames(currentObj).forEach((item => {
+                "function" == typeof currentObj[item] && properties.add(item);
+            }));
+        } while ((currentObj = Object.getPrototypeOf(currentObj)) !== Object.prototype);
+        return Array.from(properties);
+    })([]));
+    const InstanceIdKey = Symbol();
+    const CreatedKey = Symbol();
+    const instances = new Map;
+    const mainRefs = new Map;
+    const winCtxs = {};
+    const windowIds = new WeakMap;
+    const getAndSetInstanceId = (instance, instanceId) => {
+        if (instance) {
+            if (instanceId = windowIds.get(instance)) {
+                return instanceId;
+            }
+            (instanceId = instance[InstanceIdKey]) || setInstanceId(instance, instanceId = randomId());
+            return instanceId;
+        }
+    };
+    const getInstance = (winId, instanceId, win, doc, docId) => {
+        if ((win = winCtxs[winId]) && win.$window$) {
+            if (winId === instanceId) {
+                return win.$window$;
+            }
+            doc = win.$window$.document;
+            docId = instanceId.split(".").pop();
+            if ("d" === docId) {
+                return doc;
+            }
+            if ("e" === docId) {
+                return doc.documentElement;
+            }
+            if ("h" === docId) {
+                return doc.head;
+            }
+            if ("b" === docId) {
+                return doc.body;
+            }
+        }
+        return instances.get(instanceId);
+    };
+    const setInstanceId = (instance, instanceId, now) => {
+        if (instance) {
+            instances.set(instanceId, instance);
+            instance[InstanceIdKey] = instanceId;
+            instance[CreatedKey] = now = Date.now();
+            if (now > lastCleanup + 5e3) {
+                instances.forEach(((storedInstance, instanceId) => {
+                    storedInstance[CreatedKey] < lastCleanup && storedInstance.nodeType && !storedInstance.isConnected && instances.delete(instanceId);
+                }));
+                lastCleanup = now;
+            }
+        }
+    };
+    let lastCleanup = 0;
+    const mainWindow = window.parent;
+    const docImpl = document.implementation.createHTMLDocument();
+    const config = mainWindow.partytown || {};
+    const libPath = (config.lib || "/~partytown/") + "debug/";
+    const logMain = msg => {
+        console.debug.apply(console, [ "%cMain 🌎", "background: #717171; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;", msg ]);
+    };
+    const winIds = [];
+    const normalizedWinId = winId => {
+        winIds.includes(winId) || winIds.push(winId);
+        return winIds.indexOf(winId) + 1;
+    };
+    const defineCustomElement = (winId, worker, ceData) => {
+        const Cstr = defineConstructorName(class extends winCtxs[winId].$window$.HTMLElement {}, ceData[0]);
+        const ceCallbackMethods = "connectedCallback,disconnectedCallback,attributeChangedCallback,adoptedCallback".split(",");
+        ceCallbackMethods.map((callbackMethodName => Cstr.prototype[callbackMethodName] = function(...args) {
+            worker.postMessage([ 15, winId, getAndSetInstanceId(this), callbackMethodName, args ]);
+        }));
+        Cstr.observedAttributes = ceData[1];
+        return Cstr;
+    };
+    const serializeForWorker = ($winId$, value, added, type, cstrName, prevInstanceId) => void 0 !== value && (type = typeof value) ? "string" === type || "number" === type || "boolean" === type || null == value ? [ 0, value ] : "function" === type ? [ 6 ] : (added = added || new Set) && Array.isArray(value) ? added.has(value) ? [ 1, [] ] : added.add(value) && [ 1, value.map((v => serializeForWorker($winId$, v, added))) ] : "object" === type ? serializedValueIsError(value) ? [ 14, {
+        name: value.name,
+        message: value.message,
+        stack: value.stack
+    } ] : "" === (cstrName = getConstructorName(value)) ? [ 2, {} ] : "Window" === cstrName ? [ 3, [ $winId$, $winId$ ] ] : "HTMLCollection" === cstrName || "NodeList" === cstrName ? [ 7, Array.from(value).map((v => serializeForWorker($winId$, v, added)[1])) ] : cstrName.endsWith("Event") ? [ 5, serializeObjectForWorker($winId$, value, added) ] : "CSSRuleList" === cstrName ? [ 12, Array.from(value).map(serializeCssRuleForWorker) ] : startsWith(cstrName, "CSS") && cstrName.endsWith("Rule") ? [ 11, serializeCssRuleForWorker(value) ] : "CSSStyleDeclaration" === cstrName ? [ 13, serializeObjectForWorker($winId$, value, added) ] : "Attr" === cstrName ? [ 10, [ value.name, value.value ] ] : value.nodeType ? [ 3, [ $winId$, getAndSetInstanceId(value), getNodeName(value), prevInstanceId ] ] : [ 2, serializeObjectForWorker($winId$, value, added, true, true) ] : void 0 : value;
+    const serializeObjectForWorker = (winId, obj, added, includeFunctions, includeEmptyStrings, serializedObj, propName, propValue) => {
+        serializedObj = {};
+        if (!added.has(obj)) {
+            added.add(obj);
+            for (propName in obj) {
+                if (isValidMemberName(propName)) {
+                    propValue = "path" === propName && getConstructorName(obj).endsWith("Event") ? obj.composedPath() : obj[propName];
+                    (includeFunctions || "function" != typeof propValue) && (includeEmptyStrings || "" !== propValue) && (serializedObj[propName] = serializeForWorker(winId, propValue, added));
+                }
+            }
+        }
+        return serializedObj;
+    };
+    const serializeCssRuleForWorker = cssRule => {
+        let obj = {};
+        let key;
+        for (key in cssRule) {
+            validCssRuleProps.includes(key) && (obj[key] = String(cssRule[key]));
+        }
+        return obj;
+    };
+    let ErrorObject = null;
+    const serializedValueIsError = value => {
+        var _a;
+        ErrorObject = (null === (_a = window.top) || void 0 === _a ? void 0 : _a.Error) || ErrorObject;
+        return value instanceof ErrorObject;
+    };
+    const deserializeFromWorker = (worker, serializedTransfer, serializedType, serializedValue) => {
+        if (serializedTransfer) {
+            serializedType = serializedTransfer[0];
+            serializedValue = serializedTransfer[1];
+            return 0 === serializedType ? serializedValue : 4 === serializedType ? deserializeRefFromWorker(worker, serializedValue) : 1 === serializedType ? serializedValue.map((v => deserializeFromWorker(worker, v))) : 3 === serializedType ? getInstance(serializedValue[0], serializedValue[1]) : 5 === serializedType ? constructEvent(deserializeObjectFromWorker(worker, serializedValue)) : 2 === serializedType ? deserializeObjectFromWorker(worker, serializedValue) : 8 === serializedType ? serializedValue : 9 === serializedType ? new window[serializedTransfer[2]](serializedValue) : void 0;
+        }
+    };
+    const deserializeRefFromWorker = (worker, {$winId$: $winId$, $instanceId$: $instanceId$, $refId$: $refId$}, ref) => {
+        ref = mainRefs.get($refId$);
+        if (!ref) {
+            ref = function(...args) {
+                worker.postMessage([ 9, {
+                    $winId$: $winId$,
+                    $instanceId$: $instanceId$,
+                    $refId$: $refId$,
+                    $thisArg$: serializeForWorker($winId$, this),
+                    $args$: serializeForWorker($winId$, args)
+                } ]);
+            };
+            mainRefs.set($refId$, ref);
+        }
+        return ref;
+    };
+    const constructEvent = eventProps => new ("detail" in eventProps ? CustomEvent : Event)(eventProps.type, eventProps);
+    const deserializeObjectFromWorker = (worker, serializedValue, obj, key) => {
+        obj = {};
+        for (key in serializedValue) {
+            obj[key] = deserializeFromWorker(worker, serializedValue[key]);
+        }
+        return obj;
+    };
+    const validCssRuleProps = "cssText,selectorText,href,media,namespaceURI,prefix,name,conditionText".split(",");
+    const mainAccessHandler = async (worker, accessReq) => {
+        let accessRsp = {
+            $msgId$: accessReq.$msgId$
+        };
+        let totalTasks = len(accessReq.$tasks$);
+        let i = 0;
+        let task;
+        let winId;
+        let applyPath;
+        let instance;
+        let rtnValue;
+        let isLast;
+        for (;i < totalTasks; i++) {
+            try {
+                isLast = i === totalTasks - 1;
+                task = accessReq.$tasks$[i];
+                winId = task.$winId$;
+                applyPath = task.$applyPath$;
+                !winCtxs[winId] && winId.startsWith("f_") && await new Promise((resolve => {
+                    let check = 0;
+                    let callback = () => {
+                        winCtxs[winId] || check++ > 1e3 ? resolve() : requestAnimationFrame(callback);
+                    };
+                    callback();
+                }));
+                if (1 === applyPath[0] && applyPath[1] in winCtxs[winId].$window$) {
+                    setInstanceId(new winCtxs[winId].$window$[applyPath[1]](...deserializeFromWorker(worker, applyPath[2])), task.$instanceId$);
+                } else {
+                    instance = getInstance(winId, task.$instanceId$);
+                    if (instance) {
+                        rtnValue = applyToInstance(worker, winId, instance, applyPath, isLast, task.$groupedGetters$);
+                        task.$assignInstanceId$ && ("string" == typeof task.$assignInstanceId$ ? setInstanceId(rtnValue, task.$assignInstanceId$) : winCtxs[task.$assignInstanceId$.$winId$] = {
+                            $winId$: task.$assignInstanceId$.$winId$,
+                            $window$: {
+                                document: rtnValue
+                            }
+                        });
+                        if (isPromise(rtnValue)) {
+                            rtnValue = await rtnValue;
+                            isLast && (accessRsp.$isPromise$ = true);
+                        }
+                        isLast && (accessRsp.$rtnValue$ = serializeForWorker(winId, rtnValue, void 0, void 0, void 0, task.$instanceId$));
+                    } else {
+                        accessRsp.$error$ = `Error finding instance "${task.$instanceId$}" on window ${normalizedWinId(winId)}`;
+                        console.error(accessRsp.$error$, task);
+                    }
+                }
+            } catch (e) {
+                isLast ? accessRsp.$error$ = String(e.stack || e) : console.error(e);
+            }
+        }
+        return accessRsp;
+    };
+    const applyToInstance = (worker, winId, instance, applyPath, isLast, groupedGetters) => {
+        let i = 0;
+        let l = len(applyPath);
+        let next;
+        let current;
+        let previous;
+        let args;
+        let groupedRtnValues;
+        for (;i < l; i++) {
+            current = applyPath[i];
+            next = applyPath[i + 1];
+            previous = applyPath[i - 1];
+            try {
+                if (!Array.isArray(next)) {
+                    if ("string" == typeof current || "number" == typeof current) {
+                        if (i + 1 === l && groupedGetters) {
+                            groupedRtnValues = {};
+                            groupedGetters.map((propName => groupedRtnValues[propName] = instance[propName]));
+                            return groupedRtnValues;
+                        }
+                        instance = instance[current];
+                    } else {
+                        if (0 === next) {
+                            instance[previous] = deserializeFromWorker(worker, current);
+                            return;
+                        }
+                        if ("function" == typeof instance[previous]) {
+                            args = deserializeFromWorker(worker, current);
+                            "define" === previous && "CustomElementRegistry" === getConstructorName(instance) && (args[1] = defineCustomElement(winId, worker, args[1]));
+                            "insertRule" === previous && args[1] > len(instance.cssRules) && (args[1] = len(instance.cssRules));
+                            instance = instance[previous].apply(instance, args);
+                            if ("play" === previous) {
+                                return Promise.resolve();
+                            }
+                        }
+                    }
+                }
+            } catch (err) {
+                if (isLast) {
+                    throw err;
+                }
+                console.debug("Non-blocking setter error:", err);
+            }
+        }
+        return instance;
+    };
+    const mainForwardTrigger = (worker, $winId$, win) => {
+        let queuedForwardCalls = win._ptf;
+        let forwards = (win.partytown || {}).forward || [];
+        let i;
+        let mainForwardFn;
+        let forwardCall = ($forward$, args) => worker.postMessage([ 10, {
+            $winId$: $winId$,
+            $forward$: $forward$,
+            $args$: serializeForWorker($winId$, Array.from(args))
+        } ]);
+        win._ptf = void 0;
+        forwards.map((forwardProps => {
+            const [property, {preserveBehavior: preserveBehavior}] = (propertyOrPropertyWithSettings => {
+                if ("string" == typeof propertyOrPropertyWithSettings) {
+                    return [ propertyOrPropertyWithSettings, defaultPartytownForwardPropertySettings ];
+                }
+                const [property, settings = defaultPartytownForwardPropertySettings] = propertyOrPropertyWithSettings;
+                return [ property, {
+                    ...defaultPartytownForwardPropertySettings,
+                    ...settings
+                } ];
+            })(forwardProps);
+            mainForwardFn = win;
+            property.split(".").map(((_, i, arr) => {
+                mainForwardFn = mainForwardFn[arr[i]] = i + 1 < len(arr) ? mainForwardFn[arr[i]] || (propertyName => arrayMethods.includes(propertyName) ? [] : {})(arr[i + 1]) : (() => {
+                    let originalFunction = null;
+                    if (preserveBehavior) {
+                        const {methodOrProperty: methodOrProperty, thisObject: thisObject} = ((window, properties) => {
+                            let thisObject = window;
+                            for (let i = 0; i < properties.length - 1; i += 1) {
+                                thisObject = thisObject[properties[i]];
+                            }
+                            return {
+                                thisObject: thisObject,
+                                methodOrProperty: properties.length > 0 ? thisObject[properties[properties.length - 1]] : void 0
+                            };
+                        })(win, arr);
+                        "function" == typeof methodOrProperty && (originalFunction = (...args) => methodOrProperty.apply(thisObject, ...args));
+                    }
+                    return (...args) => {
+                        let returnValue;
+                        originalFunction && (returnValue = originalFunction(args));
+                        forwardCall(arr, args);
+                        return returnValue;
+                    };
+                })();
+            }));
+        }));
+        if (queuedForwardCalls) {
+            for (i = 0; i < len(queuedForwardCalls); i += 2) {
+                forwardCall(queuedForwardCalls[i], queuedForwardCalls[i + 1]);
+            }
+        }
+    };
+    const readNextScript = (worker, winCtx) => {
+        let $winId$ = winCtx.$winId$;
+        let win = winCtx.$window$;
+        let doc = win.document;
+        let scriptSelector = 'script[type="text/partytown"]:not([data-ptid]):not([data-pterror])';
+        let blockingScriptSelector = scriptSelector + ":not([async]):not([defer])";
+        let scriptElm;
+        let $instanceId$;
+        let scriptData;
+        if (doc && doc.body) {
+            scriptElm = doc.querySelector(blockingScriptSelector);
+            scriptElm || (scriptElm = doc.querySelector(scriptSelector));
+            if (scriptElm) {
+                scriptElm.dataset.ptid = $instanceId$ = getAndSetInstanceId(scriptElm, $winId$);
+                scriptData = {
+                    $winId$: $winId$,
+                    $instanceId$: $instanceId$
+                };
+                if (scriptElm.src) {
+                    scriptData.$url$ = scriptElm.src;
+                    scriptData.$orgUrl$ = scriptElm.dataset.ptsrc || scriptElm.src;
+                } else {
+                    scriptData.$content$ = scriptElm.innerHTML;
+                }
+                worker.postMessage([ 7, scriptData ]);
+            } else {
+                if (!winCtx.$isInitialized$) {
+                    winCtx.$isInitialized$ = 1;
+                    mainForwardTrigger(worker, $winId$, win);
+                    doc.dispatchEvent(new CustomEvent("pt0"));
+                    {
+                        const winType = win === win.top ? "top" : "iframe";
+                        logMain(`Executed ${winType} window ${normalizedWinId($winId$)} environment scripts in ${(performance.now() - winCtx.$startTime$).toFixed(1)}ms`);
+                    }
+                }
+                worker.postMessage([ 8, $winId$ ]);
+            }
+        } else {
+            requestAnimationFrame((() => readNextScript(worker, winCtx)));
+        }
+    };
+    const registerWindow = (worker, $winId$, $window$) => {
+        if (!windowIds.has($window$)) {
+            windowIds.set($window$, $winId$);
+            const doc = $window$.document;
+            const history = $window$.history;
+            const $parentWinId$ = windowIds.get($window$.parent);
+            let initialised = false;
+            const onInitialisedQueue = [];
+            const onInitialised = callback => {
+                initialised ? callback() : onInitialisedQueue.push(callback);
+            };
+            const sendInitEnvData = () => {
+                worker.postMessage([ 5, {
+                    $winId$: $winId$,
+                    $parentWinId$: $parentWinId$,
+                    $url$: doc.baseURI,
+                    $visibilityState$: doc.visibilityState
+                } ]);
+                setTimeout((() => {
+                    initialised = true;
+                    onInitialisedQueue.forEach((callback => {
+                        callback();
+                    }));
+                }));
+            };
+            const pushState = history.pushState.bind(history);
+            const replaceState = history.replaceState.bind(history);
+            const onLocationChange = (type, state, newUrl, oldUrl) => () => {
+                worker.postMessage([ 13, {
+                    $winId$: $winId$,
+                    type: type,
+                    state: state,
+                    url: doc.baseURI,
+                    newUrl: newUrl,
+                    oldUrl: oldUrl
+                } ]);
+            };
+            history.pushState = (state, _, newUrl) => {
+                pushState(state, _, newUrl);
+                onInitialised(onLocationChange(0, state, null == newUrl ? void 0 : newUrl.toString()));
+            };
+            history.replaceState = (state, _, newUrl) => {
+                replaceState(state, _, newUrl);
+                onInitialised(onLocationChange(1, state, null == newUrl ? void 0 : newUrl.toString()));
+            };
+            $window$.addEventListener("popstate", (event => {
+                onInitialised(onLocationChange(2, event.state));
+            }));
+            $window$.addEventListener("hashchange", (event => {
+                onInitialised(onLocationChange(3, {}, event.newURL, event.oldURL));
+            }));
+            $window$.addEventListener("ptupdate", (() => {
+                readNextScript(worker, winCtxs[$winId$]);
+            }));
+            doc.addEventListener("visibilitychange", (() => worker.postMessage([ 14, $winId$, doc.visibilityState ])));
+            winCtxs[$winId$] = {
+                $winId$: $winId$,
+                $window$: $window$
+            };
+            winCtxs[$winId$].$startTime$ = performance.now();
+            {
+                const winType = $winId$ === $parentWinId$ ? "top" : "iframe";
+                logMain(`Registered ${winType} window ${normalizedWinId($winId$)}`);
+            }
+            "complete" === doc.readyState ? sendInitEnvData() : $window$.addEventListener("load", sendInitEnvData);
+        }
+    };
+    const onMessageFromWebWorker = (worker, msg, winCtx) => {
+        if (4 === msg[0]) {
+            registerWindow(worker, randomId(), mainWindow);
+        } else {
+            winCtx = winCtxs[msg[1]];
+            winCtx && (7 === msg[0] ? requestAnimationFrame((() => readNextScript(worker, winCtx))) : 6 === msg[0] && ((worker, winCtx, instanceId, errorMsg, scriptElm) => {
+                scriptElm = winCtx.$window$.document.querySelector(`[data-ptid="${instanceId}"]`);
+                if (scriptElm) {
+                    errorMsg ? scriptElm.dataset.pterror = errorMsg : scriptElm.type += "-x";
+                    delete scriptElm.dataset.ptid;
+                }
+                readNextScript(worker, winCtx);
+            })(worker, winCtx, msg[2], msg[3]));
+        }
+    };
+    const readMainPlatform = () => {
+        const elm = docImpl.createElement("i");
+        const textNode = docImpl.createTextNode("");
+        const comment = docImpl.createComment("");
+        const frag = docImpl.createDocumentFragment();
+        const shadowRoot = docImpl.createElement("p").attachShadow({
+            mode: "open"
+        });
+        const intersectionObserver = getGlobalConstructor(mainWindow, "IntersectionObserver");
+        const mutationObserver = getGlobalConstructor(mainWindow, "MutationObserver");
+        const resizeObserver = getGlobalConstructor(mainWindow, "ResizeObserver");
+        const perf = mainWindow.performance;
+        const screen = mainWindow.screen;
+        const impls = [ [ mainWindow.history ], [ perf ], [ perf.navigation ], [ perf.timing ], [ screen ], [ screen.orientation ], [ mainWindow.visualViewport ], [ intersectionObserver, 12 ], [ mutationObserver, 12 ], [ resizeObserver, 12 ], [ textNode ], [ comment ], [ frag ], [ shadowRoot ], [ elm ], [ elm.attributes ], [ elm.classList ], [ elm.dataset ], [ elm.style ], [ docImpl ], [ docImpl.doctype ] ];
+        const initialInterfaces = [ readImplementation("Window", mainWindow), readImplementation("Node", textNode) ];
+        const $config$ = function(config) {
+            return JSON.stringify(config, ((key, value) => {
+                if ("function" == typeof value) {
+                    value = String(value);
+                    value.startsWith(key + "(") && (value = "function " + value);
+                }
+                "loadScriptsOnMainThread" === key && (value = value.map((scriptUrl => Array.isArray(scriptUrl) ? scriptUrl : [ "string" == typeof scriptUrl ? "string" : "regexp", "string" == typeof scriptUrl ? scriptUrl : scriptUrl.source ])));
+                return value;
+            }));
+        }(config);
+        const initWebWorkerData = {
+            $config$: $config$,
+            $interfaces$: readImplementations(impls, initialInterfaces),
+            $libPath$: new URL(libPath, mainWindow.location) + "",
+            $origin$: origin,
+            $tabId$: mainWindow._pttab
+        };
+        addGlobalConstructorUsingPrototype(initWebWorkerData.$interfaces$, mainWindow, "IntersectionObserverEntry");
+        return initWebWorkerData;
+    };
+    const readMainInterfaces = () => {
+        const elms = Object.getOwnPropertyNames(mainWindow).map((interfaceName => ((doc, interfaceName, r, tag) => {
+            r = interfaceName.match(/^(HTML|SVG)(.+)Element$/);
+            if (r) {
+                tag = r[2];
+                return "S" == interfaceName[0] ? doc.createElementNS("http://www.w3.org/2000/svg", svgConstructorTags[tag] || tag.slice(0, 2).toLowerCase() + tag.slice(2)) : doc.createElement(htmlConstructorTags[tag] || tag);
+            }
+        })(docImpl, interfaceName))).filter((elm => elm)).map((elm => [ elm ]));
+        return readImplementations(elms, []);
+    };
+    const readImplementations = (impls, interfaces) => {
+        const cstrs = new Set([ "Object" ]);
+        const cstrImpls = impls.filter((implData => implData[0])).map((implData => {
+            const impl = implData[0];
+            const interfaceType = implData[1];
+            const cstrName = getConstructorName(impl);
+            const CstrPrototype = mainWindow[cstrName].prototype;
+            return [ cstrName, CstrPrototype, impl, interfaceType ];
+        }));
+        cstrImpls.map((([cstrName, CstrPrototype, impl, intefaceType]) => readOwnImplementation(cstrs, interfaces, cstrName, CstrPrototype, impl, intefaceType)));
+        return interfaces;
+    };
+    const readImplementation = (cstrName, impl, memberName) => {
+        let interfaceMembers = [];
+        let interfaceInfo = [ cstrName, "Object", interfaceMembers ];
+        for (memberName in impl) {
+            readImplementationMember(interfaceMembers, impl, memberName);
+        }
+        return interfaceInfo;
+    };
+    const readOwnImplementation = (cstrs, interfaces, cstrName, CstrPrototype, impl, interfaceType) => {
+        if (!cstrs.has(cstrName)) {
+            cstrs.add(cstrName);
+            const SuperCstr = Object.getPrototypeOf(CstrPrototype);
+            const superCstrName = getConstructorName(SuperCstr);
+            const interfaceMembers = [];
+            const propDescriptors = Object.getOwnPropertyDescriptors(CstrPrototype);
+            readOwnImplementation(cstrs, interfaces, superCstrName, SuperCstr, impl, interfaceType);
+            for (const memberName in propDescriptors) {
+                readImplementationMember(interfaceMembers, impl, memberName);
+            }
+            interfaces.push([ cstrName, superCstrName, interfaceMembers, interfaceType, getNodeName(impl) ]);
+        }
+    };
+    const readImplementationMember = (interfaceMembers, implementation, memberName, value, memberType, cstrName) => {
+        try {
+            if (isValidMemberName(memberName) && isNaN(memberName[0]) && "all" !== memberName) {
+                value = implementation[memberName];
+                memberType = typeof value;
+                if ("function" === memberType) {
+                    (String(value).includes("[native") || Object.getPrototypeOf(implementation)[memberName]) && interfaceMembers.push([ memberName, 5 ]);
+                } else if ("object" === memberType && null != value) {
+                    cstrName = getConstructorName(value);
+                    "Object" !== cstrName && "Function" !== cstrName && self[cstrName] && interfaceMembers.push([ memberName, value.nodeType || cstrName ]);
+                } else {
+                    "symbol" !== memberType && (memberName.toUpperCase() === memberName ? interfaceMembers.push([ memberName, 6, value ]) : interfaceMembers.push([ memberName, 6 ]));
+                }
+            }
+        } catch (e) {
+            console.warn(e);
+        }
+    };
+    const getGlobalConstructor = (mainWindow, cstrName) => void 0 !== mainWindow[cstrName] ? new mainWindow[cstrName](noop) : 0;
+    const addGlobalConstructorUsingPrototype = ($interfaces$, mainWindow, cstrName) => {
+        void 0 !== mainWindow[cstrName] && $interfaces$.push([ cstrName, "Object", Object.keys(mainWindow[cstrName].prototype).map((propName => [ propName, 6 ])), 12 ]);
+    };
+    let worker;
+    (async receiveMessage => {
+        const sharedDataBuffer = new SharedArrayBuffer(1073741824);
+        const sharedData = new Int32Array(sharedDataBuffer);
+        return (worker, msg) => {
+            const msgType = msg[0];
+            const accessReq = msg[1];
+            if (0 === msgType) {
+                const initData = readMainPlatform();
+                initData.$sharedDataBuffer$ = sharedDataBuffer;
+                worker.postMessage([ 1, initData ]);
+            } else {
+                2 === msg[0] ? worker.postMessage([ 3, readMainInterfaces() ]) : 11 === msgType ? receiveMessage(accessReq, (accessRsp => {
+                    const stringifiedData = JSON.stringify(accessRsp);
+                    const stringifiedDataLength = stringifiedData.length;
+                    for (let i = 0; i < stringifiedDataLength; i++) {
+                        sharedData[i + 1] = stringifiedData.charCodeAt(i);
+                    }
+                    sharedData[0] = stringifiedDataLength;
+                    Atomics.notify(sharedData, 0);
+                })) : onMessageFromWebWorker(worker, msg);
+            }
+        };
+    })(((accessReq, responseCallback) => mainAccessHandler(worker, accessReq).then(responseCallback))).then((onMessageHandler => {
+        if (onMessageHandler) {
+            worker = new Worker(libPath + "partytown-ww-atomics.js?v=0.10.2-dev1727590485751", {
+                name: "Partytown 🎉"
+            });
+            worker.onmessage = ev => {
+                const msg = ev.data;
+                12 === msg[0] ? mainAccessHandler(worker, msg[1]) : onMessageHandler(worker, msg);
+            };
+            logMain("Created Partytown web worker (0.10.2-dev1727590485751)");
+            worker.onerror = ev => console.error("Web Worker Error", ev);
+            mainWindow.addEventListener("pt1", (ev => registerWindow(worker, getAndSetInstanceId(ev.detail.frameElement), ev.detail)));
+        }
+    }));
+})(window);
Index: build/debug/partytown-media.js
===================================================================
--- build/debug/partytown-media.js	(revision 3189893)
+++ build/debug/partytown-media.js	(working copy)
@@ -1 +1,374 @@
-(e=>{const[t,s,n,r,i,a,o,d,u]=e.$bridgeToMedia$;delete e.$bridgeToMedia$;const c=Symbol(),h=Symbol(),f=Symbol(),p=Symbol(),g=Symbol(),l=Symbol(),m=[],v=(e,t,s)=>e[t]=S(t,s),S=(e,t)=>Object.defineProperty(t,"name",{value:e}),b=(e,t)=>{const r={getContext:{value(e,t){return this[c]||(this[c]=(e.includes("webgl")?g:p)(this,e,t)),this[c]}}},h=v(t,"CanvasGradient",class extends e{addColorStop(...e){n(this,["addColorStop"],e,2)}}),f=v(t,"CanvasPattern",class extends e{setTransform(...e){n(this,["setTransform"],e,2)}}),p=(e,t,r)=>{const i=e[o],c=a(),f={[o]:i,[d]:c,[u]:[]},p=n(e,["getContext"],[t,r],1,c),g="getContextAttributes,getImageData,getLineDash,getTransform,isPointInPath,isPointInStroke,measureText".split(","),l={get:(e,t)=>"string"==typeof t&&t in p?"function"==typeof p[t]?(...e)=>{if(t.startsWith("create")){const r=a();return n(f,[t],e,2,r),"createImageData"===t||"createPattern"===t?(s=`${t}()`,console.warn(`${s} not implemented`),{setTransform:()=>{}}):new h(i,r)}var s;const r=g.includes(t)?1:2;return n(f,[t],e,r)}:p[t]:e[t],set:(e,t,n)=>("string"==typeof t&&t in p?(p[t]!==n&&"function"!=typeof n&&s(f,[t],n),p[t]=n):e[t]=n,!0)};return new Proxy(p,l)},g=(e,t,r)=>{const i=e[o],c=a(),h={[o]:i,[d]:c,[u]:[]},f=n(e,["getContext"],[t,r],1,c),p={get:(e,t)=>"string"==typeof t?"function"!=typeof f[t]?f[t]:(...e)=>n(h,[t],e,m(t)):e[t],set:(e,t,n)=>("string"==typeof t&&t in f?(f[t]!==n&&"function"!=typeof n&&s(h,[t],n),f[t]=n):e[t]=n,!0)};return new Proxy(f,p)},l="checkFramebufferStatus,makeXRCompatible".split(","),m=e=>e.startsWith("create")||e.startsWith("get")||e.startsWith("is")||l.includes(e)?1:2;v(t,"CanvasGradient",h),v(t,"CanvasPattern",f),i(t.HTMLCanvasElement,r)},y=(e,u,c,b)=>{var y,T;b.Audio=S("HTMLAudioElement",class{constructor(e){const t=c.$createNode$("audio",a());return t.src=e,t}});const w=class extends e{get enabled(){return t(this,["enabled"])}set enabled(e){s(this,["enabled"],e)}get id(){return t(this,["id"])}get kind(){return t(this,["kind"])}get label(){return t(this,["label"])}get language(){return t(this,["language"])}get sourceBuffer(){return new x(this)}},k=class{constructor(e){const s=e[o],r=e[d];return new Proxy({addEventListener(...t){n(e,["audioTracks","addEventListener"],t,3)},getTrackById:(...t)=>n(e,["audioTracks","getTrackById"],t),get length(){return t(e,["audioTracks","length"])},removeEventListener(...t){n(e,["audioTracks","removeEventListener"],t,3)}},{get:(e,t)=>"number"==typeof t?new w(s,r,["audioTracks",t]):e[t]})}},E=v(b,"SourceBufferList",class extends Array{constructor(e){super(),this[h]=e}addEventListener(...e){n(this[h],["sourceBuffers","addEventListener"],e,3)}removeEventListener(...e){n(this[h],["sourceBuffers","removeEventListener"],e,3)}}),x=v(b,"SourceBuffer",(T=class extends u{constructor(e){super(e[o],e[d],["sourceBuffers"]),this[y]=[],this[h]=e}abort(){const e=R(this);n(this,[e,"appendWindowStart"],m,1)}addEventListener(...e){const t=R(this);n(this,[t,"addEventListener"],e,3)}appendBuffer(e){this[g].push(["appendBuffer",[e],e]),M(this)}get appendWindowStart(){const e=R(this);return t(this,[e,"appendWindowStart"])}set appendWindowStart(e){const t=R(this);s(this,[t,"appendWindowStart"],e)}get appendWindowEnd(){const e=R(this);return t(this,[e,"appendWindowEnd"])}set appendWindowEnd(e){const t=R(this);s(this,[t,"appendWindowEnd"],e)}get buffered(){const e=this[h],t=R(this);return new B(e[o],e[d],["sourceBuffers",t,"buffered"])}changeType(e){const t=R(this);n(this,[t,"changeType"],[e],2)}get mode(){const e=R(this);return t(this,[e,"mode"])}set mode(e){const t=R(this);s(this,[t,"mode"],e)}remove(e,t){this[g].push(["remove",[e,t]]),M(this)}removeEventListener(...e){const t=R(this);n(this,[t,"removeEventListener"],e,3)}get timestampOffset(){const e=R(this);return t(this,[e,"timestampOffset"])}set timestampOffset(e){const t=R(this);s(this,[t,"timestampOffset"],e)}get updating(){const e=R(this);return t(this,[e,"updating"])}},y=g,T)),B=v(b,"TimeRanges",class extends e{start(...e){return n(this,["start"],e)}end(...e){return n(this,["end"],e)}get length(){return t(this,["length"])}}),R=e=>e?e[h][p].indexOf(e):-1,M=e=>{if(e[g].length){if(!e.updating){const t=e[g].shift();if(t){const s=R(e);n(e,[s,t[0]],t[1],3,void 0,t[2])}}setTimeout((()=>M(e)),50)}},W={buffered:{get(){return this[l]||(this[l]=new B(this[o],this[d],["buffered"]),setTimeout((()=>{this[l]=void 0}),5e3)),this[l]}},readyState:{get(){return 4===this[f]?4:("number"!=typeof this[f]&&(this[f]=t(this,["readyState"]),setTimeout((()=>{this[f]=void 0}),1e3)),this[f])}}};v(b,"MediaSource",class extends u{constructor(){super(c.$winId$),this[p]=new E(this),r(this,"MediaSource",m)}get activeSourceBuffers(){return[]}addSourceBuffer(e){const t=new x(this);return this[p].push(t),n(this,["addSourceBuffer"],[e]),t}clearLiveSeekableRange(){n(this,["clearLiveSeekableRange"],m,2)}get duration(){return t(this,["duration"])}set duration(e){s(this,["duration"],e)}endOfStream(e){n(this,["endOfStream"],[e],3)}get readyState(){return t(this,["readyState"])}removeSourceBuffer(e){const t=R(e);t>-1&&(this[p].splice(t,1),n(this,["removeSourceBuffer"],[t],1))}setLiveSeekableRange(e,t){n(this,["setLiveSeekableRange"],[e,t],2)}get sourceBuffers(){return this[p]}static isTypeSupported(e){if(!L.has(e)){const t=n(b,["MediaSource","isTypeSupported"],[e]);L.set(e,t)}return L.get(e)}});const C=b.URL=S("URL",class extends URL{});"audioTracks"in b.HTMLMediaElement.prototype&&(v(b,"AudioTrackList",k),v(b,"AudioTrack",w),W.audioTracks={get(){return new k(this)}}),i(b.HTMLMediaElement,W),C.createObjectURL=e=>n(b,["URL","createObjectURL"],[e]),C.revokeObjectURL=e=>n(b,["URL","revokeObjectURL"],[e])},L=new Map;e.$bridgeFromMedia$=(e,t,s,n,r)=>{r.map((e=>{delete n[e]})),b(e,n),y(e,t,s,n)}})(self);
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+(self => {
+    const [getter, setter, callMethod, constructGlobal, definePrototypePropertyDescriptor, randomId, WinIdKey, InstanceIdKey, ApplyPathKey] = self.$bridgeToMedia$;
+    delete self.$bridgeToMedia$;
+    const ContextKey = Symbol();
+    const MediaSourceKey = Symbol();
+    const ReadyStateKey = Symbol();
+    const SourceBuffersKey = Symbol();
+    const SourceBufferTasksKey = Symbol();
+    const TimeRangesKey = Symbol();
+    const EMPTY_ARRAY = [];
+    const defineCstr = (win, cstrName, Cstr) => win[cstrName] = defineCstrName(cstrName, Cstr);
+    const defineCstrName = (cstrName, Cstr) => Object.defineProperty(Cstr, "name", {
+        value: cstrName
+    });
+    const initCanvas = (WorkerBase, win) => {
+        const HTMLCanvasDescriptorMap = {
+            getContext: {
+                value(contextType, contextAttributes) {
+                    this[ContextKey] || (this[ContextKey] = (contextType.includes("webgl") ? createContextWebGL : createContext2D)(this, contextType, contextAttributes));
+                    return this[ContextKey];
+                }
+            }
+        };
+        const WorkerCanvasGradient = defineCstr(win, "CanvasGradient", class extends WorkerBase {
+            addColorStop(...args) {
+                callMethod(this, [ "addColorStop" ], args, 2);
+            }
+        });
+        const WorkerCanvasPattern = defineCstr(win, "CanvasPattern", class extends WorkerBase {
+            setTransform(...args) {
+                callMethod(this, [ "setTransform" ], args, 2);
+            }
+        });
+        const createContext2D = (canvasInstance, contextType, contextAttributes) => {
+            const winId = canvasInstance[WinIdKey];
+            const ctxInstanceId = randomId();
+            const ctxInstance = {
+                [WinIdKey]: winId,
+                [InstanceIdKey]: ctxInstanceId,
+                [ApplyPathKey]: []
+            };
+            const ctx = callMethod(canvasInstance, [ "getContext" ], [ contextType, contextAttributes ], 1, ctxInstanceId);
+            const ctx2dGetterMethods = "getContextAttributes,getImageData,getLineDash,getTransform,isPointInPath,isPointInStroke,measureText".split(",");
+            const CanvasRenderingContext2D = {
+                get: (target, propName) => "string" == typeof propName && propName in ctx ? "function" == typeof ctx[propName] ? (...args) => {
+                    if (propName.startsWith("create")) {
+                        const instanceId = randomId();
+                        callMethod(ctxInstance, [ propName ], args, 2, instanceId);
+                        if ("createImageData" === propName || "createPattern" === propName) {
+                            (api => {
+                                console.warn(`${api} not implemented`);
+                            })(`${propName}()`);
+                            return {
+                                setTransform: () => {}
+                            };
+                        }
+                        return new WorkerCanvasGradient(winId, instanceId);
+                    }
+                    const methodCallType = ctx2dGetterMethods.includes(propName) ? 1 : 2;
+                    return callMethod(ctxInstance, [ propName ], args, methodCallType);
+                } : ctx[propName] : target[propName],
+                set(target, propName, value) {
+                    if ("string" == typeof propName && propName in ctx) {
+                        ctx[propName] !== value && "function" != typeof value && setter(ctxInstance, [ propName ], value);
+                        ctx[propName] = value;
+                    } else {
+                        target[propName] = value;
+                    }
+                    return true;
+                }
+            };
+            return new Proxy(ctx, CanvasRenderingContext2D);
+        };
+        const createContextWebGL = (canvasInstance, contextType, contextAttributes) => {
+            const winId = canvasInstance[WinIdKey];
+            const ctxInstanceId = randomId();
+            const ctxInstance = {
+                [WinIdKey]: winId,
+                [InstanceIdKey]: ctxInstanceId,
+                [ApplyPathKey]: []
+            };
+            const ctx = callMethod(canvasInstance, [ "getContext" ], [ contextType, contextAttributes ], 1, ctxInstanceId);
+            const WebGLRenderingContextHandler = {
+                get: (target, propName) => "string" == typeof propName ? "function" != typeof ctx[propName] ? ctx[propName] : (...args) => callMethod(ctxInstance, [ propName ], args, getWebGlMethodCallType(propName)) : target[propName],
+                set(target, propName, value) {
+                    if ("string" == typeof propName && propName in ctx) {
+                        ctx[propName] !== value && "function" != typeof value && setter(ctxInstance, [ propName ], value);
+                        ctx[propName] = value;
+                    } else {
+                        target[propName] = value;
+                    }
+                    return true;
+                }
+            };
+            return new Proxy(ctx, WebGLRenderingContextHandler);
+        };
+        const ctxWebGLGetterMethods = "checkFramebufferStatus,makeXRCompatible".split(",");
+        const getWebGlMethodCallType = methodName => methodName.startsWith("create") || methodName.startsWith("get") || methodName.startsWith("is") || ctxWebGLGetterMethods.includes(methodName) ? 1 : 2;
+        defineCstr(win, "CanvasGradient", WorkerCanvasGradient);
+        defineCstr(win, "CanvasPattern", WorkerCanvasPattern);
+        definePrototypePropertyDescriptor(win.HTMLCanvasElement, HTMLCanvasDescriptorMap);
+    };
+    const initMedia = (WorkerBase, WorkerEventTargetProxy, env, win) => {
+        var _a, _b;
+        win.Audio = defineCstrName("HTMLAudioElement", class {
+            constructor(src) {
+                const audio = env.$createNode$("audio", randomId());
+                audio.src = src;
+                return audio;
+            }
+        });
+        const WorkerAudioTrack = class extends WorkerBase {
+            get enabled() {
+                return getter(this, [ "enabled" ]);
+            }
+            set enabled(value) {
+                setter(this, [ "enabled" ], value);
+            }
+            get id() {
+                return getter(this, [ "id" ]);
+            }
+            get kind() {
+                return getter(this, [ "kind" ]);
+            }
+            get label() {
+                return getter(this, [ "label" ]);
+            }
+            get language() {
+                return getter(this, [ "language" ]);
+            }
+            get sourceBuffer() {
+                return new WorkerSourceBuffer(this);
+            }
+        };
+        const WorkerAudioTrackList = class {
+            constructor(mediaElm) {
+                const winId = mediaElm[WinIdKey];
+                const instanceId = mediaElm[InstanceIdKey];
+                const instance = {
+                    addEventListener(...args) {
+                        callMethod(mediaElm, [ "audioTracks", "addEventListener" ], args, 3);
+                    },
+                    getTrackById: (...args) => callMethod(mediaElm, [ "audioTracks", "getTrackById" ], args),
+                    get length() {
+                        return getter(mediaElm, [ "audioTracks", "length" ]);
+                    },
+                    removeEventListener(...args) {
+                        callMethod(mediaElm, [ "audioTracks", "removeEventListener" ], args, 3);
+                    }
+                };
+                return new Proxy(instance, {
+                    get: (target, propName) => "number" == typeof propName ? new WorkerAudioTrack(winId, instanceId, [ "audioTracks", propName ]) : target[propName]
+                });
+            }
+        };
+        const WorkerSourceBufferList = defineCstr(win, "SourceBufferList", class extends Array {
+            constructor(mediaSource) {
+                super();
+                this[MediaSourceKey] = mediaSource;
+            }
+            addEventListener(...args) {
+                callMethod(this[MediaSourceKey], [ "sourceBuffers", "addEventListener" ], args, 3);
+            }
+            removeEventListener(...args) {
+                callMethod(this[MediaSourceKey], [ "sourceBuffers", "removeEventListener" ], args, 3);
+            }
+        });
+        const WorkerSourceBuffer = defineCstr(win, "SourceBuffer", (_b = class extends WorkerEventTargetProxy {
+            constructor(mediaSource) {
+                super(mediaSource[WinIdKey], mediaSource[InstanceIdKey], [ "sourceBuffers" ]);
+                this[_a] = [];
+                this[MediaSourceKey] = mediaSource;
+            }
+            abort() {
+                const sbIndex = getSourceBufferIndex(this);
+                callMethod(this, [ sbIndex, "appendWindowStart" ], EMPTY_ARRAY, 1);
+            }
+            addEventListener(...args) {
+                const sbIndex = getSourceBufferIndex(this);
+                callMethod(this, [ sbIndex, "addEventListener" ], args, 3);
+            }
+            appendBuffer(buf) {
+                this[SourceBufferTasksKey].push([ "appendBuffer", [ buf ], buf ]);
+                drainSourceBufferQueue(this);
+            }
+            get appendWindowStart() {
+                const sbIndex = getSourceBufferIndex(this);
+                return getter(this, [ sbIndex, "appendWindowStart" ]);
+            }
+            set appendWindowStart(value) {
+                const sbIndex = getSourceBufferIndex(this);
+                setter(this, [ sbIndex, "appendWindowStart" ], value);
+            }
+            get appendWindowEnd() {
+                const sbIndex = getSourceBufferIndex(this);
+                return getter(this, [ sbIndex, "appendWindowEnd" ]);
+            }
+            set appendWindowEnd(value) {
+                const sbIndex = getSourceBufferIndex(this);
+                setter(this, [ sbIndex, "appendWindowEnd" ], value);
+            }
+            get buffered() {
+                const mediaSource = this[MediaSourceKey];
+                const sbIndex = getSourceBufferIndex(this);
+                const timeRanges = new WorkerTimeRanges(mediaSource[WinIdKey], mediaSource[InstanceIdKey], [ "sourceBuffers", sbIndex, "buffered" ]);
+                return timeRanges;
+            }
+            changeType(mimeType) {
+                const sbIndex = getSourceBufferIndex(this);
+                callMethod(this, [ sbIndex, "changeType" ], [ mimeType ], 2);
+            }
+            get mode() {
+                const sbIndex = getSourceBufferIndex(this);
+                return getter(this, [ sbIndex, "mode" ]);
+            }
+            set mode(value) {
+                const sbIndex = getSourceBufferIndex(this);
+                setter(this, [ sbIndex, "mode" ], value);
+            }
+            remove(start, end) {
+                this[SourceBufferTasksKey].push([ "remove", [ start, end ] ]);
+                drainSourceBufferQueue(this);
+            }
+            removeEventListener(...args) {
+                const sbIndex = getSourceBufferIndex(this);
+                callMethod(this, [ sbIndex, "removeEventListener" ], args, 3);
+            }
+            get timestampOffset() {
+                const sbIndex = getSourceBufferIndex(this);
+                return getter(this, [ sbIndex, "timestampOffset" ]);
+            }
+            set timestampOffset(value) {
+                const sbIndex = getSourceBufferIndex(this);
+                setter(this, [ sbIndex, "timestampOffset" ], value);
+            }
+            get updating() {
+                const sbIndex = getSourceBufferIndex(this);
+                return getter(this, [ sbIndex, "updating" ]);
+            }
+        }, _a = SourceBufferTasksKey, _b));
+        const WorkerTimeRanges = defineCstr(win, "TimeRanges", class extends WorkerBase {
+            start(...args) {
+                return callMethod(this, [ "start" ], args);
+            }
+            end(...args) {
+                return callMethod(this, [ "end" ], args);
+            }
+            get length() {
+                return getter(this, [ "length" ]);
+            }
+        });
+        const getSourceBufferIndex = sourceBuffer => {
+            if (sourceBuffer) {
+                const mediaSource = sourceBuffer[MediaSourceKey];
+                const sourceBufferList = mediaSource[SourceBuffersKey];
+                return sourceBufferList.indexOf(sourceBuffer);
+            }
+            return -1;
+        };
+        const drainSourceBufferQueue = sourceBuffer => {
+            if (sourceBuffer[SourceBufferTasksKey].length) {
+                if (!sourceBuffer.updating) {
+                    const task = sourceBuffer[SourceBufferTasksKey].shift();
+                    if (task) {
+                        const sbIndex = getSourceBufferIndex(sourceBuffer);
+                        callMethod(sourceBuffer, [ sbIndex, task[0] ], task[1], 3, void 0, task[2]);
+                    }
+                }
+                setTimeout((() => drainSourceBufferQueue(sourceBuffer)), 50);
+            }
+        };
+        const HTMLMediaDescriptorMap = {
+            buffered: {
+                get() {
+                    if (!this[TimeRangesKey]) {
+                        this[TimeRangesKey] = new WorkerTimeRanges(this[WinIdKey], this[InstanceIdKey], [ "buffered" ]);
+                        setTimeout((() => {
+                            this[TimeRangesKey] = void 0;
+                        }), 5e3);
+                    }
+                    return this[TimeRangesKey];
+                }
+            },
+            readyState: {
+                get() {
+                    if (4 === this[ReadyStateKey]) {
+                        return 4;
+                    }
+                    if ("number" != typeof this[ReadyStateKey]) {
+                        this[ReadyStateKey] = getter(this, [ "readyState" ]);
+                        setTimeout((() => {
+                            this[ReadyStateKey] = void 0;
+                        }), 1e3);
+                    }
+                    return this[ReadyStateKey];
+                }
+            }
+        };
+        defineCstr(win, "MediaSource", class extends WorkerEventTargetProxy {
+            constructor() {
+                super(env.$winId$);
+                this[SourceBuffersKey] = new WorkerSourceBufferList(this);
+                constructGlobal(this, "MediaSource", EMPTY_ARRAY);
+            }
+            get activeSourceBuffers() {
+                return [];
+            }
+            addSourceBuffer(mimeType) {
+                const sourceBuffer = new WorkerSourceBuffer(this);
+                this[SourceBuffersKey].push(sourceBuffer);
+                callMethod(this, [ "addSourceBuffer" ], [ mimeType ]);
+                return sourceBuffer;
+            }
+            clearLiveSeekableRange() {
+                callMethod(this, [ "clearLiveSeekableRange" ], EMPTY_ARRAY, 2);
+            }
+            get duration() {
+                return getter(this, [ "duration" ]);
+            }
+            set duration(value) {
+                setter(this, [ "duration" ], value);
+            }
+            endOfStream(endOfStreamError) {
+                callMethod(this, [ "endOfStream" ], [ endOfStreamError ], 3);
+            }
+            get readyState() {
+                return getter(this, [ "readyState" ]);
+            }
+            removeSourceBuffer(sourceBuffer) {
+                const index = getSourceBufferIndex(sourceBuffer);
+                if (index > -1) {
+                    this[SourceBuffersKey].splice(index, 1);
+                    callMethod(this, [ "removeSourceBuffer" ], [ index ], 1);
+                }
+            }
+            setLiveSeekableRange(start, end) {
+                callMethod(this, [ "setLiveSeekableRange" ], [ start, end ], 2);
+            }
+            get sourceBuffers() {
+                return this[SourceBuffersKey];
+            }
+            static isTypeSupported(mimeType) {
+                if (!isStaticTypeSupported.has(mimeType)) {
+                    const isSupported = callMethod(win, [ "MediaSource", "isTypeSupported" ], [ mimeType ]);
+                    isStaticTypeSupported.set(mimeType, isSupported);
+                }
+                return isStaticTypeSupported.get(mimeType);
+            }
+        });
+        const winURL = win.URL = defineCstrName("URL", class extends URL {});
+        const hasAudioTracks = "audioTracks" in win.HTMLMediaElement.prototype;
+        if (hasAudioTracks) {
+            defineCstr(win, "AudioTrackList", WorkerAudioTrackList);
+            defineCstr(win, "AudioTrack", WorkerAudioTrack);
+            HTMLMediaDescriptorMap.audioTracks = {
+                get() {
+                    return new WorkerAudioTrackList(this);
+                }
+            };
+        }
+        definePrototypePropertyDescriptor(win.HTMLMediaElement, HTMLMediaDescriptorMap);
+        winURL.createObjectURL = obj => callMethod(win, [ "URL", "createObjectURL" ], [ obj ]);
+        winURL.revokeObjectURL = obj => callMethod(win, [ "URL", "revokeObjectURL" ], [ obj ]);
+    };
+    const isStaticTypeSupported = new Map;
+    self.$bridgeFromMedia$ = (WorkerBase, WorkerEventTargetProxy, env, win, windowMediaConstructors) => {
+        windowMediaConstructors.map((mediaCstrName => {
+            delete win[mediaCstrName];
+        }));
+        initCanvas(WorkerBase, win);
+        initMedia(WorkerBase, WorkerEventTargetProxy, env, win);
+    };
+})(self);
Index: build/debug/partytown-sandbox-sw.js
===================================================================
--- build/debug/partytown-sandbox-sw.js	(revision 3189893)
+++ build/debug/partytown-sandbox-sw.js	(working copy)
@@ -1 +1,599 @@
-(e=>{const t=()=>{},n=e=>e.length,r=e=>{var t,n,r;try{const n=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(n)return n}catch(e){}try{const t=null===(r=null===(n=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===n?void 0:n.constructor)||void 0===r?void 0:r.name;if(t)return t}catch(e){}return""},o=(e,t)=>e.startsWith(t),i=e=>!(o(e,"webkit")||o(e,"toJSON")||o(e,"constructor")||o(e,"toString")||o(e,"_")&&!["__","_n","_x","_nx"].includes(e)),a=e=>11===e.nodeType&&e.host?"#s":e.nodeName,s=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),d={Anchor:"a",DList:"dl",Image:"img",OList:"ol",Paragraph:"p",Quote:"q",TableCaption:"caption",TableCell:"td",TableCol:"colgroup",TableRow:"tr",TableSection:"tbody",UList:"ul"},c={Graphics:"g",SVG:"svg"},l={preserveBehavior:!1},p=Object.freeze((e=>{const t=new Set;let n=[];do{Object.getOwnPropertyNames(n).forEach((e=>{"function"==typeof n[e]&&t.add(e)}))}while((n=Object.getPrototypeOf(n))!==Object.prototype);return Array.from(t)})()),$=Symbol(),u=Symbol(),f=new Map,m=new Map,w={},g=new WeakMap,y=(e,t)=>{if(e)return(t=g.get(e))||(t=e[$])||v(e,t=s()),t},h=(e,t,n,r,o)=>{if((n=w[e])&&n.$window$){if(e===t)return n.$window$;if(r=n.$window$.document,"d"===(o=t.split(".").pop()))return r;if("e"===o)return r.documentElement;if("h"===o)return r.head;if("b"===o)return r.body}return f.get(t)},v=(e,t,n)=>{e&&(f.set(t,e),e[$]=t,e[u]=n=Date.now(),n>b+5e3&&(f.forEach(((e,t)=>{e[u]<b&&e.nodeType&&!e.isConnected&&f.delete(t)})),b=n))};let b=0;const I=e.parent,S=document.implementation.createHTMLDocument(),E=I.partytown||{},O=(E.lib||"/~partytown/")+"debug/",M=e=>{console.debug.apply(console,["%cMain 🌎","background: #717171; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;",e])},T=[],L=e=>(T.includes(e)||T.push(e),T.indexOf(e)+1),j=(e,t,n)=>{const r=((e,t)=>{return n=e,r={value:t},Object.defineProperty(n,"name",{...r,configurable:!0});var n,r})(class extends w[e].$window$.HTMLElement{},n[0]);return"connectedCallback,disconnectedCallback,attributeChangedCallback,adoptedCallback".split(",").map((n=>r.prototype[n]=function(...r){t.postMessage([15,e,y(this),n,r])})),r.observedAttributes=n[1],r},C=(e,t,n,i,s,d)=>void 0!==t&&(i=typeof t)?"string"===i||"number"===i||"boolean"===i||null==t?[0,t]:"function"===i?[6]:(n=n||new Set)&&Array.isArray(t)?n.has(t)?[1,[]]:n.add(t)&&[1,t.map((t=>C(e,t,n)))]:"object"===i?x(t)?[14,{name:t.name,message:t.message,stack:t.stack}]:""===(s=r(t))?[2,{}]:"Window"===s?[3,[e,e]]:"HTMLCollection"===s||"NodeList"===s?[7,Array.from(t).map((t=>C(e,t,n)[1]))]:s.endsWith("Event")?[5,A(e,t,n)]:"CSSRuleList"===s?[12,Array.from(t).map(k)]:o(s,"CSS")&&s.endsWith("Rule")?[11,k(t)]:"CSSStyleDeclaration"===s?[13,A(e,t,n)]:"Attr"===s?[10,[t.name,t.value]]:t.nodeType?[3,[e,y(t),a(t),d]]:[2,A(e,t,n,!0,!0)]:void 0:t,A=(e,t,n,o,a,s,d,c)=>{if(s={},!n.has(t))for(d in n.add(t),t)i(d)&&(c="path"===d&&r(t).endsWith("Event")?t.composedPath():t[d],(o||"function"!=typeof c)&&(a||""!==c)&&(s[d]=C(e,c,n)));return s},k=e=>{let t,n={};for(t in e)U.includes(t)&&(n[t]=String(e[t]));return n};let P=null;const x=t=>{var n;return P=(null===(n=e.top)||void 0===n?void 0:n.Error)||P,t instanceof P},R=(t,n,r,o)=>{if(n)return r=n[0],o=n[1],0===r?o:4===r?_(t,o):1===r?o.map((e=>R(t,e))):3===r?h(o[0],o[1]):5===r?N(W(t,o)):2===r?W(t,o):8===r?o:9===r?new e[n[2]](o):void 0},_=(e,{$winId$:t,$instanceId$:n,$refId$:r},o)=>((o=m.get(r))||(o=function(...o){e.postMessage([9,{$winId$:t,$instanceId$:n,$refId$:r,$thisArg$:C(t,this),$args$:C(t,o)}])},m.set(r,o)),o),N=e=>new("detail"in e?CustomEvent:Event)(e.type,e),W=(e,t,n,r)=>{for(r in n={},t)n[r]=R(e,t[r]);return n},U="cssText,selectorText,href,media,namespaceURI,prefix,name,conditionText".split(","),q=async(e,t)=>{let r,o,i,a,s,d,c={$msgId$:t.$msgId$},l=n(t.$tasks$),p=0;for(;p<l;p++)try{d=p===l-1,r=t.$tasks$[p],o=r.$winId$,i=r.$applyPath$,!w[o]&&o.startsWith("f_")&&await new Promise((e=>{let t=0,n=()=>{w[o]||t++>1e3?e():requestAnimationFrame(n)};n()})),1===i[0]&&i[1]in w[o].$window$?v(new w[o].$window$[i[1]](...R(e,i[2])),r.$instanceId$):(a=h(o,r.$instanceId$),a?(s=F(e,o,a,i,d,r.$groupedGetters$),r.$assignInstanceId$&&("string"==typeof r.$assignInstanceId$?v(s,r.$assignInstanceId$):w[r.$assignInstanceId$.$winId$]={$winId$:r.$assignInstanceId$.$winId$,$window$:{document:s}}),"object"==typeof($=s)&&$&&$.then&&(s=await s,d&&(c.$isPromise$=!0)),d&&(c.$rtnValue$=C(o,s,void 0,void 0,void 0,r.$instanceId$))):(c.$error$=`Error finding instance "${r.$instanceId$}" on window ${L(o)}`,console.error(c.$error$,r)))}catch(e){d?c.$error$=String(e.stack||e):console.error(e)}var $;return c},F=(e,t,o,i,a,s)=>{let d,c,l,p,$,u=0,f=n(i);for(;u<f;u++){c=i[u],d=i[u+1],l=i[u-1];try{if(!Array.isArray(d))if("string"==typeof c||"number"==typeof c){if(u+1===f&&s)return $={},s.map((e=>$[e]=o[e])),$;o=o[c]}else{if(0===d)return void(o[l]=R(e,c));if("function"==typeof o[l]&&(p=R(e,c),"define"===l&&"CustomElementRegistry"===r(o)&&(p[1]=j(t,e,p[1])),"insertRule"===l&&p[1]>n(o.cssRules)&&(p[1]=n(o.cssRules)),o=o[l].apply(o,p),"play"===l))return Promise.resolve()}}catch(e){if(a)throw e;console.debug("Non-blocking setter error:",e)}}return o},z=(e,t)=>{let r,o,i,a=t.$winId$,s=t.$window$,d=s.document,c='script[type="text/partytown"]:not([data-ptid]):not([data-pterror])',$=c+":not([async]):not([defer])";if(d&&d.body)if(r=d.querySelector($),r||(r=d.querySelector(c)),r)r.dataset.ptid=o=y(r,a),i={$winId$:a,$instanceId$:o},r.src?(i.$url$=r.src,i.$orgUrl$=r.dataset.ptsrc||r.src):i.$content$=r.innerHTML,e.postMessage([7,i]);else{if(!t.$isInitialized$){t.$isInitialized$=1,((e,t,r)=>{let o,i,a=r._ptf,s=(r.partytown||{}).forward||[],d=(n,r)=>e.postMessage([10,{$winId$:t,$forward$:n,$args$:C(t,Array.from(r))}]);if(r._ptf=void 0,s.map((e=>{const[t,{preserveBehavior:o}]=(e=>{if("string"==typeof e)return[e,l];const[t,n=l]=e;return[t,{...l,...n}]})(e);i=r,t.split(".").map(((e,t,a)=>{var s;i=i[a[t]]=t+1<n(a)?i[a[t]]||(s=a[t+1],p.includes(s)?[]:{}):(()=>{let e=null;if(o){const{methodOrProperty:t,thisObject:n}=((e,t)=>{let n=e;for(let e=0;e<t.length-1;e+=1)n=n[t[e]];return{thisObject:n,methodOrProperty:t.length>0?n[t[t.length-1]]:void 0}})(r,a);"function"==typeof t&&(e=(...e)=>t.apply(n,...e))}return(...t)=>{let n;return e&&(n=e(t)),d(a,t),n}})()}))})),a)for(o=0;o<n(a);o+=2)d(a[o],a[o+1])})(e,a,s),d.dispatchEvent(new CustomEvent("pt0"));{const e=s===s.top?"top":"iframe";M(`Executed ${e} window ${L(a)} environment scripts in ${(performance.now()-t.$startTime$).toFixed(1)}ms`)}}e.postMessage([8,a])}else requestAnimationFrame((()=>z(e,t)))},D=(e,t,n)=>{if(!g.has(n)){g.set(n,t);const r=n.document,o=n.history,i=g.get(n.parent);let a=!1;const s=[],d=e=>{a?e():s.push(e)},c=()=>{e.postMessage([5,{$winId$:t,$parentWinId$:i,$url$:r.baseURI,$visibilityState$:r.visibilityState}]),setTimeout((()=>{a=!0,s.forEach((e=>{e()}))}))},l=o.pushState.bind(o),p=o.replaceState.bind(o),$=(n,o,i,a)=>()=>{e.postMessage([13,{$winId$:t,type:n,state:o,url:r.baseURI,newUrl:i,oldUrl:a}])};o.pushState=(e,t,n)=>{l(e,t,n),d($(0,e,null==n?void 0:n.toString()))},o.replaceState=(e,t,n)=>{p(e,t,n),d($(1,e,null==n?void 0:n.toString()))},n.addEventListener("popstate",(e=>{d($(2,e.state))})),n.addEventListener("hashchange",(e=>{d($(3,{},e.newURL,e.oldURL))})),n.addEventListener("ptupdate",(()=>{z(e,w[t])})),r.addEventListener("visibilitychange",(()=>e.postMessage([14,t,r.visibilityState]))),w[t]={$winId$:t,$window$:n},w[t].$startTime$=performance.now(),M(`Registered ${t===i?"top":"iframe"} window ${L(t)}`),"complete"===r.readyState?c():n.addEventListener("load",c)}},G=()=>{const e=S.createElement("i"),t=S.createTextNode(""),n=S.createComment(""),r=S.createDocumentFragment(),o=S.createElement("p").attachShadow({mode:"open"}),i=X(I,"IntersectionObserver"),a=X(I,"MutationObserver"),s=X(I,"ResizeObserver"),d=I.performance,c=I.screen,l=[[I.history],[d],[d.navigation],[d.timing],[c],[c.orientation],[I.visualViewport],[i,12],[a,12],[s,12],[t],[n],[r],[o],[e],[e.attributes],[e.classList],[e.dataset],[e.style],[S],[S.doctype]],p=[B("Window",I),B("Node",t)],$=function(e){return JSON.stringify(e,((e,t)=>("function"==typeof t&&(t=String(t)).startsWith(e+"(")&&(t="function "+t),"loadScriptsOnMainThread"===e&&(t=t.map((e=>Array.isArray(e)?e:["string"==typeof e?"string":"regexp","string"==typeof e?e:e.source]))),t)))}(E),u={$config$:$,$interfaces$:V(l,p),$libPath$:new URL(O,I.location)+"",$origin$:origin,$tabId$:I._pttab};return K(u.$interfaces$,I,"IntersectionObserverEntry"),u},H=()=>{const e=Object.getOwnPropertyNames(I).map((e=>((e,t,n,r)=>{if(n=t.match(/^(HTML|SVG)(.+)Element$/))return r=n[2],"S"==t[0]?e.createElementNS("http://www.w3.org/2000/svg",c[r]||r.slice(0,2).toLowerCase()+r.slice(2)):e.createElement(d[r]||r)})(S,e))).filter((e=>e)).map((e=>[e]));return V(e,[])},V=(e,t)=>{const n=new Set(["Object"]);return e.filter((e=>e[0])).map((e=>{const t=e[0],n=e[1],o=r(t);return[o,I[o].prototype,t,n]})).map((([e,r,o,i])=>J(n,t,e,r,o,i))),t},B=(e,t,n)=>{let r=[],o=[e,"Object",r];for(n in t)Q(r,t,n);return o},J=(e,t,n,o,i,s)=>{if(!e.has(n)){e.add(n);const d=Object.getPrototypeOf(o),c=r(d),l=[],p=Object.getOwnPropertyDescriptors(o);J(e,t,c,d,i,s);for(const e in p)Q(l,i,e);t.push([n,c,l,s,a(i)])}},Q=(e,t,n,o,a,s)=>{try{i(n)&&isNaN(n[0])&&"all"!==n&&("function"==(a=typeof(o=t[n]))?(String(o).includes("[native")||Object.getPrototypeOf(t)[n])&&e.push([n,5]):"object"===a&&null!=o?"Object"!==(s=r(o))&&"Function"!==s&&self[s]&&e.push([n,o.nodeType||s]):"symbol"!==a&&(n.toUpperCase()===n?e.push([n,6,o]):e.push([n,6])))}catch(e){console.warn(e)}},X=(e,n)=>void 0!==e[n]?new e[n](t):0,K=(e,t,n)=>{void 0!==t[n]&&e.push([n,"Object",Object.keys(t[n].prototype).map((e=>[e,6])),12])};let Y;(t=>{const n=e.navigator.serviceWorker;return n.getRegistration().then((e=>(n.addEventListener("message",(t=>{return n=t.data,r=t=>e.active&&e.active.postMessage(t),q(Y,n).then(r);var n,r})),(e,t)=>{0===t[0]?e.postMessage([1,G()]):2===t[0]?e.postMessage([3,H()]):((e,t,n)=>{4===t[0]?D(e,s(),I):(n=w[t[1]])&&(7===t[0]?requestAnimationFrame((()=>z(e,n))):6===t[0]&&((e,t,n,r,o)=>{(o=t.$window$.document.querySelector(`[data-ptid="${n}"]`))&&(r?o.dataset.pterror=r:o.type+="-x",delete o.dataset.ptid),z(e,t)})(e,n,t[2],t[3]))})(e,t)})))})().then((e=>{e&&(Y=new Worker(O+"partytown-ww-sw.js?v=0.10.2-dev1727590485751",{name:"Partytown 🎉"}),Y.onmessage=t=>{const n=t.data;12===n[0]?q(Y,n[1]):e(Y,n)},M("Created Partytown web worker (0.10.2-dev1727590485751)"),Y.onerror=e=>console.error("Web Worker Error",e),I.addEventListener("pt1",(e=>D(Y,y(e.detail.frameElement),e.detail))))}))})(window);
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+(window => {
+    const isPromise = v => "object" == typeof v && v && v.then;
+    const noop = () => {};
+    const len = obj => obj.length;
+    const getConstructorName = obj => {
+        var _a, _b, _c;
+        try {
+            const constructorName = null === (_a = null == obj ? void 0 : obj.constructor) || void 0 === _a ? void 0 : _a.name;
+            if (constructorName) {
+                return constructorName;
+            }
+        } catch (e) {}
+        try {
+            const zoneJsConstructorName = null === (_c = null === (_b = null == obj ? void 0 : obj.__zone_symbol__originalInstance) || void 0 === _b ? void 0 : _b.constructor) || void 0 === _c ? void 0 : _c.name;
+            if (zoneJsConstructorName) {
+                return zoneJsConstructorName;
+            }
+        } catch (e) {}
+        return "";
+    };
+    const startsWith = (str, val) => str.startsWith(val);
+    const isValidMemberName = memberName => !(startsWith(memberName, "webkit") || startsWith(memberName, "toJSON") || startsWith(memberName, "constructor") || startsWith(memberName, "toString") || startsWith(memberName, "_") && ![ "__", "_n", "_x", "_nx" ].includes(memberName));
+    const getNodeName = node => 11 === node.nodeType && node.host ? "#s" : node.nodeName;
+    const randomId = () => Math.round(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);
+    const defineConstructorName = (Cstr, value) => ((obj, memberName, descriptor) => Object.defineProperty(obj, memberName, {
+        ...descriptor,
+        configurable: true
+    }))(Cstr, "name", {
+        value: value
+    });
+    const htmlConstructorTags = {
+        Anchor: "a",
+        DList: "dl",
+        Image: "img",
+        OList: "ol",
+        Paragraph: "p",
+        Quote: "q",
+        TableCaption: "caption",
+        TableCell: "td",
+        TableCol: "colgroup",
+        TableRow: "tr",
+        TableSection: "tbody",
+        UList: "ul"
+    };
+    const svgConstructorTags = {
+        Graphics: "g",
+        SVG: "svg"
+    };
+    const defaultPartytownForwardPropertySettings = {
+        preserveBehavior: false
+    };
+    const arrayMethods = Object.freeze((obj => {
+        const properties = new Set;
+        let currentObj = obj;
+        do {
+            Object.getOwnPropertyNames(currentObj).forEach((item => {
+                "function" == typeof currentObj[item] && properties.add(item);
+            }));
+        } while ((currentObj = Object.getPrototypeOf(currentObj)) !== Object.prototype);
+        return Array.from(properties);
+    })([]));
+    const InstanceIdKey = Symbol();
+    const CreatedKey = Symbol();
+    const instances = new Map;
+    const mainRefs = new Map;
+    const winCtxs = {};
+    const windowIds = new WeakMap;
+    const getAndSetInstanceId = (instance, instanceId) => {
+        if (instance) {
+            if (instanceId = windowIds.get(instance)) {
+                return instanceId;
+            }
+            (instanceId = instance[InstanceIdKey]) || setInstanceId(instance, instanceId = randomId());
+            return instanceId;
+        }
+    };
+    const getInstance = (winId, instanceId, win, doc, docId) => {
+        if ((win = winCtxs[winId]) && win.$window$) {
+            if (winId === instanceId) {
+                return win.$window$;
+            }
+            doc = win.$window$.document;
+            docId = instanceId.split(".").pop();
+            if ("d" === docId) {
+                return doc;
+            }
+            if ("e" === docId) {
+                return doc.documentElement;
+            }
+            if ("h" === docId) {
+                return doc.head;
+            }
+            if ("b" === docId) {
+                return doc.body;
+            }
+        }
+        return instances.get(instanceId);
+    };
+    const setInstanceId = (instance, instanceId, now) => {
+        if (instance) {
+            instances.set(instanceId, instance);
+            instance[InstanceIdKey] = instanceId;
+            instance[CreatedKey] = now = Date.now();
+            if (now > lastCleanup + 5e3) {
+                instances.forEach(((storedInstance, instanceId) => {
+                    storedInstance[CreatedKey] < lastCleanup && storedInstance.nodeType && !storedInstance.isConnected && instances.delete(instanceId);
+                }));
+                lastCleanup = now;
+            }
+        }
+    };
+    let lastCleanup = 0;
+    const mainWindow = window.parent;
+    const docImpl = document.implementation.createHTMLDocument();
+    const config = mainWindow.partytown || {};
+    const libPath = (config.lib || "/~partytown/") + "debug/";
+    const logMain = msg => {
+        console.debug.apply(console, [ "%cMain 🌎", "background: #717171; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;", msg ]);
+    };
+    const winIds = [];
+    const normalizedWinId = winId => {
+        winIds.includes(winId) || winIds.push(winId);
+        return winIds.indexOf(winId) + 1;
+    };
+    const defineCustomElement = (winId, worker, ceData) => {
+        const Cstr = defineConstructorName(class extends winCtxs[winId].$window$.HTMLElement {}, ceData[0]);
+        const ceCallbackMethods = "connectedCallback,disconnectedCallback,attributeChangedCallback,adoptedCallback".split(",");
+        ceCallbackMethods.map((callbackMethodName => Cstr.prototype[callbackMethodName] = function(...args) {
+            worker.postMessage([ 15, winId, getAndSetInstanceId(this), callbackMethodName, args ]);
+        }));
+        Cstr.observedAttributes = ceData[1];
+        return Cstr;
+    };
+    const serializeForWorker = ($winId$, value, added, type, cstrName, prevInstanceId) => void 0 !== value && (type = typeof value) ? "string" === type || "number" === type || "boolean" === type || null == value ? [ 0, value ] : "function" === type ? [ 6 ] : (added = added || new Set) && Array.isArray(value) ? added.has(value) ? [ 1, [] ] : added.add(value) && [ 1, value.map((v => serializeForWorker($winId$, v, added))) ] : "object" === type ? serializedValueIsError(value) ? [ 14, {
+        name: value.name,
+        message: value.message,
+        stack: value.stack
+    } ] : "" === (cstrName = getConstructorName(value)) ? [ 2, {} ] : "Window" === cstrName ? [ 3, [ $winId$, $winId$ ] ] : "HTMLCollection" === cstrName || "NodeList" === cstrName ? [ 7, Array.from(value).map((v => serializeForWorker($winId$, v, added)[1])) ] : cstrName.endsWith("Event") ? [ 5, serializeObjectForWorker($winId$, value, added) ] : "CSSRuleList" === cstrName ? [ 12, Array.from(value).map(serializeCssRuleForWorker) ] : startsWith(cstrName, "CSS") && cstrName.endsWith("Rule") ? [ 11, serializeCssRuleForWorker(value) ] : "CSSStyleDeclaration" === cstrName ? [ 13, serializeObjectForWorker($winId$, value, added) ] : "Attr" === cstrName ? [ 10, [ value.name, value.value ] ] : value.nodeType ? [ 3, [ $winId$, getAndSetInstanceId(value), getNodeName(value), prevInstanceId ] ] : [ 2, serializeObjectForWorker($winId$, value, added, true, true) ] : void 0 : value;
+    const serializeObjectForWorker = (winId, obj, added, includeFunctions, includeEmptyStrings, serializedObj, propName, propValue) => {
+        serializedObj = {};
+        if (!added.has(obj)) {
+            added.add(obj);
+            for (propName in obj) {
+                if (isValidMemberName(propName)) {
+                    propValue = "path" === propName && getConstructorName(obj).endsWith("Event") ? obj.composedPath() : obj[propName];
+                    (includeFunctions || "function" != typeof propValue) && (includeEmptyStrings || "" !== propValue) && (serializedObj[propName] = serializeForWorker(winId, propValue, added));
+                }
+            }
+        }
+        return serializedObj;
+    };
+    const serializeCssRuleForWorker = cssRule => {
+        let obj = {};
+        let key;
+        for (key in cssRule) {
+            validCssRuleProps.includes(key) && (obj[key] = String(cssRule[key]));
+        }
+        return obj;
+    };
+    let ErrorObject = null;
+    const serializedValueIsError = value => {
+        var _a;
+        ErrorObject = (null === (_a = window.top) || void 0 === _a ? void 0 : _a.Error) || ErrorObject;
+        return value instanceof ErrorObject;
+    };
+    const deserializeFromWorker = (worker, serializedTransfer, serializedType, serializedValue) => {
+        if (serializedTransfer) {
+            serializedType = serializedTransfer[0];
+            serializedValue = serializedTransfer[1];
+            return 0 === serializedType ? serializedValue : 4 === serializedType ? deserializeRefFromWorker(worker, serializedValue) : 1 === serializedType ? serializedValue.map((v => deserializeFromWorker(worker, v))) : 3 === serializedType ? getInstance(serializedValue[0], serializedValue[1]) : 5 === serializedType ? constructEvent(deserializeObjectFromWorker(worker, serializedValue)) : 2 === serializedType ? deserializeObjectFromWorker(worker, serializedValue) : 8 === serializedType ? serializedValue : 9 === serializedType ? new window[serializedTransfer[2]](serializedValue) : void 0;
+        }
+    };
+    const deserializeRefFromWorker = (worker, {$winId$: $winId$, $instanceId$: $instanceId$, $refId$: $refId$}, ref) => {
+        ref = mainRefs.get($refId$);
+        if (!ref) {
+            ref = function(...args) {
+                worker.postMessage([ 9, {
+                    $winId$: $winId$,
+                    $instanceId$: $instanceId$,
+                    $refId$: $refId$,
+                    $thisArg$: serializeForWorker($winId$, this),
+                    $args$: serializeForWorker($winId$, args)
+                } ]);
+            };
+            mainRefs.set($refId$, ref);
+        }
+        return ref;
+    };
+    const constructEvent = eventProps => new ("detail" in eventProps ? CustomEvent : Event)(eventProps.type, eventProps);
+    const deserializeObjectFromWorker = (worker, serializedValue, obj, key) => {
+        obj = {};
+        for (key in serializedValue) {
+            obj[key] = deserializeFromWorker(worker, serializedValue[key]);
+        }
+        return obj;
+    };
+    const validCssRuleProps = "cssText,selectorText,href,media,namespaceURI,prefix,name,conditionText".split(",");
+    const mainAccessHandler = async (worker, accessReq) => {
+        let accessRsp = {
+            $msgId$: accessReq.$msgId$
+        };
+        let totalTasks = len(accessReq.$tasks$);
+        let i = 0;
+        let task;
+        let winId;
+        let applyPath;
+        let instance;
+        let rtnValue;
+        let isLast;
+        for (;i < totalTasks; i++) {
+            try {
+                isLast = i === totalTasks - 1;
+                task = accessReq.$tasks$[i];
+                winId = task.$winId$;
+                applyPath = task.$applyPath$;
+                !winCtxs[winId] && winId.startsWith("f_") && await new Promise((resolve => {
+                    let check = 0;
+                    let callback = () => {
+                        winCtxs[winId] || check++ > 1e3 ? resolve() : requestAnimationFrame(callback);
+                    };
+                    callback();
+                }));
+                if (1 === applyPath[0] && applyPath[1] in winCtxs[winId].$window$) {
+                    setInstanceId(new winCtxs[winId].$window$[applyPath[1]](...deserializeFromWorker(worker, applyPath[2])), task.$instanceId$);
+                } else {
+                    instance = getInstance(winId, task.$instanceId$);
+                    if (instance) {
+                        rtnValue = applyToInstance(worker, winId, instance, applyPath, isLast, task.$groupedGetters$);
+                        task.$assignInstanceId$ && ("string" == typeof task.$assignInstanceId$ ? setInstanceId(rtnValue, task.$assignInstanceId$) : winCtxs[task.$assignInstanceId$.$winId$] = {
+                            $winId$: task.$assignInstanceId$.$winId$,
+                            $window$: {
+                                document: rtnValue
+                            }
+                        });
+                        if (isPromise(rtnValue)) {
+                            rtnValue = await rtnValue;
+                            isLast && (accessRsp.$isPromise$ = true);
+                        }
+                        isLast && (accessRsp.$rtnValue$ = serializeForWorker(winId, rtnValue, void 0, void 0, void 0, task.$instanceId$));
+                    } else {
+                        accessRsp.$error$ = `Error finding instance "${task.$instanceId$}" on window ${normalizedWinId(winId)}`;
+                        console.error(accessRsp.$error$, task);
+                    }
+                }
+            } catch (e) {
+                isLast ? accessRsp.$error$ = String(e.stack || e) : console.error(e);
+            }
+        }
+        return accessRsp;
+    };
+    const applyToInstance = (worker, winId, instance, applyPath, isLast, groupedGetters) => {
+        let i = 0;
+        let l = len(applyPath);
+        let next;
+        let current;
+        let previous;
+        let args;
+        let groupedRtnValues;
+        for (;i < l; i++) {
+            current = applyPath[i];
+            next = applyPath[i + 1];
+            previous = applyPath[i - 1];
+            try {
+                if (!Array.isArray(next)) {
+                    if ("string" == typeof current || "number" == typeof current) {
+                        if (i + 1 === l && groupedGetters) {
+                            groupedRtnValues = {};
+                            groupedGetters.map((propName => groupedRtnValues[propName] = instance[propName]));
+                            return groupedRtnValues;
+                        }
+                        instance = instance[current];
+                    } else {
+                        if (0 === next) {
+                            instance[previous] = deserializeFromWorker(worker, current);
+                            return;
+                        }
+                        if ("function" == typeof instance[previous]) {
+                            args = deserializeFromWorker(worker, current);
+                            "define" === previous && "CustomElementRegistry" === getConstructorName(instance) && (args[1] = defineCustomElement(winId, worker, args[1]));
+                            "insertRule" === previous && args[1] > len(instance.cssRules) && (args[1] = len(instance.cssRules));
+                            instance = instance[previous].apply(instance, args);
+                            if ("play" === previous) {
+                                return Promise.resolve();
+                            }
+                        }
+                    }
+                }
+            } catch (err) {
+                if (isLast) {
+                    throw err;
+                }
+                console.debug("Non-blocking setter error:", err);
+            }
+        }
+        return instance;
+    };
+    const mainForwardTrigger = (worker, $winId$, win) => {
+        let queuedForwardCalls = win._ptf;
+        let forwards = (win.partytown || {}).forward || [];
+        let i;
+        let mainForwardFn;
+        let forwardCall = ($forward$, args) => worker.postMessage([ 10, {
+            $winId$: $winId$,
+            $forward$: $forward$,
+            $args$: serializeForWorker($winId$, Array.from(args))
+        } ]);
+        win._ptf = void 0;
+        forwards.map((forwardProps => {
+            const [property, {preserveBehavior: preserveBehavior}] = (propertyOrPropertyWithSettings => {
+                if ("string" == typeof propertyOrPropertyWithSettings) {
+                    return [ propertyOrPropertyWithSettings, defaultPartytownForwardPropertySettings ];
+                }
+                const [property, settings = defaultPartytownForwardPropertySettings] = propertyOrPropertyWithSettings;
+                return [ property, {
+                    ...defaultPartytownForwardPropertySettings,
+                    ...settings
+                } ];
+            })(forwardProps);
+            mainForwardFn = win;
+            property.split(".").map(((_, i, arr) => {
+                mainForwardFn = mainForwardFn[arr[i]] = i + 1 < len(arr) ? mainForwardFn[arr[i]] || (propertyName => arrayMethods.includes(propertyName) ? [] : {})(arr[i + 1]) : (() => {
+                    let originalFunction = null;
+                    if (preserveBehavior) {
+                        const {methodOrProperty: methodOrProperty, thisObject: thisObject} = ((window, properties) => {
+                            let thisObject = window;
+                            for (let i = 0; i < properties.length - 1; i += 1) {
+                                thisObject = thisObject[properties[i]];
+                            }
+                            return {
+                                thisObject: thisObject,
+                                methodOrProperty: properties.length > 0 ? thisObject[properties[properties.length - 1]] : void 0
+                            };
+                        })(win, arr);
+                        "function" == typeof methodOrProperty && (originalFunction = (...args) => methodOrProperty.apply(thisObject, ...args));
+                    }
+                    return (...args) => {
+                        let returnValue;
+                        originalFunction && (returnValue = originalFunction(args));
+                        forwardCall(arr, args);
+                        return returnValue;
+                    };
+                })();
+            }));
+        }));
+        if (queuedForwardCalls) {
+            for (i = 0; i < len(queuedForwardCalls); i += 2) {
+                forwardCall(queuedForwardCalls[i], queuedForwardCalls[i + 1]);
+            }
+        }
+    };
+    const readNextScript = (worker, winCtx) => {
+        let $winId$ = winCtx.$winId$;
+        let win = winCtx.$window$;
+        let doc = win.document;
+        let scriptSelector = 'script[type="text/partytown"]:not([data-ptid]):not([data-pterror])';
+        let blockingScriptSelector = scriptSelector + ":not([async]):not([defer])";
+        let scriptElm;
+        let $instanceId$;
+        let scriptData;
+        if (doc && doc.body) {
+            scriptElm = doc.querySelector(blockingScriptSelector);
+            scriptElm || (scriptElm = doc.querySelector(scriptSelector));
+            if (scriptElm) {
+                scriptElm.dataset.ptid = $instanceId$ = getAndSetInstanceId(scriptElm, $winId$);
+                scriptData = {
+                    $winId$: $winId$,
+                    $instanceId$: $instanceId$
+                };
+                if (scriptElm.src) {
+                    scriptData.$url$ = scriptElm.src;
+                    scriptData.$orgUrl$ = scriptElm.dataset.ptsrc || scriptElm.src;
+                } else {
+                    scriptData.$content$ = scriptElm.innerHTML;
+                }
+                worker.postMessage([ 7, scriptData ]);
+            } else {
+                if (!winCtx.$isInitialized$) {
+                    winCtx.$isInitialized$ = 1;
+                    mainForwardTrigger(worker, $winId$, win);
+                    doc.dispatchEvent(new CustomEvent("pt0"));
+                    {
+                        const winType = win === win.top ? "top" : "iframe";
+                        logMain(`Executed ${winType} window ${normalizedWinId($winId$)} environment scripts in ${(performance.now() - winCtx.$startTime$).toFixed(1)}ms`);
+                    }
+                }
+                worker.postMessage([ 8, $winId$ ]);
+            }
+        } else {
+            requestAnimationFrame((() => readNextScript(worker, winCtx)));
+        }
+    };
+    const registerWindow = (worker, $winId$, $window$) => {
+        if (!windowIds.has($window$)) {
+            windowIds.set($window$, $winId$);
+            const doc = $window$.document;
+            const history = $window$.history;
+            const $parentWinId$ = windowIds.get($window$.parent);
+            let initialised = false;
+            const onInitialisedQueue = [];
+            const onInitialised = callback => {
+                initialised ? callback() : onInitialisedQueue.push(callback);
+            };
+            const sendInitEnvData = () => {
+                worker.postMessage([ 5, {
+                    $winId$: $winId$,
+                    $parentWinId$: $parentWinId$,
+                    $url$: doc.baseURI,
+                    $visibilityState$: doc.visibilityState
+                } ]);
+                setTimeout((() => {
+                    initialised = true;
+                    onInitialisedQueue.forEach((callback => {
+                        callback();
+                    }));
+                }));
+            };
+            const pushState = history.pushState.bind(history);
+            const replaceState = history.replaceState.bind(history);
+            const onLocationChange = (type, state, newUrl, oldUrl) => () => {
+                worker.postMessage([ 13, {
+                    $winId$: $winId$,
+                    type: type,
+                    state: state,
+                    url: doc.baseURI,
+                    newUrl: newUrl,
+                    oldUrl: oldUrl
+                } ]);
+            };
+            history.pushState = (state, _, newUrl) => {
+                pushState(state, _, newUrl);
+                onInitialised(onLocationChange(0, state, null == newUrl ? void 0 : newUrl.toString()));
+            };
+            history.replaceState = (state, _, newUrl) => {
+                replaceState(state, _, newUrl);
+                onInitialised(onLocationChange(1, state, null == newUrl ? void 0 : newUrl.toString()));
+            };
+            $window$.addEventListener("popstate", (event => {
+                onInitialised(onLocationChange(2, event.state));
+            }));
+            $window$.addEventListener("hashchange", (event => {
+                onInitialised(onLocationChange(3, {}, event.newURL, event.oldURL));
+            }));
+            $window$.addEventListener("ptupdate", (() => {
+                readNextScript(worker, winCtxs[$winId$]);
+            }));
+            doc.addEventListener("visibilitychange", (() => worker.postMessage([ 14, $winId$, doc.visibilityState ])));
+            winCtxs[$winId$] = {
+                $winId$: $winId$,
+                $window$: $window$
+            };
+            winCtxs[$winId$].$startTime$ = performance.now();
+            {
+                const winType = $winId$ === $parentWinId$ ? "top" : "iframe";
+                logMain(`Registered ${winType} window ${normalizedWinId($winId$)}`);
+            }
+            "complete" === doc.readyState ? sendInitEnvData() : $window$.addEventListener("load", sendInitEnvData);
+        }
+    };
+    const onMessageFromWebWorker = (worker, msg, winCtx) => {
+        if (4 === msg[0]) {
+            registerWindow(worker, randomId(), mainWindow);
+        } else {
+            winCtx = winCtxs[msg[1]];
+            winCtx && (7 === msg[0] ? requestAnimationFrame((() => readNextScript(worker, winCtx))) : 6 === msg[0] && ((worker, winCtx, instanceId, errorMsg, scriptElm) => {
+                scriptElm = winCtx.$window$.document.querySelector(`[data-ptid="${instanceId}"]`);
+                if (scriptElm) {
+                    errorMsg ? scriptElm.dataset.pterror = errorMsg : scriptElm.type += "-x";
+                    delete scriptElm.dataset.ptid;
+                }
+                readNextScript(worker, winCtx);
+            })(worker, winCtx, msg[2], msg[3]));
+        }
+    };
+    const readMainPlatform = () => {
+        const elm = docImpl.createElement("i");
+        const textNode = docImpl.createTextNode("");
+        const comment = docImpl.createComment("");
+        const frag = docImpl.createDocumentFragment();
+        const shadowRoot = docImpl.createElement("p").attachShadow({
+            mode: "open"
+        });
+        const intersectionObserver = getGlobalConstructor(mainWindow, "IntersectionObserver");
+        const mutationObserver = getGlobalConstructor(mainWindow, "MutationObserver");
+        const resizeObserver = getGlobalConstructor(mainWindow, "ResizeObserver");
+        const perf = mainWindow.performance;
+        const screen = mainWindow.screen;
+        const impls = [ [ mainWindow.history ], [ perf ], [ perf.navigation ], [ perf.timing ], [ screen ], [ screen.orientation ], [ mainWindow.visualViewport ], [ intersectionObserver, 12 ], [ mutationObserver, 12 ], [ resizeObserver, 12 ], [ textNode ], [ comment ], [ frag ], [ shadowRoot ], [ elm ], [ elm.attributes ], [ elm.classList ], [ elm.dataset ], [ elm.style ], [ docImpl ], [ docImpl.doctype ] ];
+        const initialInterfaces = [ readImplementation("Window", mainWindow), readImplementation("Node", textNode) ];
+        const $config$ = function(config) {
+            return JSON.stringify(config, ((key, value) => {
+                if ("function" == typeof value) {
+                    value = String(value);
+                    value.startsWith(key + "(") && (value = "function " + value);
+                }
+                "loadScriptsOnMainThread" === key && (value = value.map((scriptUrl => Array.isArray(scriptUrl) ? scriptUrl : [ "string" == typeof scriptUrl ? "string" : "regexp", "string" == typeof scriptUrl ? scriptUrl : scriptUrl.source ])));
+                return value;
+            }));
+        }(config);
+        const initWebWorkerData = {
+            $config$: $config$,
+            $interfaces$: readImplementations(impls, initialInterfaces),
+            $libPath$: new URL(libPath, mainWindow.location) + "",
+            $origin$: origin,
+            $tabId$: mainWindow._pttab
+        };
+        addGlobalConstructorUsingPrototype(initWebWorkerData.$interfaces$, mainWindow, "IntersectionObserverEntry");
+        return initWebWorkerData;
+    };
+    const readMainInterfaces = () => {
+        const elms = Object.getOwnPropertyNames(mainWindow).map((interfaceName => ((doc, interfaceName, r, tag) => {
+            r = interfaceName.match(/^(HTML|SVG)(.+)Element$/);
+            if (r) {
+                tag = r[2];
+                return "S" == interfaceName[0] ? doc.createElementNS("http://www.w3.org/2000/svg", svgConstructorTags[tag] || tag.slice(0, 2).toLowerCase() + tag.slice(2)) : doc.createElement(htmlConstructorTags[tag] || tag);
+            }
+        })(docImpl, interfaceName))).filter((elm => elm)).map((elm => [ elm ]));
+        return readImplementations(elms, []);
+    };
+    const readImplementations = (impls, interfaces) => {
+        const cstrs = new Set([ "Object" ]);
+        const cstrImpls = impls.filter((implData => implData[0])).map((implData => {
+            const impl = implData[0];
+            const interfaceType = implData[1];
+            const cstrName = getConstructorName(impl);
+            const CstrPrototype = mainWindow[cstrName].prototype;
+            return [ cstrName, CstrPrototype, impl, interfaceType ];
+        }));
+        cstrImpls.map((([cstrName, CstrPrototype, impl, intefaceType]) => readOwnImplementation(cstrs, interfaces, cstrName, CstrPrototype, impl, intefaceType)));
+        return interfaces;
+    };
+    const readImplementation = (cstrName, impl, memberName) => {
+        let interfaceMembers = [];
+        let interfaceInfo = [ cstrName, "Object", interfaceMembers ];
+        for (memberName in impl) {
+            readImplementationMember(interfaceMembers, impl, memberName);
+        }
+        return interfaceInfo;
+    };
+    const readOwnImplementation = (cstrs, interfaces, cstrName, CstrPrototype, impl, interfaceType) => {
+        if (!cstrs.has(cstrName)) {
+            cstrs.add(cstrName);
+            const SuperCstr = Object.getPrototypeOf(CstrPrototype);
+            const superCstrName = getConstructorName(SuperCstr);
+            const interfaceMembers = [];
+            const propDescriptors = Object.getOwnPropertyDescriptors(CstrPrototype);
+            readOwnImplementation(cstrs, interfaces, superCstrName, SuperCstr, impl, interfaceType);
+            for (const memberName in propDescriptors) {
+                readImplementationMember(interfaceMembers, impl, memberName);
+            }
+            interfaces.push([ cstrName, superCstrName, interfaceMembers, interfaceType, getNodeName(impl) ]);
+        }
+    };
+    const readImplementationMember = (interfaceMembers, implementation, memberName, value, memberType, cstrName) => {
+        try {
+            if (isValidMemberName(memberName) && isNaN(memberName[0]) && "all" !== memberName) {
+                value = implementation[memberName];
+                memberType = typeof value;
+                if ("function" === memberType) {
+                    (String(value).includes("[native") || Object.getPrototypeOf(implementation)[memberName]) && interfaceMembers.push([ memberName, 5 ]);
+                } else if ("object" === memberType && null != value) {
+                    cstrName = getConstructorName(value);
+                    "Object" !== cstrName && "Function" !== cstrName && self[cstrName] && interfaceMembers.push([ memberName, value.nodeType || cstrName ]);
+                } else {
+                    "symbol" !== memberType && (memberName.toUpperCase() === memberName ? interfaceMembers.push([ memberName, 6, value ]) : interfaceMembers.push([ memberName, 6 ]));
+                }
+            }
+        } catch (e) {
+            console.warn(e);
+        }
+    };
+    const getGlobalConstructor = (mainWindow, cstrName) => void 0 !== mainWindow[cstrName] ? new mainWindow[cstrName](noop) : 0;
+    const addGlobalConstructorUsingPrototype = ($interfaces$, mainWindow, cstrName) => {
+        void 0 !== mainWindow[cstrName] && $interfaces$.push([ cstrName, "Object", Object.keys(mainWindow[cstrName].prototype).map((propName => [ propName, 6 ])), 12 ]);
+    };
+    let worker;
+    (receiveMessage => {
+        const swContainer = window.navigator.serviceWorker;
+        return swContainer.getRegistration().then((swRegistration => {
+            swContainer.addEventListener("message", (ev => receiveMessage(ev.data, (accessRsp => swRegistration.active && swRegistration.active.postMessage(accessRsp)))));
+            return (worker, msg) => {
+                0 === msg[0] ? worker.postMessage([ 1, readMainPlatform() ]) : 2 === msg[0] ? worker.postMessage([ 3, readMainInterfaces() ]) : onMessageFromWebWorker(worker, msg);
+            };
+        }));
+    })(((accessReq, responseCallback) => mainAccessHandler(worker, accessReq).then(responseCallback))).then((onMessageHandler => {
+        if (onMessageHandler) {
+            worker = new Worker(libPath + "partytown-ww-sw.js?v=0.10.2-dev1727590485751", {
+                name: "Partytown 🎉"
+            });
+            worker.onmessage = ev => {
+                const msg = ev.data;
+                12 === msg[0] ? mainAccessHandler(worker, msg[1]) : onMessageHandler(worker, msg);
+            };
+            logMain("Created Partytown web worker (0.10.2-dev1727590485751)");
+            worker.onerror = ev => console.error("Web Worker Error", ev);
+            mainWindow.addEventListener("pt1", (ev => registerWindow(worker, getAndSetInstanceId(ev.detail.frameElement), ev.detail)));
+        }
+    }));
+})(window);
Index: build/debug/partytown-sw.js
===================================================================
--- build/debug/partytown-sw.js	(revision 3189893)
+++ build/debug/partytown-sw.js	(working copy)
@@ -1 +1,75 @@
-Object.freeze((e=>{const s=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((e=>{"function"==typeof t[e]&&s.add(e)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(s)})());const resolves=new Map,swMessageError=(e,s)=>({$msgId$:e.$msgId$,$error$:s}),httpRequestFromWebWorker=e=>new Promise((async s=>{const t=await e.clone().json(),o=await(e=>new Promise((async s=>{const t=((e,s)=>{const t=s.split(".").pop();let o=e.find((e=>e.url.endsWith(`?${t}`)));return o||(o=[...e].sort(((e,s)=>e.url>s.url?-1:e.url<s.url?1:0))[0]),o})([...await self.clients.matchAll()],e.$msgId$);if(t){const o=[s,setTimeout((()=>{resolves.delete(e.$msgId$),s(swMessageError(e,"Timeout"))}),12e4)];resolves.set(e.$msgId$,o),t.postMessage(e)}else s(swMessageError(e,"NoParty"))})))(t);s(response(JSON.stringify(o),"application/json"))})),response=(e,s)=>new Response(e,{headers:{"content-type":s||"text/html","Cache-Control":"no-store"}});self.oninstall=()=>self.skipWaiting(),self.onactivate=()=>self.clients.claim(),self.onmessage=e=>{const s=e.data,t=resolves.get(s.$msgId$);t&&(resolves.delete(s.$msgId$),clearTimeout(t[1]),t[0](s))},self.onfetch=e=>{const s=e.request,t=new URL(s.url).pathname;t.endsWith("sw.html")?e.respondWith(response('<!DOCTYPE html><html><head><meta charset="utf-8"><script src="./partytown-sandbox-sw.js?v=0.10.2-dev1727590485751"><\/script></head></html>')):t.endsWith("proxytown")&&e.respondWith(httpRequestFromWebWorker(s))};
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+Object.freeze((obj => {
+    const properties = new Set;
+    let currentObj = obj;
+    do {
+        Object.getOwnPropertyNames(currentObj).forEach((item => {
+            "function" == typeof currentObj[item] && properties.add(item);
+        }));
+    } while ((currentObj = Object.getPrototypeOf(currentObj)) !== Object.prototype);
+    return Array.from(properties);
+})([]));
+
+const resolves = new Map;
+
+const swMessageError = (accessReq, $error$) => ({
+    $msgId$: accessReq.$msgId$,
+    $error$: $error$
+});
+
+const httpRequestFromWebWorker = req => new Promise((async resolve => {
+    const accessReq = await req.clone().json();
+    const responseData = await (accessReq => new Promise((async resolve => {
+        const clients = await self.clients.matchAll();
+        const client = ((clients, msgId) => {
+            const tabId = msgId.split(".").pop();
+            let client = clients.find((a => a.url.endsWith(`?${tabId}`)));
+            client || (client = [ ...clients ].sort(((a, b) => a.url > b.url ? -1 : a.url < b.url ? 1 : 0))[0]);
+            return client;
+        })([ ...clients ], accessReq.$msgId$);
+        if (client) {
+            const timeout = 12e4;
+            const msgResolve = [ resolve, setTimeout((() => {
+                resolves.delete(accessReq.$msgId$);
+                resolve(swMessageError(accessReq, "Timeout"));
+            }), timeout) ];
+            resolves.set(accessReq.$msgId$, msgResolve);
+            client.postMessage(accessReq);
+        } else {
+            resolve(swMessageError(accessReq, "NoParty"));
+        }
+    })))(accessReq);
+    resolve(response(JSON.stringify(responseData), "application/json"));
+}));
+
+const response = (body, contentType) => new Response(body, {
+    headers: {
+        "content-type": contentType || "text/html",
+        "Cache-Control": "no-store"
+    }
+});
+
+self.oninstall = () => self.skipWaiting();
+
+self.onactivate = () => self.clients.claim();
+
+self.onmessage = ev => {
+    const accessRsp = ev.data;
+    const r = resolves.get(accessRsp.$msgId$);
+    if (r) {
+        resolves.delete(accessRsp.$msgId$);
+        clearTimeout(r[1]);
+        r[0](accessRsp);
+    }
+};
+
+self.onfetch = ev => {
+    const req = ev.request;
+    const url = new URL(req.url);
+    const pathname = url.pathname;
+    if (pathname.endsWith("sw.html")) {
+        ev.respondWith(response('<!DOCTYPE html><html><head><meta charset="utf-8"><script src="./partytown-sandbox-sw.js?v=0.10.2-dev1727590485751"><\/script></head></html>'));
+    } else {
+        pathname.endsWith("proxytown") && ev.respondWith(httpRequestFromWebWorker(req));
+    }
+};
Index: build/debug/partytown-ww-atomics.js
===================================================================
--- build/debug/partytown-ww-atomics.js	(revision 3189893)
+++ build/debug/partytown-ww-atomics.js	(working copy)
@@ -1 +1,1936 @@
-(e=>{const t=Symbol(),r=Symbol(),n=Symbol(),i=Symbol(),s=Symbol(),o=Symbol(),a=Symbol(),c=Symbol(),l=new Map,$={},u=new WeakMap,d=[],g={},p={},h=new Map,f=new Map,m=e=>e.split(","),y=e=>{if(e=g.$libPath$+e,new URL(e).origin!=location.origin)throw"Invalid "+e;return e},w=m("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft"),v=m("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling"),S=m("insertBefore,remove,removeChild,replaceChild"),b=m("className,width,height,hidden,innerHTML,innerText,textContent,text"),I=m("setAttribute,setAttributeNS,setProperty"),E=m("addEventListener,dispatchEvent,removeEventListener"),x=E.concat(I,m("add,observe,remove,unobserve")),N=/^[A-Z_]([A-Z0-9-]*[A-Z0-9])?$/,T=()=>{},M=e=>e.length,C=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},L=[],O=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),R=(e,t,r)=>Object.defineProperty(e,t,{...r,configurable:!0}),j=(e,t)=>R(e,"name",{value:t}),A=(e,t,r)=>R(e.prototype,t,r),P=(e,t)=>Object.defineProperties(e.prototype,t),W=(e,t,r)=>A(e,t,{value:r,writable:!0});function k(e,t){var r,n;return null!==(n=null===(r=e.loadScriptsOnMainThread)||void 0===r?void 0:r.map((([e,t])=>new RegExp("string"===e?t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"):t))).some((e=>e.test(t))))&&void 0!==n&&n}Object.freeze((e=>{const t=new Set;let r=[];do{Object.getOwnPropertyNames(r).forEach((e=>{"function"==typeof r[e]&&t.add(e)}))}while((r=Object.getPrototypeOf(r))!==Object.prototype);return Array.from(t)})());const H=(e,t)=>t in e[o],D=(e,t)=>e[o][t],B=(e,t,r)=>e[o][t]=r,_=(e,t,r,n,i,s)=>{if(!(i=l.get(t))&&r&&p[e]){const o=l.get(s||"");i=p[e].$createNode$(r,t,n,o),l.set(t,i)}return i},U=(e,t)=>W(e,"nodeType",t),z=(e,t)=>t.map((t=>A(e,t,{get(){let e=F(this,t),r=f.get(e);return r||(r=me(this,[t]),f.set(e,r)),r}}))),F=(e,n,i)=>[e[t],e[r],n,...(i||L).map((e=>String(e&&e[t]?e[r]:e)))].join("."),G=(e,t)=>m(t).map((t=>A(e,t,{get(){return H(this,t)||B(this,t,me(this,[t])),D(this,t)},set(e){D(this,t)!==e&&ye(this,[t],e),B(this,t,e)}}))),q=e=>w.map((t=>A(e,t,{get(){const e=h.get(F(this,t));if("number"==typeof e)return e;const r=me(this,[t],w);return r&&"object"==typeof r?(Object.entries(r).map((([e,t])=>h.set(F(this,e),t))),r[t]):r}}))),J=(e,t)=>t.map((t=>{e.prototype[t]=function(...e){let r=F(this,t,e),n=h.get(r);return n||(n=we(this,[t],e),h.set(r,n)),n}})),V=(e,n,i,s,o)=>{return void 0!==i&&(o=typeof i)?"string"===o||"boolean"===o||"number"===o||null==i?[0,i]:"function"===o?[4,{$winId$:e,$instanceId$:n,$refId$:(a=i,(c=u.get(a))||(u.set(a,c=O()),$[c]=a),c)}]:(s=s||new Set)&&Array.isArray(i)?s.has(i)?[1,[]]:s.add(i)&&[1,i.map((t=>V(e,n,t,s)))]:"object"===o?i[r]?[3,[i[t],i[r]]]:i instanceof Event?[5,Z(e,n,i,!1,s)]:X&&i instanceof TrustedHTML?[0,i.toString()]:i instanceof ArrayBuffer?[8,i]:ArrayBuffer.isView(i)?[9,i.buffer,C(i)]:[2,Z(e,n,i,!0,s)]:void 0:i;var a,c},X="undefined"!=typeof TrustedHTML,Z=(e,t,r,n,i,s,o,a)=>{if(s={},!i.has(r))for(o in i.add(r),r)a=r[o],(n||"function"!=typeof a)&&(s[o]=V(e,t,a,i));return s},Y=(e,n)=>e?V(e[t],e[r],n):[0,n],K=(e,t,r,n,i,s,o,a)=>{if(n){if(i=n[0],s=n[1],0===i||11===i||12===i)return s;if(4===i)return ee(r,s);if(6===i)return e&&r.length>0?(...t)=>we(p[e].$window$,r,t,1):T;if(3===i)return Q(s);if(7===i)return new re(s.map(Q));if(10===i)return new ne(s);if(1===i)return s.map((n=>K(e,t,r,n)));if(14===i)return new te(s);for(a in o={},s)o[a]=K(e,t,[...r,a],s[a]);if(13===i)return new p[e].$window$.CSSStyleDeclaration(e,t,r,o);if(5===i){if("message"===o.type&&o.origin){let e,t=JSON.stringify(o.data),r=d.find((e=>e.$data$===t));r&&(e=p[r.$winId$],e&&(o.source=e.$window$,o.origin=e.$location$.origin))}return new Proxy(new Event(o.type,o),{get:(e,t)=>t in o?o[t]:"function"==typeof e[String(t)]?T:e[String(t)]})}if(2===i)return o}},Q=([e,t,r,n])=>t===e&&p[e]?p[e].$window$:_(e,t,r,void 0,void 0,n),ee=(e,{$winId$:t,$instanceId$:r,$nodeName$:n,$refId$:i})=>($[i]||u.set($[i]=function(...i){const s=_(t,r,n);return we(s,e,i)},i),$[i]);class te extends Error{constructor(e){super(e.message),this.name=e.name,this.message=e.message,this.stack=e.stack}}class re{constructor(e){(this._=e).map(((e,t)=>this[t]=e))}entries(){return this._.entries()}forEach(e,t){this._.map(e,t)}item(e){return this[e]}keys(){return this._.keys()}get length(){return M(this._)}values(){return this._.values()}[Symbol.iterator](){return this._[Symbol.iterator]()}}const ne=class{constructor(e){this.name=e[0],this.value=e[1]}get nodeName(){return this.name}get nodeType(){return 2}},ie=(e,t,r)=>console.warn(`Partytown unable to ${e} cross-origin ${t}: `+r.$location$),se=(t,r)=>{try{if(g.$config$.logStackTraces){const e=(new Error).stack.split("\n"),r=e.findIndex((e=>e.includes("logWorker")));t+="\n"+e.slice(r+1).join("\n")}let n,i;r?(n=`Worker (${ae(r)}) 🎉`,i=ce(r)):(n=e.name,i="#9844bf"),g.lastLog!==t&&(g.lastLog=t,console.debug.apply(console,[`%c${n}`,`background: ${i}; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;`,t]))}catch(e){}},oe=[],ae=e=>(oe.includes(e)||oe.push(e),oe.indexOf(e)+1),ce=e=>{const t=["#00309e","#ea3655","#eea727"];return t[ae(e)-1]||t[t.length-1]},le=(e,t)=>{let r="";if(e){const t=C(e);if("Window"===t)r="";else if("string"==typeof e[n]){let t=e[n];r="#text"===t?"textNode.":"#comment"===t?"commentNode.":"#document"===t?"document.":"html"===t?"doctype.":t.toLowerCase()+"."}else r="nodeType"in e&&2===e.nodeType?"attributes.":"CanvasRenderingContext2D"===t?"context2D.":"CanvasRenderingContextWebGL"===t?"contextWebGL.":"CSSStyleDeclaration"===t?"style.":"MutationObserver"===t?"mutationObserver.":"NamedNodeMap"===t?"namedNodeMap.":"ResizeObserver"===t?"resizeObserver.":t.substring(0,1).toLowerCase()+t.substring(1)+".";e[s]&&e[s].length&&(r+=[...e[s]].join(".")+".")}if(t.length>1){const e=t.slice(0,t.length-1),n=t[t.length-1];if(!isNaN(n))return r+`${e.join(".")}[${n}]`}return r+t.join(".")},$e=(e,t)=>{const i=typeof t;if(void 0===t)return"undefined";if("boolean"===i||"number"===i||null==t)return JSON.stringify(t);if("string"===i)return e.includes("cookie")?JSON.stringify(t.slice(0,10)+"..."):JSON.stringify(t.length>50?t.slice(0,40)+"...":t);if(Array.isArray(t))return`[${t.map($e).join(", ")}]`;if("object"===i){const i=t[r],s=C(t);if("string"==typeof i){if("Window"===s)return"window";if("string"==typeof t[n]){if(1===t.nodeType)return`<${t[n].toLowerCase()}>`;if(10===t.nodeType)return`<!DOCTYPE ${t[n]}>`;if(t.nodeType<=11)return t[n]}return"¯\\_(ツ)_/¯ instance obj"}return t[Symbol.iterator]?`[${Array.from(t).map((t=>$e(e,t))).join(", ")}]`:"value"in t?"string"==typeof t.value?`"${t.value}"`:ue(t.value):ue(t)}return(e=>"object"==typeof e&&e&&e.then)(t)?"Promise":"function"===i?`ƒ() ${t.name||""}`.trim():`¯\\_(ツ)_/¯ ${String(t)}`.trim()},ue=e=>{const t=[];for(let r in e){const n=e[r],i=typeof n;"string"===i?t.push(`${r}: "${n}"`):"function"===i?t.push(`${r}: ƒ`):Array.isArray(i)?t.push(`${r}: [..]`):"object"===i&&n?t.push(`${r}: {..}`):t.push(`${r}: ${String(n)}`)}let r=t.join(", ");return r.length>200&&(r=r.substring(0,200)+".."),`{ ${r} }`},de=(e,r)=>{(g.$config$.logGetters||g.$config$.logSetters)&&se(`Dimension cache cleared from style.${r} setter`,e[t])},ge=(e,r)=>{(g.$config$.logGetters||g.$config$.logCalls)&&se(`Dimension cache cleared from method call ${r}()`,e[t])},pe=[],he=(e,n,i,o,a,c)=>{if(e[s]){if(pe.push({$winId$:e[t],$instanceId$:e[r],$applyPath$:[...e[s],...n],$assignInstanceId$:o,$groupedGetters$:a}),pe[M(pe)-1].$debug$=((e,t,r)=>{let n=le(e,t);return 1===r?n+=" (blocking)":2===r?n+=" (non-blocking)":3===r&&(n+=" (non-blocking, no-side-effect)"),n.trim()})(e,n,i),c&&3!==i&&console.error("buffer must be sent NonBlockingNoSideEffect"),3===i)g.$postMessage$([12,{$msgId$:O(),$tasks$:[...pe]}],c?[c instanceof ArrayBuffer?c:c.buffer]:void 0),pe.length=0;else if(1===i)return fe(!0);g.$asyncMsgTimer$=setTimeout(fe,20)}},fe=e=>{if(clearTimeout(g.$asyncMsgTimer$),M(pe)){g.$config$.logMainAccess&&se(`Main access, tasks sent: ${pe.length}`);const t=pe[M(pe)-1],r={$msgId$:`${O()}.${g.$tabId$}`,$tasks$:[...pe]};if(pe.length=0,e){const e=((e,t)=>{const r=e.$sharedDataBuffer$,n=new Int32Array(r);Atomics.store(n,0,0),e.$postMessage$([11,t]),Atomics.wait(n,0,0);let i=Atomics.load(n,0),s="",o=0;for(;o<i;o++)s+=String.fromCharCode(n[o+1]);return JSON.parse(s)})(g,r),n=e.$isPromise$,i=K(t.$winId$,t.$instanceId$,t.$applyPath$,e.$rtnValue$);if(e.$error$){if(n)return Promise.reject(e.$error$);throw new Error(e.$error$)}return n?Promise.resolve(i):i}g.$postMessage$([12,r])}},me=(e,r,n,i)=>(g.$config$.get&&(i=g.$config$.get(Se(e,r)))!==a||((e,r,n,i=!1,s=!1)=>{if(g.$config$.logGetters)try{const o=`Get ${le(e,r)}, returned: ${$e(r,n)}${i?" (restricted to worker)":""}${s?" (grouped getter)":""}`;o.includes("Symbol(")||se(o,e[t])}catch(e){}})(e,r,i=he(e,r,1,void 0,n),!1,!!n),i),ye=(e,r,n,i)=>{if(g.$config$.set){if((i=g.$config$.set({value:n,prevent:c,...Se(e,r)}))===c)return;i!==a&&(n=i)}var s,o;b.some((e=>r.includes(e)))&&(h.clear(),s=e,o=r[r.length-1],(g.$config$.logGetters||g.$config$.logSetters)&&se(`Dimension cache cleared from setter "${o}"`,s[t])),((e,r,n,i=!1)=>{if(g.$config$.logSetters)try{r=r.slice(0,r.length-2),se(`Set ${le(e,r)}, value: ${$e(r,n)}${i?" (restricted to worker)":""}`,e[t])}catch(e){}})(e,r=[...r,Y(e,n),0],n),he(e,r,2)},we=(e,r,n,i,s,o,c,l)=>(g.$config$.apply&&(c=g.$config$.apply({args:n,...Se(e,r)}))!==a||(l=r[M(r)-1],r=[...r,Y(e,n)],i=i||(x.includes(l)?2:1),"setAttribute"===l&&H(e,n[0])?B(e,n[0],n[1]):S.includes(l)?(h.clear(),f.clear(),((e,r)=>{(g.$config$.logGetters||g.$config$.logCalls)&&se(`Dimension and DOM structure cache cleared from method call ${r}()`,e[t])})(e,l)):I.includes(l)&&(i=2,h.clear(),ge(e,l)),((e,r,n,i)=>{if(g.$config$.logCalls)try{r=r.slice(0,r.length-1),se(`Call ${le(e,r)}(${n.map((e=>$e(r,e))).join(", ")}), returned: ${$e(r,i)}`,e[t])}catch(e){}})(e,r,n,c=he(e,r,i,s,void 0,o))),c),ve=(e,r,n)=>{((e,r,n)=>{if(g.$config$.logCalls)try{se(`Construct new ${r}(${n.map((e=>$e([],e))).join(", ")})`,e[t])}catch(e){}})(e,r,n),he(e,[1,r,Y(e,n)],1)},Se=(e,r)=>({name:r.join("."),continue:a,nodeName:e[n],constructor:C(e),instance:e,window:p[e[t]].$window$}),be=(e,t,r)=>{let n={getItem(n){if(r.$isSameOrigin$)return we(e,[t,"getItem"],[n],1);ie("get",t,r)},setItem(n,i){r.$isSameOrigin$?we(e,[t,"setItem"],[n,i],1):ie("set",t,r)},removeItem(n){r.$isSameOrigin$?we(e,[t,"removeItem"],[n],1):ie("remove",t,r)},key(n){if(r.$isSameOrigin$)return we(e,[t,"key"],[n],1);ie("key",t,r)},clear(){r.$isSameOrigin$?we(e,[t,"clear"],L,1):ie("clear",t,r)},get length(){if(r.$isSameOrigin$)return me(e,[t,"length"]);ie("length",t,r)}};e[t]=new Proxy(n,{get:(e,t)=>Reflect.has(e,t)?Reflect.get(e,t):e.getItem(t),set:(e,t,r)=>(e.setItem(t,r),!0),has:(e,t)=>!!Reflect.has(e,t)||"string"==typeof t&&null!==e.getItem(t),deleteProperty:(e,t)=>(e.removeItem(t),!0)})},Ie=(e,t,r)=>{e[r]=j(class extends t{constructor(e,t,r,i){return super(e,t,r,i||{}),new Proxy(this,{get:(e,t)=>e[t]?e[t]:(e[t]||"string"!=typeof t||e[n][t]||(e[n][t]=me(e,[t])),e[n][t]),set:(e,t,r)=>(e[n][t]=r,ye(e,[t],r),de(e,t),h.clear(),!0)})}setProperty(...e){this[n][e[0]]=e[1],we(this,["setProperty"],e,2),de(this,e[0]),h.clear()}getPropertyValue(e){return this[e]}removeProperty(e){let t=this[n][e];return we(this,["removeProperty"],[e],2),de(this,e),h.clear(),this[n][e]=void 0,t}},r)},Ee=(e,t)=>{e[t]=j(class{constructor(e){this.ownerNode=e}get cssRules(){const e=this.ownerNode;return new Proxy({},{get(t,r){const n=String(r);return"item"===n?t=>Ne(e,t):"length"===n?xe(e).length:isNaN(n)?t[r]:Ne(e,n)}})}insertRule(e,t){const r=xe(this.ownerNode);return(t=void 0===t?0:t)>=0&&t<=r.length&&(we(this.ownerNode,["sheet","insertRule"],[e,t],2),r.splice(t,0,0)),ge(this.ownerNode,"insertRule"),h.clear(),t}deleteRule(e){we(this.ownerNode,["sheet","deleteRule"],[e],2),xe(this.ownerNode).splice(e,1),ge(this.ownerNode,"deleteRule"),h.clear()}get type(){return"text/css"}},t);const r={sheet:{get(){return new e[t](this)}}};P(e.HTMLStyleElement,r)},xe=(e,t)=>((t=D(e,2))||(t=me(e,["sheet","cssRules"]),B(e,2,t)),t),Ne=(e,t,r)=>(0===(r=xe(e))[t]&&(r[t]=me(e,["sheet","cssRules",parseInt(t,10)])),r[t]),Te=(e,t,r,n,i)=>{try{g.$config$.logScriptExecution&&se(`Execute script: ${r.substring(0,100).split("\n").map((e=>e.trim())).join(" ").trim().substring(0,60)}...`,n),e.$currentScriptId$=t,Me(e,r)}catch(e){console.error(r,e),i=String(e.stack||e)}return e.$currentScriptId$="",i},Me=(e,t,r)=>{e.$runWindowLoadEvent$=1;let n=((e,t)=>e.replace(/([a-zA-Z0-9_$\.\'\"\`])?(\.\.\.)?this(?![a-zA-Z0-9_$:])/g,((e,t,r)=>{const n=(t||"")+(r||"");return null!=t?n+"this":n+"(thi$(this)?window:this)"})))(t);t=`with(this){${n.replace(/\/\/# so/g,"//Xso")}\n;function thi$(t){return t===this}};${(g.$config$.globalFns||[]).filter((e=>/[a-zA-Z_$][0-9a-zA-Z_$]*/.test(e))).map((e=>`(typeof ${e}=='function'&&(this.${e}=${e}))`)).join(";")};`+(r?"\n//# sourceURL="+r:""),e.$isSameOrigin$||(t=t.replace(/.postMessage\(/g,`.postMessage('${e.$winId$}',`)),new Function(t).call(e.$window$),e.$runWindowLoadEvent$=0},Ce=(e,t,r)=>{(r=D(e,t))&&setTimeout((()=>r.map((e=>e({type:t})))))},Le=(e,t)=>{for(t=e.$location$;!t.host&&(t=(e=p[e.$parentWinId$]).$location$,e.$winId$!==e.$parentWinId$););return t},Oe=(e,t,r,n,i,s)=>(n=Le(e,n),i=new URL(t||"",n),r&&g.$config$.resolveUrl&&(s=g.$config$.resolveUrl(i,n,r))?s:i),Re=(e,t,r)=>Oe(e,t,r)+"",je=(e,t)=>{const r=Le(e),n=new URL(t||"",r);if(g.$config$.resolveSendBeaconRequestParameters){const e=g.$config$.resolveSendBeaconRequestParameters(n,r);if(e)return e}return{}},Ae=()=>`<script src="${y("partytown.js?v=0.10.2-dev1727590485751")}"><\/script>`,Pe=e=>class{constructor(){this.s="",this.l=[],this.e=[],this.style={}}get src(){return this.s}set src(t){g.$config$.logImageRequests&&se(`Image() request: ${Re(e,t,"image")}`,e.$winId$),this.s=t,fetch(Re(e,t,"image"),{mode:"no-cors",credentials:"include",keepalive:!0}).then((e=>{e.ok||0===e.status?this.l.map((e=>e({type:"load"}))):this.e.map((e=>e({type:"error"})))}),(()=>this.e.forEach((e=>e({type:"error"})))))}addEventListener(e,t){"load"===e&&this.l.push(t),"error"===e&&this.e.push(t)}removeEventListener(e,t){"load"===e&&(this.l=this.l.filter((e=>e!==t))),"error"===e&&(this.e=this.e.filter((e=>e!==t)))}get onload(){return this.l[0]}set onload(e){this.l=[e]}get onerror(){return this.e[0]}set onerror(e){this.e=[e]}},We={addEventListener:{value(...e){const t=e[0],r=D(this,t)||[];r.push(e[1]),B(this,t,r)}},async:{get:T,set:T},defer:{get:T,set:T},onload:{get(){let e=D(this,"load");return e&&e[0]||null},set(e){B(this,"load",e?[e]:null)}},onerror:{get(){let e=D(this,"error");return e&&e[0]||null},set(e){B(this,"error",e?[e]:null)}},getAttribute:{value(e){return"src"===e?this.src:we(this,["getAttribute"],[e])}},setAttribute:{value(e,t){ke.includes(e)?this[e]=t:we(this,["setAttribute"],[e,t])}}},ke=m("src,type"),He=(e,t)=>{const r={innerHTML:De,innerText:De,src:{get(){return D(this,4)||""},set(e){const r=Re(t,e,null),n=g.$config$;e=Re(t,e,"script"),B(this,4,e),ye(this,["src"],e),r!==e&&ye(this,["dataset","ptsrc"],r),this.type&&k(n,e)&&ye(this,["type"],"text/javascript")}},text:De,textContent:De,type:{get(){return me(this,["type"])},set(e){Be(e)||(B(this,5,e),ye(this,["type"],e))}},...We};P(e,r)},De={get(){const e=me(this,["type"]);if(Be(e)){const e=D(this,3);if(e)return e}return me(this,["innerHTML"])||""},set(e){B(this,3,e)}},Be=e=>!e||"text/javascript"===e,_e=(e,i,s)=>{const o=g.$config$,a=j(class extends s{appendChild(e){return this.insertBefore(e,null)}get href(){}set href(e){}insertBefore(e,s){const a=e[t]=this[t],c=e[r],l=e[n],$="SCRIPT"===l,u="IFRAME"===l;if($){const t=D(e,3),r=D(e,5);if(t){if(Be(r)){const r=e.id;if(r&&k(o,r))ye(e,["type"],"text/javascript");else{const r=Te(i,c,t,a,""),n=r?"pterror":"ptid",s=r||c;ye(e,["type"],"text/partytown-x"),ye(e,["dataset",n],s)}}ye(e,["innerHTML"],t)}}if(we(this,["insertBefore"],[e,s],2),u){const t=D(e,0);if(t&&t.startsWith("javascript:")){const e=t.split("javascript:")[1];Te(i,c,e,a,"")}((e,t)=>{let r,n,i=0,s=()=>{p[e]&&p[e].$isInitialized$&&!p[e].$isLoading$?(r=D(t,1)?"error":"load",n=D(t,r),n&&n.map((e=>e({type:r})))):i++>2e3?(n=D(t,"error"),n&&n.map((e=>e({type:"error"})))):setTimeout(s,9)};s()})(c,e)}return $&&(fe(!0),g.$postMessage$([7,a])),e}get nodeName(){return"#s"===this[n]?"#document-fragment":this[n]}get nodeType(){return 3}get ownerDocument(){return i.$document$}},"Node");z(a,m("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling")),e.Node=a},Ue=m("AUDIO,CANVAS,VIDEO"),ze=m("Audio,MediaSource"),Fe=(e,r,n)=>{P(e,{body:{get:()=>r.$body$},cookie:{get(){return r.$isSameOrigin$?me(this,["cookie"]):(ie("get","cookie",r),"")},set(e){r.$isSameOrigin$?ye(this,["cookie"],e):ie("set","cookie",r)}},createElement:{value(e){if(e=e.toUpperCase(),!N.test(e))throw e+" not valid";const r="IFRAME"===e,n=this[t],i=(r?"f_":"")+O();we(this,["createElement"],[e],2,i);const s=_(n,i,e);if(r)st({$winId$:i,$parentWinId$:n,$url$:"about:blank"},!0).$window$.fetch=fetch,ye(s,["srcdoc"],Ae());else if("SCRIPT"===e){const e=D(s,5);Be(e)&&ye(s,["type"],"text/partytown")}return s}},createElementNS:{value(e,r){const n=O(),i=_(this[t],n,r,e);return we(this,["createElementNS"],[e,r],2,n),i}},createTextNode:{value(e){const r=this[t],n=O(),i=_(r,n,"#text");return we(this,["createTextNode"],[e],2,n),i}},createEvent:{value:e=>new Event(e)},currentScript:{get(){return r.$currentScriptId$?_(this[t],r.$currentScriptId$,"SCRIPT"):null}},defaultView:{get:()=>n?null:r.$window$},documentElement:{get:()=>r.$documentElement$},getElementsByTagName:{value(e){return"BODY"===(e=e.toUpperCase())?[r.$body$]:"HEAD"===e?[r.$head$]:we(this,["getElementsByTagName"],[e])}},head:{get:()=>r.$head$},images:{get(){return me(this,["images"])}},scripts:{get(){return me(this,["scripts"])}},implementation:{get(){return{hasFeature:()=>!0,createHTMLDocument:e=>{const t=O();return we(this,["implementation","createHTMLDocument"],[e],1,{$winId$:t}),st({$winId$:t,$parentWinId$:t,$url$:r.$location$+"",$visibilityState$:"hidden"},!0,!0).$document$}}}},location:{get:()=>r.$location$,set(e){r.$location$.href=e+""}},nodeType:{value:9},parentNode:{value:null},parentElement:{value:null},readyState:{value:"complete"},visibilityState:{get:()=>r.$visibilityState$||"visible"}}),G(e,"compatMode,referrer,forms")},Ge=(e,t)=>{P(e,{parentElement:{get(){return this.parentNode}},parentNode:{get:()=>t.$documentElement$}})},qe=(e,t)=>{P(e,{localName:{get(){return this[n].toLowerCase()}},namespaceURI:{get(){return this[i]||"http://www.w3.org/1999/xhtml"}},nodeType:{value:1},tagName:{get(){return this[n]}}}),z(e,v),G(e,"id"),q(t),J(t,m("getClientRects,getBoundingClientRect"))},Je=(e,t)=>{const r={};m("hash,host,hostname,href,origin,pathname,port,protocol,search").map((e=>{r[e]={get(){let r,n=D(this,4);if("string"!=typeof n){if(r=me(this,["href"]),""===r)return"protocol"===e?":":"";B(this,4,r),n=new URL(r)[e]}return Oe(t,n,null)[e]},set(r){let n;if("href"===e)if((e=>{try{return new URL(e),!0}catch(e){return!1}})(r))n=new URL(r);else{const e=t.$location$.href;n=Oe(t,e,null),n.href=new URL(r+"",n.href)}else n=Oe(t,this.href,null),n[e]=r;B(this,4,n.href),ye(this,["href"],n.href)}}})),P(e,r)},Ve=(e,t)=>{const r={contentDocument:{get(){return Ke(this).$document$}},contentWindow:{get(){return Ke(this).$window$}},src:{get(){let e=D(this,0);return e&&e.startsWith("javascript:")?e:(e=Ke(this).$location$.href,e.startsWith("about:")?"":e)},set(e){if(e)if(e.startsWith("javascript:"))B(this,0,e);else if(!e.startsWith("about:")){let t,r=new XMLHttpRequest,n=Ke(this);n.$location$.href=e=Re(n,e,"iframe"),n.$isLoading$=1,n.$isSameOrigin$=g.$origin$===n.$location$.origin,B(this,1,void 0),r.open("GET",e,!1),r.send(),t=r.status,t>199&&t<300?(ye(this,["srcdoc"],`<base href="${e}">`+r.responseText.replace(Ze,((e,t)=>{const r=[];let n,i=!1;for(;n=Ye.exec(t);){let[e]=n;e.startsWith("type=")&&(i=!0,e=e.replace(/(application|text)\/javascript/,"text/partytown")),r.push(e)}return i||r.push('type="text/partytown"'),`<script ${r.join(" ")}>`}))+Ae()),fe(!0),g.$postMessage$([7,n.$winId$])):(B(this,1,t),n.$isLoading$=0)}}},...We};P(e,r)},Xe="((?:\\w|-)+(?:=(?:(?:\\w|-)+|'[^']*'|\"[^\"]*\")?)?)",Ze=new RegExp(`<script\\s*((${Xe}\\s*)*)>`,"mg"),Ye=new RegExp(Xe,"mg"),Ke=e=>{const n=e[r];return p[n]||st({$winId$:n,$parentWinId$:e[t],$url$:me(e,["src"])||"about:blank"},!0),p[n]},Qe=e=>{const t=(e,t)=>{const{a:r,b:n,c:i,d:s,e:o,f:a}=we(e,[t],L);return new DOMMatrixReadOnly([r,n,i,s,o,a])},r={...e,getCTM:{value:function(){return t(this,"getCTM")}},getScreenCTM:{value:function(){return t(this,"getScreenCTM")}}};P(e,r)},et=(e,t)=>{e.NamedNodeMap=j(class extends t{constructor(e,t,r){return super(e,t,r),new Proxy(this,{get(e,t){const r=rt[t];return r?r.bind(e,[t]):me(e,[t])},set(e,t,r){if(rt[t])throw new Error("Can't set read-only property: "+String(t));return ye(e,[t],r),!0}})}},"NamedNodeMap")};function tt(e,...t){return we(this,e,t,1)}const rt={getNamedItem:tt,getNamedItemNS:tt,item:tt,removeNamedItem:tt,removeNamedItemNS:tt,setNamedItem:tt,setNamedItemNS:tt},nt=(a,c,l,$,u,h)=>{let f,w,S,b;const I=class{constructor(e,c,l,$,u){this[t]=e||a,this[r]=c||f||O(),this[s]=l||[],this[n]=$||w,this[i]=u||S,this[o]=b&&b[o]||{},f=w=S=void 0}},x=new(j(class extends URL{assign(){se("location.assign(), noop")}reload(){se("location.reload(), noop")}replace(){se("location.replace(), noop")}},"Location"))(l),N=x.origin===g.$origin$||"about:blank"===x.origin,T=c===a,L={},k=()=>{let e,t,r=[];for(e in p)t=p[e],t.$parentWinId$!==a||t.$isTopWindow$||r.push(t);return r},F=j(class extends I{constructor(){super(a,a),this.addEventListener=(...e)=>{"load"===e[0]?L.$runWindowLoadEvent$&&setTimeout((()=>e[1]({type:"load"}))):we(this,["addEventListener"],e,2)};let n,i,o=this,l=0,d=()=>{l||((g.$initWindowMedia$||(e.$bridgeToMedia$=[me,ye,we,ve,P,O,t,r,s],g.$importScripts$(y("partytown-media.js?v=0.10.2-dev1727590485751")),g.$initWindowMedia$=e.$bridgeFromMedia$,delete e.$bridgeFromMedia$),g.$initWindowMedia$)(I,X,L,o,ze),l=1)},p={},E=(e,t,r,n)=>{Ue.includes(e)&&d();const i=p[e]?p[e]:e.includes("-")?p.UNKNOWN:p.I;return f=t,w=e,S=r,b=n,new i};var M,C;if(o.Window=F,o.name=name+`${ae(a)} (${a})`,_e(o,L,I),(e=>{e.NodeList=j(re,"NodeList")})(o),et(o,I),Ie(o,I,"CSSStyleDeclaration"),((e,t,r)=>{e[r]=j(class extends t{now(){return performance.now()}},r)})(o,I,"Performance"),((e,t)=>{const r=new Map;e.customElements={define(n,i,s){r.set(n,i),t[n.toUpperCase()]=i;const o=[i.name,i.observedAttributes];we(e,["customElements","define"],[n,o,s])},get:t=>r.get(t)||we(e,["customElements","get"],[t]),whenDefined:t=>r.has(t)?Promise.resolve():we(e,["customElements","whenDefined"],[t]),upgrade:t=>we(e,["customElements","upgrade"],[t])}})(o,p),g.$interfaces$.map((([e,t,n,i,c])=>{const l=it[e]?V:"EventTarget"===t?X:"Object"===t?I:o[t],$=o[e]=j(12===i?class extends I{constructor(...t){super(),ve(this,e,t)}}:o[e]||class extends l{},e);c&&(p[c]=$),n.map((([e,t,n])=>{e in $.prototype||e in l.prototype||("string"==typeof t?A($,e,{get(){if(!H(this,e)){const n=this[r],i=[...this[s],e],c=o[t];c&&B(this,e,new c(a,n,i))}return D(this,e)},set(t){B(this,e,t)}}):5===t?W($,e,(function(...t){return we(this,[e],t)})):t>0&&(void 0!==n?W($,e,n):A($,e,{get(){return me(this,[e])},set(t){return ye(this,[e],t)}})))}))})),m("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((t=>{delete F.prototype[t],t in o||(n=e[t],null!=n&&(o[t]="function"!=typeof n||n.toString().startsWith("class")?n:n.bind(e)))})),Object.getOwnPropertyNames(e).map((t=>{t in o||(o[t]=e[t])})),ze.map((e=>R(o,e,{get:()=>(d(),o[e])}))),"trustedTypes"in e&&(o.trustedTypes=e.trustedTypes),qe(o.Element,o.HTMLElement),Fe(o.Document,L,h),M=o.DocumentFragment,U(M,11),z(M,v),Je(o.HTMLAnchorElement,L),C=o.HTMLFormElement,P(C,{}),G(C,"elements"),Ve(o.HTMLIFrameElement),He(o.HTMLScriptElement,L),Qe(o.SVGGraphicsElement),Ge(o.HTMLHeadElement,L),Ge(o.HTMLBodyElement,L),((e,t)=>{P(e,{parentElement:{value:null},parentNode:{get:()=>t.$document$}})})(o.HTMLHtmlElement,L),Ee(o,"CSSStyleSheet"),U(o.Comment,8),U(o.DocumentType,10),Object.assign(L,{$winId$:a,$parentWinId$:c,$window$:new Proxy(o,{get:(e,t)=>{var r;if("string"!=typeof t||isNaN(t))return(null===(r=g.$config$.mainWindowAccessors)||void 0===r?void 0:r.includes(t))?me(this,[t]):e[t];{let e=k()[t];return e?e.$window$:void 0}},has:()=>!0}),$document$:E("#document",a+".d"),$documentElement$:E("HTML",a+".e"),$head$:E("HEAD",a+".h"),$body$:E("BODY",a+".b"),$location$:x,$visibilityState$:$,$isSameOrigin$:N,$isTopWindow$:T,$createNode$:E}),o.requestAnimationFrame=e=>setTimeout((()=>e(performance.now())),9),o.cancelAnimationFrame=e=>clearTimeout(e),o.requestIdleCallback=(e,t)=>(t=Date.now(),setTimeout((()=>e({didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-t))})),1)),o.cancelIdleCallback=e=>clearTimeout(e),be(o,"localStorage",L),be(o,"sessionStorage",L),N||(o.indexeddb=void 0),u)i={},o.history={pushState(e){i=e},replaceState(e){i=e},get state(){return i},length:0},o.indexeddb=void 0;else{const e=o.history.pushState.bind(o.history),t=o.history.replaceState.bind(o.history);o.history.pushState=(t,r,n)=>{!1!==L.$propagateHistoryChange$&&e(t,r,n)},o.history.replaceState=(e,r,n)=>{!1!==L.$propagateHistoryChange$&&t(e,r,n)}}o.Worker=void 0}get body(){return L.$body$}get document(){return L.$document$}get documentElement(){return L.$documentElement$}fetch(e,t){return e="string"==typeof e||e instanceof URL?String(e):e.url,fetch(Re(L,e,"fetch"),t)}get frames(){return L.$window$}get frameElement(){return T?null:_(c,a,"IFRAME")}get globalThis(){return L.$window$}get head(){return L.$head$}get length(){return k().length}get location(){return x}set location(e){x.href=e+""}get Image(){return Pe(L)}get navigator(){return(e=>{const t={sendBeacon:(t,r)=>{if(g.$config$.logSendBeaconRequests)try{se(`sendBeacon: ${Re(e,t,null)}${r?", data: "+JSON.stringify(r):""}, resolvedParams: ${JSON.stringify(je(e,t))}`)}catch(e){console.error(e)}try{return fetch(Re(e,t,null),{method:"POST",body:r,mode:"no-cors",keepalive:!0,...je(e,t)}),!0}catch(e){return console.error(e),!1}}};for(let e in navigator)t[e]=navigator[e];return new Proxy(t,{set:(e,t,r)=>(navigator[t]=r,!0),get:(t,r)=>Object.prototype.hasOwnProperty.call(t,r)?t[r]:me(e.$window$,["navigator",r])})})(L)}get origin(){return x.origin}set origin(e){}get parent(){for(let e in p)if(p[e].$winId$===c)return p[e].$window$;return L.$window$}postMessage(...e){p[e[0]]&&(M(d)>50&&d.splice(0,5),d.push({$winId$:e[0],$data$:JSON.stringify(e[1])}),e=e.slice(1)),we(this,["postMessage"],e,3)}get self(){return L.$window$}get top(){for(let e in p)if(p[e].$isTopWindow$)return p[e].$window$;return L.$window$}get window(){return L.$window$}get XMLHttpRequest(){const e=XMLHttpRequest,t=String(e),r=j(class extends e{open(...e){e[1]=Re(L,e[1],"xhr"),super.open(...e)}set withCredentials(e){g.$config$.allowXhrCredentials&&(super.withCredentials=e)}toString(){return t}},C(e));return r.prototype.constructor.toString=()=>t,r}},"Window"),V=class extends I{constructor(e,t,r,n){return super(e,t,r,n),new Proxy(this,{get:(e,t)=>me(e,[t]),set:(e,t,r)=>(ye(e,[t],r),!0)})}},X=class extends I{};return E.map((e=>X.prototype[e]=function(...t){return we(this,[e],t,2)})),G(F,"devicePixelRatio"),q(F),J(F,["getComputedStyle"]),new F,L},it={DOMStringMap:1,NamedNodeMap:1},st=({$winId$:e,$parentWinId$:t,$url$:r,$visibilityState$:n},i,s)=>(p[e]||(p[e]=nt(e,t,r,n,i,s),se(`Created ${e===t?"top":"iframe"} window ${ae(e)} environment`,e)),g.$postMessage$([7,e]),p[e]),ot=[],at=t=>{const r=t.data,n=r[0],i=r[1];if(g.$isInitialized$)if(7===n)(async e=>{let t,r=e.$winId$,n=e.$instanceId$,i=_(r,n,"SCRIPT"),s=e.$content$,o=e.$url$,a=e.$orgUrl$,c="",l=p[r],$=["text/jscript","text/javascript","text/x-javascript","application/javascript","application/x-javascript","text/ecmascript","text/x-ecmascript","application/ecmascript"];if(o)try{if(o=Oe(l,o,"script")+"",B(i,4,o),g.$config$.logScriptExecution&&se(`Execute script src: ${a}`,r),t=await fetch(o),t.ok){let e=t.headers.get("content-type");$.some((t=>{var r,n,i;return null===(i=null===(r=null==e?void 0:e.toLowerCase)||void 0===r?void 0:(n=r.call(e)).includes)||void 0===i?void 0:i.call(n,t)}))&&(s=await t.text(),l.$currentScriptId$=n,Me(l,s,a||o)),Ce(i,"load")}else c=t.statusText,Ce(i,"error")}catch(e){console.error(e),c=String(e.stack||e),Ce(i,"error")}else s&&(c=Te(l,n,s,r,c));l.$currentScriptId$="",g.$postMessage$([6,r,n,c])})(i);else if(9===n)(({$winId$:e,$instanceId$:t,$refId$:r,$thisArg$:n,$args$:i})=>{if($[r])try{$[r].apply(K(e,t,[],n),K(e,t,[],i))}catch(e){console.error(e)}})(i);else if(10===n)(({$winId$:e,$forward$:t,$args$:r})=>{try{let n=p[e].$window$,i=0,s=M(t);for(;i<s;i++)i+1<s?n=n[t[i]]:n[t[i]].apply(n,K(null,e,[],r))}catch(e){console.error(e)}})(i);else if(5===n)st(i);else if(8===n){if(1!==p[i].$isInitialized$){const e=i,t=p[e],r=t.$winId$===t.$parentWinId$?"top":"iframe";se(`Initialized ${r} window ${ae(e)} environment 🎉`,e)}p[i].$isInitialized$=1,p[i].$isLoading$=0}else if(14===n)p[i].$visibilityState$=r[2];else if(13===n){const e=i.$winId$,t=p[e];t.$location$.href=i.url,function(e,t,r){const n=t.$window$.history;switch(r.type){case 0:t.$propagateHistoryChange$=!1;try{n.pushState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0;break;case 1:t.$propagateHistoryChange$=!1;try{n.replaceState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0}}(i.$winId$,t,i)}else 15===n&&((e,t,r,n,i)=>{const s=_(t,r);s&&"function"==typeof s[n]&&s[n].apply(s,i)})(...r);else 1===n?((t=>{const r=g.$config$=JSON.parse(t.$config$),n=t.$origin$;g.$importScripts$=importScripts.bind(e),g.$interfaces$=t.$interfaces$,g.$libPath$=t.$libPath$,g.$origin$=n,g.$postMessage$=postMessage.bind(e),g.$sharedDataBuffer$=t.$sharedDataBuffer$,g.$tabId$=t.$tabId$,e.importScripts=void 0,delete e.postMessage,delete e.WorkerGlobalScope,m("resolveUrl,resolveSendBeaconRequestParameters,get,set,apply").map((e=>{r[e]&&(r[e]=new Function("return "+r[e])())}))})(i),g.$postMessage$([2])):3===n?(g.$interfaces$=[...g.$interfaces$,...i],g.$isInitialized$=1,se("Initialized web worker"),g.$postMessage$([4]),ot.length&&se(`Queued ready messages: ${ot.length}`),[...ot].map(at),ot.length=0):ot.push(t)};e.onmessage=at,postMessage([0])})(self);
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+(self => {
+    const WinIdKey = Symbol();
+    const InstanceIdKey = Symbol();
+    const InstanceDataKey = Symbol();
+    const NamespaceKey = Symbol();
+    const ApplyPathKey = Symbol();
+    const InstanceStateKey = Symbol();
+    const HookContinue = Symbol();
+    const HookPrevent = Symbol();
+    const webWorkerInstances = new Map;
+    const webWorkerRefsByRefId = {};
+    const webWorkerRefIdsByRef = new WeakMap;
+    const postMessages = [];
+    const webWorkerCtx = {};
+    const environments = {};
+    const cachedDimensions = new Map;
+    const cachedStructure = new Map;
+    const commaSplit = str => str.split(",");
+    const partytownLibUrl = url => {
+        url = webWorkerCtx.$libPath$ + url;
+        if (new URL(url).origin != location.origin) {
+            throw "Invalid " + url;
+        }
+        return url;
+    };
+    const getterDimensionPropNames = commaSplit("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft");
+    const elementStructurePropNames = commaSplit("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling");
+    const structureChangingMethodNames = commaSplit("insertBefore,remove,removeChild,replaceChild");
+    const dimensionChangingSetterNames = commaSplit("className,width,height,hidden,innerHTML,innerText,textContent,text");
+    const dimensionChangingMethodNames = commaSplit("setAttribute,setAttributeNS,setProperty");
+    const eventTargetMethods = commaSplit("addEventListener,dispatchEvent,removeEventListener");
+    const nonBlockingMethods = eventTargetMethods.concat(dimensionChangingMethodNames, commaSplit("add,observe,remove,unobserve"));
+    const IS_TAG_REG = /^[A-Z_]([A-Z0-9-]*[A-Z0-9])?$/;
+    const noop = () => {};
+    const len = obj => obj.length;
+    const getConstructorName = obj => {
+        var _a, _b, _c;
+        try {
+            const constructorName = null === (_a = null == obj ? void 0 : obj.constructor) || void 0 === _a ? void 0 : _a.name;
+            if (constructorName) {
+                return constructorName;
+            }
+        } catch (e) {}
+        try {
+            const zoneJsConstructorName = null === (_c = null === (_b = null == obj ? void 0 : obj.__zone_symbol__originalInstance) || void 0 === _b ? void 0 : _b.constructor) || void 0 === _c ? void 0 : _c.name;
+            if (zoneJsConstructorName) {
+                return zoneJsConstructorName;
+            }
+        } catch (e) {}
+        return "";
+    };
+    const EMPTY_ARRAY = [];
+    const randomId = () => Math.round(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);
+    const SCRIPT_TYPE = "text/partytown";
+    const defineProperty = (obj, memberName, descriptor) => Object.defineProperty(obj, memberName, {
+        ...descriptor,
+        configurable: true
+    });
+    const defineConstructorName = (Cstr, value) => defineProperty(Cstr, "name", {
+        value: value
+    });
+    const definePrototypeProperty = (Cstr, memberName, descriptor) => defineProperty(Cstr.prototype, memberName, descriptor);
+    const definePrototypePropertyDescriptor = (Cstr, propertyDescriptorMap) => Object.defineProperties(Cstr.prototype, propertyDescriptorMap);
+    const definePrototypeValue = (Cstr, memberName, value) => definePrototypeProperty(Cstr, memberName, {
+        value: value,
+        writable: true
+    });
+    Object.freeze((obj => {
+        const properties = new Set;
+        let currentObj = obj;
+        do {
+            Object.getOwnPropertyNames(currentObj).forEach((item => {
+                "function" == typeof currentObj[item] && properties.add(item);
+            }));
+        } while ((currentObj = Object.getPrototypeOf(currentObj)) !== Object.prototype);
+        return Array.from(properties);
+    })([]));
+    function testIfMustLoadScriptOnMainThread(config, value) {
+        var _a, _b;
+        return null !== (_b = null === (_a = config.loadScriptsOnMainThread) || void 0 === _a ? void 0 : _a.map((([type, value]) => new RegExp("string" === type ? function(input) {
+            return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+        }(value) : value))).some((regexp => regexp.test(value)))) && void 0 !== _b && _b;
+    }
+    const hasInstanceStateValue = (instance, stateKey) => stateKey in instance[InstanceStateKey];
+    const getInstanceStateValue = (instance, stateKey) => instance[InstanceStateKey][stateKey];
+    const setInstanceStateValue = (instance, stateKey, stateValue) => instance[InstanceStateKey][stateKey] = stateValue;
+    const setWorkerRef = (ref, refId) => {
+        if (!(refId = webWorkerRefIdsByRef.get(ref))) {
+            webWorkerRefIdsByRef.set(ref, refId = randomId());
+            webWorkerRefsByRefId[refId] = ref;
+        }
+        return refId;
+    };
+    const getOrCreateNodeInstance = (winId, instanceId, nodeName, namespace, instance, prevInstanceId) => {
+        instance = webWorkerInstances.get(instanceId);
+        if (!instance && nodeName && environments[winId]) {
+            const prevInstance = webWorkerInstances.get(prevInstanceId || "");
+            instance = environments[winId].$createNode$(nodeName, instanceId, namespace, prevInstance);
+            webWorkerInstances.set(instanceId, instance);
+        }
+        return instance;
+    };
+    const definePrototypeNodeType = (Cstr, nodeType) => definePrototypeValue(Cstr, "nodeType", nodeType);
+    const cachedTreeProps = (Cstr, treeProps) => treeProps.map((propName => definePrototypeProperty(Cstr, propName, {
+        get() {
+            let cacheKey = getInstanceCacheKey(this, propName);
+            let result = cachedStructure.get(cacheKey);
+            if (!result) {
+                result = getter(this, [ propName ]);
+                cachedStructure.set(cacheKey, result);
+            }
+            return result;
+        }
+    })));
+    const getInstanceCacheKey = (instance, memberName, args) => [ instance[WinIdKey], instance[InstanceIdKey], memberName, ...(args || EMPTY_ARRAY).map((arg => String(arg && arg[WinIdKey] ? arg[InstanceIdKey] : arg))) ].join(".");
+    const cachedProps = (Cstr, propNames) => commaSplit(propNames).map((propName => definePrototypeProperty(Cstr, propName, {
+        get() {
+            hasInstanceStateValue(this, propName) || setInstanceStateValue(this, propName, getter(this, [ propName ]));
+            return getInstanceStateValue(this, propName);
+        },
+        set(val) {
+            getInstanceStateValue(this, propName) !== val && setter(this, [ propName ], val);
+            setInstanceStateValue(this, propName, val);
+        }
+    })));
+    const cachedDimensionProps = Cstr => getterDimensionPropNames.map((propName => definePrototypeProperty(Cstr, propName, {
+        get() {
+            const dimension = cachedDimensions.get(getInstanceCacheKey(this, propName));
+            if ("number" == typeof dimension) {
+                return dimension;
+            }
+            const groupedDimensions = getter(this, [ propName ], getterDimensionPropNames);
+            if (groupedDimensions && "object" == typeof groupedDimensions) {
+                Object.entries(groupedDimensions).map((([dimensionPropName, value]) => cachedDimensions.set(getInstanceCacheKey(this, dimensionPropName), value)));
+                return groupedDimensions[propName];
+            }
+            return groupedDimensions;
+        }
+    })));
+    const cachedDimensionMethods = (Cstr, dimensionMethodNames) => dimensionMethodNames.map((methodName => {
+        Cstr.prototype[methodName] = function(...args) {
+            let cacheKey = getInstanceCacheKey(this, methodName, args);
+            let dimensions = cachedDimensions.get(cacheKey);
+            if (!dimensions) {
+                dimensions = callMethod(this, [ methodName ], args);
+                cachedDimensions.set(cacheKey, dimensions);
+            }
+            return dimensions;
+        };
+    }));
+    const serializeForMain = ($winId$, $instanceId$, value, added, type) => void 0 !== value && (type = typeof value) ? "string" === type || "boolean" === type || "number" === type || null == value ? [ 0, value ] : "function" === type ? [ 4, {
+        $winId$: $winId$,
+        $instanceId$: $instanceId$,
+        $refId$: setWorkerRef(value)
+    } ] : (added = added || new Set) && Array.isArray(value) ? added.has(value) ? [ 1, [] ] : added.add(value) && [ 1, value.map((v => serializeForMain($winId$, $instanceId$, v, added))) ] : "object" === type ? value[InstanceIdKey] ? [ 3, [ value[WinIdKey], value[InstanceIdKey] ] ] : value instanceof Event ? [ 5, serializeObjectForMain($winId$, $instanceId$, value, false, added) ] : supportsTrustedHTML && value instanceof TrustedHTML ? [ 0, value.toString() ] : value instanceof ArrayBuffer ? [ 8, value ] : ArrayBuffer.isView(value) ? [ 9, value.buffer, getConstructorName(value) ] : [ 2, serializeObjectForMain($winId$, $instanceId$, value, true, added) ] : void 0 : value;
+    const supportsTrustedHTML = "undefined" != typeof TrustedHTML;
+    const serializeObjectForMain = (winId, instanceId, obj, includeFunctions, added, serializedObj, propName, propValue) => {
+        serializedObj = {};
+        if (!added.has(obj)) {
+            added.add(obj);
+            for (propName in obj) {
+                propValue = obj[propName];
+                (includeFunctions || "function" != typeof propValue) && (serializedObj[propName] = serializeForMain(winId, instanceId, propValue, added));
+            }
+        }
+        return serializedObj;
+    };
+    const serializeInstanceForMain = (instance, value) => instance ? serializeForMain(instance[WinIdKey], instance[InstanceIdKey], value) : [ 0, value ];
+    const deserializeFromMain = (winId, instanceId, applyPath, serializedValueTransfer, serializedType, serializedValue, obj, key) => {
+        if (serializedValueTransfer) {
+            serializedType = serializedValueTransfer[0];
+            serializedValue = serializedValueTransfer[1];
+            if (0 === serializedType || 11 === serializedType || 12 === serializedType) {
+                return serializedValue;
+            }
+            if (4 === serializedType) {
+                return deserializeRefFromMain(applyPath, serializedValue);
+            }
+            if (6 === serializedType) {
+                return winId && applyPath.length > 0 ? (...args) => callMethod(environments[winId].$window$, applyPath, args, 1) : noop;
+            }
+            if (3 === serializedType) {
+                return getOrCreateSerializedInstance(serializedValue);
+            }
+            if (7 === serializedType) {
+                return new NodeList(serializedValue.map(getOrCreateSerializedInstance));
+            }
+            if (10 === serializedType) {
+                return new Attr(serializedValue);
+            }
+            if (1 === serializedType) {
+                return serializedValue.map((v => deserializeFromMain(winId, instanceId, applyPath, v)));
+            }
+            if (14 === serializedType) {
+                return new CustomError(serializedValue);
+            }
+            obj = {};
+            for (key in serializedValue) {
+                obj[key] = deserializeFromMain(winId, instanceId, [ ...applyPath, key ], serializedValue[key]);
+            }
+            if (13 === serializedType) {
+                return new environments[winId].$window$.CSSStyleDeclaration(winId, instanceId, applyPath, obj);
+            }
+            if (5 === serializedType) {
+                if ("message" === obj.type && obj.origin) {
+                    let postMessageKey = JSON.stringify(obj.data);
+                    let postMessageData = postMessages.find((pm => pm.$data$ === postMessageKey));
+                    let env;
+                    if (postMessageData) {
+                        env = environments[postMessageData.$winId$];
+                        if (env) {
+                            obj.source = env.$window$;
+                            obj.origin = env.$location$.origin;
+                        }
+                    }
+                }
+                return new Proxy(new Event(obj.type, obj), {
+                    get: (target, propName) => propName in obj ? obj[propName] : "function" == typeof target[String(propName)] ? noop : target[String(propName)]
+                });
+            }
+            if (2 === serializedType) {
+                return obj;
+            }
+        }
+    };
+    const getOrCreateSerializedInstance = ([winId, instanceId, nodeName, prevInstanceId]) => instanceId === winId && environments[winId] ? environments[winId].$window$ : getOrCreateNodeInstance(winId, instanceId, nodeName, void 0, void 0, prevInstanceId);
+    const deserializeRefFromMain = (applyPath, {$winId$: $winId$, $instanceId$: $instanceId$, $nodeName$: $nodeName$, $refId$: $refId$}) => {
+        webWorkerRefsByRefId[$refId$] || webWorkerRefIdsByRef.set(webWorkerRefsByRefId[$refId$] = function(...args) {
+            const instance = getOrCreateNodeInstance($winId$, $instanceId$, $nodeName$);
+            return callMethod(instance, applyPath, args);
+        }, $refId$);
+        return webWorkerRefsByRefId[$refId$];
+    };
+    class CustomError extends Error {
+        constructor(errorObject) {
+            super(errorObject.message);
+            this.name = errorObject.name;
+            this.message = errorObject.message;
+            this.stack = errorObject.stack;
+        }
+    }
+    class NodeList {
+        constructor(nodes) {
+            (this._ = nodes).map(((node, index) => this[index] = node));
+        }
+        entries() {
+            return this._.entries();
+        }
+        forEach(cb, thisArg) {
+            this._.map(cb, thisArg);
+        }
+        item(index) {
+            return this[index];
+        }
+        keys() {
+            return this._.keys();
+        }
+        get length() {
+            return len(this._);
+        }
+        values() {
+            return this._.values();
+        }
+        [Symbol.iterator]() {
+            return this._[Symbol.iterator]();
+        }
+    }
+    const Attr = class {
+        constructor(serializedAttr) {
+            this.name = serializedAttr[0];
+            this.value = serializedAttr[1];
+        }
+        get nodeName() {
+            return this.name;
+        }
+        get nodeType() {
+            return 2;
+        }
+    };
+    const warnCrossOrigin = (apiType, apiName, env) => console.warn(`Partytown unable to ${apiType} cross-origin ${apiName}: ` + env.$location$);
+    const logWorker = (msg, winId) => {
+        try {
+            const config = webWorkerCtx.$config$;
+            if (config.logStackTraces) {
+                const frames = (new Error).stack.split("\n");
+                const i = frames.findIndex((f => f.includes("logWorker")));
+                msg += "\n" + frames.slice(i + 1).join("\n");
+            }
+            let prefix;
+            let color;
+            if (winId) {
+                prefix = `Worker (${normalizedWinId(winId)}) 🎉`;
+                color = winColor(winId);
+            } else {
+                prefix = self.name;
+                color = "#9844bf";
+            }
+            if (webWorkerCtx.lastLog !== msg) {
+                webWorkerCtx.lastLog = msg;
+                console.debug.apply(console, [ `%c${prefix}`, `background: ${color}; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;`, msg ]);
+            }
+        } catch (e) {}
+    };
+    const winIds = [];
+    const normalizedWinId = winId => {
+        winIds.includes(winId) || winIds.push(winId);
+        return winIds.indexOf(winId) + 1;
+    };
+    const winColor = winId => {
+        const colors = [ "#00309e", "#ea3655", "#eea727" ];
+        const index = normalizedWinId(winId) - 1;
+        return colors[index] || colors[colors.length - 1];
+    };
+    const getTargetProp = (target, applyPath) => {
+        let n = "";
+        if (target) {
+            const cstrName = getConstructorName(target);
+            if ("Window" === cstrName) {
+                n = "";
+            } else if ("string" == typeof target[InstanceDataKey]) {
+                let nodeName = target[InstanceDataKey];
+                n = "#text" === nodeName ? "textNode." : "#comment" === nodeName ? "commentNode." : "#document" === nodeName ? "document." : "html" === nodeName ? "doctype." : nodeName.toLowerCase() + ".";
+            } else {
+                n = "nodeType" in target && 2 === target.nodeType ? "attributes." : "CanvasRenderingContext2D" === cstrName ? "context2D." : "CanvasRenderingContextWebGL" === cstrName ? "contextWebGL." : "CSSStyleDeclaration" === cstrName ? "style." : "MutationObserver" === cstrName ? "mutationObserver." : "NamedNodeMap" === cstrName ? "namedNodeMap." : "ResizeObserver" === cstrName ? "resizeObserver." : cstrName.substring(0, 1).toLowerCase() + cstrName.substring(1) + ".";
+            }
+            target[ApplyPathKey] && target[ApplyPathKey].length && (n += [ ...target[ApplyPathKey] ].join(".") + ".");
+        }
+        if (applyPath.length > 1) {
+            const first = applyPath.slice(0, applyPath.length - 1);
+            const last = applyPath[applyPath.length - 1];
+            if (!isNaN(last)) {
+                return n + `${first.join(".")}[${last}]`;
+            }
+        }
+        return n + applyPath.join(".");
+    };
+    const getLogValue = (applyPath, v) => {
+        const type = typeof v;
+        if (void 0 === v) {
+            return "undefined";
+        }
+        if ("boolean" === type || "number" === type || null == v) {
+            return JSON.stringify(v);
+        }
+        if ("string" === type) {
+            return applyPath.includes("cookie") ? JSON.stringify(v.slice(0, 10) + "...") : JSON.stringify(v.length > 50 ? v.slice(0, 40) + "..." : v);
+        }
+        if (Array.isArray(v)) {
+            return `[${v.map(getLogValue).join(", ")}]`;
+        }
+        if ("object" === type) {
+            const instanceId = v[InstanceIdKey];
+            const cstrName = getConstructorName(v);
+            if ("string" == typeof instanceId) {
+                if ("Window" === cstrName) {
+                    return "window";
+                }
+                if ("string" == typeof v[InstanceDataKey]) {
+                    if (1 === v.nodeType) {
+                        return `<${v[InstanceDataKey].toLowerCase()}>`;
+                    }
+                    if (10 === v.nodeType) {
+                        return `<!DOCTYPE ${v[InstanceDataKey]}>`;
+                    }
+                    if (v.nodeType <= 11) {
+                        return v[InstanceDataKey];
+                    }
+                }
+                return "¯\\_(ツ)_/¯ instance obj";
+            }
+            return v[Symbol.iterator] ? `[${Array.from(v).map((i => getLogValue(applyPath, i))).join(", ")}]` : "value" in v ? "string" == typeof v.value ? `"${v.value}"` : objToString(v.value) : objToString(v);
+        }
+        return (v => "object" == typeof v && v && v.then)(v) ? "Promise" : "function" === type ? `ƒ() ${v.name || ""}`.trim() : `¯\\_(ツ)_/¯ ${String(v)}`.trim();
+    };
+    const objToString = obj => {
+        const s = [];
+        for (let key in obj) {
+            const value = obj[key];
+            const type = typeof value;
+            "string" === type ? s.push(`${key}: "${value}"`) : "function" === type ? s.push(`${key}: ƒ`) : Array.isArray(type) ? s.push(`${key}: [..]`) : "object" === type && value ? s.push(`${key}: {..}`) : s.push(`${key}: ${String(value)}`);
+        }
+        let str = s.join(", ");
+        str.length > 200 && (str = str.substring(0, 200) + "..");
+        return `{ ${str} }`;
+    };
+    const logDimensionCacheClearStyle = (target, propName) => {
+        (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logSetters) && logWorker(`Dimension cache cleared from style.${propName} setter`, target[WinIdKey]);
+    };
+    const logDimensionCacheClearMethod = (target, methodName) => {
+        (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logCalls) && logWorker(`Dimension cache cleared from method call ${methodName}()`, target[WinIdKey]);
+    };
+    const taskQueue = [];
+    const queue = (instance, $applyPath$, callType, $assignInstanceId$, $groupedGetters$, buffer) => {
+        if (instance[ApplyPathKey]) {
+            taskQueue.push({
+                $winId$: instance[WinIdKey],
+                $instanceId$: instance[InstanceIdKey],
+                $applyPath$: [ ...instance[ApplyPathKey], ...$applyPath$ ],
+                $assignInstanceId$: $assignInstanceId$,
+                $groupedGetters$: $groupedGetters$
+            });
+            taskQueue[len(taskQueue) - 1].$debug$ = ((target, applyPath, callType) => {
+                let m = getTargetProp(target, applyPath);
+                1 === callType ? m += " (blocking)" : 2 === callType ? m += " (non-blocking)" : 3 === callType && (m += " (non-blocking, no-side-effect)");
+                return m.trim();
+            })(instance, $applyPath$, callType);
+            buffer && 3 !== callType && console.error("buffer must be sent NonBlockingNoSideEffect");
+            if (3 === callType) {
+                webWorkerCtx.$postMessage$([ 12, {
+                    $msgId$: randomId(),
+                    $tasks$: [ ...taskQueue ]
+                } ], buffer ? [ buffer instanceof ArrayBuffer ? buffer : buffer.buffer ] : void 0);
+                taskQueue.length = 0;
+            } else if (1 === callType) {
+                return sendToMain(true);
+            }
+            webWorkerCtx.$asyncMsgTimer$ = setTimeout(sendToMain, 20);
+        }
+    };
+    const sendToMain = isBlocking => {
+        clearTimeout(webWorkerCtx.$asyncMsgTimer$);
+        if (len(taskQueue)) {
+            webWorkerCtx.$config$.logMainAccess && logWorker(`Main access, tasks sent: ${taskQueue.length}`);
+            const endTask = taskQueue[len(taskQueue) - 1];
+            const accessReq = {
+                $msgId$: `${randomId()}.${webWorkerCtx.$tabId$}`,
+                $tasks$: [ ...taskQueue ]
+            };
+            taskQueue.length = 0;
+            if (isBlocking) {
+                const accessRsp = ((webWorkerCtx, accessReq) => {
+                    const sharedDataBuffer = webWorkerCtx.$sharedDataBuffer$;
+                    const sharedData = new Int32Array(sharedDataBuffer);
+                    Atomics.store(sharedData, 0, 0);
+                    webWorkerCtx.$postMessage$([ 11, accessReq ]);
+                    Atomics.wait(sharedData, 0, 0);
+                    let dataLength = Atomics.load(sharedData, 0);
+                    let accessRespStr = "";
+                    let i = 0;
+                    for (;i < dataLength; i++) {
+                        accessRespStr += String.fromCharCode(sharedData[i + 1]);
+                    }
+                    return JSON.parse(accessRespStr);
+                })(webWorkerCtx, accessReq);
+                const isPromise = accessRsp.$isPromise$;
+                const rtnValue = deserializeFromMain(endTask.$winId$, endTask.$instanceId$, endTask.$applyPath$, accessRsp.$rtnValue$);
+                if (accessRsp.$error$) {
+                    if (isPromise) {
+                        return Promise.reject(accessRsp.$error$);
+                    }
+                    throw new Error(accessRsp.$error$);
+                }
+                return isPromise ? Promise.resolve(rtnValue) : rtnValue;
+            }
+            webWorkerCtx.$postMessage$([ 12, accessReq ]);
+        }
+    };
+    const getter = (instance, applyPath, groupedGetters, rtnValue) => {
+        if (webWorkerCtx.$config$.get) {
+            rtnValue = webWorkerCtx.$config$.get(createHookOptions(instance, applyPath));
+            if (rtnValue !== HookContinue) {
+                return rtnValue;
+            }
+        }
+        rtnValue = queue(instance, applyPath, 1, void 0, groupedGetters);
+        ((target, applyPath, rtnValue, restrictedToWorker = false, groupedGetters = false) => {
+            if (webWorkerCtx.$config$.logGetters) {
+                try {
+                    const msg = `Get ${getTargetProp(target, applyPath)}, returned: ${getLogValue(applyPath, rtnValue)}${restrictedToWorker ? " (restricted to worker)" : ""}${groupedGetters ? " (grouped getter)" : ""}`;
+                    msg.includes("Symbol(") || logWorker(msg, target[WinIdKey]);
+                } catch (e) {}
+            }
+        })(instance, applyPath, rtnValue, false, !!groupedGetters);
+        return rtnValue;
+    };
+    const setter = (instance, applyPath, value, hookSetterValue) => {
+        if (webWorkerCtx.$config$.set) {
+            hookSetterValue = webWorkerCtx.$config$.set({
+                value: value,
+                prevent: HookPrevent,
+                ...createHookOptions(instance, applyPath)
+            });
+            if (hookSetterValue === HookPrevent) {
+                return;
+            }
+            hookSetterValue !== HookContinue && (value = hookSetterValue);
+        }
+        if (dimensionChangingSetterNames.some((s => applyPath.includes(s)))) {
+            cachedDimensions.clear();
+            ((target, propName) => {
+                (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logSetters) && logWorker(`Dimension cache cleared from setter "${propName}"`, target[WinIdKey]);
+            })(instance, applyPath[applyPath.length - 1]);
+        }
+        applyPath = [ ...applyPath, serializeInstanceForMain(instance, value), 0 ];
+        ((target, applyPath, value, restrictedToWorker = false) => {
+            if (webWorkerCtx.$config$.logSetters) {
+                try {
+                    applyPath = applyPath.slice(0, applyPath.length - 2);
+                    logWorker(`Set ${getTargetProp(target, applyPath)}, value: ${getLogValue(applyPath, value)}${restrictedToWorker ? " (restricted to worker)" : ""}`, target[WinIdKey]);
+                } catch (e) {}
+            }
+        })(instance, applyPath, value);
+        queue(instance, applyPath, 2);
+    };
+    const callMethod = (instance, applyPath, args, callType, assignInstanceId, buffer, rtnValue, methodName) => {
+        if (webWorkerCtx.$config$.apply) {
+            rtnValue = webWorkerCtx.$config$.apply({
+                args: args,
+                ...createHookOptions(instance, applyPath)
+            });
+            if (rtnValue !== HookContinue) {
+                return rtnValue;
+            }
+        }
+        methodName = applyPath[len(applyPath) - 1];
+        applyPath = [ ...applyPath, serializeInstanceForMain(instance, args) ];
+        callType = callType || (nonBlockingMethods.includes(methodName) ? 2 : 1);
+        if ("setAttribute" === methodName && hasInstanceStateValue(instance, args[0])) {
+            setInstanceStateValue(instance, args[0], args[1]);
+        } else if (structureChangingMethodNames.includes(methodName)) {
+            cachedDimensions.clear();
+            cachedStructure.clear();
+            ((target, methodName) => {
+                (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logCalls) && logWorker(`Dimension and DOM structure cache cleared from method call ${methodName}()`, target[WinIdKey]);
+            })(instance, methodName);
+        } else if (dimensionChangingMethodNames.includes(methodName)) {
+            callType = 2;
+            cachedDimensions.clear();
+            logDimensionCacheClearMethod(instance, methodName);
+        }
+        rtnValue = queue(instance, applyPath, callType, assignInstanceId, void 0, buffer);
+        ((target, applyPath, args, rtnValue) => {
+            if (webWorkerCtx.$config$.logCalls) {
+                try {
+                    applyPath = applyPath.slice(0, applyPath.length - 1);
+                    logWorker(`Call ${getTargetProp(target, applyPath)}(${args.map((v => getLogValue(applyPath, v))).join(", ")}), returned: ${getLogValue(applyPath, rtnValue)}`, target[WinIdKey]);
+                } catch (e) {}
+            }
+        })(instance, applyPath, args, rtnValue);
+        return rtnValue;
+    };
+    const constructGlobal = (instance, cstrName, args) => {
+        ((target, cstrName, args) => {
+            if (webWorkerCtx.$config$.logCalls) {
+                try {
+                    logWorker(`Construct new ${cstrName}(${args.map((v => getLogValue([], v))).join(", ")})`, target[WinIdKey]);
+                } catch (e) {}
+            }
+        })(instance, cstrName, args);
+        queue(instance, [ 1, cstrName, serializeInstanceForMain(instance, args) ], 1);
+    };
+    const createHookOptions = (instance, applyPath) => ({
+        name: applyPath.join("."),
+        continue: HookContinue,
+        nodeName: instance[InstanceDataKey],
+        constructor: getConstructorName(instance),
+        instance: instance,
+        window: environments[instance[WinIdKey]].$window$
+    });
+    const addStorageApi = (win, storageName, env) => {
+        let storage = {
+            getItem(key) {
+                if (env.$isSameOrigin$) {
+                    return callMethod(win, [ storageName, "getItem" ], [ key ], 1);
+                }
+                warnCrossOrigin("get", storageName, env);
+            },
+            setItem(key, value) {
+                env.$isSameOrigin$ ? callMethod(win, [ storageName, "setItem" ], [ key, value ], 1) : warnCrossOrigin("set", storageName, env);
+            },
+            removeItem(key) {
+                env.$isSameOrigin$ ? callMethod(win, [ storageName, "removeItem" ], [ key ], 1) : warnCrossOrigin("remove", storageName, env);
+            },
+            key(index) {
+                if (env.$isSameOrigin$) {
+                    return callMethod(win, [ storageName, "key" ], [ index ], 1);
+                }
+                warnCrossOrigin("key", storageName, env);
+            },
+            clear() {
+                env.$isSameOrigin$ ? callMethod(win, [ storageName, "clear" ], EMPTY_ARRAY, 1) : warnCrossOrigin("clear", storageName, env);
+            },
+            get length() {
+                if (env.$isSameOrigin$) {
+                    return getter(win, [ storageName, "length" ]);
+                }
+                warnCrossOrigin("length", storageName, env);
+            }
+        };
+        win[storageName] = new Proxy(storage, {
+            get: (target, key) => Reflect.has(target, key) ? Reflect.get(target, key) : target.getItem(key),
+            set(target, key, value) {
+                target.setItem(key, value);
+                return true;
+            },
+            has: (target, key) => !!Reflect.has(target, key) || "string" == typeof key && null !== target.getItem(key),
+            deleteProperty(target, key) {
+                target.removeItem(key);
+                return true;
+            }
+        });
+    };
+    const createCSSStyleDeclarationCstr = (win, WorkerBase, cstrName) => {
+        win[cstrName] = defineConstructorName(class extends WorkerBase {
+            constructor(winId, instanceId, applyPath, styles) {
+                super(winId, instanceId, applyPath, styles || {});
+                return new Proxy(this, {
+                    get(target, propName) {
+                        if (target[propName]) {
+                            return target[propName];
+                        }
+                        target[propName] || "string" != typeof propName || target[InstanceDataKey][propName] || (target[InstanceDataKey][propName] = getter(target, [ propName ]));
+                        return target[InstanceDataKey][propName];
+                    },
+                    set(target, propName, propValue) {
+                        target[InstanceDataKey][propName] = propValue;
+                        setter(target, [ propName ], propValue);
+                        logDimensionCacheClearStyle(target, propName);
+                        cachedDimensions.clear();
+                        return true;
+                    }
+                });
+            }
+            setProperty(...args) {
+                this[InstanceDataKey][args[0]] = args[1];
+                callMethod(this, [ "setProperty" ], args, 2);
+                logDimensionCacheClearStyle(this, args[0]);
+                cachedDimensions.clear();
+            }
+            getPropertyValue(propName) {
+                return this[propName];
+            }
+            removeProperty(propName) {
+                let value = this[InstanceDataKey][propName];
+                callMethod(this, [ "removeProperty" ], [ propName ], 2);
+                logDimensionCacheClearStyle(this, propName);
+                cachedDimensions.clear();
+                this[InstanceDataKey][propName] = void 0;
+                return value;
+            }
+        }, cstrName);
+    };
+    const createCSSStyleSheetConstructor = (win, cssStyleSheetCstrName) => {
+        win[cssStyleSheetCstrName] = defineConstructorName(class {
+            constructor(ownerNode) {
+                this.ownerNode = ownerNode;
+            }
+            get cssRules() {
+                const ownerNode = this.ownerNode;
+                return new Proxy({}, {
+                    get(target, propKey) {
+                        const propName = String(propKey);
+                        return "item" === propName ? index => getCssRule(ownerNode, index) : "length" === propName ? getCssRules(ownerNode).length : isNaN(propName) ? target[propKey] : getCssRule(ownerNode, propName);
+                    }
+                });
+            }
+            insertRule(ruleText, index) {
+                const cssRules = getCssRules(this.ownerNode);
+                index = void 0 === index ? 0 : index;
+                if (index >= 0 && index <= cssRules.length) {
+                    callMethod(this.ownerNode, [ "sheet", "insertRule" ], [ ruleText, index ], 2);
+                    cssRules.splice(index, 0, 0);
+                }
+                logDimensionCacheClearMethod(this.ownerNode, "insertRule");
+                cachedDimensions.clear();
+                return index;
+            }
+            deleteRule(index) {
+                callMethod(this.ownerNode, [ "sheet", "deleteRule" ], [ index ], 2);
+                getCssRules(this.ownerNode).splice(index, 1);
+                logDimensionCacheClearMethod(this.ownerNode, "deleteRule");
+                cachedDimensions.clear();
+            }
+            get type() {
+                return "text/css";
+            }
+        }, cssStyleSheetCstrName);
+        const HTMLStyleDescriptorMap = {
+            sheet: {
+                get() {
+                    return new win[cssStyleSheetCstrName](this);
+                }
+            }
+        };
+        definePrototypePropertyDescriptor(win.HTMLStyleElement, HTMLStyleDescriptorMap);
+    };
+    const getCssRules = (ownerNode, cssRules) => {
+        cssRules = getInstanceStateValue(ownerNode, 2);
+        if (!cssRules) {
+            cssRules = getter(ownerNode, [ "sheet", "cssRules" ]);
+            setInstanceStateValue(ownerNode, 2, cssRules);
+        }
+        return cssRules;
+    };
+    const getCssRule = (ownerNode, index, cssRules) => {
+        cssRules = getCssRules(ownerNode);
+        0 === cssRules[index] && (cssRules[index] = getter(ownerNode, [ "sheet", "cssRules", parseInt(index, 10) ]));
+        return cssRules[index];
+    };
+    const runScriptContent = (env, instanceId, scriptContent, winId, errorMsg) => {
+        try {
+            webWorkerCtx.$config$.logScriptExecution && logWorker(`Execute script: ${scriptContent.substring(0, 100).split("\n").map((l => l.trim())).join(" ").trim().substring(0, 60)}...`, winId);
+            env.$currentScriptId$ = instanceId;
+            run(env, scriptContent);
+        } catch (contentError) {
+            console.error(scriptContent, contentError);
+            errorMsg = String(contentError.stack || contentError);
+        }
+        env.$currentScriptId$ = "";
+        return errorMsg;
+    };
+    const run = (env, scriptContent, scriptUrl) => {
+        env.$runWindowLoadEvent$ = 1;
+        let sourceWithReplacedThis = ((scriptContent, newThis) => scriptContent.replace(/([a-zA-Z0-9_$\.\'\"\`])?(\.\.\.)?this(?![a-zA-Z0-9_$:])/g, ((match, p1, p2) => {
+            const prefix = (p1 || "") + (p2 || "");
+            return null != p1 ? prefix + "this" : prefix + newThis;
+        })))(scriptContent, "(thi$(this)?window:this)");
+        scriptContent = `with(this){${sourceWithReplacedThis.replace(/\/\/# so/g, "//Xso")}\n;function thi$(t){return t===this}};${(webWorkerCtx.$config$.globalFns || []).filter((globalFnName => /[a-zA-Z_$][0-9a-zA-Z_$]*/.test(globalFnName))).map((g => `(typeof ${g}=='function'&&(this.${g}=${g}))`)).join(";")};` + (scriptUrl ? "\n//# sourceURL=" + scriptUrl : "");
+        env.$isSameOrigin$ || (scriptContent = scriptContent.replace(/.postMessage\(/g, `.postMessage('${env.$winId$}',`));
+        new Function(scriptContent).call(env.$window$);
+        env.$runWindowLoadEvent$ = 0;
+    };
+    const runStateLoadHandlers = (instance, type, handlers) => {
+        handlers = getInstanceStateValue(instance, type);
+        handlers && setTimeout((() => handlers.map((cb => cb({
+            type: type
+        })))));
+    };
+    const resolveBaseLocation = (env, baseLocation) => {
+        baseLocation = env.$location$;
+        while (!baseLocation.host) {
+            env = environments[env.$parentWinId$];
+            baseLocation = env.$location$;
+            if (env.$winId$ === env.$parentWinId$) {
+                break;
+            }
+        }
+        return baseLocation;
+    };
+    const resolveToUrl = (env, url, type, baseLocation, resolvedUrl, configResolvedUrl) => {
+        baseLocation = resolveBaseLocation(env, baseLocation);
+        resolvedUrl = new URL(url || "", baseLocation);
+        if (type && webWorkerCtx.$config$.resolveUrl) {
+            configResolvedUrl = webWorkerCtx.$config$.resolveUrl(resolvedUrl, baseLocation, type);
+            if (configResolvedUrl) {
+                return configResolvedUrl;
+            }
+        }
+        return resolvedUrl;
+    };
+    const resolveUrl = (env, url, type) => resolveToUrl(env, url, type) + "";
+    const resolveSendBeaconRequestParameters = (env, url) => {
+        const baseLocation = resolveBaseLocation(env);
+        const resolvedUrl = new URL(url || "", baseLocation);
+        if (webWorkerCtx.$config$.resolveSendBeaconRequestParameters) {
+            const configResolvedParams = webWorkerCtx.$config$.resolveSendBeaconRequestParameters(resolvedUrl, baseLocation);
+            if (configResolvedParams) {
+                return configResolvedParams;
+            }
+        }
+        return {};
+    };
+    const getPartytownScript = () => `<script src="${partytownLibUrl("partytown.js?v=0.10.2-dev1727590485751")}"><\/script>`;
+    const createImageConstructor = env => class HTMLImageElement {
+        constructor() {
+            this.s = "";
+            this.l = [];
+            this.e = [];
+            this.style = {};
+        }
+        get src() {
+            return this.s;
+        }
+        set src(src) {
+            webWorkerCtx.$config$.logImageRequests && logWorker(`Image() request: ${resolveUrl(env, src, "image")}`, env.$winId$);
+            this.s = src;
+            fetch(resolveUrl(env, src, "image"), {
+                mode: "no-cors",
+                credentials: "include",
+                keepalive: true
+            }).then((rsp => {
+                rsp.ok || 0 === rsp.status ? this.l.map((cb => cb({
+                    type: "load"
+                }))) : this.e.map((cb => cb({
+                    type: "error"
+                })));
+            }), (() => this.e.forEach((cb => cb({
+                type: "error"
+            })))));
+        }
+        addEventListener(eventName, cb) {
+            "load" === eventName && this.l.push(cb);
+            "error" === eventName && this.e.push(cb);
+        }
+        removeEventListener(eventName, cb) {
+            "load" === eventName && (this.l = this.l.filter((fn => fn !== cb)));
+            "error" === eventName && (this.e = this.e.filter((fn => fn !== cb)));
+        }
+        get onload() {
+            return this.l[0];
+        }
+        set onload(cb) {
+            this.l = [ cb ];
+        }
+        get onerror() {
+            return this.e[0];
+        }
+        set onerror(cb) {
+            this.e = [ cb ];
+        }
+    };
+    const HTMLSrcElementDescriptorMap = {
+        addEventListener: {
+            value(...args) {
+                const eventName = args[0];
+                const callbacks = getInstanceStateValue(this, eventName) || [];
+                callbacks.push(args[1]);
+                setInstanceStateValue(this, eventName, callbacks);
+            }
+        },
+        async: {
+            get: noop,
+            set: noop
+        },
+        defer: {
+            get: noop,
+            set: noop
+        },
+        onload: {
+            get() {
+                let callbacks = getInstanceStateValue(this, "load");
+                return callbacks && callbacks[0] || null;
+            },
+            set(cb) {
+                setInstanceStateValue(this, "load", cb ? [ cb ] : null);
+            }
+        },
+        onerror: {
+            get() {
+                let callbacks = getInstanceStateValue(this, "error");
+                return callbacks && callbacks[0] || null;
+            },
+            set(cb) {
+                setInstanceStateValue(this, "error", cb ? [ cb ] : null);
+            }
+        },
+        getAttribute: {
+            value(attrName) {
+                return "src" === attrName ? this.src : callMethod(this, [ "getAttribute" ], [ attrName ]);
+            }
+        },
+        setAttribute: {
+            value(attrName, attrValue) {
+                scriptAttrPropNames.includes(attrName) ? this[attrName] = attrValue : callMethod(this, [ "setAttribute" ], [ attrName, attrValue ]);
+            }
+        }
+    };
+    const scriptAttrPropNames = commaSplit("src,type");
+    const patchHTMLScriptElement = (WorkerHTMLScriptElement, env) => {
+        const HTMLScriptDescriptorMap = {
+            innerHTML: innerHTMLDescriptor,
+            innerText: innerHTMLDescriptor,
+            src: {
+                get() {
+                    return getInstanceStateValue(this, 4) || "";
+                },
+                set(url) {
+                    const orgUrl = resolveUrl(env, url, null);
+                    const config = webWorkerCtx.$config$;
+                    url = resolveUrl(env, url, "script");
+                    setInstanceStateValue(this, 4, url);
+                    setter(this, [ "src" ], url);
+                    orgUrl !== url && setter(this, [ "dataset", "ptsrc" ], orgUrl);
+                    if (this.type) {
+                        const shouldExecuteScriptViaMainThread = testIfMustLoadScriptOnMainThread(config, url);
+                        shouldExecuteScriptViaMainThread && setter(this, [ "type" ], "text/javascript");
+                    }
+                }
+            },
+            text: innerHTMLDescriptor,
+            textContent: innerHTMLDescriptor,
+            type: {
+                get() {
+                    return getter(this, [ "type" ]);
+                },
+                set(type) {
+                    if (!isScriptJsType(type)) {
+                        setInstanceStateValue(this, 5, type);
+                        setter(this, [ "type" ], type);
+                    }
+                }
+            },
+            ...HTMLSrcElementDescriptorMap
+        };
+        definePrototypePropertyDescriptor(WorkerHTMLScriptElement, HTMLScriptDescriptorMap);
+    };
+    const innerHTMLDescriptor = {
+        get() {
+            const type = getter(this, [ "type" ]);
+            if (isScriptJsType(type)) {
+                const scriptContent = getInstanceStateValue(this, 3);
+                if (scriptContent) {
+                    return scriptContent;
+                }
+            }
+            return getter(this, [ "innerHTML" ]) || "";
+        },
+        set(scriptContent) {
+            setInstanceStateValue(this, 3, scriptContent);
+        }
+    };
+    const isScriptJsType = scriptType => !scriptType || "text/javascript" === scriptType;
+    const createNodeCstr = (win, env, WorkerBase) => {
+        const config = webWorkerCtx.$config$;
+        const WorkerNode = defineConstructorName(class extends WorkerBase {
+            appendChild(node) {
+                return this.insertBefore(node, null);
+            }
+            get href() {}
+            set href(_) {}
+            insertBefore(newNode, referenceNode) {
+                const winId = newNode[WinIdKey] = this[WinIdKey];
+                const instanceId = newNode[InstanceIdKey];
+                const nodeName = newNode[InstanceDataKey];
+                const isScript = "SCRIPT" === nodeName;
+                const isIFrame = "IFRAME" === nodeName;
+                if (isScript) {
+                    const scriptContent = getInstanceStateValue(newNode, 3);
+                    const scriptType = getInstanceStateValue(newNode, 5);
+                    if (scriptContent) {
+                        if (isScriptJsType(scriptType)) {
+                            const scriptId = newNode.id;
+                            const loadOnMainThread = scriptId && testIfMustLoadScriptOnMainThread(config, scriptId);
+                            if (loadOnMainThread) {
+                                setter(newNode, [ "type" ], "text/javascript");
+                            } else {
+                                const errorMsg = runScriptContent(env, instanceId, scriptContent, winId, "");
+                                const datasetType = errorMsg ? "pterror" : "ptid";
+                                const datasetValue = errorMsg || instanceId;
+                                setter(newNode, [ "type" ], "text/partytown-x");
+                                setter(newNode, [ "dataset", datasetType ], datasetValue);
+                            }
+                        }
+                        setter(newNode, [ "innerHTML" ], scriptContent);
+                    }
+                }
+                callMethod(this, [ "insertBefore" ], [ newNode, referenceNode ], 2);
+                if (isIFrame) {
+                    const src = getInstanceStateValue(newNode, 0);
+                    if (src && src.startsWith("javascript:")) {
+                        const scriptContent = src.split("javascript:")[1];
+                        runScriptContent(env, instanceId, scriptContent, winId, "");
+                    }
+                    ((winId, iframe) => {
+                        let i = 0;
+                        let type;
+                        let handlers;
+                        let callback = () => {
+                            if (environments[winId] && environments[winId].$isInitialized$ && !environments[winId].$isLoading$) {
+                                type = getInstanceStateValue(iframe, 1) ? "error" : "load";
+                                handlers = getInstanceStateValue(iframe, type);
+                                handlers && handlers.map((handler => handler({
+                                    type: type
+                                })));
+                            } else if (i++ > 2e3) {
+                                handlers = getInstanceStateValue(iframe, "error");
+                                handlers && handlers.map((handler => handler({
+                                    type: "error"
+                                })));
+                            } else {
+                                setTimeout(callback, 9);
+                            }
+                        };
+                        callback();
+                    })(instanceId, newNode);
+                }
+                if (isScript) {
+                    sendToMain(true);
+                    webWorkerCtx.$postMessage$([ 7, winId ]);
+                }
+                return newNode;
+            }
+            get nodeName() {
+                return "#s" === this[InstanceDataKey] ? "#document-fragment" : this[InstanceDataKey];
+            }
+            get nodeType() {
+                return 3;
+            }
+            get ownerDocument() {
+                return env.$document$;
+            }
+        }, "Node");
+        cachedTreeProps(WorkerNode, commaSplit("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling"));
+        win.Node = WorkerNode;
+    };
+    const htmlMedia = commaSplit("AUDIO,CANVAS,VIDEO");
+    const windowMediaConstructors = commaSplit("Audio,MediaSource");
+    const patchDocument = (WorkerDocument, env, isDocumentImplementation) => {
+        const DocumentDescriptorMap = {
+            body: {
+                get: () => env.$body$
+            },
+            cookie: {
+                get() {
+                    if (env.$isSameOrigin$) {
+                        return getter(this, [ "cookie" ]);
+                    }
+                    warnCrossOrigin("get", "cookie", env);
+                    return "";
+                },
+                set(value) {
+                    if (env.$isSameOrigin$) {
+                        setter(this, [ "cookie" ], value);
+                    } else {
+                        warnCrossOrigin("set", "cookie", env);
+                    }
+                }
+            },
+            createElement: {
+                value(tagName) {
+                    tagName = tagName.toUpperCase();
+                    if (!IS_TAG_REG.test(tagName)) {
+                        throw tagName + " not valid";
+                    }
+                    const isIframe = "IFRAME" === tagName;
+                    const winId = this[WinIdKey];
+                    const instanceId = (isIframe ? "f_" : "") + randomId();
+                    callMethod(this, [ "createElement" ], [ tagName ], 2, instanceId);
+                    const elm = getOrCreateNodeInstance(winId, instanceId, tagName);
+                    if (isIframe) {
+                        const env = createEnvironment({
+                            $winId$: instanceId,
+                            $parentWinId$: winId,
+                            $url$: "about:blank"
+                        }, true);
+                        env.$window$.fetch = fetch;
+                        setter(elm, [ "srcdoc" ], getPartytownScript());
+                    } else if ("SCRIPT" === tagName) {
+                        const scriptType = getInstanceStateValue(elm, 5);
+                        isScriptJsType(scriptType) && setter(elm, [ "type" ], "text/partytown");
+                    }
+                    return elm;
+                }
+            },
+            createElementNS: {
+                value(namespace, tagName) {
+                    const instanceId = randomId();
+                    const nsElm = getOrCreateNodeInstance(this[WinIdKey], instanceId, tagName, namespace);
+                    callMethod(this, [ "createElementNS" ], [ namespace, tagName ], 2, instanceId);
+                    return nsElm;
+                }
+            },
+            createTextNode: {
+                value(text) {
+                    const winId = this[WinIdKey];
+                    const instanceId = randomId();
+                    const textNode = getOrCreateNodeInstance(winId, instanceId, "#text");
+                    callMethod(this, [ "createTextNode" ], [ text ], 2, instanceId);
+                    return textNode;
+                }
+            },
+            createEvent: {
+                value: type => new Event(type)
+            },
+            currentScript: {
+                get() {
+                    return env.$currentScriptId$ ? getOrCreateNodeInstance(this[WinIdKey], env.$currentScriptId$, "SCRIPT") : null;
+                }
+            },
+            defaultView: {
+                get: () => isDocumentImplementation ? null : env.$window$
+            },
+            documentElement: {
+                get: () => env.$documentElement$
+            },
+            getElementsByTagName: {
+                value(tagName) {
+                    tagName = tagName.toUpperCase();
+                    return "BODY" === tagName ? [ env.$body$ ] : "HEAD" === tagName ? [ env.$head$ ] : callMethod(this, [ "getElementsByTagName" ], [ tagName ]);
+                }
+            },
+            head: {
+                get: () => env.$head$
+            },
+            images: {
+                get() {
+                    return getter(this, [ "images" ]);
+                }
+            },
+            scripts: {
+                get() {
+                    return getter(this, [ "scripts" ]);
+                }
+            },
+            implementation: {
+                get() {
+                    return {
+                        hasFeature: () => true,
+                        createHTMLDocument: title => {
+                            const $winId$ = randomId();
+                            callMethod(this, [ "implementation", "createHTMLDocument" ], [ title ], 1, {
+                                $winId$: $winId$
+                            });
+                            const docEnv = createEnvironment({
+                                $winId$: $winId$,
+                                $parentWinId$: $winId$,
+                                $url$: env.$location$ + "",
+                                $visibilityState$: "hidden"
+                            }, true, true);
+                            return docEnv.$document$;
+                        }
+                    };
+                }
+            },
+            location: {
+                get: () => env.$location$,
+                set(url) {
+                    env.$location$.href = url + "";
+                }
+            },
+            nodeType: {
+                value: 9
+            },
+            parentNode: {
+                value: null
+            },
+            parentElement: {
+                value: null
+            },
+            readyState: {
+                value: "complete"
+            },
+            visibilityState: {
+                get: () => env.$visibilityState$ || "visible"
+            }
+        };
+        definePrototypePropertyDescriptor(WorkerDocument, DocumentDescriptorMap);
+        cachedProps(WorkerDocument, "compatMode,referrer,forms");
+    };
+    const patchDocumentElementChild = (WokerDocumentElementChild, env) => {
+        const DocumentElementChildDescriptorMap = {
+            parentElement: {
+                get() {
+                    return this.parentNode;
+                }
+            },
+            parentNode: {
+                get: () => env.$documentElement$
+            }
+        };
+        definePrototypePropertyDescriptor(WokerDocumentElementChild, DocumentElementChildDescriptorMap);
+    };
+    const patchElement = (WorkerElement, WorkerHTMLElement) => {
+        const ElementDescriptorMap = {
+            localName: {
+                get() {
+                    return this[InstanceDataKey].toLowerCase();
+                }
+            },
+            namespaceURI: {
+                get() {
+                    return this[NamespaceKey] || "http://www.w3.org/1999/xhtml";
+                }
+            },
+            nodeType: {
+                value: 1
+            },
+            tagName: {
+                get() {
+                    return this[InstanceDataKey];
+                }
+            }
+        };
+        definePrototypePropertyDescriptor(WorkerElement, ElementDescriptorMap);
+        cachedTreeProps(WorkerElement, elementStructurePropNames);
+        cachedProps(WorkerElement, "id");
+        cachedDimensionProps(WorkerHTMLElement);
+        cachedDimensionMethods(WorkerHTMLElement, commaSplit("getClientRects,getBoundingClientRect"));
+    };
+    const patchHTMLAnchorElement = (WorkerHTMLAnchorElement, env) => {
+        const HTMLAnchorDescriptorMap = {};
+        commaSplit("hash,host,hostname,href,origin,pathname,port,protocol,search").map((anchorProp => {
+            HTMLAnchorDescriptorMap[anchorProp] = {
+                get() {
+                    let value = getInstanceStateValue(this, 4);
+                    let href;
+                    if ("string" != typeof value) {
+                        href = getter(this, [ "href" ]);
+                        if ("" === href) {
+                            return "protocol" === anchorProp ? ":" : "";
+                        }
+                        setInstanceStateValue(this, 4, href);
+                        value = new URL(href)[anchorProp];
+                    }
+                    return resolveToUrl(env, value, null)[anchorProp];
+                },
+                set(value) {
+                    let url;
+                    if ("href" === anchorProp) {
+                        if ((url => {
+                            try {
+                                new URL(url);
+                                return true;
+                            } catch (_) {
+                                return false;
+                            }
+                        })(value)) {
+                            url = new URL(value);
+                        } else {
+                            const baseHref = env.$location$.href;
+                            url = resolveToUrl(env, baseHref, null);
+                            url.href = new URL(value + "", url.href);
+                        }
+                    } else {
+                        url = resolveToUrl(env, this.href, null);
+                        url[anchorProp] = value;
+                    }
+                    setInstanceStateValue(this, 4, url.href);
+                    setter(this, [ "href" ], url.href);
+                }
+            };
+        }));
+        definePrototypePropertyDescriptor(WorkerHTMLAnchorElement, HTMLAnchorDescriptorMap);
+    };
+    const patchHTMLIFrameElement = (WorkerHTMLIFrameElement, env) => {
+        const HTMLIFrameDescriptorMap = {
+            contentDocument: {
+                get() {
+                    return getIframeEnv(this).$document$;
+                }
+            },
+            contentWindow: {
+                get() {
+                    return getIframeEnv(this).$window$;
+                }
+            },
+            src: {
+                get() {
+                    let src = getInstanceStateValue(this, 0);
+                    if (src && src.startsWith("javascript:")) {
+                        return src;
+                    }
+                    src = getIframeEnv(this).$location$.href;
+                    return src.startsWith("about:") ? "" : src;
+                },
+                set(src) {
+                    if (src) {
+                        if (src.startsWith("javascript:")) {
+                            setInstanceStateValue(this, 0, src);
+                        } else if (!src.startsWith("about:")) {
+                            let xhr = new XMLHttpRequest;
+                            let xhrStatus;
+                            let env = getIframeEnv(this);
+                            env.$location$.href = src = resolveUrl(env, src, "iframe");
+                            env.$isLoading$ = 1;
+                            env.$isSameOrigin$ = webWorkerCtx.$origin$ === env.$location$.origin;
+                            setInstanceStateValue(this, 1, void 0);
+                            xhr.open("GET", src, false);
+                            xhr.send();
+                            xhrStatus = xhr.status;
+                            if (xhrStatus > 199 && xhrStatus < 300) {
+                                setter(this, [ "srcdoc" ], `<base href="${src}">` + function(text) {
+                                    return text.replace(SCRIPT_TAG_REGEXP, ((_, attrs) => {
+                                        const parts = [];
+                                        let hasType = false;
+                                        let match;
+                                        while (match = ATTR_REGEXP.exec(attrs)) {
+                                            let [keyValue] = match;
+                                            if (keyValue.startsWith("type=")) {
+                                                hasType = true;
+                                                keyValue = keyValue.replace(/(application|text)\/javascript/, SCRIPT_TYPE);
+                                            }
+                                            parts.push(keyValue);
+                                        }
+                                        hasType || parts.push('type="text/partytown"');
+                                        return `<script ${parts.join(" ")}>`;
+                                    }));
+                                }(xhr.responseText) + getPartytownScript());
+                                sendToMain(true);
+                                webWorkerCtx.$postMessage$([ 7, env.$winId$ ]);
+                            } else {
+                                setInstanceStateValue(this, 1, xhrStatus);
+                                env.$isLoading$ = 0;
+                            }
+                        }
+                    }
+                }
+            },
+            ...HTMLSrcElementDescriptorMap
+        };
+        definePrototypePropertyDescriptor(WorkerHTMLIFrameElement, HTMLIFrameDescriptorMap);
+    };
+    const ATTR_REGEXP_STR = "((?:\\w|-)+(?:=(?:(?:\\w|-)+|'[^']*'|\"[^\"]*\")?)?)";
+    const SCRIPT_TAG_REGEXP = new RegExp(`<script\\s*((${ATTR_REGEXP_STR}\\s*)*)>`, "mg");
+    const ATTR_REGEXP = new RegExp(ATTR_REGEXP_STR, "mg");
+    const getIframeEnv = iframe => {
+        const $winId$ = iframe[InstanceIdKey];
+        environments[$winId$] || createEnvironment({
+            $winId$: $winId$,
+            $parentWinId$: iframe[WinIdKey],
+            $url$: getter(iframe, [ "src" ]) || "about:blank"
+        }, true);
+        return environments[$winId$];
+    };
+    const patchSvgElement = WorkerSVGGraphicsElement => {
+        const getMatrix = (elm, methodName) => {
+            const {a: a, b: b, c: c, d: d, e: e, f: f} = callMethod(elm, [ methodName ], EMPTY_ARRAY);
+            return new DOMMatrixReadOnly([ a, b, c, d, e, f ]);
+        };
+        const SVGGraphicsElementDescriptorMap = {
+            ...WorkerSVGGraphicsElement,
+            getCTM: {
+                value: function() {
+                    return getMatrix(this, "getCTM");
+                }
+            },
+            getScreenCTM: {
+                value: function() {
+                    return getMatrix(this, "getScreenCTM");
+                }
+            }
+        };
+        definePrototypePropertyDescriptor(WorkerSVGGraphicsElement, SVGGraphicsElementDescriptorMap);
+    };
+    const createNamedNodeMapCstr = (win, WorkerBase) => {
+        win.NamedNodeMap = defineConstructorName(class NamedNodeMap extends WorkerBase {
+            constructor(winId, instanceId, applyPath) {
+                super(winId, instanceId, applyPath);
+                return new Proxy(this, {
+                    get(target, propName) {
+                        const handler = NAMED_NODE_MAP_HANDLERS[propName];
+                        return handler ? handler.bind(target, [ propName ]) : getter(target, [ propName ]);
+                    },
+                    set(target, propName, propValue) {
+                        const handler = NAMED_NODE_MAP_HANDLERS[propName];
+                        if (handler) {
+                            throw new Error("Can't set read-only property: " + String(propName));
+                        }
+                        setter(target, [ propName ], propValue);
+                        return true;
+                    }
+                });
+            }
+        }, "NamedNodeMap");
+    };
+    function method(applyPath, ...args) {
+        return callMethod(this, applyPath, args, 1);
+    }
+    const NAMED_NODE_MAP_HANDLERS = {
+        getNamedItem: method,
+        getNamedItemNS: method,
+        item: method,
+        removeNamedItem: method,
+        removeNamedItemNS: method,
+        setNamedItem: method,
+        setNamedItemNS: method
+    };
+    const createWindow = ($winId$, $parentWinId$, url, $visibilityState$, isIframeWindow, isDocumentImplementation) => {
+        let cstrInstanceId;
+        let cstrNodeName;
+        let cstrNamespace;
+        let cstrPrevInstance;
+        const WorkerBase = class {
+            constructor(winId, instanceId, applyPath, instanceData, namespace) {
+                this[WinIdKey] = winId || $winId$;
+                this[InstanceIdKey] = instanceId || cstrInstanceId || randomId();
+                this[ApplyPathKey] = applyPath || [];
+                this[InstanceDataKey] = instanceData || cstrNodeName;
+                this[NamespaceKey] = namespace || cstrNamespace;
+                this[InstanceStateKey] = cstrPrevInstance && cstrPrevInstance[InstanceStateKey] || {};
+                cstrInstanceId = cstrNodeName = cstrNamespace = void 0;
+            }
+        };
+        const WorkerLocation = defineConstructorName(class extends URL {
+            assign() {
+                logWorker("location.assign(), noop");
+            }
+            reload() {
+                logWorker("location.reload(), noop");
+            }
+            replace() {
+                logWorker("location.replace(), noop");
+            }
+        }, "Location");
+        const $location$ = new WorkerLocation(url);
+        const $isSameOrigin$ = $location$.origin === webWorkerCtx.$origin$ || "about:blank" === $location$.origin;
+        const $isTopWindow$ = $parentWinId$ === $winId$;
+        const env = {};
+        const getChildEnvs = () => {
+            let childEnv = [];
+            let envWinId;
+            let otherEnv;
+            for (envWinId in environments) {
+                otherEnv = environments[envWinId];
+                otherEnv.$parentWinId$ !== $winId$ || otherEnv.$isTopWindow$ || childEnv.push(otherEnv);
+            }
+            return childEnv;
+        };
+        const WorkerWindow = defineConstructorName(class extends WorkerBase {
+            constructor() {
+                super($winId$, $winId$);
+                this.addEventListener = (...args) => {
+                    "load" === args[0] ? env.$runWindowLoadEvent$ && setTimeout((() => args[1]({
+                        type: "load"
+                    }))) : callMethod(this, [ "addEventListener" ], args, 2);
+                };
+                let win = this;
+                let value;
+                let historyState;
+                let hasInitializedMedia = 0;
+                let initWindowMedia = () => {
+                    if (!hasInitializedMedia) {
+                        (() => {
+                            if (!webWorkerCtx.$initWindowMedia$) {
+                                self.$bridgeToMedia$ = [ getter, setter, callMethod, constructGlobal, definePrototypePropertyDescriptor, randomId, WinIdKey, InstanceIdKey, ApplyPathKey ];
+                                webWorkerCtx.$importScripts$(partytownLibUrl("partytown-media.js?v=0.10.2-dev1727590485751"));
+                                webWorkerCtx.$initWindowMedia$ = self.$bridgeFromMedia$;
+                                delete self.$bridgeFromMedia$;
+                            }
+                            return webWorkerCtx.$initWindowMedia$;
+                        })()(WorkerBase, WorkerEventTargetProxy, env, win, windowMediaConstructors);
+                        hasInitializedMedia = 1;
+                    }
+                };
+                let nodeCstrs = {};
+                let $createNode$ = (nodeName, instanceId, namespace, prevInstance) => {
+                    htmlMedia.includes(nodeName) && initWindowMedia();
+                    const NodeCstr = nodeCstrs[nodeName] ? nodeCstrs[nodeName] : nodeName.includes("-") ? nodeCstrs.UNKNOWN : nodeCstrs.I;
+                    cstrInstanceId = instanceId;
+                    cstrNodeName = nodeName;
+                    cstrNamespace = namespace;
+                    cstrPrevInstance = prevInstance;
+                    return new NodeCstr;
+                };
+                win.Window = WorkerWindow;
+                win.name = name + `${normalizedWinId($winId$)} (${$winId$})`;
+                createNodeCstr(win, env, WorkerBase);
+                (win => {
+                    win.NodeList = defineConstructorName(NodeList, "NodeList");
+                })(win);
+                createNamedNodeMapCstr(win, WorkerBase);
+                createCSSStyleDeclarationCstr(win, WorkerBase, "CSSStyleDeclaration");
+                ((win, WorkerBase, cstrName) => {
+                    win[cstrName] = defineConstructorName(class extends WorkerBase {
+                        now() {
+                            return performance.now();
+                        }
+                    }, cstrName);
+                })(win, WorkerBase, "Performance");
+                ((win, nodeCstrs) => {
+                    const registry = new Map;
+                    win.customElements = {
+                        define(tagName, Cstr, opts) {
+                            registry.set(tagName, Cstr);
+                            nodeCstrs[tagName.toUpperCase()] = Cstr;
+                            const ceData = [ Cstr.name, Cstr.observedAttributes ];
+                            callMethod(win, [ "customElements", "define" ], [ tagName, ceData, opts ]);
+                        },
+                        get: tagName => registry.get(tagName) || callMethod(win, [ "customElements", "get" ], [ tagName ]),
+                        whenDefined: tagName => registry.has(tagName) ? Promise.resolve() : callMethod(win, [ "customElements", "whenDefined" ], [ tagName ]),
+                        upgrade: elm => callMethod(win, [ "customElements", "upgrade" ], [ elm ])
+                    };
+                })(win, nodeCstrs);
+                webWorkerCtx.$interfaces$.map((([cstrName, superCstrName, members, interfaceType, nodeName]) => {
+                    const SuperCstr = TrapConstructors[cstrName] ? WorkerTrapProxy : "EventTarget" === superCstrName ? WorkerEventTargetProxy : "Object" === superCstrName ? WorkerBase : win[superCstrName];
+                    const Cstr = win[cstrName] = defineConstructorName(12 === interfaceType ? class extends WorkerBase {
+                        constructor(...args) {
+                            super();
+                            constructGlobal(this, cstrName, args);
+                        }
+                    } : win[cstrName] || class extends SuperCstr {}, cstrName);
+                    nodeName && (nodeCstrs[nodeName] = Cstr);
+                    members.map((([memberName, memberType, staticValue]) => {
+                        memberName in Cstr.prototype || memberName in SuperCstr.prototype || ("string" == typeof memberType ? definePrototypeProperty(Cstr, memberName, {
+                            get() {
+                                if (!hasInstanceStateValue(this, memberName)) {
+                                    const instanceId = this[InstanceIdKey];
+                                    const applyPath = [ ...this[ApplyPathKey], memberName ];
+                                    const PropCstr = win[memberType];
+                                    PropCstr && setInstanceStateValue(this, memberName, new PropCstr($winId$, instanceId, applyPath));
+                                }
+                                return getInstanceStateValue(this, memberName);
+                            },
+                            set(value) {
+                                setInstanceStateValue(this, memberName, value);
+                            }
+                        }) : 5 === memberType ? definePrototypeValue(Cstr, memberName, (function(...args) {
+                            return callMethod(this, [ memberName ], args);
+                        })) : memberType > 0 && (void 0 !== staticValue ? definePrototypeValue(Cstr, memberName, staticValue) : definePrototypeProperty(Cstr, memberName, {
+                            get() {
+                                return getter(this, [ memberName ]);
+                            },
+                            set(value) {
+                                return setter(this, [ memberName ], value);
+                            }
+                        })));
+                    }));
+                }));
+                commaSplit("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((globalName => {
+                    delete WorkerWindow.prototype[globalName];
+                    if (!(globalName in win)) {
+                        value = self[globalName];
+                        null != value && (win[globalName] = "function" != typeof value || value.toString().startsWith("class") ? value : value.bind(self));
+                    }
+                }));
+                Object.getOwnPropertyNames(self).map((globalName => {
+                    globalName in win || (win[globalName] = self[globalName]);
+                }));
+                windowMediaConstructors.map((cstrName => defineProperty(win, cstrName, {
+                    get() {
+                        initWindowMedia();
+                        return win[cstrName];
+                    }
+                })));
+                "trustedTypes" in self && (win.trustedTypes = self.trustedTypes);
+                patchElement(win.Element, win.HTMLElement);
+                patchDocument(win.Document, env, isDocumentImplementation);
+                (WorkerDocumentFragment => {
+                    definePrototypeNodeType(WorkerDocumentFragment, 11);
+                    cachedTreeProps(WorkerDocumentFragment, elementStructurePropNames);
+                })(win.DocumentFragment);
+                patchHTMLAnchorElement(win.HTMLAnchorElement, env);
+                (WorkerHTMLFormElement => {
+                    definePrototypePropertyDescriptor(WorkerHTMLFormElement, {});
+                    cachedProps(WorkerHTMLFormElement, "elements");
+                })(win.HTMLFormElement);
+                patchHTMLIFrameElement(win.HTMLIFrameElement);
+                patchHTMLScriptElement(win.HTMLScriptElement, env);
+                patchSvgElement(win.SVGGraphicsElement);
+                patchDocumentElementChild(win.HTMLHeadElement, env);
+                patchDocumentElementChild(win.HTMLBodyElement, env);
+                ((WorkerHTMLHtmlElement, env) => {
+                    const DocumentElementDescriptorMap = {
+                        parentElement: {
+                            value: null
+                        },
+                        parentNode: {
+                            get: () => env.$document$
+                        }
+                    };
+                    definePrototypePropertyDescriptor(WorkerHTMLHtmlElement, DocumentElementDescriptorMap);
+                })(win.HTMLHtmlElement, env);
+                createCSSStyleSheetConstructor(win, "CSSStyleSheet");
+                definePrototypeNodeType(win.Comment, 8);
+                definePrototypeNodeType(win.DocumentType, 10);
+                Object.assign(env, {
+                    $winId$: $winId$,
+                    $parentWinId$: $parentWinId$,
+                    $window$: new Proxy(win, {
+                        get: (win, propName) => {
+                            var _a;
+                            if ("string" != typeof propName || isNaN(propName)) {
+                                return (null === (_a = webWorkerCtx.$config$.mainWindowAccessors) || void 0 === _a ? void 0 : _a.includes(propName)) ? getter(this, [ propName ]) : win[propName];
+                            }
+                            {
+                                let frame = getChildEnvs()[propName];
+                                return frame ? frame.$window$ : void 0;
+                            }
+                        },
+                        has: () => true
+                    }),
+                    $document$: $createNode$("#document", $winId$ + ".d"),
+                    $documentElement$: $createNode$("HTML", $winId$ + ".e"),
+                    $head$: $createNode$("HEAD", $winId$ + ".h"),
+                    $body$: $createNode$("BODY", $winId$ + ".b"),
+                    $location$: $location$,
+                    $visibilityState$: $visibilityState$,
+                    $isSameOrigin$: $isSameOrigin$,
+                    $isTopWindow$: $isTopWindow$,
+                    $createNode$: $createNode$
+                });
+                win.requestAnimationFrame = cb => setTimeout((() => cb(performance.now())), 9);
+                win.cancelAnimationFrame = id => clearTimeout(id);
+                win.requestIdleCallback = (cb, start) => {
+                    start = Date.now();
+                    return setTimeout((() => cb({
+                        didTimeout: false,
+                        timeRemaining: () => Math.max(0, 50 - (Date.now() - start))
+                    })), 1);
+                };
+                win.cancelIdleCallback = id => clearTimeout(id);
+                addStorageApi(win, "localStorage", env);
+                addStorageApi(win, "sessionStorage", env);
+                $isSameOrigin$ || (win.indexeddb = void 0);
+                if (isIframeWindow) {
+                    historyState = {};
+                    win.history = {
+                        pushState(stateObj) {
+                            historyState = stateObj;
+                        },
+                        replaceState(stateObj) {
+                            historyState = stateObj;
+                        },
+                        get state() {
+                            return historyState;
+                        },
+                        length: 0
+                    };
+                    win.indexeddb = void 0;
+                } else {
+                    const originalPushState = win.history.pushState.bind(win.history);
+                    const originalReplaceState = win.history.replaceState.bind(win.history);
+                    win.history.pushState = (stateObj, _, newUrl) => {
+                        false !== env.$propagateHistoryChange$ && originalPushState(stateObj, _, newUrl);
+                    };
+                    win.history.replaceState = (stateObj, _, newUrl) => {
+                        false !== env.$propagateHistoryChange$ && originalReplaceState(stateObj, _, newUrl);
+                    };
+                }
+                win.Worker = void 0;
+            }
+            get body() {
+                return env.$body$;
+            }
+            get document() {
+                return env.$document$;
+            }
+            get documentElement() {
+                return env.$documentElement$;
+            }
+            fetch(input, init) {
+                input = "string" == typeof input || input instanceof URL ? String(input) : input.url;
+                return fetch(resolveUrl(env, input, "fetch"), init);
+            }
+            get frames() {
+                return env.$window$;
+            }
+            get frameElement() {
+                return $isTopWindow$ ? null : getOrCreateNodeInstance($parentWinId$, $winId$, "IFRAME");
+            }
+            get globalThis() {
+                return env.$window$;
+            }
+            get head() {
+                return env.$head$;
+            }
+            get length() {
+                return getChildEnvs().length;
+            }
+            get location() {
+                return $location$;
+            }
+            set location(loc) {
+                $location$.href = loc + "";
+            }
+            get Image() {
+                return createImageConstructor(env);
+            }
+            get navigator() {
+                return (env => {
+                    const nav = {
+                        sendBeacon: (url, body) => {
+                            if (webWorkerCtx.$config$.logSendBeaconRequests) {
+                                try {
+                                    logWorker(`sendBeacon: ${resolveUrl(env, url, null)}${body ? ", data: " + JSON.stringify(body) : ""}, resolvedParams: ${JSON.stringify(resolveSendBeaconRequestParameters(env, url))}`);
+                                } catch (e) {
+                                    console.error(e);
+                                }
+                            }
+                            try {
+                                fetch(resolveUrl(env, url, null), {
+                                    method: "POST",
+                                    body: body,
+                                    mode: "no-cors",
+                                    keepalive: true,
+                                    ...resolveSendBeaconRequestParameters(env, url)
+                                });
+                                return true;
+                            } catch (e) {
+                                console.error(e);
+                                return false;
+                            }
+                        }
+                    };
+                    for (let key in navigator) {
+                        nav[key] = navigator[key];
+                    }
+                    return new Proxy(nav, {
+                        set(_, propName, propValue) {
+                            navigator[propName] = propValue;
+                            return true;
+                        },
+                        get(target, prop) {
+                            if (Object.prototype.hasOwnProperty.call(target, prop)) {
+                                return target[prop];
+                            }
+                            const value = getter(env.$window$, [ "navigator", prop ]);
+                            return value;
+                        }
+                    });
+                })(env);
+            }
+            get origin() {
+                return $location$.origin;
+            }
+            set origin(_) {}
+            get parent() {
+                for (let envWinId in environments) {
+                    if (environments[envWinId].$winId$ === $parentWinId$) {
+                        return environments[envWinId].$window$;
+                    }
+                }
+                return env.$window$;
+            }
+            postMessage(...args) {
+                if (environments[args[0]]) {
+                    len(postMessages) > 50 && postMessages.splice(0, 5);
+                    postMessages.push({
+                        $winId$: args[0],
+                        $data$: JSON.stringify(args[1])
+                    });
+                    args = args.slice(1);
+                }
+                callMethod(this, [ "postMessage" ], args, 3);
+            }
+            get self() {
+                return env.$window$;
+            }
+            get top() {
+                for (let envWinId in environments) {
+                    if (environments[envWinId].$isTopWindow$) {
+                        return environments[envWinId].$window$;
+                    }
+                }
+                return env.$window$;
+            }
+            get window() {
+                return env.$window$;
+            }
+            get XMLHttpRequest() {
+                const Xhr = XMLHttpRequest;
+                const str = String(Xhr);
+                const ExtendedXhr = defineConstructorName(class extends Xhr {
+                    open(...args) {
+                        args[1] = resolveUrl(env, args[1], "xhr");
+                        super.open(...args);
+                    }
+                    set withCredentials(_) {
+                        webWorkerCtx.$config$.allowXhrCredentials && (super.withCredentials = _);
+                    }
+                    toString() {
+                        return str;
+                    }
+                }, getConstructorName(Xhr));
+                ExtendedXhr.prototype.constructor.toString = () => str;
+                return ExtendedXhr;
+            }
+        }, "Window");
+        const WorkerTrapProxy = class extends WorkerBase {
+            constructor(winId, instanceId, applyPath, nodeName) {
+                super(winId, instanceId, applyPath, nodeName);
+                return new Proxy(this, {
+                    get: (instance, propName) => getter(instance, [ propName ]),
+                    set(instance, propName, propValue) {
+                        setter(instance, [ propName ], propValue);
+                        return true;
+                    }
+                });
+            }
+        };
+        const WorkerEventTargetProxy = class extends WorkerBase {};
+        eventTargetMethods.map((methodName => WorkerEventTargetProxy.prototype[methodName] = function(...args) {
+            return callMethod(this, [ methodName ], args, 2);
+        }));
+        cachedProps(WorkerWindow, "devicePixelRatio");
+        cachedDimensionProps(WorkerWindow);
+        cachedDimensionMethods(WorkerWindow, [ "getComputedStyle" ]);
+        new WorkerWindow;
+        return env;
+    };
+    const TrapConstructors = {
+        DOMStringMap: 1,
+        NamedNodeMap: 1
+    };
+    const createEnvironment = ({$winId$: $winId$, $parentWinId$: $parentWinId$, $url$: $url$, $visibilityState$: $visibilityState$}, isIframeWindow, isDocumentImplementation) => {
+        if (!environments[$winId$]) {
+            environments[$winId$] = createWindow($winId$, $parentWinId$, $url$, $visibilityState$, isIframeWindow, isDocumentImplementation);
+            {
+                const winType = $winId$ === $parentWinId$ ? "top" : "iframe";
+                logWorker(`Created ${winType} window ${normalizedWinId($winId$)} environment`, $winId$);
+            }
+        }
+        webWorkerCtx.$postMessage$([ 7, $winId$ ]);
+        return environments[$winId$];
+    };
+    const queuedEvents = [];
+    const receiveMessageFromSandboxToWorker = ev => {
+        const msg = ev.data;
+        const msgType = msg[0];
+        const msgValue = msg[1];
+        if (webWorkerCtx.$isInitialized$) {
+            if (7 === msgType) {
+                (async initScript => {
+                    let winId = initScript.$winId$;
+                    let instanceId = initScript.$instanceId$;
+                    let instance = getOrCreateNodeInstance(winId, instanceId, "SCRIPT");
+                    let scriptContent = initScript.$content$;
+                    let scriptSrc = initScript.$url$;
+                    let scriptOrgSrc = initScript.$orgUrl$;
+                    let errorMsg = "";
+                    let env = environments[winId];
+                    let rsp;
+                    let javascriptContentTypes = [ "text/jscript", "text/javascript", "text/x-javascript", "application/javascript", "application/x-javascript", "text/ecmascript", "text/x-ecmascript", "application/ecmascript" ];
+                    if (scriptSrc) {
+                        try {
+                            scriptSrc = resolveToUrl(env, scriptSrc, "script") + "";
+                            setInstanceStateValue(instance, 4, scriptSrc);
+                            webWorkerCtx.$config$.logScriptExecution && logWorker(`Execute script src: ${scriptOrgSrc}`, winId);
+                            rsp = await fetch(scriptSrc);
+                            if (rsp.ok) {
+                                let responseContentType = rsp.headers.get("content-type");
+                                let shouldExecute = javascriptContentTypes.some((ct => {
+                                    var _a, _b, _c;
+                                    return null === (_c = null === (_a = null == responseContentType ? void 0 : responseContentType.toLowerCase) || void 0 === _a ? void 0 : (_b = _a.call(responseContentType)).includes) || void 0 === _c ? void 0 : _c.call(_b, ct);
+                                }));
+                                if (shouldExecute) {
+                                    scriptContent = await rsp.text();
+                                    env.$currentScriptId$ = instanceId;
+                                    run(env, scriptContent, scriptOrgSrc || scriptSrc);
+                                }
+                                runStateLoadHandlers(instance, "load");
+                            } else {
+                                errorMsg = rsp.statusText;
+                                runStateLoadHandlers(instance, "error");
+                            }
+                        } catch (urlError) {
+                            console.error(urlError);
+                            errorMsg = String(urlError.stack || urlError);
+                            runStateLoadHandlers(instance, "error");
+                        }
+                    } else {
+                        scriptContent && (errorMsg = runScriptContent(env, instanceId, scriptContent, winId, errorMsg));
+                    }
+                    env.$currentScriptId$ = "";
+                    webWorkerCtx.$postMessage$([ 6, winId, instanceId, errorMsg ]);
+                })(msgValue);
+            } else if (9 === msgType) {
+                (({$winId$: $winId$, $instanceId$: $instanceId$, $refId$: $refId$, $thisArg$: $thisArg$, $args$: $args$}) => {
+                    if (webWorkerRefsByRefId[$refId$]) {
+                        try {
+                            webWorkerRefsByRefId[$refId$].apply(deserializeFromMain($winId$, $instanceId$, [], $thisArg$), deserializeFromMain($winId$, $instanceId$, [], $args$));
+                        } catch (e) {
+                            console.error(e);
+                        }
+                    }
+                })(msgValue);
+            } else if (10 === msgType) {
+                (({$winId$: $winId$, $forward$: $forward$, $args$: $args$}) => {
+                    try {
+                        let target = environments[$winId$].$window$;
+                        let i = 0;
+                        let l = len($forward$);
+                        for (;i < l; i++) {
+                            i + 1 < l ? target = target[$forward$[i]] : target[$forward$[i]].apply(target, deserializeFromMain(null, $winId$, [], $args$));
+                        }
+                    } catch (e) {
+                        console.error(e);
+                    }
+                })(msgValue);
+            } else if (5 === msgType) {
+                createEnvironment(msgValue);
+            } else if (8 === msgType) {
+                if (1 !== environments[msgValue].$isInitialized$) {
+                    const winId = msgValue;
+                    const env = environments[winId];
+                    const winType = env.$winId$ === env.$parentWinId$ ? "top" : "iframe";
+                    logWorker(`Initialized ${winType} window ${normalizedWinId(winId)} environment 🎉`, winId);
+                }
+                environments[msgValue].$isInitialized$ = 1;
+                environments[msgValue].$isLoading$ = 0;
+            } else if (14 === msgType) {
+                environments[msgValue].$visibilityState$ = msg[2];
+            } else if (13 === msgType) {
+                const $winId$ = msgValue.$winId$;
+                const env = environments[$winId$];
+                env.$location$.href = msgValue.url;
+                !function($winId$, env, data) {
+                    const history = env.$window$.history;
+                    switch (data.type) {
+                      case 0:
+                        env.$propagateHistoryChange$ = false;
+                        try {
+                            history.pushState(data.state, "", data.newUrl);
+                        } catch (e) {}
+                        env.$propagateHistoryChange$ = true;
+                        break;
+
+                      case 1:
+                        env.$propagateHistoryChange$ = false;
+                        try {
+                            history.replaceState(data.state, "", data.newUrl);
+                        } catch (e) {}
+                        env.$propagateHistoryChange$ = true;
+                    }
+                }(msgValue.$winId$, env, msgValue);
+            } else {
+                15 === msgType && ((_type, winId, instanceId, callbackName, args) => {
+                    const elm = getOrCreateNodeInstance(winId, instanceId);
+                    elm && "function" == typeof elm[callbackName] && elm[callbackName].apply(elm, args);
+                })(...msg);
+            }
+        } else if (1 === msgType) {
+            (initWebWorkerData => {
+                const config = webWorkerCtx.$config$ = JSON.parse(initWebWorkerData.$config$);
+                const locOrigin = initWebWorkerData.$origin$;
+                webWorkerCtx.$importScripts$ = importScripts.bind(self);
+                webWorkerCtx.$interfaces$ = initWebWorkerData.$interfaces$;
+                webWorkerCtx.$libPath$ = initWebWorkerData.$libPath$;
+                webWorkerCtx.$origin$ = locOrigin;
+                webWorkerCtx.$postMessage$ = postMessage.bind(self);
+                webWorkerCtx.$sharedDataBuffer$ = initWebWorkerData.$sharedDataBuffer$;
+                webWorkerCtx.$tabId$ = initWebWorkerData.$tabId$;
+                self.importScripts = void 0;
+                delete self.postMessage;
+                delete self.WorkerGlobalScope;
+                commaSplit("resolveUrl,resolveSendBeaconRequestParameters,get,set,apply").map((configName => {
+                    config[configName] && (config[configName] = new Function("return " + config[configName])());
+                }));
+            })(msgValue);
+            webWorkerCtx.$postMessage$([ 2 ]);
+        } else if (3 === msgType) {
+            webWorkerCtx.$interfaces$ = [ ...webWorkerCtx.$interfaces$, ...msgValue ];
+            webWorkerCtx.$isInitialized$ = 1;
+            logWorker("Initialized web worker");
+            webWorkerCtx.$postMessage$([ 4 ]);
+            queuedEvents.length && logWorker(`Queued ready messages: ${queuedEvents.length}`);
+            [ ...queuedEvents ].map(receiveMessageFromSandboxToWorker);
+            queuedEvents.length = 0;
+        } else {
+            queuedEvents.push(ev);
+        }
+    };
+    self.onmessage = receiveMessageFromSandboxToWorker;
+    postMessage([ 0 ]);
+})(self);
Index: build/debug/partytown-ww-sw.js
===================================================================
--- build/debug/partytown-ww-sw.js	(revision 3189893)
+++ build/debug/partytown-ww-sw.js	(working copy)
@@ -1 +1,1928 @@
-(e=>{const t=Symbol(),n=Symbol(),r=Symbol(),i=Symbol(),s=Symbol(),o=Symbol(),a=Symbol(),c=Symbol(),l=new Map,$={},u=new WeakMap,d=[],g={},p={},h=new Map,f=new Map,m=e=>e.split(","),y=e=>{if(e=g.$libPath$+e,new URL(e).origin!=location.origin)throw"Invalid "+e;return e},w=m("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft"),v=m("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling"),S=m("insertBefore,remove,removeChild,replaceChild"),b=m("className,width,height,hidden,innerHTML,innerText,textContent,text"),I=m("setAttribute,setAttributeNS,setProperty"),x=m("addEventListener,dispatchEvent,removeEventListener"),T=x.concat(I,m("add,observe,remove,unobserve")),E=/^[A-Z_]([A-Z0-9-]*[A-Z0-9])?$/,N=()=>{},M=e=>e.length,L=e=>{var t,n,r;try{const n=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(n)return n}catch(e){}try{const t=null===(r=null===(n=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===n?void 0:n.constructor)||void 0===r?void 0:r.name;if(t)return t}catch(e){}return""},C=[],O=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),R=(e,t,n)=>Object.defineProperty(e,t,{...n,configurable:!0}),j=(e,t)=>R(e,"name",{value:t}),P=(e,t,n)=>R(e.prototype,t,n),W=(e,t)=>Object.defineProperties(e.prototype,t),k=(e,t,n)=>P(e,t,{value:n,writable:!0});function A(e,t){var n,r;return null!==(r=null===(n=e.loadScriptsOnMainThread)||void 0===n?void 0:n.map((([e,t])=>new RegExp("string"===e?t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"):t))).some((e=>e.test(t))))&&void 0!==r&&r}Object.freeze((e=>{const t=new Set;let n=[];do{Object.getOwnPropertyNames(n).forEach((e=>{"function"==typeof n[e]&&t.add(e)}))}while((n=Object.getPrototypeOf(n))!==Object.prototype);return Array.from(t)})());const H=(e,t)=>t in e[o],D=(e,t)=>e[o][t],_=(e,t,n)=>e[o][t]=n,B=(e,t,n,r,i,s)=>{if(!(i=l.get(t))&&n&&p[e]){const o=l.get(s||"");i=p[e].$createNode$(n,t,r,o),l.set(t,i)}return i},U=(e,t)=>k(e,"nodeType",t),z=(e,t)=>t.map((t=>P(e,t,{get(){let e=F(this,t),n=f.get(e);return n||(n=me(this,[t]),f.set(e,n)),n}}))),F=(e,r,i)=>[e[t],e[n],r,...(i||C).map((e=>String(e&&e[t]?e[n]:e)))].join("."),G=(e,t)=>m(t).map((t=>P(e,t,{get(){return H(this,t)||_(this,t,me(this,[t])),D(this,t)},set(e){D(this,t)!==e&&ye(this,[t],e),_(this,t,e)}}))),q=e=>w.map((t=>P(e,t,{get(){const e=h.get(F(this,t));if("number"==typeof e)return e;const n=me(this,[t],w);return n&&"object"==typeof n?(Object.entries(n).map((([e,t])=>h.set(F(this,e),t))),n[t]):n}}))),J=(e,t)=>t.map((t=>{e.prototype[t]=function(...e){let n=F(this,t,e),r=h.get(n);return r||(r=we(this,[t],e),h.set(n,r)),r}})),X=(e,r,i,s,o)=>{return void 0!==i&&(o=typeof i)?"string"===o||"boolean"===o||"number"===o||null==i?[0,i]:"function"===o?[4,{$winId$:e,$instanceId$:r,$refId$:(a=i,(c=u.get(a))||(u.set(a,c=O()),$[c]=a),c)}]:(s=s||new Set)&&Array.isArray(i)?s.has(i)?[1,[]]:s.add(i)&&[1,i.map((t=>X(e,r,t,s)))]:"object"===o?i[n]?[3,[i[t],i[n]]]:i instanceof Event?[5,Z(e,r,i,!1,s)]:V&&i instanceof TrustedHTML?[0,i.toString()]:i instanceof ArrayBuffer?[8,i]:ArrayBuffer.isView(i)?[9,i.buffer,L(i)]:[2,Z(e,r,i,!0,s)]:void 0:i;var a,c},V="undefined"!=typeof TrustedHTML,Z=(e,t,n,r,i,s,o,a)=>{if(s={},!i.has(n))for(o in i.add(n),n)a=n[o],(r||"function"!=typeof a)&&(s[o]=X(e,t,a,i));return s},Y=(e,r)=>e?X(e[t],e[n],r):[0,r],K=(e,t,n,r,i,s,o,a)=>{if(r){if(i=r[0],s=r[1],0===i||11===i||12===i)return s;if(4===i)return ee(n,s);if(6===i)return e&&n.length>0?(...t)=>we(p[e].$window$,n,t,1):N;if(3===i)return Q(s);if(7===i)return new ne(s.map(Q));if(10===i)return new re(s);if(1===i)return s.map((r=>K(e,t,n,r)));if(14===i)return new te(s);for(a in o={},s)o[a]=K(e,t,[...n,a],s[a]);if(13===i)return new p[e].$window$.CSSStyleDeclaration(e,t,n,o);if(5===i){if("message"===o.type&&o.origin){let e,t=JSON.stringify(o.data),n=d.find((e=>e.$data$===t));n&&(e=p[n.$winId$],e&&(o.source=e.$window$,o.origin=e.$location$.origin))}return new Proxy(new Event(o.type,o),{get:(e,t)=>t in o?o[t]:"function"==typeof e[String(t)]?N:e[String(t)]})}if(2===i)return o}},Q=([e,t,n,r])=>t===e&&p[e]?p[e].$window$:B(e,t,n,void 0,void 0,r),ee=(e,{$winId$:t,$instanceId$:n,$nodeName$:r,$refId$:i})=>($[i]||u.set($[i]=function(...i){const s=B(t,n,r);return we(s,e,i)},i),$[i]);class te extends Error{constructor(e){super(e.message),this.name=e.name,this.message=e.message,this.stack=e.stack}}class ne{constructor(e){(this._=e).map(((e,t)=>this[t]=e))}entries(){return this._.entries()}forEach(e,t){this._.map(e,t)}item(e){return this[e]}keys(){return this._.keys()}get length(){return M(this._)}values(){return this._.values()}[Symbol.iterator](){return this._[Symbol.iterator]()}}const re=class{constructor(e){this.name=e[0],this.value=e[1]}get nodeName(){return this.name}get nodeType(){return 2}},ie=(e,t,n)=>console.warn(`Partytown unable to ${e} cross-origin ${t}: `+n.$location$),se=(t,n)=>{try{if(g.$config$.logStackTraces){const e=(new Error).stack.split("\n"),n=e.findIndex((e=>e.includes("logWorker")));t+="\n"+e.slice(n+1).join("\n")}let r,i;n?(r=`Worker (${ae(n)}) 🎉`,i=ce(n)):(r=e.name,i="#9844bf"),g.lastLog!==t&&(g.lastLog=t,console.debug.apply(console,[`%c${r}`,`background: ${i}; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;`,t]))}catch(e){}},oe=[],ae=e=>(oe.includes(e)||oe.push(e),oe.indexOf(e)+1),ce=e=>{const t=["#00309e","#ea3655","#eea727"];return t[ae(e)-1]||t[t.length-1]},le=(e,t)=>{let n="";if(e){const t=L(e);if("Window"===t)n="";else if("string"==typeof e[r]){let t=e[r];n="#text"===t?"textNode.":"#comment"===t?"commentNode.":"#document"===t?"document.":"html"===t?"doctype.":t.toLowerCase()+"."}else n="nodeType"in e&&2===e.nodeType?"attributes.":"CanvasRenderingContext2D"===t?"context2D.":"CanvasRenderingContextWebGL"===t?"contextWebGL.":"CSSStyleDeclaration"===t?"style.":"MutationObserver"===t?"mutationObserver.":"NamedNodeMap"===t?"namedNodeMap.":"ResizeObserver"===t?"resizeObserver.":t.substring(0,1).toLowerCase()+t.substring(1)+".";e[s]&&e[s].length&&(n+=[...e[s]].join(".")+".")}if(t.length>1){const e=t.slice(0,t.length-1),r=t[t.length-1];if(!isNaN(r))return n+`${e.join(".")}[${r}]`}return n+t.join(".")},$e=(e,t)=>{const i=typeof t;if(void 0===t)return"undefined";if("boolean"===i||"number"===i||null==t)return JSON.stringify(t);if("string"===i)return e.includes("cookie")?JSON.stringify(t.slice(0,10)+"..."):JSON.stringify(t.length>50?t.slice(0,40)+"...":t);if(Array.isArray(t))return`[${t.map($e).join(", ")}]`;if("object"===i){const i=t[n],s=L(t);if("string"==typeof i){if("Window"===s)return"window";if("string"==typeof t[r]){if(1===t.nodeType)return`<${t[r].toLowerCase()}>`;if(10===t.nodeType)return`<!DOCTYPE ${t[r]}>`;if(t.nodeType<=11)return t[r]}return"¯\\_(ツ)_/¯ instance obj"}return t[Symbol.iterator]?`[${Array.from(t).map((t=>$e(e,t))).join(", ")}]`:"value"in t?"string"==typeof t.value?`"${t.value}"`:ue(t.value):ue(t)}return(e=>"object"==typeof e&&e&&e.then)(t)?"Promise":"function"===i?`ƒ() ${t.name||""}`.trim():`¯\\_(ツ)_/¯ ${String(t)}`.trim()},ue=e=>{const t=[];for(let n in e){const r=e[n],i=typeof r;"string"===i?t.push(`${n}: "${r}"`):"function"===i?t.push(`${n}: ƒ`):Array.isArray(i)?t.push(`${n}: [..]`):"object"===i&&r?t.push(`${n}: {..}`):t.push(`${n}: ${String(r)}`)}let n=t.join(", ");return n.length>200&&(n=n.substring(0,200)+".."),`{ ${n} }`},de=(e,n)=>{(g.$config$.logGetters||g.$config$.logSetters)&&se(`Dimension cache cleared from style.${n} setter`,e[t])},ge=(e,n)=>{(g.$config$.logGetters||g.$config$.logCalls)&&se(`Dimension cache cleared from method call ${n}()`,e[t])},pe=[],he=(e,r,i,o,a,c)=>{if(e[s]){if(pe.push({$winId$:e[t],$instanceId$:e[n],$applyPath$:[...e[s],...r],$assignInstanceId$:o,$groupedGetters$:a}),pe[M(pe)-1].$debug$=((e,t,n)=>{let r=le(e,t);return 1===n?r+=" (blocking)":2===n?r+=" (non-blocking)":3===n&&(r+=" (non-blocking, no-side-effect)"),r.trim()})(e,r,i),c&&3!==i&&console.error("buffer must be sent NonBlockingNoSideEffect"),3===i)g.$postMessage$([12,{$msgId$:O(),$tasks$:[...pe]}],c?[c instanceof ArrayBuffer?c:c.buffer]:void 0),pe.length=0;else if(1===i)return fe(!0);g.$asyncMsgTimer$=setTimeout(fe,20)}},fe=e=>{if(clearTimeout(g.$asyncMsgTimer$),M(pe)){g.$config$.logMainAccess&&se(`Main access, tasks sent: ${pe.length}`);const t=pe[M(pe)-1],n={$msgId$:`${O()}.${g.$tabId$}`,$tasks$:[...pe]};if(pe.length=0,e){const e=((e,t)=>{const n=new XMLHttpRequest;return n.open("POST",y("proxytown"),!1),n.send(JSON.stringify(t)),JSON.parse(n.responseText)})(0,n),r=e.$isPromise$,i=K(t.$winId$,t.$instanceId$,t.$applyPath$,e.$rtnValue$);if(e.$error$){if(r)return Promise.reject(e.$error$);throw new Error(e.$error$)}return r?Promise.resolve(i):i}g.$postMessage$([12,n])}},me=(e,n,r,i)=>(g.$config$.get&&(i=g.$config$.get(Se(e,n)))!==a||((e,n,r,i=!1,s=!1)=>{if(g.$config$.logGetters)try{const o=`Get ${le(e,n)}, returned: ${$e(n,r)}${i?" (restricted to worker)":""}${s?" (grouped getter)":""}`;o.includes("Symbol(")||se(o,e[t])}catch(e){}})(e,n,i=he(e,n,1,void 0,r),!1,!!r),i),ye=(e,n,r,i)=>{if(g.$config$.set){if((i=g.$config$.set({value:r,prevent:c,...Se(e,n)}))===c)return;i!==a&&(r=i)}var s,o;b.some((e=>n.includes(e)))&&(h.clear(),s=e,o=n[n.length-1],(g.$config$.logGetters||g.$config$.logSetters)&&se(`Dimension cache cleared from setter "${o}"`,s[t])),((e,n,r,i=!1)=>{if(g.$config$.logSetters)try{n=n.slice(0,n.length-2),se(`Set ${le(e,n)}, value: ${$e(n,r)}${i?" (restricted to worker)":""}`,e[t])}catch(e){}})(e,n=[...n,Y(e,r),0],r),he(e,n,2)},we=(e,n,r,i,s,o,c,l)=>(g.$config$.apply&&(c=g.$config$.apply({args:r,...Se(e,n)}))!==a||(l=n[M(n)-1],n=[...n,Y(e,r)],i=i||(T.includes(l)?2:1),"setAttribute"===l&&H(e,r[0])?_(e,r[0],r[1]):S.includes(l)?(h.clear(),f.clear(),((e,n)=>{(g.$config$.logGetters||g.$config$.logCalls)&&se(`Dimension and DOM structure cache cleared from method call ${n}()`,e[t])})(e,l)):I.includes(l)&&(i=2,h.clear(),ge(e,l)),((e,n,r,i)=>{if(g.$config$.logCalls)try{n=n.slice(0,n.length-1),se(`Call ${le(e,n)}(${r.map((e=>$e(n,e))).join(", ")}), returned: ${$e(n,i)}`,e[t])}catch(e){}})(e,n,r,c=he(e,n,i,s,void 0,o))),c),ve=(e,n,r)=>{((e,n,r)=>{if(g.$config$.logCalls)try{se(`Construct new ${n}(${r.map((e=>$e([],e))).join(", ")})`,e[t])}catch(e){}})(e,n,r),he(e,[1,n,Y(e,r)],1)},Se=(e,n)=>({name:n.join("."),continue:a,nodeName:e[r],constructor:L(e),instance:e,window:p[e[t]].$window$}),be=(e,t,n)=>{let r={getItem(r){if(n.$isSameOrigin$)return we(e,[t,"getItem"],[r],1);ie("get",t,n)},setItem(r,i){n.$isSameOrigin$?we(e,[t,"setItem"],[r,i],1):ie("set",t,n)},removeItem(r){n.$isSameOrigin$?we(e,[t,"removeItem"],[r],1):ie("remove",t,n)},key(r){if(n.$isSameOrigin$)return we(e,[t,"key"],[r],1);ie("key",t,n)},clear(){n.$isSameOrigin$?we(e,[t,"clear"],C,1):ie("clear",t,n)},get length(){if(n.$isSameOrigin$)return me(e,[t,"length"]);ie("length",t,n)}};e[t]=new Proxy(r,{get:(e,t)=>Reflect.has(e,t)?Reflect.get(e,t):e.getItem(t),set:(e,t,n)=>(e.setItem(t,n),!0),has:(e,t)=>!!Reflect.has(e,t)||"string"==typeof t&&null!==e.getItem(t),deleteProperty:(e,t)=>(e.removeItem(t),!0)})},Ie=(e,t,n)=>{e[n]=j(class extends t{constructor(e,t,n,i){return super(e,t,n,i||{}),new Proxy(this,{get:(e,t)=>e[t]?e[t]:(e[t]||"string"!=typeof t||e[r][t]||(e[r][t]=me(e,[t])),e[r][t]),set:(e,t,n)=>(e[r][t]=n,ye(e,[t],n),de(e,t),h.clear(),!0)})}setProperty(...e){this[r][e[0]]=e[1],we(this,["setProperty"],e,2),de(this,e[0]),h.clear()}getPropertyValue(e){return this[e]}removeProperty(e){let t=this[r][e];return we(this,["removeProperty"],[e],2),de(this,e),h.clear(),this[r][e]=void 0,t}},n)},xe=(e,t)=>{e[t]=j(class{constructor(e){this.ownerNode=e}get cssRules(){const e=this.ownerNode;return new Proxy({},{get(t,n){const r=String(n);return"item"===r?t=>Ee(e,t):"length"===r?Te(e).length:isNaN(r)?t[n]:Ee(e,r)}})}insertRule(e,t){const n=Te(this.ownerNode);return(t=void 0===t?0:t)>=0&&t<=n.length&&(we(this.ownerNode,["sheet","insertRule"],[e,t],2),n.splice(t,0,0)),ge(this.ownerNode,"insertRule"),h.clear(),t}deleteRule(e){we(this.ownerNode,["sheet","deleteRule"],[e],2),Te(this.ownerNode).splice(e,1),ge(this.ownerNode,"deleteRule"),h.clear()}get type(){return"text/css"}},t);const n={sheet:{get(){return new e[t](this)}}};W(e.HTMLStyleElement,n)},Te=(e,t)=>((t=D(e,2))||(t=me(e,["sheet","cssRules"]),_(e,2,t)),t),Ee=(e,t,n)=>(0===(n=Te(e))[t]&&(n[t]=me(e,["sheet","cssRules",parseInt(t,10)])),n[t]),Ne=(e,t,n,r,i)=>{try{g.$config$.logScriptExecution&&se(`Execute script: ${n.substring(0,100).split("\n").map((e=>e.trim())).join(" ").trim().substring(0,60)}...`,r),e.$currentScriptId$=t,Me(e,n)}catch(e){console.error(n,e),i=String(e.stack||e)}return e.$currentScriptId$="",i},Me=(e,t,n)=>{e.$runWindowLoadEvent$=1;let r=((e,t)=>e.replace(/([a-zA-Z0-9_$\.\'\"\`])?(\.\.\.)?this(?![a-zA-Z0-9_$:])/g,((e,t,n)=>{const r=(t||"")+(n||"");return null!=t?r+"this":r+"(thi$(this)?window:this)"})))(t);t=`with(this){${r.replace(/\/\/# so/g,"//Xso")}\n;function thi$(t){return t===this}};${(g.$config$.globalFns||[]).filter((e=>/[a-zA-Z_$][0-9a-zA-Z_$]*/.test(e))).map((e=>`(typeof ${e}=='function'&&(this.${e}=${e}))`)).join(";")};`+(n?"\n//# sourceURL="+n:""),e.$isSameOrigin$||(t=t.replace(/.postMessage\(/g,`.postMessage('${e.$winId$}',`)),new Function(t).call(e.$window$),e.$runWindowLoadEvent$=0},Le=(e,t,n)=>{(n=D(e,t))&&setTimeout((()=>n.map((e=>e({type:t})))))},Ce=(e,t)=>{for(t=e.$location$;!t.host&&(t=(e=p[e.$parentWinId$]).$location$,e.$winId$!==e.$parentWinId$););return t},Oe=(e,t,n,r,i,s)=>(r=Ce(e,r),i=new URL(t||"",r),n&&g.$config$.resolveUrl&&(s=g.$config$.resolveUrl(i,r,n))?s:i),Re=(e,t,n)=>Oe(e,t,n)+"",je=(e,t)=>{const n=Ce(e),r=new URL(t||"",n);if(g.$config$.resolveSendBeaconRequestParameters){const e=g.$config$.resolveSendBeaconRequestParameters(r,n);if(e)return e}return{}},Pe=()=>`<script src="${y("partytown.js?v=0.10.2-dev1727590485751")}"><\/script>`,We=e=>class{constructor(){this.s="",this.l=[],this.e=[],this.style={}}get src(){return this.s}set src(t){g.$config$.logImageRequests&&se(`Image() request: ${Re(e,t,"image")}`,e.$winId$),this.s=t,fetch(Re(e,t,"image"),{mode:"no-cors",credentials:"include",keepalive:!0}).then((e=>{e.ok||0===e.status?this.l.map((e=>e({type:"load"}))):this.e.map((e=>e({type:"error"})))}),(()=>this.e.forEach((e=>e({type:"error"})))))}addEventListener(e,t){"load"===e&&this.l.push(t),"error"===e&&this.e.push(t)}removeEventListener(e,t){"load"===e&&(this.l=this.l.filter((e=>e!==t))),"error"===e&&(this.e=this.e.filter((e=>e!==t)))}get onload(){return this.l[0]}set onload(e){this.l=[e]}get onerror(){return this.e[0]}set onerror(e){this.e=[e]}},ke={addEventListener:{value(...e){const t=e[0],n=D(this,t)||[];n.push(e[1]),_(this,t,n)}},async:{get:N,set:N},defer:{get:N,set:N},onload:{get(){let e=D(this,"load");return e&&e[0]||null},set(e){_(this,"load",e?[e]:null)}},onerror:{get(){let e=D(this,"error");return e&&e[0]||null},set(e){_(this,"error",e?[e]:null)}},getAttribute:{value(e){return"src"===e?this.src:we(this,["getAttribute"],[e])}},setAttribute:{value(e,t){Ae.includes(e)?this[e]=t:we(this,["setAttribute"],[e,t])}}},Ae=m("src,type"),He=(e,t)=>{const n={innerHTML:De,innerText:De,src:{get(){return D(this,4)||""},set(e){const n=Re(t,e,null),r=g.$config$;e=Re(t,e,"script"),_(this,4,e),ye(this,["src"],e),n!==e&&ye(this,["dataset","ptsrc"],n),this.type&&A(r,e)&&ye(this,["type"],"text/javascript")}},text:De,textContent:De,type:{get(){return me(this,["type"])},set(e){_e(e)||(_(this,5,e),ye(this,["type"],e))}},...ke};W(e,n)},De={get(){const e=me(this,["type"]);if(_e(e)){const e=D(this,3);if(e)return e}return me(this,["innerHTML"])||""},set(e){_(this,3,e)}},_e=e=>!e||"text/javascript"===e,Be=(e,i,s)=>{const o=g.$config$,a=j(class extends s{appendChild(e){return this.insertBefore(e,null)}get href(){}set href(e){}insertBefore(e,s){const a=e[t]=this[t],c=e[n],l=e[r],$="SCRIPT"===l,u="IFRAME"===l;if($){const t=D(e,3),n=D(e,5);if(t){if(_e(n)){const n=e.id;if(n&&A(o,n))ye(e,["type"],"text/javascript");else{const n=Ne(i,c,t,a,""),r=n?"pterror":"ptid",s=n||c;ye(e,["type"],"text/partytown-x"),ye(e,["dataset",r],s)}}ye(e,["innerHTML"],t)}}if(we(this,["insertBefore"],[e,s],2),u){const t=D(e,0);if(t&&t.startsWith("javascript:")){const e=t.split("javascript:")[1];Ne(i,c,e,a,"")}((e,t)=>{let n,r,i=0,s=()=>{p[e]&&p[e].$isInitialized$&&!p[e].$isLoading$?(n=D(t,1)?"error":"load",r=D(t,n),r&&r.map((e=>e({type:n})))):i++>2e3?(r=D(t,"error"),r&&r.map((e=>e({type:"error"})))):setTimeout(s,9)};s()})(c,e)}return $&&(fe(!0),g.$postMessage$([7,a])),e}get nodeName(){return"#s"===this[r]?"#document-fragment":this[r]}get nodeType(){return 3}get ownerDocument(){return i.$document$}},"Node");z(a,m("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling")),e.Node=a},Ue=m("AUDIO,CANVAS,VIDEO"),ze=m("Audio,MediaSource"),Fe=(e,n,r)=>{W(e,{body:{get:()=>n.$body$},cookie:{get(){return n.$isSameOrigin$?me(this,["cookie"]):(ie("get","cookie",n),"")},set(e){n.$isSameOrigin$?ye(this,["cookie"],e):ie("set","cookie",n)}},createElement:{value(e){if(e=e.toUpperCase(),!E.test(e))throw e+" not valid";const n="IFRAME"===e,r=this[t],i=(n?"f_":"")+O();we(this,["createElement"],[e],2,i);const s=B(r,i,e);if(n)st({$winId$:i,$parentWinId$:r,$url$:"about:blank"},!0).$window$.fetch=fetch,ye(s,["srcdoc"],Pe());else if("SCRIPT"===e){const e=D(s,5);_e(e)&&ye(s,["type"],"text/partytown")}return s}},createElementNS:{value(e,n){const r=O(),i=B(this[t],r,n,e);return we(this,["createElementNS"],[e,n],2,r),i}},createTextNode:{value(e){const n=this[t],r=O(),i=B(n,r,"#text");return we(this,["createTextNode"],[e],2,r),i}},createEvent:{value:e=>new Event(e)},currentScript:{get(){return n.$currentScriptId$?B(this[t],n.$currentScriptId$,"SCRIPT"):null}},defaultView:{get:()=>r?null:n.$window$},documentElement:{get:()=>n.$documentElement$},getElementsByTagName:{value(e){return"BODY"===(e=e.toUpperCase())?[n.$body$]:"HEAD"===e?[n.$head$]:we(this,["getElementsByTagName"],[e])}},head:{get:()=>n.$head$},images:{get(){return me(this,["images"])}},scripts:{get(){return me(this,["scripts"])}},implementation:{get(){return{hasFeature:()=>!0,createHTMLDocument:e=>{const t=O();return we(this,["implementation","createHTMLDocument"],[e],1,{$winId$:t}),st({$winId$:t,$parentWinId$:t,$url$:n.$location$+"",$visibilityState$:"hidden"},!0,!0).$document$}}}},location:{get:()=>n.$location$,set(e){n.$location$.href=e+""}},nodeType:{value:9},parentNode:{value:null},parentElement:{value:null},readyState:{value:"complete"},visibilityState:{get:()=>n.$visibilityState$||"visible"}}),G(e,"compatMode,referrer,forms")},Ge=(e,t)=>{W(e,{parentElement:{get(){return this.parentNode}},parentNode:{get:()=>t.$documentElement$}})},qe=(e,t)=>{W(e,{localName:{get(){return this[r].toLowerCase()}},namespaceURI:{get(){return this[i]||"http://www.w3.org/1999/xhtml"}},nodeType:{value:1},tagName:{get(){return this[r]}}}),z(e,v),G(e,"id"),q(t),J(t,m("getClientRects,getBoundingClientRect"))},Je=(e,t)=>{const n={};m("hash,host,hostname,href,origin,pathname,port,protocol,search").map((e=>{n[e]={get(){let n,r=D(this,4);if("string"!=typeof r){if(n=me(this,["href"]),""===n)return"protocol"===e?":":"";_(this,4,n),r=new URL(n)[e]}return Oe(t,r,null)[e]},set(n){let r;if("href"===e)if((e=>{try{return new URL(e),!0}catch(e){return!1}})(n))r=new URL(n);else{const e=t.$location$.href;r=Oe(t,e,null),r.href=new URL(n+"",r.href)}else r=Oe(t,this.href,null),r[e]=n;_(this,4,r.href),ye(this,["href"],r.href)}}})),W(e,n)},Xe=(e,t)=>{const n={contentDocument:{get(){return Ke(this).$document$}},contentWindow:{get(){return Ke(this).$window$}},src:{get(){let e=D(this,0);return e&&e.startsWith("javascript:")?e:(e=Ke(this).$location$.href,e.startsWith("about:")?"":e)},set(e){if(e)if(e.startsWith("javascript:"))_(this,0,e);else if(!e.startsWith("about:")){let t,n=new XMLHttpRequest,r=Ke(this);r.$location$.href=e=Re(r,e,"iframe"),r.$isLoading$=1,r.$isSameOrigin$=g.$origin$===r.$location$.origin,_(this,1,void 0),n.open("GET",e,!1),n.send(),t=n.status,t>199&&t<300?(ye(this,["srcdoc"],`<base href="${e}">`+n.responseText.replace(Ze,((e,t)=>{const n=[];let r,i=!1;for(;r=Ye.exec(t);){let[e]=r;e.startsWith("type=")&&(i=!0,e=e.replace(/(application|text)\/javascript/,"text/partytown")),n.push(e)}return i||n.push('type="text/partytown"'),`<script ${n.join(" ")}>`}))+Pe()),fe(!0),g.$postMessage$([7,r.$winId$])):(_(this,1,t),r.$isLoading$=0)}}},...ke};W(e,n)},Ve="((?:\\w|-)+(?:=(?:(?:\\w|-)+|'[^']*'|\"[^\"]*\")?)?)",Ze=new RegExp(`<script\\s*((${Ve}\\s*)*)>`,"mg"),Ye=new RegExp(Ve,"mg"),Ke=e=>{const r=e[n];return p[r]||st({$winId$:r,$parentWinId$:e[t],$url$:me(e,["src"])||"about:blank"},!0),p[r]},Qe=e=>{const t=(e,t)=>{const{a:n,b:r,c:i,d:s,e:o,f:a}=we(e,[t],C);return new DOMMatrixReadOnly([n,r,i,s,o,a])},n={...e,getCTM:{value:function(){return t(this,"getCTM")}},getScreenCTM:{value:function(){return t(this,"getScreenCTM")}}};W(e,n)},et=(e,t)=>{e.NamedNodeMap=j(class extends t{constructor(e,t,n){return super(e,t,n),new Proxy(this,{get(e,t){const n=nt[t];return n?n.bind(e,[t]):me(e,[t])},set(e,t,n){if(nt[t])throw new Error("Can't set read-only property: "+String(t));return ye(e,[t],n),!0}})}},"NamedNodeMap")};function tt(e,...t){return we(this,e,t,1)}const nt={getNamedItem:tt,getNamedItemNS:tt,item:tt,removeNamedItem:tt,removeNamedItemNS:tt,setNamedItem:tt,setNamedItemNS:tt},rt=(a,c,l,$,u,h)=>{let f,w,S,b;const I=class{constructor(e,c,l,$,u){this[t]=e||a,this[n]=c||f||O(),this[s]=l||[],this[r]=$||w,this[i]=u||S,this[o]=b&&b[o]||{},f=w=S=void 0}},T=new(j(class extends URL{assign(){se("location.assign(), noop")}reload(){se("location.reload(), noop")}replace(){se("location.replace(), noop")}},"Location"))(l),E=T.origin===g.$origin$||"about:blank"===T.origin,N=c===a,C={},A=()=>{let e,t,n=[];for(e in p)t=p[e],t.$parentWinId$!==a||t.$isTopWindow$||n.push(t);return n},F=j(class extends I{constructor(){super(a,a),this.addEventListener=(...e)=>{"load"===e[0]?C.$runWindowLoadEvent$&&setTimeout((()=>e[1]({type:"load"}))):we(this,["addEventListener"],e,2)};let r,i,o=this,l=0,d=()=>{l||((g.$initWindowMedia$||(e.$bridgeToMedia$=[me,ye,we,ve,W,O,t,n,s],g.$importScripts$(y("partytown-media.js?v=0.10.2-dev1727590485751")),g.$initWindowMedia$=e.$bridgeFromMedia$,delete e.$bridgeFromMedia$),g.$initWindowMedia$)(I,V,C,o,ze),l=1)},p={},x=(e,t,n,r)=>{Ue.includes(e)&&d();const i=p[e]?p[e]:e.includes("-")?p.UNKNOWN:p.I;return f=t,w=e,S=n,b=r,new i};var M,L;if(o.Window=F,o.name=name+`${ae(a)} (${a})`,Be(o,C,I),(e=>{e.NodeList=j(ne,"NodeList")})(o),et(o,I),Ie(o,I,"CSSStyleDeclaration"),((e,t,n)=>{e[n]=j(class extends t{now(){return performance.now()}},n)})(o,I,"Performance"),((e,t)=>{const n=new Map;e.customElements={define(r,i,s){n.set(r,i),t[r.toUpperCase()]=i;const o=[i.name,i.observedAttributes];we(e,["customElements","define"],[r,o,s])},get:t=>n.get(t)||we(e,["customElements","get"],[t]),whenDefined:t=>n.has(t)?Promise.resolve():we(e,["customElements","whenDefined"],[t]),upgrade:t=>we(e,["customElements","upgrade"],[t])}})(o,p),g.$interfaces$.map((([e,t,r,i,c])=>{const l=it[e]?X:"EventTarget"===t?V:"Object"===t?I:o[t],$=o[e]=j(12===i?class extends I{constructor(...t){super(),ve(this,e,t)}}:o[e]||class extends l{},e);c&&(p[c]=$),r.map((([e,t,r])=>{e in $.prototype||e in l.prototype||("string"==typeof t?P($,e,{get(){if(!H(this,e)){const r=this[n],i=[...this[s],e],c=o[t];c&&_(this,e,new c(a,r,i))}return D(this,e)},set(t){_(this,e,t)}}):5===t?k($,e,(function(...t){return we(this,[e],t)})):t>0&&(void 0!==r?k($,e,r):P($,e,{get(){return me(this,[e])},set(t){return ye(this,[e],t)}})))}))})),m("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((t=>{delete F.prototype[t],t in o||(r=e[t],null!=r&&(o[t]="function"!=typeof r||r.toString().startsWith("class")?r:r.bind(e)))})),Object.getOwnPropertyNames(e).map((t=>{t in o||(o[t]=e[t])})),ze.map((e=>R(o,e,{get:()=>(d(),o[e])}))),"trustedTypes"in e&&(o.trustedTypes=e.trustedTypes),qe(o.Element,o.HTMLElement),Fe(o.Document,C,h),M=o.DocumentFragment,U(M,11),z(M,v),Je(o.HTMLAnchorElement,C),L=o.HTMLFormElement,W(L,{}),G(L,"elements"),Xe(o.HTMLIFrameElement),He(o.HTMLScriptElement,C),Qe(o.SVGGraphicsElement),Ge(o.HTMLHeadElement,C),Ge(o.HTMLBodyElement,C),((e,t)=>{W(e,{parentElement:{value:null},parentNode:{get:()=>t.$document$}})})(o.HTMLHtmlElement,C),xe(o,"CSSStyleSheet"),U(o.Comment,8),U(o.DocumentType,10),Object.assign(C,{$winId$:a,$parentWinId$:c,$window$:new Proxy(o,{get:(e,t)=>{var n;if("string"!=typeof t||isNaN(t))return(null===(n=g.$config$.mainWindowAccessors)||void 0===n?void 0:n.includes(t))?me(this,[t]):e[t];{let e=A()[t];return e?e.$window$:void 0}},has:()=>!0}),$document$:x("#document",a+".d"),$documentElement$:x("HTML",a+".e"),$head$:x("HEAD",a+".h"),$body$:x("BODY",a+".b"),$location$:T,$visibilityState$:$,$isSameOrigin$:E,$isTopWindow$:N,$createNode$:x}),o.requestAnimationFrame=e=>setTimeout((()=>e(performance.now())),9),o.cancelAnimationFrame=e=>clearTimeout(e),o.requestIdleCallback=(e,t)=>(t=Date.now(),setTimeout((()=>e({didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-t))})),1)),o.cancelIdleCallback=e=>clearTimeout(e),be(o,"localStorage",C),be(o,"sessionStorage",C),E||(o.indexeddb=void 0),u)i={},o.history={pushState(e){i=e},replaceState(e){i=e},get state(){return i},length:0},o.indexeddb=void 0;else{const e=o.history.pushState.bind(o.history),t=o.history.replaceState.bind(o.history);o.history.pushState=(t,n,r)=>{!1!==C.$propagateHistoryChange$&&e(t,n,r)},o.history.replaceState=(e,n,r)=>{!1!==C.$propagateHistoryChange$&&t(e,n,r)}}o.Worker=void 0}get body(){return C.$body$}get document(){return C.$document$}get documentElement(){return C.$documentElement$}fetch(e,t){return e="string"==typeof e||e instanceof URL?String(e):e.url,fetch(Re(C,e,"fetch"),t)}get frames(){return C.$window$}get frameElement(){return N?null:B(c,a,"IFRAME")}get globalThis(){return C.$window$}get head(){return C.$head$}get length(){return A().length}get location(){return T}set location(e){T.href=e+""}get Image(){return We(C)}get navigator(){return(e=>{const t={sendBeacon:(t,n)=>{if(g.$config$.logSendBeaconRequests)try{se(`sendBeacon: ${Re(e,t,null)}${n?", data: "+JSON.stringify(n):""}, resolvedParams: ${JSON.stringify(je(e,t))}`)}catch(e){console.error(e)}try{return fetch(Re(e,t,null),{method:"POST",body:n,mode:"no-cors",keepalive:!0,...je(e,t)}),!0}catch(e){return console.error(e),!1}}};for(let e in navigator)t[e]=navigator[e];return new Proxy(t,{set:(e,t,n)=>(navigator[t]=n,!0),get:(t,n)=>Object.prototype.hasOwnProperty.call(t,n)?t[n]:me(e.$window$,["navigator",n])})})(C)}get origin(){return T.origin}set origin(e){}get parent(){for(let e in p)if(p[e].$winId$===c)return p[e].$window$;return C.$window$}postMessage(...e){p[e[0]]&&(M(d)>50&&d.splice(0,5),d.push({$winId$:e[0],$data$:JSON.stringify(e[1])}),e=e.slice(1)),we(this,["postMessage"],e,3)}get self(){return C.$window$}get top(){for(let e in p)if(p[e].$isTopWindow$)return p[e].$window$;return C.$window$}get window(){return C.$window$}get XMLHttpRequest(){const e=XMLHttpRequest,t=String(e),n=j(class extends e{open(...e){e[1]=Re(C,e[1],"xhr"),super.open(...e)}set withCredentials(e){g.$config$.allowXhrCredentials&&(super.withCredentials=e)}toString(){return t}},L(e));return n.prototype.constructor.toString=()=>t,n}},"Window"),X=class extends I{constructor(e,t,n,r){return super(e,t,n,r),new Proxy(this,{get:(e,t)=>me(e,[t]),set:(e,t,n)=>(ye(e,[t],n),!0)})}},V=class extends I{};return x.map((e=>V.prototype[e]=function(...t){return we(this,[e],t,2)})),G(F,"devicePixelRatio"),q(F),J(F,["getComputedStyle"]),new F,C},it={DOMStringMap:1,NamedNodeMap:1},st=({$winId$:e,$parentWinId$:t,$url$:n,$visibilityState$:r},i,s)=>(p[e]||(p[e]=rt(e,t,n,r,i,s),se(`Created ${e===t?"top":"iframe"} window ${ae(e)} environment`,e)),g.$postMessage$([7,e]),p[e]),ot=[],at=t=>{const n=t.data,r=n[0],i=n[1];if(g.$isInitialized$)if(7===r)(async e=>{let t,n=e.$winId$,r=e.$instanceId$,i=B(n,r,"SCRIPT"),s=e.$content$,o=e.$url$,a=e.$orgUrl$,c="",l=p[n],$=["text/jscript","text/javascript","text/x-javascript","application/javascript","application/x-javascript","text/ecmascript","text/x-ecmascript","application/ecmascript"];if(o)try{if(o=Oe(l,o,"script")+"",_(i,4,o),g.$config$.logScriptExecution&&se(`Execute script src: ${a}`,n),t=await fetch(o),t.ok){let e=t.headers.get("content-type");$.some((t=>{var n,r,i;return null===(i=null===(n=null==e?void 0:e.toLowerCase)||void 0===n?void 0:(r=n.call(e)).includes)||void 0===i?void 0:i.call(r,t)}))&&(s=await t.text(),l.$currentScriptId$=r,Me(l,s,a||o)),Le(i,"load")}else c=t.statusText,Le(i,"error")}catch(e){console.error(e),c=String(e.stack||e),Le(i,"error")}else s&&(c=Ne(l,r,s,n,c));l.$currentScriptId$="",g.$postMessage$([6,n,r,c])})(i);else if(9===r)(({$winId$:e,$instanceId$:t,$refId$:n,$thisArg$:r,$args$:i})=>{if($[n])try{$[n].apply(K(e,t,[],r),K(e,t,[],i))}catch(e){console.error(e)}})(i);else if(10===r)(({$winId$:e,$forward$:t,$args$:n})=>{try{let r=p[e].$window$,i=0,s=M(t);for(;i<s;i++)i+1<s?r=r[t[i]]:r[t[i]].apply(r,K(null,e,[],n))}catch(e){console.error(e)}})(i);else if(5===r)st(i);else if(8===r){if(1!==p[i].$isInitialized$){const e=i,t=p[e],n=t.$winId$===t.$parentWinId$?"top":"iframe";se(`Initialized ${n} window ${ae(e)} environment 🎉`,e)}p[i].$isInitialized$=1,p[i].$isLoading$=0}else if(14===r)p[i].$visibilityState$=n[2];else if(13===r){const e=i.$winId$,t=p[e];t.$location$.href=i.url,function(e,t,n){const r=t.$window$.history;switch(n.type){case 0:t.$propagateHistoryChange$=!1;try{r.pushState(n.state,"",n.newUrl)}catch(e){}t.$propagateHistoryChange$=!0;break;case 1:t.$propagateHistoryChange$=!1;try{r.replaceState(n.state,"",n.newUrl)}catch(e){}t.$propagateHistoryChange$=!0}}(i.$winId$,t,i)}else 15===r&&((e,t,n,r,i)=>{const s=B(t,n);s&&"function"==typeof s[r]&&s[r].apply(s,i)})(...n);else 1===r?((t=>{const n=g.$config$=JSON.parse(t.$config$),r=t.$origin$;g.$importScripts$=importScripts.bind(e),g.$interfaces$=t.$interfaces$,g.$libPath$=t.$libPath$,g.$origin$=r,g.$postMessage$=postMessage.bind(e),g.$sharedDataBuffer$=t.$sharedDataBuffer$,g.$tabId$=t.$tabId$,e.importScripts=void 0,delete e.postMessage,delete e.WorkerGlobalScope,m("resolveUrl,resolveSendBeaconRequestParameters,get,set,apply").map((e=>{n[e]&&(n[e]=new Function("return "+n[e])())}))})(i),g.$postMessage$([2])):3===r?(g.$interfaces$=[...g.$interfaces$,...i],g.$isInitialized$=1,se("Initialized web worker"),g.$postMessage$([4]),ot.length&&se(`Queued ready messages: ${ot.length}`),[...ot].map(at),ot.length=0):ot.push(t)};e.onmessage=at,postMessage([0])})(self);
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+(self => {
+    const WinIdKey = Symbol();
+    const InstanceIdKey = Symbol();
+    const InstanceDataKey = Symbol();
+    const NamespaceKey = Symbol();
+    const ApplyPathKey = Symbol();
+    const InstanceStateKey = Symbol();
+    const HookContinue = Symbol();
+    const HookPrevent = Symbol();
+    const webWorkerInstances = new Map;
+    const webWorkerRefsByRefId = {};
+    const webWorkerRefIdsByRef = new WeakMap;
+    const postMessages = [];
+    const webWorkerCtx = {};
+    const environments = {};
+    const cachedDimensions = new Map;
+    const cachedStructure = new Map;
+    const commaSplit = str => str.split(",");
+    const partytownLibUrl = url => {
+        url = webWorkerCtx.$libPath$ + url;
+        if (new URL(url).origin != location.origin) {
+            throw "Invalid " + url;
+        }
+        return url;
+    };
+    const getterDimensionPropNames = commaSplit("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft");
+    const elementStructurePropNames = commaSplit("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling");
+    const structureChangingMethodNames = commaSplit("insertBefore,remove,removeChild,replaceChild");
+    const dimensionChangingSetterNames = commaSplit("className,width,height,hidden,innerHTML,innerText,textContent,text");
+    const dimensionChangingMethodNames = commaSplit("setAttribute,setAttributeNS,setProperty");
+    const eventTargetMethods = commaSplit("addEventListener,dispatchEvent,removeEventListener");
+    const nonBlockingMethods = eventTargetMethods.concat(dimensionChangingMethodNames, commaSplit("add,observe,remove,unobserve"));
+    const IS_TAG_REG = /^[A-Z_]([A-Z0-9-]*[A-Z0-9])?$/;
+    const noop = () => {};
+    const len = obj => obj.length;
+    const getConstructorName = obj => {
+        var _a, _b, _c;
+        try {
+            const constructorName = null === (_a = null == obj ? void 0 : obj.constructor) || void 0 === _a ? void 0 : _a.name;
+            if (constructorName) {
+                return constructorName;
+            }
+        } catch (e) {}
+        try {
+            const zoneJsConstructorName = null === (_c = null === (_b = null == obj ? void 0 : obj.__zone_symbol__originalInstance) || void 0 === _b ? void 0 : _b.constructor) || void 0 === _c ? void 0 : _c.name;
+            if (zoneJsConstructorName) {
+                return zoneJsConstructorName;
+            }
+        } catch (e) {}
+        return "";
+    };
+    const EMPTY_ARRAY = [];
+    const randomId = () => Math.round(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);
+    const SCRIPT_TYPE = "text/partytown";
+    const defineProperty = (obj, memberName, descriptor) => Object.defineProperty(obj, memberName, {
+        ...descriptor,
+        configurable: true
+    });
+    const defineConstructorName = (Cstr, value) => defineProperty(Cstr, "name", {
+        value: value
+    });
+    const definePrototypeProperty = (Cstr, memberName, descriptor) => defineProperty(Cstr.prototype, memberName, descriptor);
+    const definePrototypePropertyDescriptor = (Cstr, propertyDescriptorMap) => Object.defineProperties(Cstr.prototype, propertyDescriptorMap);
+    const definePrototypeValue = (Cstr, memberName, value) => definePrototypeProperty(Cstr, memberName, {
+        value: value,
+        writable: true
+    });
+    Object.freeze((obj => {
+        const properties = new Set;
+        let currentObj = obj;
+        do {
+            Object.getOwnPropertyNames(currentObj).forEach((item => {
+                "function" == typeof currentObj[item] && properties.add(item);
+            }));
+        } while ((currentObj = Object.getPrototypeOf(currentObj)) !== Object.prototype);
+        return Array.from(properties);
+    })([]));
+    function testIfMustLoadScriptOnMainThread(config, value) {
+        var _a, _b;
+        return null !== (_b = null === (_a = config.loadScriptsOnMainThread) || void 0 === _a ? void 0 : _a.map((([type, value]) => new RegExp("string" === type ? function(input) {
+            return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+        }(value) : value))).some((regexp => regexp.test(value)))) && void 0 !== _b && _b;
+    }
+    const hasInstanceStateValue = (instance, stateKey) => stateKey in instance[InstanceStateKey];
+    const getInstanceStateValue = (instance, stateKey) => instance[InstanceStateKey][stateKey];
+    const setInstanceStateValue = (instance, stateKey, stateValue) => instance[InstanceStateKey][stateKey] = stateValue;
+    const setWorkerRef = (ref, refId) => {
+        if (!(refId = webWorkerRefIdsByRef.get(ref))) {
+            webWorkerRefIdsByRef.set(ref, refId = randomId());
+            webWorkerRefsByRefId[refId] = ref;
+        }
+        return refId;
+    };
+    const getOrCreateNodeInstance = (winId, instanceId, nodeName, namespace, instance, prevInstanceId) => {
+        instance = webWorkerInstances.get(instanceId);
+        if (!instance && nodeName && environments[winId]) {
+            const prevInstance = webWorkerInstances.get(prevInstanceId || "");
+            instance = environments[winId].$createNode$(nodeName, instanceId, namespace, prevInstance);
+            webWorkerInstances.set(instanceId, instance);
+        }
+        return instance;
+    };
+    const definePrototypeNodeType = (Cstr, nodeType) => definePrototypeValue(Cstr, "nodeType", nodeType);
+    const cachedTreeProps = (Cstr, treeProps) => treeProps.map((propName => definePrototypeProperty(Cstr, propName, {
+        get() {
+            let cacheKey = getInstanceCacheKey(this, propName);
+            let result = cachedStructure.get(cacheKey);
+            if (!result) {
+                result = getter(this, [ propName ]);
+                cachedStructure.set(cacheKey, result);
+            }
+            return result;
+        }
+    })));
+    const getInstanceCacheKey = (instance, memberName, args) => [ instance[WinIdKey], instance[InstanceIdKey], memberName, ...(args || EMPTY_ARRAY).map((arg => String(arg && arg[WinIdKey] ? arg[InstanceIdKey] : arg))) ].join(".");
+    const cachedProps = (Cstr, propNames) => commaSplit(propNames).map((propName => definePrototypeProperty(Cstr, propName, {
+        get() {
+            hasInstanceStateValue(this, propName) || setInstanceStateValue(this, propName, getter(this, [ propName ]));
+            return getInstanceStateValue(this, propName);
+        },
+        set(val) {
+            getInstanceStateValue(this, propName) !== val && setter(this, [ propName ], val);
+            setInstanceStateValue(this, propName, val);
+        }
+    })));
+    const cachedDimensionProps = Cstr => getterDimensionPropNames.map((propName => definePrototypeProperty(Cstr, propName, {
+        get() {
+            const dimension = cachedDimensions.get(getInstanceCacheKey(this, propName));
+            if ("number" == typeof dimension) {
+                return dimension;
+            }
+            const groupedDimensions = getter(this, [ propName ], getterDimensionPropNames);
+            if (groupedDimensions && "object" == typeof groupedDimensions) {
+                Object.entries(groupedDimensions).map((([dimensionPropName, value]) => cachedDimensions.set(getInstanceCacheKey(this, dimensionPropName), value)));
+                return groupedDimensions[propName];
+            }
+            return groupedDimensions;
+        }
+    })));
+    const cachedDimensionMethods = (Cstr, dimensionMethodNames) => dimensionMethodNames.map((methodName => {
+        Cstr.prototype[methodName] = function(...args) {
+            let cacheKey = getInstanceCacheKey(this, methodName, args);
+            let dimensions = cachedDimensions.get(cacheKey);
+            if (!dimensions) {
+                dimensions = callMethod(this, [ methodName ], args);
+                cachedDimensions.set(cacheKey, dimensions);
+            }
+            return dimensions;
+        };
+    }));
+    const serializeForMain = ($winId$, $instanceId$, value, added, type) => void 0 !== value && (type = typeof value) ? "string" === type || "boolean" === type || "number" === type || null == value ? [ 0, value ] : "function" === type ? [ 4, {
+        $winId$: $winId$,
+        $instanceId$: $instanceId$,
+        $refId$: setWorkerRef(value)
+    } ] : (added = added || new Set) && Array.isArray(value) ? added.has(value) ? [ 1, [] ] : added.add(value) && [ 1, value.map((v => serializeForMain($winId$, $instanceId$, v, added))) ] : "object" === type ? value[InstanceIdKey] ? [ 3, [ value[WinIdKey], value[InstanceIdKey] ] ] : value instanceof Event ? [ 5, serializeObjectForMain($winId$, $instanceId$, value, false, added) ] : supportsTrustedHTML && value instanceof TrustedHTML ? [ 0, value.toString() ] : value instanceof ArrayBuffer ? [ 8, value ] : ArrayBuffer.isView(value) ? [ 9, value.buffer, getConstructorName(value) ] : [ 2, serializeObjectForMain($winId$, $instanceId$, value, true, added) ] : void 0 : value;
+    const supportsTrustedHTML = "undefined" != typeof TrustedHTML;
+    const serializeObjectForMain = (winId, instanceId, obj, includeFunctions, added, serializedObj, propName, propValue) => {
+        serializedObj = {};
+        if (!added.has(obj)) {
+            added.add(obj);
+            for (propName in obj) {
+                propValue = obj[propName];
+                (includeFunctions || "function" != typeof propValue) && (serializedObj[propName] = serializeForMain(winId, instanceId, propValue, added));
+            }
+        }
+        return serializedObj;
+    };
+    const serializeInstanceForMain = (instance, value) => instance ? serializeForMain(instance[WinIdKey], instance[InstanceIdKey], value) : [ 0, value ];
+    const deserializeFromMain = (winId, instanceId, applyPath, serializedValueTransfer, serializedType, serializedValue, obj, key) => {
+        if (serializedValueTransfer) {
+            serializedType = serializedValueTransfer[0];
+            serializedValue = serializedValueTransfer[1];
+            if (0 === serializedType || 11 === serializedType || 12 === serializedType) {
+                return serializedValue;
+            }
+            if (4 === serializedType) {
+                return deserializeRefFromMain(applyPath, serializedValue);
+            }
+            if (6 === serializedType) {
+                return winId && applyPath.length > 0 ? (...args) => callMethod(environments[winId].$window$, applyPath, args, 1) : noop;
+            }
+            if (3 === serializedType) {
+                return getOrCreateSerializedInstance(serializedValue);
+            }
+            if (7 === serializedType) {
+                return new NodeList(serializedValue.map(getOrCreateSerializedInstance));
+            }
+            if (10 === serializedType) {
+                return new Attr(serializedValue);
+            }
+            if (1 === serializedType) {
+                return serializedValue.map((v => deserializeFromMain(winId, instanceId, applyPath, v)));
+            }
+            if (14 === serializedType) {
+                return new CustomError(serializedValue);
+            }
+            obj = {};
+            for (key in serializedValue) {
+                obj[key] = deserializeFromMain(winId, instanceId, [ ...applyPath, key ], serializedValue[key]);
+            }
+            if (13 === serializedType) {
+                return new environments[winId].$window$.CSSStyleDeclaration(winId, instanceId, applyPath, obj);
+            }
+            if (5 === serializedType) {
+                if ("message" === obj.type && obj.origin) {
+                    let postMessageKey = JSON.stringify(obj.data);
+                    let postMessageData = postMessages.find((pm => pm.$data$ === postMessageKey));
+                    let env;
+                    if (postMessageData) {
+                        env = environments[postMessageData.$winId$];
+                        if (env) {
+                            obj.source = env.$window$;
+                            obj.origin = env.$location$.origin;
+                        }
+                    }
+                }
+                return new Proxy(new Event(obj.type, obj), {
+                    get: (target, propName) => propName in obj ? obj[propName] : "function" == typeof target[String(propName)] ? noop : target[String(propName)]
+                });
+            }
+            if (2 === serializedType) {
+                return obj;
+            }
+        }
+    };
+    const getOrCreateSerializedInstance = ([winId, instanceId, nodeName, prevInstanceId]) => instanceId === winId && environments[winId] ? environments[winId].$window$ : getOrCreateNodeInstance(winId, instanceId, nodeName, void 0, void 0, prevInstanceId);
+    const deserializeRefFromMain = (applyPath, {$winId$: $winId$, $instanceId$: $instanceId$, $nodeName$: $nodeName$, $refId$: $refId$}) => {
+        webWorkerRefsByRefId[$refId$] || webWorkerRefIdsByRef.set(webWorkerRefsByRefId[$refId$] = function(...args) {
+            const instance = getOrCreateNodeInstance($winId$, $instanceId$, $nodeName$);
+            return callMethod(instance, applyPath, args);
+        }, $refId$);
+        return webWorkerRefsByRefId[$refId$];
+    };
+    class CustomError extends Error {
+        constructor(errorObject) {
+            super(errorObject.message);
+            this.name = errorObject.name;
+            this.message = errorObject.message;
+            this.stack = errorObject.stack;
+        }
+    }
+    class NodeList {
+        constructor(nodes) {
+            (this._ = nodes).map(((node, index) => this[index] = node));
+        }
+        entries() {
+            return this._.entries();
+        }
+        forEach(cb, thisArg) {
+            this._.map(cb, thisArg);
+        }
+        item(index) {
+            return this[index];
+        }
+        keys() {
+            return this._.keys();
+        }
+        get length() {
+            return len(this._);
+        }
+        values() {
+            return this._.values();
+        }
+        [Symbol.iterator]() {
+            return this._[Symbol.iterator]();
+        }
+    }
+    const Attr = class {
+        constructor(serializedAttr) {
+            this.name = serializedAttr[0];
+            this.value = serializedAttr[1];
+        }
+        get nodeName() {
+            return this.name;
+        }
+        get nodeType() {
+            return 2;
+        }
+    };
+    const warnCrossOrigin = (apiType, apiName, env) => console.warn(`Partytown unable to ${apiType} cross-origin ${apiName}: ` + env.$location$);
+    const logWorker = (msg, winId) => {
+        try {
+            const config = webWorkerCtx.$config$;
+            if (config.logStackTraces) {
+                const frames = (new Error).stack.split("\n");
+                const i = frames.findIndex((f => f.includes("logWorker")));
+                msg += "\n" + frames.slice(i + 1).join("\n");
+            }
+            let prefix;
+            let color;
+            if (winId) {
+                prefix = `Worker (${normalizedWinId(winId)}) 🎉`;
+                color = winColor(winId);
+            } else {
+                prefix = self.name;
+                color = "#9844bf";
+            }
+            if (webWorkerCtx.lastLog !== msg) {
+                webWorkerCtx.lastLog = msg;
+                console.debug.apply(console, [ `%c${prefix}`, `background: ${color}; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;`, msg ]);
+            }
+        } catch (e) {}
+    };
+    const winIds = [];
+    const normalizedWinId = winId => {
+        winIds.includes(winId) || winIds.push(winId);
+        return winIds.indexOf(winId) + 1;
+    };
+    const winColor = winId => {
+        const colors = [ "#00309e", "#ea3655", "#eea727" ];
+        const index = normalizedWinId(winId) - 1;
+        return colors[index] || colors[colors.length - 1];
+    };
+    const getTargetProp = (target, applyPath) => {
+        let n = "";
+        if (target) {
+            const cstrName = getConstructorName(target);
+            if ("Window" === cstrName) {
+                n = "";
+            } else if ("string" == typeof target[InstanceDataKey]) {
+                let nodeName = target[InstanceDataKey];
+                n = "#text" === nodeName ? "textNode." : "#comment" === nodeName ? "commentNode." : "#document" === nodeName ? "document." : "html" === nodeName ? "doctype." : nodeName.toLowerCase() + ".";
+            } else {
+                n = "nodeType" in target && 2 === target.nodeType ? "attributes." : "CanvasRenderingContext2D" === cstrName ? "context2D." : "CanvasRenderingContextWebGL" === cstrName ? "contextWebGL." : "CSSStyleDeclaration" === cstrName ? "style." : "MutationObserver" === cstrName ? "mutationObserver." : "NamedNodeMap" === cstrName ? "namedNodeMap." : "ResizeObserver" === cstrName ? "resizeObserver." : cstrName.substring(0, 1).toLowerCase() + cstrName.substring(1) + ".";
+            }
+            target[ApplyPathKey] && target[ApplyPathKey].length && (n += [ ...target[ApplyPathKey] ].join(".") + ".");
+        }
+        if (applyPath.length > 1) {
+            const first = applyPath.slice(0, applyPath.length - 1);
+            const last = applyPath[applyPath.length - 1];
+            if (!isNaN(last)) {
+                return n + `${first.join(".")}[${last}]`;
+            }
+        }
+        return n + applyPath.join(".");
+    };
+    const getLogValue = (applyPath, v) => {
+        const type = typeof v;
+        if (void 0 === v) {
+            return "undefined";
+        }
+        if ("boolean" === type || "number" === type || null == v) {
+            return JSON.stringify(v);
+        }
+        if ("string" === type) {
+            return applyPath.includes("cookie") ? JSON.stringify(v.slice(0, 10) + "...") : JSON.stringify(v.length > 50 ? v.slice(0, 40) + "..." : v);
+        }
+        if (Array.isArray(v)) {
+            return `[${v.map(getLogValue).join(", ")}]`;
+        }
+        if ("object" === type) {
+            const instanceId = v[InstanceIdKey];
+            const cstrName = getConstructorName(v);
+            if ("string" == typeof instanceId) {
+                if ("Window" === cstrName) {
+                    return "window";
+                }
+                if ("string" == typeof v[InstanceDataKey]) {
+                    if (1 === v.nodeType) {
+                        return `<${v[InstanceDataKey].toLowerCase()}>`;
+                    }
+                    if (10 === v.nodeType) {
+                        return `<!DOCTYPE ${v[InstanceDataKey]}>`;
+                    }
+                    if (v.nodeType <= 11) {
+                        return v[InstanceDataKey];
+                    }
+                }
+                return "¯\\_(ツ)_/¯ instance obj";
+            }
+            return v[Symbol.iterator] ? `[${Array.from(v).map((i => getLogValue(applyPath, i))).join(", ")}]` : "value" in v ? "string" == typeof v.value ? `"${v.value}"` : objToString(v.value) : objToString(v);
+        }
+        return (v => "object" == typeof v && v && v.then)(v) ? "Promise" : "function" === type ? `ƒ() ${v.name || ""}`.trim() : `¯\\_(ツ)_/¯ ${String(v)}`.trim();
+    };
+    const objToString = obj => {
+        const s = [];
+        for (let key in obj) {
+            const value = obj[key];
+            const type = typeof value;
+            "string" === type ? s.push(`${key}: "${value}"`) : "function" === type ? s.push(`${key}: ƒ`) : Array.isArray(type) ? s.push(`${key}: [..]`) : "object" === type && value ? s.push(`${key}: {..}`) : s.push(`${key}: ${String(value)}`);
+        }
+        let str = s.join(", ");
+        str.length > 200 && (str = str.substring(0, 200) + "..");
+        return `{ ${str} }`;
+    };
+    const logDimensionCacheClearStyle = (target, propName) => {
+        (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logSetters) && logWorker(`Dimension cache cleared from style.${propName} setter`, target[WinIdKey]);
+    };
+    const logDimensionCacheClearMethod = (target, methodName) => {
+        (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logCalls) && logWorker(`Dimension cache cleared from method call ${methodName}()`, target[WinIdKey]);
+    };
+    const taskQueue = [];
+    const queue = (instance, $applyPath$, callType, $assignInstanceId$, $groupedGetters$, buffer) => {
+        if (instance[ApplyPathKey]) {
+            taskQueue.push({
+                $winId$: instance[WinIdKey],
+                $instanceId$: instance[InstanceIdKey],
+                $applyPath$: [ ...instance[ApplyPathKey], ...$applyPath$ ],
+                $assignInstanceId$: $assignInstanceId$,
+                $groupedGetters$: $groupedGetters$
+            });
+            taskQueue[len(taskQueue) - 1].$debug$ = ((target, applyPath, callType) => {
+                let m = getTargetProp(target, applyPath);
+                1 === callType ? m += " (blocking)" : 2 === callType ? m += " (non-blocking)" : 3 === callType && (m += " (non-blocking, no-side-effect)");
+                return m.trim();
+            })(instance, $applyPath$, callType);
+            buffer && 3 !== callType && console.error("buffer must be sent NonBlockingNoSideEffect");
+            if (3 === callType) {
+                webWorkerCtx.$postMessage$([ 12, {
+                    $msgId$: randomId(),
+                    $tasks$: [ ...taskQueue ]
+                } ], buffer ? [ buffer instanceof ArrayBuffer ? buffer : buffer.buffer ] : void 0);
+                taskQueue.length = 0;
+            } else if (1 === callType) {
+                return sendToMain(true);
+            }
+            webWorkerCtx.$asyncMsgTimer$ = setTimeout(sendToMain, 20);
+        }
+    };
+    const sendToMain = isBlocking => {
+        clearTimeout(webWorkerCtx.$asyncMsgTimer$);
+        if (len(taskQueue)) {
+            webWorkerCtx.$config$.logMainAccess && logWorker(`Main access, tasks sent: ${taskQueue.length}`);
+            const endTask = taskQueue[len(taskQueue) - 1];
+            const accessReq = {
+                $msgId$: `${randomId()}.${webWorkerCtx.$tabId$}`,
+                $tasks$: [ ...taskQueue ]
+            };
+            taskQueue.length = 0;
+            if (isBlocking) {
+                const accessRsp = ((webWorkerCtx, accessReq) => {
+                    const xhr = new XMLHttpRequest;
+                    xhr.open("POST", partytownLibUrl("proxytown"), false);
+                    xhr.send(JSON.stringify(accessReq));
+                    return JSON.parse(xhr.responseText);
+                })(0, accessReq);
+                const isPromise = accessRsp.$isPromise$;
+                const rtnValue = deserializeFromMain(endTask.$winId$, endTask.$instanceId$, endTask.$applyPath$, accessRsp.$rtnValue$);
+                if (accessRsp.$error$) {
+                    if (isPromise) {
+                        return Promise.reject(accessRsp.$error$);
+                    }
+                    throw new Error(accessRsp.$error$);
+                }
+                return isPromise ? Promise.resolve(rtnValue) : rtnValue;
+            }
+            webWorkerCtx.$postMessage$([ 12, accessReq ]);
+        }
+    };
+    const getter = (instance, applyPath, groupedGetters, rtnValue) => {
+        if (webWorkerCtx.$config$.get) {
+            rtnValue = webWorkerCtx.$config$.get(createHookOptions(instance, applyPath));
+            if (rtnValue !== HookContinue) {
+                return rtnValue;
+            }
+        }
+        rtnValue = queue(instance, applyPath, 1, void 0, groupedGetters);
+        ((target, applyPath, rtnValue, restrictedToWorker = false, groupedGetters = false) => {
+            if (webWorkerCtx.$config$.logGetters) {
+                try {
+                    const msg = `Get ${getTargetProp(target, applyPath)}, returned: ${getLogValue(applyPath, rtnValue)}${restrictedToWorker ? " (restricted to worker)" : ""}${groupedGetters ? " (grouped getter)" : ""}`;
+                    msg.includes("Symbol(") || logWorker(msg, target[WinIdKey]);
+                } catch (e) {}
+            }
+        })(instance, applyPath, rtnValue, false, !!groupedGetters);
+        return rtnValue;
+    };
+    const setter = (instance, applyPath, value, hookSetterValue) => {
+        if (webWorkerCtx.$config$.set) {
+            hookSetterValue = webWorkerCtx.$config$.set({
+                value: value,
+                prevent: HookPrevent,
+                ...createHookOptions(instance, applyPath)
+            });
+            if (hookSetterValue === HookPrevent) {
+                return;
+            }
+            hookSetterValue !== HookContinue && (value = hookSetterValue);
+        }
+        if (dimensionChangingSetterNames.some((s => applyPath.includes(s)))) {
+            cachedDimensions.clear();
+            ((target, propName) => {
+                (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logSetters) && logWorker(`Dimension cache cleared from setter "${propName}"`, target[WinIdKey]);
+            })(instance, applyPath[applyPath.length - 1]);
+        }
+        applyPath = [ ...applyPath, serializeInstanceForMain(instance, value), 0 ];
+        ((target, applyPath, value, restrictedToWorker = false) => {
+            if (webWorkerCtx.$config$.logSetters) {
+                try {
+                    applyPath = applyPath.slice(0, applyPath.length - 2);
+                    logWorker(`Set ${getTargetProp(target, applyPath)}, value: ${getLogValue(applyPath, value)}${restrictedToWorker ? " (restricted to worker)" : ""}`, target[WinIdKey]);
+                } catch (e) {}
+            }
+        })(instance, applyPath, value);
+        queue(instance, applyPath, 2);
+    };
+    const callMethod = (instance, applyPath, args, callType, assignInstanceId, buffer, rtnValue, methodName) => {
+        if (webWorkerCtx.$config$.apply) {
+            rtnValue = webWorkerCtx.$config$.apply({
+                args: args,
+                ...createHookOptions(instance, applyPath)
+            });
+            if (rtnValue !== HookContinue) {
+                return rtnValue;
+            }
+        }
+        methodName = applyPath[len(applyPath) - 1];
+        applyPath = [ ...applyPath, serializeInstanceForMain(instance, args) ];
+        callType = callType || (nonBlockingMethods.includes(methodName) ? 2 : 1);
+        if ("setAttribute" === methodName && hasInstanceStateValue(instance, args[0])) {
+            setInstanceStateValue(instance, args[0], args[1]);
+        } else if (structureChangingMethodNames.includes(methodName)) {
+            cachedDimensions.clear();
+            cachedStructure.clear();
+            ((target, methodName) => {
+                (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logCalls) && logWorker(`Dimension and DOM structure cache cleared from method call ${methodName}()`, target[WinIdKey]);
+            })(instance, methodName);
+        } else if (dimensionChangingMethodNames.includes(methodName)) {
+            callType = 2;
+            cachedDimensions.clear();
+            logDimensionCacheClearMethod(instance, methodName);
+        }
+        rtnValue = queue(instance, applyPath, callType, assignInstanceId, void 0, buffer);
+        ((target, applyPath, args, rtnValue) => {
+            if (webWorkerCtx.$config$.logCalls) {
+                try {
+                    applyPath = applyPath.slice(0, applyPath.length - 1);
+                    logWorker(`Call ${getTargetProp(target, applyPath)}(${args.map((v => getLogValue(applyPath, v))).join(", ")}), returned: ${getLogValue(applyPath, rtnValue)}`, target[WinIdKey]);
+                } catch (e) {}
+            }
+        })(instance, applyPath, args, rtnValue);
+        return rtnValue;
+    };
+    const constructGlobal = (instance, cstrName, args) => {
+        ((target, cstrName, args) => {
+            if (webWorkerCtx.$config$.logCalls) {
+                try {
+                    logWorker(`Construct new ${cstrName}(${args.map((v => getLogValue([], v))).join(", ")})`, target[WinIdKey]);
+                } catch (e) {}
+            }
+        })(instance, cstrName, args);
+        queue(instance, [ 1, cstrName, serializeInstanceForMain(instance, args) ], 1);
+    };
+    const createHookOptions = (instance, applyPath) => ({
+        name: applyPath.join("."),
+        continue: HookContinue,
+        nodeName: instance[InstanceDataKey],
+        constructor: getConstructorName(instance),
+        instance: instance,
+        window: environments[instance[WinIdKey]].$window$
+    });
+    const addStorageApi = (win, storageName, env) => {
+        let storage = {
+            getItem(key) {
+                if (env.$isSameOrigin$) {
+                    return callMethod(win, [ storageName, "getItem" ], [ key ], 1);
+                }
+                warnCrossOrigin("get", storageName, env);
+            },
+            setItem(key, value) {
+                env.$isSameOrigin$ ? callMethod(win, [ storageName, "setItem" ], [ key, value ], 1) : warnCrossOrigin("set", storageName, env);
+            },
+            removeItem(key) {
+                env.$isSameOrigin$ ? callMethod(win, [ storageName, "removeItem" ], [ key ], 1) : warnCrossOrigin("remove", storageName, env);
+            },
+            key(index) {
+                if (env.$isSameOrigin$) {
+                    return callMethod(win, [ storageName, "key" ], [ index ], 1);
+                }
+                warnCrossOrigin("key", storageName, env);
+            },
+            clear() {
+                env.$isSameOrigin$ ? callMethod(win, [ storageName, "clear" ], EMPTY_ARRAY, 1) : warnCrossOrigin("clear", storageName, env);
+            },
+            get length() {
+                if (env.$isSameOrigin$) {
+                    return getter(win, [ storageName, "length" ]);
+                }
+                warnCrossOrigin("length", storageName, env);
+            }
+        };
+        win[storageName] = new Proxy(storage, {
+            get: (target, key) => Reflect.has(target, key) ? Reflect.get(target, key) : target.getItem(key),
+            set(target, key, value) {
+                target.setItem(key, value);
+                return true;
+            },
+            has: (target, key) => !!Reflect.has(target, key) || "string" == typeof key && null !== target.getItem(key),
+            deleteProperty(target, key) {
+                target.removeItem(key);
+                return true;
+            }
+        });
+    };
+    const createCSSStyleDeclarationCstr = (win, WorkerBase, cstrName) => {
+        win[cstrName] = defineConstructorName(class extends WorkerBase {
+            constructor(winId, instanceId, applyPath, styles) {
+                super(winId, instanceId, applyPath, styles || {});
+                return new Proxy(this, {
+                    get(target, propName) {
+                        if (target[propName]) {
+                            return target[propName];
+                        }
+                        target[propName] || "string" != typeof propName || target[InstanceDataKey][propName] || (target[InstanceDataKey][propName] = getter(target, [ propName ]));
+                        return target[InstanceDataKey][propName];
+                    },
+                    set(target, propName, propValue) {
+                        target[InstanceDataKey][propName] = propValue;
+                        setter(target, [ propName ], propValue);
+                        logDimensionCacheClearStyle(target, propName);
+                        cachedDimensions.clear();
+                        return true;
+                    }
+                });
+            }
+            setProperty(...args) {
+                this[InstanceDataKey][args[0]] = args[1];
+                callMethod(this, [ "setProperty" ], args, 2);
+                logDimensionCacheClearStyle(this, args[0]);
+                cachedDimensions.clear();
+            }
+            getPropertyValue(propName) {
+                return this[propName];
+            }
+            removeProperty(propName) {
+                let value = this[InstanceDataKey][propName];
+                callMethod(this, [ "removeProperty" ], [ propName ], 2);
+                logDimensionCacheClearStyle(this, propName);
+                cachedDimensions.clear();
+                this[InstanceDataKey][propName] = void 0;
+                return value;
+            }
+        }, cstrName);
+    };
+    const createCSSStyleSheetConstructor = (win, cssStyleSheetCstrName) => {
+        win[cssStyleSheetCstrName] = defineConstructorName(class {
+            constructor(ownerNode) {
+                this.ownerNode = ownerNode;
+            }
+            get cssRules() {
+                const ownerNode = this.ownerNode;
+                return new Proxy({}, {
+                    get(target, propKey) {
+                        const propName = String(propKey);
+                        return "item" === propName ? index => getCssRule(ownerNode, index) : "length" === propName ? getCssRules(ownerNode).length : isNaN(propName) ? target[propKey] : getCssRule(ownerNode, propName);
+                    }
+                });
+            }
+            insertRule(ruleText, index) {
+                const cssRules = getCssRules(this.ownerNode);
+                index = void 0 === index ? 0 : index;
+                if (index >= 0 && index <= cssRules.length) {
+                    callMethod(this.ownerNode, [ "sheet", "insertRule" ], [ ruleText, index ], 2);
+                    cssRules.splice(index, 0, 0);
+                }
+                logDimensionCacheClearMethod(this.ownerNode, "insertRule");
+                cachedDimensions.clear();
+                return index;
+            }
+            deleteRule(index) {
+                callMethod(this.ownerNode, [ "sheet", "deleteRule" ], [ index ], 2);
+                getCssRules(this.ownerNode).splice(index, 1);
+                logDimensionCacheClearMethod(this.ownerNode, "deleteRule");
+                cachedDimensions.clear();
+            }
+            get type() {
+                return "text/css";
+            }
+        }, cssStyleSheetCstrName);
+        const HTMLStyleDescriptorMap = {
+            sheet: {
+                get() {
+                    return new win[cssStyleSheetCstrName](this);
+                }
+            }
+        };
+        definePrototypePropertyDescriptor(win.HTMLStyleElement, HTMLStyleDescriptorMap);
+    };
+    const getCssRules = (ownerNode, cssRules) => {
+        cssRules = getInstanceStateValue(ownerNode, 2);
+        if (!cssRules) {
+            cssRules = getter(ownerNode, [ "sheet", "cssRules" ]);
+            setInstanceStateValue(ownerNode, 2, cssRules);
+        }
+        return cssRules;
+    };
+    const getCssRule = (ownerNode, index, cssRules) => {
+        cssRules = getCssRules(ownerNode);
+        0 === cssRules[index] && (cssRules[index] = getter(ownerNode, [ "sheet", "cssRules", parseInt(index, 10) ]));
+        return cssRules[index];
+    };
+    const runScriptContent = (env, instanceId, scriptContent, winId, errorMsg) => {
+        try {
+            webWorkerCtx.$config$.logScriptExecution && logWorker(`Execute script: ${scriptContent.substring(0, 100).split("\n").map((l => l.trim())).join(" ").trim().substring(0, 60)}...`, winId);
+            env.$currentScriptId$ = instanceId;
+            run(env, scriptContent);
+        } catch (contentError) {
+            console.error(scriptContent, contentError);
+            errorMsg = String(contentError.stack || contentError);
+        }
+        env.$currentScriptId$ = "";
+        return errorMsg;
+    };
+    const run = (env, scriptContent, scriptUrl) => {
+        env.$runWindowLoadEvent$ = 1;
+        let sourceWithReplacedThis = ((scriptContent, newThis) => scriptContent.replace(/([a-zA-Z0-9_$\.\'\"\`])?(\.\.\.)?this(?![a-zA-Z0-9_$:])/g, ((match, p1, p2) => {
+            const prefix = (p1 || "") + (p2 || "");
+            return null != p1 ? prefix + "this" : prefix + newThis;
+        })))(scriptContent, "(thi$(this)?window:this)");
+        scriptContent = `with(this){${sourceWithReplacedThis.replace(/\/\/# so/g, "//Xso")}\n;function thi$(t){return t===this}};${(webWorkerCtx.$config$.globalFns || []).filter((globalFnName => /[a-zA-Z_$][0-9a-zA-Z_$]*/.test(globalFnName))).map((g => `(typeof ${g}=='function'&&(this.${g}=${g}))`)).join(";")};` + (scriptUrl ? "\n//# sourceURL=" + scriptUrl : "");
+        env.$isSameOrigin$ || (scriptContent = scriptContent.replace(/.postMessage\(/g, `.postMessage('${env.$winId$}',`));
+        new Function(scriptContent).call(env.$window$);
+        env.$runWindowLoadEvent$ = 0;
+    };
+    const runStateLoadHandlers = (instance, type, handlers) => {
+        handlers = getInstanceStateValue(instance, type);
+        handlers && setTimeout((() => handlers.map((cb => cb({
+            type: type
+        })))));
+    };
+    const resolveBaseLocation = (env, baseLocation) => {
+        baseLocation = env.$location$;
+        while (!baseLocation.host) {
+            env = environments[env.$parentWinId$];
+            baseLocation = env.$location$;
+            if (env.$winId$ === env.$parentWinId$) {
+                break;
+            }
+        }
+        return baseLocation;
+    };
+    const resolveToUrl = (env, url, type, baseLocation, resolvedUrl, configResolvedUrl) => {
+        baseLocation = resolveBaseLocation(env, baseLocation);
+        resolvedUrl = new URL(url || "", baseLocation);
+        if (type && webWorkerCtx.$config$.resolveUrl) {
+            configResolvedUrl = webWorkerCtx.$config$.resolveUrl(resolvedUrl, baseLocation, type);
+            if (configResolvedUrl) {
+                return configResolvedUrl;
+            }
+        }
+        return resolvedUrl;
+    };
+    const resolveUrl = (env, url, type) => resolveToUrl(env, url, type) + "";
+    const resolveSendBeaconRequestParameters = (env, url) => {
+        const baseLocation = resolveBaseLocation(env);
+        const resolvedUrl = new URL(url || "", baseLocation);
+        if (webWorkerCtx.$config$.resolveSendBeaconRequestParameters) {
+            const configResolvedParams = webWorkerCtx.$config$.resolveSendBeaconRequestParameters(resolvedUrl, baseLocation);
+            if (configResolvedParams) {
+                return configResolvedParams;
+            }
+        }
+        return {};
+    };
+    const getPartytownScript = () => `<script src="${partytownLibUrl("partytown.js?v=0.10.2-dev1727590485751")}"><\/script>`;
+    const createImageConstructor = env => class HTMLImageElement {
+        constructor() {
+            this.s = "";
+            this.l = [];
+            this.e = [];
+            this.style = {};
+        }
+        get src() {
+            return this.s;
+        }
+        set src(src) {
+            webWorkerCtx.$config$.logImageRequests && logWorker(`Image() request: ${resolveUrl(env, src, "image")}`, env.$winId$);
+            this.s = src;
+            fetch(resolveUrl(env, src, "image"), {
+                mode: "no-cors",
+                credentials: "include",
+                keepalive: true
+            }).then((rsp => {
+                rsp.ok || 0 === rsp.status ? this.l.map((cb => cb({
+                    type: "load"
+                }))) : this.e.map((cb => cb({
+                    type: "error"
+                })));
+            }), (() => this.e.forEach((cb => cb({
+                type: "error"
+            })))));
+        }
+        addEventListener(eventName, cb) {
+            "load" === eventName && this.l.push(cb);
+            "error" === eventName && this.e.push(cb);
+        }
+        removeEventListener(eventName, cb) {
+            "load" === eventName && (this.l = this.l.filter((fn => fn !== cb)));
+            "error" === eventName && (this.e = this.e.filter((fn => fn !== cb)));
+        }
+        get onload() {
+            return this.l[0];
+        }
+        set onload(cb) {
+            this.l = [ cb ];
+        }
+        get onerror() {
+            return this.e[0];
+        }
+        set onerror(cb) {
+            this.e = [ cb ];
+        }
+    };
+    const HTMLSrcElementDescriptorMap = {
+        addEventListener: {
+            value(...args) {
+                const eventName = args[0];
+                const callbacks = getInstanceStateValue(this, eventName) || [];
+                callbacks.push(args[1]);
+                setInstanceStateValue(this, eventName, callbacks);
+            }
+        },
+        async: {
+            get: noop,
+            set: noop
+        },
+        defer: {
+            get: noop,
+            set: noop
+        },
+        onload: {
+            get() {
+                let callbacks = getInstanceStateValue(this, "load");
+                return callbacks && callbacks[0] || null;
+            },
+            set(cb) {
+                setInstanceStateValue(this, "load", cb ? [ cb ] : null);
+            }
+        },
+        onerror: {
+            get() {
+                let callbacks = getInstanceStateValue(this, "error");
+                return callbacks && callbacks[0] || null;
+            },
+            set(cb) {
+                setInstanceStateValue(this, "error", cb ? [ cb ] : null);
+            }
+        },
+        getAttribute: {
+            value(attrName) {
+                return "src" === attrName ? this.src : callMethod(this, [ "getAttribute" ], [ attrName ]);
+            }
+        },
+        setAttribute: {
+            value(attrName, attrValue) {
+                scriptAttrPropNames.includes(attrName) ? this[attrName] = attrValue : callMethod(this, [ "setAttribute" ], [ attrName, attrValue ]);
+            }
+        }
+    };
+    const scriptAttrPropNames = commaSplit("src,type");
+    const patchHTMLScriptElement = (WorkerHTMLScriptElement, env) => {
+        const HTMLScriptDescriptorMap = {
+            innerHTML: innerHTMLDescriptor,
+            innerText: innerHTMLDescriptor,
+            src: {
+                get() {
+                    return getInstanceStateValue(this, 4) || "";
+                },
+                set(url) {
+                    const orgUrl = resolveUrl(env, url, null);
+                    const config = webWorkerCtx.$config$;
+                    url = resolveUrl(env, url, "script");
+                    setInstanceStateValue(this, 4, url);
+                    setter(this, [ "src" ], url);
+                    orgUrl !== url && setter(this, [ "dataset", "ptsrc" ], orgUrl);
+                    if (this.type) {
+                        const shouldExecuteScriptViaMainThread = testIfMustLoadScriptOnMainThread(config, url);
+                        shouldExecuteScriptViaMainThread && setter(this, [ "type" ], "text/javascript");
+                    }
+                }
+            },
+            text: innerHTMLDescriptor,
+            textContent: innerHTMLDescriptor,
+            type: {
+                get() {
+                    return getter(this, [ "type" ]);
+                },
+                set(type) {
+                    if (!isScriptJsType(type)) {
+                        setInstanceStateValue(this, 5, type);
+                        setter(this, [ "type" ], type);
+                    }
+                }
+            },
+            ...HTMLSrcElementDescriptorMap
+        };
+        definePrototypePropertyDescriptor(WorkerHTMLScriptElement, HTMLScriptDescriptorMap);
+    };
+    const innerHTMLDescriptor = {
+        get() {
+            const type = getter(this, [ "type" ]);
+            if (isScriptJsType(type)) {
+                const scriptContent = getInstanceStateValue(this, 3);
+                if (scriptContent) {
+                    return scriptContent;
+                }
+            }
+            return getter(this, [ "innerHTML" ]) || "";
+        },
+        set(scriptContent) {
+            setInstanceStateValue(this, 3, scriptContent);
+        }
+    };
+    const isScriptJsType = scriptType => !scriptType || "text/javascript" === scriptType;
+    const createNodeCstr = (win, env, WorkerBase) => {
+        const config = webWorkerCtx.$config$;
+        const WorkerNode = defineConstructorName(class extends WorkerBase {
+            appendChild(node) {
+                return this.insertBefore(node, null);
+            }
+            get href() {}
+            set href(_) {}
+            insertBefore(newNode, referenceNode) {
+                const winId = newNode[WinIdKey] = this[WinIdKey];
+                const instanceId = newNode[InstanceIdKey];
+                const nodeName = newNode[InstanceDataKey];
+                const isScript = "SCRIPT" === nodeName;
+                const isIFrame = "IFRAME" === nodeName;
+                if (isScript) {
+                    const scriptContent = getInstanceStateValue(newNode, 3);
+                    const scriptType = getInstanceStateValue(newNode, 5);
+                    if (scriptContent) {
+                        if (isScriptJsType(scriptType)) {
+                            const scriptId = newNode.id;
+                            const loadOnMainThread = scriptId && testIfMustLoadScriptOnMainThread(config, scriptId);
+                            if (loadOnMainThread) {
+                                setter(newNode, [ "type" ], "text/javascript");
+                            } else {
+                                const errorMsg = runScriptContent(env, instanceId, scriptContent, winId, "");
+                                const datasetType = errorMsg ? "pterror" : "ptid";
+                                const datasetValue = errorMsg || instanceId;
+                                setter(newNode, [ "type" ], "text/partytown-x");
+                                setter(newNode, [ "dataset", datasetType ], datasetValue);
+                            }
+                        }
+                        setter(newNode, [ "innerHTML" ], scriptContent);
+                    }
+                }
+                callMethod(this, [ "insertBefore" ], [ newNode, referenceNode ], 2);
+                if (isIFrame) {
+                    const src = getInstanceStateValue(newNode, 0);
+                    if (src && src.startsWith("javascript:")) {
+                        const scriptContent = src.split("javascript:")[1];
+                        runScriptContent(env, instanceId, scriptContent, winId, "");
+                    }
+                    ((winId, iframe) => {
+                        let i = 0;
+                        let type;
+                        let handlers;
+                        let callback = () => {
+                            if (environments[winId] && environments[winId].$isInitialized$ && !environments[winId].$isLoading$) {
+                                type = getInstanceStateValue(iframe, 1) ? "error" : "load";
+                                handlers = getInstanceStateValue(iframe, type);
+                                handlers && handlers.map((handler => handler({
+                                    type: type
+                                })));
+                            } else if (i++ > 2e3) {
+                                handlers = getInstanceStateValue(iframe, "error");
+                                handlers && handlers.map((handler => handler({
+                                    type: "error"
+                                })));
+                            } else {
+                                setTimeout(callback, 9);
+                            }
+                        };
+                        callback();
+                    })(instanceId, newNode);
+                }
+                if (isScript) {
+                    sendToMain(true);
+                    webWorkerCtx.$postMessage$([ 7, winId ]);
+                }
+                return newNode;
+            }
+            get nodeName() {
+                return "#s" === this[InstanceDataKey] ? "#document-fragment" : this[InstanceDataKey];
+            }
+            get nodeType() {
+                return 3;
+            }
+            get ownerDocument() {
+                return env.$document$;
+            }
+        }, "Node");
+        cachedTreeProps(WorkerNode, commaSplit("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling"));
+        win.Node = WorkerNode;
+    };
+    const htmlMedia = commaSplit("AUDIO,CANVAS,VIDEO");
+    const windowMediaConstructors = commaSplit("Audio,MediaSource");
+    const patchDocument = (WorkerDocument, env, isDocumentImplementation) => {
+        const DocumentDescriptorMap = {
+            body: {
+                get: () => env.$body$
+            },
+            cookie: {
+                get() {
+                    if (env.$isSameOrigin$) {
+                        return getter(this, [ "cookie" ]);
+                    }
+                    warnCrossOrigin("get", "cookie", env);
+                    return "";
+                },
+                set(value) {
+                    if (env.$isSameOrigin$) {
+                        setter(this, [ "cookie" ], value);
+                    } else {
+                        warnCrossOrigin("set", "cookie", env);
+                    }
+                }
+            },
+            createElement: {
+                value(tagName) {
+                    tagName = tagName.toUpperCase();
+                    if (!IS_TAG_REG.test(tagName)) {
+                        throw tagName + " not valid";
+                    }
+                    const isIframe = "IFRAME" === tagName;
+                    const winId = this[WinIdKey];
+                    const instanceId = (isIframe ? "f_" : "") + randomId();
+                    callMethod(this, [ "createElement" ], [ tagName ], 2, instanceId);
+                    const elm = getOrCreateNodeInstance(winId, instanceId, tagName);
+                    if (isIframe) {
+                        const env = createEnvironment({
+                            $winId$: instanceId,
+                            $parentWinId$: winId,
+                            $url$: "about:blank"
+                        }, true);
+                        env.$window$.fetch = fetch;
+                        setter(elm, [ "srcdoc" ], getPartytownScript());
+                    } else if ("SCRIPT" === tagName) {
+                        const scriptType = getInstanceStateValue(elm, 5);
+                        isScriptJsType(scriptType) && setter(elm, [ "type" ], "text/partytown");
+                    }
+                    return elm;
+                }
+            },
+            createElementNS: {
+                value(namespace, tagName) {
+                    const instanceId = randomId();
+                    const nsElm = getOrCreateNodeInstance(this[WinIdKey], instanceId, tagName, namespace);
+                    callMethod(this, [ "createElementNS" ], [ namespace, tagName ], 2, instanceId);
+                    return nsElm;
+                }
+            },
+            createTextNode: {
+                value(text) {
+                    const winId = this[WinIdKey];
+                    const instanceId = randomId();
+                    const textNode = getOrCreateNodeInstance(winId, instanceId, "#text");
+                    callMethod(this, [ "createTextNode" ], [ text ], 2, instanceId);
+                    return textNode;
+                }
+            },
+            createEvent: {
+                value: type => new Event(type)
+            },
+            currentScript: {
+                get() {
+                    return env.$currentScriptId$ ? getOrCreateNodeInstance(this[WinIdKey], env.$currentScriptId$, "SCRIPT") : null;
+                }
+            },
+            defaultView: {
+                get: () => isDocumentImplementation ? null : env.$window$
+            },
+            documentElement: {
+                get: () => env.$documentElement$
+            },
+            getElementsByTagName: {
+                value(tagName) {
+                    tagName = tagName.toUpperCase();
+                    return "BODY" === tagName ? [ env.$body$ ] : "HEAD" === tagName ? [ env.$head$ ] : callMethod(this, [ "getElementsByTagName" ], [ tagName ]);
+                }
+            },
+            head: {
+                get: () => env.$head$
+            },
+            images: {
+                get() {
+                    return getter(this, [ "images" ]);
+                }
+            },
+            scripts: {
+                get() {
+                    return getter(this, [ "scripts" ]);
+                }
+            },
+            implementation: {
+                get() {
+                    return {
+                        hasFeature: () => true,
+                        createHTMLDocument: title => {
+                            const $winId$ = randomId();
+                            callMethod(this, [ "implementation", "createHTMLDocument" ], [ title ], 1, {
+                                $winId$: $winId$
+                            });
+                            const docEnv = createEnvironment({
+                                $winId$: $winId$,
+                                $parentWinId$: $winId$,
+                                $url$: env.$location$ + "",
+                                $visibilityState$: "hidden"
+                            }, true, true);
+                            return docEnv.$document$;
+                        }
+                    };
+                }
+            },
+            location: {
+                get: () => env.$location$,
+                set(url) {
+                    env.$location$.href = url + "";
+                }
+            },
+            nodeType: {
+                value: 9
+            },
+            parentNode: {
+                value: null
+            },
+            parentElement: {
+                value: null
+            },
+            readyState: {
+                value: "complete"
+            },
+            visibilityState: {
+                get: () => env.$visibilityState$ || "visible"
+            }
+        };
+        definePrototypePropertyDescriptor(WorkerDocument, DocumentDescriptorMap);
+        cachedProps(WorkerDocument, "compatMode,referrer,forms");
+    };
+    const patchDocumentElementChild = (WokerDocumentElementChild, env) => {
+        const DocumentElementChildDescriptorMap = {
+            parentElement: {
+                get() {
+                    return this.parentNode;
+                }
+            },
+            parentNode: {
+                get: () => env.$documentElement$
+            }
+        };
+        definePrototypePropertyDescriptor(WokerDocumentElementChild, DocumentElementChildDescriptorMap);
+    };
+    const patchElement = (WorkerElement, WorkerHTMLElement) => {
+        const ElementDescriptorMap = {
+            localName: {
+                get() {
+                    return this[InstanceDataKey].toLowerCase();
+                }
+            },
+            namespaceURI: {
+                get() {
+                    return this[NamespaceKey] || "http://www.w3.org/1999/xhtml";
+                }
+            },
+            nodeType: {
+                value: 1
+            },
+            tagName: {
+                get() {
+                    return this[InstanceDataKey];
+                }
+            }
+        };
+        definePrototypePropertyDescriptor(WorkerElement, ElementDescriptorMap);
+        cachedTreeProps(WorkerElement, elementStructurePropNames);
+        cachedProps(WorkerElement, "id");
+        cachedDimensionProps(WorkerHTMLElement);
+        cachedDimensionMethods(WorkerHTMLElement, commaSplit("getClientRects,getBoundingClientRect"));
+    };
+    const patchHTMLAnchorElement = (WorkerHTMLAnchorElement, env) => {
+        const HTMLAnchorDescriptorMap = {};
+        commaSplit("hash,host,hostname,href,origin,pathname,port,protocol,search").map((anchorProp => {
+            HTMLAnchorDescriptorMap[anchorProp] = {
+                get() {
+                    let value = getInstanceStateValue(this, 4);
+                    let href;
+                    if ("string" != typeof value) {
+                        href = getter(this, [ "href" ]);
+                        if ("" === href) {
+                            return "protocol" === anchorProp ? ":" : "";
+                        }
+                        setInstanceStateValue(this, 4, href);
+                        value = new URL(href)[anchorProp];
+                    }
+                    return resolveToUrl(env, value, null)[anchorProp];
+                },
+                set(value) {
+                    let url;
+                    if ("href" === anchorProp) {
+                        if ((url => {
+                            try {
+                                new URL(url);
+                                return true;
+                            } catch (_) {
+                                return false;
+                            }
+                        })(value)) {
+                            url = new URL(value);
+                        } else {
+                            const baseHref = env.$location$.href;
+                            url = resolveToUrl(env, baseHref, null);
+                            url.href = new URL(value + "", url.href);
+                        }
+                    } else {
+                        url = resolveToUrl(env, this.href, null);
+                        url[anchorProp] = value;
+                    }
+                    setInstanceStateValue(this, 4, url.href);
+                    setter(this, [ "href" ], url.href);
+                }
+            };
+        }));
+        definePrototypePropertyDescriptor(WorkerHTMLAnchorElement, HTMLAnchorDescriptorMap);
+    };
+    const patchHTMLIFrameElement = (WorkerHTMLIFrameElement, env) => {
+        const HTMLIFrameDescriptorMap = {
+            contentDocument: {
+                get() {
+                    return getIframeEnv(this).$document$;
+                }
+            },
+            contentWindow: {
+                get() {
+                    return getIframeEnv(this).$window$;
+                }
+            },
+            src: {
+                get() {
+                    let src = getInstanceStateValue(this, 0);
+                    if (src && src.startsWith("javascript:")) {
+                        return src;
+                    }
+                    src = getIframeEnv(this).$location$.href;
+                    return src.startsWith("about:") ? "" : src;
+                },
+                set(src) {
+                    if (src) {
+                        if (src.startsWith("javascript:")) {
+                            setInstanceStateValue(this, 0, src);
+                        } else if (!src.startsWith("about:")) {
+                            let xhr = new XMLHttpRequest;
+                            let xhrStatus;
+                            let env = getIframeEnv(this);
+                            env.$location$.href = src = resolveUrl(env, src, "iframe");
+                            env.$isLoading$ = 1;
+                            env.$isSameOrigin$ = webWorkerCtx.$origin$ === env.$location$.origin;
+                            setInstanceStateValue(this, 1, void 0);
+                            xhr.open("GET", src, false);
+                            xhr.send();
+                            xhrStatus = xhr.status;
+                            if (xhrStatus > 199 && xhrStatus < 300) {
+                                setter(this, [ "srcdoc" ], `<base href="${src}">` + function(text) {
+                                    return text.replace(SCRIPT_TAG_REGEXP, ((_, attrs) => {
+                                        const parts = [];
+                                        let hasType = false;
+                                        let match;
+                                        while (match = ATTR_REGEXP.exec(attrs)) {
+                                            let [keyValue] = match;
+                                            if (keyValue.startsWith("type=")) {
+                                                hasType = true;
+                                                keyValue = keyValue.replace(/(application|text)\/javascript/, SCRIPT_TYPE);
+                                            }
+                                            parts.push(keyValue);
+                                        }
+                                        hasType || parts.push('type="text/partytown"');
+                                        return `<script ${parts.join(" ")}>`;
+                                    }));
+                                }(xhr.responseText) + getPartytownScript());
+                                sendToMain(true);
+                                webWorkerCtx.$postMessage$([ 7, env.$winId$ ]);
+                            } else {
+                                setInstanceStateValue(this, 1, xhrStatus);
+                                env.$isLoading$ = 0;
+                            }
+                        }
+                    }
+                }
+            },
+            ...HTMLSrcElementDescriptorMap
+        };
+        definePrototypePropertyDescriptor(WorkerHTMLIFrameElement, HTMLIFrameDescriptorMap);
+    };
+    const ATTR_REGEXP_STR = "((?:\\w|-)+(?:=(?:(?:\\w|-)+|'[^']*'|\"[^\"]*\")?)?)";
+    const SCRIPT_TAG_REGEXP = new RegExp(`<script\\s*((${ATTR_REGEXP_STR}\\s*)*)>`, "mg");
+    const ATTR_REGEXP = new RegExp(ATTR_REGEXP_STR, "mg");
+    const getIframeEnv = iframe => {
+        const $winId$ = iframe[InstanceIdKey];
+        environments[$winId$] || createEnvironment({
+            $winId$: $winId$,
+            $parentWinId$: iframe[WinIdKey],
+            $url$: getter(iframe, [ "src" ]) || "about:blank"
+        }, true);
+        return environments[$winId$];
+    };
+    const patchSvgElement = WorkerSVGGraphicsElement => {
+        const getMatrix = (elm, methodName) => {
+            const {a: a, b: b, c: c, d: d, e: e, f: f} = callMethod(elm, [ methodName ], EMPTY_ARRAY);
+            return new DOMMatrixReadOnly([ a, b, c, d, e, f ]);
+        };
+        const SVGGraphicsElementDescriptorMap = {
+            ...WorkerSVGGraphicsElement,
+            getCTM: {
+                value: function() {
+                    return getMatrix(this, "getCTM");
+                }
+            },
+            getScreenCTM: {
+                value: function() {
+                    return getMatrix(this, "getScreenCTM");
+                }
+            }
+        };
+        definePrototypePropertyDescriptor(WorkerSVGGraphicsElement, SVGGraphicsElementDescriptorMap);
+    };
+    const createNamedNodeMapCstr = (win, WorkerBase) => {
+        win.NamedNodeMap = defineConstructorName(class NamedNodeMap extends WorkerBase {
+            constructor(winId, instanceId, applyPath) {
+                super(winId, instanceId, applyPath);
+                return new Proxy(this, {
+                    get(target, propName) {
+                        const handler = NAMED_NODE_MAP_HANDLERS[propName];
+                        return handler ? handler.bind(target, [ propName ]) : getter(target, [ propName ]);
+                    },
+                    set(target, propName, propValue) {
+                        const handler = NAMED_NODE_MAP_HANDLERS[propName];
+                        if (handler) {
+                            throw new Error("Can't set read-only property: " + String(propName));
+                        }
+                        setter(target, [ propName ], propValue);
+                        return true;
+                    }
+                });
+            }
+        }, "NamedNodeMap");
+    };
+    function method(applyPath, ...args) {
+        return callMethod(this, applyPath, args, 1);
+    }
+    const NAMED_NODE_MAP_HANDLERS = {
+        getNamedItem: method,
+        getNamedItemNS: method,
+        item: method,
+        removeNamedItem: method,
+        removeNamedItemNS: method,
+        setNamedItem: method,
+        setNamedItemNS: method
+    };
+    const createWindow = ($winId$, $parentWinId$, url, $visibilityState$, isIframeWindow, isDocumentImplementation) => {
+        let cstrInstanceId;
+        let cstrNodeName;
+        let cstrNamespace;
+        let cstrPrevInstance;
+        const WorkerBase = class {
+            constructor(winId, instanceId, applyPath, instanceData, namespace) {
+                this[WinIdKey] = winId || $winId$;
+                this[InstanceIdKey] = instanceId || cstrInstanceId || randomId();
+                this[ApplyPathKey] = applyPath || [];
+                this[InstanceDataKey] = instanceData || cstrNodeName;
+                this[NamespaceKey] = namespace || cstrNamespace;
+                this[InstanceStateKey] = cstrPrevInstance && cstrPrevInstance[InstanceStateKey] || {};
+                cstrInstanceId = cstrNodeName = cstrNamespace = void 0;
+            }
+        };
+        const WorkerLocation = defineConstructorName(class extends URL {
+            assign() {
+                logWorker("location.assign(), noop");
+            }
+            reload() {
+                logWorker("location.reload(), noop");
+            }
+            replace() {
+                logWorker("location.replace(), noop");
+            }
+        }, "Location");
+        const $location$ = new WorkerLocation(url);
+        const $isSameOrigin$ = $location$.origin === webWorkerCtx.$origin$ || "about:blank" === $location$.origin;
+        const $isTopWindow$ = $parentWinId$ === $winId$;
+        const env = {};
+        const getChildEnvs = () => {
+            let childEnv = [];
+            let envWinId;
+            let otherEnv;
+            for (envWinId in environments) {
+                otherEnv = environments[envWinId];
+                otherEnv.$parentWinId$ !== $winId$ || otherEnv.$isTopWindow$ || childEnv.push(otherEnv);
+            }
+            return childEnv;
+        };
+        const WorkerWindow = defineConstructorName(class extends WorkerBase {
+            constructor() {
+                super($winId$, $winId$);
+                this.addEventListener = (...args) => {
+                    "load" === args[0] ? env.$runWindowLoadEvent$ && setTimeout((() => args[1]({
+                        type: "load"
+                    }))) : callMethod(this, [ "addEventListener" ], args, 2);
+                };
+                let win = this;
+                let value;
+                let historyState;
+                let hasInitializedMedia = 0;
+                let initWindowMedia = () => {
+                    if (!hasInitializedMedia) {
+                        (() => {
+                            if (!webWorkerCtx.$initWindowMedia$) {
+                                self.$bridgeToMedia$ = [ getter, setter, callMethod, constructGlobal, definePrototypePropertyDescriptor, randomId, WinIdKey, InstanceIdKey, ApplyPathKey ];
+                                webWorkerCtx.$importScripts$(partytownLibUrl("partytown-media.js?v=0.10.2-dev1727590485751"));
+                                webWorkerCtx.$initWindowMedia$ = self.$bridgeFromMedia$;
+                                delete self.$bridgeFromMedia$;
+                            }
+                            return webWorkerCtx.$initWindowMedia$;
+                        })()(WorkerBase, WorkerEventTargetProxy, env, win, windowMediaConstructors);
+                        hasInitializedMedia = 1;
+                    }
+                };
+                let nodeCstrs = {};
+                let $createNode$ = (nodeName, instanceId, namespace, prevInstance) => {
+                    htmlMedia.includes(nodeName) && initWindowMedia();
+                    const NodeCstr = nodeCstrs[nodeName] ? nodeCstrs[nodeName] : nodeName.includes("-") ? nodeCstrs.UNKNOWN : nodeCstrs.I;
+                    cstrInstanceId = instanceId;
+                    cstrNodeName = nodeName;
+                    cstrNamespace = namespace;
+                    cstrPrevInstance = prevInstance;
+                    return new NodeCstr;
+                };
+                win.Window = WorkerWindow;
+                win.name = name + `${normalizedWinId($winId$)} (${$winId$})`;
+                createNodeCstr(win, env, WorkerBase);
+                (win => {
+                    win.NodeList = defineConstructorName(NodeList, "NodeList");
+                })(win);
+                createNamedNodeMapCstr(win, WorkerBase);
+                createCSSStyleDeclarationCstr(win, WorkerBase, "CSSStyleDeclaration");
+                ((win, WorkerBase, cstrName) => {
+                    win[cstrName] = defineConstructorName(class extends WorkerBase {
+                        now() {
+                            return performance.now();
+                        }
+                    }, cstrName);
+                })(win, WorkerBase, "Performance");
+                ((win, nodeCstrs) => {
+                    const registry = new Map;
+                    win.customElements = {
+                        define(tagName, Cstr, opts) {
+                            registry.set(tagName, Cstr);
+                            nodeCstrs[tagName.toUpperCase()] = Cstr;
+                            const ceData = [ Cstr.name, Cstr.observedAttributes ];
+                            callMethod(win, [ "customElements", "define" ], [ tagName, ceData, opts ]);
+                        },
+                        get: tagName => registry.get(tagName) || callMethod(win, [ "customElements", "get" ], [ tagName ]),
+                        whenDefined: tagName => registry.has(tagName) ? Promise.resolve() : callMethod(win, [ "customElements", "whenDefined" ], [ tagName ]),
+                        upgrade: elm => callMethod(win, [ "customElements", "upgrade" ], [ elm ])
+                    };
+                })(win, nodeCstrs);
+                webWorkerCtx.$interfaces$.map((([cstrName, superCstrName, members, interfaceType, nodeName]) => {
+                    const SuperCstr = TrapConstructors[cstrName] ? WorkerTrapProxy : "EventTarget" === superCstrName ? WorkerEventTargetProxy : "Object" === superCstrName ? WorkerBase : win[superCstrName];
+                    const Cstr = win[cstrName] = defineConstructorName(12 === interfaceType ? class extends WorkerBase {
+                        constructor(...args) {
+                            super();
+                            constructGlobal(this, cstrName, args);
+                        }
+                    } : win[cstrName] || class extends SuperCstr {}, cstrName);
+                    nodeName && (nodeCstrs[nodeName] = Cstr);
+                    members.map((([memberName, memberType, staticValue]) => {
+                        memberName in Cstr.prototype || memberName in SuperCstr.prototype || ("string" == typeof memberType ? definePrototypeProperty(Cstr, memberName, {
+                            get() {
+                                if (!hasInstanceStateValue(this, memberName)) {
+                                    const instanceId = this[InstanceIdKey];
+                                    const applyPath = [ ...this[ApplyPathKey], memberName ];
+                                    const PropCstr = win[memberType];
+                                    PropCstr && setInstanceStateValue(this, memberName, new PropCstr($winId$, instanceId, applyPath));
+                                }
+                                return getInstanceStateValue(this, memberName);
+                            },
+                            set(value) {
+                                setInstanceStateValue(this, memberName, value);
+                            }
+                        }) : 5 === memberType ? definePrototypeValue(Cstr, memberName, (function(...args) {
+                            return callMethod(this, [ memberName ], args);
+                        })) : memberType > 0 && (void 0 !== staticValue ? definePrototypeValue(Cstr, memberName, staticValue) : definePrototypeProperty(Cstr, memberName, {
+                            get() {
+                                return getter(this, [ memberName ]);
+                            },
+                            set(value) {
+                                return setter(this, [ memberName ], value);
+                            }
+                        })));
+                    }));
+                }));
+                commaSplit("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((globalName => {
+                    delete WorkerWindow.prototype[globalName];
+                    if (!(globalName in win)) {
+                        value = self[globalName];
+                        null != value && (win[globalName] = "function" != typeof value || value.toString().startsWith("class") ? value : value.bind(self));
+                    }
+                }));
+                Object.getOwnPropertyNames(self).map((globalName => {
+                    globalName in win || (win[globalName] = self[globalName]);
+                }));
+                windowMediaConstructors.map((cstrName => defineProperty(win, cstrName, {
+                    get() {
+                        initWindowMedia();
+                        return win[cstrName];
+                    }
+                })));
+                "trustedTypes" in self && (win.trustedTypes = self.trustedTypes);
+                patchElement(win.Element, win.HTMLElement);
+                patchDocument(win.Document, env, isDocumentImplementation);
+                (WorkerDocumentFragment => {
+                    definePrototypeNodeType(WorkerDocumentFragment, 11);
+                    cachedTreeProps(WorkerDocumentFragment, elementStructurePropNames);
+                })(win.DocumentFragment);
+                patchHTMLAnchorElement(win.HTMLAnchorElement, env);
+                (WorkerHTMLFormElement => {
+                    definePrototypePropertyDescriptor(WorkerHTMLFormElement, {});
+                    cachedProps(WorkerHTMLFormElement, "elements");
+                })(win.HTMLFormElement);
+                patchHTMLIFrameElement(win.HTMLIFrameElement);
+                patchHTMLScriptElement(win.HTMLScriptElement, env);
+                patchSvgElement(win.SVGGraphicsElement);
+                patchDocumentElementChild(win.HTMLHeadElement, env);
+                patchDocumentElementChild(win.HTMLBodyElement, env);
+                ((WorkerHTMLHtmlElement, env) => {
+                    const DocumentElementDescriptorMap = {
+                        parentElement: {
+                            value: null
+                        },
+                        parentNode: {
+                            get: () => env.$document$
+                        }
+                    };
+                    definePrototypePropertyDescriptor(WorkerHTMLHtmlElement, DocumentElementDescriptorMap);
+                })(win.HTMLHtmlElement, env);
+                createCSSStyleSheetConstructor(win, "CSSStyleSheet");
+                definePrototypeNodeType(win.Comment, 8);
+                definePrototypeNodeType(win.DocumentType, 10);
+                Object.assign(env, {
+                    $winId$: $winId$,
+                    $parentWinId$: $parentWinId$,
+                    $window$: new Proxy(win, {
+                        get: (win, propName) => {
+                            var _a;
+                            if ("string" != typeof propName || isNaN(propName)) {
+                                return (null === (_a = webWorkerCtx.$config$.mainWindowAccessors) || void 0 === _a ? void 0 : _a.includes(propName)) ? getter(this, [ propName ]) : win[propName];
+                            }
+                            {
+                                let frame = getChildEnvs()[propName];
+                                return frame ? frame.$window$ : void 0;
+                            }
+                        },
+                        has: () => true
+                    }),
+                    $document$: $createNode$("#document", $winId$ + ".d"),
+                    $documentElement$: $createNode$("HTML", $winId$ + ".e"),
+                    $head$: $createNode$("HEAD", $winId$ + ".h"),
+                    $body$: $createNode$("BODY", $winId$ + ".b"),
+                    $location$: $location$,
+                    $visibilityState$: $visibilityState$,
+                    $isSameOrigin$: $isSameOrigin$,
+                    $isTopWindow$: $isTopWindow$,
+                    $createNode$: $createNode$
+                });
+                win.requestAnimationFrame = cb => setTimeout((() => cb(performance.now())), 9);
+                win.cancelAnimationFrame = id => clearTimeout(id);
+                win.requestIdleCallback = (cb, start) => {
+                    start = Date.now();
+                    return setTimeout((() => cb({
+                        didTimeout: false,
+                        timeRemaining: () => Math.max(0, 50 - (Date.now() - start))
+                    })), 1);
+                };
+                win.cancelIdleCallback = id => clearTimeout(id);
+                addStorageApi(win, "localStorage", env);
+                addStorageApi(win, "sessionStorage", env);
+                $isSameOrigin$ || (win.indexeddb = void 0);
+                if (isIframeWindow) {
+                    historyState = {};
+                    win.history = {
+                        pushState(stateObj) {
+                            historyState = stateObj;
+                        },
+                        replaceState(stateObj) {
+                            historyState = stateObj;
+                        },
+                        get state() {
+                            return historyState;
+                        },
+                        length: 0
+                    };
+                    win.indexeddb = void 0;
+                } else {
+                    const originalPushState = win.history.pushState.bind(win.history);
+                    const originalReplaceState = win.history.replaceState.bind(win.history);
+                    win.history.pushState = (stateObj, _, newUrl) => {
+                        false !== env.$propagateHistoryChange$ && originalPushState(stateObj, _, newUrl);
+                    };
+                    win.history.replaceState = (stateObj, _, newUrl) => {
+                        false !== env.$propagateHistoryChange$ && originalReplaceState(stateObj, _, newUrl);
+                    };
+                }
+                win.Worker = void 0;
+            }
+            get body() {
+                return env.$body$;
+            }
+            get document() {
+                return env.$document$;
+            }
+            get documentElement() {
+                return env.$documentElement$;
+            }
+            fetch(input, init) {
+                input = "string" == typeof input || input instanceof URL ? String(input) : input.url;
+                return fetch(resolveUrl(env, input, "fetch"), init);
+            }
+            get frames() {
+                return env.$window$;
+            }
+            get frameElement() {
+                return $isTopWindow$ ? null : getOrCreateNodeInstance($parentWinId$, $winId$, "IFRAME");
+            }
+            get globalThis() {
+                return env.$window$;
+            }
+            get head() {
+                return env.$head$;
+            }
+            get length() {
+                return getChildEnvs().length;
+            }
+            get location() {
+                return $location$;
+            }
+            set location(loc) {
+                $location$.href = loc + "";
+            }
+            get Image() {
+                return createImageConstructor(env);
+            }
+            get navigator() {
+                return (env => {
+                    const nav = {
+                        sendBeacon: (url, body) => {
+                            if (webWorkerCtx.$config$.logSendBeaconRequests) {
+                                try {
+                                    logWorker(`sendBeacon: ${resolveUrl(env, url, null)}${body ? ", data: " + JSON.stringify(body) : ""}, resolvedParams: ${JSON.stringify(resolveSendBeaconRequestParameters(env, url))}`);
+                                } catch (e) {
+                                    console.error(e);
+                                }
+                            }
+                            try {
+                                fetch(resolveUrl(env, url, null), {
+                                    method: "POST",
+                                    body: body,
+                                    mode: "no-cors",
+                                    keepalive: true,
+                                    ...resolveSendBeaconRequestParameters(env, url)
+                                });
+                                return true;
+                            } catch (e) {
+                                console.error(e);
+                                return false;
+                            }
+                        }
+                    };
+                    for (let key in navigator) {
+                        nav[key] = navigator[key];
+                    }
+                    return new Proxy(nav, {
+                        set(_, propName, propValue) {
+                            navigator[propName] = propValue;
+                            return true;
+                        },
+                        get(target, prop) {
+                            if (Object.prototype.hasOwnProperty.call(target, prop)) {
+                                return target[prop];
+                            }
+                            const value = getter(env.$window$, [ "navigator", prop ]);
+                            return value;
+                        }
+                    });
+                })(env);
+            }
+            get origin() {
+                return $location$.origin;
+            }
+            set origin(_) {}
+            get parent() {
+                for (let envWinId in environments) {
+                    if (environments[envWinId].$winId$ === $parentWinId$) {
+                        return environments[envWinId].$window$;
+                    }
+                }
+                return env.$window$;
+            }
+            postMessage(...args) {
+                if (environments[args[0]]) {
+                    len(postMessages) > 50 && postMessages.splice(0, 5);
+                    postMessages.push({
+                        $winId$: args[0],
+                        $data$: JSON.stringify(args[1])
+                    });
+                    args = args.slice(1);
+                }
+                callMethod(this, [ "postMessage" ], args, 3);
+            }
+            get self() {
+                return env.$window$;
+            }
+            get top() {
+                for (let envWinId in environments) {
+                    if (environments[envWinId].$isTopWindow$) {
+                        return environments[envWinId].$window$;
+                    }
+                }
+                return env.$window$;
+            }
+            get window() {
+                return env.$window$;
+            }
+            get XMLHttpRequest() {
+                const Xhr = XMLHttpRequest;
+                const str = String(Xhr);
+                const ExtendedXhr = defineConstructorName(class extends Xhr {
+                    open(...args) {
+                        args[1] = resolveUrl(env, args[1], "xhr");
+                        super.open(...args);
+                    }
+                    set withCredentials(_) {
+                        webWorkerCtx.$config$.allowXhrCredentials && (super.withCredentials = _);
+                    }
+                    toString() {
+                        return str;
+                    }
+                }, getConstructorName(Xhr));
+                ExtendedXhr.prototype.constructor.toString = () => str;
+                return ExtendedXhr;
+            }
+        }, "Window");
+        const WorkerTrapProxy = class extends WorkerBase {
+            constructor(winId, instanceId, applyPath, nodeName) {
+                super(winId, instanceId, applyPath, nodeName);
+                return new Proxy(this, {
+                    get: (instance, propName) => getter(instance, [ propName ]),
+                    set(instance, propName, propValue) {
+                        setter(instance, [ propName ], propValue);
+                        return true;
+                    }
+                });
+            }
+        };
+        const WorkerEventTargetProxy = class extends WorkerBase {};
+        eventTargetMethods.map((methodName => WorkerEventTargetProxy.prototype[methodName] = function(...args) {
+            return callMethod(this, [ methodName ], args, 2);
+        }));
+        cachedProps(WorkerWindow, "devicePixelRatio");
+        cachedDimensionProps(WorkerWindow);
+        cachedDimensionMethods(WorkerWindow, [ "getComputedStyle" ]);
+        new WorkerWindow;
+        return env;
+    };
+    const TrapConstructors = {
+        DOMStringMap: 1,
+        NamedNodeMap: 1
+    };
+    const createEnvironment = ({$winId$: $winId$, $parentWinId$: $parentWinId$, $url$: $url$, $visibilityState$: $visibilityState$}, isIframeWindow, isDocumentImplementation) => {
+        if (!environments[$winId$]) {
+            environments[$winId$] = createWindow($winId$, $parentWinId$, $url$, $visibilityState$, isIframeWindow, isDocumentImplementation);
+            {
+                const winType = $winId$ === $parentWinId$ ? "top" : "iframe";
+                logWorker(`Created ${winType} window ${normalizedWinId($winId$)} environment`, $winId$);
+            }
+        }
+        webWorkerCtx.$postMessage$([ 7, $winId$ ]);
+        return environments[$winId$];
+    };
+    const queuedEvents = [];
+    const receiveMessageFromSandboxToWorker = ev => {
+        const msg = ev.data;
+        const msgType = msg[0];
+        const msgValue = msg[1];
+        if (webWorkerCtx.$isInitialized$) {
+            if (7 === msgType) {
+                (async initScript => {
+                    let winId = initScript.$winId$;
+                    let instanceId = initScript.$instanceId$;
+                    let instance = getOrCreateNodeInstance(winId, instanceId, "SCRIPT");
+                    let scriptContent = initScript.$content$;
+                    let scriptSrc = initScript.$url$;
+                    let scriptOrgSrc = initScript.$orgUrl$;
+                    let errorMsg = "";
+                    let env = environments[winId];
+                    let rsp;
+                    let javascriptContentTypes = [ "text/jscript", "text/javascript", "text/x-javascript", "application/javascript", "application/x-javascript", "text/ecmascript", "text/x-ecmascript", "application/ecmascript" ];
+                    if (scriptSrc) {
+                        try {
+                            scriptSrc = resolveToUrl(env, scriptSrc, "script") + "";
+                            setInstanceStateValue(instance, 4, scriptSrc);
+                            webWorkerCtx.$config$.logScriptExecution && logWorker(`Execute script src: ${scriptOrgSrc}`, winId);
+                            rsp = await fetch(scriptSrc);
+                            if (rsp.ok) {
+                                let responseContentType = rsp.headers.get("content-type");
+                                let shouldExecute = javascriptContentTypes.some((ct => {
+                                    var _a, _b, _c;
+                                    return null === (_c = null === (_a = null == responseContentType ? void 0 : responseContentType.toLowerCase) || void 0 === _a ? void 0 : (_b = _a.call(responseContentType)).includes) || void 0 === _c ? void 0 : _c.call(_b, ct);
+                                }));
+                                if (shouldExecute) {
+                                    scriptContent = await rsp.text();
+                                    env.$currentScriptId$ = instanceId;
+                                    run(env, scriptContent, scriptOrgSrc || scriptSrc);
+                                }
+                                runStateLoadHandlers(instance, "load");
+                            } else {
+                                errorMsg = rsp.statusText;
+                                runStateLoadHandlers(instance, "error");
+                            }
+                        } catch (urlError) {
+                            console.error(urlError);
+                            errorMsg = String(urlError.stack || urlError);
+                            runStateLoadHandlers(instance, "error");
+                        }
+                    } else {
+                        scriptContent && (errorMsg = runScriptContent(env, instanceId, scriptContent, winId, errorMsg));
+                    }
+                    env.$currentScriptId$ = "";
+                    webWorkerCtx.$postMessage$([ 6, winId, instanceId, errorMsg ]);
+                })(msgValue);
+            } else if (9 === msgType) {
+                (({$winId$: $winId$, $instanceId$: $instanceId$, $refId$: $refId$, $thisArg$: $thisArg$, $args$: $args$}) => {
+                    if (webWorkerRefsByRefId[$refId$]) {
+                        try {
+                            webWorkerRefsByRefId[$refId$].apply(deserializeFromMain($winId$, $instanceId$, [], $thisArg$), deserializeFromMain($winId$, $instanceId$, [], $args$));
+                        } catch (e) {
+                            console.error(e);
+                        }
+                    }
+                })(msgValue);
+            } else if (10 === msgType) {
+                (({$winId$: $winId$, $forward$: $forward$, $args$: $args$}) => {
+                    try {
+                        let target = environments[$winId$].$window$;
+                        let i = 0;
+                        let l = len($forward$);
+                        for (;i < l; i++) {
+                            i + 1 < l ? target = target[$forward$[i]] : target[$forward$[i]].apply(target, deserializeFromMain(null, $winId$, [], $args$));
+                        }
+                    } catch (e) {
+                        console.error(e);
+                    }
+                })(msgValue);
+            } else if (5 === msgType) {
+                createEnvironment(msgValue);
+            } else if (8 === msgType) {
+                if (1 !== environments[msgValue].$isInitialized$) {
+                    const winId = msgValue;
+                    const env = environments[winId];
+                    const winType = env.$winId$ === env.$parentWinId$ ? "top" : "iframe";
+                    logWorker(`Initialized ${winType} window ${normalizedWinId(winId)} environment 🎉`, winId);
+                }
+                environments[msgValue].$isInitialized$ = 1;
+                environments[msgValue].$isLoading$ = 0;
+            } else if (14 === msgType) {
+                environments[msgValue].$visibilityState$ = msg[2];
+            } else if (13 === msgType) {
+                const $winId$ = msgValue.$winId$;
+                const env = environments[$winId$];
+                env.$location$.href = msgValue.url;
+                !function($winId$, env, data) {
+                    const history = env.$window$.history;
+                    switch (data.type) {
+                      case 0:
+                        env.$propagateHistoryChange$ = false;
+                        try {
+                            history.pushState(data.state, "", data.newUrl);
+                        } catch (e) {}
+                        env.$propagateHistoryChange$ = true;
+                        break;
+
+                      case 1:
+                        env.$propagateHistoryChange$ = false;
+                        try {
+                            history.replaceState(data.state, "", data.newUrl);
+                        } catch (e) {}
+                        env.$propagateHistoryChange$ = true;
+                    }
+                }(msgValue.$winId$, env, msgValue);
+            } else {
+                15 === msgType && ((_type, winId, instanceId, callbackName, args) => {
+                    const elm = getOrCreateNodeInstance(winId, instanceId);
+                    elm && "function" == typeof elm[callbackName] && elm[callbackName].apply(elm, args);
+                })(...msg);
+            }
+        } else if (1 === msgType) {
+            (initWebWorkerData => {
+                const config = webWorkerCtx.$config$ = JSON.parse(initWebWorkerData.$config$);
+                const locOrigin = initWebWorkerData.$origin$;
+                webWorkerCtx.$importScripts$ = importScripts.bind(self);
+                webWorkerCtx.$interfaces$ = initWebWorkerData.$interfaces$;
+                webWorkerCtx.$libPath$ = initWebWorkerData.$libPath$;
+                webWorkerCtx.$origin$ = locOrigin;
+                webWorkerCtx.$postMessage$ = postMessage.bind(self);
+                webWorkerCtx.$sharedDataBuffer$ = initWebWorkerData.$sharedDataBuffer$;
+                webWorkerCtx.$tabId$ = initWebWorkerData.$tabId$;
+                self.importScripts = void 0;
+                delete self.postMessage;
+                delete self.WorkerGlobalScope;
+                commaSplit("resolveUrl,resolveSendBeaconRequestParameters,get,set,apply").map((configName => {
+                    config[configName] && (config[configName] = new Function("return " + config[configName])());
+                }));
+            })(msgValue);
+            webWorkerCtx.$postMessage$([ 2 ]);
+        } else if (3 === msgType) {
+            webWorkerCtx.$interfaces$ = [ ...webWorkerCtx.$interfaces$, ...msgValue ];
+            webWorkerCtx.$isInitialized$ = 1;
+            logWorker("Initialized web worker");
+            webWorkerCtx.$postMessage$([ 4 ]);
+            queuedEvents.length && logWorker(`Queued ready messages: ${queuedEvents.length}`);
+            [ ...queuedEvents ].map(receiveMessageFromSandboxToWorker);
+            queuedEvents.length = 0;
+        } else {
+            queuedEvents.push(ev);
+        }
+    };
+    self.onmessage = receiveMessageFromSandboxToWorker;
+    postMessage([ 0 ]);
+})(self);
Index: build/debug/partytown.js
===================================================================
--- build/debug/partytown.js	(revision 3189893)
+++ build/debug/partytown.js	(working copy)
@@ -1 +1,128 @@
-const defaultPartytownForwardPropertySettings={preserveBehavior:!1},resolvePartytownForwardProperty=t=>{if("string"==typeof t)return[t,defaultPartytownForwardPropertySettings];const[e,r=defaultPartytownForwardPropertySettings]=t;return[e,{...defaultPartytownForwardPropertySettings,...r}]},arrayMethods=Object.freeze((t=>{const e=new Set;let r=[];do{Object.getOwnPropertyNames(r).forEach((t=>{"function"==typeof r[t]&&e.add(t)}))}while((r=Object.getPrototypeOf(r))!==Object.prototype);return Array.from(e)})());!function(t,e,r,n,o,a,i,s,d,l,c=t,p){function y(){p||(p=1,"/"==(i=(a.lib||"/~partytown/")+(!1!==a.debug?"debug/":""))[0]?(d=e.querySelectorAll('script[type="text/partytown"]'),n!=t?n.dispatchEvent(new CustomEvent("pt1",{detail:t})):(s=setTimeout(u,999999999),e.addEventListener("pt0",f),o?w(1):r.serviceWorker?r.serviceWorker.register(i+(a.swPath||"partytown-sw.js"),{scope:i}).then((function(t){t.active?w():t.installing?t.installing.addEventListener("statechange",(function(t){"activated"==t.target.state&&w()})):console.warn(t)}),console.error):u())):console.warn('Partytown config.lib url must start with "/"'))}function w(r){l=e.createElement(r?"script":"iframe"),t._pttab=Date.now(),r||(l.style.display="block",l.style.width="0",l.style.height="0",l.style.border="0",l.style.visibility="hidden",l.setAttribute("aria-hidden",!0)),l.src=i+"partytown-"+(r?"atomics.js?v=0.10.2-dev1727590485751":"sandbox-sw.html?"+t._pttab),e.querySelector(a.sandboxParent||"body").appendChild(l)}function u(r,o){for(console.warn("Partytown script fallback"),f(),n==t&&(a.forward||[]).map((function(e){const[r]=resolvePartytownForwardProperty(e);delete t[r.split(".")[0]]})),r=0;r<d.length;r++)(o=e.createElement("script")).innerHTML=d[r].innerHTML,o.nonce=a.nonce,e.head.appendChild(o);l&&l.parentNode.removeChild(l)}function f(){clearTimeout(s)}a=t.partytown||{},n==t&&(a.forward||[]).map((function(e){const[r,{preserveBehavior:n}]=resolvePartytownForwardProperty(e);c=t,r.split(".").map((function(e,r,o){var a;c=c[o[r]]=r+1<o.length?c[o[r]]||(a=o[r+1],arrayMethods.includes(a)?[]:{}):(()=>{let e=null;if(n){const{methodOrProperty:r,thisObject:n}=((t,e)=>{let r=t;for(let t=0;t<e.length-1;t+=1)r=r[e[t]];return{thisObject:r,methodOrProperty:e.length>0?r[e[e.length-1]]:void 0}})(t,o);"function"==typeof r&&(e=(...t)=>r.apply(n,...t))}return function(){let r;return e&&(r=e(arguments)),(t._ptf=t._ptf||[]).push(o,arguments),r}})()}))})),"complete"==e.readyState?y():(t.addEventListener("DOMContentLoaded",y),t.addEventListener("load",y))}(window,document,navigator,top,window.crossOriginIsolated);
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+const defaultPartytownForwardPropertySettings = {
+    preserveBehavior: false
+};
+
+const resolvePartytownForwardProperty = propertyOrPropertyWithSettings => {
+    if ("string" == typeof propertyOrPropertyWithSettings) {
+        return [ propertyOrPropertyWithSettings, defaultPartytownForwardPropertySettings ];
+    }
+    const [property, settings = defaultPartytownForwardPropertySettings] = propertyOrPropertyWithSettings;
+    return [ property, {
+        ...defaultPartytownForwardPropertySettings,
+        ...settings
+    } ];
+};
+
+const arrayMethods = Object.freeze((obj => {
+    const properties = new Set;
+    let currentObj = obj;
+    do {
+        Object.getOwnPropertyNames(currentObj).forEach((item => {
+            "function" == typeof currentObj[item] && properties.add(item);
+        }));
+    } while ((currentObj = Object.getPrototypeOf(currentObj)) !== Object.prototype);
+    return Array.from(properties);
+})([]));
+
+!function(win, doc, nav, top, useAtomics, config, libPath, timeout, scripts, sandbox, mainForwardFn = win, isReady) {
+    function ready() {
+        if (!isReady) {
+            isReady = 1;
+            libPath = (config.lib || "/~partytown/") + (false !== config.debug ? "debug/" : "");
+            if ("/" == libPath[0]) {
+                scripts = doc.querySelectorAll('script[type="text/partytown"]');
+                if (top != win) {
+                    top.dispatchEvent(new CustomEvent("pt1", {
+                        detail: win
+                    }));
+                } else {
+                    timeout = setTimeout(fallback, 999999999);
+                    doc.addEventListener("pt0", clearFallback);
+                    useAtomics ? loadSandbox(1) : nav.serviceWorker ? nav.serviceWorker.register(libPath + (config.swPath || "partytown-sw.js"), {
+                        scope: libPath
+                    }).then((function(swRegistration) {
+                        if (swRegistration.active) {
+                            loadSandbox();
+                        } else if (swRegistration.installing) {
+                            swRegistration.installing.addEventListener("statechange", (function(ev) {
+                                "activated" == ev.target.state && loadSandbox();
+                            }));
+                        } else {
+                            console.warn(swRegistration);
+                        }
+                    }), console.error) : fallback();
+                }
+            } else {
+                console.warn('Partytown config.lib url must start with "/"');
+            }
+        }
+    }
+    function loadSandbox(isAtomics) {
+        sandbox = doc.createElement(isAtomics ? "script" : "iframe");
+        win._pttab = Date.now();
+        if (!isAtomics) {
+            sandbox.style.display = "block";
+            sandbox.style.width = "0";
+            sandbox.style.height = "0";
+            sandbox.style.border = "0";
+            sandbox.style.visibility = "hidden";
+            sandbox.setAttribute("aria-hidden", !0);
+        }
+        sandbox.src = libPath + "partytown-" + (isAtomics ? "atomics.js?v=0.10.2-dev1727590485751" : "sandbox-sw.html?" + win._pttab);
+        doc.querySelector(config.sandboxParent || "body").appendChild(sandbox);
+    }
+    function fallback(i, script) {
+        console.warn("Partytown script fallback");
+        clearFallback();
+        top == win && (config.forward || []).map((function(forwardProps) {
+            const [property] = resolvePartytownForwardProperty(forwardProps);
+            delete win[property.split(".")[0]];
+        }));
+        for (i = 0; i < scripts.length; i++) {
+            script = doc.createElement("script");
+            script.innerHTML = scripts[i].innerHTML;
+            script.nonce = config.nonce;
+            doc.head.appendChild(script);
+        }
+        sandbox && sandbox.parentNode.removeChild(sandbox);
+    }
+    function clearFallback() {
+        clearTimeout(timeout);
+    }
+    config = win.partytown || {};
+    top == win && (config.forward || []).map((function(forwardProps) {
+        const [property, {preserveBehavior: preserveBehavior}] = resolvePartytownForwardProperty(forwardProps);
+        mainForwardFn = win;
+        property.split(".").map((function(_, i, forwardPropsArr) {
+            mainForwardFn = mainForwardFn[forwardPropsArr[i]] = i + 1 < forwardPropsArr.length ? mainForwardFn[forwardPropsArr[i]] || (propertyName => arrayMethods.includes(propertyName) ? [] : {})(forwardPropsArr[i + 1]) : (() => {
+                let originalFunction = null;
+                if (preserveBehavior) {
+                    const {methodOrProperty: methodOrProperty, thisObject: thisObject} = ((window, properties) => {
+                        let thisObject = window;
+                        for (let i = 0; i < properties.length - 1; i += 1) {
+                            thisObject = thisObject[properties[i]];
+                        }
+                        return {
+                            thisObject: thisObject,
+                            methodOrProperty: properties.length > 0 ? thisObject[properties[properties.length - 1]] : void 0
+                        };
+                    })(win, forwardPropsArr);
+                    "function" == typeof methodOrProperty && (originalFunction = (...args) => methodOrProperty.apply(thisObject, ...args));
+                }
+                return function() {
+                    let returnValue;
+                    originalFunction && (returnValue = originalFunction(arguments));
+                    (win._ptf = win._ptf || []).push(forwardPropsArr, arguments);
+                    return returnValue;
+                };
+            })();
+        }));
+    }));
+    if ("complete" == doc.readyState) {
+        ready();
+    } else {
+        win.addEventListener("DOMContentLoaded", ready);
+        win.addEventListener("load", ready);
+    }
+}(window, document, navigator, top, window.crossOriginIsolated);
\ No newline at end of file
Index: build/partytown-atomics.js
===================================================================
--- build/partytown-atomics.js	(revision 3189893)
+++ build/partytown-atomics.js	(working copy)
@@ -1 +1,2 @@
-(e=>{const t=()=>{},r=e=>e.length,n=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},i=(e,t)=>e.startsWith(t),s=e=>!(i(e,"webkit")||i(e,"toJSON")||i(e,"constructor")||i(e,"toString")||i(e,"_")&&!["__","_n","_x","_nx"].includes(e)),o=e=>11===e.nodeType&&e.host?"#s":e.nodeName,a=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),c={Anchor:"a",DList:"dl",Image:"img",OList:"ol",Paragraph:"p",Quote:"q",TableCaption:"caption",TableCell:"td",TableCol:"colgroup",TableRow:"tr",TableSection:"tbody",UList:"ul"},l={Graphics:"g",SVG:"svg"},u={preserveBehavior:!1},p=Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})()),h=Symbol(),d=Symbol(),m=new Map,g=new Map,f={},y=new WeakMap,v=(e,t)=>{if(e)return(t=y.get(e))||(t=e[h])||b(e,t=a()),t},w=(e,t,r,n,i)=>{if((r=f[e])&&r.U){if(e===t)return r.U;if(n=r.U.document,"d"===(i=t.split(".").pop()))return n;if("e"===i)return n.documentElement;if("h"===i)return n.head;if("b"===i)return n.body}return m.get(t)},b=(e,t,r)=>{e&&(m.set(t,e),e[h]=t,e[d]=r=Date.now(),r>S+5e3&&(m.forEach(((e,t)=>{e[d]<S&&e.nodeType&&!e.isConnected&&m.delete(t)})),S=r))};let S=0;const E=e.parent,T=document.implementation.createHTMLDocument(),R=E.partytown||{},M=(R.lib||"/~partytown/")+"",x=(e,t,r)=>{const n=((e,t)=>{return r=e,n={value:t},Object.defineProperty(r,"name",{...n,configurable:!0});var r,n})(class extends f[e].U.HTMLElement{},r[0]);return"connectedCallback,disconnectedCallback,attributeChangedCallback,adoptedCallback".split(",").map((r=>n.prototype[r]=function(...n){t.postMessage([15,e,v(this),r,n])})),n.observedAttributes=r[1],n},$=(e,t,r,s,a,c)=>void 0!==t&&(s=typeof t)?"string"===s||"number"===s||"boolean"===s||null==t?[0,t]:"function"===s?[6]:(r=r||new Set)&&Array.isArray(t)?r.has(t)?[1,[]]:r.add(t)&&[1,t.map((t=>$(e,t,r)))]:"object"===s?C(t)?[14,{name:t.name,message:t.message,stack:t.stack}]:""===(a=n(t))?[2,{}]:"Window"===a?[3,[e,e]]:"HTMLCollection"===a||"NodeList"===a?[7,Array.from(t).map((t=>$(e,t,r)[1]))]:a.endsWith("Event")?[5,L(e,t,r)]:"CSSRuleList"===a?[12,Array.from(t).map(A)]:i(a,"CSS")&&a.endsWith("Rule")?[11,A(t)]:"CSSStyleDeclaration"===a?[13,L(e,t,r)]:"Attr"===a?[10,[t.name,t.value]]:t.nodeType?[3,[e,v(t),o(t),c]]:[2,L(e,t,r,!0,!0)]:void 0:t,L=(e,t,r,i,o,a,c,l)=>{if(a={},!r.has(t))for(c in r.add(t),t)s(c)&&(l="path"===c&&n(t).endsWith("Event")?t.composedPath():t[c],(i||"function"!=typeof l)&&(o||""!==l)&&(a[c]=$(e,l,r)));return a},A=e=>{let t,r={};for(t in e)P.includes(t)&&(r[t]=String(e[t]));return r};let N=null;const C=t=>{var r;return N=(null===(r=e.top)||void 0===r?void 0:r.Error)||N,t instanceof N},O=(t,r,n,i)=>r?(n=r[0],i=r[1],0===n?i:4===n?j(t,i):1===n?i.map((e=>O(t,e))):3===n?w(i[0],i[1]):5===n?U(I(t,i)):2===n?I(t,i):8===n?i:9===n?new e[r[2]](i):void 0):void 0,j=(e,{V:t,w:r,L:n},i)=>((i=g.get(n))||(i=function(...i){e.postMessage([9,{V:t,w:r,L:n,R:$(t,this),b:$(t,i)}])},g.set(n,i)),i),U=e=>new("detail"in e?CustomEvent:Event)(e.type,e),I=(e,t,r,n)=>{for(n in r={},t)r[n]=O(e,t[n]);return r},P="cssText,selectorText,href,media,namespaceURI,prefix,name,conditionText".split(","),_=async(e,t)=>{let n,i,s,o,a,c,l={F:t.F},u=r(t.Q),p=0;for(;p<u;p++)try{c=p===u-1,n=t.Q[p],i=n.V,s=n.a,!f[i]&&i.startsWith("f_")&&await new Promise((e=>{let t=0,r=()=>{f[i]||t++>1e3?e():requestAnimationFrame(r)};r()})),1===s[0]&&s[1]in f[i].U?b(new f[i].U[s[1]](...O(e,s[2])),n.w):(o=w(i,n.w),o?(a=V(e,i,o,s,c,n.r),n.d&&("string"==typeof n.d?b(a,n.d):f[n.d.V]={V:n.d.V,U:{document:a}}),"object"==typeof(h=a)&&h&&h.then&&(a=await a,c&&(l.z=!0)),c&&(l.M=$(i,a,void 0,void 0,void 0,n.w))):l.p=n.w+" not found")}catch(e){c?l.p=String(e.stack||e):console.error(e)}var h;return l},V=(e,t,i,s,o,a)=>{let c,l,u,p,h,d=0,m=r(s);for(;d<m;d++){l=s[d],c=s[d+1],u=s[d-1];try{if(!Array.isArray(c))if("string"==typeof l||"number"==typeof l){if(d+1===m&&a)return h={},a.map((e=>h[e]=i[e])),h;i=i[l]}else{if(0===c)return void(i[u]=O(e,l));if("function"==typeof i[u]&&(p=O(e,l),"define"===u&&"CustomElementRegistry"===n(i)&&(p[1]=x(t,e,p[1])),"insertRule"===u&&p[1]>r(i.cssRules)&&(p[1]=r(i.cssRules)),i=i[u].apply(i,p),"play"===u))return Promise.resolve()}}catch(e){if(o)throw e;console.debug(e)}}return i},H=(e,t)=>{let n,i,s,o=t.V,a=t.U,c=a.document,l='script[type="text/partytown"]:not([data-ptid]):not([data-pterror])',h=l+":not([async]):not([defer])";c&&c.body?(n=c.querySelector(h),n||(n=c.querySelector(l)),n?(n.dataset.ptid=i=v(n,o),s={V:o,w:i},n.src?(s.S=n.src,s.H=n.dataset.ptsrc||n.src):s.j=n.innerHTML,e.postMessage([7,s])):(t.x||(t.x=1,((e,t,n)=>{let i,s,o=n._ptf,a=(n.partytown||{}).forward||[],c=(r,n)=>e.postMessage([10,{V:t,q:r,b:$(t,Array.from(n))}]);if(n._ptf=void 0,a.map((e=>{const[t,{preserveBehavior:i}]=(e=>{if("string"==typeof e)return[e,u];const[t,r=u]=e;return[t,{...u,...r}]})(e);s=n,t.split(".").map(((e,t,o)=>{var a;s=s[o[t]]=t+1<r(o)?s[o[t]]||(a=o[t+1],p.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:t,thisObject:r}=((e,t)=>{let r=e;for(let e=0;e<t.length-1;e+=1)r=r[t[e]];return{thisObject:r,methodOrProperty:t.length>0?r[t[t.length-1]]:void 0}})(n,o);"function"==typeof t&&(e=(...e)=>t.apply(r,...e))}return(...t)=>{let r;return e&&(r=e(t)),c(o,t),r}})()}))})),o)for(i=0;i<r(o);i+=2)c(o[i],o[i+1])})(e,o,a),c.dispatchEvent(new CustomEvent("pt0"))),e.postMessage([8,o]))):requestAnimationFrame((()=>H(e,t)))},B=(e,t,r)=>{if(!y.has(r)){y.set(r,t);const n=r.document,i=r.history,s=y.get(r.parent);let o=!1;const a=[],c=e=>{o?e():a.push(e)},l=()=>{e.postMessage([5,{V:t,J:s,S:n.baseURI,T:n.visibilityState}]),setTimeout((()=>{o=!0,a.forEach((e=>{e()}))}))},u=i.pushState.bind(i),p=i.replaceState.bind(i),h=(r,i,s,o)=>()=>{e.postMessage([13,{V:t,type:r,state:i,url:n.baseURI,newUrl:s,oldUrl:o}])};i.pushState=(e,t,r)=>{u(e,t,r),c(h(0,e,null==r?void 0:r.toString()))},i.replaceState=(e,t,r)=>{p(e,t,r),c(h(1,e,null==r?void 0:r.toString()))},r.addEventListener("popstate",(e=>{c(h(2,e.state))})),r.addEventListener("hashchange",(e=>{c(h(3,{},e.newURL,e.oldURL))})),r.addEventListener("ptupdate",(()=>{H(e,f[t])})),n.addEventListener("visibilitychange",(()=>e.postMessage([14,t,n.visibilityState]))),f[t]={V:t,U:r},"complete"===n.readyState?l():r.addEventListener("load",l)}},k=()=>{const e=Object.getOwnPropertyNames(E).map((e=>((e,t,r,n)=>{if(r=t.match(/^(HTML|SVG)(.+)Element$/))return n=r[2],"S"==t[0]?e.createElementNS("http://www.w3.org/2000/svg",l[n]||n.slice(0,2).toLowerCase()+n.slice(2)):e.createElement(c[n]||n)})(T,e))).filter((e=>e)).map((e=>[e]));return W(e,[])},W=(e,t)=>{const r=new Set(["Object"]);return e.filter((e=>e[0])).map((e=>{const t=e[0],r=e[1],i=n(t);return[i,E[i].prototype,t,r]})).map((([e,n,i,s])=>F(r,t,e,n,i,s))),t},D=(e,t,r)=>{let n=[],i=[e,"Object",n];for(r in t)J(n,t,r);return i},F=(e,t,r,i,s,a)=>{if(!e.has(r)){e.add(r);const c=Object.getPrototypeOf(i),l=n(c),u=[],p=Object.getOwnPropertyDescriptors(i);F(e,t,l,c,s,a);for(const e in p)J(u,s,e);t.push([r,l,u,a,o(s)])}},J=(e,t,r,i,o,a)=>{try{s(r)&&isNaN(r[0])&&"all"!==r&&("function"==(o=typeof(i=t[r]))?(String(i).includes("[native")||Object.getPrototypeOf(t)[r])&&e.push([r,5]):"object"===o&&null!=i?"Object"!==(a=n(i))&&"Function"!==a&&self[a]&&e.push([r,i.nodeType||a]):"symbol"!==o&&(r.toUpperCase()===r?e.push([r,6,i]):e.push([r,6])))}catch(e){console.warn(e)}},q=(e,r)=>void 0!==e[r]?new e[r](t):0;let G;(async e=>{const t=new SharedArrayBuffer(1073741824),r=new Int32Array(t);return(e,n)=>{const i=n[0],s=n[1];if(0===i){const r=(()=>{const e=T.createElement("i"),t=T.createTextNode(""),r=T.createComment(""),n=T.createDocumentFragment(),i=T.createElement("p").attachShadow({mode:"open"}),s=q(E,"IntersectionObserver"),o=q(E,"MutationObserver"),a=q(E,"ResizeObserver"),c=E.performance,l=E.screen,u=[[E.history],[c],[c.navigation],[c.timing],[l],[l.orientation],[E.visualViewport],[s,12],[o,12],[a,12],[t],[r],[n],[i],[e],[e.attributes],[e.classList],[e.dataset],[e.style],[T],[T.doctype]],p=[D("Window",E),D("Node",t)],h=function(e){return JSON.stringify(e,((e,t)=>("function"==typeof t&&(t=String(t)).startsWith(e+"(")&&(t="function "+t),"loadScriptsOnMainThread"===e&&(t=t.map((e=>Array.isArray(e)?e:["string"==typeof e?"string":"regexp","string"==typeof e?e:e.source]))),t)))}(R),d={i:h,v:W(u,p),C:new URL(M,E.location)+"",I:origin,$tabId$:E._pttab};return((e,t,r)=>{void 0!==t[r]&&e.push([r,"Object",Object.keys(t[r].prototype).map((e=>[e,6])),12])})(d.v,E,"IntersectionObserverEntry"),d})();r.P=t,e.postMessage([1,r])}else 2===n[0]?e.postMessage([3,k()]):11===i?((e,t)=>{_(G,e).then((e=>{const t=JSON.stringify(e),n=t.length;for(let e=0;e<n;e++)r[e+1]=t.charCodeAt(e);r[0]=n,Atomics.notify(r,0)}))})(s):((e,t,r)=>{4===t[0]?B(e,a(),E):(r=f[t[1]])&&(7===t[0]?requestAnimationFrame((()=>H(e,r))):6===t[0]&&((e,t,r,n,i)=>{(i=t.U.document.querySelector(`[data-ptid="${r}"]`))&&(n?i.dataset.pterror=n:i.type+="-x",delete i.dataset.ptid),H(e,t)})(e,r,t[2],t[3]))})(e,n)}})().then((e=>{e&&(G=new Worker(URL.createObjectURL(new Blob(['/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */\n(e=>{const t=Symbol(),r=Symbol(),n=Symbol(),i=Symbol(),s=Symbol(),o=Symbol(),a=Symbol(),c=Symbol(),l=new Map,$={},d=new WeakMap,u=[],h={},p={},g=new Map,m=new Map,f="about:blank",w=e=>e.split(","),y=e=>{if(e=h.C+e,new URL(e).origin!=location.origin)throw"Invalid "+e;return e},v=w("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft"),S=w("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling"),b=w("insertBefore,remove,removeChild,replaceChild"),I=w("className,width,height,hidden,innerHTML,innerText,textContent,text"),M=w("setAttribute,setAttributeNS,setProperty"),T=w("addEventListener,dispatchEvent,removeEventListener"),E=T.concat(M,w("add,observe,remove,unobserve")),N=/^[A-Z_]([A-Z0-9-]*[A-Z0-9])?$/,x=()=>{},L=e=>e.length,C=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},R=[],O=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),A="text/partytown",P=(e,t,r)=>Object.defineProperty(e,t,{...r,configurable:!0}),W=(e,t)=>P(e,"name",{value:t}),H=(e,t,r)=>P(e.prototype,t,r),j=(e,t)=>Object.defineProperties(e.prototype,t),k=(e,t,r)=>H(e,t,{value:r,writable:!0});function D(e,t){var r,n;return null!==(n=null===(r=e.loadScriptsOnMainThread)||void 0===r?void 0:r.map((([e,t])=>new RegExp("string"===e?t.replace(/[.*+?^${}()|[\\]\\\\]/g,"\\\\$&"):t))).some((e=>e.test(t))))&&void 0!==n&&n}Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})());const U=(e,t)=>t in e[o],_=(e,t)=>e[o][t],B=(e,t,r)=>e[o][t]=r,F=(e,t,r,n,i,s)=>{if(!(i=l.get(t))&&r&&p[e]){const o=l.get(s||"");i=p[e].k(r,t,n,o),l.set(t,i)}return i},z=(e,t)=>k(e,"nodeType",t),q=(e,t)=>t.map((t=>H(e,t,{get(){let e=V(this,t),r=m.get(e);return r||(r=$e(this,[t]),m.set(e,r)),r}}))),V=(e,n,i)=>[e[t],e[r],n,...(i||R).map((e=>String(e&&e[t]?e[r]:e)))].join("."),X=(e,t)=>w(t).map((t=>H(e,t,{get(){return U(this,t)||B(this,t,$e(this,[t])),_(this,t)},set(e){_(this,t)!==e&&de(this,[t],e),B(this,t,e)}}))),Z=e=>v.map((t=>H(e,t,{get(){const e=g.get(V(this,t));if("number"==typeof e)return e;const r=$e(this,[t],v);return r&&"object"==typeof r?(Object.entries(r).map((([e,t])=>g.set(V(this,e),t))),r[t]):r}}))),G=(e,t)=>t.map((t=>{e.prototype[t]=function(...e){let r=V(this,t,e),n=g.get(r);return n||(n=ue(this,[t],e),g.set(r,n)),n}})),J=(e,n,i,s,o)=>{return void 0!==i&&(o=typeof i)?"string"===o||"boolean"===o||"number"===o||null==i?[0,i]:"function"===o?[4,{V:e,w:n,L:(a=i,(c=d.get(a))||(d.set(a,c=O()),$[c]=a),c)}]:(s=s||new Set)&&Array.isArray(i)?s.has(i)?[1,[]]:s.add(i)&&[1,i.map((t=>J(e,n,t,s)))]:"object"===o?i[r]?[3,[i[t],i[r]]]:i instanceof Event?[5,K(e,n,i,!1,s)]:Y&&i instanceof TrustedHTML?[0,i.toString()]:i instanceof ArrayBuffer?[8,i]:ArrayBuffer.isView(i)?[9,i.buffer,C(i)]:[2,K(e,n,i,!0,s)]:void 0:i;var a,c},Y="undefined"!=typeof TrustedHTML,K=(e,t,r,n,i,s,o,a)=>{if(s={},!i.has(r))for(o in i.add(r),r)a=r[o],(n||"function"!=typeof a)&&(s[o]=J(e,t,a,i));return s},Q=(e,n)=>e?J(e[t],e[r],n):[0,n],ee=(e,t,r,n,i,s,o,a)=>{if(n){if(i=n[0],s=n[1],0===i||11===i||12===i)return s;if(4===i)return re(r,s);if(6===i)return e&&r.length>0?(...t)=>ue(p[e].U,r,t,1):x;if(3===i)return te(s);if(7===i)return new ie(s.map(te));if(10===i)return new se(s);if(1===i)return s.map((n=>ee(e,t,r,n)));if(14===i)return new ne(s);for(a in o={},s)o[a]=ee(e,t,[...r,a],s[a]);if(13===i)return new p[e].U.CSSStyleDeclaration(e,t,r,o);if(5===i){if("message"===o.type&&o.origin){let e,t=JSON.stringify(o.data),r=u.find((e=>e.m===t));r&&(e=p[r.V],e&&(o.source=e.U,o.origin=e.E.origin))}return new Proxy(new Event(o.type,o),{get:(e,t)=>t in o?o[t]:"function"==typeof e[String(t)]?x:e[String(t)]})}if(2===i)return o}},te=([e,t,r,n])=>t===e&&p[e]?p[e].U:F(e,t,r,void 0,void 0,n),re=(e,{V:t,w:r,G:n,L:i})=>($[i]||d.set($[i]=function(...i){const s=F(t,r,n);return ue(s,e,i)},i),$[i]);class ne extends Error{constructor(e){super(e.message),this.name=e.name,this.message=e.message,this.stack=e.stack}}class ie{constructor(e){(this._=e).map(((e,t)=>this[t]=e))}entries(){return this._.entries()}forEach(e,t){this._.map(e,t)}item(e){return this[e]}keys(){return this._.keys()}get length(){return L(this._)}values(){return this._.values()}[Symbol.iterator](){return this._[Symbol.iterator]()}}const se=class{constructor(e){this.name=e[0],this.value=e[1]}get nodeName(){return this.name}get nodeType(){return 2}},oe=(e,t,r)=>console.warn(`Partytown unable to ${e} cross-origin ${t}: `+r.E),ae=[],ce=(e,n,i,o,a,c)=>{if(e[s]){if(ae.push({V:e[t],w:e[r],a:[...e[s],...n],d:o,r:a}),3===i)h.K([12,{F:O(),Q:[...ae]}],c?[c instanceof ArrayBuffer?c:c.buffer]:void 0),ae.length=0;else if(1===i)return le(!0);h.c=setTimeout(le,20)}},le=e=>{if(clearTimeout(h.c),L(ae)){const t=ae[L(ae)-1],r={F:`${O()}.${h.$tabId$}`,Q:[...ae]};if(ae.length=0,e){const e=((e,t)=>{const r=e.P,n=new Int32Array(r);Atomics.store(n,0,0),e.K([11,t]),Atomics.wait(n,0,0);let i=Atomics.load(n,0),s="",o=0;for(;o<i;o++)s+=String.fromCharCode(n[o+1]);return JSON.parse(s)})(h,r),n=e.z,i=ee(t.V,t.w,t.a,e.M);if(e.p){if(n)return Promise.reject(e.p);throw new Error(e.p)}return n?Promise.resolve(i):i}h.K([12,r])}},$e=(e,t,r,n)=>h.i.get&&(n=h.i.get(pe(e,t)))!==a?n:n=ce(e,t,1,void 0,r),de=(e,t,r,n)=>{if(h.i.set){if((n=h.i.set({value:r,prevent:c,...pe(e,t)}))===c)return;n!==a&&(r=n)}I.some((e=>t.includes(e)))&&(g.clear(),t[t.length-1]),t=[...t,Q(e,r),0],ce(e,t,2)},ue=(e,t,r,n,i,s,o,c)=>h.i.apply&&(o=h.i.apply({args:r,...pe(e,t)}))!==a?o:(c=t[L(t)-1],t=[...t,Q(e,r)],n=n||(E.includes(c)?2:1),"setAttribute"===c&&U(e,r[0])?B(e,r[0],r[1]):b.includes(c)?(g.clear(),m.clear()):M.includes(c)&&(n=2,g.clear()),o=ce(e,t,n,i,void 0,s)),he=(e,t,r)=>{ce(e,[1,t,Q(e,r)],1)},pe=(e,r)=>({name:r.join("."),continue:a,nodeName:e[n],constructor:C(e),instance:e,window:p[e[t]].U}),ge=(e,t,r)=>{let n={getItem(n){if(r.A)return ue(e,[t,"getItem"],[n],1);oe("get",t,r)},setItem(n,i){r.A?ue(e,[t,"setItem"],[n,i],1):oe("set",t,r)},removeItem(n){r.A?ue(e,[t,"removeItem"],[n],1):oe("remove",t,r)},key(n){if(r.A)return ue(e,[t,"key"],[n],1);oe("key",t,r)},clear(){r.A?ue(e,[t,"clear"],R,1):oe("clear",t,r)},get length(){if(r.A)return $e(e,[t,"length"]);oe("length",t,r)}};e[t]=new Proxy(n,{get:(e,t)=>Reflect.has(e,t)?Reflect.get(e,t):e.getItem(t),set:(e,t,r)=>(e.setItem(t,r),!0),has:(e,t)=>!!Reflect.has(e,t)||"string"==typeof t&&null!==e.getItem(t),deleteProperty:(e,t)=>(e.removeItem(t),!0)})},me=(e,t,r)=>{e[r]=W(class extends t{constructor(e,t,r,i){return super(e,t,r,i||{}),new Proxy(this,{get:(e,t)=>e[t]?e[t]:(e[t]||"string"!=typeof t||e[n][t]||(e[n][t]=$e(e,[t])),e[n][t]),set:(e,t,r)=>(e[n][t]=r,de(e,[t],r),g.clear(),!0)})}setProperty(...e){this[n][e[0]]=e[1],ue(this,["setProperty"],e,2),e[0],g.clear()}getPropertyValue(e){return this[e]}removeProperty(e){let t=this[n][e];return ue(this,["removeProperty"],[e],2),g.clear(),this[n][e]=void 0,t}},r)},fe=(e,t)=>{e[t]=W(class{constructor(e){this.ownerNode=e}get cssRules(){const e=this.ownerNode;return new Proxy({},{get(t,r){const n=String(r);return"item"===n?t=>ye(e,t):"length"===n?we(e).length:isNaN(n)?t[r]:ye(e,n)}})}insertRule(e,t){const r=we(this.ownerNode);return(t=void 0===t?0:t)>=0&&t<=r.length&&(ue(this.ownerNode,["sheet","insertRule"],[e,t],2),r.splice(t,0,0)),this.ownerNode,g.clear(),t}deleteRule(e){ue(this.ownerNode,["sheet","deleteRule"],[e],2),we(this.ownerNode).splice(e,1),this.ownerNode,g.clear()}get type(){return"text/css"}},t);const r={sheet:{get(){return new e[t](this)}}};j(e.HTMLStyleElement,r)},we=(e,t)=>((t=_(e,2))||(t=$e(e,["sheet","cssRules"]),B(e,2,t)),t),ye=(e,t,r)=>(0===(r=we(e))[t]&&(r[t]=$e(e,["sheet","cssRules",parseInt(t,10)])),r[t]),ve="0.10.2-dev1727590485751",Se=(e,t,r,n,i)=>{try{e.l=t,be(e,r)}catch(e){console.error(r,e),i=String(e.stack||e)}return e.l="",i},be=(e,t,r)=>{e.N=1;let n=(e=>e.replace(/([a-zA-Z0-9_$\\.\\\'\\"\\`])?(\\.\\.\\.)?this(?![a-zA-Z0-9_$:])/g,((e,t,r)=>{const n=(t||"")+(r||"");return null!=t?n+"this":n+"(thi$(this)?window:this)"})))(t);t=`with(this){${n.replace(/\\/\\/# so/g,"//Xso")}\\n;function thi$(t){return t===this}};${(h.i.globalFns||[]).filter((e=>/[a-zA-Z_$][0-9a-zA-Z_$]*/.test(e))).map((e=>`(typeof ${e}==\'function\'&&(this.${e}=${e}))`)).join(";")};`+(r?"\\n//# sourceURL="+r:""),e.A||(t=t.replace(/.postMessage\\(/g,`.postMessage(\'${e.V}\',`)),new Function(t).call(e.U),e.N=0},Ie=(e,t,r)=>{(r=_(e,t))&&setTimeout((()=>r.map((e=>e({type:t})))))},Me=(e,t)=>{for(t=e.E;!t.host&&(t=(e=p[e.J]).E,e.V!==e.J););return t},Te=(e,t,r,n,i,s)=>(n=Me(e,n),i=new URL(t||"",n),r&&h.i.resolveUrl&&(s=h.i.resolveUrl(i,n,r))?s:i),Ee=(e,t,r)=>Te(e,t,r)+"",Ne=(e,t)=>{const r=Me(e),n=new URL(t||"",r);if(h.i.resolveSendBeaconRequestParameters){const e=h.i.resolveSendBeaconRequestParameters(n,r);if(e)return e}return{}},xe=()=>`<script src="${y("partytown.js?v="+ve)}"><\\/script>`,Le=e=>class{constructor(){this.s="",this.l=[],this.e=[],this.style={}}get src(){return this.s}set src(t){this.s=t,fetch(Ee(e,t,"image"),{mode:"no-cors",credentials:"include",keepalive:!0}).then((e=>{e.ok||0===e.status?this.l.map((e=>e({type:"load"}))):this.e.map((e=>e({type:"error"})))}),(()=>this.e.forEach((e=>e({type:"error"})))))}addEventListener(e,t){"load"===e&&this.l.push(t),"error"===e&&this.e.push(t)}removeEventListener(e,t){"load"===e&&(this.l=this.l.filter((e=>e!==t))),"error"===e&&(this.e=this.e.filter((e=>e!==t)))}get onload(){return this.l[0]}set onload(e){this.l=[e]}get onerror(){return this.e[0]}set onerror(e){this.e=[e]}},Ce={addEventListener:{value(...e){const t=e[0],r=_(this,t)||[];r.push(e[1]),B(this,t,r)}},async:{get:x,set:x},defer:{get:x,set:x},onload:{get(){let e=_(this,"load");return e&&e[0]||null},set(e){B(this,"load",e?[e]:null)}},onerror:{get(){let e=_(this,"error");return e&&e[0]||null},set(e){B(this,"error",e?[e]:null)}},getAttribute:{value(e){return"src"===e?this.src:ue(this,["getAttribute"],[e])}},setAttribute:{value(e,t){Re.includes(e)?this[e]=t:ue(this,["setAttribute"],[e,t])}}},Re=w("src,type"),Oe=(e,t)=>{const r={innerHTML:Ae,innerText:Ae,src:{get(){return _(this,4)||""},set(e){const r=Ee(t,e,null),n=h.i;e=Ee(t,e,"script"),B(this,4,e),de(this,["src"],e),r!==e&&de(this,["dataset","ptsrc"],r),this.type&&D(n,e)&&de(this,["type"],"text/javascript")}},text:Ae,textContent:Ae,type:{get(){return $e(this,["type"])},set(e){Pe(e)||(B(this,5,e),de(this,["type"],e))}},...Ce};j(e,r)},Ae={get(){const e=$e(this,["type"]);if(Pe(e)){const e=_(this,3);if(e)return e}return $e(this,["innerHTML"])||""},set(e){B(this,3,e)}},Pe=e=>!e||"text/javascript"===e,We=(e,i,s)=>{const o=h.i,a=W(class extends s{appendChild(e){return this.insertBefore(e,null)}get href(){}set href(e){}insertBefore(e,s){const a=e[t]=this[t],c=e[r],l=e[n],$="SCRIPT"===l,d="IFRAME"===l;if($){const t=_(e,3),r=_(e,5);if(t){if(Pe(r)){const r=e.id;if(r&&D(o,r))de(e,["type"],"text/javascript");else{const r=Se(i,c,t,0,""),n=r?"pterror":"ptid",s=r||c;de(e,["type"],A+"-x"),de(e,["dataset",n],s)}}de(e,["innerHTML"],t)}}if(ue(this,["insertBefore"],[e,s],2),d){const t=_(e,0);if(t&&t.startsWith("javascript:")){const e=t.split("javascript:")[1];Se(i,c,e,0,"")}((e,t)=>{let r,n,i=0,s=()=>{p[e]&&p[e].x&&!p[e].y?(r=_(t,1)?"error":"load",n=_(t,r),n&&n.map((e=>e({type:r})))):i++>2e3?(n=_(t,"error"),n&&n.map((e=>e({type:"error"})))):setTimeout(s,9)};s()})(c,e)}return $&&(le(!0),h.K([7,a])),e}get nodeName(){return"#s"===this[n]?"#document-fragment":this[n]}get nodeType(){return 3}get ownerDocument(){return i.n}},"Node");q(a,w("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling")),e.Node=a},He=w("AUDIO,CANVAS,VIDEO"),je=w("Audio,MediaSource"),ke=(e,r,n)=>{j(e,{body:{get:()=>r.e},cookie:{get(){return r.A?$e(this,["cookie"]):(oe("get","cookie",r),"")},set(e){r.A&&de(this,["cookie"],e)}},createElement:{value(e){if(e=e.toUpperCase(),!N.test(e))throw e+" not valid";const r="IFRAME"===e,n=this[t],i=(r?"f_":"")+O();ue(this,["createElement"],[e],2,i);const s=F(n,i,e);if(r)Qe({V:i,J:n,S:f},!0).U.fetch=fetch,de(s,["srcdoc"],xe());else if("SCRIPT"===e){const e=_(s,5);Pe(e)&&de(s,["type"],A)}return s}},createElementNS:{value(e,r){const n=O(),i=F(this[t],n,r,e);return ue(this,["createElementNS"],[e,r],2,n),i}},createTextNode:{value(e){const r=this[t],n=O(),i=F(r,n,"#text");return ue(this,["createTextNode"],[e],2,n),i}},createEvent:{value:e=>new Event(e)},currentScript:{get(){return r.l?F(this[t],r.l,"SCRIPT"):null}},defaultView:{get:()=>n?null:r.U},documentElement:{get:()=>r.o},getElementsByTagName:{value(e){return"BODY"===(e=e.toUpperCase())?[r.e]:"HEAD"===e?[r.s]:ue(this,["getElementsByTagName"],[e])}},head:{get:()=>r.s},images:{get(){return $e(this,["images"])}},scripts:{get(){return $e(this,["scripts"])}},implementation:{get(){return{hasFeature:()=>!0,createHTMLDocument:e=>{const t=O();return ue(this,["implementation","createHTMLDocument"],[e],1,{V:t}),Qe({V:t,J:t,S:r.E+"",T:"hidden"},!0,!0).n}}}},location:{get:()=>r.E,set(e){r.E.href=e+""}},nodeType:{value:9},parentNode:{value:null},parentElement:{value:null},readyState:{value:"complete"},visibilityState:{get:()=>r.T||"visible"}}),X(e,"compatMode,referrer,forms")},De=(e,t)=>{j(e,{parentElement:{get(){return this.parentNode}},parentNode:{get:()=>t.o}})},Ue=(e,t)=>{j(e,{localName:{get(){return this[n].toLowerCase()}},namespaceURI:{get(){return this[i]||"http://www.w3.org/1999/xhtml"}},nodeType:{value:1},tagName:{get(){return this[n]}}}),q(e,S),X(e,"id"),Z(t),G(t,w("getClientRects,getBoundingClientRect"))},_e=(e,t)=>{const r={};w("hash,host,hostname,href,origin,pathname,port,protocol,search").map((e=>{r[e]={get(){let r,n=_(this,4);if("string"!=typeof n){if(r=$e(this,["href"]),""===r)return"protocol"===e?":":"";B(this,4,r),n=new URL(r)[e]}return Te(t,n,null)[e]},set(r){let n;if("href"===e)if((e=>{try{return new URL(e),!0}catch(e){return!1}})(r))n=new URL(r);else{const e=t.E.href;n=Te(t,e,null),n.href=new URL(r+"",n.href)}else n=Te(t,this.href,null),n[e]=r;B(this,4,n.href),de(this,["href"],n.href)}}})),j(e,r)},Be=(e,t)=>{const r={contentDocument:{get(){return Ve(this).n}},contentWindow:{get(){return Ve(this).U}},src:{get(){let e=_(this,0);return e&&e.startsWith("javascript:")?e:(e=Ve(this).E.href,e.startsWith("about:")?"":e)},set(e){if(e)if(e.startsWith("javascript:"))B(this,0,e);else if(!e.startsWith("about:")){let t,r=new XMLHttpRequest,n=Ve(this);n.E.href=e=Ee(n,e,"iframe"),n.y=1,n.A=h.I===n.E.origin,B(this,1,void 0),r.open("GET",e,!1),r.send(),t=r.status,t>199&&t<300?(de(this,["srcdoc"],`<base href="${e}">`+r.responseText.replace(ze,((e,t)=>{const r=[];let n,i=!1;for(;n=qe.exec(t);){let[e]=n;e.startsWith("type=")&&(i=!0,e=e.replace(/(application|text)\\/javascript/,A)),r.push(e)}return i||r.push(\'type="\'+A+\'"\'),`<script ${r.join(" ")}>`}))+xe()),le(!0),h.K([7,n.V])):(B(this,1,t),n.y=0)}}},...Ce};j(e,r)},Fe="((?:\\\\w|-)+(?:=(?:(?:\\\\w|-)+|\'[^\']*\'|\\"[^\\"]*\\")?)?)",ze=new RegExp(`<script\\\\s*((${Fe}\\\\s*)*)>`,"mg"),qe=new RegExp(Fe,"mg"),Ve=e=>{const n=e[r];return p[n]||Qe({V:n,J:e[t],S:$e(e,["src"])||f},!0),p[n]},Xe=e=>{const t=(e,t)=>{const{a:r,b:n,c:i,d:s,e:o,f:a}=ue(e,[t],R);return new DOMMatrixReadOnly([r,n,i,s,o,a])},r={...e,getCTM:{value:function(){return t(this,"getCTM")}},getScreenCTM:{value:function(){return t(this,"getScreenCTM")}}};j(e,r)},Ze=(e,t)=>{e.NamedNodeMap=W(class extends t{constructor(e,t,r){return super(e,t,r),new Proxy(this,{get(e,t){const r=Je[t];return r?r.bind(e,[t]):$e(e,[t])},set(e,t,r){if(Je[t])throw new Error("Can\'t set read-only property: "+String(t));return de(e,[t],r),!0}})}},"NamedNodeMap")};function Ge(e,...t){return ue(this,e,t,1)}const Je={getNamedItem:Ge,getNamedItemNS:Ge,item:Ge,removeNamedItem:Ge,removeNamedItemNS:Ge,setNamedItem:Ge,setNamedItemNS:Ge},Ye=(a,c,l,$,d,g)=>{let m,v,b,I;const M=class{constructor(e,c,l,$,d){this[t]=e||a,this[r]=c||m||O(),this[s]=l||[],this[n]=$||v,this[i]=d||b,this[o]=I&&I[o]||{},m=v=b=void 0}},E=new(W(class extends URL{assign(){}reload(){}replace(){}},"Location"))(l),N=E.origin===h.I||E.origin===f,x=c===a,R={},A=()=>{let e,t,r=[];for(e in p)t=p[e],t.J!==a||t.B||r.push(t);return r},D=W(class extends M{constructor(){super(a,a),this.addEventListener=(...e)=>{"load"===e[0]?R.N&&setTimeout((()=>e[1]({type:"load"}))):ue(this,["addEventListener"],e,2)};let n,i,o=this,l=0,u=()=>{l||((h.u||(e.g=[$e,de,ue,he,j,O,t,r,s],h.t(y("partytown-media.js?v="+ve)),h.u=e.f,delete e.f),h.u)(M,J,R,o,je),l=1)},p={},f=(e,t,r,n)=>{He.includes(e)&&u();const i=p[e]?p[e]:e.includes("-")?p.UNKNOWN:p.I;return m=t,v=e,b=r,I=n,new i};var T,L;if(o.Window=D,o.name=name+a,We(o,R,M),(e=>{e.NodeList=W(ie,"NodeList")})(o),Ze(o,M),me(o,M,"CSSStyleDeclaration"),((e,t,r)=>{e[r]=W(class extends t{now(){return performance.now()}},r)})(o,M,"Performance"),((e,t)=>{const r="customElements",n=new Map;e[r]={define(i,s,o){n.set(i,s),t[i.toUpperCase()]=s;const a=[s.name,s.observedAttributes];ue(e,[r,"define"],[i,a,o])},get:t=>n.get(t)||ue(e,[r,"get"],[t]),whenDefined:t=>n.has(t)?Promise.resolve():ue(e,[r,"whenDefined"],[t]),upgrade:t=>ue(e,[r,"upgrade"],[t])}})(o,p),h.v.map((([e,t,n,i,c])=>{const l=Ke[e]?V:"EventTarget"===t?J:"Object"===t?M:o[t],$=o[e]=W(12===i?class extends M{constructor(...t){super(),he(this,e,t)}}:o[e]||class extends l{},e);c&&(p[c]=$),n.map((([e,t,n])=>{e in $.prototype||e in l.prototype||("string"==typeof t?H($,e,{get(){if(!U(this,e)){const n=this[r],i=[...this[s],e],c=o[t];c&&B(this,e,new c(a,n,i))}return _(this,e)},set(t){B(this,e,t)}}):5===t?k($,e,(function(...t){return ue(this,[e],t)})):t>0&&(void 0!==n?k($,e,n):H($,e,{get(){return $e(this,[e])},set(t){return de(this,[e],t)}})))}))})),w("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((t=>{delete D.prototype[t],t in o||(n=e[t],null!=n&&(o[t]="function"!=typeof n||n.toString().startsWith("class")?n:n.bind(e)))})),Object.getOwnPropertyNames(e).map((t=>{t in o||(o[t]=e[t])})),je.map((e=>P(o,e,{get:()=>(u(),o[e])}))),"trustedTypes"in e&&(o.trustedTypes=e.trustedTypes),Ue(o.Element,o.HTMLElement),ke(o.Document,R,g),T=o.DocumentFragment,z(T,11),q(T,S),_e(o.HTMLAnchorElement,R),L=o.HTMLFormElement,j(L,{}),X(L,"elements"),Be(o.HTMLIFrameElement),Oe(o.HTMLScriptElement,R),Xe(o.SVGGraphicsElement),De(o.HTMLHeadElement,R),De(o.HTMLBodyElement,R),((e,t)=>{j(e,{parentElement:{value:null},parentNode:{get:()=>t.n}})})(o.HTMLHtmlElement,R),fe(o,"CSSStyleSheet"),z(o.Comment,8),z(o.DocumentType,10),Object.assign(R,{V:a,J:c,U:new Proxy(o,{get:(e,t)=>{var r;if("string"!=typeof t||isNaN(t))return(null===(r=h.i.mainWindowAccessors)||void 0===r?void 0:r.includes(t))?$e(this,[t]):e[t];{let e=A()[t];return e?e.U:void 0}},has:()=>!0}),n:f("#document",a+".d"),o:f("HTML",a+".e"),s:f("HEAD",a+".h"),e:f("BODY",a+".b"),E:E,T:$,A:N,B:x,k:f}),o.requestAnimationFrame=e=>setTimeout((()=>e(performance.now())),9),o.cancelAnimationFrame=e=>clearTimeout(e),o.requestIdleCallback=(e,t)=>(t=Date.now(),setTimeout((()=>e({didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-t))})),1)),o.cancelIdleCallback=e=>clearTimeout(e),ge(o,"localStorage",R),ge(o,"sessionStorage",R),N||(o.indexeddb=void 0),d)i={},o.history={pushState(e){i=e},replaceState(e){i=e},get state(){return i},length:0},o.indexeddb=void 0;else{const e=o.history.pushState.bind(o.history),t=o.history.replaceState.bind(o.history);o.history.pushState=(t,r,n)=>{!1!==R.$propagateHistoryChange$&&e(t,r,n)},o.history.replaceState=(e,r,n)=>{!1!==R.$propagateHistoryChange$&&t(e,r,n)}}o.Worker=void 0}get body(){return R.e}get document(){return R.n}get documentElement(){return R.o}fetch(e,t){return e="string"==typeof e||e instanceof URL?String(e):e.url,fetch(Ee(R,e,"fetch"),t)}get frames(){return R.U}get frameElement(){return x?null:F(c,a,"IFRAME")}get globalThis(){return R.U}get head(){return R.s}get length(){return A().length}get location(){return E}set location(e){E.href=e+""}get Image(){return Le(R)}get navigator(){return(e=>{const t={sendBeacon:(t,r)=>{try{return fetch(Ee(e,t,null),{method:"POST",body:r,mode:"no-cors",keepalive:!0,...Ne(e,t)}),!0}catch(e){return console.error(e),!1}}};for(let e in navigator)t[e]=navigator[e];return new Proxy(t,{set:(e,t,r)=>(navigator[t]=r,!0),get:(t,r)=>Object.prototype.hasOwnProperty.call(t,r)?t[r]:$e(e.U,["navigator",r])})})(R)}get origin(){return E.origin}set origin(e){}get parent(){for(let e in p)if(p[e].V===c)return p[e].U;return R.U}postMessage(...e){p[e[0]]&&(L(u)>50&&u.splice(0,5),u.push({V:e[0],m:JSON.stringify(e[1])}),e=e.slice(1)),ue(this,["postMessage"],e,3)}get self(){return R.U}get top(){for(let e in p)if(p[e].B)return p[e].U;return R.U}get window(){return R.U}get XMLHttpRequest(){const e=XMLHttpRequest,t=String(e),r=W(class extends e{open(...e){e[1]=Ee(R,e[1],"xhr"),super.open(...e)}set withCredentials(e){h.i.allowXhrCredentials&&(super.withCredentials=e)}toString(){return t}},C(e));return r.prototype.constructor.toString=()=>t,r}},"Window"),V=class extends M{constructor(e,t,r,n){return super(e,t,r,n),new Proxy(this,{get:(e,t)=>$e(e,[t]),set:(e,t,r)=>(de(e,[t],r),!0)})}},J=class extends M{};return T.map((e=>J.prototype[e]=function(...t){return ue(this,[e],t,2)})),X(D,"devicePixelRatio"),Z(D),G(D,["getComputedStyle"]),new D,R},Ke={DOMStringMap:1,NamedNodeMap:1},Qe=({V:e,J:t,S:r,T:n},i,s)=>(p[e]||(p[e]=Ye(e,t,r,n,i,s)),h.K([7,e]),p[e]),et=[],tt=t=>{const r=t.data,n=r[0],i=r[1];if(h.x)if(7===n)(async e=>{let t,r=e.V,n=e.w,i=F(r,n,"SCRIPT"),s=e.j,o=e.S,a=e.H,c="",l=p[r],$=["text/jscript","text/javascript","text/x-javascript","application/javascript","application/x-javascript","text/ecmascript","text/x-ecmascript","application/ecmascript"];if(o)try{if(o=Te(l,o,"script")+"",B(i,4,o),t=await fetch(o),t.ok){let e=t.headers.get("content-type");$.some((t=>{var r,n,i;return null===(i=null===(r=null==e?void 0:e.toLowerCase)||void 0===r?void 0:(n=r.call(e)).includes)||void 0===i?void 0:i.call(n,t)}))&&(s=await t.text(),l.l=n,be(l,s,a||o)),Ie(i,"load")}else c=t.statusText,Ie(i,"error")}catch(e){console.error(e),c=String(e.stack||e),Ie(i,"error")}else s&&(c=Se(l,n,s,0,c));l.l="",h.K([6,r,n,c])})(i);else if(9===n)(({V:e,w:t,L:r,R:n,b:i})=>{if($[r])try{$[r].apply(ee(e,t,[],n),ee(e,t,[],i))}catch(e){console.error(e)}})(i);else if(10===n)(({V:e,q:t,b:r})=>{try{let n=p[e].U,i=0,s=L(t);for(;i<s;i++)i+1<s?n=n[t[i]]:n[t[i]].apply(n,ee(null,e,[],r))}catch(e){console.error(e)}})(i);else if(5===n)Qe(i);else if(8===n)p[i].x=1,p[i].y=0;else if(14===n)p[i].T=r[2];else if(13===n){const e=i.V,t=p[e];t.E.href=i.url,function(e,t,r){const n=t.U.history;switch(r.type){case 0:t.$propagateHistoryChange$=!1;try{n.pushState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0;break;case 1:t.$propagateHistoryChange$=!1;try{n.replaceState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0}}(i.V,t,i)}else 15===n&&((e,t,r,n,i)=>{const s=F(t,r);s&&"function"==typeof s[n]&&s[n].apply(s,i)})(...r);else 1===n?((t=>{const r=h.i=JSON.parse(t.i),n=t.I;h.t=importScripts.bind(e),h.v=t.v,h.C=t.C,h.I=n,h.K=postMessage.bind(e),h.P=t.P,h.$tabId$=t.$tabId$,e.importScripts=void 0,delete e.postMessage,delete e.WorkerGlobalScope,w("resolveUrl,resolveSendBeaconRequestParameters,get,set,apply").map((e=>{r[e]&&(r[e]=new Function("return "+r[e])())}))})(i),h.K([2])):3===n?(h.v=[...h.v,...i],h.x=1,h.K([4]),[...et].map(tt),et.length=0):et.push(t)};e.onmessage=tt,postMessage([0])})(self);\n'],{type:"text/javascript"})),{name:"Partytown 🎉"}),G.onmessage=t=>{const r=t.data;12===r[0]?_(G,r[1]):e(G,r)},E.addEventListener("pt1",(e=>B(G,v(e.detail.frameElement),e.detail))))}))})(window);
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+(e=>{const t=()=>{},r=e=>e.length,n=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},i=(e,t)=>e.startsWith(t),s=e=>!(i(e,"webkit")||i(e,"toJSON")||i(e,"constructor")||i(e,"toString")||i(e,"_")&&!["__","_n","_x","_nx"].includes(e)),o=e=>11===e.nodeType&&e.host?"#s":e.nodeName,a=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),c={Anchor:"a",DList:"dl",Image:"img",OList:"ol",Paragraph:"p",Quote:"q",TableCaption:"caption",TableCell:"td",TableCol:"colgroup",TableRow:"tr",TableSection:"tbody",UList:"ul"},l={Graphics:"g",SVG:"svg"},u={preserveBehavior:!1},p=Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})()),d=Symbol(),h=Symbol(),g=new Map,m=new Map,f={},y=new WeakMap,$=(e,t)=>{if(e)return(t=y.get(e))||(t=e[d])||v(e,t=a()),t},w=(e,t,r,n,i)=>{if((r=f[e])&&r.U){if(e===t)return r.U;if(n=r.U.document,"d"===(i=t.split(".").pop()))return n;if("e"===i)return n.documentElement;if("h"===i)return n.head;if("b"===i)return n.body}return g.get(t)},v=(e,t,r)=>{e&&(g.set(t,e),e[d]=t,e[h]=r=Date.now(),r>b+5e3&&(g.forEach(((e,t)=>{e[h]<b&&e.nodeType&&!e.isConnected&&g.delete(t)})),b=r))};let b=0;const S=e.parent,E=document.implementation.createHTMLDocument(),T=S.partytown||{},I=(T.lib||"/~partytown/")+"",R=(e,t,r)=>{const n=((e,t)=>{return r=e,n={value:t},Object.defineProperty(r,"name",{...n,configurable:!0});var r,n})(class extends f[e].U.HTMLElement{},r[0]);return"connectedCallback,disconnectedCallback,attributeChangedCallback,adoptedCallback".split(",").map((r=>n.prototype[r]=function(...n){t.postMessage([15,e,$(this),r,n])})),n.observedAttributes=r[1],n},M=(e,t,r,s,a,c)=>void 0!==t&&(s=typeof t)?"string"===s||"number"===s||"boolean"===s||null==t?[0,t]:"function"===s?[6]:(r=r||new Set)&&Array.isArray(t)?r.has(t)?[1,[]]:r.add(t)&&[1,t.map((t=>M(e,t,r)))]:"object"===s?L(t)?[14,{name:t.name,message:t.message,stack:t.stack}]:""===(a=n(t))?[2,{}]:"Window"===a?[3,[e,e]]:"HTMLCollection"===a||"NodeList"===a?[7,Array.from(t).map((t=>M(e,t,r)[1]))]:a.endsWith("Event")?[5,x(e,t,r)]:"CSSRuleList"===a?[12,Array.from(t).map(A)]:i(a,"CSS")&&a.endsWith("Rule")?[11,A(t)]:"CSSStyleDeclaration"===a?[13,x(e,t,r)]:"Attr"===a?[10,[t.name,t.value]]:t.nodeType?[3,[e,$(t),o(t),c]]:[2,x(e,t,r,!0,!0)]:void 0:t,x=(e,t,r,i,o,a,c,l)=>{if(a={},!r.has(t))for(c in r.add(t),t)s(c)&&(l="path"===c&&n(t).endsWith("Event")?t.composedPath():t[c],(i||"function"!=typeof l)&&(o||""!==l)&&(a[c]=M(e,l,r)));return a},A=e=>{let t,r={};for(t in e)U.includes(t)&&(r[t]=String(e[t]));return r};let N=null;const L=t=>{var r;return N=(null===(r=e.top)||void 0===r?void 0:r.Error)||N,t instanceof N},O=(t,r,n,i)=>r?(n=r[0],i=r[1],0===n?i:4===n?C(t,i):1===n?i.map((e=>O(t,e))):3===n?w(i[0],i[1]):5===n?j(P(t,i)):2===n?P(t,i):8===n?i:9===n?new e[r[2]](i):void 0):void 0,C=(e,{V:t,w:r,L:n},i)=>((i=m.get(n))||(i=function(...i){e.postMessage([9,{V:t,w:r,L:n,R:M(t,this),b:M(t,i)}])},m.set(n,i)),i),j=e=>new("detail"in e?CustomEvent:Event)(e.type,e),P=(e,t,r,n)=>{for(n in r={},t)r[n]=O(e,t[n]);return r},U="cssText,selectorText,href,media,namespaceURI,prefix,name,conditionText".split(","),_=async(e,t)=>{let n,i,s,o,a,c,l={F:t.F},u=r(t.Q),p=0;for(;p<u;p++)try{c=p===u-1,n=t.Q[p],i=n.V,s=n.a,!f[i]&&i.startsWith("f_")&&await new Promise((e=>{let t=0,r=()=>{f[i]||t++>1e3?e():requestAnimationFrame(r)};r()})),1===s[0]&&s[1]in f[i].U?v(new f[i].U[s[1]](...O(e,s[2])),n.w):(o=w(i,n.w),o?(a=H(e,i,o,s,c,n.r),n.d&&("string"==typeof n.d?v(a,n.d):f[n.d.V]={V:n.d.V,U:{document:a}}),"object"==typeof(d=a)&&d&&d.then&&(a=await a,c&&(l.z=!0)),c&&(l.M=M(i,a,void 0,void 0,void 0,n.w))):l.p=n.w+" not found")}catch(e){c?l.p=String(e.stack||e):console.error(e)}var d;return l},H=(e,t,i,s,o,a)=>{let c,l,u,p,d,h=0,g=r(s);for(;h<g;h++){l=s[h],c=s[h+1],u=s[h-1];try{if(!Array.isArray(c))if("string"==typeof l||"number"==typeof l){if(h+1===g&&a)return d={},a.map((e=>d[e]=i[e])),d;i=i[l]}else{if(0===c)return void(i[u]=O(e,l));if("function"==typeof i[u]&&(p=O(e,l),"define"===u&&"CustomElementRegistry"===n(i)&&(p[1]=R(t,e,p[1])),"insertRule"===u&&p[1]>r(i.cssRules)&&(p[1]=r(i.cssRules)),i=i[u].apply(i,p),"play"===u))return Promise.resolve()}}catch(e){if(o)throw e;console.debug(e)}}return i},B=(e,t)=>{let n,i,s,o=t.V,a=t.U,c=a.document,l='script[type="text/partytown"]:not([data-ptid]):not([data-pterror])',d=l+":not([async]):not([defer])";c&&c.body?(n=c.querySelector(d),n||(n=c.querySelector(l)),n?(n.dataset.ptid=i=$(n,o),s={V:o,w:i},n.src?(s.S=n.src,s.H=n.dataset.ptsrc||n.src):s.j=n.innerHTML,e.postMessage([7,s])):(t.x||(t.x=1,((e,t,n)=>{let i,s,o=n._ptf,a=(n.partytown||{}).forward||[],c=(r,n)=>e.postMessage([10,{V:t,q:r,b:M(t,Array.from(n))}]);if(n._ptf=void 0,a.map((e=>{const[t,{preserveBehavior:i}]=(e=>{if("string"==typeof e)return[e,u];const[t,r=u]=e;return[t,{...u,...r}]})(e);s=n,t.split(".").map(((e,t,o)=>{var a;s=s[o[t]]=t+1<r(o)?s[o[t]]||(a=o[t+1],p.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:t,thisObject:r}=((e,t)=>{let r=e;for(let e=0;e<t.length-1;e+=1)r=r[t[e]];return{thisObject:r,methodOrProperty:t.length>0?r[t[t.length-1]]:void 0}})(n,o);"function"==typeof t&&(e=(...e)=>t.apply(r,...e))}return(...t)=>{let r;return e&&(r=e(t)),c(o,t),r}})()}))})),o)for(i=0;i<r(o);i+=2)c(o[i],o[i+1])})(e,o,a),c.dispatchEvent(new CustomEvent("pt0"))),e.postMessage([8,o]))):requestAnimationFrame((()=>B(e,t)))},k=(e,t,r)=>{if(!y.has(r)){y.set(r,t);const n=r.document,i=r.history,s=y.get(r.parent);let o=!1;const a=[],c=e=>{o?e():a.push(e)},l=()=>{e.postMessage([5,{V:t,J:s,S:n.baseURI,T:n.visibilityState}]),setTimeout((()=>{o=!0,a.forEach((e=>{e()}))}))},u=i.pushState.bind(i),p=i.replaceState.bind(i),d=(r,i,s,o)=>()=>{e.postMessage([13,{V:t,type:r,state:i,url:n.baseURI,newUrl:s,oldUrl:o}])};i.pushState=(e,t,r)=>{u(e,t,r),c(d(0,e,null==r?void 0:r.toString()))},i.replaceState=(e,t,r)=>{p(e,t,r),c(d(1,e,null==r?void 0:r.toString()))},r.addEventListener("popstate",(e=>{c(d(2,e.state))})),r.addEventListener("hashchange",(e=>{c(d(3,{},e.newURL,e.oldURL))})),r.addEventListener("ptupdate",(()=>{B(e,f[t])})),n.addEventListener("visibilitychange",(()=>e.postMessage([14,t,n.visibilityState]))),f[t]={V:t,U:r},"complete"===n.readyState?l():r.addEventListener("load",l)}},W=()=>{const e=Object.getOwnPropertyNames(S).map((e=>((e,t,r,n)=>{if(r=t.match(/^(HTML|SVG)(.+)Element$/))return n=r[2],"S"==t[0]?e.createElementNS("http://www.w3.org/2000/svg",l[n]||n.slice(0,2).toLowerCase()+n.slice(2)):e.createElement(c[n]||n)})(E,e))).filter((e=>e)).map((e=>[e]));return V(e,[])},V=(e,t)=>{const r=new Set(["Object"]);return e.filter((e=>e[0])).map((e=>{const t=e[0],r=e[1],i=n(t);return[i,S[i].prototype,t,r]})).map((([e,n,i,s])=>F(r,t,e,n,i,s))),t},D=(e,t,r)=>{let n=[],i=[e,"Object",n];for(r in t)J(n,t,r);return i},F=(e,t,r,i,s,a)=>{if(!e.has(r)){e.add(r);const c=Object.getPrototypeOf(i),l=n(c),u=[],p=Object.getOwnPropertyDescriptors(i);F(e,t,l,c,s,a);for(const e in p)J(u,s,e);t.push([r,l,u,a,o(s)])}},J=(e,t,r,i,o,a)=>{try{s(r)&&isNaN(r[0])&&"all"!==r&&("function"==(o=typeof(i=t[r]))?(String(i).includes("[native")||Object.getPrototypeOf(t)[r])&&e.push([r,5]):"object"===o&&null!=i?"Object"!==(a=n(i))&&"Function"!==a&&self[a]&&e.push([r,i.nodeType||a]):"symbol"!==o&&(r.toUpperCase()===r?e.push([r,6,i]):e.push([r,6])))}catch(e){console.warn(e)}},q=(e,r)=>void 0!==e[r]?new e[r](t):0;let G;(async e=>{const t=new SharedArrayBuffer(1073741824),r=new Int32Array(t);return(n,i)=>{const s=i[0],o=i[1];if(0===s){const e=(()=>{const e=E.createElement("i"),t=E.createTextNode(""),r=E.createComment(""),n=E.createDocumentFragment(),i=E.createElement("p").attachShadow({mode:"open"}),s=q(S,"IntersectionObserver"),o=q(S,"MutationObserver"),a=q(S,"ResizeObserver"),c=S.performance,l=S.screen,u=[[S.history],[c],[c.navigation],[c.timing],[l],[l.orientation],[S.visualViewport],[s,12],[o,12],[a,12],[t],[r],[n],[i],[e],[e.attributes],[e.classList],[e.dataset],[e.style],[E],[E.doctype]],p=[D("Window",S),D("Node",t)],d=function(e){return JSON.stringify(e,((e,t)=>("function"==typeof t&&(t=String(t)).startsWith(e+"(")&&(t="function "+t),"loadScriptsOnMainThread"===e&&(t=t.map((e=>Array.isArray(e)?e:["string"==typeof e?"string":"regexp","string"==typeof e?e:e.source]))),t)))}(T),h={i:d,v:V(u,p),C:new URL(I,S.location)+"",I:origin,$tabId$:S._pttab};return((e,t,r)=>{void 0!==t[r]&&e.push([r,"Object",Object.keys(t[r].prototype).map((e=>[e,6])),12])})(h.v,S,"IntersectionObserverEntry"),h})();e.P=t,n.postMessage([1,e])}else 2===i[0]?n.postMessage([3,W()]):11===s?e(o,(e=>{const t=JSON.stringify(e),n=t.length;for(let e=0;e<n;e++)r[e+1]=t.charCodeAt(e);r[0]=n,Atomics.notify(r,0)})):((e,t,r)=>{4===t[0]?k(e,a(),S):(r=f[t[1]])&&(7===t[0]?requestAnimationFrame((()=>B(e,r))):6===t[0]&&((e,t,r,n,i)=>{(i=t.U.document.querySelector(`[data-ptid="${r}"]`))&&(n?i.dataset.pterror=n:i.type+="-x",delete i.dataset.ptid),B(e,t)})(e,r,t[2],t[3]))})(n,i)}})(((e,t)=>_(G,e).then(t))).then((e=>{e&&(G=new Worker(URL.createObjectURL(new Blob(['/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */\n(e=>{const t=Symbol(),r=Symbol(),n=Symbol(),i=Symbol(),s=Symbol(),o=Symbol(),a=Symbol(),c=Symbol(),l=new Map,$={},d=new WeakMap,u=[],h={},p={},g=new Map,m=new Map,f="about:blank",w=e=>e.split(","),y=e=>{if(e=h.C+e,new URL(e).origin!=location.origin)throw"Invalid "+e;return e},v=w("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft"),S=w("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling"),b=w("insertBefore,remove,removeChild,replaceChild"),I=w("className,width,height,hidden,innerHTML,innerText,textContent,text"),M=w("setAttribute,setAttributeNS,setProperty"),T=w("addEventListener,dispatchEvent,removeEventListener"),E=T.concat(M,w("add,observe,remove,unobserve")),N=/^[A-Z_]([A-Z0-9-]*[A-Z0-9])?$/,x=()=>{},L=e=>e.length,C=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},R=[],O=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),A="text/partytown",P=(e,t,r)=>Object.defineProperty(e,t,{...r,configurable:!0}),W=(e,t)=>P(e,"name",{value:t}),H=(e,t,r)=>P(e.prototype,t,r),j=(e,t)=>Object.defineProperties(e.prototype,t),k=(e,t,r)=>H(e,t,{value:r,writable:!0});function D(e,t){var r,n;return null!==(n=null===(r=e.loadScriptsOnMainThread)||void 0===r?void 0:r.map((([e,t])=>new RegExp("string"===e?t.replace(/[.*+?^${}()|[\\]\\\\]/g,"\\\\$&"):t))).some((e=>e.test(t))))&&void 0!==n&&n}Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})());const U=(e,t)=>t in e[o],_=(e,t)=>e[o][t],B=(e,t,r)=>e[o][t]=r,F=(e,t,r,n,i,s)=>{if(!(i=l.get(t))&&r&&p[e]){const o=l.get(s||"");i=p[e].k(r,t,n,o),l.set(t,i)}return i},z=(e,t)=>k(e,"nodeType",t),q=(e,t)=>t.map((t=>H(e,t,{get(){let e=V(this,t),r=m.get(e);return r||(r=$e(this,[t]),m.set(e,r)),r}}))),V=(e,n,i)=>[e[t],e[r],n,...(i||R).map((e=>String(e&&e[t]?e[r]:e)))].join("."),X=(e,t)=>w(t).map((t=>H(e,t,{get(){return U(this,t)||B(this,t,$e(this,[t])),_(this,t)},set(e){_(this,t)!==e&&de(this,[t],e),B(this,t,e)}}))),Z=e=>v.map((t=>H(e,t,{get(){const e=g.get(V(this,t));if("number"==typeof e)return e;const r=$e(this,[t],v);return r&&"object"==typeof r?(Object.entries(r).map((([e,t])=>g.set(V(this,e),t))),r[t]):r}}))),G=(e,t)=>t.map((t=>{e.prototype[t]=function(...e){let r=V(this,t,e),n=g.get(r);return n||(n=ue(this,[t],e),g.set(r,n)),n}})),J=(e,n,i,s,o)=>{return void 0!==i&&(o=typeof i)?"string"===o||"boolean"===o||"number"===o||null==i?[0,i]:"function"===o?[4,{V:e,w:n,L:(a=i,(c=d.get(a))||(d.set(a,c=O()),$[c]=a),c)}]:(s=s||new Set)&&Array.isArray(i)?s.has(i)?[1,[]]:s.add(i)&&[1,i.map((t=>J(e,n,t,s)))]:"object"===o?i[r]?[3,[i[t],i[r]]]:i instanceof Event?[5,K(e,n,i,!1,s)]:Y&&i instanceof TrustedHTML?[0,i.toString()]:i instanceof ArrayBuffer?[8,i]:ArrayBuffer.isView(i)?[9,i.buffer,C(i)]:[2,K(e,n,i,!0,s)]:void 0:i;var a,c},Y="undefined"!=typeof TrustedHTML,K=(e,t,r,n,i,s,o,a)=>{if(s={},!i.has(r))for(o in i.add(r),r)a=r[o],(n||"function"!=typeof a)&&(s[o]=J(e,t,a,i));return s},Q=(e,n)=>e?J(e[t],e[r],n):[0,n],ee=(e,t,r,n,i,s,o,a)=>{if(n){if(i=n[0],s=n[1],0===i||11===i||12===i)return s;if(4===i)return re(r,s);if(6===i)return e&&r.length>0?(...t)=>ue(p[e].U,r,t,1):x;if(3===i)return te(s);if(7===i)return new ie(s.map(te));if(10===i)return new se(s);if(1===i)return s.map((n=>ee(e,t,r,n)));if(14===i)return new ne(s);for(a in o={},s)o[a]=ee(e,t,[...r,a],s[a]);if(13===i)return new p[e].U.CSSStyleDeclaration(e,t,r,o);if(5===i){if("message"===o.type&&o.origin){let e,t=JSON.stringify(o.data),r=u.find((e=>e.m===t));r&&(e=p[r.V],e&&(o.source=e.U,o.origin=e.E.origin))}return new Proxy(new Event(o.type,o),{get:(e,t)=>t in o?o[t]:"function"==typeof e[String(t)]?x:e[String(t)]})}if(2===i)return o}},te=([e,t,r,n])=>t===e&&p[e]?p[e].U:F(e,t,r,void 0,void 0,n),re=(e,{V:t,w:r,G:n,L:i})=>($[i]||d.set($[i]=function(...i){const s=F(t,r,n);return ue(s,e,i)},i),$[i]);class ne extends Error{constructor(e){super(e.message),this.name=e.name,this.message=e.message,this.stack=e.stack}}class ie{constructor(e){(this._=e).map(((e,t)=>this[t]=e))}entries(){return this._.entries()}forEach(e,t){this._.map(e,t)}item(e){return this[e]}keys(){return this._.keys()}get length(){return L(this._)}values(){return this._.values()}[Symbol.iterator](){return this._[Symbol.iterator]()}}const se=class{constructor(e){this.name=e[0],this.value=e[1]}get nodeName(){return this.name}get nodeType(){return 2}},oe=(e,t,r)=>console.warn(`Partytown unable to ${e} cross-origin ${t}: `+r.E),ae=[],ce=(e,n,i,o,a,c)=>{if(e[s]){if(ae.push({V:e[t],w:e[r],a:[...e[s],...n],d:o,r:a}),3===i)h.K([12,{F:O(),Q:[...ae]}],c?[c instanceof ArrayBuffer?c:c.buffer]:void 0),ae.length=0;else if(1===i)return le(!0);h.c=setTimeout(le,20)}},le=e=>{if(clearTimeout(h.c),L(ae)){const t=ae[L(ae)-1],r={F:`${O()}.${h.$tabId$}`,Q:[...ae]};if(ae.length=0,e){const e=((e,t)=>{const r=e.P,n=new Int32Array(r);Atomics.store(n,0,0),e.K([11,t]),Atomics.wait(n,0,0);let i=Atomics.load(n,0),s="",o=0;for(;o<i;o++)s+=String.fromCharCode(n[o+1]);return JSON.parse(s)})(h,r),n=e.z,i=ee(t.V,t.w,t.a,e.M);if(e.p){if(n)return Promise.reject(e.p);throw new Error(e.p)}return n?Promise.resolve(i):i}h.K([12,r])}},$e=(e,t,r,n)=>h.i.get&&(n=h.i.get(pe(e,t)))!==a?n:n=ce(e,t,1,void 0,r),de=(e,t,r,n)=>{if(h.i.set){if((n=h.i.set({value:r,prevent:c,...pe(e,t)}))===c)return;n!==a&&(r=n)}I.some((e=>t.includes(e)))&&(g.clear(),t[t.length-1]),t=[...t,Q(e,r),0],ce(e,t,2)},ue=(e,t,r,n,i,s,o,c)=>h.i.apply&&(o=h.i.apply({args:r,...pe(e,t)}))!==a?o:(c=t[L(t)-1],t=[...t,Q(e,r)],n=n||(E.includes(c)?2:1),"setAttribute"===c&&U(e,r[0])?B(e,r[0],r[1]):b.includes(c)?(g.clear(),m.clear()):M.includes(c)&&(n=2,g.clear()),o=ce(e,t,n,i,void 0,s)),he=(e,t,r)=>{ce(e,[1,t,Q(e,r)],1)},pe=(e,r)=>({name:r.join("."),continue:a,nodeName:e[n],constructor:C(e),instance:e,window:p[e[t]].U}),ge=(e,t,r)=>{let n={getItem(n){if(r.A)return ue(e,[t,"getItem"],[n],1);oe("get",t,r)},setItem(n,i){r.A?ue(e,[t,"setItem"],[n,i],1):oe("set",t,r)},removeItem(n){r.A?ue(e,[t,"removeItem"],[n],1):oe("remove",t,r)},key(n){if(r.A)return ue(e,[t,"key"],[n],1);oe("key",t,r)},clear(){r.A?ue(e,[t,"clear"],R,1):oe("clear",t,r)},get length(){if(r.A)return $e(e,[t,"length"]);oe("length",t,r)}};e[t]=new Proxy(n,{get:(e,t)=>Reflect.has(e,t)?Reflect.get(e,t):e.getItem(t),set:(e,t,r)=>(e.setItem(t,r),!0),has:(e,t)=>!!Reflect.has(e,t)||"string"==typeof t&&null!==e.getItem(t),deleteProperty:(e,t)=>(e.removeItem(t),!0)})},me=(e,t,r)=>{e[r]=W(class extends t{constructor(e,t,r,i){return super(e,t,r,i||{}),new Proxy(this,{get:(e,t)=>e[t]?e[t]:(e[t]||"string"!=typeof t||e[n][t]||(e[n][t]=$e(e,[t])),e[n][t]),set:(e,t,r)=>(e[n][t]=r,de(e,[t],r),g.clear(),!0)})}setProperty(...e){this[n][e[0]]=e[1],ue(this,["setProperty"],e,2),e[0],g.clear()}getPropertyValue(e){return this[e]}removeProperty(e){let t=this[n][e];return ue(this,["removeProperty"],[e],2),g.clear(),this[n][e]=void 0,t}},r)},fe=(e,t)=>{e[t]=W(class{constructor(e){this.ownerNode=e}get cssRules(){const e=this.ownerNode;return new Proxy({},{get(t,r){const n=String(r);return"item"===n?t=>ye(e,t):"length"===n?we(e).length:isNaN(n)?t[r]:ye(e,n)}})}insertRule(e,t){const r=we(this.ownerNode);return(t=void 0===t?0:t)>=0&&t<=r.length&&(ue(this.ownerNode,["sheet","insertRule"],[e,t],2),r.splice(t,0,0)),this.ownerNode,g.clear(),t}deleteRule(e){ue(this.ownerNode,["sheet","deleteRule"],[e],2),we(this.ownerNode).splice(e,1),this.ownerNode,g.clear()}get type(){return"text/css"}},t);const r={sheet:{get(){return new e[t](this)}}};j(e.HTMLStyleElement,r)},we=(e,t)=>((t=_(e,2))||(t=$e(e,["sheet","cssRules"]),B(e,2,t)),t),ye=(e,t,r)=>(0===(r=we(e))[t]&&(r[t]=$e(e,["sheet","cssRules",parseInt(t,10)])),r[t]),ve="0.10.2-dev1727590485751",Se=(e,t,r,n,i)=>{try{e.l=t,be(e,r)}catch(e){console.error(r,e),i=String(e.stack||e)}return e.l="",i},be=(e,t,r)=>{e.N=1;let n=(e=>e.replace(/([a-zA-Z0-9_$\\.\\\'\\"\\`])?(\\.\\.\\.)?this(?![a-zA-Z0-9_$:])/g,((e,t,r)=>{const n=(t||"")+(r||"");return null!=t?n+"this":n+"(thi$(this)?window:this)"})))(t);t=`with(this){${n.replace(/\\/\\/# so/g,"//Xso")}\\n;function thi$(t){return t===this}};${(h.i.globalFns||[]).filter((e=>/[a-zA-Z_$][0-9a-zA-Z_$]*/.test(e))).map((e=>`(typeof ${e}==\'function\'&&(this.${e}=${e}))`)).join(";")};`+(r?"\\n//# sourceURL="+r:""),e.A||(t=t.replace(/.postMessage\\(/g,`.postMessage(\'${e.V}\',`)),new Function(t).call(e.U),e.N=0},Ie=(e,t,r)=>{(r=_(e,t))&&setTimeout((()=>r.map((e=>e({type:t})))))},Me=(e,t)=>{for(t=e.E;!t.host&&(t=(e=p[e.J]).E,e.V!==e.J););return t},Te=(e,t,r,n,i,s)=>(n=Me(e,n),i=new URL(t||"",n),r&&h.i.resolveUrl&&(s=h.i.resolveUrl(i,n,r))?s:i),Ee=(e,t,r)=>Te(e,t,r)+"",Ne=(e,t)=>{const r=Me(e),n=new URL(t||"",r);if(h.i.resolveSendBeaconRequestParameters){const e=h.i.resolveSendBeaconRequestParameters(n,r);if(e)return e}return{}},xe=()=>`<script src="${y("partytown.js?v="+ve)}"><\\/script>`,Le=e=>class{constructor(){this.s="",this.l=[],this.e=[],this.style={}}get src(){return this.s}set src(t){this.s=t,fetch(Ee(e,t,"image"),{mode:"no-cors",credentials:"include",keepalive:!0}).then((e=>{e.ok||0===e.status?this.l.map((e=>e({type:"load"}))):this.e.map((e=>e({type:"error"})))}),(()=>this.e.forEach((e=>e({type:"error"})))))}addEventListener(e,t){"load"===e&&this.l.push(t),"error"===e&&this.e.push(t)}removeEventListener(e,t){"load"===e&&(this.l=this.l.filter((e=>e!==t))),"error"===e&&(this.e=this.e.filter((e=>e!==t)))}get onload(){return this.l[0]}set onload(e){this.l=[e]}get onerror(){return this.e[0]}set onerror(e){this.e=[e]}},Ce={addEventListener:{value(...e){const t=e[0],r=_(this,t)||[];r.push(e[1]),B(this,t,r)}},async:{get:x,set:x},defer:{get:x,set:x},onload:{get(){let e=_(this,"load");return e&&e[0]||null},set(e){B(this,"load",e?[e]:null)}},onerror:{get(){let e=_(this,"error");return e&&e[0]||null},set(e){B(this,"error",e?[e]:null)}},getAttribute:{value(e){return"src"===e?this.src:ue(this,["getAttribute"],[e])}},setAttribute:{value(e,t){Re.includes(e)?this[e]=t:ue(this,["setAttribute"],[e,t])}}},Re=w("src,type"),Oe=(e,t)=>{const r={innerHTML:Ae,innerText:Ae,src:{get(){return _(this,4)||""},set(e){const r=Ee(t,e,null),n=h.i;e=Ee(t,e,"script"),B(this,4,e),de(this,["src"],e),r!==e&&de(this,["dataset","ptsrc"],r),this.type&&D(n,e)&&de(this,["type"],"text/javascript")}},text:Ae,textContent:Ae,type:{get(){return $e(this,["type"])},set(e){Pe(e)||(B(this,5,e),de(this,["type"],e))}},...Ce};j(e,r)},Ae={get(){const e=$e(this,["type"]);if(Pe(e)){const e=_(this,3);if(e)return e}return $e(this,["innerHTML"])||""},set(e){B(this,3,e)}},Pe=e=>!e||"text/javascript"===e,We=(e,i,s)=>{const o=h.i,a=W(class extends s{appendChild(e){return this.insertBefore(e,null)}get href(){}set href(e){}insertBefore(e,s){const a=e[t]=this[t],c=e[r],l=e[n],$="SCRIPT"===l,d="IFRAME"===l;if($){const t=_(e,3),r=_(e,5);if(t){if(Pe(r)){const r=e.id;if(r&&D(o,r))de(e,["type"],"text/javascript");else{const r=Se(i,c,t,0,""),n=r?"pterror":"ptid",s=r||c;de(e,["type"],A+"-x"),de(e,["dataset",n],s)}}de(e,["innerHTML"],t)}}if(ue(this,["insertBefore"],[e,s],2),d){const t=_(e,0);if(t&&t.startsWith("javascript:")){const e=t.split("javascript:")[1];Se(i,c,e,0,"")}((e,t)=>{let r,n,i=0,s=()=>{p[e]&&p[e].x&&!p[e].y?(r=_(t,1)?"error":"load",n=_(t,r),n&&n.map((e=>e({type:r})))):i++>2e3?(n=_(t,"error"),n&&n.map((e=>e({type:"error"})))):setTimeout(s,9)};s()})(c,e)}return $&&(le(!0),h.K([7,a])),e}get nodeName(){return"#s"===this[n]?"#document-fragment":this[n]}get nodeType(){return 3}get ownerDocument(){return i.n}},"Node");q(a,w("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling")),e.Node=a},He=w("AUDIO,CANVAS,VIDEO"),je=w("Audio,MediaSource"),ke=(e,r,n)=>{j(e,{body:{get:()=>r.e},cookie:{get(){return r.A?$e(this,["cookie"]):(oe("get","cookie",r),"")},set(e){r.A&&de(this,["cookie"],e)}},createElement:{value(e){if(e=e.toUpperCase(),!N.test(e))throw e+" not valid";const r="IFRAME"===e,n=this[t],i=(r?"f_":"")+O();ue(this,["createElement"],[e],2,i);const s=F(n,i,e);if(r)Qe({V:i,J:n,S:f},!0).U.fetch=fetch,de(s,["srcdoc"],xe());else if("SCRIPT"===e){const e=_(s,5);Pe(e)&&de(s,["type"],A)}return s}},createElementNS:{value(e,r){const n=O(),i=F(this[t],n,r,e);return ue(this,["createElementNS"],[e,r],2,n),i}},createTextNode:{value(e){const r=this[t],n=O(),i=F(r,n,"#text");return ue(this,["createTextNode"],[e],2,n),i}},createEvent:{value:e=>new Event(e)},currentScript:{get(){return r.l?F(this[t],r.l,"SCRIPT"):null}},defaultView:{get:()=>n?null:r.U},documentElement:{get:()=>r.o},getElementsByTagName:{value(e){return"BODY"===(e=e.toUpperCase())?[r.e]:"HEAD"===e?[r.s]:ue(this,["getElementsByTagName"],[e])}},head:{get:()=>r.s},images:{get(){return $e(this,["images"])}},scripts:{get(){return $e(this,["scripts"])}},implementation:{get(){return{hasFeature:()=>!0,createHTMLDocument:e=>{const t=O();return ue(this,["implementation","createHTMLDocument"],[e],1,{V:t}),Qe({V:t,J:t,S:r.E+"",T:"hidden"},!0,!0).n}}}},location:{get:()=>r.E,set(e){r.E.href=e+""}},nodeType:{value:9},parentNode:{value:null},parentElement:{value:null},readyState:{value:"complete"},visibilityState:{get:()=>r.T||"visible"}}),X(e,"compatMode,referrer,forms")},De=(e,t)=>{j(e,{parentElement:{get(){return this.parentNode}},parentNode:{get:()=>t.o}})},Ue=(e,t)=>{j(e,{localName:{get(){return this[n].toLowerCase()}},namespaceURI:{get(){return this[i]||"http://www.w3.org/1999/xhtml"}},nodeType:{value:1},tagName:{get(){return this[n]}}}),q(e,S),X(e,"id"),Z(t),G(t,w("getClientRects,getBoundingClientRect"))},_e=(e,t)=>{const r={};w("hash,host,hostname,href,origin,pathname,port,protocol,search").map((e=>{r[e]={get(){let r,n=_(this,4);if("string"!=typeof n){if(r=$e(this,["href"]),""===r)return"protocol"===e?":":"";B(this,4,r),n=new URL(r)[e]}return Te(t,n,null)[e]},set(r){let n;if("href"===e)if((e=>{try{return new URL(e),!0}catch(e){return!1}})(r))n=new URL(r);else{const e=t.E.href;n=Te(t,e,null),n.href=new URL(r+"",n.href)}else n=Te(t,this.href,null),n[e]=r;B(this,4,n.href),de(this,["href"],n.href)}}})),j(e,r)},Be=(e,t)=>{const r={contentDocument:{get(){return Ve(this).n}},contentWindow:{get(){return Ve(this).U}},src:{get(){let e=_(this,0);return e&&e.startsWith("javascript:")?e:(e=Ve(this).E.href,e.startsWith("about:")?"":e)},set(e){if(e)if(e.startsWith("javascript:"))B(this,0,e);else if(!e.startsWith("about:")){let t,r=new XMLHttpRequest,n=Ve(this);n.E.href=e=Ee(n,e,"iframe"),n.y=1,n.A=h.I===n.E.origin,B(this,1,void 0),r.open("GET",e,!1),r.send(),t=r.status,t>199&&t<300?(de(this,["srcdoc"],`<base href="${e}">`+r.responseText.replace(ze,((e,t)=>{const r=[];let n,i=!1;for(;n=qe.exec(t);){let[e]=n;e.startsWith("type=")&&(i=!0,e=e.replace(/(application|text)\\/javascript/,A)),r.push(e)}return i||r.push(\'type="\'+A+\'"\'),`<script ${r.join(" ")}>`}))+xe()),le(!0),h.K([7,n.V])):(B(this,1,t),n.y=0)}}},...Ce};j(e,r)},Fe="((?:\\\\w|-)+(?:=(?:(?:\\\\w|-)+|\'[^\']*\'|\\"[^\\"]*\\")?)?)",ze=new RegExp(`<script\\\\s*((${Fe}\\\\s*)*)>`,"mg"),qe=new RegExp(Fe,"mg"),Ve=e=>{const n=e[r];return p[n]||Qe({V:n,J:e[t],S:$e(e,["src"])||f},!0),p[n]},Xe=e=>{const t=(e,t)=>{const{a:r,b:n,c:i,d:s,e:o,f:a}=ue(e,[t],R);return new DOMMatrixReadOnly([r,n,i,s,o,a])},r={...e,getCTM:{value:function(){return t(this,"getCTM")}},getScreenCTM:{value:function(){return t(this,"getScreenCTM")}}};j(e,r)},Ze=(e,t)=>{e.NamedNodeMap=W(class extends t{constructor(e,t,r){return super(e,t,r),new Proxy(this,{get(e,t){const r=Je[t];return r?r.bind(e,[t]):$e(e,[t])},set(e,t,r){if(Je[t])throw new Error("Can\'t set read-only property: "+String(t));return de(e,[t],r),!0}})}},"NamedNodeMap")};function Ge(e,...t){return ue(this,e,t,1)}const Je={getNamedItem:Ge,getNamedItemNS:Ge,item:Ge,removeNamedItem:Ge,removeNamedItemNS:Ge,setNamedItem:Ge,setNamedItemNS:Ge},Ye=(a,c,l,$,d,g)=>{let m,v,b,I;const M=class{constructor(e,c,l,$,d){this[t]=e||a,this[r]=c||m||O(),this[s]=l||[],this[n]=$||v,this[i]=d||b,this[o]=I&&I[o]||{},m=v=b=void 0}},E=new(W(class extends URL{assign(){}reload(){}replace(){}},"Location"))(l),N=E.origin===h.I||E.origin===f,x=c===a,R={},A=()=>{let e,t,r=[];for(e in p)t=p[e],t.J!==a||t.B||r.push(t);return r},D=W(class extends M{constructor(){super(a,a),this.addEventListener=(...e)=>{"load"===e[0]?R.N&&setTimeout((()=>e[1]({type:"load"}))):ue(this,["addEventListener"],e,2)};let n,i,o=this,l=0,u=()=>{l||((h.u||(e.g=[$e,de,ue,he,j,O,t,r,s],h.t(y("partytown-media.js?v="+ve)),h.u=e.f,delete e.f),h.u)(M,J,R,o,je),l=1)},p={},f=(e,t,r,n)=>{He.includes(e)&&u();const i=p[e]?p[e]:e.includes("-")?p.UNKNOWN:p.I;return m=t,v=e,b=r,I=n,new i};var T,L;if(o.Window=D,o.name=name+a,We(o,R,M),(e=>{e.NodeList=W(ie,"NodeList")})(o),Ze(o,M),me(o,M,"CSSStyleDeclaration"),((e,t,r)=>{e[r]=W(class extends t{now(){return performance.now()}},r)})(o,M,"Performance"),((e,t)=>{const r="customElements",n=new Map;e[r]={define(i,s,o){n.set(i,s),t[i.toUpperCase()]=s;const a=[s.name,s.observedAttributes];ue(e,[r,"define"],[i,a,o])},get:t=>n.get(t)||ue(e,[r,"get"],[t]),whenDefined:t=>n.has(t)?Promise.resolve():ue(e,[r,"whenDefined"],[t]),upgrade:t=>ue(e,[r,"upgrade"],[t])}})(o,p),h.v.map((([e,t,n,i,c])=>{const l=Ke[e]?V:"EventTarget"===t?J:"Object"===t?M:o[t],$=o[e]=W(12===i?class extends M{constructor(...t){super(),he(this,e,t)}}:o[e]||class extends l{},e);c&&(p[c]=$),n.map((([e,t,n])=>{e in $.prototype||e in l.prototype||("string"==typeof t?H($,e,{get(){if(!U(this,e)){const n=this[r],i=[...this[s],e],c=o[t];c&&B(this,e,new c(a,n,i))}return _(this,e)},set(t){B(this,e,t)}}):5===t?k($,e,(function(...t){return ue(this,[e],t)})):t>0&&(void 0!==n?k($,e,n):H($,e,{get(){return $e(this,[e])},set(t){return de(this,[e],t)}})))}))})),w("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((t=>{delete D.prototype[t],t in o||(n=e[t],null!=n&&(o[t]="function"!=typeof n||n.toString().startsWith("class")?n:n.bind(e)))})),Object.getOwnPropertyNames(e).map((t=>{t in o||(o[t]=e[t])})),je.map((e=>P(o,e,{get:()=>(u(),o[e])}))),"trustedTypes"in e&&(o.trustedTypes=e.trustedTypes),Ue(o.Element,o.HTMLElement),ke(o.Document,R,g),T=o.DocumentFragment,z(T,11),q(T,S),_e(o.HTMLAnchorElement,R),L=o.HTMLFormElement,j(L,{}),X(L,"elements"),Be(o.HTMLIFrameElement),Oe(o.HTMLScriptElement,R),Xe(o.SVGGraphicsElement),De(o.HTMLHeadElement,R),De(o.HTMLBodyElement,R),((e,t)=>{j(e,{parentElement:{value:null},parentNode:{get:()=>t.n}})})(o.HTMLHtmlElement,R),fe(o,"CSSStyleSheet"),z(o.Comment,8),z(o.DocumentType,10),Object.assign(R,{V:a,J:c,U:new Proxy(o,{get:(e,t)=>{var r;if("string"!=typeof t||isNaN(t))return(null===(r=h.i.mainWindowAccessors)||void 0===r?void 0:r.includes(t))?$e(this,[t]):e[t];{let e=A()[t];return e?e.U:void 0}},has:()=>!0}),n:f("#document",a+".d"),o:f("HTML",a+".e"),s:f("HEAD",a+".h"),e:f("BODY",a+".b"),E:E,T:$,A:N,B:x,k:f}),o.requestAnimationFrame=e=>setTimeout((()=>e(performance.now())),9),o.cancelAnimationFrame=e=>clearTimeout(e),o.requestIdleCallback=(e,t)=>(t=Date.now(),setTimeout((()=>e({didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-t))})),1)),o.cancelIdleCallback=e=>clearTimeout(e),ge(o,"localStorage",R),ge(o,"sessionStorage",R),N||(o.indexeddb=void 0),d)i={},o.history={pushState(e){i=e},replaceState(e){i=e},get state(){return i},length:0},o.indexeddb=void 0;else{const e=o.history.pushState.bind(o.history),t=o.history.replaceState.bind(o.history);o.history.pushState=(t,r,n)=>{!1!==R.$propagateHistoryChange$&&e(t,r,n)},o.history.replaceState=(e,r,n)=>{!1!==R.$propagateHistoryChange$&&t(e,r,n)}}o.Worker=void 0}get body(){return R.e}get document(){return R.n}get documentElement(){return R.o}fetch(e,t){return e="string"==typeof e||e instanceof URL?String(e):e.url,fetch(Ee(R,e,"fetch"),t)}get frames(){return R.U}get frameElement(){return x?null:F(c,a,"IFRAME")}get globalThis(){return R.U}get head(){return R.s}get length(){return A().length}get location(){return E}set location(e){E.href=e+""}get Image(){return Le(R)}get navigator(){return(e=>{const t={sendBeacon:(t,r)=>{try{return fetch(Ee(e,t,null),{method:"POST",body:r,mode:"no-cors",keepalive:!0,...Ne(e,t)}),!0}catch(e){return console.error(e),!1}}};for(let e in navigator)t[e]=navigator[e];return new Proxy(t,{set:(e,t,r)=>(navigator[t]=r,!0),get:(t,r)=>Object.prototype.hasOwnProperty.call(t,r)?t[r]:$e(e.U,["navigator",r])})})(R)}get origin(){return E.origin}set origin(e){}get parent(){for(let e in p)if(p[e].V===c)return p[e].U;return R.U}postMessage(...e){p[e[0]]&&(L(u)>50&&u.splice(0,5),u.push({V:e[0],m:JSON.stringify(e[1])}),e=e.slice(1)),ue(this,["postMessage"],e,3)}get self(){return R.U}get top(){for(let e in p)if(p[e].B)return p[e].U;return R.U}get window(){return R.U}get XMLHttpRequest(){const e=XMLHttpRequest,t=String(e),r=W(class extends e{open(...e){e[1]=Ee(R,e[1],"xhr"),super.open(...e)}set withCredentials(e){h.i.allowXhrCredentials&&(super.withCredentials=e)}toString(){return t}},C(e));return r.prototype.constructor.toString=()=>t,r}},"Window"),V=class extends M{constructor(e,t,r,n){return super(e,t,r,n),new Proxy(this,{get:(e,t)=>$e(e,[t]),set:(e,t,r)=>(de(e,[t],r),!0)})}},J=class extends M{};return T.map((e=>J.prototype[e]=function(...t){return ue(this,[e],t,2)})),X(D,"devicePixelRatio"),Z(D),G(D,["getComputedStyle"]),new D,R},Ke={DOMStringMap:1,NamedNodeMap:1},Qe=({V:e,J:t,S:r,T:n},i,s)=>(p[e]||(p[e]=Ye(e,t,r,n,i,s)),h.K([7,e]),p[e]),et=[],tt=t=>{const r=t.data,n=r[0],i=r[1];if(h.x)if(7===n)(async e=>{let t,r=e.V,n=e.w,i=F(r,n,"SCRIPT"),s=e.j,o=e.S,a=e.H,c="",l=p[r],$=["text/jscript","text/javascript","text/x-javascript","application/javascript","application/x-javascript","text/ecmascript","text/x-ecmascript","application/ecmascript"];if(o)try{if(o=Te(l,o,"script")+"",B(i,4,o),t=await fetch(o),t.ok){let e=t.headers.get("content-type");$.some((t=>{var r,n,i;return null===(i=null===(r=null==e?void 0:e.toLowerCase)||void 0===r?void 0:(n=r.call(e)).includes)||void 0===i?void 0:i.call(n,t)}))&&(s=await t.text(),l.l=n,be(l,s,a||o)),Ie(i,"load")}else c=t.statusText,Ie(i,"error")}catch(e){console.error(e),c=String(e.stack||e),Ie(i,"error")}else s&&(c=Se(l,n,s,0,c));l.l="",h.K([6,r,n,c])})(i);else if(9===n)(({V:e,w:t,L:r,R:n,b:i})=>{if($[r])try{$[r].apply(ee(e,t,[],n),ee(e,t,[],i))}catch(e){console.error(e)}})(i);else if(10===n)(({V:e,q:t,b:r})=>{try{let n=p[e].U,i=0,s=L(t);for(;i<s;i++)i+1<s?n=n[t[i]]:n[t[i]].apply(n,ee(null,e,[],r))}catch(e){console.error(e)}})(i);else if(5===n)Qe(i);else if(8===n)p[i].x=1,p[i].y=0;else if(14===n)p[i].T=r[2];else if(13===n){const e=i.V,t=p[e];t.E.href=i.url,function(e,t,r){const n=t.U.history;switch(r.type){case 0:t.$propagateHistoryChange$=!1;try{n.pushState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0;break;case 1:t.$propagateHistoryChange$=!1;try{n.replaceState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0}}(i.V,t,i)}else 15===n&&((e,t,r,n,i)=>{const s=F(t,r);s&&"function"==typeof s[n]&&s[n].apply(s,i)})(...r);else 1===n?((t=>{const r=h.i=JSON.parse(t.i),n=t.I;h.t=importScripts.bind(e),h.v=t.v,h.C=t.C,h.I=n,h.K=postMessage.bind(e),h.P=t.P,h.$tabId$=t.$tabId$,e.importScripts=void 0,delete e.postMessage,delete e.WorkerGlobalScope,w("resolveUrl,resolveSendBeaconRequestParameters,get,set,apply").map((e=>{r[e]&&(r[e]=new Function("return "+r[e])())}))})(i),h.K([2])):3===n?(h.v=[...h.v,...i],h.x=1,h.K([4]),[...et].map(tt),et.length=0):et.push(t)};e.onmessage=tt,postMessage([0])})(self);\n'],{type:"text/javascript"})),{name:"Partytown 🎉"}),G.onmessage=t=>{const r=t.data;12===r[0]?_(G,r[1]):e(G,r)},S.addEventListener("pt1",(e=>k(G,$(e.detail.frameElement),e.detail))))}))})(window);
Index: build/partytown-media.js
===================================================================
--- build/partytown-media.js	(revision 3189893)
+++ build/partytown-media.js	(working copy)
@@ -1 +1,2 @@
-(e=>{const[t,s,n,r,i,a,o,u,d]=e.g;delete e.g;const c=Symbol(),h=Symbol(),f=Symbol(),p=Symbol(),g=Symbol(),l=Symbol(),m=[],v=(e,t,s)=>e[t]=S(t,s),S=(e,t)=>Object.defineProperty(t,"name",{value:e}),b=(e,t)=>{const r={getContext:{value(e,t){return this[c]||(this[c]=(e.includes("webgl")?g:p)(this,e,t)),this[c]}}},h=v(t,"CanvasGradient",class extends e{addColorStop(...e){n(this,["addColorStop"],e,2)}}),f=v(t,"CanvasPattern",class extends e{setTransform(...e){n(this,["setTransform"],e,2)}}),p=(e,t,r)=>{const i=e[o],c=a(),f={[o]:i,[u]:c,[d]:[]},p=n(e,["getContext"],[t,r],1,c),g="getContextAttributes,getImageData,getLineDash,getTransform,isPointInPath,isPointInStroke,measureText".split(","),l={get:(e,t)=>"string"==typeof t&&t in p?"function"==typeof p[t]?(...e)=>{if(t.startsWith("create")){const r=a();return n(f,[t],e,2,r),"createImageData"===t||"createPattern"===t?(s=`${t}()`,console.warn(`${s} not implemented`),{setTransform:()=>{}}):new h(i,r)}var s;const r=g.includes(t)?1:2;return n(f,[t],e,r)}:p[t]:e[t],set:(e,t,n)=>("string"==typeof t&&t in p?(p[t]!==n&&"function"!=typeof n&&s(f,[t],n),p[t]=n):e[t]=n,!0)};return new Proxy(p,l)},g=(e,t,r)=>{const i=e[o],c=a(),h={[o]:i,[u]:c,[d]:[]},f=n(e,["getContext"],[t,r],1,c),p={get:(e,t)=>"string"==typeof t?"function"!=typeof f[t]?f[t]:(...e)=>n(h,[t],e,m(t)):e[t],set:(e,t,n)=>("string"==typeof t&&t in f?(f[t]!==n&&"function"!=typeof n&&s(h,[t],n),f[t]=n):e[t]=n,!0)};return new Proxy(f,p)},l="checkFramebufferStatus,makeXRCompatible".split(","),m=e=>e.startsWith("create")||e.startsWith("get")||e.startsWith("is")||l.includes(e)?1:2;v(t,"CanvasGradient",h),v(t,"CanvasPattern",f),i(t.HTMLCanvasElement,r)},y=(e,d,c,b)=>{var y,T;b.Audio=S("HTMLAudioElement",class{constructor(e){const t=c.k("audio",a());return t.src=e,t}});const w=class extends e{get enabled(){return t(this,["enabled"])}set enabled(e){s(this,["enabled"],e)}get id(){return t(this,["id"])}get kind(){return t(this,["kind"])}get label(){return t(this,["label"])}get language(){return t(this,["language"])}get sourceBuffer(){return new x(this)}},E=class{constructor(e){const s="audioTracks",r=e[o],i=e[u];return new Proxy({addEventListener(...t){n(e,[s,"addEventListener"],t,3)},getTrackById:(...t)=>n(e,[s,"getTrackById"],t),get length(){return t(e,[s,"length"])},removeEventListener(...t){n(e,[s,"removeEventListener"],t,3)}},{get:(e,t)=>"number"==typeof t?new w(r,i,[s,t]):e[t]})}},k=v(b,"SourceBufferList",class extends Array{constructor(e){super(),this[h]=e}addEventListener(...e){n(this[h],["sourceBuffers","addEventListener"],e,3)}removeEventListener(...e){n(this[h],["sourceBuffers","removeEventListener"],e,3)}}),x=v(b,"SourceBuffer",(T=class extends d{constructor(e){super(e[o],e[u],["sourceBuffers"]),this[y]=[],this[h]=e}abort(){const e=R(this);n(this,[e,"appendWindowStart"],m,1)}addEventListener(...e){const t=R(this);n(this,[t,"addEventListener"],e,3)}appendBuffer(e){this[g].push(["appendBuffer",[e],e]),W(this)}get appendWindowStart(){const e=R(this);return t(this,[e,"appendWindowStart"])}set appendWindowStart(e){const t=R(this);s(this,[t,"appendWindowStart"],e)}get appendWindowEnd(){const e=R(this);return t(this,[e,"appendWindowEnd"])}set appendWindowEnd(e){const t=R(this);s(this,[t,"appendWindowEnd"],e)}get buffered(){const e=this[h],t=R(this);return new B(e[o],e[u],["sourceBuffers",t,"buffered"])}changeType(e){const t=R(this);n(this,[t,"changeType"],[e],2)}get mode(){const e=R(this);return t(this,[e,"mode"])}set mode(e){const t=R(this);s(this,[t,"mode"],e)}remove(e,t){this[g].push(["remove",[e,t]]),W(this)}removeEventListener(...e){const t=R(this);n(this,[t,"removeEventListener"],e,3)}get timestampOffset(){const e=R(this);return t(this,[e,"timestampOffset"])}set timestampOffset(e){const t=R(this);s(this,[t,"timestampOffset"],e)}get updating(){const e=R(this);return t(this,[e,"updating"])}},y=g,T)),B=v(b,"TimeRanges",class extends e{start(...e){return n(this,["start"],e)}end(...e){return n(this,["end"],e)}get length(){return t(this,["length"])}}),R=e=>e?e[h][p].indexOf(e):-1,W=e=>{if(e[g].length){if(!e.updating){const t=e[g].shift();if(t){const s=R(e);n(e,[s,t[0]],t[1],3,void 0,t[2])}}setTimeout((()=>W(e)),50)}},C={buffered:{get(){return this[l]||(this[l]=new B(this[o],this[u],["buffered"]),setTimeout((()=>{this[l]=void 0}),5e3)),this[l]}},readyState:{get(){return 4===this[f]?4:("number"!=typeof this[f]&&(this[f]=t(this,["readyState"]),setTimeout((()=>{this[f]=void 0}),1e3)),this[f])}}};v(b,"MediaSource",class extends d{constructor(){super(c.V),this[p]=new k(this),r(this,"MediaSource",m)}get activeSourceBuffers(){return[]}addSourceBuffer(e){const t=new x(this);return this[p].push(t),n(this,["addSourceBuffer"],[e]),t}clearLiveSeekableRange(){n(this,["clearLiveSeekableRange"],m,2)}get duration(){return t(this,["duration"])}set duration(e){s(this,["duration"],e)}endOfStream(e){n(this,["endOfStream"],[e],3)}get readyState(){return t(this,["readyState"])}removeSourceBuffer(e){const t=R(e);t>-1&&(this[p].splice(t,1),n(this,["removeSourceBuffer"],[t],1))}setLiveSeekableRange(e,t){n(this,["setLiveSeekableRange"],[e,t],2)}get sourceBuffers(){return this[p]}static isTypeSupported(e){if(!L.has(e)){const t=n(b,["MediaSource","isTypeSupported"],[e]);L.set(e,t)}return L.get(e)}});const O=b.URL=S("URL",class extends URL{});"audioTracks"in b.HTMLMediaElement.prototype&&(v(b,"AudioTrackList",E),v(b,"AudioTrack",w),C.audioTracks={get(){return new E(this)}}),i(b.HTMLMediaElement,C),O.createObjectURL=e=>n(b,["URL","createObjectURL"],[e]),O.revokeObjectURL=e=>n(b,["URL","revokeObjectURL"],[e])},L=new Map;e.f=(e,t,s,n,r)=>{r.map((e=>{delete n[e]})),b(e,n),y(e,t,s,n)}})(self);
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+(e=>{const[t,s,n,r,i,a,o,d,u]=e.g;delete e.g;const c=Symbol(),h=Symbol(),f=Symbol(),p=Symbol(),g=Symbol(),l=Symbol(),m=[],v=(e,t,s)=>e[t]=S(t,s),S=(e,t)=>Object.defineProperty(t,"name",{value:e}),b=(e,t)=>{const r={getContext:{value(e,t){return this[c]||(this[c]=(e.includes("webgl")?g:p)(this,e,t)),this[c]}}},h=v(t,"CanvasGradient",class extends e{addColorStop(...e){n(this,["addColorStop"],e,2)}}),f=v(t,"CanvasPattern",class extends e{setTransform(...e){n(this,["setTransform"],e,2)}}),p=(e,t,r)=>{const i=e[o],c=a(),f={[o]:i,[d]:c,[u]:[]},p=n(e,["getContext"],[t,r],1,c),g="getContextAttributes,getImageData,getLineDash,getTransform,isPointInPath,isPointInStroke,measureText".split(","),l={get:(e,t)=>"string"==typeof t&&t in p?"function"==typeof p[t]?(...e)=>{if(t.startsWith("create")){const r=a();return n(f,[t],e,2,r),"createImageData"===t||"createPattern"===t?(s=`${t}()`,console.warn(`${s} not implemented`),{setTransform:()=>{}}):new h(i,r)}var s;const r=g.includes(t)?1:2;return n(f,[t],e,r)}:p[t]:e[t],set:(e,t,n)=>("string"==typeof t&&t in p?(p[t]!==n&&"function"!=typeof n&&s(f,[t],n),p[t]=n):e[t]=n,!0)};return new Proxy(p,l)},g=(e,t,r)=>{const i=e[o],c=a(),h={[o]:i,[d]:c,[u]:[]},f=n(e,["getContext"],[t,r],1,c),p={get:(e,t)=>"string"==typeof t?"function"!=typeof f[t]?f[t]:(...e)=>n(h,[t],e,m(t)):e[t],set:(e,t,n)=>("string"==typeof t&&t in f?(f[t]!==n&&"function"!=typeof n&&s(h,[t],n),f[t]=n):e[t]=n,!0)};return new Proxy(f,p)},l="checkFramebufferStatus,makeXRCompatible".split(","),m=e=>e.startsWith("create")||e.startsWith("get")||e.startsWith("is")||l.includes(e)?1:2;v(t,"CanvasGradient",h),v(t,"CanvasPattern",f),i(t.HTMLCanvasElement,r)},y=(e,u,c,b)=>{var y,T;b.Audio=S("HTMLAudioElement",class{constructor(e){const t=c.k("audio",a());return t.src=e,t}});const w=class extends e{get enabled(){return t(this,["enabled"])}set enabled(e){s(this,["enabled"],e)}get id(){return t(this,["id"])}get kind(){return t(this,["kind"])}get label(){return t(this,["label"])}get language(){return t(this,["language"])}get sourceBuffer(){return new x(this)}},E=class{constructor(e){const s="audioTracks",r=e[o],i=e[d];return new Proxy({addEventListener(...t){n(e,[s,"addEventListener"],t,3)},getTrackById:(...t)=>n(e,[s,"getTrackById"],t),get length(){return t(e,[s,"length"])},removeEventListener(...t){n(e,[s,"removeEventListener"],t,3)}},{get:(e,t)=>"number"==typeof t?new w(r,i,[s,t]):e[t]})}},k=v(b,"SourceBufferList",class extends Array{constructor(e){super(),this[h]=e}addEventListener(...e){n(this[h],["sourceBuffers","addEventListener"],e,3)}removeEventListener(...e){n(this[h],["sourceBuffers","removeEventListener"],e,3)}}),x=v(b,"SourceBuffer",(T=class extends u{constructor(e){super(e[o],e[d],["sourceBuffers"]),this[y]=[],this[h]=e}abort(){const e=R(this);n(this,[e,"appendWindowStart"],m,1)}addEventListener(...e){const t=R(this);n(this,[t,"addEventListener"],e,3)}appendBuffer(e){this[g].push(["appendBuffer",[e],e]),M(this)}get appendWindowStart(){const e=R(this);return t(this,[e,"appendWindowStart"])}set appendWindowStart(e){const t=R(this);s(this,[t,"appendWindowStart"],e)}get appendWindowEnd(){const e=R(this);return t(this,[e,"appendWindowEnd"])}set appendWindowEnd(e){const t=R(this);s(this,[t,"appendWindowEnd"],e)}get buffered(){const e=this[h],t=R(this);return new B(e[o],e[d],["sourceBuffers",t,"buffered"])}changeType(e){const t=R(this);n(this,[t,"changeType"],[e],2)}get mode(){const e=R(this);return t(this,[e,"mode"])}set mode(e){const t=R(this);s(this,[t,"mode"],e)}remove(e,t){this[g].push(["remove",[e,t]]),M(this)}removeEventListener(...e){const t=R(this);n(this,[t,"removeEventListener"],e,3)}get timestampOffset(){const e=R(this);return t(this,[e,"timestampOffset"])}set timestampOffset(e){const t=R(this);s(this,[t,"timestampOffset"],e)}get updating(){const e=R(this);return t(this,[e,"updating"])}},y=g,T)),B=v(b,"TimeRanges",class extends e{start(...e){return n(this,["start"],e)}end(...e){return n(this,["end"],e)}get length(){return t(this,["length"])}}),R=e=>e?e[h][p].indexOf(e):-1,M=e=>{if(e[g].length){if(!e.updating){const t=e[g].shift();if(t){const s=R(e);n(e,[s,t[0]],t[1],3,void 0,t[2])}}setTimeout((()=>M(e)),50)}},W={buffered:{get(){return this[l]||(this[l]=new B(this[o],this[d],["buffered"]),setTimeout((()=>{this[l]=void 0}),5e3)),this[l]}},readyState:{get(){return 4===this[f]?4:("number"!=typeof this[f]&&(this[f]=t(this,["readyState"]),setTimeout((()=>{this[f]=void 0}),1e3)),this[f])}}};v(b,"MediaSource",class extends u{constructor(){super(c.V),this[p]=new k(this),r(this,"MediaSource",m)}get activeSourceBuffers(){return[]}addSourceBuffer(e){const t=new x(this);return this[p].push(t),n(this,["addSourceBuffer"],[e]),t}clearLiveSeekableRange(){n(this,["clearLiveSeekableRange"],m,2)}get duration(){return t(this,["duration"])}set duration(e){s(this,["duration"],e)}endOfStream(e){n(this,["endOfStream"],[e],3)}get readyState(){return t(this,["readyState"])}removeSourceBuffer(e){const t=R(e);t>-1&&(this[p].splice(t,1),n(this,["removeSourceBuffer"],[t],1))}setLiveSeekableRange(e,t){n(this,["setLiveSeekableRange"],[e,t],2)}get sourceBuffers(){return this[p]}static isTypeSupported(e){if(!L.has(e)){const t=n(b,["MediaSource","isTypeSupported"],[e]);L.set(e,t)}return L.get(e)}});const C=b.URL=S("URL",class extends URL{});"audioTracks"in b.HTMLMediaElement.prototype&&(v(b,"AudioTrackList",E),v(b,"AudioTrack",w),W.audioTracks={get(){return new E(this)}}),i(b.HTMLMediaElement,W),C.createObjectURL=e=>n(b,["URL","createObjectURL"],[e]),C.revokeObjectURL=e=>n(b,["URL","revokeObjectURL"],[e])},L=new Map;e.f=(e,t,s,n,r)=>{r.map((e=>{delete n[e]})),b(e,n),y(e,t,s,n)}})(self);
Index: build/partytown-sw.js
===================================================================
--- build/partytown-sw.js	(revision 3189893)
+++ build/partytown-sw.js	(working copy)
@@ -1 +1,2 @@
-Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})());const e=new Map,t=(e,t)=>({F:e.F,p:t}),r=(e,t)=>new Response(e,{headers:{"content-type":t||"text/html","Cache-Control":"no-store"}});self.oninstall=()=>self.skipWaiting(),self.onactivate=()=>self.clients.claim(),self.onmessage=t=>{const r=t.data,n=e.get(r.F);n&&(e.delete(r.F),clearTimeout(n[1]),n[0](r))},self.onfetch=n=>{const i=n.request,s=new URL(i.url).pathname;s.endsWith("sw.html")?n.respondWith(r('<!DOCTYPE html><html><head><meta charset="utf-8"><script type="module">/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */\n(e=>{const t=()=>{},r=e=>e.length,n=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},i=(e,t)=>e.startsWith(t),s=e=>!(i(e,"webkit")||i(e,"toJSON")||i(e,"constructor")||i(e,"toString")||i(e,"_")&&!["__","_n","_x","_nx"].includes(e)),o=e=>11===e.nodeType&&e.host?"#s":e.nodeName,a=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),c={Anchor:"a",DList:"dl",Image:"img",OList:"ol",Paragraph:"p",Quote:"q",TableCaption:"caption",TableCell:"td",TableCol:"colgroup",TableRow:"tr",TableSection:"tbody",UList:"ul"},l={Graphics:"g",SVG:"svg"},u={preserveBehavior:!1},p=Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})()),d=Symbol(),h=Symbol(),g=new Map,m=new Map,f={},y=new WeakMap,v=(e,t)=>{if(e)return(t=y.get(e))||(t=e[d])||w(e,t=a()),t},$=(e,t,r,n,i)=>{if((r=f[e])&&r.U){if(e===t)return r.U;if(n=r.U.document,"d"===(i=t.split(".").pop()))return n;if("e"===i)return n.documentElement;if("h"===i)return n.head;if("b"===i)return n.body}return g.get(t)},w=(e,t,r)=>{e&&(g.set(t,e),e[d]=t,e[h]=r=Date.now(),r>b+5e3&&(g.forEach(((e,t)=>{e[h]<b&&e.nodeType&&!e.isConnected&&g.delete(t)})),b=r))};let b=0;const S=e.parent,E=document.implementation.createHTMLDocument(),T=S.partytown||{},I=(T.lib||"/~partytown/")+"",R=(e,t,r)=>{const n=((e,t)=>{return r=e,n={value:t},Object.defineProperty(r,"name",{...n,configurable:!0});var r,n})(class extends f[e].U.HTMLElement{},r[0]);return"connectedCallback,disconnectedCallback,attributeChangedCallback,adoptedCallback".split(",").map((r=>n.prototype[r]=function(...n){t.postMessage([15,e,v(this),r,n])})),n.observedAttributes=r[1],n},M=(e,t,r,s,a,c)=>void 0!==t&&(s=typeof t)?"string"===s||"number"===s||"boolean"===s||null==t?[0,t]:"function"===s?[6]:(r=r||new Set)&&Array.isArray(t)?r.has(t)?[1,[]]:r.add(t)&&[1,t.map((t=>M(e,t,r)))]:"object"===s?C(t)?[14,{name:t.name,message:t.message,stack:t.stack}]:""===(a=n(t))?[2,{}]:"Window"===a?[3,[e,e]]:"HTMLCollection"===a||"NodeList"===a?[7,Array.from(t).map((t=>M(e,t,r)[1]))]:a.endsWith("Event")?[5,x(e,t,r)]:"CSSRuleList"===a?[12,Array.from(t).map(L)]:i(a,"CSS")&&a.endsWith("Rule")?[11,L(t)]:"CSSStyleDeclaration"===a?[13,x(e,t,r)]:"Attr"===a?[10,[t.name,t.value]]:t.nodeType?[3,[e,v(t),o(t),c]]:[2,x(e,t,r,!0,!0)]:void 0:t,x=(e,t,r,i,o,a,c,l)=>{if(a={},!r.has(t))for(c in r.add(t),t)s(c)&&(l="path"===c&&n(t).endsWith("Event")?t.composedPath():t[c],(i||"function"!=typeof l)&&(o||""!==l)&&(a[c]=M(e,l,r)));return a},L=e=>{let t,r={};for(t in e)U.includes(t)&&(r[t]=String(e[t]));return r};let N=null;const C=t=>{var r;return N=(null===(r=e.top)||void 0===r?void 0:r.Error)||N,t instanceof N},A=(t,r,n,i)=>r?(n=r[0],i=r[1],0===n?i:4===n?O(t,i):1===n?i.map((e=>A(t,e))):3===n?$(i[0],i[1]):5===n?j(P(t,i)):2===n?P(t,i):8===n?i:9===n?new e[r[2]](i):void 0):void 0,O=(e,{V:t,w:r,L:n},i)=>((i=m.get(n))||(i=function(...i){e.postMessage([9,{V:t,w:r,L:n,R:M(t,this),b:M(t,i)}])},m.set(n,i)),i),j=e=>new("detail"in e?CustomEvent:Event)(e.type,e),P=(e,t,r,n)=>{for(n in r={},t)r[n]=A(e,t[n]);return r},U="cssText,selectorText,href,media,namespaceURI,prefix,name,conditionText".split(","),_=async(e,t)=>{let n,i,s,o,a,c,l={F:t.F},u=r(t.Q),p=0;for(;p<u;p++)try{c=p===u-1,n=t.Q[p],i=n.V,s=n.a,!f[i]&&i.startsWith("f_")&&await new Promise((e=>{let t=0,r=()=>{f[i]||t++>1e3?e():requestAnimationFrame(r)};r()})),1===s[0]&&s[1]in f[i].U?w(new f[i].U[s[1]](...A(e,s[2])),n.w):(o=$(i,n.w),o?(a=H(e,i,o,s,c,n.r),n.d&&("string"==typeof n.d?w(a,n.d):f[n.d.V]={V:n.d.V,U:{document:a}}),"object"==typeof(d=a)&&d&&d.then&&(a=await a,c&&(l.z=!0)),c&&(l.M=M(i,a,void 0,void 0,void 0,n.w))):l.p=n.w+" not found")}catch(e){c?l.p=String(e.stack||e):console.error(e)}var d;return l},H=(e,t,i,s,o,a)=>{let c,l,u,p,d,h=0,g=r(s);for(;h<g;h++){l=s[h],c=s[h+1],u=s[h-1];try{if(!Array.isArray(c))if("string"==typeof l||"number"==typeof l){if(h+1===g&&a)return d={},a.map((e=>d[e]=i[e])),d;i=i[l]}else{if(0===c)return void(i[u]=A(e,l));if("function"==typeof i[u]&&(p=A(e,l),"define"===u&&"CustomElementRegistry"===n(i)&&(p[1]=R(t,e,p[1])),"insertRule"===u&&p[1]>r(i.cssRules)&&(p[1]=r(i.cssRules)),i=i[u].apply(i,p),"play"===u))return Promise.resolve()}}catch(e){if(o)throw e;console.debug(e)}}return i},k=(e,t)=>{let n,i,s,o=t.V,a=t.U,c=a.document,l=\'script[type="text/partytown"]:not([data-ptid]):not([data-pterror])\',d=l+":not([async]):not([defer])";c&&c.body?(n=c.querySelector(d),n||(n=c.querySelector(l)),n?(n.dataset.ptid=i=v(n,o),s={V:o,w:i},n.src?(s.S=n.src,s.H=n.dataset.ptsrc||n.src):s.j=n.innerHTML,e.postMessage([7,s])):(t.x||(t.x=1,((e,t,n)=>{let i,s,o=n._ptf,a=(n.partytown||{}).forward||[],c=(r,n)=>e.postMessage([10,{V:t,q:r,b:M(t,Array.from(n))}]);if(n._ptf=void 0,a.map((e=>{const[t,{preserveBehavior:i}]=(e=>{if("string"==typeof e)return[e,u];const[t,r=u]=e;return[t,{...u,...r}]})(e);s=n,t.split(".").map(((e,t,o)=>{var a;s=s[o[t]]=t+1<r(o)?s[o[t]]||(a=o[t+1],p.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:t,thisObject:r}=((e,t)=>{let r=e;for(let e=0;e<t.length-1;e+=1)r=r[t[e]];return{thisObject:r,methodOrProperty:t.length>0?r[t[t.length-1]]:void 0}})(n,o);"function"==typeof t&&(e=(...e)=>t.apply(r,...e))}return(...t)=>{let r;return e&&(r=e(t)),c(o,t),r}})()}))})),o)for(i=0;i<r(o);i+=2)c(o[i],o[i+1])})(e,o,a),c.dispatchEvent(new CustomEvent("pt0"))),e.postMessage([8,o]))):requestAnimationFrame((()=>k(e,t)))},B=(e,t,r)=>{if(!y.has(r)){y.set(r,t);const n=r.document,i=r.history,s=y.get(r.parent);let o=!1;const a=[],c=e=>{o?e():a.push(e)},l=()=>{e.postMessage([5,{V:t,J:s,S:n.baseURI,T:n.visibilityState}]),setTimeout((()=>{o=!0,a.forEach((e=>{e()}))}))},u=i.pushState.bind(i),p=i.replaceState.bind(i),d=(r,i,s,o)=>()=>{e.postMessage([13,{V:t,type:r,state:i,url:n.baseURI,newUrl:s,oldUrl:o}])};i.pushState=(e,t,r)=>{u(e,t,r),c(d(0,e,null==r?void 0:r.toString()))},i.replaceState=(e,t,r)=>{p(e,t,r),c(d(1,e,null==r?void 0:r.toString()))},r.addEventListener("popstate",(e=>{c(d(2,e.state))})),r.addEventListener("hashchange",(e=>{c(d(3,{},e.newURL,e.oldURL))})),r.addEventListener("ptupdate",(()=>{k(e,f[t])})),n.addEventListener("visibilitychange",(()=>e.postMessage([14,t,n.visibilityState]))),f[t]={V:t,U:r},"complete"===n.readyState?l():r.addEventListener("load",l)}},V=()=>{const e=E.createElement("i"),t=E.createTextNode(""),r=E.createComment(""),n=E.createDocumentFragment(),i=E.createElement("p").attachShadow({mode:"open"}),s=G(S,"IntersectionObserver"),o=G(S,"MutationObserver"),a=G(S,"ResizeObserver"),c=S.performance,l=S.screen,u=[[S.history],[c],[c.navigation],[c.timing],[l],[l.orientation],[S.visualViewport],[s,12],[o,12],[a,12],[t],[r],[n],[i],[e],[e.attributes],[e.classList],[e.dataset],[e.style],[E],[E.doctype]],p=[F("Window",S),F("Node",t)],d=function(e){return JSON.stringify(e,((e,t)=>("function"==typeof t&&(t=String(t)).startsWith(e+"(")&&(t="function "+t),"loadScriptsOnMainThread"===e&&(t=t.map((e=>Array.isArray(e)?e:["string"==typeof e?"string":"regexp","string"==typeof e?e:e.source]))),t)))}(T),h={i:d,v:W(u,p),C:new URL(I,S.location)+"",I:origin,$tabId$:S._pttab};return z(h.v,S,"IntersectionObserverEntry"),h},D=()=>{const e=Object.getOwnPropertyNames(S).map((e=>((e,t,r,n)=>{if(r=t.match(/^(HTML|SVG)(.+)Element$/))return n=r[2],"S"==t[0]?e.createElementNS("http://www.w3.org/2000/svg",l[n]||n.slice(0,2).toLowerCase()+n.slice(2)):e.createElement(c[n]||n)})(E,e))).filter((e=>e)).map((e=>[e]));return W(e,[])},W=(e,t)=>{const r=new Set(["Object"]);return e.filter((e=>e[0])).map((e=>{const t=e[0],r=e[1],i=n(t);return[i,S[i].prototype,t,r]})).map((([e,n,i,s])=>J(r,t,e,n,i,s))),t},F=(e,t,r)=>{let n=[],i=[e,"Object",n];for(r in t)q(n,t,r);return i},J=(e,t,r,i,s,a)=>{if(!e.has(r)){e.add(r);const c=Object.getPrototypeOf(i),l=n(c),u=[],p=Object.getOwnPropertyDescriptors(i);J(e,t,l,c,s,a);for(const e in p)q(u,s,e);t.push([r,l,u,a,o(s)])}},q=(e,t,r,i,o,a)=>{try{s(r)&&isNaN(r[0])&&"all"!==r&&("function"==(o=typeof(i=t[r]))?(String(i).includes("[native")||Object.getPrototypeOf(t)[r])&&e.push([r,5]):"object"===o&&null!=i?"Object"!==(a=n(i))&&"Function"!==a&&self[a]&&e.push([r,i.nodeType||a]):"symbol"!==o&&(r.toUpperCase()===r?e.push([r,6,i]):e.push([r,6])))}catch(e){console.warn(e)}},G=(e,r)=>void 0!==e[r]?new e[r](t):0,z=(e,t,r)=>{void 0!==t[r]&&e.push([r,"Object",Object.keys(t[r].prototype).map((e=>[e,6])),12])};let X;(()=>{const t=e.navigator.serviceWorker;return t.getRegistration().then((e=>(t.addEventListener("message",(t=>{return r=t.data,n=t=>e.active&&e.active.postMessage(t),_(X,r).then(n);var r,n})),(e,t)=>{0===t[0]?e.postMessage([1,V()]):2===t[0]?e.postMessage([3,D()]):((e,t,r)=>{4===t[0]?B(e,a(),S):(r=f[t[1]])&&(7===t[0]?requestAnimationFrame((()=>k(e,r))):6===t[0]&&((e,t,r,n,i)=>{(i=t.U.document.querySelector(`[data-ptid="${r}"]`))&&(n?i.dataset.pterror=n:i.type+="-x",delete i.dataset.ptid),k(e,t)})(e,r,t[2],t[3]))})(e,t)})))})().then((e=>{e&&(X=new Worker(URL.createObjectURL(new Blob([\'/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */\\n(e=>{const t=Symbol(),r=Symbol(),n=Symbol(),i=Symbol(),s=Symbol(),o=Symbol(),a=Symbol(),c=Symbol(),l=new Map,$={},d=new WeakMap,u=[],h={},p={},g=new Map,m=new Map,f="about:blank",w=e=>e.split(","),y=e=>{if(e=h.C+e,new URL(e).origin!=location.origin)throw"Invalid "+e;return e},v=w("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft"),S=w("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling"),b=w("insertBefore,remove,removeChild,replaceChild"),I=w("className,width,height,hidden,innerHTML,innerText,textContent,text"),T=w("setAttribute,setAttributeNS,setProperty"),M=w("addEventListener,dispatchEvent,removeEventListener"),E=M.concat(T,w("add,observe,remove,unobserve")),N=/^[A-Z_]([A-Z0-9-]*[A-Z0-9])?$/,x=()=>{},L=e=>e.length,O=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},R=[],C=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),P="text/partytown",A=(e,t,r)=>Object.defineProperty(e,t,{...r,configurable:!0}),H=(e,t)=>A(e,"name",{value:t}),W=(e,t,r)=>A(e.prototype,t,r),j=(e,t)=>Object.defineProperties(e.prototype,t),k=(e,t,r)=>W(e,t,{value:r,writable:!0});function D(e,t){var r,n;return null!==(n=null===(r=e.loadScriptsOnMainThread)||void 0===r?void 0:r.map((([e,t])=>new RegExp("string"===e?t.replace(/[.*+?^${}()|[\\\\]\\\\\\\\]/g,"\\\\\\\\$&"):t))).some((e=>e.test(t))))&&void 0!==n&&n}Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})());const U=(e,t)=>t in e[o],_=(e,t)=>e[o][t],B=(e,t,r)=>e[o][t]=r,F=(e,t,r,n,i,s)=>{if(!(i=l.get(t))&&r&&p[e]){const o=l.get(s||"");i=p[e].k(r,t,n,o),l.set(t,i)}return i},z=(e,t)=>k(e,"nodeType",t),q=(e,t)=>t.map((t=>W(e,t,{get(){let e=V(this,t),r=m.get(e);return r||(r=$e(this,[t]),m.set(e,r)),r}}))),V=(e,n,i)=>[e[t],e[r],n,...(i||R).map((e=>String(e&&e[t]?e[r]:e)))].join("."),X=(e,t)=>w(t).map((t=>W(e,t,{get(){return U(this,t)||B(this,t,$e(this,[t])),_(this,t)},set(e){_(this,t)!==e&&de(this,[t],e),B(this,t,e)}}))),Z=e=>v.map((t=>W(e,t,{get(){const e=g.get(V(this,t));if("number"==typeof e)return e;const r=$e(this,[t],v);return r&&"object"==typeof r?(Object.entries(r).map((([e,t])=>g.set(V(this,e),t))),r[t]):r}}))),G=(e,t)=>t.map((t=>{e.prototype[t]=function(...e){let r=V(this,t,e),n=g.get(r);return n||(n=ue(this,[t],e),g.set(r,n)),n}})),J=(e,n,i,s,o)=>{return void 0!==i&&(o=typeof i)?"string"===o||"boolean"===o||"number"===o||null==i?[0,i]:"function"===o?[4,{V:e,w:n,L:(a=i,(c=d.get(a))||(d.set(a,c=C()),$[c]=a),c)}]:(s=s||new Set)&&Array.isArray(i)?s.has(i)?[1,[]]:s.add(i)&&[1,i.map((t=>J(e,n,t,s)))]:"object"===o?i[r]?[3,[i[t],i[r]]]:i instanceof Event?[5,K(e,n,i,!1,s)]:Y&&i instanceof TrustedHTML?[0,i.toString()]:i instanceof ArrayBuffer?[8,i]:ArrayBuffer.isView(i)?[9,i.buffer,O(i)]:[2,K(e,n,i,!0,s)]:void 0:i;var a,c},Y="undefined"!=typeof TrustedHTML,K=(e,t,r,n,i,s,o,a)=>{if(s={},!i.has(r))for(o in i.add(r),r)a=r[o],(n||"function"!=typeof a)&&(s[o]=J(e,t,a,i));return s},Q=(e,n)=>e?J(e[t],e[r],n):[0,n],ee=(e,t,r,n,i,s,o,a)=>{if(n){if(i=n[0],s=n[1],0===i||11===i||12===i)return s;if(4===i)return re(r,s);if(6===i)return e&&r.length>0?(...t)=>ue(p[e].U,r,t,1):x;if(3===i)return te(s);if(7===i)return new ie(s.map(te));if(10===i)return new se(s);if(1===i)return s.map((n=>ee(e,t,r,n)));if(14===i)return new ne(s);for(a in o={},s)o[a]=ee(e,t,[...r,a],s[a]);if(13===i)return new p[e].U.CSSStyleDeclaration(e,t,r,o);if(5===i){if("message"===o.type&&o.origin){let e,t=JSON.stringify(o.data),r=u.find((e=>e.m===t));r&&(e=p[r.V],e&&(o.source=e.U,o.origin=e.E.origin))}return new Proxy(new Event(o.type,o),{get:(e,t)=>t in o?o[t]:"function"==typeof e[String(t)]?x:e[String(t)]})}if(2===i)return o}},te=([e,t,r,n])=>t===e&&p[e]?p[e].U:F(e,t,r,void 0,void 0,n),re=(e,{V:t,w:r,G:n,L:i})=>($[i]||d.set($[i]=function(...i){const s=F(t,r,n);return ue(s,e,i)},i),$[i]);class ne extends Error{constructor(e){super(e.message),this.name=e.name,this.message=e.message,this.stack=e.stack}}class ie{constructor(e){(this._=e).map(((e,t)=>this[t]=e))}entries(){return this._.entries()}forEach(e,t){this._.map(e,t)}item(e){return this[e]}keys(){return this._.keys()}get length(){return L(this._)}values(){return this._.values()}[Symbol.iterator](){return this._[Symbol.iterator]()}}const se=class{constructor(e){this.name=e[0],this.value=e[1]}get nodeName(){return this.name}get nodeType(){return 2}},oe=(e,t,r)=>console.warn(`Partytown unable to ${e} cross-origin ${t}: `+r.E),ae=[],ce=(e,n,i,o,a,c)=>{if(e[s]){if(ae.push({V:e[t],w:e[r],a:[...e[s],...n],d:o,r:a}),3===i)h.K([12,{F:C(),Q:[...ae]}],c?[c instanceof ArrayBuffer?c:c.buffer]:void 0),ae.length=0;else if(1===i)return le(!0);h.c=setTimeout(le,20)}},le=e=>{if(clearTimeout(h.c),L(ae)){const t=ae[L(ae)-1],r={F:`${C()}.${h.$tabId$}`,Q:[...ae]};if(ae.length=0,e){const e=((e,t)=>{const r=new XMLHttpRequest;return r.open("POST",y("proxytown"),!1),r.send(JSON.stringify(t)),JSON.parse(r.responseText)})(0,r),n=e.z,i=ee(t.V,t.w,t.a,e.M);if(e.p){if(n)return Promise.reject(e.p);throw new Error(e.p)}return n?Promise.resolve(i):i}h.K([12,r])}},$e=(e,t,r,n)=>h.i.get&&(n=h.i.get(pe(e,t)))!==a?n:n=ce(e,t,1,void 0,r),de=(e,t,r,n)=>{if(h.i.set){if((n=h.i.set({value:r,prevent:c,...pe(e,t)}))===c)return;n!==a&&(r=n)}I.some((e=>t.includes(e)))&&(g.clear(),t[t.length-1]),t=[...t,Q(e,r),0],ce(e,t,2)},ue=(e,t,r,n,i,s,o,c)=>h.i.apply&&(o=h.i.apply({args:r,...pe(e,t)}))!==a?o:(c=t[L(t)-1],t=[...t,Q(e,r)],n=n||(E.includes(c)?2:1),"setAttribute"===c&&U(e,r[0])?B(e,r[0],r[1]):b.includes(c)?(g.clear(),m.clear()):T.includes(c)&&(n=2,g.clear()),o=ce(e,t,n,i,void 0,s)),he=(e,t,r)=>{ce(e,[1,t,Q(e,r)],1)},pe=(e,r)=>({name:r.join("."),continue:a,nodeName:e[n],constructor:O(e),instance:e,window:p[e[t]].U}),ge=(e,t,r)=>{let n={getItem(n){if(r.A)return ue(e,[t,"getItem"],[n],1);oe("get",t,r)},setItem(n,i){r.A?ue(e,[t,"setItem"],[n,i],1):oe("set",t,r)},removeItem(n){r.A?ue(e,[t,"removeItem"],[n],1):oe("remove",t,r)},key(n){if(r.A)return ue(e,[t,"key"],[n],1);oe("key",t,r)},clear(){r.A?ue(e,[t,"clear"],R,1):oe("clear",t,r)},get length(){if(r.A)return $e(e,[t,"length"]);oe("length",t,r)}};e[t]=new Proxy(n,{get:(e,t)=>Reflect.has(e,t)?Reflect.get(e,t):e.getItem(t),set:(e,t,r)=>(e.setItem(t,r),!0),has:(e,t)=>!!Reflect.has(e,t)||"string"==typeof t&&null!==e.getItem(t),deleteProperty:(e,t)=>(e.removeItem(t),!0)})},me=(e,t,r)=>{e[r]=H(class extends t{constructor(e,t,r,i){return super(e,t,r,i||{}),new Proxy(this,{get:(e,t)=>e[t]?e[t]:(e[t]||"string"!=typeof t||e[n][t]||(e[n][t]=$e(e,[t])),e[n][t]),set:(e,t,r)=>(e[n][t]=r,de(e,[t],r),g.clear(),!0)})}setProperty(...e){this[n][e[0]]=e[1],ue(this,["setProperty"],e,2),e[0],g.clear()}getPropertyValue(e){return this[e]}removeProperty(e){let t=this[n][e];return ue(this,["removeProperty"],[e],2),g.clear(),this[n][e]=void 0,t}},r)},fe=(e,t)=>{e[t]=H(class{constructor(e){this.ownerNode=e}get cssRules(){const e=this.ownerNode;return new Proxy({},{get(t,r){const n=String(r);return"item"===n?t=>ye(e,t):"length"===n?we(e).length:isNaN(n)?t[r]:ye(e,n)}})}insertRule(e,t){const r=we(this.ownerNode);return(t=void 0===t?0:t)>=0&&t<=r.length&&(ue(this.ownerNode,["sheet","insertRule"],[e,t],2),r.splice(t,0,0)),this.ownerNode,g.clear(),t}deleteRule(e){ue(this.ownerNode,["sheet","deleteRule"],[e],2),we(this.ownerNode).splice(e,1),this.ownerNode,g.clear()}get type(){return"text/css"}},t);const r={sheet:{get(){return new e[t](this)}}};j(e.HTMLStyleElement,r)},we=(e,t)=>((t=_(e,2))||(t=$e(e,["sheet","cssRules"]),B(e,2,t)),t),ye=(e,t,r)=>(0===(r=we(e))[t]&&(r[t]=$e(e,["sheet","cssRules",parseInt(t,10)])),r[t]),ve="0.10.2-dev1727590485751",Se=(e,t,r,n,i)=>{try{e.l=t,be(e,r)}catch(e){console.error(r,e),i=String(e.stack||e)}return e.l="",i},be=(e,t,r)=>{e.N=1;let n=(e=>e.replace(/([a-zA-Z0-9_$\\\\.\\\\\\\'\\\\"\\\\`])?(\\\\.\\\\.\\\\.)?this(?![a-zA-Z0-9_$:])/g,((e,t,r)=>{const n=(t||"")+(r||"");return null!=t?n+"this":n+"(thi$(this)?window:this)"})))(t);t=`with(this){${n.replace(/\\\\/\\\\/# so/g,"//Xso")}\\\\n;function thi$(t){return t===this}};${(h.i.globalFns||[]).filter((e=>/[a-zA-Z_$][0-9a-zA-Z_$]*/.test(e))).map((e=>`(typeof ${e}==\\\'function\\\'&&(this.${e}=${e}))`)).join(";")};`+(r?"\\\\n//# sourceURL="+r:""),e.A||(t=t.replace(/.postMessage\\\\(/g,`.postMessage(\\\'${e.V}\\\',`)),new Function(t).call(e.U),e.N=0},Ie=(e,t,r)=>{(r=_(e,t))&&setTimeout((()=>r.map((e=>e({type:t})))))},Te=(e,t)=>{for(t=e.E;!t.host&&(t=(e=p[e.J]).E,e.V!==e.J););return t},Me=(e,t,r,n,i,s)=>(n=Te(e,n),i=new URL(t||"",n),r&&h.i.resolveUrl&&(s=h.i.resolveUrl(i,n,r))?s:i),Ee=(e,t,r)=>Me(e,t,r)+"",Ne=(e,t)=>{const r=Te(e),n=new URL(t||"",r);if(h.i.resolveSendBeaconRequestParameters){const e=h.i.resolveSendBeaconRequestParameters(n,r);if(e)return e}return{}},xe=()=>`<script src="${y("partytown.js?v="+ve)}"><\\\\/script>`,Le=e=>class{constructor(){this.s="",this.l=[],this.e=[],this.style={}}get src(){return this.s}set src(t){this.s=t,fetch(Ee(e,t,"image"),{mode:"no-cors",credentials:"include",keepalive:!0}).then((e=>{e.ok||0===e.status?this.l.map((e=>e({type:"load"}))):this.e.map((e=>e({type:"error"})))}),(()=>this.e.forEach((e=>e({type:"error"})))))}addEventListener(e,t){"load"===e&&this.l.push(t),"error"===e&&this.e.push(t)}removeEventListener(e,t){"load"===e&&(this.l=this.l.filter((e=>e!==t))),"error"===e&&(this.e=this.e.filter((e=>e!==t)))}get onload(){return this.l[0]}set onload(e){this.l=[e]}get onerror(){return this.e[0]}set onerror(e){this.e=[e]}},Oe={addEventListener:{value(...e){const t=e[0],r=_(this,t)||[];r.push(e[1]),B(this,t,r)}},async:{get:x,set:x},defer:{get:x,set:x},onload:{get(){let e=_(this,"load");return e&&e[0]||null},set(e){B(this,"load",e?[e]:null)}},onerror:{get(){let e=_(this,"error");return e&&e[0]||null},set(e){B(this,"error",e?[e]:null)}},getAttribute:{value(e){return"src"===e?this.src:ue(this,["getAttribute"],[e])}},setAttribute:{value(e,t){Re.includes(e)?this[e]=t:ue(this,["setAttribute"],[e,t])}}},Re=w("src,type"),Ce=(e,t)=>{const r={innerHTML:Pe,innerText:Pe,src:{get(){return _(this,4)||""},set(e){const r=Ee(t,e,null),n=h.i;e=Ee(t,e,"script"),B(this,4,e),de(this,["src"],e),r!==e&&de(this,["dataset","ptsrc"],r),this.type&&D(n,e)&&de(this,["type"],"text/javascript")}},text:Pe,textContent:Pe,type:{get(){return $e(this,["type"])},set(e){Ae(e)||(B(this,5,e),de(this,["type"],e))}},...Oe};j(e,r)},Pe={get(){const e=$e(this,["type"]);if(Ae(e)){const e=_(this,3);if(e)return e}return $e(this,["innerHTML"])||""},set(e){B(this,3,e)}},Ae=e=>!e||"text/javascript"===e,He=(e,i,s)=>{const o=h.i,a=H(class extends s{appendChild(e){return this.insertBefore(e,null)}get href(){}set href(e){}insertBefore(e,s){const a=e[t]=this[t],c=e[r],l=e[n],$="SCRIPT"===l,d="IFRAME"===l;if($){const t=_(e,3),r=_(e,5);if(t){if(Ae(r)){const r=e.id;if(r&&D(o,r))de(e,["type"],"text/javascript");else{const r=Se(i,c,t,0,""),n=r?"pterror":"ptid",s=r||c;de(e,["type"],P+"-x"),de(e,["dataset",n],s)}}de(e,["innerHTML"],t)}}if(ue(this,["insertBefore"],[e,s],2),d){const t=_(e,0);if(t&&t.startsWith("javascript:")){const e=t.split("javascript:")[1];Se(i,c,e,0,"")}((e,t)=>{let r,n,i=0,s=()=>{p[e]&&p[e].x&&!p[e].y?(r=_(t,1)?"error":"load",n=_(t,r),n&&n.map((e=>e({type:r})))):i++>2e3?(n=_(t,"error"),n&&n.map((e=>e({type:"error"})))):setTimeout(s,9)};s()})(c,e)}return $&&(le(!0),h.K([7,a])),e}get nodeName(){return"#s"===this[n]?"#document-fragment":this[n]}get nodeType(){return 3}get ownerDocument(){return i.n}},"Node");q(a,w("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling")),e.Node=a},We=w("AUDIO,CANVAS,VIDEO"),je=w("Audio,MediaSource"),ke=(e,r,n)=>{j(e,{body:{get:()=>r.e},cookie:{get(){return r.A?$e(this,["cookie"]):(oe("get","cookie",r),"")},set(e){r.A&&de(this,["cookie"],e)}},createElement:{value(e){if(e=e.toUpperCase(),!N.test(e))throw e+" not valid";const r="IFRAME"===e,n=this[t],i=(r?"f_":"")+C();ue(this,["createElement"],[e],2,i);const s=F(n,i,e);if(r)Qe({V:i,J:n,S:f},!0).U.fetch=fetch,de(s,["srcdoc"],xe());else if("SCRIPT"===e){const e=_(s,5);Ae(e)&&de(s,["type"],P)}return s}},createElementNS:{value(e,r){const n=C(),i=F(this[t],n,r,e);return ue(this,["createElementNS"],[e,r],2,n),i}},createTextNode:{value(e){const r=this[t],n=C(),i=F(r,n,"#text");return ue(this,["createTextNode"],[e],2,n),i}},createEvent:{value:e=>new Event(e)},currentScript:{get(){return r.l?F(this[t],r.l,"SCRIPT"):null}},defaultView:{get:()=>n?null:r.U},documentElement:{get:()=>r.o},getElementsByTagName:{value(e){return"BODY"===(e=e.toUpperCase())?[r.e]:"HEAD"===e?[r.s]:ue(this,["getElementsByTagName"],[e])}},head:{get:()=>r.s},images:{get(){return $e(this,["images"])}},scripts:{get(){return $e(this,["scripts"])}},implementation:{get(){return{hasFeature:()=>!0,createHTMLDocument:e=>{const t=C();return ue(this,["implementation","createHTMLDocument"],[e],1,{V:t}),Qe({V:t,J:t,S:r.E+"",T:"hidden"},!0,!0).n}}}},location:{get:()=>r.E,set(e){r.E.href=e+""}},nodeType:{value:9},parentNode:{value:null},parentElement:{value:null},readyState:{value:"complete"},visibilityState:{get:()=>r.T||"visible"}}),X(e,"compatMode,referrer,forms")},De=(e,t)=>{j(e,{parentElement:{get(){return this.parentNode}},parentNode:{get:()=>t.o}})},Ue=(e,t)=>{j(e,{localName:{get(){return this[n].toLowerCase()}},namespaceURI:{get(){return this[i]||"http://www.w3.org/1999/xhtml"}},nodeType:{value:1},tagName:{get(){return this[n]}}}),q(e,S),X(e,"id"),Z(t),G(t,w("getClientRects,getBoundingClientRect"))},_e=(e,t)=>{const r={};w("hash,host,hostname,href,origin,pathname,port,protocol,search").map((e=>{r[e]={get(){let r,n=_(this,4);if("string"!=typeof n){if(r=$e(this,["href"]),""===r)return"protocol"===e?":":"";B(this,4,r),n=new URL(r)[e]}return Me(t,n,null)[e]},set(r){let n;if("href"===e)if((e=>{try{return new URL(e),!0}catch(e){return!1}})(r))n=new URL(r);else{const e=t.E.href;n=Me(t,e,null),n.href=new URL(r+"",n.href)}else n=Me(t,this.href,null),n[e]=r;B(this,4,n.href),de(this,["href"],n.href)}}})),j(e,r)},Be=(e,t)=>{const r={contentDocument:{get(){return Ve(this).n}},contentWindow:{get(){return Ve(this).U}},src:{get(){let e=_(this,0);return e&&e.startsWith("javascript:")?e:(e=Ve(this).E.href,e.startsWith("about:")?"":e)},set(e){if(e)if(e.startsWith("javascript:"))B(this,0,e);else if(!e.startsWith("about:")){let t,r=new XMLHttpRequest,n=Ve(this);n.E.href=e=Ee(n,e,"iframe"),n.y=1,n.A=h.I===n.E.origin,B(this,1,void 0),r.open("GET",e,!1),r.send(),t=r.status,t>199&&t<300?(de(this,["srcdoc"],`<base href="${e}">`+r.responseText.replace(ze,((e,t)=>{const r=[];let n,i=!1;for(;n=qe.exec(t);){let[e]=n;e.startsWith("type=")&&(i=!0,e=e.replace(/(application|text)\\\\/javascript/,P)),r.push(e)}return i||r.push(\\\'type="\\\'+P+\\\'"\\\'),`<script ${r.join(" ")}>`}))+xe()),le(!0),h.K([7,n.V])):(B(this,1,t),n.y=0)}}},...Oe};j(e,r)},Fe="((?:\\\\\\\\w|-)+(?:=(?:(?:\\\\\\\\w|-)+|\\\'[^\\\']*\\\'|\\\\"[^\\\\"]*\\\\")?)?)",ze=new RegExp(`<script\\\\\\\\s*((${Fe}\\\\\\\\s*)*)>`,"mg"),qe=new RegExp(Fe,"mg"),Ve=e=>{const n=e[r];return p[n]||Qe({V:n,J:e[t],S:$e(e,["src"])||f},!0),p[n]},Xe=e=>{const t=(e,t)=>{const{a:r,b:n,c:i,d:s,e:o,f:a}=ue(e,[t],R);return new DOMMatrixReadOnly([r,n,i,s,o,a])},r={...e,getCTM:{value:function(){return t(this,"getCTM")}},getScreenCTM:{value:function(){return t(this,"getScreenCTM")}}};j(e,r)},Ze=(e,t)=>{e.NamedNodeMap=H(class extends t{constructor(e,t,r){return super(e,t,r),new Proxy(this,{get(e,t){const r=Je[t];return r?r.bind(e,[t]):$e(e,[t])},set(e,t,r){if(Je[t])throw new Error("Can\\\'t set read-only property: "+String(t));return de(e,[t],r),!0}})}},"NamedNodeMap")};function Ge(e,...t){return ue(this,e,t,1)}const Je={getNamedItem:Ge,getNamedItemNS:Ge,item:Ge,removeNamedItem:Ge,removeNamedItemNS:Ge,setNamedItem:Ge,setNamedItemNS:Ge},Ye=(a,c,l,$,d,g)=>{let m,v,b,I;const T=class{constructor(e,c,l,$,d){this[t]=e||a,this[r]=c||m||C(),this[s]=l||[],this[n]=$||v,this[i]=d||b,this[o]=I&&I[o]||{},m=v=b=void 0}},E=new(H(class extends URL{assign(){}reload(){}replace(){}},"Location"))(l),N=E.origin===h.I||E.origin===f,x=c===a,R={},P=()=>{let e,t,r=[];for(e in p)t=p[e],t.J!==a||t.B||r.push(t);return r},D=H(class extends T{constructor(){super(a,a),this.addEventListener=(...e)=>{"load"===e[0]?R.N&&setTimeout((()=>e[1]({type:"load"}))):ue(this,["addEventListener"],e,2)};let n,i,o=this,l=0,u=()=>{l||((h.u||(e.g=[$e,de,ue,he,j,C,t,r,s],h.t(y("partytown-media.js?v="+ve)),h.u=e.f,delete e.f),h.u)(T,J,R,o,je),l=1)},p={},f=(e,t,r,n)=>{We.includes(e)&&u();const i=p[e]?p[e]:e.includes("-")?p.UNKNOWN:p.I;return m=t,v=e,b=r,I=n,new i};var M,L;if(o.Window=D,o.name=name+a,He(o,R,T),(e=>{e.NodeList=H(ie,"NodeList")})(o),Ze(o,T),me(o,T,"CSSStyleDeclaration"),((e,t,r)=>{e[r]=H(class extends t{now(){return performance.now()}},r)})(o,T,"Performance"),((e,t)=>{const r="customElements",n=new Map;e[r]={define(i,s,o){n.set(i,s),t[i.toUpperCase()]=s;const a=[s.name,s.observedAttributes];ue(e,[r,"define"],[i,a,o])},get:t=>n.get(t)||ue(e,[r,"get"],[t]),whenDefined:t=>n.has(t)?Promise.resolve():ue(e,[r,"whenDefined"],[t]),upgrade:t=>ue(e,[r,"upgrade"],[t])}})(o,p),h.v.map((([e,t,n,i,c])=>{const l=Ke[e]?V:"EventTarget"===t?J:"Object"===t?T:o[t],$=o[e]=H(12===i?class extends T{constructor(...t){super(),he(this,e,t)}}:o[e]||class extends l{},e);c&&(p[c]=$),n.map((([e,t,n])=>{e in $.prototype||e in l.prototype||("string"==typeof t?W($,e,{get(){if(!U(this,e)){const n=this[r],i=[...this[s],e],c=o[t];c&&B(this,e,new c(a,n,i))}return _(this,e)},set(t){B(this,e,t)}}):5===t?k($,e,(function(...t){return ue(this,[e],t)})):t>0&&(void 0!==n?k($,e,n):W($,e,{get(){return $e(this,[e])},set(t){return de(this,[e],t)}})))}))})),w("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((t=>{delete D.prototype[t],t in o||(n=e[t],null!=n&&(o[t]="function"!=typeof n||n.toString().startsWith("class")?n:n.bind(e)))})),Object.getOwnPropertyNames(e).map((t=>{t in o||(o[t]=e[t])})),je.map((e=>A(o,e,{get:()=>(u(),o[e])}))),"trustedTypes"in e&&(o.trustedTypes=e.trustedTypes),Ue(o.Element,o.HTMLElement),ke(o.Document,R,g),M=o.DocumentFragment,z(M,11),q(M,S),_e(o.HTMLAnchorElement,R),L=o.HTMLFormElement,j(L,{}),X(L,"elements"),Be(o.HTMLIFrameElement),Ce(o.HTMLScriptElement,R),Xe(o.SVGGraphicsElement),De(o.HTMLHeadElement,R),De(o.HTMLBodyElement,R),((e,t)=>{j(e,{parentElement:{value:null},parentNode:{get:()=>t.n}})})(o.HTMLHtmlElement,R),fe(o,"CSSStyleSheet"),z(o.Comment,8),z(o.DocumentType,10),Object.assign(R,{V:a,J:c,U:new Proxy(o,{get:(e,t)=>{var r;if("string"!=typeof t||isNaN(t))return(null===(r=h.i.mainWindowAccessors)||void 0===r?void 0:r.includes(t))?$e(this,[t]):e[t];{let e=P()[t];return e?e.U:void 0}},has:()=>!0}),n:f("#document",a+".d"),o:f("HTML",a+".e"),s:f("HEAD",a+".h"),e:f("BODY",a+".b"),E:E,T:$,A:N,B:x,k:f}),o.requestAnimationFrame=e=>setTimeout((()=>e(performance.now())),9),o.cancelAnimationFrame=e=>clearTimeout(e),o.requestIdleCallback=(e,t)=>(t=Date.now(),setTimeout((()=>e({didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-t))})),1)),o.cancelIdleCallback=e=>clearTimeout(e),ge(o,"localStorage",R),ge(o,"sessionStorage",R),N||(o.indexeddb=void 0),d)i={},o.history={pushState(e){i=e},replaceState(e){i=e},get state(){return i},length:0},o.indexeddb=void 0;else{const e=o.history.pushState.bind(o.history),t=o.history.replaceState.bind(o.history);o.history.pushState=(t,r,n)=>{!1!==R.$propagateHistoryChange$&&e(t,r,n)},o.history.replaceState=(e,r,n)=>{!1!==R.$propagateHistoryChange$&&t(e,r,n)}}o.Worker=void 0}get body(){return R.e}get document(){return R.n}get documentElement(){return R.o}fetch(e,t){return e="string"==typeof e||e instanceof URL?String(e):e.url,fetch(Ee(R,e,"fetch"),t)}get frames(){return R.U}get frameElement(){return x?null:F(c,a,"IFRAME")}get globalThis(){return R.U}get head(){return R.s}get length(){return P().length}get location(){return E}set location(e){E.href=e+""}get Image(){return Le(R)}get navigator(){return(e=>{const t={sendBeacon:(t,r)=>{try{return fetch(Ee(e,t,null),{method:"POST",body:r,mode:"no-cors",keepalive:!0,...Ne(e,t)}),!0}catch(e){return console.error(e),!1}}};for(let e in navigator)t[e]=navigator[e];return new Proxy(t,{set:(e,t,r)=>(navigator[t]=r,!0),get:(t,r)=>Object.prototype.hasOwnProperty.call(t,r)?t[r]:$e(e.U,["navigator",r])})})(R)}get origin(){return E.origin}set origin(e){}get parent(){for(let e in p)if(p[e].V===c)return p[e].U;return R.U}postMessage(...e){p[e[0]]&&(L(u)>50&&u.splice(0,5),u.push({V:e[0],m:JSON.stringify(e[1])}),e=e.slice(1)),ue(this,["postMessage"],e,3)}get self(){return R.U}get top(){for(let e in p)if(p[e].B)return p[e].U;return R.U}get window(){return R.U}get XMLHttpRequest(){const e=XMLHttpRequest,t=String(e),r=H(class extends e{open(...e){e[1]=Ee(R,e[1],"xhr"),super.open(...e)}set withCredentials(e){h.i.allowXhrCredentials&&(super.withCredentials=e)}toString(){return t}},O(e));return r.prototype.constructor.toString=()=>t,r}},"Window"),V=class extends T{constructor(e,t,r,n){return super(e,t,r,n),new Proxy(this,{get:(e,t)=>$e(e,[t]),set:(e,t,r)=>(de(e,[t],r),!0)})}},J=class extends T{};return M.map((e=>J.prototype[e]=function(...t){return ue(this,[e],t,2)})),X(D,"devicePixelRatio"),Z(D),G(D,["getComputedStyle"]),new D,R},Ke={DOMStringMap:1,NamedNodeMap:1},Qe=({V:e,J:t,S:r,T:n},i,s)=>(p[e]||(p[e]=Ye(e,t,r,n,i,s)),h.K([7,e]),p[e]),et=[],tt=t=>{const r=t.data,n=r[0],i=r[1];if(h.x)if(7===n)(async e=>{let t,r=e.V,n=e.w,i=F(r,n,"SCRIPT"),s=e.j,o=e.S,a=e.H,c="",l=p[r],$=["text/jscript","text/javascript","text/x-javascript","application/javascript","application/x-javascript","text/ecmascript","text/x-ecmascript","application/ecmascript"];if(o)try{if(o=Me(l,o,"script")+"",B(i,4,o),t=await fetch(o),t.ok){let e=t.headers.get("content-type");$.some((t=>{var r,n,i;return null===(i=null===(r=null==e?void 0:e.toLowerCase)||void 0===r?void 0:(n=r.call(e)).includes)||void 0===i?void 0:i.call(n,t)}))&&(s=await t.text(),l.l=n,be(l,s,a||o)),Ie(i,"load")}else c=t.statusText,Ie(i,"error")}catch(e){console.error(e),c=String(e.stack||e),Ie(i,"error")}else s&&(c=Se(l,n,s,0,c));l.l="",h.K([6,r,n,c])})(i);else if(9===n)(({V:e,w:t,L:r,R:n,b:i})=>{if($[r])try{$[r].apply(ee(e,t,[],n),ee(e,t,[],i))}catch(e){console.error(e)}})(i);else if(10===n)(({V:e,q:t,b:r})=>{try{let n=p[e].U,i=0,s=L(t);for(;i<s;i++)i+1<s?n=n[t[i]]:n[t[i]].apply(n,ee(null,e,[],r))}catch(e){console.error(e)}})(i);else if(5===n)Qe(i);else if(8===n)p[i].x=1,p[i].y=0;else if(14===n)p[i].T=r[2];else if(13===n){const e=i.V,t=p[e];t.E.href=i.url,function(e,t,r){const n=t.U.history;switch(r.type){case 0:t.$propagateHistoryChange$=!1;try{n.pushState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0;break;case 1:t.$propagateHistoryChange$=!1;try{n.replaceState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0}}(i.V,t,i)}else 15===n&&((e,t,r,n,i)=>{const s=F(t,r);s&&"function"==typeof s[n]&&s[n].apply(s,i)})(...r);else 1===n?((t=>{const r=h.i=JSON.parse(t.i),n=t.I;h.t=importScripts.bind(e),h.v=t.v,h.C=t.C,h.I=n,h.K=postMessage.bind(e),h.P=t.P,h.$tabId$=t.$tabId$,e.importScripts=void 0,delete e.postMessage,delete e.WorkerGlobalScope,w("resolveUrl,resolveSendBeaconRequestParameters,get,set,apply").map((e=>{r[e]&&(r[e]=new Function("return "+r[e])())}))})(i),h.K([2])):3===n?(h.v=[...h.v,...i],h.x=1,h.K([4]),[...et].map(tt),et.length=0):et.push(t)};e.onmessage=tt,postMessage([0])})(self);\\n\'],{type:"text/javascript"})),{name:"Partytown 🎉"}),X.onmessage=t=>{const r=t.data;12===r[0]?_(X,r[1]):e(X,r)},S.addEventListener("pt1",(e=>B(X,v(e.detail.frameElement),e.detail))))}))})(window);\n<\/script></head></html>')):s.endsWith("proxytown")&&n.respondWith((n=>new Promise((async i=>{const s=await n.clone().json(),o=await(r=>new Promise((async n=>{const i=((e,t)=>{const r=t.split(".").pop();let n=e.find((e=>e.url.endsWith(`?${r}`)));return n||(n=[...e].sort(((e,t)=>e.url>t.url?-1:e.url<t.url?1:0))[0]),n})([...await self.clients.matchAll()],r.F);if(i){const s=[n,setTimeout((()=>{e.delete(r.F),n(t(r,"Timeout"))}),1e4)];e.set(r.F,s),i.postMessage(r)}else n(t(r,"NoParty"))})))(s);i(r(JSON.stringify(o),"application/json"))})))(i))};
\ No newline at end of file
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
+Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})());const e=new Map,t=(e,t)=>({F:e.F,p:t}),r=(e,t)=>new Response(e,{headers:{"content-type":t||"text/html","Cache-Control":"no-store"}});self.oninstall=()=>self.skipWaiting(),self.onactivate=()=>self.clients.claim(),self.onmessage=t=>{const r=t.data,n=e.get(r.F);n&&(e.delete(r.F),clearTimeout(n[1]),n[0](r))},self.onfetch=n=>{const i=n.request,s=new URL(i.url).pathname;s.endsWith("sw.html")?n.respondWith(r('<!DOCTYPE html><html><head><meta charset="utf-8"><script type="module">/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */\n(e=>{const t=()=>{},r=e=>e.length,n=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},i=(e,t)=>e.startsWith(t),s=e=>!(i(e,"webkit")||i(e,"toJSON")||i(e,"constructor")||i(e,"toString")||i(e,"_")&&!["__","_n","_x","_nx"].includes(e)),o=e=>11===e.nodeType&&e.host?"#s":e.nodeName,a=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),c={Anchor:"a",DList:"dl",Image:"img",OList:"ol",Paragraph:"p",Quote:"q",TableCaption:"caption",TableCell:"td",TableCol:"colgroup",TableRow:"tr",TableSection:"tbody",UList:"ul"},l={Graphics:"g",SVG:"svg"},u={preserveBehavior:!1},p=Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})()),d=Symbol(),h=Symbol(),g=new Map,m=new Map,f={},y=new WeakMap,v=(e,t)=>{if(e)return(t=y.get(e))||(t=e[d])||w(e,t=a()),t},$=(e,t,r,n,i)=>{if((r=f[e])&&r.U){if(e===t)return r.U;if(n=r.U.document,"d"===(i=t.split(".").pop()))return n;if("e"===i)return n.documentElement;if("h"===i)return n.head;if("b"===i)return n.body}return g.get(t)},w=(e,t,r)=>{e&&(g.set(t,e),e[d]=t,e[h]=r=Date.now(),r>b+5e3&&(g.forEach(((e,t)=>{e[h]<b&&e.nodeType&&!e.isConnected&&g.delete(t)})),b=r))};let b=0;const S=e.parent,E=document.implementation.createHTMLDocument(),T=S.partytown||{},I=(T.lib||"/~partytown/")+"",R=(e,t,r)=>{const n=((e,t)=>{return r=e,n={value:t},Object.defineProperty(r,"name",{...n,configurable:!0});var r,n})(class extends f[e].U.HTMLElement{},r[0]);return"connectedCallback,disconnectedCallback,attributeChangedCallback,adoptedCallback".split(",").map((r=>n.prototype[r]=function(...n){t.postMessage([15,e,v(this),r,n])})),n.observedAttributes=r[1],n},M=(e,t,r,s,a,c)=>void 0!==t&&(s=typeof t)?"string"===s||"number"===s||"boolean"===s||null==t?[0,t]:"function"===s?[6]:(r=r||new Set)&&Array.isArray(t)?r.has(t)?[1,[]]:r.add(t)&&[1,t.map((t=>M(e,t,r)))]:"object"===s?C(t)?[14,{name:t.name,message:t.message,stack:t.stack}]:""===(a=n(t))?[2,{}]:"Window"===a?[3,[e,e]]:"HTMLCollection"===a||"NodeList"===a?[7,Array.from(t).map((t=>M(e,t,r)[1]))]:a.endsWith("Event")?[5,x(e,t,r)]:"CSSRuleList"===a?[12,Array.from(t).map(L)]:i(a,"CSS")&&a.endsWith("Rule")?[11,L(t)]:"CSSStyleDeclaration"===a?[13,x(e,t,r)]:"Attr"===a?[10,[t.name,t.value]]:t.nodeType?[3,[e,v(t),o(t),c]]:[2,x(e,t,r,!0,!0)]:void 0:t,x=(e,t,r,i,o,a,c,l)=>{if(a={},!r.has(t))for(c in r.add(t),t)s(c)&&(l="path"===c&&n(t).endsWith("Event")?t.composedPath():t[c],(i||"function"!=typeof l)&&(o||""!==l)&&(a[c]=M(e,l,r)));return a},L=e=>{let t,r={};for(t in e)U.includes(t)&&(r[t]=String(e[t]));return r};let N=null;const C=t=>{var r;return N=(null===(r=e.top)||void 0===r?void 0:r.Error)||N,t instanceof N},A=(t,r,n,i)=>r?(n=r[0],i=r[1],0===n?i:4===n?O(t,i):1===n?i.map((e=>A(t,e))):3===n?$(i[0],i[1]):5===n?j(P(t,i)):2===n?P(t,i):8===n?i:9===n?new e[r[2]](i):void 0):void 0,O=(e,{V:t,w:r,L:n},i)=>((i=m.get(n))||(i=function(...i){e.postMessage([9,{V:t,w:r,L:n,R:M(t,this),b:M(t,i)}])},m.set(n,i)),i),j=e=>new("detail"in e?CustomEvent:Event)(e.type,e),P=(e,t,r,n)=>{for(n in r={},t)r[n]=A(e,t[n]);return r},U="cssText,selectorText,href,media,namespaceURI,prefix,name,conditionText".split(","),_=async(e,t)=>{let n,i,s,o,a,c,l={F:t.F},u=r(t.Q),p=0;for(;p<u;p++)try{c=p===u-1,n=t.Q[p],i=n.V,s=n.a,!f[i]&&i.startsWith("f_")&&await new Promise((e=>{let t=0,r=()=>{f[i]||t++>1e3?e():requestAnimationFrame(r)};r()})),1===s[0]&&s[1]in f[i].U?w(new f[i].U[s[1]](...A(e,s[2])),n.w):(o=$(i,n.w),o?(a=H(e,i,o,s,c,n.r),n.d&&("string"==typeof n.d?w(a,n.d):f[n.d.V]={V:n.d.V,U:{document:a}}),"object"==typeof(d=a)&&d&&d.then&&(a=await a,c&&(l.z=!0)),c&&(l.M=M(i,a,void 0,void 0,void 0,n.w))):l.p=n.w+" not found")}catch(e){c?l.p=String(e.stack||e):console.error(e)}var d;return l},H=(e,t,i,s,o,a)=>{let c,l,u,p,d,h=0,g=r(s);for(;h<g;h++){l=s[h],c=s[h+1],u=s[h-1];try{if(!Array.isArray(c))if("string"==typeof l||"number"==typeof l){if(h+1===g&&a)return d={},a.map((e=>d[e]=i[e])),d;i=i[l]}else{if(0===c)return void(i[u]=A(e,l));if("function"==typeof i[u]&&(p=A(e,l),"define"===u&&"CustomElementRegistry"===n(i)&&(p[1]=R(t,e,p[1])),"insertRule"===u&&p[1]>r(i.cssRules)&&(p[1]=r(i.cssRules)),i=i[u].apply(i,p),"play"===u))return Promise.resolve()}}catch(e){if(o)throw e;console.debug(e)}}return i},k=(e,t)=>{let n,i,s,o=t.V,a=t.U,c=a.document,l=\'script[type="text/partytown"]:not([data-ptid]):not([data-pterror])\',d=l+":not([async]):not([defer])";c&&c.body?(n=c.querySelector(d),n||(n=c.querySelector(l)),n?(n.dataset.ptid=i=v(n,o),s={V:o,w:i},n.src?(s.S=n.src,s.H=n.dataset.ptsrc||n.src):s.j=n.innerHTML,e.postMessage([7,s])):(t.x||(t.x=1,((e,t,n)=>{let i,s,o=n._ptf,a=(n.partytown||{}).forward||[],c=(r,n)=>e.postMessage([10,{V:t,q:r,b:M(t,Array.from(n))}]);if(n._ptf=void 0,a.map((e=>{const[t,{preserveBehavior:i}]=(e=>{if("string"==typeof e)return[e,u];const[t,r=u]=e;return[t,{...u,...r}]})(e);s=n,t.split(".").map(((e,t,o)=>{var a;s=s[o[t]]=t+1<r(o)?s[o[t]]||(a=o[t+1],p.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:t,thisObject:r}=((e,t)=>{let r=e;for(let e=0;e<t.length-1;e+=1)r=r[t[e]];return{thisObject:r,methodOrProperty:t.length>0?r[t[t.length-1]]:void 0}})(n,o);"function"==typeof t&&(e=(...e)=>t.apply(r,...e))}return(...t)=>{let r;return e&&(r=e(t)),c(o,t),r}})()}))})),o)for(i=0;i<r(o);i+=2)c(o[i],o[i+1])})(e,o,a),c.dispatchEvent(new CustomEvent("pt0"))),e.postMessage([8,o]))):requestAnimationFrame((()=>k(e,t)))},B=(e,t,r)=>{if(!y.has(r)){y.set(r,t);const n=r.document,i=r.history,s=y.get(r.parent);let o=!1;const a=[],c=e=>{o?e():a.push(e)},l=()=>{e.postMessage([5,{V:t,J:s,S:n.baseURI,T:n.visibilityState}]),setTimeout((()=>{o=!0,a.forEach((e=>{e()}))}))},u=i.pushState.bind(i),p=i.replaceState.bind(i),d=(r,i,s,o)=>()=>{e.postMessage([13,{V:t,type:r,state:i,url:n.baseURI,newUrl:s,oldUrl:o}])};i.pushState=(e,t,r)=>{u(e,t,r),c(d(0,e,null==r?void 0:r.toString()))},i.replaceState=(e,t,r)=>{p(e,t,r),c(d(1,e,null==r?void 0:r.toString()))},r.addEventListener("popstate",(e=>{c(d(2,e.state))})),r.addEventListener("hashchange",(e=>{c(d(3,{},e.newURL,e.oldURL))})),r.addEventListener("ptupdate",(()=>{k(e,f[t])})),n.addEventListener("visibilitychange",(()=>e.postMessage([14,t,n.visibilityState]))),f[t]={V:t,U:r},"complete"===n.readyState?l():r.addEventListener("load",l)}},V=()=>{const e=E.createElement("i"),t=E.createTextNode(""),r=E.createComment(""),n=E.createDocumentFragment(),i=E.createElement("p").attachShadow({mode:"open"}),s=G(S,"IntersectionObserver"),o=G(S,"MutationObserver"),a=G(S,"ResizeObserver"),c=S.performance,l=S.screen,u=[[S.history],[c],[c.navigation],[c.timing],[l],[l.orientation],[S.visualViewport],[s,12],[o,12],[a,12],[t],[r],[n],[i],[e],[e.attributes],[e.classList],[e.dataset],[e.style],[E],[E.doctype]],p=[F("Window",S),F("Node",t)],d=function(e){return JSON.stringify(e,((e,t)=>("function"==typeof t&&(t=String(t)).startsWith(e+"(")&&(t="function "+t),"loadScriptsOnMainThread"===e&&(t=t.map((e=>Array.isArray(e)?e:["string"==typeof e?"string":"regexp","string"==typeof e?e:e.source]))),t)))}(T),h={i:d,v:W(u,p),C:new URL(I,S.location)+"",I:origin,$tabId$:S._pttab};return z(h.v,S,"IntersectionObserverEntry"),h},D=()=>{const e=Object.getOwnPropertyNames(S).map((e=>((e,t,r,n)=>{if(r=t.match(/^(HTML|SVG)(.+)Element$/))return n=r[2],"S"==t[0]?e.createElementNS("http://www.w3.org/2000/svg",l[n]||n.slice(0,2).toLowerCase()+n.slice(2)):e.createElement(c[n]||n)})(E,e))).filter((e=>e)).map((e=>[e]));return W(e,[])},W=(e,t)=>{const r=new Set(["Object"]);return e.filter((e=>e[0])).map((e=>{const t=e[0],r=e[1],i=n(t);return[i,S[i].prototype,t,r]})).map((([e,n,i,s])=>J(r,t,e,n,i,s))),t},F=(e,t,r)=>{let n=[],i=[e,"Object",n];for(r in t)q(n,t,r);return i},J=(e,t,r,i,s,a)=>{if(!e.has(r)){e.add(r);const c=Object.getPrototypeOf(i),l=n(c),u=[],p=Object.getOwnPropertyDescriptors(i);J(e,t,l,c,s,a);for(const e in p)q(u,s,e);t.push([r,l,u,a,o(s)])}},q=(e,t,r,i,o,a)=>{try{s(r)&&isNaN(r[0])&&"all"!==r&&("function"==(o=typeof(i=t[r]))?(String(i).includes("[native")||Object.getPrototypeOf(t)[r])&&e.push([r,5]):"object"===o&&null!=i?"Object"!==(a=n(i))&&"Function"!==a&&self[a]&&e.push([r,i.nodeType||a]):"symbol"!==o&&(r.toUpperCase()===r?e.push([r,6,i]):e.push([r,6])))}catch(e){console.warn(e)}},G=(e,r)=>void 0!==e[r]?new e[r](t):0,z=(e,t,r)=>{void 0!==t[r]&&e.push([r,"Object",Object.keys(t[r].prototype).map((e=>[e,6])),12])};let X;(()=>{const t=e.navigator.serviceWorker;return t.getRegistration().then((e=>(t.addEventListener("message",(t=>{return r=t.data,n=t=>e.active&&e.active.postMessage(t),_(X,r).then(n);var r,n})),(e,t)=>{0===t[0]?e.postMessage([1,V()]):2===t[0]?e.postMessage([3,D()]):((e,t,r)=>{4===t[0]?B(e,a(),S):(r=f[t[1]])&&(7===t[0]?requestAnimationFrame((()=>k(e,r))):6===t[0]&&((e,t,r,n,i)=>{(i=t.U.document.querySelector(`[data-ptid="${r}"]`))&&(n?i.dataset.pterror=n:i.type+="-x",delete i.dataset.ptid),k(e,t)})(e,r,t[2],t[3]))})(e,t)})))})().then((e=>{e&&(X=new Worker(URL.createObjectURL(new Blob([\'/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */\\n(e=>{const t=Symbol(),r=Symbol(),n=Symbol(),i=Symbol(),s=Symbol(),o=Symbol(),a=Symbol(),c=Symbol(),l=new Map,$={},d=new WeakMap,u=[],h={},p={},g=new Map,m=new Map,f="about:blank",w=e=>e.split(","),y=e=>{if(e=h.C+e,new URL(e).origin!=location.origin)throw"Invalid "+e;return e},v=w("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft"),S=w("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling"),b=w("insertBefore,remove,removeChild,replaceChild"),I=w("className,width,height,hidden,innerHTML,innerText,textContent,text"),T=w("setAttribute,setAttributeNS,setProperty"),M=w("addEventListener,dispatchEvent,removeEventListener"),E=M.concat(T,w("add,observe,remove,unobserve")),N=/^[A-Z_]([A-Z0-9-]*[A-Z0-9])?$/,x=()=>{},L=e=>e.length,O=e=>{var t,r,n;try{const r=null===(t=null==e?void 0:e.constructor)||void 0===t?void 0:t.name;if(r)return r}catch(e){}try{const t=null===(n=null===(r=null==e?void 0:e.__zone_symbol__originalInstance)||void 0===r?void 0:r.constructor)||void 0===n?void 0:n.name;if(t)return t}catch(e){}return""},R=[],C=()=>Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36),P="text/partytown",A=(e,t,r)=>Object.defineProperty(e,t,{...r,configurable:!0}),H=(e,t)=>A(e,"name",{value:t}),W=(e,t,r)=>A(e.prototype,t,r),j=(e,t)=>Object.defineProperties(e.prototype,t),k=(e,t,r)=>W(e,t,{value:r,writable:!0});function D(e,t){var r,n;return null!==(n=null===(r=e.loadScriptsOnMainThread)||void 0===r?void 0:r.map((([e,t])=>new RegExp("string"===e?t.replace(/[.*+?^${}()|[\\\\]\\\\\\\\]/g,"\\\\\\\\$&"):t))).some((e=>e.test(t))))&&void 0!==n&&n}Object.freeze((()=>{const e=new Set;let t=[];do{Object.getOwnPropertyNames(t).forEach((r=>{"function"==typeof t[r]&&e.add(r)}))}while((t=Object.getPrototypeOf(t))!==Object.prototype);return Array.from(e)})());const U=(e,t)=>t in e[o],_=(e,t)=>e[o][t],B=(e,t,r)=>e[o][t]=r,F=(e,t,r,n,i,s)=>{if(!(i=l.get(t))&&r&&p[e]){const o=l.get(s||"");i=p[e].k(r,t,n,o),l.set(t,i)}return i},z=(e,t)=>k(e,"nodeType",t),q=(e,t)=>t.map((t=>W(e,t,{get(){let e=V(this,t),r=m.get(e);return r||(r=$e(this,[t]),m.set(e,r)),r}}))),V=(e,n,i)=>[e[t],e[r],n,...(i||R).map((e=>String(e&&e[t]?e[r]:e)))].join("."),X=(e,t)=>w(t).map((t=>W(e,t,{get(){return U(this,t)||B(this,t,$e(this,[t])),_(this,t)},set(e){_(this,t)!==e&&de(this,[t],e),B(this,t,e)}}))),Z=e=>v.map((t=>W(e,t,{get(){const e=g.get(V(this,t));if("number"==typeof e)return e;const r=$e(this,[t],v);return r&&"object"==typeof r?(Object.entries(r).map((([e,t])=>g.set(V(this,e),t))),r[t]):r}}))),G=(e,t)=>t.map((t=>{e.prototype[t]=function(...e){let r=V(this,t,e),n=g.get(r);return n||(n=ue(this,[t],e),g.set(r,n)),n}})),J=(e,n,i,s,o)=>{return void 0!==i&&(o=typeof i)?"string"===o||"boolean"===o||"number"===o||null==i?[0,i]:"function"===o?[4,{V:e,w:n,L:(a=i,(c=d.get(a))||(d.set(a,c=C()),$[c]=a),c)}]:(s=s||new Set)&&Array.isArray(i)?s.has(i)?[1,[]]:s.add(i)&&[1,i.map((t=>J(e,n,t,s)))]:"object"===o?i[r]?[3,[i[t],i[r]]]:i instanceof Event?[5,K(e,n,i,!1,s)]:Y&&i instanceof TrustedHTML?[0,i.toString()]:i instanceof ArrayBuffer?[8,i]:ArrayBuffer.isView(i)?[9,i.buffer,O(i)]:[2,K(e,n,i,!0,s)]:void 0:i;var a,c},Y="undefined"!=typeof TrustedHTML,K=(e,t,r,n,i,s,o,a)=>{if(s={},!i.has(r))for(o in i.add(r),r)a=r[o],(n||"function"!=typeof a)&&(s[o]=J(e,t,a,i));return s},Q=(e,n)=>e?J(e[t],e[r],n):[0,n],ee=(e,t,r,n,i,s,o,a)=>{if(n){if(i=n[0],s=n[1],0===i||11===i||12===i)return s;if(4===i)return re(r,s);if(6===i)return e&&r.length>0?(...t)=>ue(p[e].U,r,t,1):x;if(3===i)return te(s);if(7===i)return new ie(s.map(te));if(10===i)return new se(s);if(1===i)return s.map((n=>ee(e,t,r,n)));if(14===i)return new ne(s);for(a in o={},s)o[a]=ee(e,t,[...r,a],s[a]);if(13===i)return new p[e].U.CSSStyleDeclaration(e,t,r,o);if(5===i){if("message"===o.type&&o.origin){let e,t=JSON.stringify(o.data),r=u.find((e=>e.m===t));r&&(e=p[r.V],e&&(o.source=e.U,o.origin=e.E.origin))}return new Proxy(new Event(o.type,o),{get:(e,t)=>t in o?o[t]:"function"==typeof e[String(t)]?x:e[String(t)]})}if(2===i)return o}},te=([e,t,r,n])=>t===e&&p[e]?p[e].U:F(e,t,r,void 0,void 0,n),re=(e,{V:t,w:r,G:n,L:i})=>($[i]||d.set($[i]=function(...i){const s=F(t,r,n);return ue(s,e,i)},i),$[i]);class ne extends Error{constructor(e){super(e.message),this.name=e.name,this.message=e.message,this.stack=e.stack}}class ie{constructor(e){(this._=e).map(((e,t)=>this[t]=e))}entries(){return this._.entries()}forEach(e,t){this._.map(e,t)}item(e){return this[e]}keys(){return this._.keys()}get length(){return L(this._)}values(){return this._.values()}[Symbol.iterator](){return this._[Symbol.iterator]()}}const se=class{constructor(e){this.name=e[0],this.value=e[1]}get nodeName(){return this.name}get nodeType(){return 2}},oe=(e,t,r)=>console.warn(`Partytown unable to ${e} cross-origin ${t}: `+r.E),ae=[],ce=(e,n,i,o,a,c)=>{if(e[s]){if(ae.push({V:e[t],w:e[r],a:[...e[s],...n],d:o,r:a}),3===i)h.K([12,{F:C(),Q:[...ae]}],c?[c instanceof ArrayBuffer?c:c.buffer]:void 0),ae.length=0;else if(1===i)return le(!0);h.c=setTimeout(le,20)}},le=e=>{if(clearTimeout(h.c),L(ae)){const t=ae[L(ae)-1],r={F:`${C()}.${h.$tabId$}`,Q:[...ae]};if(ae.length=0,e){const e=((e,t)=>{const r=new XMLHttpRequest;return r.open("POST",y("proxytown"),!1),r.send(JSON.stringify(t)),JSON.parse(r.responseText)})(0,r),n=e.z,i=ee(t.V,t.w,t.a,e.M);if(e.p){if(n)return Promise.reject(e.p);throw new Error(e.p)}return n?Promise.resolve(i):i}h.K([12,r])}},$e=(e,t,r,n)=>h.i.get&&(n=h.i.get(pe(e,t)))!==a?n:n=ce(e,t,1,void 0,r),de=(e,t,r,n)=>{if(h.i.set){if((n=h.i.set({value:r,prevent:c,...pe(e,t)}))===c)return;n!==a&&(r=n)}I.some((e=>t.includes(e)))&&(g.clear(),t[t.length-1]),t=[...t,Q(e,r),0],ce(e,t,2)},ue=(e,t,r,n,i,s,o,c)=>h.i.apply&&(o=h.i.apply({args:r,...pe(e,t)}))!==a?o:(c=t[L(t)-1],t=[...t,Q(e,r)],n=n||(E.includes(c)?2:1),"setAttribute"===c&&U(e,r[0])?B(e,r[0],r[1]):b.includes(c)?(g.clear(),m.clear()):T.includes(c)&&(n=2,g.clear()),o=ce(e,t,n,i,void 0,s)),he=(e,t,r)=>{ce(e,[1,t,Q(e,r)],1)},pe=(e,r)=>({name:r.join("."),continue:a,nodeName:e[n],constructor:O(e),instance:e,window:p[e[t]].U}),ge=(e,t,r)=>{let n={getItem(n){if(r.A)return ue(e,[t,"getItem"],[n],1);oe("get",t,r)},setItem(n,i){r.A?ue(e,[t,"setItem"],[n,i],1):oe("set",t,r)},removeItem(n){r.A?ue(e,[t,"removeItem"],[n],1):oe("remove",t,r)},key(n){if(r.A)return ue(e,[t,"key"],[n],1);oe("key",t,r)},clear(){r.A?ue(e,[t,"clear"],R,1):oe("clear",t,r)},get length(){if(r.A)return $e(e,[t,"length"]);oe("length",t,r)}};e[t]=new Proxy(n,{get:(e,t)=>Reflect.has(e,t)?Reflect.get(e,t):e.getItem(t),set:(e,t,r)=>(e.setItem(t,r),!0),has:(e,t)=>!!Reflect.has(e,t)||"string"==typeof t&&null!==e.getItem(t),deleteProperty:(e,t)=>(e.removeItem(t),!0)})},me=(e,t,r)=>{e[r]=H(class extends t{constructor(e,t,r,i){return super(e,t,r,i||{}),new Proxy(this,{get:(e,t)=>e[t]?e[t]:(e[t]||"string"!=typeof t||e[n][t]||(e[n][t]=$e(e,[t])),e[n][t]),set:(e,t,r)=>(e[n][t]=r,de(e,[t],r),g.clear(),!0)})}setProperty(...e){this[n][e[0]]=e[1],ue(this,["setProperty"],e,2),e[0],g.clear()}getPropertyValue(e){return this[e]}removeProperty(e){let t=this[n][e];return ue(this,["removeProperty"],[e],2),g.clear(),this[n][e]=void 0,t}},r)},fe=(e,t)=>{e[t]=H(class{constructor(e){this.ownerNode=e}get cssRules(){const e=this.ownerNode;return new Proxy({},{get(t,r){const n=String(r);return"item"===n?t=>ye(e,t):"length"===n?we(e).length:isNaN(n)?t[r]:ye(e,n)}})}insertRule(e,t){const r=we(this.ownerNode);return(t=void 0===t?0:t)>=0&&t<=r.length&&(ue(this.ownerNode,["sheet","insertRule"],[e,t],2),r.splice(t,0,0)),this.ownerNode,g.clear(),t}deleteRule(e){ue(this.ownerNode,["sheet","deleteRule"],[e],2),we(this.ownerNode).splice(e,1),this.ownerNode,g.clear()}get type(){return"text/css"}},t);const r={sheet:{get(){return new e[t](this)}}};j(e.HTMLStyleElement,r)},we=(e,t)=>((t=_(e,2))||(t=$e(e,["sheet","cssRules"]),B(e,2,t)),t),ye=(e,t,r)=>(0===(r=we(e))[t]&&(r[t]=$e(e,["sheet","cssRules",parseInt(t,10)])),r[t]),ve="0.10.2-dev1727590485751",Se=(e,t,r,n,i)=>{try{e.l=t,be(e,r)}catch(e){console.error(r,e),i=String(e.stack||e)}return e.l="",i},be=(e,t,r)=>{e.N=1;let n=(e=>e.replace(/([a-zA-Z0-9_$\\\\.\\\\\\\'\\\\"\\\\`])?(\\\\.\\\\.\\\\.)?this(?![a-zA-Z0-9_$:])/g,((e,t,r)=>{const n=(t||"")+(r||"");return null!=t?n+"this":n+"(thi$(this)?window:this)"})))(t);t=`with(this){${n.replace(/\\\\/\\\\/# so/g,"//Xso")}\\\\n;function thi$(t){return t===this}};${(h.i.globalFns||[]).filter((e=>/[a-zA-Z_$][0-9a-zA-Z_$]*/.test(e))).map((e=>`(typeof ${e}==\\\'function\\\'&&(this.${e}=${e}))`)).join(";")};`+(r?"\\\\n//# sourceURL="+r:""),e.A||(t=t.replace(/.postMessage\\\\(/g,`.postMessage(\\\'${e.V}\\\',`)),new Function(t).call(e.U),e.N=0},Ie=(e,t,r)=>{(r=_(e,t))&&setTimeout((()=>r.map((e=>e({type:t})))))},Te=(e,t)=>{for(t=e.E;!t.host&&(t=(e=p[e.J]).E,e.V!==e.J););return t},Me=(e,t,r,n,i,s)=>(n=Te(e,n),i=new URL(t||"",n),r&&h.i.resolveUrl&&(s=h.i.resolveUrl(i,n,r))?s:i),Ee=(e,t,r)=>Me(e,t,r)+"",Ne=(e,t)=>{const r=Te(e),n=new URL(t||"",r);if(h.i.resolveSendBeaconRequestParameters){const e=h.i.resolveSendBeaconRequestParameters(n,r);if(e)return e}return{}},xe=()=>`<script src="${y("partytown.js?v="+ve)}"><\\\\/script>`,Le=e=>class{constructor(){this.s="",this.l=[],this.e=[],this.style={}}get src(){return this.s}set src(t){this.s=t,fetch(Ee(e,t,"image"),{mode:"no-cors",credentials:"include",keepalive:!0}).then((e=>{e.ok||0===e.status?this.l.map((e=>e({type:"load"}))):this.e.map((e=>e({type:"error"})))}),(()=>this.e.forEach((e=>e({type:"error"})))))}addEventListener(e,t){"load"===e&&this.l.push(t),"error"===e&&this.e.push(t)}removeEventListener(e,t){"load"===e&&(this.l=this.l.filter((e=>e!==t))),"error"===e&&(this.e=this.e.filter((e=>e!==t)))}get onload(){return this.l[0]}set onload(e){this.l=[e]}get onerror(){return this.e[0]}set onerror(e){this.e=[e]}},Oe={addEventListener:{value(...e){const t=e[0],r=_(this,t)||[];r.push(e[1]),B(this,t,r)}},async:{get:x,set:x},defer:{get:x,set:x},onload:{get(){let e=_(this,"load");return e&&e[0]||null},set(e){B(this,"load",e?[e]:null)}},onerror:{get(){let e=_(this,"error");return e&&e[0]||null},set(e){B(this,"error",e?[e]:null)}},getAttribute:{value(e){return"src"===e?this.src:ue(this,["getAttribute"],[e])}},setAttribute:{value(e,t){Re.includes(e)?this[e]=t:ue(this,["setAttribute"],[e,t])}}},Re=w("src,type"),Ce=(e,t)=>{const r={innerHTML:Pe,innerText:Pe,src:{get(){return _(this,4)||""},set(e){const r=Ee(t,e,null),n=h.i;e=Ee(t,e,"script"),B(this,4,e),de(this,["src"],e),r!==e&&de(this,["dataset","ptsrc"],r),this.type&&D(n,e)&&de(this,["type"],"text/javascript")}},text:Pe,textContent:Pe,type:{get(){return $e(this,["type"])},set(e){Ae(e)||(B(this,5,e),de(this,["type"],e))}},...Oe};j(e,r)},Pe={get(){const e=$e(this,["type"]);if(Ae(e)){const e=_(this,3);if(e)return e}return $e(this,["innerHTML"])||""},set(e){B(this,3,e)}},Ae=e=>!e||"text/javascript"===e,He=(e,i,s)=>{const o=h.i,a=H(class extends s{appendChild(e){return this.insertBefore(e,null)}get href(){}set href(e){}insertBefore(e,s){const a=e[t]=this[t],c=e[r],l=e[n],$="SCRIPT"===l,d="IFRAME"===l;if($){const t=_(e,3),r=_(e,5);if(t){if(Ae(r)){const r=e.id;if(r&&D(o,r))de(e,["type"],"text/javascript");else{const r=Se(i,c,t,0,""),n=r?"pterror":"ptid",s=r||c;de(e,["type"],P+"-x"),de(e,["dataset",n],s)}}de(e,["innerHTML"],t)}}if(ue(this,["insertBefore"],[e,s],2),d){const t=_(e,0);if(t&&t.startsWith("javascript:")){const e=t.split("javascript:")[1];Se(i,c,e,0,"")}((e,t)=>{let r,n,i=0,s=()=>{p[e]&&p[e].x&&!p[e].y?(r=_(t,1)?"error":"load",n=_(t,r),n&&n.map((e=>e({type:r})))):i++>2e3?(n=_(t,"error"),n&&n.map((e=>e({type:"error"})))):setTimeout(s,9)};s()})(c,e)}return $&&(le(!0),h.K([7,a])),e}get nodeName(){return"#s"===this[n]?"#document-fragment":this[n]}get nodeType(){return 3}get ownerDocument(){return i.n}},"Node");q(a,w("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling")),e.Node=a},We=w("AUDIO,CANVAS,VIDEO"),je=w("Audio,MediaSource"),ke=(e,r,n)=>{j(e,{body:{get:()=>r.e},cookie:{get(){return r.A?$e(this,["cookie"]):(oe("get","cookie",r),"")},set(e){r.A&&de(this,["cookie"],e)}},createElement:{value(e){if(e=e.toUpperCase(),!N.test(e))throw e+" not valid";const r="IFRAME"===e,n=this[t],i=(r?"f_":"")+C();ue(this,["createElement"],[e],2,i);const s=F(n,i,e);if(r)Qe({V:i,J:n,S:f},!0).U.fetch=fetch,de(s,["srcdoc"],xe());else if("SCRIPT"===e){const e=_(s,5);Ae(e)&&de(s,["type"],P)}return s}},createElementNS:{value(e,r){const n=C(),i=F(this[t],n,r,e);return ue(this,["createElementNS"],[e,r],2,n),i}},createTextNode:{value(e){const r=this[t],n=C(),i=F(r,n,"#text");return ue(this,["createTextNode"],[e],2,n),i}},createEvent:{value:e=>new Event(e)},currentScript:{get(){return r.l?F(this[t],r.l,"SCRIPT"):null}},defaultView:{get:()=>n?null:r.U},documentElement:{get:()=>r.o},getElementsByTagName:{value(e){return"BODY"===(e=e.toUpperCase())?[r.e]:"HEAD"===e?[r.s]:ue(this,["getElementsByTagName"],[e])}},head:{get:()=>r.s},images:{get(){return $e(this,["images"])}},scripts:{get(){return $e(this,["scripts"])}},implementation:{get(){return{hasFeature:()=>!0,createHTMLDocument:e=>{const t=C();return ue(this,["implementation","createHTMLDocument"],[e],1,{V:t}),Qe({V:t,J:t,S:r.E+"",T:"hidden"},!0,!0).n}}}},location:{get:()=>r.E,set(e){r.E.href=e+""}},nodeType:{value:9},parentNode:{value:null},parentElement:{value:null},readyState:{value:"complete"},visibilityState:{get:()=>r.T||"visible"}}),X(e,"compatMode,referrer,forms")},De=(e,t)=>{j(e,{parentElement:{get(){return this.parentNode}},parentNode:{get:()=>t.o}})},Ue=(e,t)=>{j(e,{localName:{get(){return this[n].toLowerCase()}},namespaceURI:{get(){return this[i]||"http://www.w3.org/1999/xhtml"}},nodeType:{value:1},tagName:{get(){return this[n]}}}),q(e,S),X(e,"id"),Z(t),G(t,w("getClientRects,getBoundingClientRect"))},_e=(e,t)=>{const r={};w("hash,host,hostname,href,origin,pathname,port,protocol,search").map((e=>{r[e]={get(){let r,n=_(this,4);if("string"!=typeof n){if(r=$e(this,["href"]),""===r)return"protocol"===e?":":"";B(this,4,r),n=new URL(r)[e]}return Me(t,n,null)[e]},set(r){let n;if("href"===e)if((e=>{try{return new URL(e),!0}catch(e){return!1}})(r))n=new URL(r);else{const e=t.E.href;n=Me(t,e,null),n.href=new URL(r+"",n.href)}else n=Me(t,this.href,null),n[e]=r;B(this,4,n.href),de(this,["href"],n.href)}}})),j(e,r)},Be=(e,t)=>{const r={contentDocument:{get(){return Ve(this).n}},contentWindow:{get(){return Ve(this).U}},src:{get(){let e=_(this,0);return e&&e.startsWith("javascript:")?e:(e=Ve(this).E.href,e.startsWith("about:")?"":e)},set(e){if(e)if(e.startsWith("javascript:"))B(this,0,e);else if(!e.startsWith("about:")){let t,r=new XMLHttpRequest,n=Ve(this);n.E.href=e=Ee(n,e,"iframe"),n.y=1,n.A=h.I===n.E.origin,B(this,1,void 0),r.open("GET",e,!1),r.send(),t=r.status,t>199&&t<300?(de(this,["srcdoc"],`<base href="${e}">`+r.responseText.replace(ze,((e,t)=>{const r=[];let n,i=!1;for(;n=qe.exec(t);){let[e]=n;e.startsWith("type=")&&(i=!0,e=e.replace(/(application|text)\\\\/javascript/,P)),r.push(e)}return i||r.push(\\\'type="\\\'+P+\\\'"\\\'),`<script ${r.join(" ")}>`}))+xe()),le(!0),h.K([7,n.V])):(B(this,1,t),n.y=0)}}},...Oe};j(e,r)},Fe="((?:\\\\\\\\w|-)+(?:=(?:(?:\\\\\\\\w|-)+|\\\'[^\\\']*\\\'|\\\\"[^\\\\"]*\\\\")?)?)",ze=new RegExp(`<script\\\\\\\\s*((${Fe}\\\\\\\\s*)*)>`,"mg"),qe=new RegExp(Fe,"mg"),Ve=e=>{const n=e[r];return p[n]||Qe({V:n,J:e[t],S:$e(e,["src"])||f},!0),p[n]},Xe=e=>{const t=(e,t)=>{const{a:r,b:n,c:i,d:s,e:o,f:a}=ue(e,[t],R);return new DOMMatrixReadOnly([r,n,i,s,o,a])},r={...e,getCTM:{value:function(){return t(this,"getCTM")}},getScreenCTM:{value:function(){return t(this,"getScreenCTM")}}};j(e,r)},Ze=(e,t)=>{e.NamedNodeMap=H(class extends t{constructor(e,t,r){return super(e,t,r),new Proxy(this,{get(e,t){const r=Je[t];return r?r.bind(e,[t]):$e(e,[t])},set(e,t,r){if(Je[t])throw new Error("Can\\\'t set read-only property: "+String(t));return de(e,[t],r),!0}})}},"NamedNodeMap")};function Ge(e,...t){return ue(this,e,t,1)}const Je={getNamedItem:Ge,getNamedItemNS:Ge,item:Ge,removeNamedItem:Ge,removeNamedItemNS:Ge,setNamedItem:Ge,setNamedItemNS:Ge},Ye=(a,c,l,$,d,g)=>{let m,v,b,I;const T=class{constructor(e,c,l,$,d){this[t]=e||a,this[r]=c||m||C(),this[s]=l||[],this[n]=$||v,this[i]=d||b,this[o]=I&&I[o]||{},m=v=b=void 0}},E=new(H(class extends URL{assign(){}reload(){}replace(){}},"Location"))(l),N=E.origin===h.I||E.origin===f,x=c===a,R={},P=()=>{let e,t,r=[];for(e in p)t=p[e],t.J!==a||t.B||r.push(t);return r},D=H(class extends T{constructor(){super(a,a),this.addEventListener=(...e)=>{"load"===e[0]?R.N&&setTimeout((()=>e[1]({type:"load"}))):ue(this,["addEventListener"],e,2)};let n,i,o=this,l=0,u=()=>{l||((h.u||(e.g=[$e,de,ue,he,j,C,t,r,s],h.t(y("partytown-media.js?v="+ve)),h.u=e.f,delete e.f),h.u)(T,J,R,o,je),l=1)},p={},f=(e,t,r,n)=>{We.includes(e)&&u();const i=p[e]?p[e]:e.includes("-")?p.UNKNOWN:p.I;return m=t,v=e,b=r,I=n,new i};var M,L;if(o.Window=D,o.name=name+a,He(o,R,T),(e=>{e.NodeList=H(ie,"NodeList")})(o),Ze(o,T),me(o,T,"CSSStyleDeclaration"),((e,t,r)=>{e[r]=H(class extends t{now(){return performance.now()}},r)})(o,T,"Performance"),((e,t)=>{const r="customElements",n=new Map;e[r]={define(i,s,o){n.set(i,s),t[i.toUpperCase()]=s;const a=[s.name,s.observedAttributes];ue(e,[r,"define"],[i,a,o])},get:t=>n.get(t)||ue(e,[r,"get"],[t]),whenDefined:t=>n.has(t)?Promise.resolve():ue(e,[r,"whenDefined"],[t]),upgrade:t=>ue(e,[r,"upgrade"],[t])}})(o,p),h.v.map((([e,t,n,i,c])=>{const l=Ke[e]?V:"EventTarget"===t?J:"Object"===t?T:o[t],$=o[e]=H(12===i?class extends T{constructor(...t){super(),he(this,e,t)}}:o[e]||class extends l{},e);c&&(p[c]=$),n.map((([e,t,n])=>{e in $.prototype||e in l.prototype||("string"==typeof t?W($,e,{get(){if(!U(this,e)){const n=this[r],i=[...this[s],e],c=o[t];c&&B(this,e,new c(a,n,i))}return _(this,e)},set(t){B(this,e,t)}}):5===t?k($,e,(function(...t){return ue(this,[e],t)})):t>0&&(void 0!==n?k($,e,n):W($,e,{get(){return $e(this,[e])},set(t){return de(this,[e],t)}})))}))})),w("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((t=>{delete D.prototype[t],t in o||(n=e[t],null!=n&&(o[t]="function"!=typeof n||n.toString().startsWith("class")?n:n.bind(e)))})),Object.getOwnPropertyNames(e).map((t=>{t in o||(o[t]=e[t])})),je.map((e=>A(o,e,{get:()=>(u(),o[e])}))),"trustedTypes"in e&&(o.trustedTypes=e.trustedTypes),Ue(o.Element,o.HTMLElement),ke(o.Document,R,g),M=o.DocumentFragment,z(M,11),q(M,S),_e(o.HTMLAnchorElement,R),L=o.HTMLFormElement,j(L,{}),X(L,"elements"),Be(o.HTMLIFrameElement),Ce(o.HTMLScriptElement,R),Xe(o.SVGGraphicsElement),De(o.HTMLHeadElement,R),De(o.HTMLBodyElement,R),((e,t)=>{j(e,{parentElement:{value:null},parentNode:{get:()=>t.n}})})(o.HTMLHtmlElement,R),fe(o,"CSSStyleSheet"),z(o.Comment,8),z(o.DocumentType,10),Object.assign(R,{V:a,J:c,U:new Proxy(o,{get:(e,t)=>{var r;if("string"!=typeof t||isNaN(t))return(null===(r=h.i.mainWindowAccessors)||void 0===r?void 0:r.includes(t))?$e(this,[t]):e[t];{let e=P()[t];return e?e.U:void 0}},has:()=>!0}),n:f("#document",a+".d"),o:f("HTML",a+".e"),s:f("HEAD",a+".h"),e:f("BODY",a+".b"),E:E,T:$,A:N,B:x,k:f}),o.requestAnimationFrame=e=>setTimeout((()=>e(performance.now())),9),o.cancelAnimationFrame=e=>clearTimeout(e),o.requestIdleCallback=(e,t)=>(t=Date.now(),setTimeout((()=>e({didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-t))})),1)),o.cancelIdleCallback=e=>clearTimeout(e),ge(o,"localStorage",R),ge(o,"sessionStorage",R),N||(o.indexeddb=void 0),d)i={},o.history={pushState(e){i=e},replaceState(e){i=e},get state(){return i},length:0},o.indexeddb=void 0;else{const e=o.history.pushState.bind(o.history),t=o.history.replaceState.bind(o.history);o.history.pushState=(t,r,n)=>{!1!==R.$propagateHistoryChange$&&e(t,r,n)},o.history.replaceState=(e,r,n)=>{!1!==R.$propagateHistoryChange$&&t(e,r,n)}}o.Worker=void 0}get body(){return R.e}get document(){return R.n}get documentElement(){return R.o}fetch(e,t){return e="string"==typeof e||e instanceof URL?String(e):e.url,fetch(Ee(R,e,"fetch"),t)}get frames(){return R.U}get frameElement(){return x?null:F(c,a,"IFRAME")}get globalThis(){return R.U}get head(){return R.s}get length(){return P().length}get location(){return E}set location(e){E.href=e+""}get Image(){return Le(R)}get navigator(){return(e=>{const t={sendBeacon:(t,r)=>{try{return fetch(Ee(e,t,null),{method:"POST",body:r,mode:"no-cors",keepalive:!0,...Ne(e,t)}),!0}catch(e){return console.error(e),!1}}};for(let e in navigator)t[e]=navigator[e];return new Proxy(t,{set:(e,t,r)=>(navigator[t]=r,!0),get:(t,r)=>Object.prototype.hasOwnProperty.call(t,r)?t[r]:$e(e.U,["navigator",r])})})(R)}get origin(){return E.origin}set origin(e){}get parent(){for(let e in p)if(p[e].V===c)return p[e].U;return R.U}postMessage(...e){p[e[0]]&&(L(u)>50&&u.splice(0,5),u.push({V:e[0],m:JSON.stringify(e[1])}),e=e.slice(1)),ue(this,["postMessage"],e,3)}get self(){return R.U}get top(){for(let e in p)if(p[e].B)return p[e].U;return R.U}get window(){return R.U}get XMLHttpRequest(){const e=XMLHttpRequest,t=String(e),r=H(class extends e{open(...e){e[1]=Ee(R,e[1],"xhr"),super.open(...e)}set withCredentials(e){h.i.allowXhrCredentials&&(super.withCredentials=e)}toString(){return t}},O(e));return r.prototype.constructor.toString=()=>t,r}},"Window"),V=class extends T{constructor(e,t,r,n){return super(e,t,r,n),new Proxy(this,{get:(e,t)=>$e(e,[t]),set:(e,t,r)=>(de(e,[t],r),!0)})}},J=class extends T{};return M.map((e=>J.prototype[e]=function(...t){return ue(this,[e],t,2)})),X(D,"devicePixelRatio"),Z(D),G(D,["getComputedStyle"]),new D,R},Ke={DOMStringMap:1,NamedNodeMap:1},Qe=({V:e,J:t,S:r,T:n},i,s)=>(p[e]||(p[e]=Ye(e,t,r,n,i,s)),h.K([7,e]),p[e]),et=[],tt=t=>{const r=t.data,n=r[0],i=r[1];if(h.x)if(7===n)(async e=>{let t,r=e.V,n=e.w,i=F(r,n,"SCRIPT"),s=e.j,o=e.S,a=e.H,c="",l=p[r],$=["text/jscript","text/javascript","text/x-javascript","application/javascript","application/x-javascript","text/ecmascript","text/x-ecmascript","application/ecmascript"];if(o)try{if(o=Me(l,o,"script")+"",B(i,4,o),t=await fetch(o),t.ok){let e=t.headers.get("content-type");$.some((t=>{var r,n,i;return null===(i=null===(r=null==e?void 0:e.toLowerCase)||void 0===r?void 0:(n=r.call(e)).includes)||void 0===i?void 0:i.call(n,t)}))&&(s=await t.text(),l.l=n,be(l,s,a||o)),Ie(i,"load")}else c=t.statusText,Ie(i,"error")}catch(e){console.error(e),c=String(e.stack||e),Ie(i,"error")}else s&&(c=Se(l,n,s,0,c));l.l="",h.K([6,r,n,c])})(i);else if(9===n)(({V:e,w:t,L:r,R:n,b:i})=>{if($[r])try{$[r].apply(ee(e,t,[],n),ee(e,t,[],i))}catch(e){console.error(e)}})(i);else if(10===n)(({V:e,q:t,b:r})=>{try{let n=p[e].U,i=0,s=L(t);for(;i<s;i++)i+1<s?n=n[t[i]]:n[t[i]].apply(n,ee(null,e,[],r))}catch(e){console.error(e)}})(i);else if(5===n)Qe(i);else if(8===n)p[i].x=1,p[i].y=0;else if(14===n)p[i].T=r[2];else if(13===n){const e=i.V,t=p[e];t.E.href=i.url,function(e,t,r){const n=t.U.history;switch(r.type){case 0:t.$propagateHistoryChange$=!1;try{n.pushState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0;break;case 1:t.$propagateHistoryChange$=!1;try{n.replaceState(r.state,"",r.newUrl)}catch(e){}t.$propagateHistoryChange$=!0}}(i.V,t,i)}else 15===n&&((e,t,r,n,i)=>{const s=F(t,r);s&&"function"==typeof s[n]&&s[n].apply(s,i)})(...r);else 1===n?((t=>{const r=h.i=JSON.parse(t.i),n=t.I;h.t=importScripts.bind(e),h.v=t.v,h.C=t.C,h.I=n,h.K=postMessage.bind(e),h.P=t.P,h.$tabId$=t.$tabId$,e.importScripts=void 0,delete e.postMessage,delete e.WorkerGlobalScope,w("resolveUrl,resolveSendBeaconRequestParameters,get,set,apply").map((e=>{r[e]&&(r[e]=new Function("return "+r[e])())}))})(i),h.K([2])):3===n?(h.v=[...h.v,...i],h.x=1,h.K([4]),[...et].map(tt),et.length=0):et.push(t)};e.onmessage=tt,postMessage([0])})(self);\\n\'],{type:"text/javascript"})),{name:"Partytown 🎉"}),X.onmessage=t=>{const r=t.data;12===r[0]?_(X,r[1]):e(X,r)},S.addEventListener("pt1",(e=>B(X,v(e.detail.frameElement),e.detail))))}))})(window);\n<\/script></head></html>')):s.endsWith("proxytown")&&n.respondWith((n=>new Promise((async i=>{const s=await n.clone().json(),o=await(r=>new Promise((async n=>{const i=((e,t)=>{const r=t.split(".").pop();let n=e.find((e=>e.url.endsWith(`?${r}`)));return n||(n=[...e].sort(((e,t)=>e.url>t.url?-1:e.url<t.url?1:0))[0]),n})([...await self.clients.matchAll()],r.F);if(i){const s=[n,setTimeout((()=>{e.delete(r.F),n(t(r,"Timeout"))}),1e4)];e.set(r.F,s),i.postMessage(r)}else n(t(r,"NoParty"))})))(s);i(r(JSON.stringify(o),"application/json"))})))(i))};
Index: build/partytown.js
===================================================================
--- build/partytown.js	(revision 3189893)
+++ build/partytown.js	(working copy)
@@ -1 +1,2 @@
+/* Partytown 0.10.2-dev1727590485751 - MIT builder.io */
 const t={preserveBehavior:!1},e=e=>{if("string"==typeof e)return[e,t];const[n,r=t]=e;return[n,{...t,...r}]},n=Object.freeze((()=>{const t=new Set;let e=[];do{Object.getOwnPropertyNames(e).forEach((n=>{"function"==typeof e[n]&&t.add(n)}))}while((e=Object.getPrototypeOf(e))!==Object.prototype);return Array.from(t)})());!function(t,r,o,i,a,s,c,d,l,p,u=t,f){function h(){f||(f=1,"/"==(c=(s.lib||"/~partytown/")+(s.debug?"debug/":""))[0]&&(l=r.querySelectorAll('script[type="text/partytown"]'),i!=t?i.dispatchEvent(new CustomEvent("pt1",{detail:t})):(d=setTimeout(v,999999999),r.addEventListener("pt0",w),a?y(1):o.serviceWorker?o.serviceWorker.register(c+(s.swPath||"partytown-sw.js"),{scope:c}).then((function(t){t.active?y():t.installing&&t.installing.addEventListener("statechange",(function(t){"activated"==t.target.state&&y()}))}),console.error):v())))}function y(e){p=r.createElement(e?"script":"iframe"),t._pttab=Date.now(),e||(p.style.display="block",p.style.width="0",p.style.height="0",p.style.border="0",p.style.visibility="hidden",p.setAttribute("aria-hidden",!0)),p.src=c+"partytown-"+(e?"atomics.js?v=0.10.2-dev1727590485751":"sandbox-sw.html?"+t._pttab),r.querySelector(s.sandboxParent||"body").appendChild(p)}function v(n,o){for(w(),i==t&&(s.forward||[]).map((function(n){const[r]=e(n);delete t[r.split(".")[0]]})),n=0;n<l.length;n++)(o=r.createElement("script")).innerHTML=l[n].innerHTML,o.nonce=s.nonce,r.head.appendChild(o);p&&p.parentNode.removeChild(p)}function w(){clearTimeout(d)}s=t.partytown||{},i==t&&(s.forward||[]).map((function(r){const[o,{preserveBehavior:i}]=e(r);u=t,o.split(".").map((function(e,r,o){var a;u=u[o[r]]=r+1<o.length?u[o[r]]||(a=o[r+1],n.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:n,thisObject:r}=((t,e)=>{let n=t;for(let t=0;t<e.length-1;t+=1)n=n[e[t]];return{thisObject:n,methodOrProperty:e.length>0?n[e[e.length-1]]:void 0}})(t,o);"function"==typeof n&&(e=(...t)=>n.apply(r,...t))}return function(){let n;return e&&(n=e(arguments)),(t._ptf=t._ptf||[]).push(o,arguments),n}})()}))})),"complete"==r.readyState?h():(t.addEventListener("DOMContentLoaded",h),t.addEventListener("load",h))}(window,document,navigator,top,window.crossOriginIsolated);
\ No newline at end of file
Index: hooks.php
===================================================================
--- hooks.php	(revision 3189893)
+++ hooks.php	(working copy)
@@ -21,7 +21,13 @@
 function plwwo_register_default_scripts( WP_Scripts $scripts ): void {
 	// The source code for partytown.js is built from <https://github.com/BuilderIO/partytown/blob/b292a14047a0c12ca05ba97df1833935d42fdb66/src/lib/main/snippet.ts>.
 	// See webpack config in the WordPress/performance repo: <https://github.com/WordPress/performance/blob/282a068f3eb2575d37aeb9034e894e7140fcddca/webpack.config.js#L84-L130>.
-	$partytown_js = file_get_contents( __DIR__ . '/build/partytown.js' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- It's a local filesystem path not a remote request.
+	if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
+		$partytown_js_path = '/build/debug/partytown.js';
+	} else {
+		$partytown_js_path = '/build/partytown.js';
+	}
+
+	$partytown_js = file_get_contents( __DIR__ . $partytown_js_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- It's a local filesystem path not a remote request.
 	if ( false === $partytown_js ) {
 		return;
 	}
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -94,6 +94,12 @@
 
 == Changelog ==
 
+= n.e.x.t =
+
+**Enhancements**
+
+* Serve unminified scripts when `SCRIPT_DEBUG` is enabled. ([1643](https://github.com/WordPress/performance/pull/1643))
+
 = 0.1.1 =
 
 **Enhancements**

webp-uploads

Important

Stable tag change: 2.2.0 → 2.3.0

svn status:

M       helper.php
M       hooks.php
M       load.php
M       picture-element.php
M       readme.txt
svn diff
Index: helper.php
===================================================================
--- helper.php	(revision 3189893)
+++ helper.php	(working copy)
@@ -468,3 +468,27 @@
 
 	return null;
 }
+
+/**
+ * Retrieves the MIME type of a file, checking the file directly if possible,
+ * and falling back to the attachment's MIME type if needed.
+ *
+ * The function attempts to determine the MIME type directly from the file.
+ * If that information is unavailable, it uses the MIME type from the attachment metadata.
+ * If neither is available, it defaults to an empty string.
+ *
+ * @since n.e.x.t
+ *
+ * @param string $file          The path to the file.
+ * @param int    $attachment_id The attachment ID.
+ * @return string The MIME type of the file, or an empty string if not found.
+ */
+function webp_uploads_get_file_mime_type( string $file, int $attachment_id ): string {
+	/*
+	 * We need to get the MIME type ideally from the file, as WordPress Core may have already altered it.
+	 * The post MIME type is typically not updated during that process.
+	 */
+	$filetype  = wp_check_filetype( $file );
+	$mime_type = $filetype['type'] ?? get_post_mime_type( $attachment_id );
+	return is_string( $mime_type ) ? $mime_type : '';
+}
Index: hooks.php
===================================================================
--- hooks.php	(revision 3189893)
+++ hooks.php	(working copy)
@@ -52,18 +52,21 @@
  * } An array with the updated structure for the metadata before is stored in the database.
  */
 function webp_uploads_create_sources_property( array $metadata, int $attachment_id ): array {
-	// This should take place only on the JPEG image.
-	$valid_mime_transforms = webp_uploads_get_upload_image_mime_transforms();
+	$file = get_attached_file( $attachment_id, true );
+	// File does not exist.
+	if ( false === $file || ! file_exists( $file ) ) {
+		return $metadata;
+	}
 
-	// Not a supported mime type to create the sources property.
-	$mime_type = get_post_mime_type( $attachment_id );
-	if ( ! is_string( $mime_type ) || ! isset( $valid_mime_transforms[ $mime_type ] ) ) {
+	$mime_type = webp_uploads_get_file_mime_type( $file, $attachment_id );
+	if ( '' === $mime_type ) {
 		return $metadata;
 	}
 
-	$file = get_attached_file( $attachment_id, true );
-	// File does not exist.
-	if ( false === $file || ! file_exists( $file ) ) {
+	$valid_mime_transforms = webp_uploads_get_upload_image_mime_transforms();
+
+	// Not a supported mime type to create the sources property.
+	if ( ! isset( $valid_mime_transforms[ $mime_type ] ) ) {
 		return $metadata;
 	}
 
Index: load.php
===================================================================
--- load.php	(revision 3189893)
+++ load.php	(working copy)
@@ -5,7 +5,7 @@
  * Description: Converts images to more modern formats such as WebP or AVIF during upload.
  * Requires at least: 6.5
  * Requires PHP: 7.2
- * Version: 2.2.0
+ * Version: 2.3.0
  * Author: WordPress Performance Team
  * Author URI: https://make.wordpress.org/performance/
  * License: GPLv2 or later
@@ -25,7 +25,7 @@
 	return;
 }
 
-define( 'WEBP_UPLOADS_VERSION', '2.2.0' );
+define( 'WEBP_UPLOADS_VERSION', '2.3.0' );
 define( 'WEBP_UPLOADS_MAIN_FILE', plugin_basename( __FILE__ ) );
 
 require_once __DIR__ . '/helper.php';
Index: picture-element.php
===================================================================
--- picture-element.php	(revision 3189893)
+++ picture-element.php	(working copy)
@@ -22,12 +22,24 @@
 	if ( 'the_content' !== $context ) {
 		return $image;
 	}
-	$image_meta              = wp_get_attachment_metadata( $attachment_id );
-	$original_file_mime_type = get_post_mime_type( $attachment_id );
-	if ( false === $original_file_mime_type || ! isset( $image_meta['sizes'] ) ) {
+
+	$file = get_attached_file( $attachment_id, true );
+	// File does not exist.
+	if ( false === $file || ! file_exists( $file ) ) {
 		return $image;
 	}
 
+	$original_file_mime_type = webp_uploads_get_file_mime_type( $file, $attachment_id );
+	if ( '' === $original_file_mime_type ) {
+		return $image;
+	}
+
+	$image_meta = wp_get_attachment_metadata( $attachment_id );
+
+	if ( ! isset( $image_meta['sizes'] ) ) {
+		return $image;
+	}
+
 	$image_sizes = $image_meta['sizes'];
 
 	// Append missing full size image in $image_sizes array for srcset.
Index: readme.txt
===================================================================
--- readme.txt	(revision 3189893)
+++ readme.txt	(working copy)
@@ -1,8 +1,8 @@
 === Modern Image Formats ===
 
 Contributors: wordpressdotorg
-Tested up to: 6.6
-Stable tag:   2.2.0
+Tested up to: 6.7
+Stable tag:   2.3.0
 License:      GPLv2 or later
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 Tags:         performance, images, webp, avif, modern image formats
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment