PageSourceSearch

https://www.altalink.ca/wp-content/plugins/crkit-for-wordpress/ass…=0&crkit_packaged=1&ver=4.5.236.1790885748

js altalink.ca collected 2026-10-02 10:21:22 UTC 98,561 bytes, 2,582 lines download raw bytes

1(function () {
2    const CRKIT_WORDPRESS_VERSION = '4.5';
3    const CONTROL_HOST_SELECTOR = '[data-crkit-control-host="true"]';
4    const CONTROL_ATTR_NAMES = ['data-crkit-control', 'data-crkit-control-host', 'data-crkit-state-token'];
5    const DEFAULT_THEME = 'charcoal-ice';
6    const DEFAULT_THEME_STYLES = Object.freeze([
7        'fonts/source-code-pro/source-code-pro.css',
8        'css/globals.css',
9        'css/style.css',
10        'css/dark.css'
11    ]);
12    const BARE_THEME_STYLES = Object.freeze([
13        'fonts/source-code-pro/source-code-pro.css',
14        'css/globals.css',
15        'css/dark.css'
16    ]);
17    const DEFAULT_CORE_MODULES = Object.freeze(['events', 'strings', 'dom', 'primitive', 'theme', 'control', 'toast']);
18    const GLOBAL_KEY = '__crkitWordPressRuntime';
19    const PUBLIC_SCHEMA_ACCESS = 'public';
20    const MOUNT_ROOT_SELECTOR = '[data-crkit-wp-mount-root="true"]';
21    const CRKIT_ID_ATTR = 'data-crkit-id';
22    const CRKIT_STATE_TOKEN_ATTR = 'data-crkit-state-token';
23    const CRKIT_PROPS_COMMENT_PREFIX = 'crkit:props ';
24    const SERIALIZED_PROPERTY_VALUES_KEY = '__crkitSerializedPropertyValues';
25    const PREVIEW_CLIENT_ID_ATTR = 'data-crkit-editor-client-id';
26    const RUNTIME_STATUS_ATTR_NAMES = new Set(['aria-busy', 'data-crkit-wp-status']);
27    const RUNTIME_READY_EVENT = 'crkit:wordpress-ready';
28    const DEFERRED_HOST_STATUS = 'deferred';
29    const DEFERRED_TOGGLE_REPLAY_KEY = '__crkitDeferredToggleReplay';
30    const DEFERRED_SURFACE_CONTROL_TYPES = new Set(['panel', 'dialog', 'popover', 'surface']);
31    const EDITOR_PREVIEW_NAMESPACE_ATTR = 'data-crkit-editor-preview-root';
32    const EDITOR_CHILD_BLOCKS_ATTR = 'data-crkit-editor-child-blocks';
33    const WORDPRESS_EDITOR_BLOCK_ID_PATTERN = /^block-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
34
35    const globalState = globalThis[GLOBAL_KEY] || (globalThis[GLOBAL_KEY] = {
36        version: CRKIT_WORDPRESS_VERSION,
37        runtimePromise: null,
38        runtimeApi: null,
39        scanScheduled: false,
40        scanRunning: false,
41        pendingHosts: new Set(),
42        bootingHosts: new Set(),
43        hostState: new WeakMap(),
44        observer: null,
45        deferredHostsById: new Map(),
46        deferredToggleBootsById: new Map(),
47        deferredToggleBootHandlerInstalled: false,
48        pageLifecycleRecoveryInstalled: false,
49        pageLifecycleSuspended: false,
50        editorPreviewNamespaceByHost: new WeakMap(),
51        editorPreviewNamespaceCounter: 0,
52        schemaByControl: new Map(),
53        schemaPromiseByControl: new Map(),
54        preloadedAssetKeys: new Set(),
55        activeBoots: 0,
56        bootstrapped: false,
57        readyDispatched: false,
58        emailTemplatesCaptchaPageToken: '',
59        emailTemplatesCaptchaPageTokenPromise: null
60    });
61    if (typeof globalState.bootstrapped !== 'boolean') {
62        globalState.bootstrapped = false;
63    }
64    if (typeof globalState.readyDispatched !== 'boolean') {
65        globalState.readyDispatched = false;
66    }
67    if (!(globalState.deferredHostsById instanceof Map)) {
68        globalState.deferredHostsById = new Map();
69    }
70    if (!(globalState.deferredToggleBootsById instanceof Map)) {
71        globalState.deferredToggleBootsById = new Map();
72    }
73    if (!(globalState.bootingHosts instanceof Set)) {
74        globalState.bootingHosts = new Set();
75    }
76    if (typeof globalState.deferredToggleBootHandlerInstalled !== 'boolean') {
77        globalState.deferredToggleBootHandlerInstalled = false;
78    }
79    if (typeof globalState.pageLifecycleRecoveryInstalled !== 'boolean') {
80        globalState.pageLifecycleRecoveryInstalled = false;
81    }
82    if (typeof globalState.pageLifecycleSuspended !== 'boolean') {
83        globalState.pageLifecycleSuspended = false;
84    }
85    if (!Number.isFinite(globalState.activeBoots)) {
86        globalState.activeBoots = 0;
87    }
88    if (!(globalState.editorPreviewNamespaceByHost instanceof WeakMap)) {
89        globalState.editorPreviewNamespaceByHost = new WeakMap();
90    }
91    if (!Number.isFinite(globalState.editorPreviewNamespaceCounter)) {
92        globalState.editorPreviewNamespaceCounter = 0;
93    }
94    if (typeof globalState.emailTemplatesCaptchaPageToken !== 'string') {
95        globalState.emailTemplatesCaptchaPageToken = '';
96    }
97    if (
98        globalState.emailTemplatesCaptchaPageTokenPromise
99        && typeof globalState.emailTemplatesCaptchaPageTokenPromise.then !== 'function'
100    ) {
101        globalState.emailTemplatesCaptchaPageTokenPromise = null;
102    }
103
104    const normalizeText = (value) => String(value ?? '').trim();
105    const escapeSelectorValue = (value) => {
106        const normalized = normalizeText(value);
107        if (!normalized) {
108            return '';
109        }
110        if (globalThis.CSS && typeof globalThis.CSS.escape === 'function') {
111            return globalThis.CSS.escape(normalized);
112        }
113        return normalized.replace(/["\\]/g, '\\$&');
114    };
115    const decodeTextPropertyValue = (value) => {
116        const normalized = String(value ?? '');
117        if (!normalized || normalized.indexOf('&') === -1) {
118            return normalized;
119        }
120
121        const decodeHtmlEntities = globalState.runtimeApi?.crkitlib?.strings?.decodeHtmlEntities;
122        return typeof decodeHtmlEntities === 'function'
123            ? String(decodeHtmlEntities(normalized, document, { maxPasses: 4 }) ?? normalized)
124            : normalized;
125    };
126    const appendVersionQuery = (href, version) => {
127        const normalizedHref = normalizeText(href);
128        const normalizedVersion = normalizeText(version);
129        if (!normalizedHref || !normalizedVersion) {
130            return normalizedHref;
131        }
132
133        const hashIndex = normalizedHref.indexOf('#');
134        const baseHref = hashIndex >= 0 ? normalizedHref.slice(0, hashIndex) : normalizedHref;
135        const hash = hashIndex >= 0 ? normalizedHref.slice(hashIndex) : '';
136        const encodedVersion = encodeURIComponent(normalizedVersion);
137        return `${baseHref}${baseHref.includes('?') ? '&' : '?'}ver=${encodedVersion}${hash}`;
138    };
139    const removeQueryParam = (href, paramName) => {
140        const normalizedHref = normalizeText(href);
141        const normalizedParamName = normalizeText(paramName);
142        if (!normalizedHref || !normalizedParamName) {
143            return normalizedHref;
144        }
145
146        const hashIndex = normalizedHref.indexOf('#');
147        const beforeHash = hashIndex >= 0 ? normalizedHref.slice(0, hashIndex) : normalizedHref;
148        const hash = hashIndex >= 0 ? normalizedHref.slice(hashIndex) : '';
149        const queryIndex = beforeHash.indexOf('?');
150        if (queryIndex < 0) {
151            return normalizedHref;
152        }
153
154        const baseHref = beforeHash.slice(0, queryIndex);
155        const query = beforeHash.slice(queryIndex + 1);
156        const keptParams = query.split('&').filter((entry) => {
157            if (!entry) {
158                return false;
159            }
160            const [rawKey] = entry.split('=');
161            let key = rawKey;
162            try {
163                key = decodeURIComponent(rawKey.replace(/\+/g, ' '));
164            } catch (_) {
165                key = rawKey;
166            }
167            return key !== normalizedParamName;
168        });
169        return `${baseHref}${keptParams.length ? `?${keptParams.join('&')}` : ''}${hash}`;
170    };
171    const replaceVersionQuery = (href, version) => {
172        const normalizedVersion = normalizeText(version);
173        if (!normalizedVersion) {
174            return normalizeText(href);
175        }
176        return appendVersionQuery(removeQueryParam(href, 'ver'), normalizedVersion);
177    };
178    const readVersionQuery = (href) => {
179        const normalizedHref = normalizeText(href);
180        if (!normalizedHref) {
181            return '';
182        }
183
184        try {
185            return normalizeText(new URL(normalizedHref, window.location.href).searchParams.get('ver'));
186        } catch {
187            return '';
188        }
189    };
190    const appendResolvedVersionQuery = (href, importHref = '', fallbackVersion = '') => {
191        const normalizedHref = normalizeText(href);
192        if (!normalizedHref) {
193            return normalizedHref;
194        }
195
196        const resolvedVersion = readVersionQuery(importHref) || normalizeText(fallbackVersion);
197        return resolvedVersion
198            ? replaceVersionQuery(normalizedHref, resolvedVersion)
199            : normalizedHref;
200    };
201    const normalizeTagName = (value, fallback = 'div') => {
202        const normalized = String(value ?? '').trim().toLowerCase();
203        return /^[a-z][a-z0-9-]*$/.test(normalized) ? normalized : fallback;
204    };
205    const isPlainObject = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
206    const isAppControlType = (value) => normalizeText(value).toLowerCase() === 'app';
207    const resolveDocument = () => document;
208    const resolveBody = () => resolveDocument().body || resolveDocument().documentElement;
209    const isElement = (value) => value instanceof Element;
210    const isWordPressEditorGeneratedBlockId = (value) => WORDPRESS_EDITOR_BLOCK_ID_PATTERN.test(normalizeText(value));
211    const hasCrkitPreviewIdentity = (value) => isElement(value) && (
212        value.matches(CONTROL_HOST_SELECTOR)
213        || value.hasAttribute(CRKIT_ID_ATTR)
214        || value.hasAttribute(PREVIEW_CLIENT_ID_ATTR)
215    );
216    const isWordPressEditorChromeNode = (value) => {
217        if (!(value instanceof Element)) {
218            return false;
219        }
220
221        if (isWordPressEditorGeneratedBlockId(value.id) && !hasCrkitPreviewIdentity(value)) {
222            return true;
223        }
224
225        if (value.hasAttribute('data-block')) {
226            return true;
227        }
228
229        if (value.hasAttribute(EDITOR_CHILD_BLOCKS_ATTR)) {
230            return true;
231        }
232
233        const classList = value.classList;
234        return classList.contains('block-editor-inner-blocks')
235            || classList.contains('block-editor-block-list__layout')
236            || classList.contains('block-editor-block-list__block');
237    };
238    const stripWordPressEditorGeneratedBlockIds = (rootEl) => {
239        if (!isElement(rootEl)) {
240            return;
241        }
242
243        if (isWordPressEditorGeneratedBlockId(rootEl.id)) {
244            rootEl.removeAttribute('id');
245        }
246
247        rootEl.querySelectorAll?.('[id^="block-"]').forEach((el) => {
248            if (isWordPressEditorGeneratedBlockId(el.id)) {
249                el.removeAttribute('id');
250            }
251        });
252    };
253    const installWordPressEditorChromeBootResolver = (crkitlib) => {
254        const registerBootResolver = crkitlib?.control?.registerBootResolver;
255        if (typeof registerBootResolver !== 'function') {
256            return;
257        }
258
259        registerBootResolver('wordpress-editor-chrome', (el) => {
260            if (!isWordPressEditorChromeNode(el)) {
261                return null;
262            }
263
264            return {
265                claimed: true,
266                descend: false
267            };
268        });
269    };
270    const installWordPressDeferredHostBootResolver = (crkitlib) => {
271        const registerBootResolver = crkitlib?.control?.registerBootResolver;
272        if (typeof registerBootResolver !== 'function') {
273            return;
274        }
275
276        registerBootResolver('wordpress-deferred-host', (el) => {
277            if (!isElement(el) || normalizeText(el.dataset?.crkitWpStatus) !== DEFERRED_HOST_STATUS) {
278                return null;
279            }
280
281            return {
282                claimed: true,
283                descend: false
284            };
285        });
286    };
287    const isRuntimeMountedTreeNode = (value) => isElement(value) && value.matches(MOUNT_ROOT_SELECTOR);
288    const dispatchRuntimeReady = () => {
289        if (globalState.readyDispatched) {
290            return;
291        }
292
293        globalState.readyDispatched = true;
294        const documentEl = resolveDocument().documentElement;
295        if (documentEl) {
296            documentEl.dataset.crkitWpReady = 'true';
297        }
298
299        resolveDocument().dispatchEvent(new CustomEvent(RUNTIME_READY_EVENT, {
300            detail: {
301                version: CRKIT_WORDPRESS_VERSION
302            }
303        }));
304    };
305    const dispatchRuntimeReadyIfSettled = () => {
306        if (
307            !globalState.bootstrapped
308            || globalState.readyDispatched
309            || globalState.scanScheduled
310            || globalState.scanRunning
311            || globalState.activeBoots > 0
312            || globalState.pendingHosts.size > 0
313        ) {
314            return;
315        }
316
317        dispatchRuntimeReady();
318    };
319    const collectBootControlTypes = (preparedBoots) => {
320        const controlTypes = new Set();
321        preparedBoots.forEach((preparedBoot) => {
322            preparedBoot.controlTypes.forEach((controlType) => {
323                const normalizedType = normalizeText(controlType);
324                if (normalizedType) {
325                    controlTypes.add(normalizedType);
326                }
327            });
328        });
329        return controlTypes;
330    };
331    const containsOnlyMountedTree = (hostEl, mountedTreeEl) => {
332        if (!isElement(hostEl) || !isElement(mountedTreeEl) || mountedTreeEl.parentElement !== hostEl) {
333            return false;
334        }
335
336        let mountedTreeCount = 0;
337        for (const node of hostEl.childNodes) {
338            if (node === mountedTreeEl) {
339                mountedTreeCount += 1;
340                continue;
341            }
342
343            if (node.nodeType === Node.TEXT_NODE && !normalizeText(node.textContent)) {
344                continue;
345            }
346
347            return false;
348        }
349
350        return mountedTreeCount === 1;
351    };
352
353    const cloneValue = (value) => {
354        if (value == null || typeof value !== 'object') {
355            return value;
356        }
357        if (typeof structuredClone === 'function') {
358            return structuredClone(value);
359        }
360        return JSON.parse(JSON.stringify(value));
361    };
362    const decodeBase64Url = (value) => {
363        const normalizedValue = normalizeText(value);
364        if (!normalizedValue) {
365            return '';
366        }
367        const paddedValue = normalizedValue
368            .replace(/-/g, '+')
369            .replace(/_/g, '/')
370            .padEnd(Math.ceil(normalizedValue.length / 4) * 4, '=');
371        const binary = atob(paddedValue);
372        if (typeof TextDecoder === 'function') {
373            const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
374            return new TextDecoder().decode(bytes);
375        }
376        return decodeURIComponent(escape(binary));
377    };
378    const readHostPropsPayload = (hostEl) => {
379        if (!isElement(hostEl)) {
380            return null;
381        }
382
383        for (const node of hostEl.childNodes) {
384            if (node.nodeType !== Node.COMMENT_NODE) {
385                continue;
386            }
387            const text = normalizeText(node.textContent);
388            if (!text.startsWith(CRKIT_PROPS_COMMENT_PREFIX)) {
389                continue;
390            }
391
392            try {
393                const encodedPayload = text.slice(CRKIT_PROPS_COMMENT_PREFIX.length);
394                const payload = JSON.parse(decodeBase64Url(encodedPayload));
395                return isPlainObject(payload) ? payload : null;
396            } catch (err) {
397                console.error('CRKIT WordPress failed to read serialized props payload', err);
398                return null;
399            }
400        }
401
402        return null;
403    };
404    const normalizeModuleHref = (value) => {
405        const normalized = normalizeText(value);
406        if (!normalized) {
407            return '';
408        }
409
410        try {
411            return new URL(normalized, PLUGIN_BASE_URL).href;
412        } catch {
413            return normalized;
414        }
415    };
416    const normalizeStyleRefs = (value, fallback = []) => {
417        if (!Array.isArray(value) || value.length === 0) {
418            return Object.freeze([...(fallback || [])]);
419        }
420
421        return Object.freeze(value
422            .map((entry) => normalizeText(entry))
423            .filter(Boolean));
424    };
425    const normalizeHrefRoots = (value) => Object.freeze(
426        Array.isArray(value)
427            ? value
428                .map((entry) => normalizeModuleHref(entry).split('?')[0].split('#')[0])
429                .filter(Boolean)
430                .map((entry) => entry.endsWith('/') ? entry : `${entry}/`)
431            : []
432    );
433    const normalizeStringList = (value) => Object.freeze(
434        Array.isArray(value)
435            ? value.map((entry) => normalizeText(entry)).filter(Boolean)
436            : []
437    );
438    const normalizeOptionalBoolean = (value) => (
439        value === true
440            ? true
441            : (value === false ? false : null)
442    );
443    const normalizePropertyName = (value) => {
444        const normalized = normalizeText(value);
445        return /^[A-Za-z][A-Za-z0-9_]*$/.test(normalized) ? normalized : '';
446    };
447    const normalizePublicShellKey = (value) => {
448        const normalized = normalizeText(value).toLowerCase();
449        return /^[a-z][a-z0-9-]*$/.test(normalized)
450            ? normalized
451            : '';
452    };
453    const normalizeThemePathHref = (value, fallback = THEME_PATH) => {
454        const normalized = normalizeText(value);
455        if (!normalized) {
456            return fallback;
457        }
458
459        try {
460            return new URL(normalized, PLUGIN_BASE_URL).href;
461        } catch {
462            return fallback;
463        }
464    };
465    const normalizeThemeBridgeRegistryEntry = (entry) => {
466        if (!isPlainObject(entry)) {
467            return null;
468        }
469
470        const name = normalizeText(entry.name);
471        const moduleUrl = normalizeModuleHref(entry.moduleUrl || entry.url);
472        if (!name || !moduleUrl) {
473            return null;
474        }
475
476        return Object.freeze({
477            name,
478            title: normalizeText(entry.title),
479            iconUrl: normalizeModuleHref(entry.iconUrl),
480            moduleUrl,
481            hostTagName: normalizeTagName(entry.hostTagName, ''),
482            hostTagProperty: normalizePropertyName(entry.hostTagProperty),
483            hostsControls: normalizeOptionalBoolean(entry.hostsControls) ?? false,
484            childContent: normalizeText(entry.childContent),
485            styles: normalizeStringList(entry.styles),
486            deps: normalizeStringList(entry.deps),
487            publicShellKey: normalizePublicShellKey(entry.publicShellKey),
488            renderMode: normalizeText(entry.renderMode).toLowerCase() === 'dynamic' ? 'dynamic' : 'static'
489        });
490    };
491    const normalizeWordPressControlRegistryEntry = (entry) => {
492        if (!isPlainObject(entry)) {
493            return null;
494        }
495
496        const name = normalizeText(entry.name);
497        if (!name) {
498            return null;
499        }
500
501        return Object.freeze({
502            name,
503            title: normalizeText(entry.title),
504            hostTagName: normalizeTagName(entry.hostTagName, ''),
505            hostTagProperty: normalizePropertyName(entry.hostTagProperty),
506            hostsControls: normalizeOptionalBoolean(entry.hostsControls) ?? false,
507            childContent: normalizeText(entry.childContent),
508            editorChildSlotPart: normalizeText(entry.editorChildSlotPart),
509            publicShellKey: normalizePublicShellKey(entry.publicShellKey),
510            renderMode: normalizeText(entry.renderMode).toLowerCase() === 'dynamic' ? 'dynamic' : 'static'
511        });
512    };
513
514    const resolveCurrentScriptUrl = () => {
515        const currentSrc = document.currentScript?.src;
516        if (currentSrc) {
517            return currentSrc;
518        }
519
520        const scriptNodes = document.querySelectorAll('script[src]');
521        for (const scriptNode of scriptNodes) {
522            const src = scriptNode.getAttribute('src') || '';
523            if (src.includes('/assets/js/crkit-runtime.js')) {
524                return scriptNode.src;
525            }
526        }
527
528        return new URL('./assets/js/crkit-runtime.js', window.location.href).href;
529    };
530
531    const SCRIPT_URL = resolveCurrentScriptUrl();
532    const PLUGIN_BASE_URL = new URL('../../', SCRIPT_URL).href;
533    const SCRIPT_QUERY = (() => {
534        try {
535            return new URL(SCRIPT_URL).searchParams;
536        } catch {
537            return new URLSearchParams();
538        }
539    })();
540    const THEME_PATH = new URL('kit/themes/', PLUGIN_BASE_URL).href;
541    const IMAGES_PATH = new URL('kit/themes/charcoal-ice/vector-images.js', PLUGIN_BASE_URL).href;
542    const REFLECTOR_MODULE_URL = new URL('kit/controls/reflector/index.js', PLUGIN_BASE_URL).href;
543    const IDENTITY_ENABLED = normalizeText(SCRIPT_QUERY.get('crkit_identity_enabled')) === '1';
544    const IDENTITY_API_BASE_URL = normalizeText(SCRIPT_QUERY.get('crkit_identity_api_root'));
545    const IDENTITY_DRIVER_MODULE_URL = normalizeText(SCRIPT_QUERY.get('crkit_identity_driver_url'));
546    const IDENTITY_NONCE = normalizeText(SCRIPT_QUERY.get('crkit_identity_nonce'));
547    const REGISTRY_API_BASE_URL = normalizeText(SCRIPT_QUERY.get('crkit_registry_api_root'));
548    const REGISTRY_PROVIDER_MODULE_URL = normalizeText(SCRIPT_QUERY.get('crkit_registry_provider_url'));
549    const REGISTRY_NONCE = normalizeText(SCRIPT_QUERY.get('crkit_registry_nonce'));
550    const EMAIL_TEMPLATES_ENABLED = normalizeText(SCRIPT_QUERY.get('crkit_email_templates_enabled')) === '1';
551    const EMAIL_TEMPLATES_API_BASE_URL = normalizeText(SCRIPT_QUERY.get('crkit_email_templates_api_root'));
552    const EMAIL_TEMPLATES_DRIVER_MODULE_URL = normalizeText(SCRIPT_QUERY.get('crkit_email_templates_driver_url'));
553    const EMAIL_TEMPLATES_NONCE = normalizeText(SCRIPT_QUERY.get('crkit_email_templates_nonce'));
554    const EMAIL_TEMPLATES_CAPTCHA_PAGE_TOKEN = normalizeText(SCRIPT_QUERY.get('crkit_email_templates_captcha_page_token'));
555    const FORM_PROCESSOR_PROVIDER = normalizeText(SCRIPT_QUERY.get('crkit_form_processor_provider')) || 'wordpress';
556    const CRKIT_DEBUG_ENABLED = normalizeText(SCRIPT_QUERY.get('crkit_debug')) === '1';
557    const CRKIT_PACKAGED_STYLES = normalizeText(SCRIPT_QUERY.get('crkit_packaged')) === '1';
558    const CRKIT_THEME_NAME = normalizeText(SCRIPT_QUERY.get('crkit_theme_name')) || DEFAULT_THEME;
559    const CRKIT_THEME_PATH = normalizeThemePathHref(SCRIPT_QUERY.get('crkit_theme_path'), THEME_PATH);
560    const CRKIT_THEME_MODE = normalizeText(SCRIPT_QUERY.get('crkit_theme_mode'));
561    const RUNTIME_ASSET_VERSION = normalizeText(SCRIPT_QUERY.get('crkit_core_version'))
562        || normalizeText(SCRIPT_QUERY.get('ver'))
563        || CRKIT_WORDPRESS_VERSION;
564    if (EMAIL_TEMPLATES_CAPTCHA_PAGE_TOKEN) {
565        globalState.emailTemplatesCaptchaPageToken = EMAIL_TEMPLATES_CAPTCHA_PAGE_TOKEN;
566    }
567    const resolveEmailTemplatesApiEndpoint = (path) => {
568        const normalizedBaseUrl = normalizeText(EMAIL_TEMPLATES_API_BASE_URL);
569        const normalizedPath = normalizeText(path);
570        if (!normalizedBaseUrl || !normalizedPath) {
571            return '';
572        }
573
574        try {
575            const baseUrl = normalizedBaseUrl.endsWith('/') ? normalizedBaseUrl : `${normalizedBaseUrl}/`;
576            return new URL(normalizedPath, baseUrl).href;
577        } catch {
578            return '';
579        }
580    };
581    const readEmailTemplatesCaptchaPageToken = (payload) => {
582        const source = isPlainObject(payload?.data) ? payload.data : payload;
583        return normalizeText(isPlainObject(source) ? source.token : '');
584    };
585    const requestEmailTemplatesCaptchaPageToken = async () => {
586        const endpoint = resolveEmailTemplatesApiEndpoint('captcha/page-token');
587        if (!endpoint || typeof fetch !== 'function') {
588            return '';
589        }
590
591        const headers = EMAIL_TEMPLATES_NONCE ? { 'X-WP-Nonce': EMAIL_TEMPLATES_NONCE } : {};
592        const response = await fetch(endpoint, {
593            method: 'GET',
594            credentials: 'same-origin',
595            headers
596        });
597        if (!response.ok) {
598            return '';
599        }
600
601        try {
602            return readEmailTemplatesCaptchaPageToken(await response.json());
603        } catch {
604            return '';
605        }
606    };
607    const getEmailTemplatesCaptchaPageToken = () => {
608        const existingToken = normalizeText(globalState.emailTemplatesCaptchaPageToken);
609        if (existingToken) {
610            return Promise.resolve(existingToken);
611        }
612        if (
613            globalState.emailTemplatesCaptchaPageTokenPromise
614            && typeof globalState.emailTemplatesCaptchaPageTokenPromise.then === 'function'
615        ) {
616            return globalState.emailTemplatesCaptchaPageTokenPromise;
617        }
618        if (!EMAIL_TEMPLATES_ENABLED || typeof fetch !== 'function') {
619            return Promise.resolve('');
620        }
621
622        const tokenPromise = requestEmailTemplatesCaptchaPageToken()
623            .then((token) => {
624                const normalizedToken = normalizeText(token);
625                if (normalizedToken) {
626                    globalState.emailTemplatesCaptchaPageToken = normalizedToken;
627                } else {
628                    globalState.emailTemplatesCaptchaPageTokenPromise = null;
629                }
630                return normalizedToken;
631            })
632            .catch(() => {
633                globalState.emailTemplatesCaptchaPageTokenPromise = null;
634                return '';
635            });
636        globalState.emailTemplatesCaptchaPageTokenPromise = tokenPromise;
637        return tokenPromise;
638    };
639    const EMAIL_TEMPLATES_CAPTCHA_PAGE_TOKEN_PROMISE = getEmailTemplatesCaptchaPageToken();
640    const normalizeThemeMode = (value) => {
641        const normalized = normalizeText(value).toLowerCase();
642        return normalized === 'light' || normalized === 'dark'
643            ? normalized
644            : 'auto';
645    };
646    const THEME_BRIDGE = (() => {
647        const rawBridge = isPlainObject(globalThis.CRKIT_WP_THEME_BRIDGE)
648            ? globalThis.CRKIT_WP_THEME_BRIDGE
649            : {};
650        const controlRegistry = Array.isArray(rawBridge.controlRegistry)
651            ? rawBridge.controlRegistry
652                .map((entry) => normalizeThemeBridgeRegistryEntry(entry))
653                .filter(Boolean)
654            : [];
655        const controlsByName = new Map(controlRegistry.map((entry) => [entry.name, entry]));
656
657        const bridgeActiveTheme = normalizeText(rawBridge.activeTheme);
658        const bridgeThemePath = normalizeModuleHref(rawBridge.themePath);
659        const bridgeAppImagesPath = normalizeModuleHref(rawBridge.appImagesPath);
660        const selectedThemeExtendsBase = CRKIT_THEME_NAME !== DEFAULT_THEME || CRKIT_THEME_PATH !== THEME_PATH;
661        const hasThemeExtension = !!bridgeActiveTheme || !!bridgeThemePath || !!bridgeAppImagesPath || selectedThemeExtendsBase;
662        const activeTheme = bridgeActiveTheme || CRKIT_THEME_NAME;
663
664        return Object.freeze({
665            activeTheme,
666            baseTheme: normalizeText(rawBridge.baseTheme) || DEFAULT_THEME,
667            policy: hasThemeExtension ? 'extend' : 'replace',
668            themeMode: normalizeThemeMode(rawBridge.themeMode || CRKIT_THEME_MODE),
669            themePath: normalizeThemePathHref(rawBridge.themePath, CRKIT_THEME_PATH),
670            baseThemePath: normalizeThemePathHref(rawBridge.baseThemePath, THEME_PATH),
671            themeStyles: normalizeStyleRefs(rawBridge.themeStyles, DEFAULT_THEME_STYLES),
672            baseThemeStyles: normalizeStyleRefs(rawBridge.baseThemeStyles, DEFAULT_THEME_STYLES),
673            bareThemeStyles: normalizeStyleRefs(rawBridge.bareThemeStyles, BARE_THEME_STYLES),
674            bundledStyleRoots: normalizeHrefRoots(rawBridge.bundledStyleRoots),
675            imagesPath: normalizeModuleHref(rawBridge.imagesPath) || (hasThemeExtension ? '' : IMAGES_PATH),
676            baseImagesPath: normalizeModuleHref(rawBridge.baseImagesPath) || IMAGES_PATH,
677            appImagesPath: bridgeAppImagesPath,
678            controlRegistry: Object.freeze(controlRegistry),
679            controlsByName
680        });
681    })();
682    const resolveThemeBridgeControlEntry = (controlType) => THEME_BRIDGE.controlsByName.get(normalizeText(controlType)) || null;
683    const resolveWordPressControlRegistry = () => (
684        Array.isArray(globalThis.CRKIT_WP_CONTROL_REGISTRY)
685            ? globalThis.CRKIT_WP_CONTROL_REGISTRY
686                .map((entry) => normalizeWordPressControlRegistryEntry(entry))
687                .filter(Boolean)
688            : []
689    );
690    const resolveWordPressControlRegistryEntry = (controlType) => (
691        resolveWordPressControlRegistry()
692            .find((entry) => entry.name === normalizeText(controlType))
693        || null
694    );
695    const mergeControlSchemaMeta = (controlType, rawSchema) => {
696        const registryEntry = resolveThemeBridgeControlEntry(controlType)
697            || resolveWordPressControlRegistryEntry(controlType);
698        return {
699            ...rawSchema,
700            title: normalizeText(rawSchema?.title) || normalizeText(registryEntry?.title),
701            hostTagName: normalizeTagName(rawSchema?.hostTagName || registryEntry?.hostTagName, ''),
702            hostTagProperty: normalizePropertyName(rawSchema?.hostTagProperty || registryEntry?.hostTagProperty),
703            hostsControls: rawSchema?.hostsControls === true || registryEntry?.hostsControls === true,
704            childContent: normalizeText(rawSchema?.childContent || registryEntry?.childContent),
705            editorChildSlotPart: normalizeText(rawSchema?.editorChildSlotPart || registryEntry?.editorChildSlotPart),
706            publicShellKey: normalizePublicShellKey(rawSchema?.publicShellKey || registryEntry?.publicShellKey),
707            renderMode: normalizeText(rawSchema?.renderMode || registryEntry?.renderMode).toLowerCase() === 'dynamic' ? 'dynamic' : 'static'
708        };
709    };
710    const resolveControlModuleUrl = (controlType) => {
711        const normalizedType = normalizeText(controlType);
712        const themeEntry = resolveThemeBridgeControlEntry(normalizedType);
713        if (themeEntry?.moduleUrl) {
714            return appendResolvedVersionQuery(themeEntry.moduleUrl, '', RUNTIME_ASSET_VERSION);
715        }
716
717        return appendResolvedVersionQuery(
718            new URL(`kit/controls/${normalizedType}/index.js`, PLUGIN_BASE_URL).href,
719            '',
720            RUNTIME_ASSET_VERSION
721        );
722    };
723    const hasAncestorMountRoot = (hostEl) => {
724        if (!isElement(hostEl)) {
725            return false;
726        }
727
728        const ancestorMountRoot = hostEl.parentElement?.closest?.(MOUNT_ROOT_SELECTOR) || null;
729        if (ancestorMountRoot) {
730            return true;
731        }
732
733        const ancestorThemeRoot = hostEl.parentElement?.closest?.('[data-crkit-theme]') || null;
734        return !!ancestorThemeRoot;
735    };
736
737    const resolveMountedThemeConfig = (isAppRoot = false, hostEl = null) => {
738        const usesBridgeTheme = isAppRoot || !hasAncestorMountRoot(hostEl);
739        if (!usesBridgeTheme) {
740            return {
741                policy: 'inherit',
742                mode: THEME_BRIDGE.themeMode,
743                appImagesPath: THEME_BRIDGE.appImagesPath
744            };
745        }
746
747        return {
748            policy: THEME_BRIDGE.policy,
749            baseTheme: THEME_BRIDGE.baseTheme,
750            baseThemePath: THEME_BRIDGE.baseThemePath,
751            baseStyles: [...THEME_BRIDGE.baseThemeStyles],
752            baseImagesPath: THEME_BRIDGE.baseImagesPath,
753            activeTheme: THEME_BRIDGE.activeTheme,
754            themePath: THEME_BRIDGE.themePath,
755            styles: [...THEME_BRIDGE.themeStyles],
756            mode: THEME_BRIDGE.themeMode,
757            imagesPath: THEME_BRIDGE.imagesPath,
758            appImagesPath: THEME_BRIDGE.appImagesPath
759        };
760    };
761
762    const resolveMountRoot = (node) => {
763        const element = isElement(node) ? node : node?.parentElement;
764        return element?.closest?.(MOUNT_ROOT_SELECTOR) || null;
765    };
766
767    const isWithinMountedTree = (node) => !!resolveMountRoot(node);
768
769    const resolveHostElement = (node) => {
770        let current = isElement(node) ? node : node?.parentElement || null;
771        while (current) {
772            if (current.matches(CONTROL_HOST_SELECTOR)) {
773                return current;
774            }
775            current = current.parentElement;
776        }
777        return null;
778    };
779
780    const resolveParentHost = (hostEl) => {
781        let current = hostEl?.parentElement || null;
782        while (current) {
783            if (current.matches(CONTROL_HOST_SELECTOR)) {
784                return current;
785            }
786            current = current.parentElement;
787        }
788        return null;
789    };
790
791    const resolveTopLevelHost = (node) => {
792        let current = resolveHostElement(node);
793        let topLevelHost = current;
794        while (current) {
795            topLevelHost = current;
796            current = resolveParentHost(current);
797        }
798        return topLevelHost || null;
799    };
800    const isBlockEditorDocument = (ownerDocument = document) => {
801        const bodyEl = ownerDocument?.body || null;
802        if (!bodyEl) {
803            return false;
804        }
805
806        return bodyEl.classList.contains('block-editor-page')
807            || bodyEl.classList.contains('edit-site')
808            || !!ownerDocument.querySelector?.('.edit-post-layout, .edit-site-layout, .block-editor');
809    };
810    const isWithinBlockEditorCanvas = (node) => !!node?.closest?.(
811        '.block-editor-writing-flow, .block-editor-block-list__layout, .editor-styles-wrapper, .is-root-container, .edit-post-visual-editor'
812    );
813    const isEditorPreviewHost = (hostEl) => {
814        const previewContext = normalizeText(hostEl?.getAttribute?.('data-crkit-preview-context')).toLowerCase();
815        return previewContext === 'editor'
816            || !!normalizeText(hostEl?.getAttribute?.(PREVIEW_CLIENT_ID_ATTR));
817    };
818    const normalizeControlIdSegment = (value) => {
819        const normalizeSafeId = globalState.runtimeApi?.crkitlib?.strings?.normalizeSafeId;
820        if (typeof normalizeSafeId === 'function') {
821            return normalizeSafeId(value, 'preview') || 'preview';
822        }
823
824        const normalized = normalizeText(value)
825            .replace(/[^a-zA-Z0-9_-]+/g, '-')
826            .replace(/^-+|-+$/g, '');
827        return normalized || 'preview';
828    };
829    const allocateEditorPreviewNamespaceId = (hostEl) => {
830        if (!isEditorPreviewHost(hostEl)) {
831            return '';
832        }
833
834        const existingId = globalState.editorPreviewNamespaceByHost.get(hostEl);
835        if (existingId) {
836            return existingId;
837        }
838
839        globalState.editorPreviewNamespaceCounter += 1;
840        const sourceId = normalizeText(hostEl.getAttribute(PREVIEW_CLIENT_ID_ATTR))
841            || normalizeText(hostEl.getAttribute(CRKIT_STATE_TOKEN_ATTR))
842            || normalizeText(hostEl.getAttribute(CRKIT_ID_ATTR))
843            || normalizeText(hostEl.id)
844            || normalizeText(hostEl.dataset?.crkitControl)
845            || 'control';
846        const namespaceId = `wp-editor-preview-${normalizeControlIdSegment(sourceId)}-${globalState.editorPreviewNamespaceCounter}`;
847        globalState.editorPreviewNamespaceByHost.set(hostEl, namespaceId);
848        return namespaceId;
849    };
850    const shouldBootHost = (hostEl) => {
851        if (!isElement(hostEl)) {
852            return false;
853        }
854
855        const ownerDocument = hostEl.ownerDocument || document;
856        if (isBlockEditorDocument(ownerDocument) && isWithinBlockEditorCanvas(hostEl)) {
857            return isEditorPreviewHost(hostEl);
858        }
859
860        return true;
861    };
862    const resolveHostRuntimeId = (hostEl) => (
863        normalizeText(hostEl?.id)
864        || normalizeText(hostEl?.dataset?.crkitId)
865    );
866    const normalizeHostControlType = (hostEl) => normalizeText(hostEl?.dataset?.crkitControl).toLowerCase();
867    const isDeferredSurfaceControlType = (hostEl) => DEFERRED_SURFACE_CONTROL_TYPES.has(normalizeHostControlType(hostEl));
868    const isHostOpen = (hostEl) => {
869        const surfaceOpenState = normalizeText(hostEl?.dataset?.surfaceOpenState).toLowerCase();
870        if (surfaceOpenState) {
871            return surfaceOpenState === 'open';
872        }
873
874        if (Object.prototype.hasOwnProperty.call(hostEl?.dataset || {}, 'open')) {
875            return normalizeText(hostEl.dataset.open).toLowerCase() === 'true';
876        }
877
878        return false;
879    };
880    const shouldDeferHostBoot = (hostEl) => (
881        isElement(hostEl)
882        && isDeferredSurfaceControlType(hostEl)
883        && !isEditorPreviewHost(hostEl)
884        && !isHostOpen(hostEl)
885        && !!resolveHostRuntimeId(hostEl)
886        && !hasVisibleToggleForHost(hostEl)
887    );
888    const registerDeferredHost = (hostEl) => {
889        const hostId = resolveHostRuntimeId(hostEl);
890        if (!isElement(hostEl) || !hostId) {
891            return false;
892        }
893
894        globalState.deferredHostsById.set(hostId, hostEl);
895        setHostBootStatus(hostEl, DEFERRED_HOST_STATUS);
896        return true;
897    };
898    const unregisterDeferredHost = (hostEl) => {
899        const hostId = resolveHostRuntimeId(hostEl);
900        if (hostId && globalState.deferredHostsById.get(hostId) === hostEl) {
901            globalState.deferredHostsById.delete(hostId);
902        }
903        if (normalizeText(hostEl?.dataset?.crkitWpStatus) === DEFERRED_HOST_STATUS) {
904            setHostBootStatus(hostEl, '');
905        }
906    };
907    const canBootDeferredHostForToggle = (hostEl) => (
908        isElement(hostEl)
909        && hostEl.isConnected
910        && normalizeText(hostEl.dataset?.crkitWpStatus) === DEFERRED_HOST_STATUS
911        && isDeferredSurfaceControlType(hostEl)
912        && !isEditorPreviewHost(hostEl)
913        && !!resolveHostRuntimeId(hostEl)
914    );
915    const resolveDeferredHostById = (hostId) => {
916        const normalizedId = normalizeText(hostId);
917        if (!normalizedId) {
918            return null;
919        }
920
921        const registeredHost = globalState.deferredHostsById.get(normalizedId) || null;
922        if (
923            registeredHost?.isConnected
924            && (
925                canBootDeferredHostForToggle(registeredHost)
926                || shouldDeferHostBoot(registeredHost)
927            )
928        ) {
929            return registeredHost;
930        }
931        if (registeredHost) {
932            globalState.deferredHostsById.delete(normalizedId);
933        }
934
935        const escapedId = escapeSelectorValue(normalizedId);
936        const discoveredHost = document.querySelector?.([
937            `${CONTROL_HOST_SELECTOR}[id="${escapedId}"]`,
938            `${CONTROL_HOST_SELECTOR}[data-crkit-id="${escapedId}"]`
939        ].join(', ')) || null;
940        if (
941            discoveredHost?.isConnected
942            && (
943                canBootDeferredHostForToggle(discoveredHost)
944                || shouldDeferHostBoot(discoveredHost)
945            )
946        ) {
947            registerDeferredHost(discoveredHost);
948            return discoveredHost;
949        }
950
951        return null;
952    };
953    const isVisibleToggleForHost = (toggleEl) => {
954        if (!isElement(toggleEl) || !toggleEl.isConnected) {
955            return false;
956        }
957
958        const style = toggleEl.ownerDocument?.defaultView?.getComputedStyle?.(toggleEl) || null;
959        if (style && (style.display === 'none' || style.visibility === 'hidden')) {
960            return false;
961        }
962
963        const rect = toggleEl.getBoundingClientRect?.() || null;
964        return !!rect && rect.width > 0 && rect.height > 0;
965    };
966    const hasVisibleToggleForHost = (hostEl) => {
967        const ownerDocument = hostEl?.ownerDocument || document;
968        const hostId = normalizeText(hostEl?.id) || normalizeText(hostEl?.dataset?.crkitId);
969        if (!hostId || !ownerDocument?.querySelectorAll) {
970            return false;
971        }
972
973        const escapedId = escapeSelectorValue(hostId);
974        const toggles = ownerDocument.querySelectorAll(
975            `[data-toggle-control-id="${escapedId}"], [data-toggle-id="${escapedId}"]`
976        );
977        for (const toggleEl of toggles) {
978            if (isVisibleToggleForHost(toggleEl)) {
979                return true;
980            }
981        }
982        return false;
983    };
984    const getHostBootPriority = (hostEl) => {
985        const controlType = normalizeText(hostEl?.dataset?.crkitControl).toLowerCase();
986        if (!controlType) {
987            return 40;
988        }
989
990        if (
991            controlType === 'panel'
992            || controlType === 'dialog'
993            || controlType === 'popover'
994            || controlType === 'surface'
995        ) {
996            const openState = normalizeText(hostEl?.dataset?.surfaceOpenState).toLowerCase();
997            if (hasVisibleToggleForHost(hostEl)) {
998                return openState === 'open' ? 5 : 6;
999            }
1000            return openState === 'open' ? 10 : 30;
1001        }
1002
1003        if (controlType === 'footer') {
1004            return 20;
1005        }
1006
1007        return 0;
1008    };
1009    const sortHostsForBoot = (hosts) => hosts
1010        .map((hostEl, index) => ({
1011            hostEl,
1012            index,
1013            priority: getHostBootPriority(hostEl)
1014        }))
1015        .sort((a, b) => a.priority - b.priority || a.index - b.index)
1016        .map((entry) => entry.hostEl);
1017
1018    const collectSearchDocuments = (rootDocument) => {
1019        const documents = [];
1020        const visited = new Set();
1021        const queue = [];
1022
1023        if (rootDocument?.querySelector) {
1024            queue.push(rootDocument);
1025        }
1026
1027        while (queue.length > 0) {
1028            const currentDocument = queue.shift();
1029            if (!currentDocument || visited.has(currentDocument)) {
1030                continue;
1031            }
1032
1033            visited.add(currentDocument);
1034            documents.push(currentDocument);
1035
1036            const frameElements = currentDocument.querySelectorAll
1037                ? currentDocument.querySelectorAll('iframe')
1038                : [];
1039            for (const frameEl of frameElements) {
1040                let frameDocument = null;
1041                try {
1042                    frameDocument = frameEl.contentDocument || frameEl.contentWindow?.document || null;
1043                } catch {
1044                    frameDocument = null;
1045                }
1046
1047                if (frameDocument?.querySelector && !visited.has(frameDocument)) {
1048                    queue.push(frameDocument);
1049                }
1050            }
1051        }
1052
1053        return documents;
1054    };
1055
1056    const resolveMountedControlElementByPreviewClientId = (previewClientId, ownerDocument = document) => {
1057        const normalizedClientId = normalizeText(previewClientId);
1058        if (!normalizedClientId || !ownerDocument?.querySelector) {
1059            return null;
1060        }
1061
1062        const escapedClientId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'
1063            ? CSS.escape(normalizedClientId)
1064            : normalizedClientId.replace(/["\\]/g, '\\$&');
1065
1066        for (const searchDocument of collectSearchDocuments(ownerDocument)) {
1067            const mountedControlEl = searchDocument.querySelector(
1068                `[data-crkit-wp-mount-root] [data-type][${PREVIEW_CLIENT_ID_ATTR}="${escapedClientId}"]`
1069            );
1070            if (mountedControlEl) {
1071                return mountedControlEl;
1072            }
1073        }
1074
1075        return null;
1076    };
1077
1078    const resolveMountedControlRuntime = (controlEl) => {
1079        const runtimeWindow = controlEl?.ownerDocument?.defaultView || null;
1080        if (!runtimeWindow || runtimeWindow === globalThis) {
1081            return null;
1082        }
1083
1084        const runtimeApi = runtimeWindow.CRKIT_WORDPRESS_RUNTIME || null;
1085        return runtimeApi && typeof runtimeApi === 'object' ? runtimeApi : null;
1086    };
1087    const collectDirectChildHosts = (hostEl) => {
1088        const childHosts = [];
1089        const stack = [];
1090
1091        for (let index = hostEl?.children?.length - 1; index >= 0; index -= 1) {
1092            stack.push(hostEl.children[index]);
1093        }
1094
1095        while (stack.length) {
1096            const candidate = stack.pop();
1097            if (!isElement(candidate)) {
1098                continue;
1099            }
1100
1101            if (candidate.matches(CONTROL_HOST_SELECTOR)) {
1102                childHosts.push(candidate);
1103                continue;
1104            }
1105
1106            for (let index = candidate.children.length - 1; index >= 0; index -= 1) {
1107                stack.push(candidate.children[index]);
1108            }
1109        }
1110
1111        return childHosts;
1112    };
1113
1114    const collectHostedControlTypes = (hostEl, sink = new Set()) => {
1115        const controlType = normalizeText(hostEl?.dataset?.crkitControl);
1116        if (controlType) {
1117            sink.add(controlType);
1118        }
1119
1120        const childHosts = collectDirectChildHosts(hostEl);
1121        for (const childHost of childHosts) {
1122            if (shouldDeferHostBoot(childHost)) {
1123                registerDeferredHost(childHost);
1124                continue;
1125            }
1126            collectHostedControlTypes(childHost, sink);
1127        }
1128
1129        return sink;
1130    };
1131    const CORE_STYLE_PRELOAD_TYPES = new Set(['container', 'loading', 'section']);
1132    const resolveAssetHref = (baseHref, assetRef) => {
1133        const normalizedAssetRef = normalizeText(assetRef);
1134        if (!normalizedAssetRef) {
1135            return '';
1136        }
1137
1138        try {
1139            const assetUrl = new URL(normalizedAssetRef, baseHref);
1140            return appendResolvedVersionQuery(assetUrl.href, baseHref);
1141        } catch {
1142            return '';
1143        }
1144    };
1145    const appendPreloadLink = (href, rel, asValue = '') => {
1146        const normalizedHref = normalizeText(href);
1147        const headEl = document.head || document.documentElement;
1148        if (!normalizedHref || !headEl) {
1149            return;
1150        }
1151
1152        const cacheKey = `${rel}:${asValue}:${normalizedHref}`;
1153        if (globalState.preloadedAssetKeys.has(cacheKey)) {
1154            return;
1155        }
1156
1157        globalState.preloadedAssetKeys.add(cacheKey);
1158        const linkEl = document.createElement('link');
1159        linkEl.rel = rel;
1160        linkEl.href = normalizedHref;
1161        if (asValue) {
1162            linkEl.as = asValue;
1163        }
1164        headEl.append(linkEl);
1165    };
1166    const collectControlAssetPlan = (controlType, plan = null, visited = new Set()) => {
1167        const normalizedType = normalizeText(controlType);
1168        if (!normalizedType || visited.has(normalizedType)) {
1169            return plan || { moduleHrefs: new Set(), styleHrefs: new Set() };
1170        }
1171
1172        visited.add(normalizedType);
1173        const nextPlan = plan || {
1174            moduleHrefs: new Set(),
1175            styleHrefs: new Set()
1176        };
1177        const themeEntry = resolveThemeBridgeControlEntry(normalizedType);
1178        const moduleUrl = appendResolvedVersionQuery(
1179            themeEntry?.moduleUrl || resolveControlModuleUrl(normalizedType),
1180            '',
1181            RUNTIME_ASSET_VERSION
1182        );
1183        if (moduleUrl) {
1184            nextPlan.moduleHrefs.add(moduleUrl);
1185        }
1186
1187        if (CRKIT_PACKAGED_STYLES) {
1188            return nextPlan;
1189        }
1190
1191        if (themeEntry?.styles?.length) {
1192            themeEntry.styles.forEach((styleRef) => {
1193                const styleHref = resolveAssetHref(moduleUrl, styleRef);
1194                if (styleHref) {
1195                    nextPlan.styleHrefs.add(styleHref);
1196                }
1197            });
1198        } else if (CORE_STYLE_PRELOAD_TYPES.has(normalizedType) && moduleUrl) {
1199            const styleHref = resolveAssetHref(moduleUrl, 'view.css');
1200            if (styleHref) {
1201                nextPlan.styleHrefs.add(styleHref);
1202            }
1203        }
1204
1205        const deps = themeEntry?.deps || [];
1206        deps.forEach((dependencyType) => {
1207            collectControlAssetPlan(dependencyType, nextPlan, visited);
1208        });
1209
1210        return nextPlan;
1211    };
1212    const primeControlAssetPreloads = (targets) => {
1213        const controlTypes = new Set();
1214        const normalizedTargets = Array.isArray(targets) || targets instanceof Set
1215            ? [...targets]
1216            : [targets];
1217
1218        normalizedTargets.forEach((target) => {
1219            if (typeof target === 'string') {
1220                const controlType = normalizeText(target);
1221                if (controlType) {
1222                    controlTypes.add(controlType);
1223                }
1224                return;
1225            }
1226
1227            if (isElement(target)) {
1228                collectHostedControlTypes(target, controlTypes);
1229            }
1230        });
1231
1232        if (controlTypes.size === 0) {
1233            return;
1234        }
1235
1236        const plan = {
1237            moduleHrefs: new Set([
1238                appendResolvedVersionQuery(new URL('kit/crkit.js', PLUGIN_BASE_URL).href, '', RUNTIME_ASSET_VERSION),
1239                appendResolvedVersionQuery(REFLECTOR_MODULE_URL, '', RUNTIME_ASSET_VERSION)
1240            ]),
1241            styleHrefs: new Set()
1242        };
1243
1244        controlTypes.forEach((controlType) => {
1245            collectControlAssetPlan(controlType, plan);
1246        });
1247
1248        plan.moduleHrefs.forEach((moduleHref) => {
1249            appendPreloadLink(moduleHref, 'modulepreload');
1250        });
1251        plan.styleHrefs.forEach((styleHref) => {
1252            appendPreloadLink(styleHref, 'preload', 'style');
1253        });
1254    };
1255    const sanitizeHostShell = (hostEl) => {
1256        if (!isElement(hostEl)) {
1257            return;
1258        }
1259
1260        hostEl.removeAttribute('data-type');
1261        sanitizeHostShellIds(hostEl);
1262    };
1263    const sanitizeHostedControlShells = (rootEl) => {
1264        if (!isElement(rootEl) && rootEl !== document && rootEl !== document.body) {
1265            return;
1266        }
1267
1268        const scopeRoot = rootEl === document ? document.body : rootEl;
1269        if (!scopeRoot) {
1270            return;
1271        }
1272
1273        if (isElement(scopeRoot) && scopeRoot.matches(CONTROL_HOST_SELECTOR)) {
1274            sanitizeHostShell(scopeRoot);
1275        }
1276
1277        if (typeof scopeRoot.querySelectorAll !== 'function') {
1278            return;
1279        }
1280
1281        scopeRoot.querySelectorAll(CONTROL_HOST_SELECTOR).forEach((hostEl) => {
1282            sanitizeHostShell(hostEl);
1283        });
1284    };
1285    const sanitizeHostShellIds = (hostEl) => {
1286        if (!isElement(hostEl)) {
1287            return;
1288        }
1289
1290        const hostControlId = normalizeText(hostEl.getAttribute(CRKIT_ID_ATTR));
1291        if (!hostControlId) {
1292            return;
1293        }
1294
1295        if (normalizeText(hostEl.getAttribute('id')) === hostControlId) {
1296            hostEl.removeAttribute('id');
1297        }
1298        hostEl.removeAttribute('aria-labelledby');
1299        hostEl.removeAttribute('role');
1300    };
1301    const sanitizeNestedHostShellIdentity = (hostEl) => {
1302        sanitizeHostShellIds(hostEl);
1303        hostEl.removeAttribute(CRKIT_ID_ATTR);
1304    };
1305    const buildHostTreeSignature = (hostEl) => JSON.stringify([
1306        normalizeText(hostEl?.dataset?.crkitControl),
1307        hostEl?.getAttribute(CRKIT_STATE_TOKEN_ATTR) || '',
1308        collectDirectChildHosts(hostEl)
1309            .filter((childHost) => !shouldDeferHostBoot(childHost))
1310            .map((childHost) => buildHostTreeSignature(childHost))
1311    ]);
1312    const setHostBootStatus = (hostEl, status = '') => {
1313        if (!isElement(hostEl)) {
1314            return;
1315        }
1316
1317        const normalizedStatus = normalizeText(status);
1318        if (normalizedStatus) {
1319            hostEl.dataset.crkitWpStatus = normalizedStatus;
1320        } else {
1321            delete hostEl.dataset.crkitWpStatus;
1322        }
1323
1324        if (normalizedStatus === 'booting') {
1325            hostEl.setAttribute('aria-busy', 'true');
1326            return;
1327        }
1328
1329        hostEl.removeAttribute('aria-busy');
1330    };
1331
1332    const setMountedTreePendingState = (themeRootEl, pending) => {
1333        if (!isElement(themeRootEl)) {
1334            return;
1335        }
1336
1337        if (pending) {
1338            themeRootEl.dataset.crkitWpPending = 'true';
1339            themeRootEl.setAttribute('aria-busy', 'true');
1340            return;
1341        }
1342
1343        delete themeRootEl.dataset.crkitWpPending;
1344        themeRootEl.removeAttribute('aria-busy');
1345    };
1346
1347    const renderHostError = (hostEl, message) => {
1348        if (!isElement(hostEl)) {
1349            return;
1350        }
1351
1352        const pre = hostEl.ownerDocument.createElement('pre');
1353        pre.textContent = String(message ?? '').trim() || 'Unknown CRKIT error';
1354        hostEl.replaceChildren(pre);
1355        setHostBootStatus(hostEl, 'error');
1356    };
1357
1358    const normalizePropertySchema = (schema) => {
1359        const properties = Array.isArray(schema?.properties) ? schema.properties : [];
1360        return Object.freeze({
1361            ...schema,
1362            properties: Object.freeze(properties
1363                .filter((property) => normalizeText(property?.name))
1364                .map((property) => Object.freeze({
1365                    ...property,
1366                    name: normalizeText(property.name),
1367                    type: normalizeText(property.type) || 'data',
1368                    access: normalizeText(property.access) || null,
1369                    attrName: normalizeText(property.attrName),
1370                    label: normalizeText(property.label) || null,
1371                    description: normalizeText(property.description) || null,
1372                    options: cloneValue(property.options),
1373                    visibleWhen: cloneValue(property.visibleWhen),
1374                    readonlyWhen: cloneValue(property.readonlyWhen),
1375                    inspectorVariant: normalizeText(property.inspectorVariant) || null,
1376                    editorVariant: normalizeText(property.editorVariant) || null,
1377                    editorTagProperty: normalizeText(property.editorTagProperty) || null,
1378                    editorSourceProperty: normalizeText(property.editorSourceProperty) || null,
1379                    editorOutputProperty: normalizeText(property.editorOutputProperty) || null,
1380                    editorSourceFormat: normalizeText(property.editorSourceFormat) || null,
1381                    editorPlaceholder: normalizeText(property.editorPlaceholder) || null,
1382                    editorFormats: cloneValue(property.editorFormats),
1383                    commitOnBlur: property.commitOnBlur === true,
1384                    reflectToAttribute: property.reflectToAttribute === true,
1385                    defaultValue: cloneValue(property.defaultValue),
1386                    value: cloneValue(property.value)
1387                })))
1388        });
1389    };
1390
1391    const serializePropertyValue = (value, propertyType = 'data') => {
1392        if (value == null) {
1393            return null;
1394        }
1395
1396        switch (normalizeText(propertyType).toLowerCase()) {
1397        case 'boolean':
1398            return value === true || value === 'true' ? 'true' : 'false';
1399        case 'int':
1400        case 'datetime': {
1401            const numericValue = Number(value);
1402            return Number.isFinite(numericValue) ? String(numericValue) : null;
1403        }
1404        case 'json':
1405            return JSON.stringify(value);
1406        case 'text':
1407            return decodeTextPropertyValue(value);
1408        case 'imgurl':
1409        case 'data':
1410        default:
1411            return String(value);
1412        }
1413    };
1414
1415    const copyHostPropertyAttributes = (hostEl, mountEl, schema, payload = null) => {
1416        const properties = Array.isArray(schema?.properties) ? schema.properties : [];
1417        const payloadValues = isPlainObject(payload?.propertyValues) ? payload.propertyValues : null;
1418        for (const property of properties) {
1419            if (property.access !== PUBLIC_SCHEMA_ACCESS || !property.attrName) {
1420                continue;
1421            }
1422
1423            if (property.attrName === 'id') {
1424                const sourceId = normalizeText(
1425                    (payloadValues && Object.prototype.hasOwnProperty.call(payloadValues, property.name)
1426                        ? payloadValues[property.name]
1427                        : '')
1428                    || hostEl.getAttribute(CRKIT_ID_ATTR)
1429                    || hostEl.getAttribute('id')
1430                );
1431                if (sourceId) {
1432                    mountEl.setAttribute(CRKIT_ID_ATTR, sourceId);
1433                    if (normalizeText(mountEl.getAttribute('id')) === sourceId) {
1434                        mountEl.removeAttribute('id');
1435                    }
1436                    continue;
1437                }
1438
1439                mountEl.removeAttribute(CRKIT_ID_ATTR);
1440                mountEl.removeAttribute('id');
1441                continue;
1442            }
1443
1444            if (payloadValues && Object.prototype.hasOwnProperty.call(payloadValues, property.name)) {
1445                const serializedPayloadValue = serializePropertyValue(payloadValues[property.name], property.type || 'data');
1446                if (serializedPayloadValue == null) {
1447                    mountEl.removeAttribute(property.attrName);
1448                } else {
1449                    mountEl.setAttribute(property.attrName, serializedPayloadValue);
1450                }
1451                continue;
1452            }
1453
1454            if (hostEl.hasAttribute(property.attrName)) {
1455                mountEl.setAttribute(property.attrName, hostEl.getAttribute(property.attrName) || '');
1456                continue;
1457            }
1458
1459            mountEl.removeAttribute(property.attrName);
1460        }
1461    };
1462
1463    const setSerializedPropertyValues = (el, propertyValues) => {
1464        if (!isElement(el)) {
1465            return;
1466        }
1467
1468        if (!isPlainObject(propertyValues)) {
1469            delete el[SERIALIZED_PROPERTY_VALUES_KEY];
1470            return;
1471        }
1472
1473        Object.defineProperty(el, SERIALIZED_PROPERTY_VALUES_KEY, {
1474            configurable: true,
1475            enumerable: false,
1476            writable: true,
1477            value: propertyValues
1478        });
1479    };
1480
1481    const resolveControlMeta = (controlType, metaMap) => metaMap.get(normalizeText(controlType)) || null;
1482    const resolveHostTagName = (controlType, hostEl, metaMap) => normalizeTagName(
1483        hostEl?.getAttribute?.('data-tag')
1484        || hostEl?.dataset?.crkitHostTag
1485        || resolveControlMeta(controlType, metaMap)?.hostTagName
1486        || hostEl?.tagName
1487        || 'div'
1488    );
1489    const createMountElementFromHost = (hostEl, controlType, metaMap) => {
1490        const mountEl = hostEl.cloneNode(false);
1491        const resolvedTagName = resolveHostTagName(controlType, hostEl, metaMap);
1492        if (normalizeTagName(mountEl.tagName, 'div') !== resolvedTagName) {
1493            const replacementEl = hostEl.ownerDocument.createElement(resolvedTagName);
1494            for (const attribute of [...mountEl.attributes]) {
1495                replacementEl.setAttribute(attribute.name, attribute.value);
1496            }
1497            replacementEl.className = mountEl.className;
1498            mountEl.replaceWith?.();
1499            return replacementEl;
1500        }
1501
1502        return mountEl;
1503    };
1504    const sanitizeMountElement = (mountEl) => {
1505        if (!isElement(mountEl)) {
1506            return mountEl;
1507        }
1508
1509        mountEl.removeAttribute('data-crkit-control-host');
1510        mountEl.removeAttribute(CRKIT_STATE_TOKEN_ATTR);
1511        mountEl.removeAttribute('data-crkit-host-tag');
1512        mountEl.removeAttribute('data-crkit-wp-status');
1513        mountEl.removeAttribute('data-crkit-wp-mount-root');
1514        mountEl.removeAttribute('data-crkit-wp-pending');
1515        mountEl.removeAttribute('data-app-root');
1516        mountEl.removeAttribute('aria-busy');
1517        mountEl.classList.remove('wp-block-crkit-control', 'crkit-wp-control-host');
1518        return mountEl;
1519    };
1520
1521    const compileHostChildNode = (node, schemaMap, metaMap) => {
1522        if (node?.nodeType === Node.TEXT_NODE) {
1523            return node.ownerDocument.createTextNode(node.textContent || '');
1524        }
1525
1526        if (!isElement(node)) {
1527            return null;
1528        }
1529
1530        if (isWordPressEditorChromeNode(node) || isRuntimeMountedTreeNode(node)) {
1531            return null;
1532        }
1533
1534        if (node.matches(CONTROL_HOST_SELECTOR)) {
1535            if (shouldDeferHostBoot(node)) {
1536                registerDeferredHost(node);
1537                return node;
1538            }
1539            return buildControlTreeFromHost(node, schemaMap, metaMap)?.compiledNode || null;
1540        }
1541
1542        const clonedNode = node.cloneNode(false);
1543        stripWordPressEditorGeneratedBlockIds(clonedNode);
1544        if (Object.prototype.hasOwnProperty.call(node, '__crkitNativeBlockPreview')) {
1545            clonedNode.__crkitNativeBlockPreview = cloneValue(node.__crkitNativeBlockPreview);
1546        }
1547        for (const childNode of node.childNodes) {
1548            const compiledChildNode = compileHostChildNode(childNode, schemaMap, metaMap);
1549            if (compiledChildNode) {
1550                clonedNode.append(compiledChildNode);
1551            }
1552        }
1553
1554        return clonedNode;
1555    };
1556
1557    const buildControlTreeFromHost = (hostEl, schemaMap, metaMap) => {
1558        const controlType = normalizeText(hostEl?.dataset?.crkitControl);
1559        if (!controlType) {
1560            return null;
1561        }
1562
1563        const payload = readHostPropsPayload(hostEl);
1564        const mountEl = sanitizeMountElement(createMountElementFromHost(hostEl, controlType, metaMap));
1565        mountEl.dataset.type = controlType;
1566        const previewClientId = normalizeText(hostEl.getAttribute(PREVIEW_CLIENT_ID_ATTR));
1567        if (previewClientId) {
1568            mountEl.setAttribute(PREVIEW_CLIENT_ID_ATTR, previewClientId);
1569        }
1570        copyHostPropertyAttributes(hostEl, mountEl, schemaMap.get(controlType), payload);
1571        setSerializedPropertyValues(mountEl, payload?.propertyValues);
1572        stripWordPressEditorGeneratedBlockIds(mountEl);
1573
1574        const compiledChildren = [];
1575        for (const childNode of hostEl.childNodes) {
1576            const compiledChildNode = compileHostChildNode(childNode, schemaMap, metaMap);
1577            if (compiledChildNode) {
1578                compiledChildren.push(compiledChildNode);
1579            }
1580        }
1581
1582        compiledChildren.forEach((childNode) => {
1583            mountEl.append(childNode);
1584        });
1585
1586        return {
1587            compiledNode: mountEl,
1588            controlRootEl: mountEl
1589        };
1590    };
1591    const namespaceEditorPreviewTree = (controlType, compiledTree, hostEl = null) => {
1592        if (!isEditorPreviewHost(hostEl) || !compiledTree?.compiledNode || !compiledTree?.controlRootEl) {
1593            return {
1594                controlType,
1595                compiledTree
1596            };
1597        }
1598
1599        const namespaceId = allocateEditorPreviewNamespaceId(hostEl);
1600        if (!namespaceId) {
1601            return {
1602                controlType,
1603                compiledTree
1604            };
1605        }
1606
1607        const ownerDocument = compiledTree.compiledNode.ownerDocument || hostEl.ownerDocument || document;
1608        const namespaceEl = ownerDocument.createElement('div');
1609        namespaceEl.dataset.type = 'control';
1610        namespaceEl.setAttribute(CRKIT_ID_ATTR, namespaceId);
1611        namespaceEl.setAttribute(EDITOR_PREVIEW_NAMESPACE_ATTR, 'true');
1612        namespaceEl.append(compiledTree.compiledNode);
1613
1614        return {
1615            controlType: 'control',
1616            compiledTree: {
1617                compiledNode: namespaceEl,
1618                controlRootEl: namespaceEl
1619            }
1620        };
1621    };
1622
1623    const syncElementToTemplate = (targetEl, templateEl) => {
1624        if (!isElement(targetEl) || !isElement(templateEl)) {
1625            return targetEl;
1626        }
1627
1628        const nextAttributes = new Map();
1629        for (const attribute of [...templateEl.attributes]) {
1630            nextAttributes.set(attribute.name, attribute.value);
1631        }
1632
1633        for (const attribute of [...targetEl.attributes]) {
1634            if (
1635                attribute.name === 'data-crkit-wp-status'
1636                || attribute.name === 'data-crkit-wp-pending'
1637                || attribute.name === 'aria-busy'
1638            ) {
1639                continue;
1640            }
1641            if (!nextAttributes.has(attribute.name)) {
1642                targetEl.removeAttribute(attribute.name);
1643            }
1644        }
1645
1646        for (const [name, value] of nextAttributes.entries()) {
1647            targetEl.setAttribute(name, value);
1648        }
1649
1650        if (Object.prototype.hasOwnProperty.call(templateEl, SERIALIZED_PROPERTY_VALUES_KEY)) {
1651            setSerializedPropertyValues(targetEl, templateEl[SERIALIZED_PROPERTY_VALUES_KEY]);
1652        } else {
1653            delete targetEl[SERIALIZED_PROPERTY_VALUES_KEY];
1654        }
1655
1656        targetEl.replaceChildren(...[...templateEl.childNodes]);
1657        return targetEl;
1658    };
1659
1660    const canInlineHostTree = (hostEl, compiledTree) => {
1661        if (!isElement(hostEl) || !compiledTree?.controlRootEl || compiledTree.compiledNode !== compiledTree.controlRootEl) {
1662            return false;
1663        }
1664
1665        if (normalizeText(hostEl.dataset?.crkitPreviewContext)) {
1666            return false;
1667        }
1668
1669        return normalizeTagName(hostEl.tagName, 'div') === normalizeTagName(compiledTree.controlRootEl.tagName, 'div');
1670    };
1671
1672    const createMountedTree = (controlType, compiledTree, hostEl = null) => {
1673        const isAppRoot = isAppControlType(controlType);
1674        const inlineHostRoot = !isAppRoot && canInlineHostTree(hostEl, compiledTree);
1675        const themeRootEl = isAppRoot
1676            ? compiledTree.controlRootEl
1677            : (inlineHostRoot
1678                ? syncElementToTemplate(hostEl, compiledTree.controlRootEl)
1679                : compiledTree.controlRootEl.ownerDocument.createElement('div'));
1680
1681        if (!isAppRoot && !inlineHostRoot) {
1682            themeRootEl.append(compiledTree.compiledNode);
1683        }
1684
1685        themeRootEl.dataset.crkitWpMountRoot = 'true';
1686        if (isAppRoot) {
1687            themeRootEl.dataset.appRoot = 'true';
1688        } else {
1689            delete themeRootEl.dataset.appRoot;
1690        }
1691
1692        setMountedTreePendingState(themeRootEl, true);
1693
1694        return {
1695            themeRootEl,
1696            controlRootEl: inlineHostRoot ? themeRootEl : compiledTree.controlRootEl,
1697            themeConfig: resolveMountedThemeConfig(isAppRoot, hostEl)
1698        };
1699    };
1700
1701    const ensureRuntime = async () => {
1702        if (globalState.runtimeApi) {
1703            return globalState.runtimeApi;
1704        }
1705
1706        if (globalState.runtimePromise) {
1707            return globalState.runtimePromise;
1708        }
1709
1710        globalState.runtimePromise = (async () => {
1711            const [{ crkitlib }] = await Promise.all([
1712                import(/* @vite-ignore */ appendResolvedVersionQuery(
1713                    new URL('kit/crkit.js', PLUGIN_BASE_URL).href,
1714                    '',
1715                    RUNTIME_ASSET_VERSION
1716                ))
1717            ]);
1718            installWordPressEditorChromeBootResolver(crkitlib);
1719            installWordPressDeferredHostBootResolver(crkitlib);
1720
1721            sanitizeHostedControlShells(resolveBody());
1722
1723            if (!crkitlib.globals?.initialized) {
1724                await crkitlib.create({
1725                    version: RUNTIME_ASSET_VERSION,
1726                    debug: CRKIT_DEBUG_ENABLED,
1727                    rootEl: resolveBody(),
1728                    coreModules: [...DEFAULT_CORE_MODULES],
1729                    dynamicLoadCSS: !CRKIT_PACKAGED_STYLES,
1730                    packagedStyles: CRKIT_PACKAGED_STYLES,
1731                    bundledStyleRoots: [...THEME_BRIDGE.bundledStyleRoots],
1732                    strongCSP: true,
1733                    activeTheme: DEFAULT_THEME,
1734                    themePath: THEME_PATH,
1735                    themeStyles: [...DEFAULT_THEME_STYLES],
1736                    themeMode: THEME_BRIDGE.themeMode,
1737                    imagesPath: IMAGES_PATH,
1738                    appImagesPath: '',
1739                    packagedTheme: DEFAULT_THEME,
1740                    packagedThemePath: THEME_PATH
1741                }, resolveBody());
1742            } else {
1743                if (crkitlib.globals.version !== RUNTIME_ASSET_VERSION) {
1744                    crkitlib.globals.version = RUNTIME_ASSET_VERSION;
1745                }
1746            }
1747            crkitlib.setDebug?.(CRKIT_DEBUG_ENABLED);
1748
1749            const getControlSchema = async (controlType) => {
1750                const normalizedType = normalizeText(controlType);
1751                if (!normalizedType) {
1752                    throw new Error('CRKIT control type is required');
1753                }
1754
1755                if (globalState.schemaByControl.has(normalizedType)) {
1756                    return globalState.schemaByControl.get(normalizedType);
1757                }
1758
1759                if (globalState.schemaPromiseByControl.has(normalizedType)) {
1760                    return globalState.schemaPromiseByControl.get(normalizedType);
1761                }
1762
1763                const schemaPromise = (async () => {
1764                    primeControlAssetPreloads([normalizedType]);
1765                    const controlModuleUrl = resolveControlModuleUrl(normalizedType);
1766                    const reflectorModuleUrl = appendResolvedVersionQuery(
1767                        REFLECTOR_MODULE_URL,
1768                        '',
1769                        RUNTIME_ASSET_VERSION
1770                    );
1771                    await crkitlib.loadModule(reflectorModuleUrl);
1772                    await crkitlib.loadModule(controlModuleUrl);
1773
1774                    const rawSchema = crkitlib.reflector?.controlSchema?.(normalizedType);
1775                    if (!rawSchema || !Array.isArray(rawSchema.properties)) {
1776                        throw new Error(`CRKIT schema is unavailable for "${normalizedType}"`);
1777                    }
1778
1779                    const schema = normalizePropertySchema(
1780                        mergeControlSchemaMeta(normalizedType, rawSchema)
1781                    );
1782                    globalState.schemaByControl.set(normalizedType, schema);
1783                    globalState.schemaPromiseByControl.delete(normalizedType);
1784                    return schema;
1785                })().catch((err) => {
1786                    globalState.schemaPromiseByControl.delete(normalizedType);
1787                    throw err;
1788                });
1789
1790                globalState.schemaPromiseByControl.set(normalizedType, schemaPromise);
1791                return schemaPromise;
1792            };
1793
1794            const getControlSchemaForPreviewClientId = async (previewClientId, ownerDocument = document) => {
1795                const normalizedClientId = normalizeText(previewClientId);
1796                if (!normalizedClientId) {
1797                    throw new Error('CRKIT preview client ID is required');
1798                }
1799
1800                const controlEl = resolveMountedControlElementByPreviewClientId(normalizedClientId, ownerDocument);
1801                if (!controlEl) {
1802                    return null;
1803                }
1804
1805                const delegatedRuntime = resolveMountedControlRuntime(controlEl);
1806                if (delegatedRuntime && typeof delegatedRuntime.getControlSchemaForPreviewClientId === 'function') {
1807                    return delegatedRuntime.getControlSchemaForPreviewClientId(normalizedClientId, controlEl.ownerDocument);
1808                }
1809
1810                await crkitlib.loadModule(appendResolvedVersionQuery(
1811                    REFLECTOR_MODULE_URL,
1812                    '',
1813                    RUNTIME_ASSET_VERSION
1814                ));
1815
1816                const instance = crkitlib.control?.getInstance?.(controlEl);
1817                if (!instance) {
1818                    return null;
1819                }
1820
1821                const rawSchema = crkitlib.reflector?.controlSchema?.(instance);
1822                if (!rawSchema || !Array.isArray(rawSchema.properties)) {
1823                    return null;
1824                }
1825
1826                return normalizePropertySchema(
1827                    mergeControlSchemaMeta(normalizeText(instance?.type), rawSchema)
1828                );
1829            };
1830
1831            const getControlPropertyValuesForPreviewClientId = async (previewClientId, ownerDocument = document) => {
1832                const normalizedClientId = normalizeText(previewClientId);
1833                if (!normalizedClientId) {
1834                    throw new Error('CRKIT preview client ID is required');
1835                }
1836
1837                const controlEl = resolveMountedControlElementByPreviewClientId(normalizedClientId, ownerDocument);
1838                if (!controlEl) {
1839                    return null;
1840                }
1841
1842                const delegatedRuntime = resolveMountedControlRuntime(controlEl);
1843                if (delegatedRuntime && typeof delegatedRuntime.getControlPropertyValuesForPreviewClientId === 'function') {
1844                    return delegatedRuntime.getControlPropertyValuesForPreviewClientId(normalizedClientId, controlEl.ownerDocument);
1845                }
1846
1847                const instance = crkitlib.control?.getInstance?.(controlEl);
1848                if (!instance || typeof crkitlib.control?.listProperties !== 'function') {
1849                    return null;
1850                }
1851
1852                const propertyValues = {};
1853                crkitlib.control.listProperties(instance).forEach((property) => {
1854                    const propertyName = normalizeText(property?.name);
1855                    if (!propertyName) {
1856                        return;
1857                    }
1858
1859                    const access = normalizeText(property?.access).toLowerCase();
1860                    if (access !== PUBLIC_SCHEMA_ACCESS && access !== 'readonly') {
1861                        return;
1862                    }
1863
1864                    propertyValues[propertyName] = cloneValue(property?.value);
1865                });
1866
1867                return propertyValues;
1868            };
1869
1870            const getControlInspectorPropertyValuesForPreviewClientId = async (previewClientId, ownerDocument = document) => {
1871                const normalizedClientId = normalizeText(previewClientId);
1872                if (!normalizedClientId) {
1873                    throw new Error('CRKIT preview client ID is required');
1874                }
1875
1876                const controlEl = resolveMountedControlElementByPreviewClientId(normalizedClientId, ownerDocument);
1877                if (!controlEl) {
1878                    return null;
1879                }
1880
1881                const delegatedRuntime = resolveMountedControlRuntime(controlEl);
1882                if (delegatedRuntime && typeof delegatedRuntime.getControlInspectorPropertyValuesForPreviewClientId === 'function') {
1883                    return delegatedRuntime.getControlInspectorPropertyValuesForPreviewClientId(normalizedClientId, controlEl.ownerDocument);
1884                }
1885
1886                const instance = crkitlib.control?.getInstance?.(controlEl);
1887                const listMethod = typeof crkitlib.control?.listInspectorProperties === 'function'
1888                    ? crkitlib.control.listInspectorProperties
1889                    : crkitlib.control?.listProperties;
1890                if (!instance || typeof listMethod !== 'function') {
1891                    return null;
1892                }
1893
1894                const propertyValues = {};
1895                const reflectedProperties = await listMethod(instance);
1896                reflectedProperties.forEach((property) => {
1897                    const propertyName = normalizeText(property?.name);
1898                    if (!propertyName) {
1899                        return;
1900                    }
1901
1902                    const access = normalizeText(property?.access).toLowerCase();
1903                    if (access !== PUBLIC_SCHEMA_ACCESS && access !== 'readonly') {
1904                        return;
1905                    }
1906
1907                    propertyValues[propertyName] = cloneValue(property?.value);
1908                });
1909
1910                return propertyValues;
1911            };
1912
1913            globalState.runtimeApi = {
1914                crkitlib,
1915                getControlSchema,
1916                getControlSchemaForPreviewClientId,
1917                getControlPropertyValuesForPreviewClientId,
1918                getControlInspectorPropertyValuesForPreviewClientId
1919            };
1920
1921            return globalState.runtimeApi;
1922        })().catch((err) => {
1923            globalState.runtimePromise = null;
1924            throw err;
1925        });
1926
1927        return globalState.runtimePromise;
1928    };
1929
1930    const cleanupControlHost = async (hostEl, expectedToken = null) => {
1931        const state = globalState.hostState.get(hostEl);
1932        if (!state) {
1933            return;
1934        }
1935        if (expectedToken != null && state.token !== expectedToken) {
1936            return;
1937        }
1938
1939        try {
1940            const runtimeApi = globalState.runtimeApi;
1941            const crkitlib = runtimeApi?.crkitlib;
1942            if (crkitlib?.control && state.controlRootEl) {
1943                crkitlib.control.destroy(state.controlRootEl);
1944            }
1945            if (crkitlib?.theme && state.themeRootEl) {
1946                crkitlib.theme.unbind(state.themeRootEl);
1947            }
1948        } catch (err) {
1949            console.error('CRKIT WordPress cleanup failed', err);
1950        }
1951
1952        if (state.themeRootEl?.isConnected && state.themeRootEl !== hostEl) {
1953            state.themeRootEl.remove();
1954        }
1955
1956        const currentState = globalState.hostState.get(hostEl);
1957        if (expectedToken != null && currentState?.token !== expectedToken) {
1958            return;
1959        }
1960
1961        globalState.hostState.delete(hostEl);
1962        globalState.bootingHosts.delete(hostEl);
1963        setHostBootStatus(hostEl, '');
1964    };
1965
1966    const discardHost = (hostEl) => {
1967        unregisterDeferredHost(hostEl);
1968        const topLevelHost = resolveTopLevelHost(hostEl);
1969        if (!topLevelHost) {
1970            return false;
1971        }
1972
1973        globalState.pendingHosts.delete(topLevelHost);
1974        globalState.bootingHosts.delete(topLevelHost);
1975        const state = globalState.hostState.get(topLevelHost) || null;
1976        void cleanupControlHost(topLevelHost, state?.token ?? null);
1977        setHostBootStatus(topLevelHost, '');
1978        return true;
1979    };
1980
1981    const prepareControlHostBoot = (hostEl) => {
1982        if (!isElement(hostEl) || !hostEl.isConnected) {
1983            return null;
1984        }
1985
1986        unregisterDeferredHost(hostEl);
1987        sanitizeHostShell(hostEl);
1988
1989        if (resolveParentHost(hostEl)) {
1990            void cleanupControlHost(hostEl);
1991            return null;
1992        }
1993
1994        const controlType = normalizeText(hostEl.dataset.crkitControl);
1995        if (!controlType) {
1996            void cleanupControlHost(hostEl);
1997            return null;
1998        }
1999
2000        const previousState = globalState.hostState.get(hostEl) || null;
2001        if (previousState?.ready && containsOnlyMountedTree(hostEl, previousState.themeRootEl)) {
2002            return null;
2003        }
2004
2005        const signature = buildHostTreeSignature(hostEl);
2006        if (
2007            previousState?.booting &&
2008            previousState.signature === signature
2009        ) {
2010            return null;
2011        }
2012
2013        if (
2014            previousState?.signature === signature &&
2015            previousState.ready &&
2016            previousState.themeRootEl &&
2017            previousState.themeRootEl.isConnected &&
2018            hostEl.contains(previousState.themeRootEl)
2019        ) {
2020            return null;
2021        }
2022
2023        const token = (previousState?.token || 0) + 1;
2024        const controlTypes = [...collectHostedControlTypes(hostEl)];
2025        globalState.hostState.set(hostEl, {
2026            token,
2027            signature,
2028            themeRootEl: previousState?.themeRootEl || null,
2029            controlRootEl: previousState?.controlRootEl || null,
2030            ready: false,
2031            booting: true
2032        });
2033        globalState.bootingHosts.add(hostEl);
2034        setHostBootStatus(hostEl, 'booting');
2035
2036        return {
2037            hostEl,
2038            controlType,
2039            controlTypes,
2040            token,
2041            signature
2042        };
2043    };
2044
2045    const loadControlSchemaMaps = async (runtimeApi, controlTypes) => {
2046        const { crkitlib } = runtimeApi;
2047        const schemaMap = new Map();
2048        const metaMap = new Map();
2049
2050        for (const typeName of controlTypes) {
2051            const normalizedType = normalizeText(typeName);
2052            if (!normalizedType || schemaMap.has(normalizedType)) {
2053                continue;
2054            }
2055
2056            schemaMap.set(normalizedType, await runtimeApi.getControlSchema(normalizedType));
2057            metaMap.set(normalizedType, crkitlib.control?.getTypeMeta?.(normalizedType) || null);
2058        }
2059
2060        return { schemaMap, metaMap };
2061    };
2062
2063    const failPreparedControlHostBoot = async (preparedBoot, err) => {
2064        await cleanupControlHost(preparedBoot.hostEl);
2065        renderHostError(preparedBoot.hostEl, err?.message || err);
2066        console.error(`CRKIT WordPress failed to boot control "${preparedBoot.controlType}"`, err);
2067    };
2068
2069    const bootPreparedControlHost = async (preparedBoot, runtimeApi, schemaMap, metaMap) => {
2070        const {
2071            hostEl,
2072            controlType,
2073            token,
2074            signature
2075        } = preparedBoot;
2076        const { crkitlib } = runtimeApi;
2077
2078        try {
2079            const currentState = globalState.hostState.get(hostEl);
2080            if (!currentState || currentState.token !== token || !hostEl.isConnected) {
2081                return;
2082            }
2083
2084            if (currentState.controlRootEl) {
2085                crkitlib.control.destroy(currentState.controlRootEl);
2086            }
2087            if (currentState.themeRootEl) {
2088                crkitlib.theme.unbind(currentState.themeRootEl);
2089            }
2090
2091            const compiledTree = buildControlTreeFromHost(hostEl, schemaMap, metaMap);
2092            if (!compiledTree?.controlRootEl) {
2093                await cleanupControlHost(hostEl);
2094                return;
2095            }
2096
2097            if (!canInlineHostTree(hostEl, compiledTree)) {
2098                sanitizeNestedHostShellIdentity(hostEl);
2099            }
2100
2101            const mountSource = namespaceEditorPreviewTree(controlType, compiledTree, hostEl);
2102            const mountedTree = createMountedTree(mountSource.controlType, mountSource.compiledTree, hostEl);
2103            if (mountedTree.themeRootEl !== hostEl) {
2104                hostEl.replaceChildren(mountedTree.themeRootEl);
2105            }
2106            stripWordPressEditorGeneratedBlockIds(mountedTree.themeRootEl);
2107
2108            await crkitlib.theme.bind(mountedTree.themeRootEl, mountedTree.themeConfig);
2109
2110            crkitlib.bootControls(mountedTree.themeRootEl);
2111            setMountedTreePendingState(mountedTree.themeRootEl, false);
2112
2113            const finalState = globalState.hostState.get(hostEl);
2114            if (!finalState || finalState.token !== token || !hostEl.isConnected) {
2115                crkitlib.control.destroy(mountedTree.controlRootEl);
2116                crkitlib.theme.unbind(mountedTree.themeRootEl);
2117                if (mountedTree.themeRootEl.isConnected && mountedTree.themeRootEl !== hostEl) {
2118                    mountedTree.themeRootEl.remove();
2119                }
2120                return;
2121            }
2122
2123            globalState.hostState.set(hostEl, {
2124                token,
2125                signature,
2126                themeRootEl: mountedTree.themeRootEl,
2127                controlRootEl: mountedTree.controlRootEl,
2128                ready: true,
2129                booting: false
2130            });
2131            globalState.bootingHosts.delete(hostEl);
2132            setHostBootStatus(hostEl, 'ready');
2133        } catch (err) {
2134            await failPreparedControlHostBoot(preparedBoot, err);
2135        }
2136    };
2137
2138    const bootPreparedControlHosts = async (preparedBoots) => {
2139        if (preparedBoots.length === 0) {
2140            return;
2141        }
2142
2143        let runtimeApi = null;
2144        let schemaMaps = null;
2145        try {
2146            primeControlAssetPreloads(preparedBoots.map((preparedBoot) => preparedBoot.hostEl));
2147            runtimeApi = await ensureRuntime();
2148            schemaMaps = await loadControlSchemaMaps(runtimeApi, collectBootControlTypes(preparedBoots));
2149        } catch (err) {
2150            await Promise.all(preparedBoots.map((preparedBoot) => failPreparedControlHostBoot(preparedBoot, err)));
2151            return;
2152        }
2153
2154        await Promise.all(preparedBoots.map((preparedBoot) => bootPreparedControlHost(
2155            preparedBoot,
2156            runtimeApi,
2157            schemaMaps.schemaMap,
2158            schemaMaps.metaMap
2159        )));
2160    };
2161
2162    const bootControlHosts = async (hosts) => {
2163        const preparedBoots = [];
2164        for (const hostEl of hosts) {
2165            const preparedBoot = prepareControlHostBoot(hostEl);
2166            if (preparedBoot) {
2167                preparedBoots.push(preparedBoot);
2168            }
2169        }
2170
2171        await bootPreparedControlHosts(preparedBoots);
2172    };
2173
2174    const schedulePendingHosts = () => {
2175        if (globalState.scanScheduled || globalState.scanRunning) {
2176            return;
2177        }
2178
2179        globalState.scanScheduled = true;
2180        queueMicrotask(() => {
2181            globalState.scanScheduled = false;
2182            globalState.scanRunning = true;
2183
2184            try {
2185                const hosts = sortHostsForBoot([...globalState.pendingHosts]);
2186                globalState.pendingHosts.clear();
2187                if (hosts.length > 0) {
2188                    globalState.activeBoots += 1;
2189                    Promise.resolve(bootControlHosts(hosts))
2190                        .catch((err) => {
2191                            hosts.forEach((hostEl) => {
2192                                setHostBootStatus(hostEl, 'error');
2193                            });
2194                            console.error('CRKIT WordPress failed to boot queued control hosts', err, hosts);
2195                        })
2196                        .finally(() => {
2197                            globalState.activeBoots = Math.max(0, globalState.activeBoots - 1);
2198                            if (globalState.pendingHosts.size > 0) {
2199                                schedulePendingHosts();
2200                                return;
2201                            }
2202                            dispatchRuntimeReadyIfSettled();
2203                        });
2204                }
2205            } finally {
2206                globalState.scanRunning = false;
2207            }
2208
2209            if (globalState.pendingHosts.size > 0) {
2210                schedulePendingHosts();
2211                return;
2212            }
2213
2214            dispatchRuntimeReadyIfSettled();
2215        });
2216    };
2217
2218    const enqueueHost = (hostEl) => {
2219        const topLevelHost = resolveTopLevelHost(hostEl);
2220        if (!topLevelHost || !shouldBootHost(topLevelHost)) {
2221            return;
2222        }
2223
2224        globalState.pendingHosts.add(topLevelHost);
2225        primeControlAssetPreloads([topLevelHost]);
2226        schedulePendingHosts();
2227    };
2228
2229    const bootControlHost = async (hostEl) => {
2230        await bootControlHosts([hostEl]);
2231    };
2232
2233    const collectControlHosts = (node, sink = globalState.pendingHosts) => {
2234        if (!isElement(node) || isWithinMountedTree(node)) {
2235            return sink;
2236        }
2237
2238        if (node.matches(CONTROL_HOST_SELECTOR)) {
2239            if (shouldDeferHostBoot(node)) {
2240                registerDeferredHost(node);
2241                return sink;
2242            }
2243            const topLevelHost = resolveTopLevelHost(node);
2244            if (topLevelHost && shouldBootHost(topLevelHost)) {
2245                sink.add(topLevelHost);
2246            }
2247        }
2248
2249        const descendants = node.querySelectorAll(CONTROL_HOST_SELECTOR);
2250        for (const hostEl of descendants) {
2251            if (shouldDeferHostBoot(hostEl)) {
2252                registerDeferredHost(hostEl);
2253                continue;
2254            }
2255            const topLevelHost = resolveTopLevelHost(hostEl);
2256            if (topLevelHost && topLevelHost !== hostEl && shouldDeferHostBoot(topLevelHost)) {
2257                registerDeferredHost(topLevelHost);
2258                continue;
2259            }
2260            if (topLevelHost && shouldBootHost(topLevelHost)) {
2261                sink.add(topLevelHost);
2262            }
2263        }
2264
2265        return sink;
2266    };
2267
2268    const cleanupRemovedHosts = (node) => {
2269        if (!isElement(node) || isWithinMountedTree(node)) {
2270            return;
2271        }
2272
2273        const hosts = [];
2274        if (node.matches(CONTROL_HOST_SELECTOR)) {
2275            hosts.push(node);
2276        }
2277        hosts.push(...node.querySelectorAll(CONTROL_HOST_SELECTOR));
2278        hosts.forEach((hostEl) => {
2279            try {
2280                unregisterDeferredHost(hostEl);
2281                if (hostEl.isConnected) {
2282                    return;
2283                }
2284                discardHost(hostEl);
2285            } catch (err) {
2286                console.error('CRKIT WordPress failed to clean up a removed host', err);
2287            }
2288        });
2289    };
2290
2291    const bootDeferredHostForToggle = async (hostEl, hostId) => {
2292        const normalizedId = normalizeText(hostId) || resolveHostRuntimeId(hostEl);
2293        if (!isElement(hostEl) || !hostEl.isConnected || !normalizedId) {
2294            return false;
2295        }
2296
2297        const existingBoot = globalState.deferredToggleBootsById.get(normalizedId);
2298        if (existingBoot) {
2299            return existingBoot;
2300        }
2301
2302        const bootPromise = (async () => {
2303            unregisterDeferredHost(hostEl);
2304            globalState.pendingHosts.delete(hostEl);
2305            await bootControlHost(hostEl);
2306            const state = globalState.hostState.get(hostEl);
2307            return state?.ready === true;
2308        })().finally(() => {
2309            globalState.deferredToggleBootsById.delete(normalizedId);
2310        });
2311
2312        globalState.deferredToggleBootsById.set(normalizedId, bootPromise);
2313        return bootPromise;
2314    };
2315
2316    const reconcileDeferredHosts = () => {
2317        if (!(globalState.deferredHostsById instanceof Map) || globalState.deferredHostsById.size === 0) {
2318            return;
2319        }
2320
2321        for (const [hostId, hostEl] of [...globalState.deferredHostsById.entries()]) {
2322            if (!isElement(hostEl) || !hostEl.isConnected) {
2323                globalState.deferredHostsById.delete(hostId);
2324                continue;
2325            }
2326
2327            if (shouldDeferHostBoot(hostEl)) {
2328                continue;
2329            }
2330
2331            void bootDeferredHostForToggle(hostEl, hostId)
2332                .catch((err) => {
2333                    console.error('CRKIT WordPress failed to boot deferred host after toggle reconciliation', err, hostEl);
2334                });
2335        }
2336    };
2337
2338    const replayDeferredToggleEvent = (event, detail) => {
2339        const eventTarget = event?.target instanceof EventTarget
2340            ? event.target
2341            : document;
2342        const replayDetail = {
2343            ...detail,
2344            visible: true,
2345            [DEFERRED_TOGGLE_REPLAY_KEY]: true
2346        };
2347        eventTarget.dispatchEvent(new CustomEvent('toggle', {
2348            bubbles: true,
2349            composed: true,
2350            cancelable: true,
2351            detail: replayDetail
2352        }));
2353    };
2354
2355    const installDeferredToggleBootHandler = () => {
2356        if (globalState.deferredToggleBootHandlerInstalled) {
2357            return;
2358        }
2359
2360        document.addEventListener('toggle', (event) => {
2361            if (!event || event.defaultPrevented) {
2362                return;
2363            }
2364
2365            const detail = isPlainObject(event.detail) ? event.detail : {};
2366            if (detail[DEFERRED_TOGGLE_REPLAY_KEY] === true) {
2367                return;
2368            }
2369
2370            const targetId = normalizeText(detail.toggleControlId || detail.controlId || detail.id);
2371            if (!targetId) {
2372                return;
2373            }
2374
2375            const hostEl = resolveDeferredHostById(targetId);
2376            if (!hostEl) {
2377                return;
2378            }
2379
2380            const requestedVisible = typeof detail.visible === 'boolean'
2381                ? detail.visible
2382                : true;
2383            if (requestedVisible !== true) {
2384                return;
2385            }
2386
2387            event.preventDefault();
2388            void bootDeferredHostForToggle(hostEl, targetId)
2389                .then((ready) => {
2390                    if (ready) {
2391                        replayDeferredToggleEvent(event, detail);
2392                    }
2393                })
2394                .catch((err) => {
2395                    console.error('CRKIT WordPress failed to boot deferred host for toggle', err, hostEl);
2396                });
2397        }, true);
2398
2399        globalState.deferredToggleBootHandlerInstalled = true;
2400    };
2401
2402    const installObserver = () => {
2403        if (globalState.observer || !resolveBody()) {
2404            return;
2405        }
2406
2407        const observer = new MutationObserver((mutations) => {
2408            for (const mutation of mutations) {
2409                if (mutation.type === 'attributes') {
2410                    if (RUNTIME_STATUS_ATTR_NAMES.has(mutation.attributeName)) {
2411                        continue;
2412                    }
2413
2414                    if (isWithinMountedTree(mutation.target)) {
2415                        continue;
2416                    }
2417
2418                    if (isElement(mutation.target) && mutation.target.matches(CONTROL_HOST_SELECTOR)) {
2419                        enqueueHost(mutation.target);
2420                    }
2421                    continue;
2422                }
2423
2424                if (isWithinMountedTree(mutation.target)) {
2425                    continue;
2426                }
2427
2428                mutation.addedNodes.forEach((node) => {
2429                    if (isWithinMountedTree(node)) {
2430                        return;
2431                    }
2432                    collectControlHosts(node);
2433                });
2434                mutation.removedNodes.forEach((node) => {
2435                    if (isWithinMountedTree(node)) {
2436                        return;
2437                    }
2438                    cleanupRemovedHosts(node);
2439                });
2440            }
2441
2442            if (globalState.pendingHosts.size > 0) {
2443                schedulePendingHosts();
2444            }
2445            reconcileDeferredHosts();
2446        });
2447
2448        observer.observe(resolveBody(), {
2449            subtree: true,
2450            childList: true,
2451            attributes: true,
2452            attributeFilter: CONTROL_ATTR_NAMES
2453        });
2454
2455        globalState.observer = observer;
2456    };
2457
2458    const markPageLifecycleSuspended = () => {
2459        globalState.pageLifecycleSuspended = true;
2460    };
2461
2462    const recoverPageLifecycleBoots = () => {
2463        if (!globalState.pageLifecycleSuspended) {
2464            return;
2465        }
2466
2467        globalState.pageLifecycleSuspended = false;
2468        const hosts = [...globalState.bootingHosts.values()];
2469        if (hosts.length === 0) {
2470            return;
2471        }
2472
2473        hosts.forEach((hostEl) => {
2474            if (!isElement(hostEl) || !hostEl.isConnected) {
2475                globalState.bootingHosts.delete(hostEl);
2476                return;
2477            }
2478
2479            const state = globalState.hostState.get(hostEl) || null;
2480            if (!state?.booting) {
2481                globalState.bootingHosts.delete(hostEl);
2482                return;
2483            }
2484
2485            globalState.hostState.delete(hostEl);
2486            globalState.bootingHosts.delete(hostEl);
2487            setHostBootStatus(hostEl, '');
2488            enqueueHost(hostEl);
2489        });
2490    };
2491
2492    const installPageLifecycleRecovery = () => {
2493        if (globalState.pageLifecycleRecoveryInstalled) {
2494            return;
2495        }
2496
2497        document.addEventListener('visibilitychange', () => {
2498            if (document.visibilityState === 'hidden') {
2499                markPageLifecycleSuspended();
2500                return;
2501            }
2502
2503            recoverPageLifecycleBoots();
2504        }, true);
2505
2506        window.addEventListener('pagehide', markPageLifecycleSuspended, true);
2507        window.addEventListener('pageshow', recoverPageLifecycleBoots, true);
2508        globalState.pageLifecycleRecoveryInstalled = true;
2509    };
2510
2511    const bootstrap = () => {
2512        const bodyEl = resolveBody();
2513        if (!bodyEl) {
2514            return;
2515        }
2516
2517        globalState.bootstrapped = true;
2518        sanitizeHostedControlShells(bodyEl);
2519        collectControlHosts(bodyEl);
2520        reconcileDeferredHosts();
2521        if (globalState.pendingHosts.size > 0) {
2522            primeControlAssetPreloads([...globalState.pendingHosts]);
2523        }
2524
2525        ensureRuntime().catch((err) => {
2526            console.error('CRKIT WordPress runtime failed to initialize', err);
2527        });
2528
2529        if (globalState.pendingHosts.size > 0) {
2530            schedulePendingHosts();
2531        }
2532        dispatchRuntimeReadyIfSettled();
2533        installDeferredToggleBootHandler();
2534        installPageLifecycleRecovery();
2535        installObserver();
2536    };
2537
2538    globalThis.CRKIT_WORDPRESS_RUNTIME = Object.freeze({
2539        version: CRKIT_WORDPRESS_VERSION,
2540        identityEnabled: IDENTITY_ENABLED,
2541        identityApiBaseUrl: IDENTITY_API_BASE_URL,
2542        identityWordPressDriverModuleUrl: IDENTITY_DRIVER_MODULE_URL,
2543        identityNonce: IDENTITY_NONCE,
2544        registryApiBaseUrl: REGISTRY_API_BASE_URL,
2545        registryWordPressProviderModuleUrl: REGISTRY_PROVIDER_MODULE_URL,
2546        registryNonce: REGISTRY_NONCE,
2547        emailTemplatesEnabled: EMAIL_TEMPLATES_ENABLED,
2548        emailTemplatesApiBaseUrl: EMAIL_TEMPLATES_API_BASE_URL,
2549        emailTemplatesDriverUrl: EMAIL_TEMPLATES_DRIVER_MODULE_URL,
2550        emailTemplatesWordPressDriverModuleUrl: EMAIL_TEMPLATES_DRIVER_MODULE_URL,
2551        emailTemplatesNonce: EMAIL_TEMPLATES_NONCE,
2552        emailTemplatesCaptchaPageToken: globalState.emailTemplatesCaptchaPageToken,
2553        emailTemplatesCaptchaPageTokenPromise: EMAIL_TEMPLATES_CAPTCHA_PAGE_TOKEN_PROMISE,
2554        getEmailTemplatesCaptchaPageToken,
2555        formProcessorProvider: FORM_PROCESSOR_PROVIDER,
2556        ensureRuntime,
2557        getControlSchema: async (controlType) => {
2558            const runtimeApi = await ensureRuntime();
2559            return runtimeApi.getControlSchema(controlType);
2560        },
2561        getControlSchemaForPreviewClientId: async (previewClientId, ownerDocument = document) => {
2562            const runtimeApi = await ensureRuntime();
2563            return runtimeApi.getControlSchemaForPreviewClientId(previewClientId, ownerDocument);
2564        },
2565        getControlPropertyValuesForPreviewClientId: async (previewClientId, ownerDocument = document) => {
2566            const runtimeApi = await ensureRuntime();
2567            return runtimeApi.getControlPropertyValuesForPreviewClientId(previewClientId, ownerDocument);
2568        },
2569        getControlInspectorPropertyValuesForPreviewClientId: async (previewClientId, ownerDocument = document) => {
2570            const runtimeApi = await ensureRuntime();
2571            return runtimeApi.getControlInspectorPropertyValuesForPreviewClientId(previewClientId, ownerDocument);
2572        },
2573        discardHost,
2574        enqueueHost
2575    });
2576
2577    if (resolveBody()) {
2578        bootstrap();
2579    } else if (document.readyState === 'loading') {
2580        document.addEventListener('DOMContentLoaded', bootstrap, { once: true });
2581    }
2582})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.