(function () {
    function safeParseJson(raw, fallback) {
        if (raw == null || raw === '') {
            return fallback;
        }
        if (typeof raw === 'object') {
            return raw;
        }
        try {
            return JSON.parse(String(raw));
        } catch (error) {
            return fallback;
        }
    }

    function parseConfig(scriptNode) {
        if (!scriptNode) {
            return {};
        }

        var parsed = safeParseJson(scriptNode.textContent || '{}', null);
        if (parsed && typeof parsed === 'object') {
            return parsed;
        }

        console.error('[APD] Invalid config JSON.');
        return {};
    }


    function isApdVariationDebugEnabled() {
        return false;
    }

    function getApdVariationDebugStore() {
        return [];
    }

    function getApdVariationDebugSequence() {
        return 0;
    }

    function safeObjectKeys(value) {
        if (!value || typeof value !== 'object' || Array.isArray(value)) {
            return [];
        }
        try {
            return Object.keys(value);
        } catch (error) {
            return [];
        }
    }

    function apdPlainDataEqual(left, right) {
        if (left === right) {
            return true;
        }
        try {
            return JSON.stringify(left) === JSON.stringify(right);
        } catch (error) {
            return false;
        }
    }




    function apdDebugScalar(value) {
        if (value == null) {
            return '';
        }
        if (typeof value === 'number' || typeof value === 'boolean') {
            return value;
        }
        return String(value || '');
    }

    function apdDebugSummarizeObjectList(objects, limit) {
        objects = Array.isArray(objects) ? objects : [];
        limit = typeof limit === 'number' ? limit : 4;
        return {
            present: objects.length > 0,
            count: objects.length,
            samples: objects.slice(0, limit).map(function (object) {
                object = object && typeof object === 'object' ? object : {};
                return {
                    type: apdDebugScalar(object.type || object.objectType || object.kind),
                    id: apdDebugScalar(object.id || object._asukaObjectId || object.uuid || object.objectId),
                    name: apdDebugScalar(object.name || object.label || object._asukaElementName || object.asukaElementName),
                    itemGroup: apdDebugScalar(object.itemGroup || object.group || object._asukaSourceModule),
                    asukaElementId: apdDebugScalar(object._asukaElementId || object.asukaElementId),
                    left: object.left != null ? Number(object.left) : null,
                    top: object.top != null ? Number(object.top) : null,
                    width: object.width != null ? Number(object.width) : null,
                    height: object.height != null ? Number(object.height) : null,
                    srcLength: object.src != null ? String(object.src || '').length : (object.url != null ? String(object.url || '').length : 0),
                    keys: safeObjectKeys(object).slice(0, 14)
                };
            })
        };
    }

    function apdDebugSummarizeByViewBucket(bucket, snapshotMode) {
        var summary = {
            present: false,
            viewCount: 0,
            totalObjects: 0,
            viewIds: [],
            counts: {},
            samples: {}
        };
        if (!bucket || typeof bucket !== 'object' || Array.isArray(bucket)) {
            return summary;
        }
        var keys = safeObjectKeys(bucket);
        summary.present = keys.length > 0;
        summary.viewCount = keys.length;
        summary.viewIds = keys.slice(0, 12);
        keys.forEach(function (viewId) {
            var value = bucket[viewId];
            var objects = [];
            if (snapshotMode && value && typeof value === 'object' && Array.isArray(value.objects)) {
                objects = value.objects;
            } else if (!snapshotMode && Array.isArray(value)) {
                objects = value;
            } else if (!snapshotMode && value && typeof value === 'object' && Array.isArray(value.objects)) {
                objects = value.objects;
            }
            summary.counts[String(viewId)] = objects.length;
            summary.totalObjects += objects.length;
            if (objects.length) {
                summary.samples[String(viewId)] = apdDebugSummarizeObjectList(objects, 2).samples;
            }
        });
        return summary;
    }

    function apdDebugMaybeAddBucket(target, name, bucket, snapshotMode) {
        var summary = apdDebugSummarizeByViewBucket(bucket, !!snapshotMode);
        if (summary.present) {
            target[name] = summary;
        }
    }

    function apdDebugViewsSummary(value) {
        value = value && typeof value === 'object' ? value : {};
        var views = [];
        var shape = 'none';
        var activeViewId = value.activeViewId != null ? String(value.activeViewId || '') : '';
        if (Array.isArray(value.views)) {
            views = value.views;
            shape = 'array';
        } else if (value.views && typeof value.views === 'object' && Array.isArray(value.views.views)) {
            views = value.views.views;
            shape = 'bucket';
            activeViewId = value.views.activeViewId != null ? String(value.views.activeViewId || '') : activeViewId;
        }
        return {
            shape: shape,
            count: views.length,
            activeViewId: activeViewId,
            ids: views.slice(0, 12).map(function (view, index) {
                if (!view || typeof view !== 'object') {
                    return 'index:' + index;
                }
                return view.id != null ? String(view.id) : (view.name != null ? String(view.name) : 'index:' + index);
            })
        };
    }

    function apdDebugSummarizePayloadRestorePaths(value, depth) {
        depth = typeof depth === 'number' ? depth : 0;
        if (!value || typeof value !== 'object') {
            return {
                present: !!value,
                type: typeof value
            };
        }
        var canvas = value.canvas && typeof value.canvas === 'object' && !Array.isArray(value.canvas) ? value.canvas : {};
        var objectBuckets = {};
        var snapshotBuckets = {};
        apdDebugMaybeAddBucket(objectBuckets, 'objects.byView', value.objects && !Array.isArray(value.objects) ? value.objects.byView : null, false);
        apdDebugMaybeAddBucket(objectBuckets, 'documentObjectsByView', value.documentObjectsByView, false);
        apdDebugMaybeAddBucket(objectBuckets, 'objectsByView', value.objectsByView, false);
        apdDebugMaybeAddBucket(objectBuckets, 'byView', value.byView, false);
        apdDebugMaybeAddBucket(objectBuckets, 'canvas.objects.byView', canvas.objects && !Array.isArray(canvas.objects) ? canvas.objects.byView : null, false);
        apdDebugMaybeAddBucket(objectBuckets, 'canvas.documentObjectsByView', canvas.documentObjectsByView, false);
        apdDebugMaybeAddBucket(objectBuckets, 'canvas.objectsByView', canvas.objectsByView, false);
        apdDebugMaybeAddBucket(objectBuckets, 'canvas.byView', canvas.byView, false);

        apdDebugMaybeAddBucket(snapshotBuckets, 'snapshotsByView', value.snapshotsByView, true);
        apdDebugMaybeAddBucket(snapshotBuckets, 'snapshots.snapshotsByView', value.snapshots && !Array.isArray(value.snapshots) ? value.snapshots.snapshotsByView : null, true);
        apdDebugMaybeAddBucket(snapshotBuckets, 'viewSnapshots.snapshotsByView', value.viewSnapshots && !Array.isArray(value.viewSnapshots) ? value.viewSnapshots.snapshotsByView : null, true);
        apdDebugMaybeAddBucket(snapshotBuckets, 'viewSnapshots', value.viewSnapshots, true);
        apdDebugMaybeAddBucket(snapshotBuckets, 'canvas.snapshotsByView', canvas.snapshotsByView, true);
        apdDebugMaybeAddBucket(snapshotBuckets, 'canvas.snapshots.snapshotsByView', canvas.snapshots && !Array.isArray(canvas.snapshots) ? canvas.snapshots.snapshotsByView : null, true);
        apdDebugMaybeAddBucket(snapshotBuckets, 'canvas.viewSnapshots.snapshotsByView', canvas.viewSnapshots && !Array.isArray(canvas.viewSnapshots) ? canvas.viewSnapshots.snapshotsByView : null, true);
        apdDebugMaybeAddBucket(snapshotBuckets, 'canvas.viewSnapshots', canvas.viewSnapshots, true);

        var nested = {};
        if (depth < 1) {
            ['initialDocument', 'document', 'documentState', 'initialState', 'state', 'legacy'].forEach(function (key) {
                if (value[key] && typeof value[key] === 'object') {
                    nested[key] = apdDebugSummarizePayloadRestorePaths(value[key], depth + 1);
                }
            });
        }

        return {
            present: true,
            type: Array.isArray(value) ? 'array' : 'object',
            topKeys: safeObjectKeys(value).slice(0, 40),
            views: apdDebugViewsSummary(value),
            rootObjects: apdDebugSummarizeObjectList(Array.isArray(value.objects) ? value.objects : [], 4),
            objectBuckets: objectBuckets,
            snapshotBuckets: snapshotBuckets,
            selectedObjectsByView: apdDebugSummarizeByViewBucket(getPayloadObjectsByView(value), false),
            selectedSnapshotsByView: apdDebugSummarizeByViewBucket(getPayloadSnapshotsByView(value), true),
            nested: nested
        };
    }


    function apdDebugGetObjects(instance) {
        try {
            if (instance && instance.api && typeof instance.api.listObjects === 'function') {
                return instance.api.listObjects();
            }
            if (instance && instance.api && typeof instance.api.getObjects === 'function') {
                return instance.api.getObjects();
            }
        } catch (error) {}
        return [];
    }

    function apdDebugSummarizeRuntimeRestoreState(instance) {
        var result = {
            hasInstance: !!instance,
            hasStore: false,
            stateKeys: [],
            activeViewId: '',
            views: { count: 0, ids: [] },
            documentObjectsByView: apdDebugSummarizeByViewBucket(null, false),
            objectsByView: apdDebugSummarizeByViewBucket(null, false),
            stateObjectsByView: apdDebugSummarizeByViewBucket(null, false),
            snapshotsByView: apdDebugSummarizeByViewBucket(null, true),
            drawingAreasCount: 0,
            canvas: { hasCanvas: false, objects: apdDebugSummarizeObjectList([], 4) }
        };
        try {
            var store = apdGetRuntimeStore(instance || null);
            result.hasStore = !!store;
            var state = store && typeof store.getState === 'function' ? (store.getState() || {}) : {};
            result.stateKeys = safeObjectKeys(state).slice(0, 50);
            result.activeViewId = state.activeViewId != null ? String(state.activeViewId || '') : (state.views && state.views.activeViewId != null ? String(state.views.activeViewId || '') : '');
            var views = apdGetRuntimeViewsFromState(state);
            result.views = {
                count: Array.isArray(views) ? views.length : 0,
                ids: (Array.isArray(views) ? views : []).slice(0, 12).map(function (view, index) {
                    return view && typeof view === 'object' && view.id != null ? String(view.id) : 'index:' + index;
                })
            };
            result.documentObjectsByView = apdDebugSummarizeByViewBucket(state.documentObjectsByView, false);
            result.objectsByView = apdDebugSummarizeByViewBucket(state.objectsByView, false);
            result.stateObjectsByView = apdDebugSummarizeByViewBucket(state.objects && typeof state.objects === 'object' ? state.objects.byView : null, false);
            result.snapshotsByView = apdDebugSummarizeByViewBucket(apdGetRuntimeSnapshotsByViewFromState(state), true);
            result.drawingAreasCount = Array.isArray(state.documentDrawingAreas) ? state.documentDrawingAreas.length : 0;
        } catch (error) {
            result.storeError = error && error.message ? error.message : String(error);
        }
        try {
            var objects = apdDebugGetObjects(instance || null);
            result.canvas.hasCanvas = Array.isArray(objects);
            result.canvas.objects = apdDebugSummarizeObjectList(objects, 6);
        } catch (error) {
            result.canvasError = error && error.message ? error.message : String(error);
        }
        return result;
    }

    function countVariationTreeNodes(item) {
        if (!item || typeof item !== 'object') {
            return 0;
        }
        var total = 0;
        var variations = Array.isArray(item.variations) ? item.variations : [];
        total += variations.length;
        variations.forEach(function (variation) {
            total += countVariationTreeNodes(variation);
        });
        return total;
    }

    function summarizeElementDefinition(item) {
        if (!item || typeof item !== 'object') {
            return null;
        }
        return {
            id: item.id != null ? String(item.id) : '',
            name: item.name != null ? String(item.name) : '',
            label: item.label != null ? String(item.label) : '',
            familyId: item.familyId != null ? String(item.familyId) : '',
            asukaElementId: item._asukaElementId != null ? String(item._asukaElementId) : (item.asukaElementId != null ? String(item.asukaElementId) : ''),
            asukaElementName: item._asukaElementName != null ? String(item._asukaElementName) : (item.asukaElementName != null ? String(item.asukaElementName) : ''),
            asukaElementFamilyId: item._asukaElementFamilyId != null ? String(item._asukaElementFamilyId) : (item.asukaElementFamilyId != null ? String(item.asukaElementFamilyId) : ''),
            variationRoots: Array.isArray(item.variations) ? item.variations.length : 0,
            variationTotal: countVariationTreeNodes(item),
            childCount: Array.isArray(item.children) ? item.children.length : 0,
            keys: safeObjectKeys(item).slice(0, 24)
        };
    }

    function summarizeElementDefinitions(elements, limit) {
        elements = Array.isArray(elements) ? elements : [];
        limit = typeof limit === 'number' ? limit : 12;
        var variationTotal = 0;
        elements.forEach(function (item) {
            variationTotal += countVariationTreeNodes(item);
        });
        return {
            count: elements.length,
            variationTotal: variationTotal,
            items: elements.slice(0, limit).map(summarizeElementDefinition).filter(Boolean)
        };
    }

    function summarizeElementObject(object) {
        if (!object || typeof object !== 'object') {
            return null;
        }
        return {
            type: object.type != null ? String(object.type) : '',
            id: object.id != null ? String(object.id) : '',
            objectId: object._asukaObjectId != null ? String(object._asukaObjectId) : (object.uuid != null ? String(object.uuid) : ''),
            name: object.name != null ? String(object.name) : '',
            itemGroup: object.itemGroup != null ? String(object.itemGroup) : '',
            asukaElementId: object._asukaElementId != null ? String(object._asukaElementId) : (object.asukaElementId != null ? String(object.asukaElementId) : ''),
            asukaElementName: object._asukaElementName != null ? String(object._asukaElementName) : (object.asukaElementName != null ? String(object.asukaElementName) : (object.elementName != null ? String(object.elementName) : '')),
            asukaElementFamilyId: object._asukaElementFamilyId != null ? String(object._asukaElementFamilyId) : (object.asukaElementFamilyId != null ? String(object.asukaElementFamilyId) : (object.familyId != null ? String(object.familyId) : '')),
            variationId: object._asukaElementVariationId != null ? String(object._asukaElementVariationId) : (object.asukaElementVariationId != null ? String(object.asukaElementVariationId) : ''),
            isElementInstance: !!(object._asukaElementIsInstance || object.asukaElementIsInstance),
            keys: safeObjectKeys(object).slice(0, 28)
        };
    }

    function collectElementObjectsFromList(objects, limit, bucket) {
        bucket = bucket || [];
        if (!Array.isArray(objects) || bucket.length >= (limit || 20)) {
            return bucket;
        }
        objects.forEach(function (object) {
            if (!object || typeof object !== 'object' || bucket.length >= (limit || 20)) {
                return;
            }
            var summary = summarizeElementObject(object);
            var looksElement = summary && (
                summary.isElementInstance || summary.asukaElementId || summary.asukaElementName || summary.asukaElementFamilyId || String(summary.itemGroup).toLowerCase() === 'elements'
            );
            if (looksElement) {
                bucket.push(summary);
            }
            collectElementObjectsFromList(object.objects, limit, bucket);
            collectElementObjectsFromList(object._objects, limit, bucket);
        });
        return bucket;
    }

    function summarizeRuntimeElementState(instance) {
        var result = {
            hasInstance: !!instance,
            hasStore: false,
            storeElements: summarizeElementDefinitions([], 8),
            picker: null,
            activeViewId: '',
            documentObjectViewKeys: [],
            documentElementObjects: [],
            canvasElementObjects: []
        };
        try {
            var store = apdGetRuntimeStore(instance);
            result.hasStore = !!store;
            if (store && typeof store.getState === 'function') {
                var state = store.getState() || {};
                result.storeElements = summarizeElementDefinitions(Array.isArray(state.elements) ? state.elements : [], 8);
                result.picker = state.elementVariationPicker && typeof state.elementVariationPicker === 'object' ? clonePlainObject(state.elementVariationPicker) : null;
                result.activeViewId = state.activeViewId != null ? String(state.activeViewId) : '';
                var byView = state.documentObjectsByView && typeof state.documentObjectsByView === 'object' ? state.documentObjectsByView : {};
                result.documentObjectViewKeys = safeObjectKeys(byView);
                result.documentObjectViewKeys.forEach(function (viewId) {
                    result.documentElementObjects = result.documentElementObjects.concat(collectElementObjectsFromList(byView[viewId], 20, []));
                });
            }
        } catch (error) {
            result.storeError = error && error.message ? error.message : String(error);
        }
        try {
            result.canvasElementObjects = collectElementObjectsFromList(apdDebugGetObjects(instance), 20, []);
        } catch (error) {
            result.canvasError = error && error.message ? error.message : String(error);
        }
        return result;
    }

    function installVariationRuntimeDump(instance, shell) {
        return;
    }

    function summarizeViewContainer(value) {
        if (!value || typeof value !== 'object') {
            return { hasValue: !!value, type: typeof value, viewsCount: 0, activeViewId: '', objectCount: 0, snapshotCount: 0 };
        }
        var views = [];
        var activeViewId = value.activeViewId != null ? String(value.activeViewId) : '';
        if (Array.isArray(value.views)) {
            views = value.views;
        } else if (value.views && typeof value.views === 'object' && Array.isArray(value.views.views)) {
            views = value.views.views;
            activeViewId = value.views.activeViewId != null ? String(value.views.activeViewId) : activeViewId;
        } else if (value.document && typeof value.document === 'object') {
            return summarizeViewContainer(value.document);
        } else if (value.initialDocument && typeof value.initialDocument === 'object') {
            return summarizeViewContainer(value.initialDocument);
        } else if (value.documentState && typeof value.documentState === 'object') {
            return summarizeViewContainer(value.documentState);
        }

        var snapshotsByView = getPayloadSnapshotsByView(value);
        var objectsByView = getPayloadObjectsByView(value);
        var snapshotKeys = safeObjectKeys(snapshotsByView);
        var objectViewKeys = safeObjectKeys(objectsByView);
        var objectCount = countPayloadObjects(value);

        return {
            hasValue: true,
            type: 'object',
            topKeys: safeObjectKeys(value),
            viewsCount: Array.isArray(views) ? views.length : 0,
            activeViewId: activeViewId,
            firstViewIds: Array.isArray(views) ? views.slice(0, 4).map(function (item) {
                if (!item || typeof item !== 'object') {
                    return '';
                }
                return item.id != null ? String(item.id) : (item.name != null ? String(item.name) : '');
            }).filter(Boolean) : [],
            snapshotCount: snapshotKeys.length,
            snapshotViewIds: snapshotKeys.slice(0, 4),
            objectViewCount: objectViewKeys.length,
            objectViewIds: objectViewKeys.slice(0, 4),
            objectCount: objectCount,
            drawingAreasCount: Array.isArray(value.drawingAreas) ? value.drawingAreas.length : (value.drawingAreas && Array.isArray(value.drawingAreas.zones) ? value.drawingAreas.zones.length : 0)
        };
    }

    function summarizeMountPayload(payload) {
        payload = payload && typeof payload === 'object' ? payload : {};
        var stateDocument = payload.initialState && typeof payload.initialState === 'object'
            ? (payload.initialState.initialDocument || payload.initialState.document || payload.initialState)
            : null;
        var context = payload.context && typeof payload.context === 'object' ? payload.context : {};
        var templateDebug = context.apdTemplateLayoutDebug && typeof context.apdTemplateLayoutDebug === 'object'
            ? context.apdTemplateLayoutDebug
            : null;
        return {
            topKeys: safeObjectKeys(payload),
            hasInitialDocument: !!(payload.initialDocument && typeof payload.initialDocument === 'object'),
            hasInitialState: !!(payload.initialState && typeof payload.initialState === 'object'),
            initialDocument: summarizeViewContainer(payload.initialDocument),
            initialStateDocument: summarizeViewContainer(stateDocument),
            viewsCount: Array.isArray(payload.views) ? payload.views.length : 0,
            drawingZonesCount: Array.isArray(payload.drawingZones) ? payload.drawingZones.length : 0,
            elements: summarizeElementDefinitions(Array.isArray(payload.elements) ? payload.elements : [], 6),
            runtimeElements: summarizeElementDefinitions(Array.isArray(payload.runtimeElements) ? payload.runtimeElements : [], 6),
            catalogElements: summarizeElementDefinitions(payload.catalog && Array.isArray(payload.catalog.elements) ? payload.catalog.elements : [], 6),
            initialStateElements: summarizeElementDefinitions(payload.initialState && Array.isArray(payload.initialState.elements) ? payload.initialState.elements : [], 6),
            initialDocumentElements: summarizeElementDefinitions(payload.initialDocument && Array.isArray(payload.initialDocument.elements) ? payload.initialDocument.elements : [], 6),
            layout: summarizeLayoutDebug(payload.layout),
            layoutKeys: safeObjectKeys(payload.layout),
            uiKeys: safeObjectKeys(payload.ui),
            viewsPagination: payload.ui && typeof payload.ui === 'object' ? {
                hasViewsPagination: Object.prototype.hasOwnProperty.call(payload.ui, 'viewsPagination'),
                viewsPagination: payload.ui.viewsPagination === false ? false : (payload.ui.viewsPagination && typeof payload.ui.viewsPagination === 'object' ? clonePlainObject(payload.ui.viewsPagination) : null),
                viewsPaginationEnabled: Object.prototype.hasOwnProperty.call(payload.ui, 'viewsPaginationEnabled') ? !!payload.ui.viewsPaginationEnabled : null,
                viewsPaginationMode: typeof payload.ui.viewsPaginationMode === 'string' ? payload.ui.viewsPaginationMode : ''
            } : null,
            contextKeys: safeObjectKeys(payload.context),
            templateDebug: templateDebug ? {
                productId: Number(templateDebug.productId || 0) || 0,
                configId: Number(templateDebug.configId || 0) || 0,
                variationId: Number(templateDebug.variationId || 0) || 0,
                configTitle: templateDebug.configTitle || '',
                templateId: Number(templateDebug.templateId || 0) || 0,
                templateTitle: templateDebug.templateTitle || '',
                templateExists: !!templateDebug.templateExists,
                templateHasLayout: !!templateDebug.templateHasLayout,
                productLayout: templateDebug.productLayout || null,
                templateLayout: templateDebug.templateLayout || null,
                frontendLayout: templateDebug.frontendLayout || null,
                layoutSource: templateDebug.layoutSource || '',
                frontendLayoutIsNull: !!templateDebug.frontendLayoutIsNull
            } : null
        };
    }

    function summarizeShellDebug(shell) {
        if (!shell || typeof shell !== 'object') {
            return {};
        }
        return {
            shellKey: shell.dataset && shell.dataset.apdShellKey ? String(shell.dataset.apdShellKey) : '',
            productId: shell.dataset && shell.dataset.productId ? Number(shell.dataset.productId || 0) : 0,
            configId: shell.dataset && shell.dataset.configId ? Number(shell.dataset.configId || 0) : 0,
            variationId: shell.dataset && shell.dataset.variationId ? Number(shell.dataset.variationId || 0) : 0,
            templateId: shell.dataset && shell.dataset.templateId ? Number(shell.dataset.templateId || 0) : 0,
            templateTitle: shell.dataset && shell.dataset.templateTitle ? String(shell.dataset.templateTitle || '') : '',
            configTitle: shell.dataset && shell.dataset.configTitle ? String(shell.dataset.configTitle || '') : ''
        };
    }

    function isApdRuntimeDebugEnabled() {
        try {
            var search = window.location && typeof window.location.search === 'string' ? window.location.search : '';
            if (search.indexOf('apd_debug_runtime=0') !== -1 || search.indexOf('apd_debug=0') !== -1) {
                return false;
            }
            if (search.indexOf('apd_debug_runtime=1') !== -1 || search.indexOf('apd_debug=1') !== -1 || search.indexOf('apd_submit_debug=1') !== -1) {
                return true;
            }
        } catch (error) {}
        return false;
    }

    var APD_RUNTIME_DEBUG_STORAGE_KEY = 'apd_runtime_debug_entries';

    function logApdVariationDebug(tag, data) {
        if (!isApdRuntimeDebugEnabled()) {
            return;
        }
        var entry = {
            time: (new Date()).toISOString(),
            tag: String(tag || ''),
            data: data || {}
        };
        try {
            if (window.sessionStorage) {
                var list = [];
                try {
                    list = JSON.parse(window.sessionStorage.getItem(APD_RUNTIME_DEBUG_STORAGE_KEY) || '[]') || [];
                } catch (error) {
                    list = [];
                }
                list.push(entry);
                if (list.length > 250) {
                    list = list.slice(list.length - 250);
                }
                window.sessionStorage.setItem(APD_RUNTIME_DEBUG_STORAGE_KEY, JSON.stringify(list));
            }
        } catch (error) {}
        try {
            if (window.console && typeof window.console.log === 'function') {
                window.console.log('[APD RUNTIME] ' + entry.tag + '\n' + JSON.stringify(entry.data, null, 2));
            }
        } catch (error) {}
    }

    try {
        window.APDRuntimeDebugCopy = function () {
            var text = '[]';
            try {
                text = window.sessionStorage ? (window.sessionStorage.getItem(APD_RUNTIME_DEBUG_STORAGE_KEY) || '[]') : '[]';
            } catch (error) {}
            try {
                if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
                    navigator.clipboard.writeText(text);
                }
            } catch (error) {}
            try {
                return JSON.parse(text);
            } catch (error) {
                return text;
            }
        };
        window.APDRuntimeDebugClear = function () {
            try {
                if (window.sessionStorage) {
                    window.sessionStorage.removeItem(APD_RUNTIME_DEBUG_STORAGE_KEY);
                }
            } catch (error) {}
            return true;
        };
    } catch (error) {}


    function isApdTemplateLayoutDebugEnabled() {
        try {
            var search = window.location && typeof window.location.search === 'string' ? window.location.search : '';
            if (search.indexOf('apd_debug_template=0') !== -1 || search.indexOf('apd_debug=0') !== -1) {
                return false;
            }
            if (search.indexOf('apd_debug_template=1') !== -1 || search.indexOf('apd_debug=1') !== -1) {
                return true;
            }
            return false;
        } catch (error) {}
        return false;
    }

    function summarizeLayoutDebug(layout) {
        layout = layout && typeof layout === 'object' && !Array.isArray(layout) ? layout : {};
        var zoneItemCounts = {};
        var itemIds = [];
        var items = [];
        ['left', 'right', 'top', 'bottom'].forEach(function (zone) {
            var zoneConfig = layout[zone] && typeof layout[zone] === 'object' ? layout[zone] : {};
            var zoneItems = Array.isArray(zoneConfig.items) ? zoneConfig.items : [];
            zoneItemCounts[zone] = zoneItems.length;
            zoneItems.forEach(function (item) {
                if (!item || typeof item !== 'object') {
                    return;
                }
                var id = item.id != null ? String(item.id) : (item.kind != null ? String(item.kind) : '');
                if (id) {
                    itemIds.push(id);
                }
                items.push({
                    id: id,
                    kind: item.kind != null ? String(item.kind) : '',
                    zone: zone,
                    mountTarget: typeof item.mountTarget === 'string' ? item.mountTarget : '',
                    renderMode: typeof item.renderMode === 'string' ? item.renderMode : ''
                });
            });
        });
        return {
            topKeys: safeObjectKeys(layout),
            zoneItemCounts: zoneItemCounts,
            itemIds: itemIds,
            items: items
        };
    }

    function exposeTemplateLayoutDebug(shell, layout) {
        if (!shell || !shell.setAttribute || !isApdTemplateLayoutDebugEnabled()) {
            return;
        }
        try {
            shell.setAttribute('data-apd-debug-runtime-layout', JSON.stringify(summarizeLayoutDebug(layout)));
        } catch (error) {}
    }

    function getExportedRuntimeLayout(instance) {
        var store = apdGetRuntimeStore(instance);
        try {
            if (store && typeof store.getState === 'function') {
                var liveState = store.getState() || {};
                var blocksByZone = liveState.blocksByZone && typeof liveState.blocksByZone === 'object'
                    ? liveState.blocksByZone
                    : null;
                if (blocksByZone) {
                    var liveLayout = {};
                    ['left', 'right', 'top', 'bottom'].forEach(function (zone) {
                        liveLayout[zone] = {
                            items: Array.isArray(blocksByZone[zone]) ? clonePlainObject(blocksByZone[zone]) : [],
                            collapsed: !!(liveState.zoneCollapsed && liveState.zoneCollapsed[zone]),
                            collapsible: !(liveState.zoneCollapsible && liveState.zoneCollapsible[zone] === false),
                            type: liveState.zoneType && typeof liveState.zoneType[zone] === 'string'
                                ? liveState.zoneType[zone]
                                : 'default'
                        };
                    });
                    return liveLayout;
                }
            }
        } catch (error) {}

        var state = exportState(instance || null);
        if (!state || typeof state !== 'object') {
            return {};
        }
        return normalizeRuntimeLayout(state.layout || (state.ui && typeof state.ui === 'object' ? state.ui.layout : null) || {});
    }

    function logTemplateLayoutDebug(tag, data) {
        if (!isApdTemplateLayoutDebugEnabled()) {
            return;
        }
        var payload = data || {};
        logApdVariationDebug('templateLayout:' + String(tag || ''), payload);
    }

    function runtimeLabel(key, fallback) {
        var runtimeLabels = window.APD_RUNTIME && window.APD_RUNTIME.labels ? window.APD_RUNTIME.labels : {};
        if (Object.prototype.hasOwnProperty.call(runtimeLabels, key)) {
            return runtimeLabels[key];
        }
        var adminLabels = window.APDAdminConfig && window.APDAdminConfig.labels ? window.APDAdminConfig.labels : {};
        if (Object.prototype.hasOwnProperty.call(adminLabels, key)) {
            return adminLabels[key];
        }
        return fallback;
    }

    function getCreateFn() {
        if (window.createAsukaDesigner && typeof window.createAsukaDesigner === 'function') {
            return window.createAsukaDesigner;
        }
        if (window.AsukaDesigner && typeof window.AsukaDesigner.createAsukaDesigner === 'function') {
            return window.AsukaDesigner.createAsukaDesigner;
        }
        return null;
    }

    function sanitizeObject(value, fallback) {
        return value && typeof value === 'object' && !Array.isArray(value) ? value : fallback;
    }

    function sanitizeArray(value, fallback) {
        return Array.isArray(value) ? value : fallback;
    }

    function normalizeRuntimeDrawingZonesInput(value) {
        if (Array.isArray(value)) {
            return value.map(function (zone) { return normalizeDrawingAreaZone(zone, ''); }).filter(Boolean);
        }
        if (!value || typeof value !== 'object') {
            return [];
        }
        var byView = null;
        if (value.byView && typeof value.byView === 'object' && !Array.isArray(value.byView)) {
            byView = value.byView;
        } else if (value.drawingAreasByView && typeof value.drawingAreasByView === 'object' && !Array.isArray(value.drawingAreasByView)) {
            byView = value.drawingAreasByView;
        } else if (value.drawingAreas && value.drawingAreas.byView && typeof value.drawingAreas.byView === 'object' && !Array.isArray(value.drawingAreas.byView)) {
            byView = value.drawingAreas.byView;
        }
        if (byView) {
            return flattenDrawingAreasByView(byView);
        }
        if (value.drawingAreas && Array.isArray(value.drawingAreas.zones)) {
            return value.drawingAreas.zones.map(function (zone) { return normalizeDrawingAreaZone(zone, ''); }).filter(Boolean);
        }
        if (Array.isArray(value.zones)) {
            return value.zones.map(function (zone) { return normalizeDrawingAreaZone(zone, ''); }).filter(Boolean);
        }
        if (Array.isArray(value.drawingZones)) {
            return value.drawingZones.map(function (zone) { return normalizeDrawingAreaZone(zone, ''); }).filter(Boolean);
        }
        return [];
    }

    function ensureRuntimeLayoutItem(layout, zone, item, beforeKinds) {
        layout = layout && typeof layout === 'object' && !Array.isArray(layout) ? layout : {};
        zone = zone || 'left';
        beforeKinds = Array.isArray(beforeKinds) ? beforeKinds : [];
        layout[zone] = layout[zone] && typeof layout[zone] === 'object' && !Array.isArray(layout[zone]) ? layout[zone] : {};
        layout[zone].type = layout[zone].type || 'default';
        layout[zone].collapsed = !!layout[zone].collapsed;
        layout[zone].collapsible = layout[zone].collapsible !== false;

        var items = Array.isArray(layout[zone].items) ? layout[zone].items.slice() : [];
        var targetKind = String(item.kind || item.id || '');
        var hasItem = items.some(function (existing) {
            if (!existing || typeof existing !== 'object') {
                return false;
            }
            return String(existing.kind || existing.id || '') === targetKind;
        });
        if (hasItem) {
            layout[zone].items = items;
            return layout;
        }

        var insertAt = items.length;
        for (var index = 0; index < items.length; index += 1) {
            var existing = items[index];
            if (!existing || typeof existing !== 'object') {
                continue;
            }
            if (beforeKinds.indexOf(String(existing.kind || existing.id || '')) !== -1) {
                insertAt = index;
                break;
            }
        }
        items.splice(insertAt, 0, item);
        layout[zone].items = items;
        return layout;
    }

    var ADMIN_PERMISSION_KEYS = [
        'canOpenModule', 'canMovePanels', 'canCollapsePanels', 'canUseStateTools',
        'canUseMagnifier', 'canUseZoom', 'canZoomIn', 'canZoomOut', 'canFitViewport',
        'canResetViewport', 'canPanCanvas', 'canUndo', 'canRedo', 'canReset',
        'canAddRect', 'canAddText', 'canAddImage', 'canAddShape', 'canDrawShape',
        'canClearCanvas', 'canDuplicateObject', 'canDeleteObject', 'canMoveObject',
        'canResizeObject', 'canRotateObject', 'canEditObjectColors', 'canEditObjectStudio',
        'canEditObjectText', 'canSwitchView', 'canAddView', 'canViewViews',
        'canCreateView', 'canEditView', 'canDeleteView', 'canViewLayers',
        'canReorderLayers', 'canLockLayers', 'canHideLayers', 'canSelectLayers',
        'canViewDesigns', 'canAddDesigns', 'canOpenImages', 'canUploadImage',
        'canUseRemoteImages', 'canUseExternalImageLibraries', 'canUseFacebookImages',
        'canUsePixabayImages', 'canUsePexelsImages', 'canEditText', 'canEditFontFamily',
        'canEditTextFormatting', 'canEditTextCurve', 'canUseColors', 'canEditColors',
        'canUseStudio', 'canApplyStudioEffects', 'canDownload', 'canDownloadCurrentView',
        'canDownloadAllViews', 'canDownloadObjects', 'canDownloadDrawingZones',
        'canExportJson', 'canImportJson', 'canViewDrawingAreas', 'canCreateDrawingAreas',
        'canEditDrawingAreas', 'canDeleteDrawingAreas', 'canViewFixedSlots',
        'canCreateFixedSlots', 'canEditFixedSlots', 'canDeleteFixedSlots', 'canViewPricing',
        'canEditPricingBasePrice', 'canEditPricingRules', 'canAddPricingRule',
        'canRemovePricingRule', 'canViewElements', 'canAddElements', 'canEditElements',
        'canEditElementVariations', 'canDeleteElements'
    ];

    var ADMIN_MODULE_KEYS = [
        'views', 'designs', 'text', 'image', 'images', 'shapes', 'layers',
        'elements', 'drawingAreas', 'marker', 'fixedSlots', 'pricing', 'pricingRules',
        'colors', 'download', 'state', 'history', 'zoom', 'ruler', 'magnifier',
        'studio', 'aiTextToImage', 'facebookImage', 'pixabayImage', 'pexelsImage'
    ];

    function isAdminEditorRuntimeConfig(config) {
        if (!config || typeof config !== 'object') {
            return false;
        }
        var context = config.context && typeof config.context === 'object' ? config.context : {};
        return !!(
            window.APDAdminConfig
            || context.isAdmin === true
            || String(context.isAdmin || '') === '1'
            || context.apdAdminEditorPermissions
            || String(context.apdLayoutSource || '') === 'admin_editor'
        );
    }

    function makeAdminRuntimePermissions(base) {
        var permissions = Object.assign({}, sanitizeObject(base, {}));
        ADMIN_PERMISSION_KEYS.forEach(function (key) {
            permissions[key] = true;
        });
        Object.keys(permissions).forEach(function (key) {
            if (typeof permissions[key] === 'boolean') {
                permissions[key] = true;
            }
        });
        var moduleOpen = sanitizeObject(permissions.moduleOpen, {});
        Object.keys(moduleOpen).forEach(function (key) {
            moduleOpen[key] = true;
        });
        ADMIN_MODULE_KEYS.forEach(function (key) {
            moduleOpen[key] = true;
        });
        permissions.moduleOpen = moduleOpen;
        return permissions;
    }

    function stripRuntimePermissionsFromBootPayload(payload) {
        if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
            return payload;
        }
        delete payload.permissions;
        delete payload.permissionsByView;
        delete payload.role;
        if (payload.ui && typeof payload.ui === 'object') {
            delete payload.ui.permissions;
            delete payload.ui.permissionsByView;
        }
        if (payload.scope && typeof payload.scope === 'object') {
            delete payload.scope.permissions;
            delete payload.scope.permissionsByView;
        }
        if (payload.legacy && typeof payload.legacy === 'object') {
            if (payload.legacy.state && typeof payload.legacy.state === 'object') {
                payload.legacy.state = stripRuntimePermissionsFromBootPayload(payload.legacy.state);
            }
            if (payload.legacy.scope && typeof payload.legacy.scope === 'object') {
                delete payload.legacy.scope.permissions;
                delete payload.legacy.scope.permissionsByView;
            }
        }
        ['state', 'initialState', 'document', 'documentState', 'initialDocument'].forEach(function (key) {
            if (payload[key] && typeof payload[key] === 'object') {
                payload[key] = stripRuntimePermissionsFromBootPayload(payload[key]);
            }
        });
        return payload;
    }

    function forceAdminRuntimePermissions(config) {
        if (!isAdminEditorRuntimeConfig(config)) {
            return config;
        }
        config.permissions = makeAdminRuntimePermissions(config.permissions);
        config.context = config.context && typeof config.context === 'object' ? config.context : {};
        config.context.isAdmin = true;
        config.context.apdAdminEditorPermissions = true;
        if (config.initialDocument && typeof config.initialDocument === 'object') {
            config.initialDocument = stripRuntimePermissionsFromBootPayload(config.initialDocument);
        }
        if (config.initialState && typeof config.initialState === 'object') {
            config.initialState = stripRuntimePermissionsFromBootPayload(config.initialState);
        }
        return config;
    }

    var APD_CLIENT_MODULE_ALIAS_GROUPS = [
        ['views'],
        ['designs'],
        ['text'],
        ['image', 'images'],
        ['image-upload', 'uploadImage', 'upload-image'],
        ['image-qrcode', 'qrcodeImage', 'qrcode-image'],
        ['image-ai-text-to-image', 'aiTextToImage', 'ai-text-to-image'],
        ['image-facebook', 'facebookImage', 'facebook-image'],
        ['image-pixabay', 'pixabayImage', 'pixabay-image'],
        ['image-pexels', 'pexelsImage', 'pexels-image'],
        ['shapes'],
        ['layers'],
        ['colors'],
        ['zoom'],
        ['magnifier'],
        ['download'],
        ['history'],
        ['state'],
        ['pricing'],
        ['pricingRules', 'pricing-rules'],
        ['elements'],
        ['element-variation-picker', 'elementVariationPicker', 'variations'],
        ['drawingAreas', 'drawing-areas'],
        ['marker', 'fixedSlots', 'fixed-slots'],
        ['element-editor', 'elementEditor'],
        ['product-parameters', 'productParameters'],
        ['materials'],
        ['camera'],
        ['modelOptimizer', 'model-optimizer'],
        ['license'],
        ['studio'],
        ['ruler']
    ];

    function apdNormalizeModuleOpenAliases(moduleOpen) {
        moduleOpen = sanitizeObject(moduleOpen, {});
        APD_CLIENT_MODULE_ALIAS_GROUPS.forEach(function (aliases) {
            var hasExplicitFalse = aliases.some(function (alias) { return Object.prototype.hasOwnProperty.call(moduleOpen, alias) && moduleOpen[alias] === false; });
            var hasExplicitTrue = aliases.some(function (alias) { return Object.prototype.hasOwnProperty.call(moduleOpen, alias) && moduleOpen[alias] === true; });
            if (!hasExplicitFalse && !hasExplicitTrue) {
                return;
            }
            var resolved = !hasExplicitFalse;
            aliases.forEach(function (alias) {
                moduleOpen[alias] = resolved;
            });
        });
        Object.keys(moduleOpen).forEach(function (key) {
            if (moduleOpen[key] !== true && moduleOpen[key] !== false) {
                delete moduleOpen[key];
            }
        });
        return moduleOpen;
    }

    function apdSetModuleAliases(moduleOpen, aliases, enabled) {
        aliases.forEach(function (alias) {
            moduleOpen[alias] = !!enabled;
        });
    }

    function apdHasDisabledModuleAlias(moduleOpen, aliases) {
        return aliases.some(function (alias) {
            return Object.prototype.hasOwnProperty.call(moduleOpen, alias) && moduleOpen[alias] === false;
        });
    }

    function apdSetPermissionsFalse(permissions, keys) {
        keys.forEach(function (key) {
            permissions[key] = false;
        });
    }

    function normalizeClientViewPermissions(config) {
        if (!config || typeof config !== 'object' || isAdminEditorRuntimeConfig(config)) {
            return config;
        }

        var permissions = sanitizeObject(config.permissions, {});
        if (!Object.keys(permissions).length) {
            return config;
        }

        var moduleOpen = apdNormalizeModuleOpenAliases(permissions.moduleOpen);

        if (permissions.canOpenModule === false) {
            APD_CLIENT_MODULE_ALIAS_GROUPS.forEach(function (aliases) {
                apdSetModuleAliases(moduleOpen, aliases, false);
            });
        }

        if (apdHasDisabledModuleAlias(moduleOpen, ['views'])) permissions.canViewViews = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['designs'])) permissions.canViewDesigns = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['text'])) apdSetPermissionsFalse(permissions, ['canAddText', 'canEditText']);
        if (apdHasDisabledModuleAlias(moduleOpen, ['image', 'images'])) permissions.canOpenImages = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['shapes'])) apdSetPermissionsFalse(permissions, ['canAddRect', 'canAddShape', 'canDrawShape']);
        if (apdHasDisabledModuleAlias(moduleOpen, ['layers'])) permissions.canViewLayers = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['colors'])) permissions.canUseColors = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['zoom'])) permissions.canUseZoom = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['magnifier'])) permissions.canUseMagnifier = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['download'])) permissions.canDownload = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['history'])) apdSetPermissionsFalse(permissions, ['canUndo', 'canRedo', 'canReset']);
        if (apdHasDisabledModuleAlias(moduleOpen, ['state'])) permissions.canUseStateTools = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['pricing', 'pricingRules', 'pricing-rules'])) permissions.canViewPricing = false;
        // Hiding the Elements catalog only removes the administration surface.
        // Customers still need readonly element access so a product instance can
        // open its dedicated variation picker from the canvas.
        if (apdHasDisabledModuleAlias(moduleOpen, ['element-editor', 'elementEditor'])) apdSetPermissionsFalse(permissions, ['canEditElements', 'canEditElementVariations', 'canDeleteElements']);
        if (apdHasDisabledModuleAlias(moduleOpen, ['drawingAreas', 'drawing-areas'])) permissions.canViewDrawingAreas = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['marker', 'fixedSlots', 'fixed-slots'])) permissions.canViewFixedSlots = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['studio'])) permissions.canUseStudio = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['image-facebook', 'facebookImage', 'facebook-image'])) permissions.canUseFacebookImages = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['image-pixabay', 'pixabayImage', 'pixabay-image'])) permissions.canUsePixabayImages = false;
        if (apdHasDisabledModuleAlias(moduleOpen, ['image-pexels', 'pexelsImage', 'pexels-image'])) permissions.canUsePexelsImages = false;

        if (permissions.canCreateView === false || permissions.canAddView === false) {
            apdSetPermissionsFalse(permissions, ['canCreateView', 'canAddView']);
        }
        if (permissions.canViewViews === false) {
            apdSetPermissionsFalse(permissions, ['canCreateView', 'canAddView', 'canEditView', 'canDeleteView']);
            apdSetModuleAliases(moduleOpen, ['views'], false);
        }
        if (permissions.canViewDesigns === false) {
            permissions.canAddDesigns = false;
            apdSetModuleAliases(moduleOpen, ['designs'], false);
        }
        if (permissions.canOpenImages === false) {
            apdSetPermissionsFalse(permissions, ['canAddImage', 'canUploadImage', 'canUseRemoteImages', 'canUseExternalImageLibraries', 'canUseFacebookImages', 'canUsePixabayImages', 'canUsePexelsImages']);
            apdSetModuleAliases(moduleOpen, ['image', 'images', 'image-upload', 'uploadImage', 'upload-image', 'image-qrcode', 'qrcodeImage', 'qrcode-image', 'image-ai-text-to-image', 'aiTextToImage', 'ai-text-to-image', 'image-facebook', 'facebookImage', 'facebook-image', 'image-pixabay', 'pixabayImage', 'pixabay-image', 'image-pexels', 'pexelsImage', 'pexels-image'], false);
        }
        if (permissions.canAddImage === false) {
            apdSetPermissionsFalse(permissions, ['canUploadImage', 'canUseRemoteImages']);
            apdSetModuleAliases(moduleOpen, ['image-upload', 'uploadImage', 'upload-image', 'image-qrcode', 'qrcodeImage', 'qrcode-image', 'image-ai-text-to-image', 'aiTextToImage', 'ai-text-to-image', 'image-facebook', 'facebookImage', 'facebook-image', 'image-pixabay', 'pixabayImage', 'pixabay-image', 'image-pexels', 'pexelsImage', 'pexels-image'], false);
        }
        if (permissions.canUploadImage === false) apdSetModuleAliases(moduleOpen, ['image-upload', 'uploadImage', 'upload-image'], false);
        if (permissions.canUseExternalImageLibraries === false) {
            apdSetPermissionsFalse(permissions, ['canUseFacebookImages', 'canUsePixabayImages', 'canUsePexelsImages']);
            apdSetModuleAliases(moduleOpen, ['image-facebook', 'facebookImage', 'facebook-image', 'image-pixabay', 'pixabayImage', 'pixabay-image', 'image-pexels', 'pexelsImage', 'pexels-image'], false);
        }
        if (permissions.canUseFacebookImages === false) apdSetModuleAliases(moduleOpen, ['image-facebook', 'facebookImage', 'facebook-image'], false);
        if (permissions.canUsePixabayImages === false) apdSetModuleAliases(moduleOpen, ['image-pixabay', 'pixabayImage', 'pixabay-image'], false);
        if (permissions.canUsePexelsImages === false) apdSetModuleAliases(moduleOpen, ['image-pexels', 'pexelsImage', 'pexels-image'], false);
        if (permissions.canEditText === false) {
            apdSetPermissionsFalse(permissions, ['canEditFontFamily', 'canEditTextFormatting', 'canEditTextCurve', 'canEditObjectText']);
        }
        if (permissions.canAddShape === false) permissions.canDrawShape = false;
        if (permissions.canViewLayers === false) {
            apdSetPermissionsFalse(permissions, ['canReorderLayers', 'canLockLayers', 'canHideLayers', 'canSelectLayers']);
            apdSetModuleAliases(moduleOpen, ['layers'], false);
        }
        if (permissions.canUseColors === false) {
            permissions.canEditColors = false;
            apdSetModuleAliases(moduleOpen, ['colors'], false);
        }
        if (permissions.canUseZoom === false) {
            apdSetPermissionsFalse(permissions, ['canZoomIn', 'canZoomOut', 'canFitViewport', 'canResetViewport']);
            apdSetModuleAliases(moduleOpen, ['zoom'], false);
        }
        if (permissions.canUseMagnifier === false) apdSetModuleAliases(moduleOpen, ['magnifier'], false);
        if (permissions.canDownload === false) {
            apdSetPermissionsFalse(permissions, ['canDownloadCurrentView', 'canDownloadAllViews', 'canDownloadObjects', 'canDownloadDrawingZones']);
            apdSetModuleAliases(moduleOpen, ['download'], false);
        }
        if (permissions.canUseStateTools === false) {
            apdSetPermissionsFalse(permissions, ['canExportJson', 'canImportJson']);
            apdSetModuleAliases(moduleOpen, ['state'], false);
        }
        if (permissions.canUseStudio === false) {
            permissions.canApplyStudioEffects = false;
            apdSetModuleAliases(moduleOpen, ['studio'], false);
        }
        if (permissions.canViewDrawingAreas === false) {
            apdSetPermissionsFalse(permissions, ['canCreateDrawingAreas', 'canEditDrawingAreas', 'canDeleteDrawingAreas']);
            apdSetModuleAliases(moduleOpen, ['drawingAreas', 'drawing-areas'], false);
        }
        if (permissions.canViewFixedSlots === false) {
            apdSetPermissionsFalse(permissions, ['canCreateFixedSlots', 'canEditFixedSlots', 'canDeleteFixedSlots']);
            apdSetModuleAliases(moduleOpen, ['marker', 'fixedSlots', 'fixed-slots'], false);
        }
        if (permissions.canViewPricing === false) {
            apdSetPermissionsFalse(permissions, ['canEditPricingBasePrice', 'canEditPricingRules', 'canAddPricingRule', 'canRemovePricingRule']);
            apdSetModuleAliases(moduleOpen, ['pricing', 'pricingRules', 'pricing-rules'], false);
        }
        if (permissions.canEditPricingRules === false) {
            apdSetPermissionsFalse(permissions, ['canAddPricingRule', 'canRemovePricingRule']);
        }
        if (permissions.canViewElements === false) {
            apdSetPermissionsFalse(permissions, ['canAddElements', 'canEditElements', 'canEditElementVariations', 'canDeleteElements']);
            apdSetModuleAliases(moduleOpen, ['elements', 'element-editor', 'elementEditor'], false);
        }
        if (permissions.canEditElements === false) {
            apdSetPermissionsFalse(permissions, ['canEditElementVariations', 'canDeleteElements']);
            apdSetModuleAliases(moduleOpen, ['element-editor', 'elementEditor'], false);
        }

        moduleOpen = apdNormalizeModuleOpenAliases(moduleOpen);
        if (Object.keys(moduleOpen).length) {
            permissions.moduleOpen = moduleOpen;
        } else {
            delete permissions.moduleOpen;
        }

        config.permissions = permissions;
        return config;
    }


    var APD_BOOT_IMPORT_PERMISSION_KEYS = [
        'canOpenModule', 'canMovePanels', 'canCollapsePanels', 'canUseStateTools', 'canImportJson', 'canExportJson',
        'canViewViews', 'canSwitchView', 'canCreateView', 'canAddView', 'canEditView',
        'canViewLayers', 'canSelectLayers', 'canOpenImages', 'canAddImage',
        'canViewDesigns', 'canAddDesigns', 'canAddText', 'canAddRect', 'canAddShape',
        'canViewElements', 'canAddElements', 'canEditElements', 'canEditElementVariations',
        'canViewDrawingAreas', 'canCreateDrawingAreas', 'canEditDrawingAreas'
    ];

    function makeBootImportPermissions(base) {
        var permissions = Object.assign({}, sanitizeObject(base, {}));
        APD_BOOT_IMPORT_PERMISSION_KEYS.forEach(function (key) {
            permissions[key] = true;
        });

        // Boot import must be able to rebuild saved views/objects even when the
        // customer is not allowed to open modules or create/edit views manually.
        // Keep this relaxed copy only for the import window; strict moduleOpen is
        // re-applied immediately after the product/template state is restored.
        var bootModuleOpen = {};
        APD_CLIENT_MODULE_ALIAS_GROUPS.forEach(function (aliases) {
            aliases.forEach(function (alias) {
                bootModuleOpen[alias] = true;
            });
        });
        permissions.moduleOpen = bootModuleOpen;

        return permissions;
    }

    function createCanonicalStateScope() {
        return {
            meta: false,
            layout: false,
            modules: false,
            document: {
                views: false,
                drawingAreas: false,
                snapshots: false,
                objects: false,
                selection: false,
                viewportByView: false,
                scenes3d: false,
                asukaDocument: false
            },
            catalog: { elements: false, designs: false, colors: false, printingMethods: false },
            appearance: { defaults: false, theme: false },
            pricing: { basePrice: false, rules: false, totals: false },
            tools: { fixedSlots: false, magnifier: false, ruler: false, shapes: false, colorScope: false, selectionMenu: false },
            behavior: { listeners: false },
            configuration: { moduleConfig: false, integrations: false, fonts: false },
            permissions: false,
            history: false
        };
    }

    function buildCanonicalDocumentState(documentPayload, config) {
        if (documentPayload && documentPayload.format === 'asuka-state' && Number(documentPayload.schemaVersion) === 2) {
            return clonePlainObject(documentPayload);
        }

        config = config && typeof config === 'object' ? config : {};
        var normalized = normalizeDocumentHotStatePayload(documentPayload) || {};
        var views = getPayloadViews(normalized);
        var activeViewId = getPayloadActiveViewId(normalized, views[0] && views[0].id != null ? String(views[0].id) : '');
        var objectsByView = getPayloadObjectsByView(normalized);
        var snapshotsByView = getPayloadSnapshotsByView(documentPayload || {});
        var drawingAreasByView = extractDrawingAreasByViewPayload(normalized, activeViewId || '');
        var activeDrawingAreaId = normalized.drawingAreas && typeof normalized.drawingAreas === 'object'
            ? (normalized.drawingAreas.activeDrawingAreaId || null)
            : (normalized.selection && normalized.selection.activeDrawingAreaId ? normalized.selection.activeDrawingAreaId : null);
        var selection = normalized.selection && typeof normalized.selection === 'object'
            ? clonePlainObject(normalized.selection)
            : { activeObjectIds: [], activeDrawingAreaId: activeDrawingAreaId };
        var viewportByView = normalized.viewportByView && typeof normalized.viewportByView === 'object'
            ? clonePlainObject(normalized.viewportByView)
            : {};
        var source = documentPayload && typeof documentPayload === 'object' ? documentPayload : {};
        if (!payloadHasDirectViews(source) && source.document && typeof source.document === 'object') {
            source = source.document;
        }
        var neutralDocument = source.asukaDocument && typeof source.asukaDocument === 'object' && !Array.isArray(source.asukaDocument)
            ? source.asukaDocument
            : null;
        var scenes3d = source.scenes3d && typeof source.scenes3d === 'object'
            ? clonePlainObject(source.scenes3d)
            : (source.document3dScenesByView && typeof source.document3dScenesByView === 'object'
                ? clonePlainObject(source.document3dScenesByView)
                : (neutralDocument && neutralDocument.scenes3d && typeof neutralDocument.scenes3d === 'object'
                    ? clonePlainObject(neutralDocument.scenes3d)
                    : {}));
        var elements = Array.isArray(normalized.elements) && normalized.elements.length
            ? clonePlainObject(normalized.elements)
            : (Array.isArray(config.runtimeElements) && config.runtimeElements.length
                ? clonePlainObject(config.runtimeElements)
                : (config.catalog && Array.isArray(config.catalog.elements) ? clonePlainObject(config.catalog.elements) : []));

        var document = {
            views: { views: clonePlainObject(views), activeViewId: String(activeViewId || '') },
            objects: { byView: clonePlainObject(objectsByView || {}), source: 'document-store' },
            selection: selection
        };
        if (Object.keys(drawingAreasByView || {}).length) {
            var activeByView = {};
            if (activeViewId) {
                activeByView[String(activeViewId)] = activeDrawingAreaId;
            }
            document.drawingAreas = {
                zones: clonePlainObject(drawingAreasByView[String(activeViewId || '')] || []),
                activeDrawingAreaId: activeDrawingAreaId,
                byView: clonePlainObject(drawingAreasByView),
                activeByView: activeByView
            };
        }
        if (Object.keys(snapshotsByView || {}).length) {
            document.snapshots = { snapshotsByView: clonePlainObject(snapshotsByView) };
        }
        if (Object.keys(viewportByView || {}).length) {
            document.viewportByView = viewportByView;
        }
        if (Object.keys(scenes3d || {}).length) {
            document.scenes3d = scenes3d;
        }
        if (neutralDocument) {
            document.asukaDocument = clonePlainObject(neutralDocument);
        }
        if (elements.length) {
            document.elements = clonePlainObject(elements);
        }

        var scope = createCanonicalStateScope();
        scope.document.views = views.length > 0;
        scope.document.objects = true;
        scope.document.drawingAreas = !!document.drawingAreas;
        scope.document.snapshots = !!document.snapshots;
        scope.document.selection = true;
        scope.document.viewportByView = !!document.viewportByView;
        scope.document.scenes3d = !!document.scenes3d;
        scope.document.asukaDocument = !!document.asukaDocument;
        scope.catalog.elements = elements.length > 0;

        var state = {
            format: 'asuka-state',
            schemaVersion: 2,
            exportedAt: (new Date()).toISOString(),
            scope: scope,
            document: document
        };
        if (elements.length) {
            state.catalog = { elements: clonePlainObject(elements) };
        }
        return state;
    }

    function buildCanonicalFullState(fullState, documentPayload, config) {
        if (fullState && fullState.format === 'asuka-state' && Number(fullState.schemaVersion) === 2) {
            return clonePlainObject(fullState);
        }
        fullState = fullState && typeof fullState === 'object' ? fullState : {};
        var sourceDocument = documentPayload
            || fullState.document
            || fullState.initialDocument
            || fullState.documentState
            || fullState;
        var state = buildCanonicalDocumentState(sourceDocument, config);
        if (fullState.layout && typeof fullState.layout === 'object') {
            state.layout = clonePlainObject(fullState.layout);
            state.scope.layout = true;
        }
        return state;
    }

    function makeBootCreateConfig(createConfig, bootPayload) {
        var next = clonePlainObject(createConfig || {});
        if (!next || typeof next !== 'object') {
            return {};
        }

        // V1 accepts only canonical `asuka-state` schema 2 payloads through
        // `initialState`. Convert persisted pre-V1 product documents at this host
        // boundary so existing WordPress configurations remain usable.
        if (bootPayload && bootPayload.initialDocument && typeof bootPayload.initialDocument === 'object' && !next.initialState) {
            var canonicalDocumentState = buildCanonicalDocumentState(bootPayload.initialDocument, next);
            next.initialState = canonicalDocumentState;
            next.boot = {
                mode: 'initialState',
                state: clonePlainObject(canonicalDocumentState)
            };
        }
        if (!next.initialState && bootPayload && bootPayload.initialState && typeof bootPayload.initialState === 'object') {
            var canonicalFullState = buildCanonicalFullState(bootPayload.initialState, null, next);
            next.initialState = canonicalFullState;
            next.boot = {
                mode: 'initialState',
                state: clonePlainObject(canonicalFullState)
            };
        }
        delete next.initialDocument;

        if (isAdminEditorRuntimeConfig(next) || !bootPayloadHasViews(bootPayload)) {
            return next;
        }

        next.permissions = makeBootImportPermissions(next.permissions || {});
        return next;
    }

    function withBootImportPermissions(instance, strictPermissions, callback) {
        if (typeof callback !== 'function') {
            return null;
        }

        var relaxedPermissions = makeBootImportPermissions(strictPermissions || {});
        if (instance && Object.keys(relaxedPermissions).length) {
            apdApplyRuntimePermissionsToInstance(instance, relaxedPermissions);
        }

        try {
            return callback();
        } finally {
            if (instance && strictPermissions && Object.keys(strictPermissions).length) {
                window.setTimeout(function () {
                    apdApplyRuntimePermissionsToInstance(instance, strictPermissions);
                }, 0);
            }
        }
    }

    function makeInternalStateExportPermissions(base) {
        var permissions = Object.assign({}, sanitizeObject(base, {}));
        permissions.canOpenModule = true;
        permissions.canUseStateTools = true;
        permissions.canExportJson = true;

        var moduleOpen = apdNormalizeModuleOpenAliases(permissions.moduleOpen);
        apdSetModuleAliases(moduleOpen, ['state'], true);
        permissions.moduleOpen = moduleOpen;

        return permissions;
    }

    function withInternalStateExportPermissions(instance, strictPermissions, callback) {
        if (typeof callback !== 'function') {
            return null;
        }

        if (!instance) {
            return callback();
        }

        var restorePermissions = sanitizeObject(strictPermissions, {});
        if (!Object.keys(restorePermissions).length && instance.util && typeof instance.util.getPermissions === 'function') {
            try { restorePermissions = sanitizeObject(instance.util.getPermissions(), {}); } catch (error) {}
        }
        var exportPermissions = makeInternalStateExportPermissions(restorePermissions);
        var activeViewId = '';
        var activeViewPermissions = {};
        try {
            var runtimeState = instance.util && typeof instance.util.getState === 'function' ? instance.util.getState() : null;
            activeViewId = runtimeState && runtimeState.activeViewId != null ? String(runtimeState.activeViewId || '') : '';
            if (activeViewId && instance.util && typeof instance.util.getForActiveView === 'function') {
                activeViewPermissions = sanitizeObject(instance.util.getForActiveView(), {});
            }
        } catch (error) {}
        if (Object.keys(exportPermissions).length) {
            apdApplyRuntimePermissionsToInstance(instance, exportPermissions);
            try {
                if (activeViewId && instance.util && typeof instance.util.setForView === 'function') {
                    instance.util.setForView(activeViewId, exportPermissions);
                }
            } catch (error) {}
        }

        try {
            return callback();
        } finally {
            var restore = function () {
                try {
                    if (activeViewId && instance.util && typeof instance.util.clearForView === 'function') {
                        instance.util.clearForView(activeViewId);
                    }
                    if (activeViewId && Object.keys(activeViewPermissions).length && instance.util && typeof instance.util.setForView === 'function') {
                        instance.util.setForView(activeViewId, activeViewPermissions);
                    }
                } catch (error) {}
                if (Object.keys(restorePermissions).length) {
                    apdApplyRuntimePermissionsToInstance(instance, restorePermissions);
                }
            };
            restore();
            window.setTimeout(restore, 0);
        }
    }

    function ensureAdminDrawingAreasLayout(config) {
        if (!config || typeof config !== 'object') {
            return config;
        }
        var context = config.context && typeof config.context === 'object' ? config.context : {};
        var isAdminEditor = String(config.mode || '') === 'admin' || context.isAdmin || context.apdLayoutSource === 'admin_editor';
        if (!isAdminEditor) {
            return config;
        }

        config.layout = config.layout && typeof config.layout === 'object' && !Array.isArray(config.layout) ? config.layout : {};
        if (!config.layout.height) {
            config.layout.height = '820px';
        }
        config.layout = ensureRuntimeLayoutItem(config.layout, 'left', {
            id: 'drawingAreas',
            kind: 'drawingAreas',
            label: 'Drawing Areas',
            icon: 'drawing-areas',
            zone: 'left',
            type: 'floating'
        }, ['elements', 'marker']);

        return config;
    }


    function apdUploadDebug(tag, payload) {
        return;
    }

    function apdResolveUploadResponseUrl(payload, uploadConfig) {
        try {
            if (uploadConfig && typeof uploadConfig.mapResponseToUrl === 'function') {
                var mapped = uploadConfig.mapResponseToUrl(payload);
                if (typeof mapped === 'string' && mapped) return mapped;
            }
        } catch (error) {}
        if (typeof payload === 'string' && payload) return payload;
        if (payload && typeof payload === 'object') {
            var directKeys = ['url', 'src', 'value', 'fileUrl', 'downloadUrl'];
            for (var i = 0; i < directKeys.length; i += 1) {
                var value = payload[directKeys[i]];
                if (typeof value === 'string' && value) return value;
            }
            var nested = [payload.data, payload.result];
            for (var j = 0; j < nested.length; j += 1) {
                var item = nested[j];
                if (item && typeof item === 'object') {
                    for (var k = 0; k < directKeys.length; k += 1) {
                        var nestedValue = item[directKeys[k]];
                        if (typeof nestedValue === 'string' && nestedValue) return nestedValue;
                    }
                }
            }
        }
        return null;
    }

    function apdParseUploadResponse(response) {
        var contentType = response && response.headers && typeof response.headers.get === 'function'
            ? String(response.headers.get('content-type') || '')
            : '';
        if (contentType.indexOf('application/json') !== -1) {
            return response.json();
        }
        return response.text().then(function (text) {
            try { return JSON.parse(text); } catch (error) { return text; }
        });
    }

    function apdUploadErrorMessage(payload, status) {
        function visit(value, depth) {
            if (depth > 5 || value == null) return '';
            if (typeof value === 'string') {
                var message = value.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
                return message && message.length <= 500 ? message : '';
            }
            if (typeof value !== 'object') return '';
            var keys = ['message', 'detail', 'error_description', 'error', 'data', 'result'];
            for (var index = 0; index < keys.length; index += 1) {
                var nested = visit(value[keys[index]], depth + 1);
                if (nested) return nested;
            }
            return '';
        }
        return visit(payload, 0) || ('Upload failed with status ' + status + '.');
    }

    function apdCloneUploadHeaders(headers) {
        var next = Object.assign({}, headers || {});
        Object.keys(next).forEach(function (key) {
            if (String(key).toLowerCase() === 'content-type') {
                delete next[key];
            }
        });
        return next;
    }

    function apdCreateWordPressUploadHandler(uploadConfig) {
        return function (file, context) {
            if (!file) {
                return Promise.reject(new Error('No file provided for upload.'));
            }
            var endpoint = String(uploadConfig.endpoint || '').trim();
            if (!endpoint) {
                return Promise.reject(new Error('Upload endpoint is not configured.'));
            }
            var body = new FormData();
            body.append(uploadConfig.fieldName || 'file', file, file.name || 'upload');
            if (uploadConfig.source) {
                body.append('apd_source', String(uploadConfig.source));
            }
            if (context && typeof context === 'object') {
                try { body.append('apd_context', JSON.stringify(context)); } catch (error) {}
                if (context.source) body.append('asuka_source', String(context.source));
                if (context.mode) body.append('asuka_mode', String(context.mode));
            }
            return fetch(endpoint, {
                method: uploadConfig.method || 'POST',
                body: body,
                headers: apdCloneUploadHeaders(uploadConfig.headers || {}),
                credentials: uploadConfig.credentials || 'same-origin'
            }).then(function (response) {
                return apdParseUploadResponse(response).then(function (payload) {
                    if (!response.ok) {
                        throw new Error(apdUploadErrorMessage(payload, response.status));
                    }
                    return payload;
                });
            }).then(function (payload) {
                var url = apdResolveUploadResponseUrl(payload, uploadConfig);
                if (!url) {
                    throw new Error('The upload response did not contain a usable URL.');
                }
                return url;
            });
        };
    }


    function apdResolveMediaAttachmentUrl(data) {
        if (!data || typeof data !== 'object') return '';
        var candidates = [
            data.url,
            data.source_url,
            data.fileUrl,
            data.downloadUrl,
            data.src,
            data.value,
            data.sizes && data.sizes.full && data.sizes.full.url,
            data.sizes && data.sizes.large && data.sizes.large.url,
            data.sizes && data.sizes.medium && data.sizes.medium.url,
            data.media_details && data.media_details.sizes && data.media_details.sizes.full && data.media_details.sizes.full.source_url,
            data.media_details && data.media_details.sizes && data.media_details.sizes.large && data.media_details.sizes.large.source_url,
            data.media_details && data.media_details.sizes && data.media_details.sizes.medium && data.media_details.sizes.medium.source_url
        ];
        for (var i = 0; i < candidates.length; i += 1) {
            var value = candidates[i];
            if (typeof value === 'string' && value.trim()) return value.trim();
        }
        return '';
    }

    function apdNormalizeWordPressMediaItem(data) {
        data = data && typeof data === 'object' ? data : {};
        var url = apdResolveMediaAttachmentUrl(data);
        if (!url) return null;
        var id = data.id || data.attachmentId || undefined;
        return {
            url: url,
            name: data.filename || data.name || data.title || (url.split('/').pop() || 'wordpress-media'),
            filename: data.filename || data.name || '',
            id: id,
            source: 'wordpress-media',
            attachmentId: id,
            metadata: data
        };
    }

    function apdDedupeUploadSelectionItems(items) {
        var seen = {};
        return (Array.isArray(items) ? items : []).filter(function (item) {
            if (!item) return false;
            var id = item.attachmentId || item.id || (item.metadata && item.metadata.id) || '';
            var url = item.url || item.src || item.value || item.fileUrl || item.downloadUrl || '';
            var key = id ? ('id:' + String(id)) : (url ? ('url:' + String(url)) : '');
            if (!key) return true;
            if (seen[key]) return false;
            seen[key] = true;
            return true;
        });
    }

    function apdCollectWordPressMediaSelection(selection) {
        var attachments = [];
        if (selection && typeof selection.each === 'function') {
            selection.each(function (attachment) { attachments.push(attachment); });
        } else if (selection && typeof selection.map === 'function') {
            attachments = selection.map(function (attachment) { return attachment; });
        } else {
            var first = selection && typeof selection.first === 'function' ? selection.first() : null;
            if (first) attachments.push(first);
        }
        return apdDedupeUploadSelectionItems(attachments.map(function (attachment) {
            var data = attachment && typeof attachment.toJSON === 'function' ? attachment.toJSON() : (attachment || null);
            return apdNormalizeWordPressMediaItem(data);
        }).filter(Boolean));
    }

    function apdOpenAdminMediaPicker(options) {
        options = sanitizeObject(options, {});
        return new Promise(function (resolve, reject) {
            if (!window.wp || !window.wp.media) {
                reject(new Error('WordPress media uploader is not available.'));
                return;
            }
            var settled = false;
            var selected = false;
            var done = function (items) {
                if (settled) return;
                settled = true;
                items = apdDedupeUploadSelectionItems(Array.isArray(items) ? items : []);
                apdUploadDebug('wp.media normalized items', items);
                resolve(items);
            };
            var fail = function (error) {
                if (settled) return;
                settled = true;
                reject(error);
            };
            var labels = ((window.APDAdminConfig || {}).labels || {});
            var accept = String(options.accept || '').toLowerCase();
            var imageOnly = !accept || accept.indexOf('image') !== -1 || accept.indexOf('.png') !== -1 || accept.indexOf('.jpg') !== -1 || accept.indexOf('.jpeg') !== -1 || accept.indexOf('.gif') !== -1 || accept.indexOf('.webp') !== -1 || accept.indexOf('.svg') !== -1 || accept.indexOf('.avif') !== -1;
            var frame = window.wp.media({
                title: imageOnly ? (labels.mediaFrameTitleImage || 'Choose an image') : (labels.mediaFrameTitleFile || 'Choose a file'),
                button: { text: labels.mediaFrameButton || 'Use this file' },
                multiple: !!options.multiple,
                library: imageOnly ? { type: 'image' } : {}
            });
            frame.on('select', function () {
                selected = true;
                try {
                    var selection = frame.state().get('selection');
                    apdUploadDebug('wp.media select raw selection', selection);
                    done(apdCollectWordPressMediaSelection(selection));
                } catch (error) {
                    fail(error);
                }
            });
            frame.on('close', function () {
                window.setTimeout(function () {
                    apdUploadDebug('wp.media close', { settled: settled, selected: selected });
                    if (!settled && !selected) {
                        done([]);
                    }
                }, 50);
            });
            frame.open();
        });
    }

    if (typeof window.openAdminMediaPicker !== 'function') {
        window.openAdminMediaPicker = apdOpenAdminMediaPicker;
    }

    function apdCreateAdminUploadSelectHandler() {
        var pendingPicker = null;
        return function (context) {
            context = sanitizeObject(context, {});
            apdUploadDebug('selectHandler called', context);
            if (pendingPicker) {
                return pendingPicker;
            }
            var picker = typeof window.openAdminMediaPicker === 'function' ? window.openAdminMediaPicker : apdOpenAdminMediaPicker;
            pendingPicker = Promise.resolve(picker({
                multiple: !!context.multiple,
                accept: context.accept || 'image/*',
                source: context.source || context.uploadContext || context.kind || 'admin',
                uploadContext: context.uploadContext || context.kind || context.source || 'admin'
            })).then(function (items) {
                apdUploadDebug('wp.media returned', items);
                if (!Array.isArray(items)) items = items ? [items] : [];
                var normalized = apdDedupeUploadSelectionItems(items.map(function (item) {
                    if (typeof item === 'string') {
                        return { url: item, name: item.split('/').pop() || 'wordpress-media', source: 'wordpress-media' };
                    }
                    item = item && typeof item === 'object' ? item : {};
                    var metadata = sanitizeObject(item.metadata, sanitizeObject(item.data, item));
                    var url = item.url || item.src || item.value || item.fileUrl || item.downloadUrl || apdResolveMediaAttachmentUrl(metadata);
                    if (!url) return null;
                    var id = item.attachmentId || item.id || metadata.attachmentId || metadata.id || undefined;
                    return {
                        url: url,
                        name: item.name || item.filename || metadata.filename || metadata.name || metadata.title || (String(url).split('/').pop() || 'wordpress-media'),
                        filename: item.filename || metadata.filename || metadata.name || '',
                        id: id,
                        source: item.source || 'wordpress-media',
                        attachmentId: id,
                        metadata: metadata
                    };
                }).filter(Boolean));
                apdUploadDebug('selectHandler returns', normalized);
                return normalized;
            }).finally(function () {
                pendingPicker = null;
            });
            return pendingPicker;
        };
    }

    function apdEnsureRuntimeUploadConfig(config, defaults) {
        if (!config || typeof config !== 'object') {
            return config;
        }
        defaults = sanitizeObject(defaults, {});
        var topUpload = sanitizeObject(config.upload, {});
        var moduleConfig = sanitizeObject(config.moduleConfig, {});
        var nestedUpload = sanitizeObject(moduleConfig.upload, {});
        var uploadConfig = Object.assign({}, defaults, nestedUpload, topUpload);
        uploadConfig.headers = Object.assign({}, sanitizeObject(defaults.headers, {}), sanitizeObject(nestedUpload.headers, {}), sanitizeObject(topUpload.headers, {}));
        if (!String(uploadConfig.endpoint || '').trim() && defaults.endpoint) {
            uploadConfig.endpoint = defaults.endpoint;
        }
        if (defaults.source && !uploadConfig.source) {
            uploadConfig.source = defaults.source;
        }
        if (defaults.credentials && !uploadConfig.credentials) {
            uploadConfig.credentials = defaults.credentials;
        }
        if (!Object.keys(uploadConfig).length) {
            return config;
        }
        if (!uploadConfig.fieldName) {
            uploadConfig.fieldName = 'file';
        }
        if ((defaults.endpoint && uploadConfig.strategy !== 'remote') || uploadConfig.endpoint || uploadConfig.strategy === 'remote') {
            uploadConfig.strategy = 'remote';
            uploadConfig.method = uploadConfig.method || 'POST';
        }
        if (uploadConfig.endpoint && typeof uploadConfig.handler !== 'function') {
            uploadConfig.handler = apdCreateWordPressUploadHandler(uploadConfig);
        }
        if ((uploadConfig.source === 'admin' || defaults.source === 'admin') && typeof uploadConfig.selectHandler !== 'function') {
            uploadConfig.selectHandler = apdCreateAdminUploadSelectHandler();
        }
        delete uploadConfig.picker;
        moduleConfig.upload = uploadConfig;
        config.moduleConfig = moduleConfig;
        config.upload = uploadConfig;
        return config;
    }


    function apdGetRuntimeStore(instance) {
        if (!instance || typeof instance !== 'object') {
            return null;
        }
        if (instance.store && typeof instance.store.getState === 'function') {
            return instance.store;
        }
        if (instance.__store && typeof instance.__store.getState === 'function') {
            return instance.__store;
        }
        if (instance.runtime && instance.runtime.store && typeof instance.runtime.store.getState === 'function') {
            return instance.runtime.store;
        }
        return null;
    }

    function apdMergeUploadRuntimeFunctions(target, source) {
        target = sanitizeObject(target, {});
        source = sanitizeObject(source, {});
        var next = Object.assign({}, target, source);
        if (typeof source.handler === 'function') {
            next.handler = source.handler;
        }
        if (typeof source.selectHandler === 'function') {
            next.selectHandler = source.selectHandler;
        }
        if (typeof source.mapResponseToUrl === 'function') {
            next.mapResponseToUrl = source.mapResponseToUrl;
        }
        delete next.picker;
        return next;
    }

    function apdApplyRuntimeUploadConfigToInstance(instance, uploadConfig) {
        uploadConfig = sanitizeObject(uploadConfig, {});
        if (!Object.keys(uploadConfig).length) {
            return false;
        }
        var store = apdGetRuntimeStore(instance);
        if (!store || typeof store.getState !== 'function') {
            return false;
        }
        try {
            var state = store.getState() || {};
            var currentModuleConfig = sanitizeObject(state.moduleConfig, {});
            var nextUpload = apdMergeUploadRuntimeFunctions(sanitizeObject(currentModuleConfig.upload, {}), uploadConfig);
            var nextModuleConfig = Object.assign({}, currentModuleConfig, { upload: nextUpload });
            if (state && typeof state.setModuleConfig === 'function') {
                state.setModuleConfig({ upload: nextUpload });
            } else if (typeof store.setState === 'function') {
                store.setState({ moduleConfig: nextModuleConfig });
            } else {
                return false;
            }
            return true;
        } catch (error) {
            return false;
        }
    }


    function apdIsReusableElementDefinition(item) {
        if (!item || typeof item !== 'object' || Array.isArray(item)) {
            return false;
        }
        if (Array.isArray(item.variations) || Array.isArray(item.children)) {
            return true;
        }
        if (item.familyId || item._asukaElementFamilyId || item.asukaElementId || item._asukaElementId) {
            return true;
        }
        var itemType = String(item.itemType || item.elementType || item.kind || '').toLowerCase();
        return itemType === 'element' || itemType === 'elements' || itemType === 'reusable-element';
    }

    function apdCountElementVariations(item) {
        if (!item || typeof item !== 'object') {
            return 0;
        }
        var total = 0;
        var variations = Array.isArray(item.variations) ? item.variations : [];
        total += variations.length;
        variations.forEach(function (variation) {
            total += apdCountElementVariations(variation);
        });
        return total;
    }

    function apdElementDefinitionKey(item) {
        if (!item || typeof item !== 'object') {
            return '';
        }
        var keys = [item.id, item.familyId, item.name, item.label, item._asukaElementId, item.asukaElementId];
        for (var i = 0; i < keys.length; i += 1) {
            var value = String(keys[i] == null ? '' : keys[i]).trim();
            if (value) {
                return value.toLowerCase();
            }
        }
        return '';
    }

    function apdPreferElementDefinition(current, incoming) {
        if (!current) {
            return incoming;
        }
        if (!incoming) {
            return current;
        }
        var currentVariationCount = apdCountElementVariations(current);
        var incomingVariationCount = apdCountElementVariations(incoming);
        if (incomingVariationCount > currentVariationCount) {
            return Object.assign({}, current, incoming);
        }
        if (currentVariationCount > incomingVariationCount) {
            return Object.assign({}, incoming, current);
        }
        var currentChildren = Array.isArray(current.children) ? current.children.length : 0;
        var incomingChildren = Array.isArray(incoming.children) ? incoming.children.length : 0;
        if (incomingChildren > currentChildren) {
            return Object.assign({}, current, incoming);
        }
        return Object.assign({}, incoming, current);
    }

    function apdMergeElementDefinitionGroups(groups) {
        var keyed = {};
        var loose = [];
        (groups || []).forEach(function (group) {
            (Array.isArray(group) ? group : []).forEach(function (item) {
                if (!item || typeof item !== 'object' || Array.isArray(item)) {
                    return;
                }
                var key = apdElementDefinitionKey(item);
                if (!key) {
                    loose.push(clonePlainObject(item));
                    return;
                }
                keyed[key] = apdPreferElementDefinition(keyed[key], clonePlainObject(item));
            });
        });
        return loose.concat(Object.keys(keyed).map(function (key) { return keyed[key]; }));
    }


    function apdGetRuntimeElementDefinitions(instance) {
        var store = apdGetRuntimeStore(instance);
        if (!store || typeof store.getState !== 'function') {
            return [];
        }
        try {
            var state = store.getState() || {};
            return (Array.isArray(state.elements) ? state.elements : []).filter(function (item) {
                return item && typeof item === 'object' && !Array.isArray(item) && apdIsReusableElementDefinition(item);
            }).map(function (item) { return clonePlainObject(item); });
        } catch (error) {}
        return [];
    }

    function apdRememberShellRuntimeElements(shell, groups) {
        if (!shell || !groups) {
            return [];
        }
        var current = Array.isArray(shell.__apdRuntimeElementDefinitions) ? shell.__apdRuntimeElementDefinitions : [];
        var next = apdMergeElementDefinitionGroups([current].concat(Array.isArray(groups) && groups.length && Array.isArray(groups[0]) ? groups : [groups]));
        shell.__apdRuntimeElementDefinitions = next;
        return next;
    }

    function apdApplyPreservedRuntimeElements(shell, instance, extraGroups) {
        var groups = [];
        if (shell && Array.isArray(shell.__apdRuntimeElementDefinitions)) {
            groups.push(shell.__apdRuntimeElementDefinitions);
        }
        groups.push(apdGetRuntimeElementDefinitions(instance));
        if (Array.isArray(extraGroups)) {
            if (extraGroups.length && Array.isArray(extraGroups[0])) {
                groups = groups.concat(extraGroups);
            } else {
                groups.push(extraGroups);
            }
        }
        var elements = apdMergeElementDefinitionGroups(groups);
        if (shell) {
            shell.__apdRuntimeElementDefinitions = elements;
        }
        if (!elements.length) {
            return false;
        }
        return apdApplyRuntimeCatalogAndModuleConfigToInstance(instance, { elements: elements });
    }


    function apdPushElementAlias(list, value) {
        var alias = String(value == null ? '' : value).trim();
        if (alias && list.indexOf(alias) === -1) {
            list.push(alias);
        }
    }

    function apdGetElementDefinitionAliases(item) {
        var aliases = [];
        if (!item || typeof item !== 'object' || Array.isArray(item)) {
            return aliases;
        }
        [
            item.id,
            item.name,
            item.label,
            item.familyId,
            item._asukaElementId,
            item.asukaElementId,
            item._asukaElementFamilyId,
            item.asukaElementFamilyId
        ].forEach(function (value) {
            apdPushElementAlias(aliases, value);
        });
        return aliases;
    }

    function apdGetElementObjectAliases(object) {
        var aliases = [];
        if (!object || typeof object !== 'object' || Array.isArray(object)) {
            return aliases;
        }
        [
            object._asukaElementId,
            object.asukaElementId,
            object._asukaElementName,
            object.asukaElementName,
            object.elementName,
            object._asukaElementFamilyId,
            object.asukaElementFamilyId,
            object.familyId,
            object.name,
            object.label
        ].forEach(function (value) {
            apdPushElementAlias(aliases, value);
        });
        return aliases;
    }

    function apdBuildElementDefinitionLookup(elements) {
        var map = {};
        var visit = function (items, root) {
            (Array.isArray(items) ? items : []).forEach(function (item) {
                if (!item || typeof item !== 'object' || Array.isArray(item)) {
                    return;
                }
                // The Variations module needs the reusable Element root. Some
                // serialized frontend objects only expose a currently active
                // variation id/name, so aliases found on child variation nodes must
                // still resolve to the root element definition that owns the full
                // variation tree.
                var owner = root || item;
                var target = owner && apdCountElementVariations(owner) > 0 ? owner : item;
                apdGetElementDefinitionAliases(item).forEach(function (alias) {
                    var lowerAlias = alias.toLowerCase();
                    map[alias] = map[alias] ? apdPreferElementDefinition(map[alias], target) : target;
                    map[lowerAlias] = map[lowerAlias] ? apdPreferElementDefinition(map[lowerAlias], target) : target;
                });
                if (Array.isArray(item.children)) {
                    visit(item.children, owner);
                }
                if (Array.isArray(item.variations)) {
                    visit(item.variations, owner);
                }
            });
        };
        visit(elements, null);
        return map;
    }

    function apdFindElementDefinitionByAliases(elements, aliases) {
        var lookup = apdBuildElementDefinitionLookup(elements);
        for (var i = 0; i < aliases.length; i += 1) {
            var alias = String(aliases[i] == null ? '' : aliases[i]).trim();
            if (!alias) {
                continue;
            }
            if (lookup[alias]) {
                return lookup[alias];
            }
            if (lookup[alias.toLowerCase()]) {
                return lookup[alias.toLowerCase()];
            }
        }
        return null;
    }


    function apdNormalizeElementAliasForMatch(value) {
        var alias = String(value == null ? '' : value).trim().toLowerCase();
        if (!alias) {
            return '';
        }
        try {
            alias = alias.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
        } catch (error) {}
        return alias.replace(/[^a-z0-9]+/g, '');
    }

    function apdFlattenElementDefinitions(elements, bucket, seen) {
        bucket = bucket || [];
        seen = seen || [];
        (Array.isArray(elements) ? elements : []).forEach(function (item) {
            if (!item || typeof item !== 'object' || Array.isArray(item) || seen.indexOf(item) !== -1) {
                return;
            }
            seen.push(item);
            bucket.push(item);
            if (Array.isArray(item.children)) {
                apdFlattenElementDefinitions(item.children, bucket, seen);
            }
        });
        return bucket;
    }

    function apdFindElementDefinitionByFuzzyAliases(elements, aliases) {
        aliases = (Array.isArray(aliases) ? aliases : [aliases]).map(function (value) {
            return String(value == null ? '' : value).trim();
        }).filter(Boolean);
        var direct = apdFindElementDefinitionByAliases(elements, aliases);
        if (direct) {
            return direct;
        }

        var normalizedAliases = aliases.map(apdNormalizeElementAliasForMatch).filter(function (value) {
            return value.length >= 3;
        });
        if (!normalizedAliases.length) {
            return null;
        }

        var collectDeepAliases = function (item, bucket, seen) {
            bucket = bucket || [];
            seen = seen || [];
            if (!item || typeof item !== 'object' || seen.indexOf(item) !== -1) {
                return bucket;
            }
            seen.push(item);
            apdGetElementDefinitionAliases(item).forEach(function (alias) {
                apdPushElementAlias(bucket, alias);
            });
            [item.children, item.variations].forEach(function (children) {
                (Array.isArray(children) ? children : []).forEach(function (child) {
                    collectDeepAliases(child, bucket, seen);
                });
            });
            return bucket;
        };
        var best = null;
        var bestScore = 0;
        (Array.isArray(elements) ? elements : []).forEach(function (item) {
            if (!item || typeof item !== 'object') {
                return;
            }
            var itemAliases = collectDeepAliases(item, [], []);
            var normalizedItemAliases = itemAliases.map(apdNormalizeElementAliasForMatch).filter(function (value) {
                return value.length >= 3;
            });
            var score = 0;
            normalizedAliases.forEach(function (candidate) {
                normalizedItemAliases.forEach(function (itemAlias) {
                    if (!candidate || !itemAlias) {
                        return;
                    }
                    if (candidate === itemAlias) {
                        score = Math.max(score, 600);
                        return;
                    }
                    if (candidate.length >= 4 && itemAlias.indexOf(candidate) !== -1) {
                        score = Math.max(score, 260 + Math.min(candidate.length, 80));
                        return;
                    }
                    if (itemAlias.length >= 4 && candidate.indexOf(itemAlias) !== -1) {
                        score = Math.max(score, 220 + Math.min(itemAlias.length, 80));
                    }
                });
            });
            if (score > 0) {
                score += Math.min(apdCountElementVariations(item), 120);
                if (Array.isArray(item.children)) {
                    score += Math.min(item.children.length, 20);
                }
            }
            if (score > bestScore) {
                bestScore = score;
                best = item;
            }
        });
        return bestScore > 0 ? best : null;
    }

    function apdGetRuntimeObjectIdentity(object) {
        if (!object || typeof object !== 'object') {
            return [];
        }
        var ids = [];
        [
            object._asukaObjectId,
            object.id,
            object.uuid,
            object.name,
            object._asukaElementObjectId,
            object.asukaElementObjectId
        ].forEach(function (value) {
            apdPushElementAlias(ids, value);
        });
        return ids;
    }

    function apdCollectElementObjectAliases(object, aliases, seen) {
        aliases = aliases || [];
        seen = seen || [];
        if (!object || typeof object !== 'object' || seen.indexOf(object) !== -1) {
            return aliases;
        }
        seen.push(object);
        apdGetElementObjectAliases(object).forEach(function (value) {
            apdPushElementAlias(aliases, value);
        });
        [object.objects, object._objects].forEach(function (children) {
            (Array.isArray(children) ? children : []).forEach(function (child) {
                apdCollectElementObjectAliases(child, aliases, seen);
            });
        });
        return aliases;
    }

    function apdFindObjectByIdentityInList(objects, wantedIds, seen) {
        wantedIds = (Array.isArray(wantedIds) ? wantedIds : []).map(function (value) {
            return String(value == null ? '' : value).trim();
        }).filter(Boolean);
        if (!wantedIds.length) {
            return null;
        }
        seen = seen || [];
        for (var i = 0; i < (Array.isArray(objects) ? objects : []).length; i += 1) {
            var object = objects[i];
            if (!object || typeof object !== 'object' || seen.indexOf(object) !== -1) {
                continue;
            }
            seen.push(object);
            var ids = apdGetRuntimeObjectIdentity(object);
            var matched = ids.some(function (id) {
                return wantedIds.indexOf(String(id == null ? '' : id).trim()) !== -1;
            });
            if (matched) {
                return object;
            }
            var child = apdFindObjectByIdentityInList([].concat(Array.isArray(object.objects) ? object.objects : [], Array.isArray(object._objects) ? object._objects : []), wantedIds, seen);
            if (child) {
                return child;
            }
        }
        return null;
    }

    function apdCollectRuntimeElementObjectAliases(instance, state, picker) {
        var aliases = [];
        picker = picker && typeof picker === 'object' ? picker : {};
        [
            picker.elementId,
            picker.elementName,
            picker.elementFamilyId,
            picker.familyId,
            picker.name,
            picker.label
        ].forEach(function (value) {
            apdPushElementAlias(aliases, value);
        });

        var wantedIds = [];
        [picker.objectId, picker.object_id, picker.id, picker.uuid].forEach(function (value) {
            apdPushElementAlias(wantedIds, value);
        });
        if (!wantedIds.length) {
            return aliases;
        }

        try {
            var byView = state && state.documentObjectsByView && typeof state.documentObjectsByView === 'object' ? state.documentObjectsByView : {};
            Object.keys(byView).some(function (viewId) {
                var object = apdFindObjectByIdentityInList(byView[viewId], wantedIds, []);
                if (object) {
                    apdCollectElementObjectAliases(object, aliases, []);
                    return true;
                }
                return false;
            });
        } catch (error) {}

        try {
            var oldByView = state && state.objectsByView && typeof state.objectsByView === 'object' ? state.objectsByView : {};
            Object.keys(oldByView).some(function (viewId) {
                var object = apdFindObjectByIdentityInList(oldByView[viewId], wantedIds, []);
                if (object) {
                    apdCollectElementObjectAliases(object, aliases, []);
                    return true;
                }
                return false;
            });
        } catch (error) {}

        try {
            var liveObject = apdFindObjectByIdentityInList(apdDebugGetObjects(instance), wantedIds, []);
            if (liveObject) {
                apdCollectElementObjectAliases(liveObject, aliases, []);
            }
        } catch (error) {}

        return aliases;
    }

    function apdFindSingleElementWithVariations(elements) {
        var roots = (Array.isArray(elements) ? elements : []).filter(function (item) {
            return item && typeof item === 'object' && apdCountElementVariations(item) > 0;
        });
        return roots.length === 1 ? roots[0] : null;
    }

    function apdPatchRuntimeElementFinder(instance) {
        var store = apdGetRuntimeStore(instance);
        if (!store || typeof store.getState !== 'function' || typeof store.setState !== 'function') {
            return false;
        }
        try {
            var state = store.getState() || {};
            if (state.__apdElementFinderFamilyAliasPatch) {
                return false;
            }
            var originalFindElement = typeof state.findElement === 'function' ? state.findElement : null;
            var patchedFindElement = function (identifier) {
                var current = store.getState ? (store.getState() || {}) : {};
                var elements = Array.isArray(current.elements) ? current.elements : [];
                var rawCandidates = Array.isArray(identifier) ? identifier : [identifier];
                var picker = current.elementVariationPicker && typeof current.elementVariationPicker === 'object' ? current.elementVariationPicker : {};
                var runtimeObjectAliases = apdCollectRuntimeElementObjectAliases(instance, current, picker);
                var candidates = [];
                rawCandidates.concat(runtimeObjectAliases).forEach(function (value) {
                    apdPushElementAlias(candidates, value);
                });
                var direct = apdFindElementDefinitionByFuzzyAliases(elements, candidates);
                logApdVariationDebug('runtimeBridge:elements:findElement:call', {
                    rawCandidates: rawCandidates,
                    picker: picker,
                    runtimeObjectAliases: runtimeObjectAliases,
                    candidates: candidates,
                    elements: summarizeElementDefinitions(elements, 10),
                    direct: summarizeElementDefinition(direct)
                });
                if (direct) {
                    return direct;
                }
                if (originalFindElement) {
                    for (var i = 0; i < candidates.length; i += 1) {
                        try {
                            var found = originalFindElement.call(current, candidates[i]);
                            if (found) {
                                logApdVariationDebug('runtimeBridge:elements:findElement:original-found', {
                                    candidate: candidates[i],
                                    found: summarizeElementDefinition(found)
                                });
                                return found;
                            }
                        } catch (error) {}
                    }
                }
                var single = apdFindSingleElementWithVariations(elements);
                if (single) {
                    logApdVariationDebug('runtimeBridge:elements:findElement:single-variation-fallback', {
                        candidates: candidates,
                        found: summarizeElementDefinition(single)
                    });
                    return single;
                }
                logApdVariationDebug('runtimeBridge:elements:findElement:not-found', {
                    rawCandidates: rawCandidates,
                    picker: picker,
                    runtimeObjectAliases: runtimeObjectAliases,
                    candidates: candidates,
                    elements: summarizeElementDefinitions(elements, 10)
                });
                return null;
            };
            store.setState({
                findElement: patchedFindElement,
                __apdElementFinderFamilyAliasPatch: true
            });
            return true;
        } catch (error) {
            return false;
        }
    }

    function apdNormalizeElementInstanceObject(object, elements) {
        if (!object || typeof object !== 'object') {
            return false;
        }
        var changed = false;
        var aliases = apdGetElementObjectAliases(object);
        var definition = apdFindElementDefinitionByFuzzyAliases(elements, aliases);
        if (definition && typeof definition === 'object') {
            var nextId = String(definition.id || definition.familyId || definition.name || '').trim();
            var nextName = String(definition.name || definition.label || definition.id || '').trim();
            var nextFamilyId = String(definition.familyId || definition._asukaElementFamilyId || definition.asukaElementFamilyId || definition.id || '').trim();
            if (nextId && String(object._asukaElementId || '') !== nextId) {
                object._asukaElementId = nextId;
                object.asukaElementId = nextId;
                changed = true;
            }
            if (nextName && String(object._asukaElementName || '') !== nextName) {
                object._asukaElementName = nextName;
                object.asukaElementName = nextName;
                changed = true;
            }
            if (nextFamilyId && String(object._asukaElementFamilyId || '') !== nextFamilyId) {
                object._asukaElementFamilyId = nextFamilyId;
                object.asukaElementFamilyId = nextFamilyId;
                changed = true;
            }
            if (object._asukaElementIsInstance !== true) {
                object._asukaElementIsInstance = true;
                changed = true;
            }
            if (!object.itemGroup) {
                object.itemGroup = 'Elements';
                changed = true;
            }
            if (changed) {
                logApdVariationDebug('runtimeBridge:elements:normalizeObject:changed', {
                    object: summarizeElementObject(object),
                    aliases: aliases,
                    definition: summarizeElementDefinition(definition)
                });
            }
        }

        var children = [];
        if (Array.isArray(object.objects)) {
            children = children.concat(object.objects);
        }
        if (Array.isArray(object._objects)) {
            children = children.concat(object._objects);
        }
        children.forEach(function (child) {
            if (apdNormalizeElementInstanceObject(child, elements)) {
                changed = true;
            }
        });
        return changed;
    }

    function apdNormalizeElementInstanceReferences(instance, elements) {
        elements = Array.isArray(elements) ? elements : [];
        if (!elements.length) {
            return false;
        }
        var changed = false;
        logApdVariationDebug('runtimeBridge:elements:normalizeReferences:start', {
            elements: summarizeElementDefinitions(elements, 10),
            runtimeBefore: summarizeRuntimeElementState(instance)
        });
        var store = apdGetRuntimeStore(instance);
        try {
            if (store && typeof store.getState === 'function' && typeof store.setState === 'function') {
                var state = store.getState() || {};
                var patch = {};
                ['documentObjectsByView', 'objectsByView'].forEach(function (key) {
                    var byView = state[key];
                    if (!byView || typeof byView !== 'object' || Array.isArray(byView)) {
                        return;
                    }
                    var nextByView = {};
                    var localChanged = false;
                    Object.keys(byView).forEach(function (viewId) {
                        var objects = Array.isArray(byView[viewId]) ? byView[viewId].map(function (object) { return clonePlainObject(object); }) : byView[viewId];
                        if (Array.isArray(objects)) {
                            objects.forEach(function (object) {
                                if (apdNormalizeElementInstanceObject(object, elements)) {
                                    localChanged = true;
                                }
                            });
                        }
                        nextByView[viewId] = objects;
                    });
                    if (localChanged) {
                        patch[key] = nextByView;
                        changed = true;
                    }
                });
                if (Object.keys(patch).length) {
                    store.setState(patch);
                }
            }
        } catch (error) {}

        logApdVariationDebug('runtimeBridge:elements:normalizeReferences:end', {
            changed: changed,
            runtimeAfter: summarizeRuntimeElementState(instance)
        });
        return changed;
    }

    function apdCollectElementDefinitionsFromPayload(payload, seen) {
        if (!payload || typeof payload !== 'object') {
            return [];
        }
        seen = seen || [];
        if (seen.indexOf(payload) !== -1) {
            return [];
        }
        seen.push(payload);

        var found = [];
        ['elements', 'runtimeElements'].forEach(function (bucketKey) {
            if (Array.isArray(payload[bucketKey])) {
                found = found.concat(payload[bucketKey].filter(function (item) {
                    return item && typeof item === 'object' && !Array.isArray(item);
                }));
            }
        });
        if (payload.catalog && typeof payload.catalog === 'object' && Array.isArray(payload.catalog.elements)) {
            found = found.concat(payload.catalog.elements.filter(function (item) {
                return apdIsReusableElementDefinition(item);
            }));
        }

        [
            'initialState', 'initialDocument', 'documentState', 'document', 'state'
        ].forEach(function (key) {
            if (payload[key] && typeof payload[key] === 'object') {
                found = found.concat(apdCollectElementDefinitionsFromPayload(payload[key], seen));
            }
        });
        if (payload.legacy && typeof payload.legacy === 'object') {
            found = found.concat(apdCollectElementDefinitionsFromPayload(payload.legacy, seen));
        }

        return found;
    }

    function apdBuildSafeCatalogForFullStateImport(catalog, payload) {
        catalog = sanitizeObject(catalog, {});
        var next = clonePlainObject(catalog) || {};
        if (!Object.prototype.hasOwnProperty.call(next, 'elements')) {
            return next;
        }

        var catalogElements = Array.isArray(next.elements) ? next.elements : [];
        var reusableCatalogElements = catalogElements.filter(apdIsReusableElementDefinition);
        var payloadElements = apdCollectElementDefinitionsFromPayload(payload || {});
        var mergedElements = apdMergeElementDefinitionGroups([payloadElements, reusableCatalogElements]);

        if (mergedElements.length) {
            next.elements = mergedElements;
        } else {
            // WordPress catalog “shapes” are mapped to moduleConfig.shapes.svgAssets.
            // Do not pass shape-only catalog.elements through full-state imports,
            // because AsukaDesigner also uses store.elements for reusable Elements
            // and their selectable variations.
            delete next.elements;
        }
        return next;
    }

    function apdApplyRuntimeCatalogAndModuleConfigToInstance(instance, config) {
        config = sanitizeObject(config, {});
        var store = apdGetRuntimeStore(instance);
        if (!store || typeof store.getState !== 'function') {
            return false;
        }

        var applied = false;
        try {
            var state = store.getState() || {};
            logApdVariationDebug('runtimeBridge:elements:applyCatalog:start', {
                config: summarizeMountPayload(config),
                runtimeBefore: summarizeRuntimeElementState(instance)
            });
            var moduleConfig = sanitizeObject(config.moduleConfig, {});
            var catalog = sanitizeObject(config.catalog, {});

            if (Array.isArray(catalog.designs)) {
                moduleConfig = Object.assign({}, moduleConfig, {
                    designs: Object.assign({}, sanitizeObject(moduleConfig.designs, {}), {
                        items: catalog.designs.filter(function (item) { return item && typeof item === 'object'; })
                    })
                });
            }

            if (Array.isArray(catalog.elements)) {
                moduleConfig = Object.assign({}, moduleConfig, {
                    shapes: Object.assign({}, sanitizeObject(moduleConfig.shapes, {}), {
                        svgAssets: catalog.elements.filter(function (item) { return item && typeof item === 'object'; })
                    })
                });
            }

            if (Object.keys(moduleConfig).length) {
                var currentModuleConfig = sanitizeObject(state && state.moduleConfig, {});
                var nextModuleConfig = Object.assign({}, currentModuleConfig, moduleConfig);
                if (!apdPlainDataEqual(currentModuleConfig, nextModuleConfig)) {
                    if (state && typeof state.setModuleConfig === 'function') {
                        state.setModuleConfig(moduleConfig);
                        applied = true;
                    } else if (typeof store.setState === 'function') {
                        store.setState({ moduleConfig: nextModuleConfig });
                        applied = true;
                    }
                }
            }

            if (typeof store.setState === 'function') {
                var patch = {};
                var currentElements = Array.isArray(state.elements)
                    ? state.elements.filter(function (item) { return item && typeof item === 'object'; })
                    : [];
                var payloadElements = apdCollectElementDefinitionsFromPayload(config);
                var reusableCatalogElements = Array.isArray(catalog.elements)
                    ? catalog.elements.filter(apdIsReusableElementDefinition)
                    : [];
                var mergedElements = apdMergeElementDefinitionGroups([currentElements, payloadElements, reusableCatalogElements]);
                logApdVariationDebug('runtimeBridge:elements:applyCatalog:merge', {
                    currentElements: summarizeElementDefinitions(currentElements, 10),
                    payloadElements: summarizeElementDefinitions(payloadElements, 10),
                    reusableCatalogElements: summarizeElementDefinitions(reusableCatalogElements, 10),
                    mergedElements: summarizeElementDefinitions(mergedElements, 10)
                });
                if (mergedElements.length && !apdPlainDataEqual(currentElements, mergedElements)) {
                    patch.elements = mergedElements;
                }
                if (apdPatchRuntimeElementFinder(instance)) {
                    applied = true;
                }
                if (apdNormalizeElementInstanceReferences(instance, mergedElements)) {
                    applied = true;
                }
                if (Array.isArray(catalog.colors)) {
                    var nextColors = catalog.colors.filter(function (item) { return item && typeof item === 'object'; });
                    if (!apdPlainDataEqual(Array.isArray(state.colors) ? state.colors : [], nextColors)) {
                        patch.colors = nextColors;
                    }
                }
                if (Array.isArray(catalog.printingMethods)) {
                    var nextPrintingMethods = catalog.printingMethods.filter(function (item) { return item && typeof item === 'object'; });
                    if (!apdPlainDataEqual(Array.isArray(state.printingMethods) ? state.printingMethods : [], nextPrintingMethods)) {
                        patch.printingMethods = nextPrintingMethods;
                    }
                }
                if (Object.keys(patch).length) {
                    store.setState(patch);
                    applied = true;
                    if (patch.elements && apdNormalizeElementInstanceReferences(instance, patch.elements)) {
                        applied = true;
                    }
                    if (patch.elements && apdPatchRuntimeElementFinder(instance)) {
                        applied = true;
                    }
                }
            }
        } catch (error) {
            return applied;
        }

        logApdVariationDebug('runtimeBridge:elements:applyCatalog:end', {
            applied: applied,
            runtimeAfter: summarizeRuntimeElementState(instance)
        });
        return applied;
    }

    function apdApplyRuntimePermissionsToInstance(instance, permissions) {
        permissions = sanitizeObject(permissions, {});
        if (!Object.keys(permissions).length || !instance) {
            return false;
        }

        var applied = false;
        var patch = normalizeClientViewPermissions({ permissions: clonePlainObject(permissions), context: {} }).permissions || permissions;

        try {
            if (instance.util && instance.util.permissions && typeof instance.util.permissions.setPermissions === 'function') {
                instance.util.permissions.setPermissions(patch);
                applied = true;
            }
        } catch (error) {}

        try {
            if (!applied && instance.util && typeof instance.util.setPermissions === 'function') {
                instance.util.setPermissions(patch);
                applied = true;
            }
        } catch (error) {}

        try {
            if (!applied && instance.api && instance.api.permissions && typeof instance.api.permissions.setPermissions === 'function') {
                instance.api.permissions.setPermissions(patch);
                applied = true;
            }
        } catch (error) {}

        var store = apdGetRuntimeStore(instance);
        try {
            if (store && typeof store.getState === 'function') {
                var state = store.getState() || {};
                if (state && typeof state.setPermissions === 'function') {
                    state.setPermissions(patch);
                    applied = true;
                } else if (typeof store.setState === 'function') {
                    store.setState(function (current) {
                        return { permissions: Object.assign({}, sanitizeObject(current && current.permissions, {}), patch) };
                    });
                    applied = true;
                }
            }
        } catch (error) {}

        return applied;
    }

    function apdKeepRuntimePermissions(instance, permissions) {
        permissions = sanitizeObject(permissions, {});
        if (!Object.keys(permissions).length) {
            return;
        }
        [0, 16, 80, 220, 500, 1000].forEach(function (delay) {
            window.setTimeout(function () {
                apdApplyRuntimePermissionsToInstance(instance, permissions);
            }, delay);
        });
    }

    function apdKeepRuntimeUploadConfig(instance, uploadConfig) {
        uploadConfig = sanitizeObject(uploadConfig, {});
        if (!Object.keys(uploadConfig).length) {
            return;
        }
        [0, 16, 80, 220, 500, 1000, 1800].forEach(function (delay) {
            window.setTimeout(function () {
                apdApplyRuntimeUploadConfigToInstance(instance, uploadConfig);
            }, delay);
        });
    }

    function apdKeepRuntimeCatalogAndModuleConfig(instance, config) {
        config = sanitizeObject(config, {});
        if (!instance || !Object.keys(config).length) {
            return;
        }
        [0, 16, 80, 220, 500, 1000, 1800].forEach(function (delay) {
            window.setTimeout(function () {
                apdApplyRuntimeCatalogAndModuleConfigToInstance(instance, config);
            }, delay);
        });
    }


    function normalizeColorsConfig(value) {
        if (Array.isArray(value)) {
            return { scope: 'object', items: value };
        }
        if (!value || typeof value !== 'object') {
            return { scope: 'object', items: [] };
        }
        var scope = ['object', 'canvas', 'document'].indexOf(String(value.scope || 'object')) !== -1
            ? String(value.scope || 'object')
            : 'object';
        var items = [];
        if (Array.isArray(value.items)) {
            items = value.items;
        } else if (Array.isArray(value.colors)) {
            items = value.colors;
        }
        return { scope: scope, items: items };
    }


    function normalizeStringList(value) {
        if (typeof value === 'string') {
            value = value.split(/[\s,]+/);
        }
        if (!Array.isArray(value)) {
            return [];
        }
        var seen = {};
        var items = [];
        value.forEach(function (item) {
            item = String(item == null ? '' : item).trim();
            if (!item || seen[item]) {
                return;
            }
            seen[item] = true;
            items.push(item);
        });
        return items;
    }

    function normalizeFontItem(font, fallbackSource) {
        if (!font || typeof font !== 'object') {
            return null;
        }
        var family = String(font.family || font.label || font.name || '').trim();
        if (!family) {
            return null;
        }
        var source = String(font.source || fallbackSource || 'system').trim().toLowerCase();
        if (['system', 'google', 'custom'].indexOf(source) === -1) {
            source = 'system';
        }
        var id = String(font.id || family).trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || family;
        var item = { id: id, family: family };
        if (source === 'google') {
            if (font.cssUrl) item.cssUrl = String(font.cssUrl);
            var weights = normalizeStringList(font.weights);
            if (weights.length) item.weights = weights;
            var styles = normalizeStringList(font.styles).filter(function (style) { return style === 'normal' || style === 'italic'; });
            if (styles.length) item.styles = styles;
            return { source: 'google', item: item };
        }
        if (source === 'custom') {
            var url = String(font.url || font.fileUrl || '').trim();
            var cssUrl = String(font.cssUrl || '').trim();
            if (url) item.url = url;
            if (cssUrl) item.cssUrl = cssUrl;
            if (font.format) item.format = String(font.format);
            if (font.weight != null && font.weight !== '') item.weight = font.weight;
            if (font.style === 'normal' || font.style === 'italic') item.style = font.style;
            if (url || cssUrl) {
                return { source: 'custom', item: item };
            }
        }
        return { source: 'system', item: item };
    }

    function normalizeFontsConfig(value) {
        var out = { system: [], google: [], custom: [] };
        var push = function (font, source) {
            var normalized = normalizeFontItem(font, source);
            if (!normalized) {
                return;
            }
            out[normalized.source].push(normalized.item);
        };
        if (Array.isArray(value)) {
            value.forEach(function (font) { push(font, font && font.source); });
        } else if (value && typeof value === 'object') {
            ['system', 'google', 'custom'].forEach(function (source) {
                if (Array.isArray(value[source])) {
                    value[source].forEach(function (font) { push(font, source); });
                }
            });
            if (Array.isArray(value.items)) {
                value.items.forEach(function (font) { push(font, font && font.source); });
            }
            if (Array.isArray(value.fonts)) {
                value.fonts.forEach(function (font) { push(font, font && font.source); });
            }
        }
        ['system', 'google', 'custom'].forEach(function (source) {
            var byId = {};
            out[source].forEach(function (font) {
                var id = String(font.id || font.family || '');
                if (!id) return;
                byId[id] = Object.assign({}, byId[id] || {}, font);
            });
            out[source] = Object.keys(byId).map(function (id) { return byId[id]; });
        });
        return out;
    }

    function hasFontsConfigItems(value) {
        return !!(value && typeof value === 'object' && (
            (Array.isArray(value.system) && value.system.length) ||
            (Array.isArray(value.google) && value.google.length) ||
            (Array.isArray(value.custom) && value.custom.length)
        ));
    }

    function normalizeColorItem(color, index) {
        if (!color || typeof color !== 'object') {
            return null;
        }
        var value = String(color.value || color.color || color.hex || '').trim();
        if (!value) {
            return null;
        }
        var id = String(color.id || '').trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || ('color-' + index);
        var label = String(color.label || color.name || value).trim() || value;
        return Object.assign({}, color, { id: id, label: label, value: value, price: Number(color.price || 0) || 0 });
    }

    function normalizeColorItems(items) {
        if (!Array.isArray(items)) {
            if (items && typeof items === 'object' && Array.isArray(items.items)) {
                items = items.items;
            } else if (items && typeof items === 'object' && Array.isArray(items.colors)) {
                items = items.colors;
            } else {
                return [];
            }
        }
        return items.map(function (color, index) { return normalizeColorItem(color, index); }).filter(Boolean);
    }

    function normalizePrintingMethodColorItems(rawColors, colorItems) {
        var map = {};
        normalizeColorItems(colorItems || []).forEach(function (color) {
            if (color.id) map[String(color.id)] = color;
            if (color.value) map[String(color.value)] = color;
        });
        if (!Array.isArray(rawColors)) {
            rawColors = typeof rawColors === 'string' ? normalizeStringList(rawColors) : [];
        }
        return rawColors.map(function (entry, index) {
            if (entry && typeof entry === 'object') {
                return normalizeColorItem(entry, index);
            }
            var key = String(entry == null ? '' : entry).trim();
            if (!key) return null;
            return map[key] || map[key.toLowerCase()] || { id: key.toLowerCase().replace(/[^a-z0-9_-]+/g, '-') || ('color-' + index), label: key, value: key };
        }).filter(Boolean);
    }

    function normalizePrintingMethodsConfig(value, colorItems) {
        if (!Array.isArray(value)) {
            if (value && typeof value === 'object' && Array.isArray(value.items)) {
                value = value.items;
            } else if (value && typeof value === 'object' && Array.isArray(value.printingMethods)) {
                value = value.printingMethods;
            } else {
                return [];
            }
        }
        return value.map(function (method, index) {
            if (!method || typeof method !== 'object') {
                return null;
            }
            var label = String(method.label || method.name || method.id || '').trim();
            var id = String(method.id || label || ('printing-method-' + index)).trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || ('printing-method-' + index);
            return Object.assign({}, method, {
                id: id,
                label: label || id,
                name: method.name || label || id,
                price: Number(method.price || 0) || 0,
                colors: normalizePrintingMethodColorItems(method.colors || [], colorItems || [])
            });
        }).filter(Boolean);
    }

    function normalizePricingHandler(handler) {
        var normalized = String(handler || '').trim().toLowerCase().replace(/[^a-z0-9]+/g, '');
        var map = {
            layersamount: 'layersAmount',
            textlength: 'textLength',
            textlines: 'textLines',
            usedcolorsamount: 'usedColorsAmount',
            colorslength: 'usedColorsAmount',
            scale: 'scale',
            layersize: 'layerSize',
            canvassize: 'canvasSize'
        };
        return map[normalized] || (handler ? String(handler) : 'layersAmount');
    }

    function normalizePricingScope(scope) {
        scope = String(scope || 'all').trim().toLowerCase();
        return scope === 'first' || scope === 'current' ? 'first' : 'all';
    }

    function normalizePricingTargetTypes(value) {
        return normalizeStringList(value).map(function (part) {
            var normalized = String(part || '').toLowerCase().replace(/[^a-z0-9]+/g, '');
            if (['text', 'textbox', 'itext'].indexOf(normalized) !== -1) return 'Text';
            if (['image', 'images'].indexOf(normalized) !== -1) return 'Image';
            if (['design', 'designs', 'group'].indexOf(normalized) !== -1) return 'Design';
            if (['tool', 'tools'].indexOf(normalized) !== -1) return 'Tools';
            return part;
        });
    }

    function normalizePricingRuleConfig(rule, index) {
        if (!rule || typeof rule !== 'object') {
            return null;
        }
        var conditions = [];
        if (Array.isArray(rule.conditions)) {
            conditions = rule.conditions.filter(function (item) { return item && typeof item === 'object'; });
        } else if (typeof rule.conditionsJson === 'string' && rule.conditionsJson.trim()) {
            try {
                var decoded = JSON.parse(rule.conditionsJson);
                if (Array.isArray(decoded)) {
                    conditions = decoded.filter(function (item) { return item && typeof item === 'object'; });
                }
            } catch (error) {}
        }
        var id = String(rule.id || rule.label || ('pricing-rule-' + index)).trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || ('pricing-rule-' + index);
        var target = rule.target && typeof rule.target === 'object' && !Array.isArray(rule.target) ? rule.target : {};
        var targetTypes = normalizePricingTargetTypes(target.types || rule.targetTypes || []);
        var targetViews = normalizeStringList(target.view || rule.targetViews || []);
        var normalizedTarget = {};
        if (targetTypes.length) normalizedTarget.types = targetTypes;
        if (targetViews.length) normalizedTarget.view = targetViews;
        return Object.assign({}, rule, {
            id: id,
            label: String(rule.label || rule.name || id),
            handler: normalizePricingHandler(rule.handler),
            scope: normalizePricingScope(rule.scope),
            match: String(rule.match || 'all').toLowerCase() === 'any' ? 'any' : 'all',
            target: normalizedTarget,
            conditions: conditions,
            enabled: typeof rule.enabled === 'undefined' ? true : !!rule.enabled
        });
    }

    function normalizePricingRulesConfig(value) {
        var rules = extractPricingRules(value);
        return rules.map(function (rule, index) { return normalizePricingRuleConfig(rule, index); }).filter(Boolean);
    }

    function normalizeShapeAsset(shape, index) {
        if (!shape || typeof shape !== 'object') {
            return null;
        }
        var svgText = String(shape.svgText || shape.svg || '').trim();
        var svgPath = String(shape.svgPath || shape.path || '').trim();
        if (!svgText && svgPath) {
            var viewBox = String(shape.viewBox || '0 0 100 100');
            var fill = String(shape.fill || 'currentColor');
            var stroke = String(shape.stroke || '');
            svgText = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="' + viewBox.replace(/"/g, '&quot;') + '"><path d="' + svgPath.replace(/"/g, '&quot;') + '" fill="' + fill.replace(/"/g, '&quot;') + '"' + (stroke ? ' stroke="' + stroke.replace(/"/g, '&quot;') + '"' : '') + '/></svg>';
        }
        if (!svgText) {
            return null;
        }
        var label = String(shape.label || shape.name || ('Shape ' + (index + 1))).trim();
        var id = String(shape.id || label || ('shape-' + index)).trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || ('shape-' + index);
        return Object.assign({}, shape, { id: id, name: label || id, label: label || id, svgText: svgText });
    }

    function normalizeModuleConfigConfig(value, catalog) {
        var moduleConfig = sanitizeObject(value, {});
        catalog = sanitizeObject(catalog, {});
        var hasCatalogDesigns = Array.isArray(catalog.designs);
        var designs = hasCatalogDesigns ? catalog.designs.slice() : [];
        if (!hasCatalogDesigns && moduleConfig.designs && typeof moduleConfig.designs === 'object' && Array.isArray(moduleConfig.designs.items)) {
            designs = moduleConfig.designs.items.slice();
        }
        if (hasCatalogDesigns || designs.length) {
            moduleConfig.designs = Object.assign({}, sanitizeObject(moduleConfig.designs, {}), { items: designs.filter(function (item) { return item && typeof item === 'object'; }) });
        }
        var hasCatalogShapes = Array.isArray(catalog.elements);
        var shapeAssets = hasCatalogShapes ? catalog.elements.slice() : [];
        if (!hasCatalogShapes && moduleConfig.shapes && typeof moduleConfig.shapes === 'object' && Array.isArray(moduleConfig.shapes.svgAssets)) {
            shapeAssets = moduleConfig.shapes.svgAssets.slice();
        }
        shapeAssets = shapeAssets.map(normalizeShapeAsset).filter(Boolean);
        if (hasCatalogShapes || shapeAssets.length) {
            moduleConfig.shapes = Object.assign({}, sanitizeObject(moduleConfig.shapes, {}), { svgAssets: shapeAssets });
        }
        return moduleConfig;
    }



    function summarizeI18nValue(i18n, key) {
        return getI18nTranslation(i18n, key) || '';
    }

    function collectLayoutMenuDebug(layout, i18n) {
        var rows = [];
        if (!layout || typeof layout !== 'object') {
            return rows;
        }
        ['top', 'left', 'right', 'bottom'].forEach(function (zone) {
            var zoneConfig = layout[zone];
            if (!zoneConfig || typeof zoneConfig !== 'object') {
                return;
            }
            var items = Array.isArray(zoneConfig.items) ? zoneConfig.items : (Array.isArray(zoneConfig) ? zoneConfig : null);
            if (!items) {
                return;
            }
            items.forEach(function (item) {
                if (!item || typeof item !== 'object') {
                    return;
                }
                var id = item.id != null ? String(item.id) : '';
                var kind = item.kind != null ? String(item.kind) : '';
                rows.push({
                    zone: zone,
                    id: id,
                    kind: kind,
                    label: item.label != null ? String(item.label) : '',
                    byId: id ? summarizeI18nValue(i18n, 'menu.' + id) : '',
                    byKind: kind ? summarizeI18nValue(i18n, 'menu.' + kind) : ''
                });
            });
        });
        return rows;
    }

    function debugI18nPayload(source, rawI18n, finalI18n, layout) {
        return;
    }
    function getI18nTranslation(i18n, key) {
        if (!i18n || typeof i18n !== 'object' || !key) {
            return '';
        }

        var translations = i18n.translations && typeof i18n.translations === 'object' ? i18n.translations : {};
        var locale = typeof i18n.locale === 'string' ? i18n.locale : '';
        var fallbackLocale = typeof i18n.fallbackLocale === 'string' ? i18n.fallbackLocale : 'en';
        var languageLocale = locale ? String(locale).split(/[-_]/)[0].toLowerCase() : '';
        var order = [];

        [locale, languageLocale, fallbackLocale, 'en'].forEach(function (candidate) {
            if (!candidate) {
                return;
            }
            if (order.indexOf(candidate) === -1) {
                order.push(candidate);
            }
        });

        var segments = String(key).split('.');
        for (var i = 0; i < order.length; i += 1) {
            var node = translations[order[i]];
            for (var j = 0; node && j < segments.length; j += 1) {
                node = Object.prototype.hasOwnProperty.call(node, segments[j]) ? node[segments[j]] : undefined;
            }
            if (typeof node === 'string' && node !== '') {
                return node;
            }
        }

        return '';
    }

    function localizeLayoutMenus(layout, i18n) {
        if (!layout || typeof layout !== 'object') {
            return layout;
        }

        ['top', 'left', 'right', 'bottom'].forEach(function (zone) {
            var zoneConfig = layout[zone];
            if (!zoneConfig || typeof zoneConfig !== 'object') {
                return;
            }

            var items = Array.isArray(zoneConfig.items) ? zoneConfig.items : (Array.isArray(zoneConfig) ? zoneConfig : null);
            if (!items) {
                return;
            }

            items.forEach(function (item) {
                if (!item || typeof item !== 'object') {
                    return;
                }

                var id = item.id != null ? String(item.id) : '';
                var kind = item.kind != null ? String(item.kind) : '';
                var translated = '';

                if (id) {
                    translated = getI18nTranslation(i18n, 'menu.' + id);
                }
                if (!translated && kind) {
                    translated = getI18nTranslation(i18n, 'menu.' + kind);
                }
                if (translated) {
                    item.label = translated;
                }
            });
        });

        return layout;
    }



    function normalizeMenuToken(value) {
        return String(value == null ? '' : value)
            .trim()
            .toLowerCase()
            .replace(/&apos;|&#039;/g, '')
            .replace(/[^a-z0-9]+/g, '-')
            .replace(/^-+|-+$/g, '');
    }

    function collectMenuTranslationMap(i18n) {
        var map = {};
        if (!i18n || typeof i18n !== 'object') {
            return map;
        }
        var translations = i18n.translations && typeof i18n.translations === 'object' ? i18n.translations : {};
        var locale = typeof i18n.locale === 'string' ? i18n.locale : '';
        var fallbackLocale = typeof i18n.fallbackLocale === 'string' ? i18n.fallbackLocale : 'en';
        var languageLocale = locale ? String(locale).split(/[-_]/)[0].toLowerCase() : '';
        var order = [];
        ['en', fallbackLocale, languageLocale, locale].forEach(function (candidate) {
            if (!candidate || order.indexOf(candidate) !== -1) {
                return;
            }
            order.push(candidate);
        });
        order.forEach(function (candidate) {
            var node = translations[candidate];
            var menu = node && typeof node === 'object' && node.menu && typeof node.menu === 'object' ? node.menu : null;
            if (!menu) {
                return;
            }
            Object.keys(menu).forEach(function (key) {
                var value = menu[key];
                if (typeof value === 'string' && value !== '') {
                    map[String(key)] = value;
                }
            });
        });
        return map;
    }

    function getRenderedMenuElements(root) {
        if (!root || typeof root.querySelectorAll !== 'function') {
            return [];
        }
        var selectors = [
            '[data-asuka-block-id]',
            '.ask-theme-sidebar-item',
            '.ask-menu-item',
            '[class*="ask-theme-sidebar-item"]'
        ];
        var seen = [];
        var items = [];
        selectors.forEach(function (selector) {
            root.querySelectorAll(selector).forEach(function (node) {
                if (seen.indexOf(node) !== -1) {
                    return;
                }
                seen.push(node);
                items.push(node);
            });
        });
        return items;
    }

    function buildRenderedMenuRows(root, i18n) {
        var rows = [];
        var menuMap = collectMenuTranslationMap(i18n);
        getRenderedMenuElements(root).forEach(function (node, index) {
            if (!node || typeof node !== 'object') {
                return;
            }
            var labelNode = node.querySelector ? node.querySelector('.ask-theme-sidebar-item__label, .ask-nav__label, .ask-font-medium') : null;
            var visibleLabel = labelNode && labelNode.textContent ? String(labelNode.textContent).trim() : '';
            var title = node.getAttribute ? String(node.getAttribute('title') || node.getAttribute('aria-label') || '').trim() : '';
            var blockId = node.getAttribute ? String(node.getAttribute('data-asuka-block-id') || '').trim() : '';
            var kind = node.getAttribute ? String(node.getAttribute('data-kind') || node.getAttribute('data-module-kind') || '').trim() : '';
            var normalizedVisible = normalizeMenuToken(visibleLabel || title);
            var byId = blockId ? getI18nTranslation(i18n, 'menu.' + blockId) : '';
            var byKind = kind ? getI18nTranslation(i18n, 'menu.' + kind) : '';
            var byVisible = !byId && !byKind && normalizedVisible && Object.prototype.hasOwnProperty.call(menuMap, normalizedVisible) ? String(menuMap[normalizedVisible]) : '';
            rows.push({
                index: index,
                blockId: blockId,
                kind: kind,
                title: title,
                visibleLabel: visibleLabel,
                normalizedVisible: normalizedVisible,
                byId: byId,
                byKind: byKind,
                byVisible: byVisible
            });
        });
        return rows;
    }

    function patchRenderedMenuDom(root, i18n, source) {
        var patched = [];
        var rows = buildRenderedMenuRows(root, i18n);
        var nodes = getRenderedMenuElements(root);
        rows.forEach(function (row) {
            var node = nodes[row.index];
            if (!node) {
                return;
            }
            var translated = row.byId || row.byKind || row.byVisible || '';
            if (!translated) {
                return;
            }
            var labelNode = node.querySelector ? node.querySelector('.ask-theme-sidebar-item__label, .ask-nav__label, .ask-font-medium') : null;
            if (labelNode && String(labelNode.textContent || '').trim() !== translated) {
                labelNode.textContent = translated;
                patched.push({ target: 'text', blockId: row.blockId, kind: row.kind, from: row.visibleLabel, to: translated });
            }
            if (node.setAttribute) {
                var currentTitle = String(node.getAttribute('title') || '').trim();
                if (currentTitle && currentTitle !== translated) {
                    node.setAttribute('title', translated);
                    patched.push({ target: 'title', blockId: row.blockId, kind: row.kind, from: currentTitle, to: translated });
                }
                var currentAria = String(node.getAttribute('aria-label') || '').trim();
                if (currentAria && currentAria !== translated) {
                    node.setAttribute('aria-label', translated);
                    patched.push({ target: 'aria-label', blockId: row.blockId, kind: row.kind, from: currentAria, to: translated });
                }
            }
        });
        return rows;
    }

    function patchInstanceLayoutMenus(instance, i18n, source) {
        var results = [];
        if (!instance || !instance.layout || typeof instance.layout.updateItem !== 'function') {
            return results;
        }
        var menuMap = collectMenuTranslationMap(i18n);
        Object.keys(menuMap).forEach(function (key) {
            var translated = menuMap[key];
            if (!translated) {
                return;
            }
            try {
                instance.layout.updateItem(key, { label: translated });
                results.push({ target: key, label: translated, ok: true });
            } catch (error) {
                results.push({ target: key, label: translated, ok: false, error: error && error.message ? error.message : String(error) });
            }
        });
        return results;
    }

    function installRenderedMenuDebug(root, instance, i18n, source) {
        if (!root || !i18n || typeof i18n !== 'object') {
            return;
        }
        patchInstanceLayoutMenus(instance, i18n, source);
        if (root.__apdRenderedMenuObserver && typeof root.__apdRenderedMenuObserver.disconnect === 'function') {
            root.__apdRenderedMenuObserver.disconnect();
        }
        root.__apdRenderedMenuState = { signature: '' };
        var run = function () {
            var rows = patchRenderedMenuDom(root, i18n, source);
            var signature = rows.map(function (row) {
                return [row.blockId, row.kind, row.visibleLabel, row.title, row.byId, row.byKind, row.byVisible].join('|');
            }).join('||');
            if (root.__apdRenderedMenuState.signature === signature) {
                return;
            }
            root.__apdRenderedMenuState.signature = signature;
        };
        run();
        window.setTimeout(run, 80);
        window.setTimeout(run, 300);
        window.setTimeout(run, 900);
        if (typeof MutationObserver === 'function') {
            root.__apdRenderedMenuObserver = new MutationObserver(function () {
                if (root.__apdRenderedMenuTick) {
                    return;
                }
                root.__apdRenderedMenuTick = window.setTimeout(function () {
                    root.__apdRenderedMenuTick = null;
                    run();
                }, 30);
            });
            root.__apdRenderedMenuObserver.observe(root, {
                childList: true,
                subtree: true,
                attributes: true,
                characterData: false,
            });
        }
    }

    function extractPricingRules(container) {
        if (!container) {
            return [];
        }
        if (Array.isArray(container)) {
            return container.filter(function (item) { return item && typeof item === 'object'; });
        }
        if (typeof container !== 'object') {
            return [];
        }
        if (Array.isArray(container.pricingRules)) {
            return container.pricingRules.filter(function (item) { return item && typeof item === 'object'; });
        }
        if (Array.isArray(container.rules)) {
            return container.rules.filter(function (item) { return item && typeof item === 'object'; });
        }
        return [];
    }

    function getTopLevelPricingPayload(raw) {
        raw = sanitizeObject(raw, {});
        var nested = sanitizeObject(raw.pricing, {});
        var topLevelRules = normalizePricingRulesConfig(raw);
        var nestedRules = normalizePricingRulesConfig(nested);
        var rawPrice = typeof raw.price !== 'undefined' ? raw.price : undefined;
        if (typeof rawPrice === 'undefined') rawPrice = typeof raw.basePrice !== 'undefined' ? raw.basePrice : undefined;
        if (typeof rawPrice === 'undefined') rawPrice = typeof raw.designerBasePrice !== 'undefined' ? raw.designerBasePrice : undefined;
        if (typeof rawPrice === 'undefined') rawPrice = typeof nested.price !== 'undefined' ? nested.price : undefined;
        if (typeof rawPrice === 'undefined') rawPrice = typeof nested.basePrice !== 'undefined' ? nested.basePrice : undefined;
        if (typeof rawPrice === 'undefined') rawPrice = typeof nested.designerBasePrice !== 'undefined' ? nested.designerBasePrice : undefined;
        var priceFormat = sanitizeObject(raw.priceFormat, {});
        if (!Object.keys(priceFormat).length) {
            priceFormat = sanitizeObject(nested.priceFormat, {});
        }
        return {
            price: typeof rawPrice === 'undefined' ? undefined : (Number(rawPrice) || 0),
            pricingRules: topLevelRules.length ? topLevelRules : nestedRules,
            priceFormat: priceFormat
        };
    }

    function isPhpRuntimePayload(raw) {
        raw = sanitizeObject(raw, {});
        var context = sanitizeObject(raw.context, {});
        return Number(raw.runtimePayloadVersion || context.apdRuntimeConfigVersion || 0) >= 2
            || String(context.apdRuntimeConfigBuilder || '') === 'php';
    }

    function sanitizePhpRuntimeConfig(raw) {
        raw = sanitizeObject(raw, {});
        var colorsConfig = sanitizeObject(raw.colors, { scope: 'object', items: [] });
        if (['object', 'canvas', 'document'].indexOf(String(colorsConfig.scope || 'object')) === -1) {
            colorsConfig.scope = 'object';
        }
        if (!Array.isArray(colorsConfig.items)) {
            colorsConfig.items = [];
        }

        var safe = {
            runtimePayloadVersion: Number(raw.runtimePayloadVersion || 3) || 3,
            mode: typeof raw.mode === 'string' ? raw.mode : 'standalone',
            theme: sanitizeObject(raw.theme, {}),
            layout: sanitizeObject(raw.layout, {}),
            permissions: sanitizeObject(raw.permissions, {}),
            listeners: sanitizeObject(raw.listeners, {}),
            integrations: sanitizeObject(raw.integrations, {}),
            license: sanitizeObject(raw.license, {}),
            ai: sanitizeObject(raw.ai, {}),
            exports: sanitizeObject(raw.exports, {}),
            upload: sanitizeObject(raw.upload, {}),
            pricing: sanitizeObject(raw.pricing, {}),
            price: typeof raw.price === 'undefined' ? undefined : (Number(raw.price) || 0),
            pricingRules: sanitizeArray(raw.pricingRules, []),
            priceFormat: sanitizeObject(raw.priceFormat, {}),
            context: sanitizeObject(raw.context, {}),
            pdf: sanitizeObject(raw.pdf, {}),
            i18n: sanitizeObject(raw.i18n, {}),
            ui: sanitizeObject(raw.ui, {}),
            moduleConfig: sanitizeObject(raw.moduleConfig, {}),
            colors: colorsConfig,
            printingMethods: sanitizeArray(raw.printingMethods, []),
            catalog: sanitizeObject(raw.catalog, {}),
            runtimeElements: sanitizeArray(raw.runtimeElements, []),
            views: sanitizeArray(raw.views, []),
            drawingZones: normalizeRuntimeDrawingZonesInput(raw.drawingZones),
            fonts: sanitizeObject(raw.fonts, {}),
            initialState: raw.initialState && typeof raw.initialState === 'object'
                ? buildCanonicalFullState(raw.initialState, null, raw)
                : (raw.initialDocument && typeof raw.initialDocument === 'object'
                    ? buildCanonicalDocumentState(raw.initialDocument, raw)
                    : null),
        };

        if (!safe.initialState) delete safe.initialState;

        var hasStateBootPayload = !!(
            safe.initialState
            && typeof safe.initialState === 'object'
            && !Array.isArray(safe.initialState)
            && Object.keys(safe.initialState).length
        );

        var stateHasViews = payloadHasViews(safe.initialState);

        if (!hasStateBootPayload || !stateHasViews) {
            delete safe.initialState;
            hasStateBootPayload = false;
        }

        if (hasStateBootPayload && stateHasViews) {
            mergeTopLevelDrawingZonesIntoBootPayload(safe);
            delete safe.views;
            delete safe.drawingZones;
        }

        normalizeClientViewPermissions(safe);
        ensureAdminDrawingAreasLayout(safe);
        forceAdminRuntimePermissions(safe);

        if (!safe.views || !safe.views.length) delete safe.views;
        if (!safe.drawingZones || !safe.drawingZones.length) delete safe.drawingZones;
        if (!hasFontsConfigItems(safe.fonts)) delete safe.fonts;
        if (!Object.keys(safe.theme).length) delete safe.theme;
        if (!Object.keys(safe.layout).length) delete safe.layout;
        if (!Object.keys(safe.permissions).length) delete safe.permissions;
        if (!Object.keys(safe.listeners).length) delete safe.listeners;
        if (!Object.keys(safe.integrations).length) delete safe.integrations;
        if (!Object.keys(safe.license).length) delete safe.license;
        if (!Object.keys(safe.ai).length) delete safe.ai;
        if (!Object.keys(safe.exports).length) delete safe.exports;
        if (!Object.keys(safe.upload).length) delete safe.upload;
        if (!Object.keys(safe.pricing).length) delete safe.pricing;
        if (typeof safe.price === 'undefined') delete safe.price;
        if (!Array.isArray(safe.pricingRules) || !safe.pricingRules.length) delete safe.pricingRules;
        if (!Object.keys(safe.priceFormat).length) delete safe.priceFormat;
        if (!Object.keys(safe.context).length) delete safe.context;
        if (!Object.keys(safe.pdf).length) delete safe.pdf;
        if (!Object.keys(safe.ui).length) delete safe.ui;
        localizeLayoutMenus(safe.layout, safe.i18n);
        debugI18nPayload('runtime-bridge:sanitizePhpRuntimeConfig', raw.i18n, safe.i18n, safe.layout);

        if (!Object.keys(safe.i18n).length) delete safe.i18n;
        if (!Object.keys(safe.moduleConfig).length) delete safe.moduleConfig;
        if (!safe.printingMethods.length) delete safe.printingMethods;
        if (!Array.isArray(safe.runtimeElements) || !safe.runtimeElements.length) delete safe.runtimeElements;
        if (!Object.keys(safe.catalog).length) delete safe.catalog;

        logApdVariationDebug('runtimeBridge:sanitizePhpRuntimeConfig', {
            raw: summarizeMountPayload(raw),
            safe: summarizeMountPayload(safe)
        });

        return safe;
    }

    function sanitizeMountConfig(raw) {
        raw = sanitizeObject(raw, {});
        if (isPhpRuntimePayload(raw)) {
            return sanitizePhpRuntimeConfig(raw);
        }
        var topLevelPricing = getTopLevelPricingPayload(raw);
        var colorsConfig = normalizeColorsConfig(raw.colors);
        colorsConfig.items = normalizeColorItems(colorsConfig.items);
        var catalog = sanitizeObject(raw.catalog, {});
        catalog.colors = normalizeColorItems(catalog.colors || colorsConfig.items || []);
        if (!catalog.colors.length && colorsConfig.items.length) {
            catalog.colors = colorsConfig.items.slice();
        }
        catalog.printingMethods = normalizePrintingMethodsConfig(catalog.printingMethods || raw.printingMethods || [], catalog.colors || colorsConfig.items || []);
        if (Array.isArray(catalog.elements)) {
            catalog.elements = catalog.elements.map(normalizeShapeAsset).filter(Boolean);
        }
        var printingMethods = normalizePrintingMethodsConfig(raw.printingMethods || catalog.printingMethods || [], colorsConfig.items || catalog.colors || []);
        var moduleConfig = normalizeModuleConfigConfig(raw.moduleConfig, catalog);
        var fontsConfig = normalizeFontsConfig(raw.fonts);
        var pricingConfig = sanitizeObject(raw.pricing, {});
        if (topLevelPricing.pricingRules.length) {
            pricingConfig = Object.assign({}, pricingConfig, {
                rules: topLevelPricing.pricingRules,
                pricingRules: topLevelPricing.pricingRules
            });
        }
        var safe = {
            mode: typeof raw.mode === 'string' ? raw.mode : 'standalone',
            theme: sanitizeObject(raw.theme, {}),
            layout: sanitizeObject(raw.layout, {}),
            permissions: sanitizeObject(raw.permissions, {}),
            listeners: sanitizeObject(raw.listeners, {}),
            integrations: sanitizeObject(raw.integrations, {}),
            license: sanitizeObject(raw.license, {}),
            ai: sanitizeObject(raw.ai, {}),
            exports: sanitizeObject(raw.exports, {}),
            upload: sanitizeObject(raw.upload, {}),
            pricing: pricingConfig,
            price: topLevelPricing.price,
            pricingRules: topLevelPricing.pricingRules,
            priceFormat: sanitizeObject(topLevelPricing.priceFormat, {}),
            context: sanitizeObject(raw.context, {}),
            pdf: sanitizeObject(raw.pdf, {}),
            i18n: sanitizeObject(raw.i18n, {}),
            ui: sanitizeObject(raw.ui, {}),
            moduleConfig: moduleConfig,
            colors: colorsConfig,
            printingMethods: printingMethods,
            catalog: catalog,
            views: sanitizeArray(raw.views, []),
            drawingZones: normalizeRuntimeDrawingZonesInput(raw.drawingZones),
            fonts: fontsConfig,
            initialState: raw.initialState && typeof raw.initialState === 'object'
                ? buildCanonicalFullState(raw.initialState, null, raw)
                : (raw.initialDocument && typeof raw.initialDocument === 'object'
                    ? buildCanonicalDocumentState(raw.initialDocument, raw)
                    : null),
        };

        if (!safe.initialState) delete safe.initialState;

        var hasStateBootPayload = !!(
            safe.initialState
            && typeof safe.initialState === 'object'
            && !Array.isArray(safe.initialState)
            && Object.keys(safe.initialState).length
        );

        var stateHasViews = payloadHasViews(safe.initialState);

        if (!hasStateBootPayload || !stateHasViews) {
            delete safe.initialState;
            hasStateBootPayload = false;
        }

        if (hasStateBootPayload && stateHasViews) {
            mergeTopLevelDrawingZonesIntoBootPayload(safe);
            delete safe.views;
            delete safe.drawingZones;
        }

        normalizeClientViewPermissions(safe);
        ensureAdminDrawingAreasLayout(safe);
        forceAdminRuntimePermissions(safe);

        if (!safe.views || !safe.views.length) delete safe.views;
        if (!safe.drawingZones || !safe.drawingZones.length) delete safe.drawingZones;
        if (!hasFontsConfigItems(safe.fonts)) delete safe.fonts;
        if (!Object.keys(safe.theme).length) delete safe.theme;
        if (!Object.keys(safe.layout).length) delete safe.layout;
        if (!Object.keys(safe.permissions).length) delete safe.permissions;
        if (!Object.keys(safe.listeners).length) delete safe.listeners;
        if (!Object.keys(safe.integrations).length) delete safe.integrations;
        if (!Object.keys(safe.license).length) delete safe.license;
        if (!Object.keys(safe.ai).length) delete safe.ai;
        if (!Object.keys(safe.exports).length) delete safe.exports;
        if (!Object.keys(safe.upload).length) delete safe.upload;
        if (!Object.keys(safe.pricing).length) delete safe.pricing;
        if (typeof safe.price === 'undefined') delete safe.price;
        if (!Array.isArray(safe.pricingRules) || !safe.pricingRules.length) delete safe.pricingRules;
        if (!Object.keys(safe.priceFormat).length) delete safe.priceFormat;
        if (!Object.keys(safe.context).length) delete safe.context;
        if (!Object.keys(safe.pdf).length) delete safe.pdf;
        if (!Object.keys(safe.ui).length) delete safe.ui;
        localizeLayoutMenus(safe.layout, safe.i18n);
        debugI18nPayload('runtime-bridge:sanitizeMountConfig', raw.i18n, safe.i18n, safe.layout);

        if (!Object.keys(safe.i18n).length) delete safe.i18n;
        if (!Object.keys(safe.moduleConfig).length) delete safe.moduleConfig;
        if (!safe.printingMethods.length) delete safe.printingMethods;
        if (!Array.isArray(safe.runtimeElements) || !safe.runtimeElements.length) delete safe.runtimeElements;
        if (!Object.keys(safe.catalog).length) delete safe.catalog;

        logApdVariationDebug('runtimeBridge:sanitizeMountConfig', {
            raw: summarizeMountPayload(raw),
            safe: summarizeMountPayload(safe)
        });

        return safe;
    }

    function flushInstanceForExport(instance) {
        return instance;
    }

    function scoreRestorableDocumentPayload(value) {
        if (!value || typeof value !== 'object') {
            return 0;
        }
        return (countBootViews(value) * 10) + (countPayloadObjects(value) * 100);
    }

    function exportDesign(instance) {
        flushInstanceForExport(instance);
        var bestValue = {};
        var bestScore = 0;
        var candidates = [
            function () { return instance && instance.util && instance.util.state && instance.util.state.exportPart && instance.util.state.exportPart('document'); }
        ];

        for (var i = 0; i < candidates.length; i += 1) {
            try {
                var value = candidates[i]();
                if (value && typeof value === 'object') {
                    var score = scoreRestorableDocumentPayload(value);
                    if (score > bestScore) {
                        bestScore = score;
                        bestValue = value;
                    }
                }
            } catch (error) {}
        }

        // Prefer the official document export path whenever it returns a
        // restorable payload. The runtime/canvas fallback is only a last resort:
        // it can reflect a post-boot Fabric canvas that has already been
        // re-normalized, which would persist wrong centered coordinates.
        if (bestScore > 0) {
            var exportedDocument = bestValue && typeof bestValue === 'object' ? clonePlainObject(bestValue) : {};
            try {
                var currentSnapshot = readCurrentDocumentSnapshot(instance || null);
                if (currentSnapshot && currentSnapshot.drawingAreasByView) {
                    mergeDrawingAreasIntoDocumentPayload(exportedDocument, currentSnapshot);
                }
            } catch (error) {}
            return exportedDocument;
        }

        var fallbackDocument = apdBuildDocumentFromRuntimeState(instance || null, null);
        var fallbackScore = scoreRestorableDocumentPayload(fallbackDocument);
        if (fallbackScore > 0) {
            try {
                var fallbackSnapshot = readCurrentDocumentSnapshot(instance || null);
                if (fallbackSnapshot && fallbackSnapshot.drawingAreasByView) {
                    mergeDrawingAreasIntoDocumentPayload(fallbackDocument, fallbackSnapshot);
                }
            } catch (error) {}
            return fallbackDocument;
        }

        return {};
    }

    function apdSerializeCanvasObjectForCart(object) {
        if (!object || typeof object !== 'object') {
            return null;
        }
        var extraProps = [
            'id', 'name', 'itemGroup', 'itemType', 'role', 'data',
            '_asukaImage', '_asukaDesign', '_asukaQrCode', '_asukaElementId', '_asukaElementName', '_asukaElementFamilyId', '_asukaElementIsInstance', '_asukaSourceModule', '_asukaFixedSlotId', '_asukaDrawingAreaId', '_asukaDrawingZoneId'
        ];
        try {
            if (typeof object.toObject === 'function') {
                return object.toObject(extraProps);
            }
        } catch (error) {}
        return clonePlainObject(object);
    }

    function apdGetLiveCanvasForCart(instance) {
        return instance && instance.util && instance.util.state && typeof instance.util.state.exportPart === 'function'
            ? instance
            : null;
    }

    function apdGetLiveCanvasObjectsForCart(instance) {
        var liveInstance = apdGetLiveCanvasForCart(instance);
        if (!liveInstance) {
            return null;
        }
        try {
            var exported = liveInstance.util.state.exportPart('document');
            var document = exported && exported.document && typeof exported.document === 'object'
                ? exported.document
                : {};
            var activeViewId = getPayloadActiveViewId(document, '');
            var byView = getPayloadObjectsByView(document);
            return Array.isArray(byView[activeViewId]) ? clonePlainObject(byView[activeViewId]) : [];
        } catch (error) {
            return null;
        }
    }

    function apdGetRuntimeViewsFromState(state) {
        state = state && typeof state === 'object' ? state : {};
        var candidates = [state.views, state.documentViews, state.viewList, state.viewsState && state.viewsState.views];
        for (var i = 0; i < candidates.length; i += 1) {
            var value = candidates[i];
            if (Array.isArray(value) && value.length) {
                return clonePlainObject(value);
            }
            if (value && typeof value === 'object' && Array.isArray(value.views) && value.views.length) {
                return clonePlainObject(value.views);
            }
        }
        return [];
    }

    function apdObjectsByViewHasObjects(value) {
        if (!value || typeof value !== 'object' || Array.isArray(value)) {
            return false;
        }
        var keys = Object.keys(value);
        for (var i = 0; i < keys.length; i += 1) {
            if (Array.isArray(value[keys[i]]) && value[keys[i]].length) {
                return true;
            }
        }
        return false;
    }

    function apdGetRuntimeObjectsByViewFromState(state, instance, fallbackActiveViewId) {
        state = state && typeof state === 'object' ? state : {};
        var candidates = [
            state.documentObjectsByView,
            state.objectsByView,
            state.objects && state.objects.byView,
            state.document && state.document.objects && state.document.objects.byView,
            state.initialDocument && state.initialDocument.objects && state.initialDocument.objects.byView
        ];
        var selected = {};
        var emptyCandidate = null;
        for (var i = 0; i < candidates.length; i += 1) {
            var value = candidates[i];
            if (value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length) {
                if (apdObjectsByViewHasObjects(value)) {
                    selected = clonePlainObject(value);
                    break;
                }
                if (!emptyCandidate) {
                    emptyCandidate = clonePlainObject(value);
                }
            }
        }
        if (!Object.keys(selected).length && emptyCandidate) {
            selected = emptyCandidate;
        }

        var activeViewId = state.activeViewId || (state.views && state.views.activeViewId) || fallbackActiveViewId || '';
        var liveObjects = apdGetLiveCanvasObjectsForCart(instance || null);
        // The visible Fabric canvas is the source of truth for the active view at
        // submit/export time. Store buckets can lag behind Fabric until the next
        // runtime sync, so always overwrite the active view when a canvas exists,
        // including with an empty array after deletions.
        if (liveObjects !== null) {
            selected[String(activeViewId || 'view-1')] = liveObjects;
        }
        return selected;
    }

    function apdGetRuntimeSnapshotsByViewFromState(state) {
        state = state && typeof state === 'object' ? state : {};
        var candidates = [
            state.snapshotsByView,
            state.snapshots && state.snapshots.snapshotsByView,
            state.viewSnapshots && state.viewSnapshots.snapshotsByView,
            state.viewSnapshots,
            state.snapshots
        ];
        for (var i = 0; i < candidates.length; i += 1) {
            var value = candidates[i];
            if (value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length) {
                return clonePlainObject(value);
            }
        }
        return {};
    }

    function apdBuildDocumentFromRuntimeState(instance, fallbackConfig) {
        var store = apdGetRuntimeStore(instance || null);
        var state = null;
        try {
            state = store && typeof store.getState === 'function' ? (store.getState() || {}) : {};
        } catch (error) {
            state = {};
        }

        fallbackConfig = fallbackConfig && typeof fallbackConfig === 'object' ? fallbackConfig : {};
        var views = apdGetRuntimeViewsFromState(state);
        if (!views.length && Array.isArray(fallbackConfig.views) && fallbackConfig.views.length) {
            views = clonePlainObject(fallbackConfig.views);
        }
        if (!views.length && fallbackConfig.views && typeof fallbackConfig.views === 'object' && Array.isArray(fallbackConfig.views.views)) {
            views = clonePlainObject(fallbackConfig.views.views);
        }
        if (!views.length) {
            return {};
        }

        var activeViewId = state.activeViewId || (state.views && state.views.activeViewId) || fallbackConfig.activeViewId || (fallbackConfig.views && fallbackConfig.views.activeViewId) || '';
        if (!activeViewId && views[0] && views[0].id != null) {
            activeViewId = String(views[0].id);
        }

        var objectsByView = apdGetRuntimeObjectsByViewFromState(state, instance, activeViewId);
        var snapshotsByView = apdGetRuntimeSnapshotsByViewFromState(state);
        if (!Object.keys(snapshotsByView).length && Object.keys(objectsByView).length) {
            snapshotsByView = {};
            Object.keys(objectsByView).forEach(function (viewId) {
                snapshotsByView[viewId] = { objects: clonePlainObject(objectsByView[viewId] || []) };
            });
        }

        var document = {
            views: {
                views: clonePlainObject(views),
                activeViewId: String(activeViewId || '')
            },
            activeViewId: String(activeViewId || '')
        };
        if (Object.keys(objectsByView).length) {
            document.objects = { byView: clonePlainObject(objectsByView) };
            document.objectsByView = clonePlainObject(objectsByView);
        }
        if (Object.keys(snapshotsByView).length) {
            document.snapshots = { snapshotsByView: clonePlainObject(snapshotsByView) };
        }
        if (state.selection && typeof state.selection === 'object') {
            document.selection = clonePlainObject(state.selection);
        }
        if (state.viewportByView && typeof state.viewportByView === 'object') {
            document.viewportByView = clonePlainObject(state.viewportByView);
        }
        if (state.drawingAreas && typeof state.drawingAreas === 'object') {
            document.drawingAreas = clonePlainObject(state.drawingAreas);
        } else if (fallbackConfig.drawingAreas && typeof fallbackConfig.drawingAreas === 'object') {
            document.drawingAreas = clonePlainObject(fallbackConfig.drawingAreas);
        }
        if (state.drawingAreasByView && typeof state.drawingAreasByView === 'object') {
            document.drawingAreasByView = clonePlainObject(state.drawingAreasByView);
        } else if (fallbackConfig.drawingAreasByView && typeof fallbackConfig.drawingAreasByView === 'object') {
            document.drawingAreasByView = clonePlainObject(fallbackConfig.drawingAreasByView);
        }
        if (Array.isArray(state.drawingZones) && state.drawingZones.length) {
            document.drawingZones = clonePlainObject(state.drawingZones);
        } else if (Array.isArray(fallbackConfig.drawingZones) && fallbackConfig.drawingZones.length) {
            document.drawingZones = clonePlainObject(fallbackConfig.drawingZones);
        }
        if (Array.isArray(state.elements) && state.elements.length) {
            document.elements = clonePlainObject(state.elements);
        } else if (Array.isArray(fallbackConfig.runtimeElements) && fallbackConfig.runtimeElements.length) {
            document.elements = clonePlainObject(fallbackConfig.runtimeElements);
        }
        return document;
    }

    function apdDocumentHasRestorableContent(document) {
        return !!(document && typeof document === 'object' && (countBootViews(document) > 0 || countPayloadObjects(document) > 0));
    }

    function apdBuildFullStateFallbackFromDocument(document, previousState, fallbackConfig) {
        if (!apdDocumentHasRestorableContent(document)) {
            return previousState && typeof previousState === 'object' ? previousState : {};
        }
        previousState = previousState && typeof previousState === 'object' ? clonePlainObject(previousState) : {};
        var next = Object.assign({}, previousState);
        return buildCanonicalFullState(next, document, fallbackConfig || {});
    }

    function exportState(instance) {
        flushInstanceForExport(instance);
        var bestValue = {};
        var bestScore = 0;
        var candidates = [
            function () { return instance && instance.util && instance.util.state && instance.util.state.exportFull && instance.util.state.exportFull(); }
        ];

        for (var i = 0; i < candidates.length; i += 1) {
            try {
                var value = candidates[i]();
                if (value && typeof value === 'object') {
                    var document = value.initialDocument || value.document || value.documentState || value;
                    var score = scoreRestorableDocumentPayload(document);
                    if (score > bestScore) {
                        bestScore = score;
                        bestValue = value;
                    }
                }
            } catch (error) {}
        }

        var fallbackDocument = apdBuildDocumentFromRuntimeState(instance || null, null);
        var fallbackScore = scoreRestorableDocumentPayload(fallbackDocument);
        if (fallbackScore > 0 && fallbackScore >= bestScore) {
            return apdBuildFullStateFallbackFromDocument(fallbackDocument, bestValue, null);
        }

        return bestValue && typeof bestValue === 'object' ? bestValue : {};
    }

    function extractPreviewFromState(state) {
        if (!state || typeof state !== 'object') {
            return '';
        }

        var activeViewId = state.activeViewId != null ? String(state.activeViewId) : '';
        var viewThumbnails = state.viewThumbnails && typeof state.viewThumbnails === 'object' ? state.viewThumbnails : null;
        if (viewThumbnails) {
            if (activeViewId && typeof viewThumbnails[activeViewId] === 'string' && viewThumbnails[activeViewId].indexOf('data:image/') === 0) {
                return viewThumbnails[activeViewId];
            }

            for (var key in viewThumbnails) {
                if (!Object.prototype.hasOwnProperty.call(viewThumbnails, key)) {
                    continue;
                }
                var candidate = typeof viewThumbnails[key] === 'string' ? viewThumbnails[key] : '';
                if (candidate.indexOf('data:image/') === 0) {
                    return candidate;
                }
            }
        }

        return '';
    }

    function canvasHasVisiblePixels(canvas) {
        if (!canvas || typeof canvas.getContext !== 'function') {
            return false;
        }
        try {
            var width = Math.max(1, Number(canvas.width || 0));
            var height = Math.max(1, Number(canvas.height || 0));
            var context = canvas.getContext('2d', { willReadFrequently: true });
            if (!context || typeof context.getImageData !== 'function') {
                return false;
            }
            var pixels = context.getImageData(0, 0, width, height).data;
            var pixelCount = Math.max(1, Math.floor(pixels.length / 4));
            var pixelStep = Math.max(1, Math.floor(pixelCount / 50000));
            for (var pixel = 3; pixel < pixels.length; pixel += pixelStep * 4) {
                if (pixels[pixel] > 2) {
                    return true;
                }
            }
        } catch (error) {}
        return false;
    }

    function exportVisibleDomCanvasPreview(shell) {
        var canvasSelectors = [
            'canvas[data-fabric="main"]',
            'canvas.lower-canvas',
            '.canvas-container canvas',
            'canvas'
        ];

        for (var i = 0; i < canvasSelectors.length; i += 1) {
            var canvas = shell.querySelector(canvasSelectors[i]);
            if (!canvas || typeof canvas.toDataURL !== 'function') {
                continue;
            }

            try {
                if (!canvasHasVisiblePixels(canvas)) {
                    continue;
                }
                var data = canvas.toDataURL('image/png');
                if (data && data.indexOf('data:image/') === 0) {
                    return data;
                }
            } catch (error) {}
        }

        return '';
    }

    function previewBlobToDataUrl(value) {
        if (typeof value === 'string') {
            return Promise.resolve(value);
        }
        if (!value || typeof FileReader === 'undefined') {
            return Promise.resolve('');
        }
        return new Promise(function (resolve) {
            try {
                var reader = new FileReader();
                reader.onload = function () {
                    resolve(typeof reader.result === 'string' ? reader.result : '');
                };
                reader.onerror = function () {
                    resolve('');
                };
                reader.readAsDataURL(value);
            } catch (error) {
                resolve('');
            }
        });
    }

    function previewDataUrlHasVisiblePixels(dataUrl) {
        if (!dataUrl || dataUrl.indexOf('data:image/') !== 0 || typeof Image === 'undefined') {
            return Promise.resolve(false);
        }
        return new Promise(function (resolve) {
            var image = new Image();
            image.onload = function () {
                try {
                    var width = Math.max(1, Number(image.naturalWidth || image.width || 1));
                    var height = Math.max(1, Number(image.naturalHeight || image.height || 1));
                    var ratio = Math.min(1, 96 / Math.max(width, height));
                    var sample = document.createElement('canvas');
                    sample.width = Math.max(1, Math.round(width * ratio));
                    sample.height = Math.max(1, Math.round(height * ratio));
                    var context = sample.getContext('2d', { willReadFrequently: true });
                    context.drawImage(image, 0, 0, sample.width, sample.height);
                    resolve(canvasHasVisiblePixels(sample));
                } catch (error) {
                    resolve(false);
                }
            };
            image.onerror = function () {
                resolve(false);
            };
            image.src = dataUrl;
        });
    }

    function commitShellPreview(shell, dataUrl) {
        if (!shell || !dataUrl || dataUrl.indexOf('data:image/') !== 0) {
            return '';
        }
        shell.__apdLastPreviewDataUrl = dataUrl;
        var previewDataField = shell.querySelector('[data-apd-preview-data]');
        if (previewDataField && previewDataField.value !== dataUrl) {
            previewDataField.value = dataUrl;
        }
        try {
            var event;
            if (typeof CustomEvent === 'function') {
                event = new CustomEvent('apd:preview-ready', { detail: { preview: dataUrl } });
            } else {
                event = document.createEvent('CustomEvent');
                event.initCustomEvent('apd:preview-ready', false, false, { preview: dataUrl });
            }
            shell.dispatchEvent(event);
        } catch (error) {}
        return dataUrl;
    }

    function captureRendererPreview(shell, instance) {
        if (!shell || !instance) {
            return Promise.resolve('');
        }
        var result = null;
        try {
            if (instance.api && typeof instance.api.exportPng === 'function') {
                result = instance.api.exportPng({ scale: 1 });
            } else if (instance.engine && instance.engine.exports && typeof instance.engine.exports.png === 'function') {
                result = instance.engine.exports.png({ scale: 1 });
            }
        } catch (error) {
            result = null;
        }
        return Promise.resolve(result)
            .then(previewBlobToDataUrl)
            .then(function (dataUrl) {
                return previewDataUrlHasVisiblePixels(dataUrl).then(function (visible) {
                    return visible ? dataUrl : '';
                });
            })
            .catch(function () {
                return '';
            });
    }

    function getRendererPreviewKind(shell, instance, state) {
        var candidates = [];
        try {
            if (instance && instance.api && instance.api.engine && typeof instance.api.engine.getKind === 'function') {
                candidates.push(instance.api.engine.getKind());
            }
        } catch (error) {}
        try {
            if (instance && instance.engine && instance.engine.kind) {
                candidates.push(instance.engine.kind);
            }
        } catch (error) {}
        if (state && typeof state === 'object') {
            candidates.push(state.activeRenderEngineKind, state.defaultRenderEngineKind);
        }

        var config = shell && shell.__apdCreateMountConfig && typeof shell.__apdCreateMountConfig === 'object'
            ? shell.__apdCreateMountConfig
            : (shell && shell.__apdMountConfig && typeof shell.__apdMountConfig === 'object' ? shell.__apdMountConfig : {});
        var documentPayload = state && typeof state === 'object'
            ? (state.initialDocument || state.document || state.documentState || state)
            : (config.initialDocument || config.document || config.documentState || config.initialState || {});
        var views = getPayloadViews(documentPayload);
        var activeViewId = String(
            documentPayload.activeViewId
            || (documentPayload.views && !Array.isArray(documentPayload.views) ? documentPayload.views.activeViewId : '')
            || state && state.activeViewId
            || ''
        ).trim();
        var activeView = null;
        for (var i = 0; i < views.length; i += 1) {
            if (!activeView || (activeViewId && String(views[i] && views[i].id || '') === activeViewId)) {
                activeView = views[i];
            }
            if (activeViewId && activeView && String(activeView.id || '') === activeViewId) {
                break;
            }
        }
        if (activeView && typeof activeView === 'object') {
            candidates.push(activeView.engine, activeView.renderEngine, activeView.engineKind);
        }
        candidates.push(config.defaultRenderEngineKind, config.renderEngine, config.engine);

        for (var candidateIndex = 0; candidateIndex < candidates.length; candidateIndex += 1) {
            var candidate = String(candidates[candidateIndex] || '').trim().toLowerCase();
            if (candidate === '3d' || candidate === 'babylon') {
                return '3d';
            }
            if (candidate === '2d' || candidate === 'fabric' || candidate === 'canvas') {
                return 'fabric';
            }
        }
        if (shell && shell.querySelector && shell.querySelector('canvas[data-asuka-3d-engine="babylon"]')) {
            return '3d';
        }
        return 'fabric';
    }

    function scheduleRendererPreview(shell, instance) {
        if (!shell || !instance) {
            return false;
        }
        var token = String(Date.now ? Date.now() : (new Date()).getTime()) + ':' + String(Math.random()).slice(2);
        shell.__apdPreviewCaptureToken = token;
        [100, 420, 1100].forEach(function (delay) {
            window.setTimeout(function () {
                if (!shell.isConnected || shell.__apdInstance !== instance || shell.__apdPreviewCaptureToken !== token) {
                    return;
                }
                var previewKind = getRendererPreviewKind(shell, instance, null);
                var canvasPreview = previewKind === 'fabric' ? exportVisibleDomCanvasPreview(shell) : '';
                if (canvasPreview) {
                    commitShellPreview(shell, canvasPreview);
                    return;
                }
                if (previewKind === 'fabric') {
                    if (renderLiveCanvasIfPopulated(instance || null)) {
                        canvasPreview = exportVisibleDomCanvasPreview(shell);
                        if (canvasPreview) {
                            commitShellPreview(shell, canvasPreview);
                        }
                    }
                    return;
                }
                captureRendererPreview(shell, instance).then(function (dataUrl) {
                    if (!shell.isConnected || shell.__apdInstance !== instance || shell.__apdPreviewCaptureToken !== token) {
                        return;
                    }
                    if (!dataUrl) {
                        dataUrl = exportVisibleDomCanvasPreview(shell);
                    }
                    if (dataUrl) {
                        commitShellPreview(shell, dataUrl);
                    }
                });
            }, delay);
        });
        return true;
    }

    function exportPreview(shell, state, instance) {
        var previewKind = getRendererPreviewKind(shell, instance || null, state || null);
        var canvasPreview = previewKind === 'fabric' ? exportVisibleDomCanvasPreview(shell) : '';
        scheduleRendererPreview(shell, instance || null);
        if (canvasPreview) {
            return canvasPreview;
        }

        var statePreview = extractPreviewFromState(state);
        if (statePreview) {
            return statePreview;
        }

        var thumbnail = shell.querySelector('.ask-theme-carousel-page__preview img, [class*="carousel-page__preview"] img');
        if (thumbnail && thumbnail.getAttribute('src') && thumbnail.getAttribute('src').indexOf('data:image/') === 0) {
            return thumbnail.getAttribute('src') || '';
        }

        return shell.__apdLastPreviewDataUrl || '';
    }

    function getPricingBreakdown(instance, basePrice) {
        var candidates = [
            function () { return instance && instance.api && typeof instance.api.getPriceUiBreakdown === 'function' ? instance.api.getPriceUiBreakdown(basePrice) : null; },
            function () { return instance && typeof instance.getPriceUiBreakdown === 'function' ? instance.getPriceUiBreakdown(basePrice) : null; },
            function () { return instance && instance.util && instance.util.pricing && typeof instance.util.pricing.getPriceUiBreakdown === 'function' ? instance.util.pricing.getPriceUiBreakdown(basePrice) : null; }
        ];

        for (var i = 0; i < candidates.length; i += 1) {
            try {
                var value = candidates[i]();
                if (value && typeof value === 'object') {
                    return value;
                }
            } catch (error) {}
        }

        return null;
    }

    function normalizePricingPayload(pricing, fallbackBase) {
        fallbackBase = typeof fallbackBase === 'number' ? fallbackBase : 0;
        if (!pricing || typeof pricing !== 'object') {
            pricing = {};
        }

        var display = pricing.display_breakdown && typeof pricing.display_breakdown === 'object'
            ? pricing.display_breakdown
            : (pricing.uiBreakdown && typeof pricing.uiBreakdown === 'object' ? pricing.uiBreakdown : {});

        var base = typeof pricing.base_price !== 'undefined' ? Number(pricing.base_price || 0) : null;
        if (base === null && typeof pricing.base !== 'undefined') { base = Number(pricing.base || 0); }
        if (base === null && typeof pricing.basePrice !== 'undefined') { base = Number(pricing.basePrice || 0); }
        if (base === null && typeof display.base_price !== 'undefined') { base = Number(display.base_price || 0); }
        if (base === null && typeof display.base !== 'undefined') { base = Number(display.base || 0); }
        if (base === null) { base = fallbackBase; }

        var total = typeof pricing.final_price !== 'undefined' ? Number(pricing.final_price || 0) : null;
        if (total === null && typeof pricing.total !== 'undefined') { total = Number(pricing.total || 0); }
        if (total === null && typeof display.final_price !== 'undefined') { total = Number(display.final_price || 0); }
        if (total === null && typeof display.total !== 'undefined') { total = Number(display.total || 0); }
        if (total === null) { total = base; }

        var adjustment = typeof pricing.adjustment_total !== 'undefined' ? Number(pricing.adjustment_total || 0) : null;
        if (adjustment === null && typeof pricing.adjustment !== 'undefined') { adjustment = Number(pricing.adjustment || 0); }
        if (adjustment === null && typeof display.adjustment_total !== 'undefined') { adjustment = Number(display.adjustment_total || 0); }
        if (adjustment === null && typeof display.adjustment !== 'undefined') { adjustment = Number(display.adjustment || 0); }
        if (adjustment === null) { adjustment = total - base; }

        return {
            payload_version: 1,
            success: typeof pricing.success === 'undefined' ? true : !!pricing.success,
            base_price: isFinite(base) ? base : fallbackBase,
            adjustment_total: isFinite(adjustment) ? adjustment : 0,
            final_price: isFinite(total) ? total : fallbackBase,
            fixed_fee: typeof pricing.fixed_fee !== 'undefined' ? Number(pricing.fixed_fee || 0) : Number(pricing.fixedFee || 0),
            designer_base_price: typeof pricing.designer_base_price !== 'undefined' ? Number(pricing.designer_base_price || 0) : Number(pricing.designerBasePrice || pricing.designerBase || 0),
            standard_price: typeof pricing.standard_price !== 'undefined' ? Number(pricing.standard_price || 0) : Number(pricing.standard || 0),
            rules_total: typeof pricing.rules_total !== 'undefined' ? Number(pricing.rules_total || 0) : Number(pricing.rules || 0),
            display_breakdown: {
                base_price: isFinite(base) ? base : fallbackBase,
                fixed_fee: typeof pricing.fixed_fee !== 'undefined' ? Number(pricing.fixed_fee || 0) : Number(pricing.fixedFee || 0),
                designer_base_price: typeof pricing.designer_base_price !== 'undefined' ? Number(pricing.designer_base_price || 0) : Number(pricing.designerBasePrice || pricing.designerBase || 0),
                standard_price: typeof pricing.standard_price !== 'undefined' ? Number(pricing.standard_price || 0) : Number(pricing.standard || 0),
                rules_total: typeof pricing.rules_total !== 'undefined' ? Number(pricing.rules_total || 0) : Number(pricing.rules || 0),
                adjustment_total: isFinite(adjustment) ? adjustment : 0,
                final_price: isFinite(total) ? total : fallbackBase
            },
            breakdown: Array.isArray(pricing.breakdown) ? pricing.breakdown : [],
            applied_rules: Array.isArray(pricing.applied_rules) ? pricing.applied_rules : (Array.isArray(pricing.appliedRules) ? pricing.appliedRules : []),
            warnings: Array.isArray(pricing.warnings) ? pricing.warnings : [],
            base: isFinite(base) ? base : fallbackBase,
            basePrice: isFinite(base) ? base : fallbackBase,
            adjustment: isFinite(adjustment) ? adjustment : 0,
            total: isFinite(total) ? total : fallbackBase,
            fixedFee: typeof pricing.fixed_fee !== 'undefined' ? Number(pricing.fixed_fee || 0) : Number(pricing.fixedFee || 0),
            designerBase: typeof pricing.designer_base_price !== 'undefined' ? Number(pricing.designer_base_price || 0) : Number(pricing.designerBasePrice || pricing.designerBase || 0),
            designerBasePrice: typeof pricing.designer_base_price !== 'undefined' ? Number(pricing.designer_base_price || 0) : Number(pricing.designerBasePrice || pricing.designerBase || 0),
            standard: typeof pricing.standard_price !== 'undefined' ? Number(pricing.standard_price || 0) : Number(pricing.standard || 0),
            rules: typeof pricing.rules_total !== 'undefined' ? Number(pricing.rules_total || 0) : Number(pricing.rules || 0),
            uiBreakdown: {
                base: isFinite(base) ? base : fallbackBase,
                designerBase: typeof pricing.designer_base_price !== 'undefined' ? Number(pricing.designer_base_price || 0) : Number(pricing.designerBasePrice || pricing.designerBase || 0),
                standard: typeof pricing.standard_price !== 'undefined' ? Number(pricing.standard_price || 0) : Number(pricing.standard || 0),
                rules: typeof pricing.rules_total !== 'undefined' ? Number(pricing.rules_total || 0) : Number(pricing.rules || 0),
                adjustment: isFinite(adjustment) ? adjustment : 0,
                total: isFinite(total) ? total : fallbackBase
            },
            appliedRules: Array.isArray(pricing.applied_rules) ? pricing.applied_rules : (Array.isArray(pricing.appliedRules) ? pricing.appliedRules : [])
        };
    }

    function setStatus(shell, message, tone) {
        var status = shell.querySelector('[data-apd-status]');
        if (!status) {
            return;
        }

        status.textContent = message;
        status.dataset.tone = tone || 'neutral';
    }

    function getPermissionController(instance) {
        if (!instance || !instance.util) {
            return null;
        }
        if (instance.util.permissions && typeof instance.util.permissions.can === 'function') {
            return instance.util.permissions;
        }
        return instance.util;
    }

    function canUsePermission(instance, key, options, fallbackConfig) {
        var permissions = fallbackConfig && fallbackConfig.permissions && typeof fallbackConfig.permissions === 'object'
            ? fallbackConfig.permissions
            : {};

        // The WordPress product-side permissions are the source of truth for the
        // customer runtime. If the product explicitly disables a capability, do
        // not let an older imported state or a stale designer controller reopen it.
        if (Object.prototype.hasOwnProperty.call(permissions, key) && permissions[key] === false) {
            return false;
        }

        var controller = getPermissionController(instance);
        if (controller && typeof controller.can === 'function') {
            try {
                return !!controller.can(key, options || {});
            } catch (error) {}
        }

        if (Object.prototype.hasOwnProperty.call(permissions, key)) {
            return !!permissions[key];
        }
        return true;
    }

    function getModulePermission(instance, moduleId, fallbackConfig) {
        var permissions = fallbackConfig && fallbackConfig.permissions && typeof fallbackConfig.permissions === 'object'
            ? fallbackConfig.permissions
            : {};
        var moduleOpen = permissions.moduleOpen && typeof permissions.moduleOpen === 'object' ? permissions.moduleOpen : {};
        if (Object.prototype.hasOwnProperty.call(moduleOpen, moduleId)) {
            return !!moduleOpen[moduleId];
        }
        return canUsePermission(instance, 'canOpenModule', { id: moduleId }, fallbackConfig);
    }

    function wrapPermissionedMethod(target, methodName, instance, permissionKey, optionsFactory, fallbackConfig) {
        if (!target || typeof target[methodName] !== 'function') {
            return;
        }
        if (target[methodName].__apdPermissionWrapped) {
            return;
        }
        var original = target[methodName];
        var wrapped = function () {
            var options = typeof optionsFactory === 'function' ? optionsFactory.apply(null, arguments) : (optionsFactory || {});
            if (!canUsePermission(instance, permissionKey, options, fallbackConfig)) {
                return undefined;
            }
            return original.apply(this, arguments);
        };
        wrapped.__apdPermissionWrapped = true;
        wrapped.__apdOriginal = original;
        target[methodName] = wrapped;
    }

    function applyRuntimePermissionGuards(shell, instance, config) {
        if (!shell || !instance || shell.__apdPermissionGuardsInstalled) {
            return;
        }

        wrapPermissionedMethod(instance.api, 'addText', instance, 'canAddText', null, config);
        wrapPermissionedMethod(instance.api, 'addRect', instance, 'canAddRect', null, config);
        wrapPermissionedMethod(instance.api, 'clearCanvas', instance, 'canClearCanvas', null, config);
        wrapPermissionedMethod(instance.api, 'undo', instance, 'canUndo', null, config);
        wrapPermissionedMethod(instance.api, 'redo', instance, 'canRedo', null, config);
        wrapPermissionedMethod(instance.api, 'reset', instance, 'canReset', null, config);
        wrapPermissionedMethod(instance.api, 'addView', instance, 'canAddView', null, config);
        wrapPermissionedMethod(instance.api, 'updateView', instance, 'canEditView', null, config);
        wrapPermissionedMethod(instance.api, 'removeView', instance, 'canDeleteView', null, config);
        wrapPermissionedMethod(instance.api, 'deleteView', instance, 'canDeleteView', null, config);
        wrapPermissionedMethod(instance.api, 'setActiveView', instance, 'canSwitchView', null, config);

        if (instance.layout && typeof instance.layout.openModule === 'function' && !instance.layout.openModule.__apdPermissionWrapped) {
            var originalOpenModule = instance.layout.openModule;
            var wrappedOpenModule = function (id) {
                var moduleId = String(id || '');
                if (!getModulePermission(instance, moduleId, config)) {
                    return undefined;
                }
                return originalOpenModule.apply(this, arguments);
            };
            wrappedOpenModule.__apdPermissionWrapped = true;
            wrappedOpenModule.__apdOriginal = originalOpenModule;
            instance.layout.openModule = wrappedOpenModule;
        }

        if (!shell.__apdPermissionKeydownHandler) {
            shell.__apdPermissionKeydownHandler = function (event) {
                if (!shell.isConnected) {
                    return;
                }
                var target = event.target;
                var activeInsideShell = !!(target && shell.contains(target));
                var focusedInsideShell = !!(document.activeElement && shell.contains(document.activeElement));
                if (!activeInsideShell && !focusedInsideShell) {
                    return;
                }

                var ctrlOrMeta = !!(event.ctrlKey || event.metaKey);
                var key = String(event.key || '').toLowerCase();

                if (ctrlOrMeta && key === 'z' && !event.shiftKey && !canUsePermission(instance, 'canUndo', null, config)) {
                    event.preventDefault();
                    event.stopPropagation();
                    return;
                }

                if (ctrlOrMeta && ((key === 'y') || (key === 'z' && event.shiftKey)) && !canUsePermission(instance, 'canRedo', null, config)) {
                    event.preventDefault();
                    event.stopPropagation();
                }
            };
            document.addEventListener('keydown', shell.__apdPermissionKeydownHandler, true);
        }

        shell.__apdPermissionGuardsInstalled = true;
    }

    function clonePlainObject(value) {
        if (!value || typeof value !== 'object') {
            return value;
        }
        try {
            return JSON.parse(JSON.stringify(value));
        } catch (error) {
            return value;
        }
    }

    function getPayloadActiveViewId(value, fallback) {
        fallback = fallback != null ? String(fallback) : '';
        if (!value || typeof value !== 'object') {
            return fallback;
        }
        if (value.activeViewId != null) {
            return String(value.activeViewId);
        }
        if (value.views && typeof value.views === 'object' && value.views.activeViewId != null) {
            return String(value.views.activeViewId);
        }
        if (value.document && typeof value.document === 'object') {
            return getPayloadActiveViewId(value.document, fallback);
        }
        if (value.initialDocument && typeof value.initialDocument === 'object') {
            return getPayloadActiveViewId(value.initialDocument, fallback);
        }
        if (value.documentState && typeof value.documentState === 'object') {
            return getPayloadActiveViewId(value.documentState, fallback);
        }
        return fallback;
    }

    function normalizeDrawingAreaZone(zone, fallbackViewId) {
        if (!zone || typeof zone !== 'object' || Array.isArray(zone)) {
            return null;
        }

        var next = clonePlainObject(zone) || {};
        var viewId = next.viewId != null ? String(next.viewId) : (fallbackViewId != null ? String(fallbackViewId) : '');
        if (viewId) {
            next.viewId = viewId;
        }
        if (!next.id && next.uid != null) {
            next.id = String(next.uid);
        }
        if (!next.id) {
            next.id = 'drawing-area-' + String(viewId || 'view') + '-' + String(Math.random()).slice(2);
        }

        if (next.left == null && next.x != null) next.left = next.x;
        if (next.top == null && next.y != null) next.top = next.y;
        if (next.x == null && next.left != null) next.x = next.left;
        if (next.y == null && next.top != null) next.y = next.top;

        ['left', 'top', 'x', 'y', 'width', 'height'].forEach(function (key) {
            if (next[key] == null || next[key] === '') {
                return;
            }
            var numeric = Number(next[key]);
            if (Number.isFinite(numeric)) {
                next[key] = numeric;
            }
        });

        return next;
    }

    function putDrawingZoneByView(target, zone, fallbackViewId) {
        var normalized = normalizeDrawingAreaZone(zone, fallbackViewId);
        if (!normalized) {
            return target;
        }
        var viewId = normalized.viewId != null ? String(normalized.viewId) : (fallbackViewId != null ? String(fallbackViewId) : '');
        if (!viewId) {
            viewId = '__default__';
        }
        if (!Array.isArray(target[viewId])) {
            target[viewId] = [];
        }
        target[viewId].push(normalized);
        return target;
    }

    function mergeDrawingAreasByView(target, source) {
        target = target && typeof target === 'object' && !Array.isArray(target) ? target : {};
        if (!source || typeof source !== 'object' || Array.isArray(source)) {
            return target;
        }
        safeObjectKeys(source).forEach(function (viewId) {
            var zones = Array.isArray(source[viewId]) ? source[viewId] : [];
            zones.forEach(function (zone) {
                putDrawingZoneByView(target, zone, viewId === '__default__' ? '' : viewId);
            });
        });
        return target;
    }

    function extractDrawingAreasByViewPayload(value, fallbackViewId, depth) {
        var byView = {};
        depth = depth || 0;
        if (!value || typeof value !== 'object' || depth > 5) {
            return byView;
        }

        var activeViewId = getPayloadActiveViewId(value, fallbackViewId || '');
        if (value.drawingAreasByView && typeof value.drawingAreasByView === 'object' && !Array.isArray(value.drawingAreasByView)) {
            mergeDrawingAreasByView(byView, value.drawingAreasByView);
        }
        if (value.drawingAreas && typeof value.drawingAreas === 'object' && !Array.isArray(value.drawingAreas)) {
            if (value.drawingAreas.byView && typeof value.drawingAreas.byView === 'object' && !Array.isArray(value.drawingAreas.byView)) {
                mergeDrawingAreasByView(byView, value.drawingAreas.byView);
            }
            if (Array.isArray(value.drawingAreas.zones)) {
                value.drawingAreas.zones.forEach(function (zone) {
                    putDrawingZoneByView(byView, zone, activeViewId);
                });
            }
        }
        if (Array.isArray(value.drawingAreas)) {
            value.drawingAreas.forEach(function (zone) {
                putDrawingZoneByView(byView, zone, activeViewId);
            });
        }
        if (Array.isArray(value.drawingZones)) {
            value.drawingZones.forEach(function (zone) {
                putDrawingZoneByView(byView, zone, activeViewId);
            });
        }

        ['document', 'initialDocument', 'documentState', 'state', 'legacy'].forEach(function (key) {
            if (value[key] && typeof value[key] === 'object') {
                mergeDrawingAreasByView(byView, extractDrawingAreasByViewPayload(value[key], activeViewId, depth + 1));
            }
        });

        return byView;
    }

    function flattenDrawingAreasByView(byView) {
        var zones = [];
        if (!byView || typeof byView !== 'object' || Array.isArray(byView)) {
            return zones;
        }
        safeObjectKeys(byView).forEach(function (viewId) {
            if (!Array.isArray(byView[viewId])) {
                return;
            }
            byView[viewId].forEach(function (zone) {
                var normalized = normalizeDrawingAreaZone(zone, viewId === '__default__' ? '' : viewId);
                if (normalized) {
                    zones.push(normalized);
                }
            });
        });
        return zones;
    }

    function payloadHasExplicitDrawingAreas(value, depth) {
        depth = depth || 0;
        if (!value || typeof value !== 'object' || depth > 5) {
            return false;
        }
        if (Object.prototype.hasOwnProperty.call(value, 'drawingAreasByView')
            || Object.prototype.hasOwnProperty.call(value, 'drawingZones')
            || Object.prototype.hasOwnProperty.call(value, 'drawingAreas')) {
            return true;
        }
        var nestedKeys = ['document', 'initialDocument', 'documentState', 'state', 'legacy'];
        for (var i = 0; i < nestedKeys.length; i += 1) {
            var key = nestedKeys[i];
            if (value[key] && typeof value[key] === 'object' && payloadHasExplicitDrawingAreas(value[key], depth + 1)) {
                return true;
            }
        }
        return false;
    }

    function createSnapshotFromDrawingZones(zones, views, fallbackActiveViewId) {
        zones = Array.isArray(zones) ? zones : [];
        var activeViewId = fallbackActiveViewId != null ? String(fallbackActiveViewId) : '';
        if (!activeViewId && Array.isArray(views) && views.length && views[0] && views[0].id != null) {
            activeViewId = String(views[0].id);
        }
        var byView = {};
        zones.forEach(function (zone) {
            putDrawingZoneByView(byView, zone, activeViewId);
        });
        if (!safeObjectKeys(byView).length) {
            return null;
        }
        return {
            activeViewId: activeViewId,
            drawingAreasByView: byView,
            zones: flattenDrawingAreasByView(byView)
        };
    }

    function mergeDrawingAreasIntoDocumentPayload(payload, snapshot) {
        if (!payload || typeof payload !== 'object' || !snapshot || !snapshot.drawingAreasByView) {
            return payload;
        }
        var byView = mergeDrawingAreasByView({}, snapshot.drawingAreasByView);
        var zones = flattenDrawingAreasByView(byView);
        var activeViewId = getPayloadActiveViewId(payload, snapshot.activeViewId || '');
        if (!activeViewId && snapshot.activeViewId) {
            activeViewId = String(snapshot.activeViewId);
        }
        payload.drawingAreasByView = byView;
        payload.drawingZones = zones;
        payload.drawingAreas = payload.drawingAreas && typeof payload.drawingAreas === 'object' && !Array.isArray(payload.drawingAreas) ? payload.drawingAreas : {};
        payload.drawingAreas.zones = byView[activeViewId] ? clonePlainObject(byView[activeViewId]) : (safeObjectKeys(byView).length === 1 ? clonePlainObject(byView[safeObjectKeys(byView)[0]]) : []);
        if (payload.drawingAreas.activeDrawingAreaId == null) {
            payload.drawingAreas.activeDrawingAreaId = null;
        }
        return payload;
    }

    function mergeDrawingAreasIntoStatePayload(payload, snapshot) {
        if (!payload || typeof payload !== 'object' || !snapshot || !snapshot.drawingAreasByView) {
            return payload;
        }
        mergeDrawingAreasIntoDocumentPayload(payload, snapshot);
        ['document', 'initialDocument', 'documentState'].forEach(function (key) {
            if (payload[key] && typeof payload[key] === 'object' && !Array.isArray(payload[key])) {
                mergeDrawingAreasIntoDocumentPayload(payload[key], snapshot);
            }
        });
        payload.scope = payload.scope && typeof payload.scope === 'object' && !Array.isArray(payload.scope) ? payload.scope : {};
        payload.scope.document = payload.scope.document && typeof payload.scope.document === 'object' && !Array.isArray(payload.scope.document) ? payload.scope.document : {};
        payload.scope.document.drawingAreas = true;
        return payload;
    }

    function mergeTopLevelDrawingZonesIntoBootPayload(config) {
        if (!config || typeof config !== 'object' || !Array.isArray(config.drawingZones) || !config.drawingZones.length) {
            return config;
        }
        var bootSource = (config.initialState && typeof config.initialState === 'object' ? config.initialState : null)
            || (config.initialDocument && typeof config.initialDocument === 'object' ? config.initialDocument : null)
            || config;
        var snapshot = createSnapshotFromDrawingZones(config.drawingZones, getPayloadViews(config), getPayloadActiveViewId(bootSource, ''));
        if (!snapshot) {
            return config;
        }
        if (config.initialDocument && typeof config.initialDocument === 'object') {
            mergeDrawingAreasIntoDocumentPayload(config.initialDocument, snapshot);
        }
        if (config.initialState && typeof config.initialState === 'object') {
            mergeDrawingAreasIntoStatePayload(config.initialState, snapshot);
        }
        return config;
    }

    function readCurrentDocumentSnapshot(instance) {
        if (!instance || !instance.util || !instance.util.state || typeof instance.util.state.exportPart !== 'function') {
            return null;
        }
        try {
            var exported = instance.util.state.exportPart('document');
            var document = exported && exported.document && typeof exported.document === 'object'
                ? exported.document
                : {};
            return {
                activeViewId: getPayloadActiveViewId(document, ''),
                objectsByView: clonePlainObject(getPayloadObjectsByView(document)) || {},
                drawingAreasByView: clonePlainObject(extractDrawingAreasByViewPayload(document, getPayloadActiveViewId(document, ''))) || {},
                viewportByView: clonePlainObject(document.viewportByView || {}) || {},
                elements: exported && exported.catalog && Array.isArray(exported.catalog.elements)
                    ? clonePlainObject(exported.catalog.elements)
                    : []
            };
        } catch (error) {}
        return null;
    }

    function buildDrawingAreaSnapshotFromPayload(instance, payload) {
        var byView = extractDrawingAreasByViewPayload(payload, getPayloadActiveViewId(payload, ''));
        var explicitDrawingAreas = payloadHasExplicitDrawingAreas(payload);
        if (!safeObjectKeys(byView).length && !explicitDrawingAreas) {
            return null;
        }

        var current = readCurrentDocumentSnapshot(instance) || {};
        var snapshot = current && typeof current === 'object' && !Array.isArray(current) ? current : {};
        var activeViewId = getPayloadActiveViewId(payload, snapshot.activeViewId || '');
        snapshot.activeViewId = activeViewId || snapshot.activeViewId || '';
        snapshot.drawingAreasByView = byView;

        if (!snapshot.objectsByView || typeof snapshot.objectsByView !== 'object' || Array.isArray(snapshot.objectsByView)) {
            snapshot.objectsByView = clonePlainObject(getPayloadObjectsByView(payload)) || {};
        }
        if (!snapshot.viewportByView || typeof snapshot.viewportByView !== 'object' || Array.isArray(snapshot.viewportByView)) {
            snapshot.viewportByView = clonePlainObject(payload && payload.viewportByView ? payload.viewportByView : {}) || {};
        }
        if (!Array.isArray(snapshot.elements)) {
            snapshot.elements = Array.isArray(payload && payload.elements) ? clonePlainObject(payload.elements) : [];
        }

        var viewIds = safeObjectKeys(byView);
        getPayloadViews(payload).forEach(function (view) {
            if (view && view.id != null) {
                viewIds.push(String(view.id));
            }
        });
        viewIds.forEach(function (viewId) {
            if (!Array.isArray(snapshot.objectsByView[viewId])) {
                snapshot.objectsByView[viewId] = [];
            }
        });

        return snapshot;
    }

    function applyDrawingAreaSnapshotPayload(instance, payload, reason) {
        if (!instance || !payload || typeof payload !== 'object') {
            return false;
        }
        var snapshot = buildDrawingAreaSnapshotFromPayload(instance, payload);
        if (!snapshot) {
            return false;
        }

        if (!instance.util || !instance.util.state || typeof instance.util.state.importPart !== 'function') {
            logApdVariationDebug('runtimeBridge:drawingAreas:snapshot-skip', {
                reason: reason || '',
                loader: 'unavailable',
                drawingAreasByViewKeys: safeObjectKeys(snapshot.drawingAreasByView)
            });
            return false;
        }

        try {
            var currentState = instance.util.state.exportPart('document');
            var nextState = buildCanonicalDocumentState(currentState, {});
            nextState.document = nextState.document && typeof nextState.document === 'object' ? nextState.document : {};
            nextState.document.drawingAreas = {
                byView: clonePlainObject(snapshot.drawingAreasByView || {}),
                zones: flattenDrawingAreasByView(snapshot.drawingAreasByView || {}),
                activeDrawingAreaId: snapshot.activeDrawingAreaId || null
            };
            nextState.scope.document.drawingAreas = true;
            instance.util.state.importPart('document', nextState, { replaceViews: true, replaceSnapshots: true });
            logApdVariationDebug('runtimeBridge:drawingAreas:snapshot-applied', {
                reason: reason || '',
                drawingAreasByViewKeys: safeObjectKeys(snapshot.drawingAreasByView),
                zones: flattenDrawingAreasByView(snapshot.drawingAreasByView).length
            });
            return true;
        } catch (error) {
            logApdVariationDebug('runtimeBridge:drawingAreas:snapshot-error', {
                reason: reason || '',
                message: error && error.message ? error.message : String(error)
            });
        }
        return false;
    }

    function payloadHasViews(payload) {
        if (!payload || typeof payload !== 'object') {
            return false;
        }
        if (Array.isArray(payload.views) && payload.views.length > 0) {
            return true;
        }
        if (payload.views && typeof payload.views === 'object' && Array.isArray(payload.views.views) && payload.views.views.length > 0) {
            return true;
        }
        var nestedKeys = ['document', 'initialDocument', 'state', 'legacy'];
        for (var i = 0; i < nestedKeys.length; i += 1) {
            var key = nestedKeys[i];
            if (payload[key] && payloadHasViews(payload[key])) {
                return true;
            }
        }
        return false;
    }

    function extractBootPayload(config) {
        config = config && typeof config === 'object' ? config : {};
        var initialDocument = config.initialDocument && typeof config.initialDocument === 'object'
            ? clonePlainObject(config.initialDocument)
            : null;

        // WordPress product/template configs expose the product document as
        // top-level `views` / `drawingZones`. AsukaDesigner's boot/import APIs do
        // not consume those top-level keys directly, so always lift them into an
        // initialDocument for the bridge. This keeps the product config as the
        // default source of truth while the cart only transports the customer
        // document delta.
        if (!initialDocument && Array.isArray(config.views) && config.views.length) {
            initialDocument = {
                views: clonePlainObject(config.views),
                activeViewId: config.activeViewId != null ? String(config.activeViewId || '') : '',
                drawingZones: Array.isArray(config.drawingZones) ? clonePlainObject(config.drawingZones) : [],
                drawingAreasByView: config.drawingAreasByView && typeof config.drawingAreasByView === 'object' ? clonePlainObject(config.drawingAreasByView) : {},
                drawingAreas: config.drawingAreas && typeof config.drawingAreas === 'object' ? clonePlainObject(config.drawingAreas) : undefined,
                objects: config.objects && typeof config.objects === 'object' ? clonePlainObject(config.objects) : undefined,
                objectsByView: config.objectsByView && typeof config.objectsByView === 'object' ? clonePlainObject(config.objectsByView) : undefined,
                documentObjectsByView: config.documentObjectsByView && typeof config.documentObjectsByView === 'object' ? clonePlainObject(config.documentObjectsByView) : undefined,
                snapshots: config.snapshots && typeof config.snapshots === 'object' ? clonePlainObject(config.snapshots) : undefined,
                snapshotsByView: config.snapshotsByView && typeof config.snapshotsByView === 'object' ? clonePlainObject(config.snapshotsByView) : undefined,
                viewSnapshots: config.viewSnapshots && typeof config.viewSnapshots === 'object' ? clonePlainObject(config.viewSnapshots) : undefined,
                canvas: config.canvas && typeof config.canvas === 'object' ? clonePlainObject(config.canvas) : undefined,
                viewportByView: config.viewportByView && typeof config.viewportByView === 'object' ? clonePlainObject(config.viewportByView) : undefined,
                documentViewportByView: config.documentViewportByView && typeof config.documentViewportByView === 'object' ? clonePlainObject(config.documentViewportByView) : undefined,
                selection: config.selection && typeof config.selection === 'object' ? clonePlainObject(config.selection) : undefined,
                scenes3d: config.scenes3d && typeof config.scenes3d === 'object' ? clonePlainObject(config.scenes3d) : undefined,
                document3dScenesByView: config.document3dScenesByView && typeof config.document3dScenesByView === 'object' ? clonePlainObject(config.document3dScenesByView) : undefined,
                asukaDocument: config.asukaDocument && typeof config.asukaDocument === 'object' ? clonePlainObject(config.asukaDocument) : undefined
            };
        }

        return {
            initialState: config.initialState && typeof config.initialState === 'object' ? clonePlainObject(config.initialState) : null,
            initialDocument: initialDocument ? normalizeDocumentHotStatePayload(initialDocument) : null
        };
    }

    function stripBootPayload(config) {
        var next = clonePlainObject(config || {});
        if (!next || typeof next !== 'object') {
            return {};
        }
        [
            'initialState',
            'initialDocument',
            'document',
            'documentState',
            'legacy',
            'views',
            'activeViewId',
            'drawingZones',
            'drawingAreas',
            'drawingAreasByView',
            'documentDrawingAreas',
            'documentDrawingAreasByView',
            'objects',
            'objectsByView',
            'documentObjectsByView',
            'snapshots',
            'snapshotsByView',
            'viewSnapshots',
            'canvas',
            'viewportByView',
            'documentViewportByView',
            'selection',
            'documentSelection',
            'fixedSlots',
            'fixedSlotActiveId'
        ].forEach(function (key) {
            delete next[key];
        });
        return next;
    }


    function stripStrictRuntimeConfigBucketsFromFullState(state) {
        var next = clonePlainObject(state || {});
        if (!next || typeof next !== 'object') {
            return {};
        }

        [
            'layout',
            'permissions',
            'permissionsByView',
            'moduleConfig',
            'modules',
            'catalog',
            'colors',
            'fonts',
            'printingMethods',
            'pricing',
            'price',
            'pricingRules',
            'priceFormat',
            'defaults',
            'upload',
            'tools',
            'configuration',
            'appearance',
            'ui'
        ].forEach(function (key) {
            if (Object.prototype.hasOwnProperty.call(next, key)) {
                delete next[key];
            }
        });

        if (next.scope && typeof next.scope === 'object') {
            next.scope = clonePlainObject(next.scope);
            ['layout', 'permissions', 'moduleConfig', 'modules', 'catalog', 'pricing', 'tools', 'configuration', 'appearance', 'ui'].forEach(function (key) {
                if (Object.prototype.hasOwnProperty.call(next.scope, key)) {
                    delete next.scope[key];
                }
            });
            if (!Object.keys(next.scope).length) {
                delete next.scope;
            }
        }

        if (next.legacy && typeof next.legacy === 'object') {
            next.legacy = clonePlainObject(next.legacy);
            if (next.legacy.state && typeof next.legacy.state === 'object') {
                next.legacy.state = clonePlainObject(next.legacy.state);
                ['layout', 'permissions', 'permissionsByView', 'moduleConfig', 'modules', 'catalog', 'colors', 'fonts', 'printingMethods', 'pricing', 'price', 'pricingRules', 'priceFormat', 'defaults', 'upload', 'tools', 'configuration', 'appearance', 'ui'].forEach(function (key) {
                    if (Object.prototype.hasOwnProperty.call(next.legacy.state, key)) {
                        delete next.legacy.state[key];
                    }
                });
            }
        }

        return next;
    }

    function applyStrictRuntimeConfigAfterVariationFullState(shell, instance, options) {
        options = options || {};
        if (!shell || !instance) {
            return false;
        }
        var desiredConfig = getShellStrictRuntimeConfig(shell);
        if (!desiredConfig || typeof desiredConfig !== 'object' || !Object.keys(desiredConfig).length) {
            desiredConfig = shell.__apdCreateMountConfig || shell.__apdMountConfig || {};
        }
        var desiredLayout = desiredConfig && desiredConfig.layout && typeof desiredConfig.layout === 'object'
            ? normalizeRuntimeLayout(desiredConfig.layout)
            : {};
        var beforeLayout = getExportedRuntimeLayout(instance || null);
        var layoutApplied = false;
        if (Object.keys(desiredLayout).length) {
            layoutApplied = applyRuntimeLayout(instance, beforeLayout, desiredLayout);
        }

        var strictConfigApplied = false;
        var strictConfigPayload = {};
        ['moduleConfig', 'catalog', 'colors', 'printingMethods', 'pricing', 'pricingRules', 'priceFormat', 'permissions'].forEach(function (key) {
            if (desiredConfig && Object.prototype.hasOwnProperty.call(desiredConfig, key)) {
                strictConfigPayload[key] = clonePlainObject(desiredConfig[key]);
            }
        });
        if (desiredConfig && Object.prototype.hasOwnProperty.call(desiredConfig, 'price')) {
            strictConfigPayload.price = Number(desiredConfig.price) || 0;
        }
        if (Object.keys(strictConfigPayload).length) {
            try {
                var importerHost = instance && instance.util && typeof instance.util.importConfig === 'function'
                    ? instance.util
                    : (instance && instance.api && typeof instance.api.importConfig === 'function' ? instance.api : null);
                if (importerHost && typeof importerHost.importConfig === 'function') {
                    importerHost.importConfig(strictConfigPayload);
                    strictConfigApplied = true;
                }
                var catalogApplyPayload = Object.assign({}, strictConfigPayload);
                if (desiredConfig && desiredConfig.initialState && typeof desiredConfig.initialState === 'object') {
                    catalogApplyPayload.initialState = clonePlainObject(desiredConfig.initialState);
                }
                if (desiredConfig && desiredConfig.initialDocument && typeof desiredConfig.initialDocument === 'object') {
                    catalogApplyPayload.initialDocument = clonePlainObject(desiredConfig.initialDocument);
                }
                if (desiredConfig && Array.isArray(desiredConfig.runtimeElements) && desiredConfig.runtimeElements.length) {
                    catalogApplyPayload.runtimeElements = clonePlainObject(desiredConfig.runtimeElements);
                }
                if (shell && Array.isArray(shell.__apdRuntimeElementDefinitions) && shell.__apdRuntimeElementDefinitions.length) {
                    catalogApplyPayload.elements = apdMergeElementDefinitionGroups([
                        Array.isArray(catalogApplyPayload.elements) ? catalogApplyPayload.elements : [],
                        shell.__apdRuntimeElementDefinitions
                    ]);
                }
                if (apdApplyRuntimeCatalogAndModuleConfigToInstance(instance, catalogApplyPayload)) {
                    strictConfigApplied = true;
                }
                if (apdApplyRuntimePermissionsToInstance(instance, strictConfigPayload.permissions)) {
                    strictConfigApplied = true;
                }
            } catch (error) {}
        }

        logApdVariationDebug('runtimeBridge:strictVariationConfig:afterFullState', {
            source: options.source || '',
            key: options.key || '',
            layoutApplied: layoutApplied,
            strictConfigApplied: strictConfigApplied,
            desiredLayout: summarizeLayoutDebug(desiredLayout),
            beforeLayout: summarizeLayoutDebug(beforeLayout),
            afterLayout: summarizeLayoutDebug(getExportedRuntimeLayout(instance || null)),
            config: summarizeMountPayload(desiredConfig || {})
        });
        return layoutApplied || strictConfigApplied;
    }


    function normalizeApdMenuIconName(icon, fallbackKind) {
        var value = typeof icon === 'string' ? icon.trim() : '';
        if (!value && fallbackKind) {
            value = String(fallbackKind || '').trim();
        }
        if (!value) {
            return '';
        }
        if (value.indexOf('url:') === 0 || value.indexOf('svg:') === 0 || /^https?:\/\//i.test(value) || /^\/\//.test(value) || value.charAt(0) === '/') {
            return value;
        }
        var normalized = value.toLowerCase().replace(/\s+/g, '-').replace(/_/g, '-');
        if (['crop', 'drawingareas', 'drawing-area', 'drawing-areas'].indexOf(normalized) !== -1) {
            return 'drawing-areas';
        }
        return value;
    }

    function normalizeRuntimeLayout(layout) {
        return layout && typeof layout === 'object' && !Array.isArray(layout) ? layout : {};
    }

    function normalizeRuntimeLayoutItem(item, fallbackZone) {
        item = item && typeof item === 'object' ? item : {};
        var zone = ['left', 'right', 'top', 'bottom'].indexOf(String(item.zone || fallbackZone || 'left')) !== -1
            ? String(item.zone || fallbackZone || 'left')
            : 'left';
        var id = String(item.id || item.kind || '');
        var kind = String(item.kind || item.id || '');
        var normalized = {
            id: id,
            kind: kind,
            label: typeof item.label === 'string' && item.label ? item.label : String(item.kind || item.id || ''),
            icon: normalizeApdMenuIconName(item.icon, kind || id || 'puzzle'),
            zone: zone,
            type: typeof item.type === 'string' && item.type ? item.type : 'floating',
            collapsed: !!item.collapsed,
            collapsible: item.collapsible !== false,
            order: Number.isFinite(Number(item.order)) ? Number(item.order) : null
        };
        var mountTarget = typeof item.mountTarget === 'string' ? item.mountTarget.trim() : '';
        if (mountTarget) {
            normalized.mountTarget = mountTarget;
        }
        if (item.renderMode === 'inline' || item.renderMode === 'portal') {
            normalized.renderMode = item.renderMode;
        }
        return normalized;
    }

    function collectRuntimeLayoutItems(layout) {
        layout = normalizeRuntimeLayout(layout);
        var map = {};
        ['left', 'right', 'top', 'bottom'].forEach(function (zone) {
            var zoneConfig = layout[zone] && typeof layout[zone] === 'object' ? layout[zone] : {};
            var items = Array.isArray(zoneConfig.items) ? zoneConfig.items : [];
            items.forEach(function (item, index) {
                var normalized = normalizeRuntimeLayoutItem(item, zone);
                if (normalized.id) {
                    normalized.index = index;
                    if (normalized.order === null) {
                        normalized.order = index;
                    }
                    map[normalized.id] = normalized;
                }
            });
        });
        return map;
    }

    function setRuntimeZoneCollapsible(instance, zone, value) {
        if (!instance || !zone) {
            return false;
        }
        if (instance.layout && typeof instance.layout.setZoneCollapsible === 'function') {
            try {
                instance.layout.setZoneCollapsible(zone, !!value);
                return true;
            } catch (error) {
                return false;
            }
        }
        if (instance.store && typeof instance.store.getState === 'function') {
            try {
                var storeState = instance.store.getState();
                if (storeState && typeof storeState.setZoneCollapsible === 'function') {
                    storeState.setZoneCollapsible(zone, !!value);
                    return true;
                }
            } catch (error) {
                return false;
            }
        }
        return false;
    }

    function applyRuntimeLayout(instance, currentLayout, desiredLayout) {
        if (!instance || !instance.layout || !desiredLayout || typeof desiredLayout !== 'object') {
            return false;
        }

        var layoutApi = instance.layout;
        if (typeof layoutApi.addItem !== 'function' || typeof layoutApi.removeItem !== 'function') {
            return false;
        }

        var normalizedCurrent = normalizeRuntimeLayout(currentLayout);
        var normalizedDesired = normalizeRuntimeLayout(desiredLayout);
        var currentMap = collectRuntimeLayoutItems(normalizedCurrent);
        var desiredMap = collectRuntimeLayoutItems(normalizedDesired);
        var hasUpdateItem = typeof layoutApi.updateItem === 'function';
        var hasMoveBlock = typeof layoutApi.moveBlock === 'function';
        var hasSetBlockCollapsed = typeof layoutApi.setBlockCollapsed === 'function';
        var hasSetBlockCollapsible = typeof layoutApi.setBlockCollapsible === 'function';
        var hasSetZoneType = typeof layoutApi.setZoneType === 'function';
        var hasSetZoneCollapsed = typeof layoutApi.setZoneCollapsed === 'function';

        ['left', 'right', 'top', 'bottom'].forEach(function (zone) {
            var currentZone = normalizedCurrent[zone] && typeof normalizedCurrent[zone] === 'object' ? normalizedCurrent[zone] : {};
            var desiredZone = normalizedDesired[zone] && typeof normalizedDesired[zone] === 'object' ? normalizedDesired[zone] : {};
            if (hasSetZoneType && desiredZone.type !== undefined && currentZone.type !== desiredZone.type) {
                try { layoutApi.setZoneType(zone, desiredZone.type); } catch (error) {}
            }
            if (hasSetZoneCollapsed && desiredZone.collapsed !== undefined && !!currentZone.collapsed !== !!desiredZone.collapsed) {
                try { layoutApi.setZoneCollapsed(zone, !!desiredZone.collapsed); } catch (error) {}
            }
            if (desiredZone.collapsible !== undefined && (currentZone.collapsible !== false) !== (desiredZone.collapsible !== false)) {
                setRuntimeZoneCollapsible(instance, zone, desiredZone.collapsible !== false);
            }
        });

        Object.keys(currentMap).forEach(function (key) {
            if (!desiredMap[key]) {
                try { layoutApi.removeItem(key); } catch (error) {}
            }
        });

        ['left', 'right', 'top', 'bottom'].forEach(function (zone) {
            var desiredZone = normalizedDesired[zone] && typeof normalizedDesired[zone] === 'object' ? normalizedDesired[zone] : {};
            var items = Array.isArray(desiredZone.items) ? desiredZone.items : [];
            items.forEach(function (item, index) {
                var nextItem = normalizeRuntimeLayoutItem(item, zone);
                if (!nextItem.id) {
                    return;
                }
                var previousItem = currentMap[nextItem.id] || null;
                if (!previousItem) {
                    try {
                        layoutApi.addItem(nextItem.zone, {
                            id: nextItem.id,
                            kind: nextItem.kind,
                            label: nextItem.label,
                            icon: nextItem.icon,
                            zone: nextItem.zone,
                            type: nextItem.type,
                            mountTarget: nextItem.mountTarget || undefined,
                            renderMode: nextItem.renderMode || undefined,
                            collapsed: nextItem.collapsed,
                            collapsible: nextItem.collapsible
                        }, index);
                    } catch (error) {}
                    return;
                }

                if (previousItem.zone !== nextItem.zone) {
                    try { layoutApi.removeItem(nextItem.id); } catch (error) {}
                    try {
                        layoutApi.addItem(nextItem.zone, {
                            id: nextItem.id,
                            kind: nextItem.kind,
                            label: nextItem.label,
                            icon: nextItem.icon,
                            zone: nextItem.zone,
                            type: nextItem.type,
                            mountTarget: nextItem.mountTarget || undefined,
                            renderMode: nextItem.renderMode || undefined,
                            collapsed: nextItem.collapsed,
                            collapsible: nextItem.collapsible
                        }, index);
                    } catch (error) {}
                    return;
                }

                if (hasUpdateItem) {
                    var patch = {};
                    if (previousItem.label !== nextItem.label) patch.label = nextItem.label;
                    if (previousItem.icon !== nextItem.icon) patch.icon = nextItem.icon;
                    if (previousItem.type !== nextItem.type) patch.type = nextItem.type;
                    if (String(previousItem.mountTarget || '') !== String(nextItem.mountTarget || '')) {
                        patch.mountTarget = nextItem.mountTarget || null;
                    }
                    if (String(previousItem.renderMode || '') !== String(nextItem.renderMode || '')) {
                        patch.renderMode = nextItem.renderMode || null;
                    }
                    if (Object.keys(patch).length) {
                        try { layoutApi.updateItem(nextItem.id, patch); } catch (error) {}
                    }
                }

                if (hasSetBlockCollapsed && previousItem.collapsed !== nextItem.collapsed) {
                    try { layoutApi.setBlockCollapsed(nextItem.id, nextItem.collapsed); } catch (error) {}
                }
                if (hasSetBlockCollapsible && previousItem.collapsible !== nextItem.collapsible) {
                    try { layoutApi.setBlockCollapsible(nextItem.id, nextItem.collapsible); } catch (error) {}
                } else if (hasUpdateItem && previousItem.collapsible !== nextItem.collapsible) {
                    try { layoutApi.updateItem(nextItem.id, { collapsible: nextItem.collapsible }); } catch (error) {}
                }
            });
        });

        ['left', 'right', 'top', 'bottom'].forEach(function (zone) {
            var desiredZone = normalizedDesired[zone] && typeof normalizedDesired[zone] === 'object' ? normalizedDesired[zone] : {};
            var items = Array.isArray(desiredZone.items) ? desiredZone.items : [];
            items.forEach(function (item, index) {
                var nextItem = normalizeRuntimeLayoutItem(item, zone);
                if (!nextItem.id) {
                    return;
                }
                if (hasMoveBlock) {
                    try { layoutApi.moveBlock(nextItem.id, nextItem.zone, index); } catch (error) {}
                } else if (hasUpdateItem) {
                    try { layoutApi.updateItem(nextItem.id, { order: index }); } catch (error) {}
                }
            });
        });

        return true;
    }


    function countBootViews(value) {
        if (!value || typeof value !== 'object') {
            return 0;
        }

        // exportDocument()/documentState can expose views either as a direct array
        // (`views: [...]`) or as the canonical modular bucket
        // (`views: { views: [...], activeViewId }`). The previous check only
        // handled the array shape, so a successful importDocument() was rejected
        // as empty and the bridge then tried fallback strategies that could blank
        // the canvas. Keep this helper aligned with payloadHasViews().
        if (Array.isArray(value.views)) {
            return value.views.length;
        }
        if (value.views && typeof value.views === 'object' && Array.isArray(value.views.views)) {
            return value.views.views.length;
        }
        if (value.document && typeof value.document === 'object') {
            return countBootViews(value.document);
        }
        if (value.initialDocument && typeof value.initialDocument === 'object') {
            return countBootViews(value.initialDocument);
        }
        if (value.documentState && typeof value.documentState === 'object') {
            return countBootViews(value.documentState);
        }
        if (value.legacy && typeof value.legacy === 'object') {
            return countBootViews(value.legacy);
        }
        if (value.state && typeof value.state === 'object') {
            return countBootViews(value.state);
        }
        return 0;
    }


    function getPayloadViews(value) {
        if (!value || typeof value !== 'object') {
            return [];
        }
        if (Array.isArray(value.views)) {
            return value.views;
        }
        if (value.views && typeof value.views === 'object' && Array.isArray(value.views.views)) {
            return value.views.views;
        }
        return [];
    }

    function getPayloadSnapshotsByView(value) {
        if (!value || typeof value !== 'object') {
            return {};
        }
        var canvas = value.canvas && typeof value.canvas === 'object' && !Array.isArray(value.canvas) ? value.canvas : null;
        var candidates = [
            value.snapshotsByView,
            value.snapshots && value.snapshots.snapshotsByView,
            value.viewSnapshots && value.viewSnapshots.snapshotsByView,
            value.viewSnapshots,
            canvas && canvas.snapshotsByView,
            canvas && canvas.snapshots && canvas.snapshots.snapshotsByView,
            canvas && canvas.viewSnapshots && canvas.viewSnapshots.snapshotsByView,
            canvas && canvas.viewSnapshots,
            value.snapshots
        ];
        for (var i = 0; i < candidates.length; i += 1) {
            var candidate = candidates[i];
            if (candidate && typeof candidate === 'object' && !Array.isArray(candidate) && safeObjectKeys(candidate).length) {
                return candidate;
            }
        }
        return {};
    }

    function deriveObjectsByViewFromSnapshots(snapshotsByView, baseByView) {
        var next = baseByView && typeof baseByView === 'object' && !Array.isArray(baseByView) ? clonePlainObject(baseByView) : {};
        snapshotsByView = snapshotsByView && typeof snapshotsByView === 'object' && !Array.isArray(snapshotsByView) ? snapshotsByView : {};
        safeObjectKeys(snapshotsByView).forEach(function (viewId) {
            if (Array.isArray(next[viewId]) && next[viewId].length) {
                return;
            }
            var snapshot = snapshotsByView[viewId];
            if (snapshot && typeof snapshot === 'object' && Array.isArray(snapshot.objects)) {
                next[viewId] = clonePlainObject(snapshot.objects);
            }
        });
        return next;
    }

    function getPayloadRootObjects(value) {
        if (!value || typeof value !== 'object') {
            return [];
        }
        var canvas = value.canvas && typeof value.canvas === 'object' && !Array.isArray(value.canvas) ? value.canvas : null;
        if (Array.isArray(value.objects)) {
            return value.objects;
        }
        if (value.objects && typeof value.objects === 'object' && Array.isArray(value.objects.objects)) {
            return value.objects.objects;
        }
        if (canvas && Array.isArray(canvas.objects)) {
            return canvas.objects;
        }
        if (canvas && canvas.objects && typeof canvas.objects === 'object' && Array.isArray(canvas.objects.objects)) {
            return canvas.objects.objects;
        }
        return [];
    }

    function getPayloadFallbackViewId(value) {
        var viewId = getPayloadActiveViewId(value, '');
        if (viewId) {
            return viewId;
        }
        var views = getPayloadViews(value);
        if (views[0] && typeof views[0] === 'object' && views[0].id != null) {
            return String(views[0].id);
        }
        return 'view-1';
    }

    function getPayloadObjectsByView(value) {
        if (!value || typeof value !== 'object') {
            return {};
        }
        var canvas = value.canvas && typeof value.canvas === 'object' && !Array.isArray(value.canvas) ? value.canvas : null;
        var candidates = [
            value.objects && !Array.isArray(value.objects) && value.objects.byView,
            value.documentObjectsByView,
            value.objectsByView,
            value.byView,
            canvas && canvas.objects && !Array.isArray(canvas.objects) && canvas.objects.byView,
            canvas && canvas.documentObjectsByView,
            canvas && canvas.objectsByView,
            canvas && canvas.byView
        ];
        var selected = {};
        for (var i = 0; i < candidates.length; i += 1) {
            var candidate = candidates[i];
            if (candidate && typeof candidate === 'object' && !Array.isArray(candidate) && safeObjectKeys(candidate).length) {
                selected = clonePlainObject(candidate) || {};
                break;
            }
        }

        selected = deriveObjectsByViewFromSnapshots(getPayloadSnapshotsByView(value), selected);

        // Important for WooCommerce/cart restore: some exports are plain Fabric
        // JSON snapshots (`objects: [...]`) decorated with Asuka view metadata.
        // Counting saw those objects, but the runtime loader only reads
        // objectsByView/documentObjectsByView, so the active view was created
        // with an empty canvas. Map root Fabric objects to the active view.
        var rootObjects = getPayloadRootObjects(value);
        if (rootObjects.length) {
            var fallbackViewId = getPayloadFallbackViewId(value);
            if (!Array.isArray(selected[fallbackViewId]) || !selected[fallbackViewId].length) {
                selected[fallbackViewId] = clonePlainObject(rootObjects);
            }
        }

        return selected && typeof selected === 'object' && !Array.isArray(selected) ? selected : {};
    }


    function payloadHasDirectViews(value) {
        return getPayloadViews(value || {}).length > 0;
    }

    function countPayloadOwnObjects(value) {
        if (!value || typeof value !== 'object') {
            return 0;
        }

        var count = 0;
        var objectsByView = getPayloadObjectsByView(value);
        safeObjectKeys(objectsByView).forEach(function (key) {
            if (Array.isArray(objectsByView[key])) {
                count += objectsByView[key].length;
            }
        });

        var snapshotsByView = getPayloadSnapshotsByView(value);
        safeObjectKeys(snapshotsByView).forEach(function (key) {
            if (Array.isArray(objectsByView[key]) && objectsByView[key].length) {
                return;
            }
            var snapshot = snapshotsByView[key];
            if (snapshot && Array.isArray(snapshot.objects)) {
                count += snapshot.objects.length;
            }
        });

        return count;
    }

    function countPayloadObjects(value) {
        if (!value || typeof value !== 'object') {
            return 0;
        }

        var count = 0;
        var objectsByView = getPayloadObjectsByView(value);
        safeObjectKeys(objectsByView).forEach(function (key) {
            if (Array.isArray(objectsByView[key])) {
                count += objectsByView[key].length;
            }
        });

        var snapshotsByView = getPayloadSnapshotsByView(value);
        safeObjectKeys(snapshotsByView).forEach(function (key) {
            if (Array.isArray(objectsByView[key]) && objectsByView[key].length) {
                return;
            }
            var snapshot = snapshotsByView[key];
            if (snapshot && Array.isArray(snapshot.objects)) {
                count += snapshot.objects.length;
            }
        });

        ['document', 'initialDocument', 'documentState'].forEach(function (key) {
            if (value[key] && typeof value[key] === 'object') {
                count += countPayloadObjects(value[key]);
            }
        });

        if (value.legacy && typeof value.legacy === 'object') {
            count += countPayloadObjects(value.legacy.document || null);
            count += countPayloadObjects(value.legacy.state || null);
        }

        return count;
    }


    function normalizeDocumentHotStatePayload(value) {
        if (!value || typeof value !== 'object') {
            return null;
        }

        var source = value;
        // New canonical contract: a cart/resume document is the document itself.
        // Runtime/full-state wrappers may still be passed internally by exportState(),
        // so unwrap them before writing/importing. This is an adapter, not a persisted
        // legacy shape.
        if (!payloadHasDirectViews(source)) {
            if (source.document && typeof source.document === 'object') {
                source = source.document;
            } else if (source.initialDocument && typeof source.initialDocument === 'object') {
                source = source.initialDocument;
            }
        }

        var views = getPayloadViews(source);
        var activeViewId = getPayloadActiveViewId(source, '');
        if (!activeViewId && views[0] && typeof views[0] === 'object' && views[0].id != null) {
            activeViewId = String(views[0].id);
        }

        var snapshotsByView = getPayloadSnapshotsByView(source);
        var objectsByView = deriveObjectsByViewFromSnapshots(snapshotsByView, getPayloadObjectsByView(source));
        var rootObjects = getPayloadRootObjects(source);
        if (rootObjects.length) {
            var fallbackViewId = activeViewId || getPayloadFallbackViewId(source);
            if (!Array.isArray(objectsByView[fallbackViewId]) || !objectsByView[fallbackViewId].length) {
                objectsByView[fallbackViewId] = clonePlainObject(rootObjects);
            }
        }

        var drawingAreasByView = extractDrawingAreasByViewPayload(source, activeViewId || '');
        var selection = source.selection && typeof source.selection === 'object'
            ? clonePlainObject(source.selection)
            : { activeObjectIds: [], activeDrawingAreaId: source.activeDrawingAreaId || null };

        var document = {
            schemaVersion: 1,
            views: {
                views: clonePlainObject(views || []),
                activeViewId: String(activeViewId || '')
            },
            activeViewId: String(activeViewId || '')
        };

        if (safeObjectKeys(objectsByView).length) {
            document.objects = { byView: clonePlainObject(objectsByView) };
        }
        if (source.viewportByView && typeof source.viewportByView === 'object' && !Array.isArray(source.viewportByView)) {
            document.viewportByView = clonePlainObject(source.viewportByView);
        } else if (source.documentViewportByView && typeof source.documentViewportByView === 'object' && !Array.isArray(source.documentViewportByView)) {
            document.viewportByView = clonePlainObject(source.documentViewportByView);
        }
        if (safeObjectKeys(drawingAreasByView).length) {
            document.drawingAreas = {
                byView: clonePlainObject(drawingAreasByView),
                activeDrawingAreaId: selection.activeDrawingAreaId || null
            };
        }
        if (selection && typeof selection === 'object') {
            document.selection = selection;
        }
        var neutralDocument = source.asukaDocument && typeof source.asukaDocument === 'object' && !Array.isArray(source.asukaDocument)
            ? source.asukaDocument
            : null;
        var scenes3d = source.scenes3d && typeof source.scenes3d === 'object' && !Array.isArray(source.scenes3d)
            ? source.scenes3d
            : (source.document3dScenesByView && typeof source.document3dScenesByView === 'object' && !Array.isArray(source.document3dScenesByView)
                ? source.document3dScenesByView
                : (neutralDocument && neutralDocument.scenes3d && typeof neutralDocument.scenes3d === 'object' && !Array.isArray(neutralDocument.scenes3d)
                    ? neutralDocument.scenes3d
                    : null));
        if (scenes3d && safeObjectKeys(scenes3d).length) {
            document.scenes3d = clonePlainObject(scenes3d);
        }
        if (neutralDocument) {
            document.asukaDocument = clonePlainObject(neutralDocument);
        }
        if (Array.isArray(source.elements) && source.elements.length) {
            document.elements = clonePlainObject(source.elements);
        }
        if (Array.isArray(source.fixedSlots) && source.fixedSlots.length) {
            document.fixedSlots = clonePlainObject(source.fixedSlots);
            document.fixedSlotActiveId = source.fixedSlotActiveId || null;
        }

        return document;
    }

    function collectHotDocumentCandidates(value, source, results, depth) {
        results = results || [];
        depth = depth || 0;
        if (!value || typeof value !== 'object' || depth > 5) {
            return results;
        }

        var normalized = normalizeDocumentHotStatePayload(value) || value;
        if (payloadHasDirectViews(normalized)) {
            results.push({
                source: source || 'payload',
                payload: normalized,
                viewsCount: getPayloadViews(normalized).length,
                objectCount: countPayloadOwnObjects(normalized),
                topKeys: safeObjectKeys(normalized)
            });
        }

        var nested = [
            ['initialDocument', value.initialDocument],
            ['documentState', value.documentState],
            ['document', value.document],
            ['state', value.state],
            ['legacy.document', value.legacy && value.legacy.document],
            ['legacy.state', value.legacy && value.legacy.state]
        ];
        nested.forEach(function (entry) {
            if (entry[1] && typeof entry[1] === 'object') {
                collectHotDocumentCandidates(entry[1], (source ? source + '.' : '') + entry[0], results, depth + 1);
            }
        });

        return results;
    }

    function chooseBestHotDocumentPayload(bootPayload) {
        var candidates = [];
        collectHotDocumentCandidates(bootPayload && bootPayload.initialDocument, 'initialDocument', candidates, 0);
        collectHotDocumentCandidates(bootPayload && bootPayload.initialState, 'initialState', candidates, 0);

        if (!candidates.length) {
            return null;
        }

        var hasObjectCandidate = candidates.some(function (candidate) {
            return candidate.objectCount > 0;
        });

        candidates.sort(function (a, b) {
            if (hasObjectCandidate && a.objectCount !== b.objectCount) {
                return b.objectCount - a.objectCount;
            }
            if (a.viewsCount !== b.viewsCount) {
                return b.viewsCount - a.viewsCount;
            }
            if (a.source === 'initialDocument' && b.source !== 'initialDocument') {
                return -1;
            }
            if (b.source === 'initialDocument' && a.source !== 'initialDocument') {
                return 1;
            }
            return String(a.source).localeCompare(String(b.source));
        });

        logApdVariationDebug('runtimeBridge:hotDocumentCandidates', {
            candidates: candidates.map(function (candidate) {
                return {
                    source: candidate.source,
                    viewsCount: candidate.viewsCount,
                    objectCount: candidate.objectCount,
                    topKeys: candidate.topKeys
                };
            }),
            selected: {
                source: candidates[0].source,
                viewsCount: candidates[0].viewsCount,
                objectCount: candidates[0].objectCount,
                topKeys: candidates[0].topKeys
            }
        });

        return candidates[0].payload;
    }

    function bootPayloadHasViews(bootPayload) {
        if (!bootPayload || typeof bootPayload !== 'object') {
            return false;
        }
        return countBootViews(bootPayload.initialState) > 0 || countBootViews(bootPayload.initialDocument) > 0;
    }

    function getBootPayloadExpectedDocument(bootPayload) {
        if (!bootPayload || typeof bootPayload !== 'object') {
            return null;
        }
        return chooseBestHotDocumentPayload(bootPayload)
            || bootPayload.initialDocument
            || (bootPayload.initialState && typeof bootPayload.initialState === 'object'
                ? (bootPayload.initialState.document || bootPayload.initialState.initialDocument || bootPayload.initialState.documentState)
                : null);
    }


    function isRuntimeCanvasHelperObject(object) {
        if (!object || typeof object !== 'object') {
            return true;
        }
        var role = String(object._asukaRole || object.role || (object.data && object.data.role) || '').trim().toLowerCase();
        var source = String(object._asukaSourceModule || object.sourceModule || '').trim().toLowerCase();
        if (role === 'drawingzone' || role === 'drawing-zone' || role === 'drawingarea' || role === 'drawing-area' || role === 'drawingareadraft' || role === 'drawing-area-draft' || role === 'tool' || role === 'guide' || role === 'snapline' || role === 'snap-line' || role === 'selectionoutline' || role === 'selection-outline') {
            return true;
        }
        if (source === 'drawing-areas' && (object.excludeFromExport || object.evented === false)) {
            return true;
        }
        return false;
    }

    function countLiveCanvasUserObjects(instance) {
        if (!instance || !instance.api) {
            return 0;
        }
        try {
            var objects = typeof instance.api.listObjects === 'function'
                ? instance.api.listObjects()
                : (typeof instance.api.getObjects === 'function' ? instance.api.getObjects() : []);
            return (objects || []).filter(function (object) {
                return !isRuntimeCanvasHelperObject(object);
            }).length;
        } catch (error) {
            return 0;
        }
    }

    function renderLiveCanvasIfPopulated(instance) {
        return countLiveCanvasUserObjects(instance || null) > 0;
    }

    function getDocumentObjectsForCanvasRestore(documentPayload, targetViewId) {
        var payload = normalizeDocumentHotStatePayload(documentPayload) || documentPayload || {};
        var byView = getPayloadObjectsByView(payload);
        byView = byView && typeof byView === 'object' && !Array.isArray(byView) ? byView : {};
        var viewId = targetViewId != null && String(targetViewId || '') ? String(targetViewId || '') : getPayloadActiveViewId(payload, '');
        if (viewId && Array.isArray(byView[viewId]) && byView[viewId].length) {
            return clonePlainObject(byView[viewId]);
        }
        var keys = safeObjectKeys(byView).filter(function (key) {
            return Array.isArray(byView[key]) && byView[key].length;
        });
        if (keys.length === 1) {
            return clonePlainObject(byView[keys[0]]);
        }
        if (keys.length) {
            return clonePlainObject(byView[keys[0]]);
        }
        return [];
    }

    function syncRuntimeStoreObjectsForCanvasRestore(instance, documentPayload, objects, targetViewId) {
        if (!instance || !Array.isArray(objects) || !objects.length) {
            return;
        }
        var viewId = targetViewId != null && String(targetViewId || '') ? String(targetViewId || '') : getPayloadActiveViewId(documentPayload || {}, '');
        if (!viewId) {
            return;
        }
        try {
            if (instance.store && typeof instance.store.getState === 'function') {
                var state = instance.store.getState();
                if (state && typeof state.setDocumentObjectsForView === 'function') {
                    state.setDocumentObjectsForView(String(viewId), clonePlainObject(objects));
                }
            }
        } catch (error) {}
        try {
            if (instance.store && typeof instance.store.setState === 'function') {
                instance.store.setState(function (current) {
                    current = current && typeof current === 'object' ? current : {};
                    var currentByView = current.documentObjectsByView && typeof current.documentObjectsByView === 'object' && !Array.isArray(current.documentObjectsByView)
                        ? clonePlainObject(current.documentObjectsByView)
                        : {};
                    currentByView[String(viewId)] = clonePlainObject(objects);
                    return { documentObjectsByView: currentByView, activeViewId: String(viewId) };
                });
            }
        } catch (error) {}
    }

    function forceCanvasFromDocumentPayload(instance, documentPayload, reason, targetViewId, onComplete) {
        if (!instance || !instance.util || !instance.util.state || typeof instance.util.state.importPart !== 'function') {
            if (typeof onComplete === 'function') {
                onComplete(false);
            }
            return false;
        }
        try {
            var canonicalState = buildCanonicalDocumentState(documentPayload || {}, {});
            instance.util.state.importPart('document', canonicalState, { replaceViews: true, replaceSnapshots: true });
            instance.util.state.rebuildActiveViewFromDocument(targetViewId || getPayloadActiveViewId(documentPayload || {}, ''));
            window.setTimeout(function () {
                var success = countPayloadObjects(documentPayload || {}) === 0 || countLiveCanvasUserObjects(instance || null) > 0;
                if (typeof onComplete === 'function') {
                    onComplete(success);
                }
            }, 0);
            return true;
        } catch (error) {
            logApdVariationDebug('runtimeBridge:forceCanvasFromDocumentPayload:error', {
                reason: reason || '',
                message: error && error.message ? error.message : String(error)
            });
            if (typeof onComplete === 'function') {
                onComplete(false);
            }
            return false;
        }
    }

    function scheduleForcedDocumentCanvasRestore(shell, instance, documentPayload, reason) {
        if (!documentPayload || typeof documentPayload !== 'object' || countPayloadObjects(documentPayload) <= 0) {
            return false;
        }
        shell = shell || null;
        var token = String(Date.now ? Date.now() : (new Date()).getTime()) + ':' + String(Math.random()).slice(2);
        if (shell) {
            shell.__apdForcedCanvasRestoreToken = token;
        }
        var activeViewId = getPayloadActiveViewId(documentPayload || {}, '');
        [0, 200, 750, 1500, 3000, 5000].forEach(function (delay) {
            window.setTimeout(function () {
                if (shell && shell.__apdForcedCanvasRestoreToken !== token) {
                    return;
                }
                var liveInstance = (shell && shell.__apdInstance) || instance || null;
                if (!liveInstance) {
                    return;
                }
                if (shell && shell.__apdCanvasRestoreInFlight) {
                    return;
                }
                var storeApplied = applyDocumentExactlyToRuntimeStore(liveInstance || null, documentPayload || {}, 'forced-document-watchdog:' + String(reason || '') + ':' + String(delay));
                var attemptToken = token + ':' + String(delay);
                if (shell) {
                    shell.__apdCanvasRestoreInFlight = attemptToken;
                }
                var canvasApplied = forceCanvasFromDocumentPayload(liveInstance || null, documentPayload || {}, 'forced-canvas-watchdog:' + String(reason || '') + ':' + String(delay), activeViewId, function (success) {
                    if (shell && shell.__apdCanvasRestoreInFlight === attemptToken) {
                        shell.__apdCanvasRestoreInFlight = '';
                    }
                    if (success && shell && shell.__apdForcedCanvasRestoreToken === token) {
                        shell.__apdForcedCanvasRestoreToken = '';
                    }
                });
                if (!canvasApplied && shell && shell.__apdCanvasRestoreInFlight === attemptToken) {
                    shell.__apdCanvasRestoreInFlight = '';
                }
                logApdVariationDebug('runtimeBridge:forcedDocumentWatchdog:applied', {
                    reason: reason || '',
                    delay: delay,
                    activeViewId: activeViewId,
                    storeApplied: !!storeApplied,
                    canvasApplied: !!canvasApplied,
                    expectedDocument: summarizeViewContainer(documentPayload || {}),
                    afterDocument: summarizeViewContainer(exportDesign(liveInstance || null)),
                    afterCanvasObjects: countLiveCanvasUserObjects(liveInstance || null)
                });
            }, delay);
        });
        return true;
    }


    function apdMergeRestorableDocumentIntoFullStatePayload(fullStatePayload, documentPayload, reason) {
        if (!fullStatePayload || typeof fullStatePayload !== 'object' || !documentPayload || typeof documentPayload !== 'object') {
            return fullStatePayload;
        }
        var normalizedDocument = normalizeDocumentHotStatePayload(documentPayload) || documentPayload;
        var existingDocument = fullStatePayload.document && typeof fullStatePayload.document === 'object'
            ? fullStatePayload.document
            : (fullStatePayload.initialDocument && typeof fullStatePayload.initialDocument === 'object'
                ? fullStatePayload.initialDocument
                : (fullStatePayload.documentState && typeof fullStatePayload.documentState === 'object' ? fullStatePayload.documentState : null));
        var incomingObjects = countPayloadObjects(normalizedDocument || {});
        var existingObjects = countPayloadObjects(existingDocument || {});
        var incomingViews = countBootViews(normalizedDocument || {});
        if (incomingViews <= 0 || incomingObjects <= existingObjects) {
            return fullStatePayload;
        }
        fullStatePayload.document = clonePlainObject(normalizedDocument);
        fullStatePayload.initialDocument = clonePlainObject(normalizedDocument);
        fullStatePayload.scope = fullStatePayload.scope && typeof fullStatePayload.scope === 'object' ? fullStatePayload.scope : {};
        fullStatePayload.scope.document = {
            views: true,
            drawingAreas: true,
            snapshots: true,
            objects: true,
            selection: true,
            viewportByView: true
        };
        return fullStatePayload;
    }

    function scheduleCanvasRestoreWatchdog(shell, instance, documentPayload, reason) {
        if (!documentPayload || typeof documentPayload !== 'object' || countPayloadObjects(documentPayload) <= 0) {
            return false;
        }
        shell = shell || null;
        var token = String(Date.now ? Date.now() : (new Date()).getTime()) + ':' + String(Math.random()).slice(2);
        if (shell) {
            shell.__apdCanvasRestoreWatchdogToken = token;
        }
        // Let AsukaDesigner finish its own Fabric boot first. Starting a raw
        // fallback load at 0 ms races the renderer's element/image hydration
        // and can replace a healthy in-progress canvas with an empty frame.
        var delays = [900, 1800, 3200];
        delays.forEach(function (delay) {
            window.setTimeout(function () {
                if (shell && shell.__apdCanvasRestoreWatchdogToken !== token) {
                    return;
                }
                var liveInstance = (shell && shell.__apdInstance) || instance || null;
                if (!liveInstance) {
                    return;
                }
                if (renderLiveCanvasIfPopulated(liveInstance || null)) {
                    if (shell && shell.__apdCanvasRestoreWatchdogToken === token) {
                        shell.__apdCanvasRestoreWatchdogToken = '';
                    }
                    return;
                }
                var canvasObjects = countLiveCanvasUserObjects(liveInstance || null);
                if (canvasObjects > 0) {
                    if (shell && shell.__apdCanvasRestoreWatchdogToken === token) {
                        shell.__apdCanvasRestoreWatchdogToken = '';
                    }
                    return;
                }
                if (shell && shell.__apdCanvasRestoreInFlight) {
                    return;
                }
                var activeViewId = getPayloadActiveViewId(documentPayload || {}, '');
                var attemptToken = token + ':' + String(delay);
                if (shell) {
                    shell.__apdCanvasRestoreInFlight = attemptToken;
                }
                var started = forceCanvasFromDocumentPayload(liveInstance || null, documentPayload || {}, 'watchdog:' + String(reason || '') + ':' + String(delay), activeViewId, function (success) {
                    if (shell && shell.__apdCanvasRestoreInFlight === attemptToken) {
                        shell.__apdCanvasRestoreInFlight = '';
                    }
                    if (success && shell && shell.__apdCanvasRestoreWatchdogToken === token) {
                        shell.__apdCanvasRestoreWatchdogToken = '';
                    }
                });
                if (!started && shell && shell.__apdCanvasRestoreInFlight === attemptToken) {
                    shell.__apdCanvasRestoreInFlight = '';
                }
            }, delay);
        });
        return true;
    }

    function runtimeDocumentSatisfiesExpectedPayload(instance, expectedPayload) {
        if (!expectedPayload || typeof expectedPayload !== 'object') {
            return true;
        }

        var expectedViews = countBootViews(expectedPayload);
        var expectedObjects = countPayloadObjects(expectedPayload);
        if (expectedViews <= 0 && expectedObjects <= 0) {
            return true;
        }

        var afterDocument = exportDesign(instance || null);
        var afterState = exportState(instance || null);
        var afterStateDocument = afterState && typeof afterState === 'object'
            ? (afterState.initialDocument || afterState.document || afterState.documentState || afterState)
            : null;
        var afterViews = Math.max(countBootViews(afterDocument), countBootViews(afterStateDocument));
        var afterObjects = Math.max(countPayloadObjects(afterDocument), countPayloadObjects(afterStateDocument));
        var afterCanvasObjects = countLiveCanvasUserObjects(instance || null);

        return !(expectedViews > 0 && afterViews <= 0)
            && !(expectedObjects > 0 && afterObjects <= 0)
            && !(expectedObjects > 0 && afterCanvasObjects <= 0);
    }

    function bootPayloadRestoreSatisfied(instance, bootPayload) {
        return runtimeDocumentSatisfiesExpectedPayload(instance || null, getBootPayloadExpectedDocument(bootPayload));
    }


    function extractBootViewsPayload(value) {
        if (!value || typeof value !== 'object') {
            return null;
        }

        if (Array.isArray(value.views)) {
            return {
                views: value.views,
                activeViewId: value.activeViewId != null ? String(value.activeViewId) : ''
            };
        }

        if (value.views && typeof value.views === 'object' && Array.isArray(value.views.views)) {
            return {
                views: value.views.views,
                activeViewId: value.views.activeViewId != null ? String(value.views.activeViewId) : (value.activeViewId != null ? String(value.activeViewId) : '')
            };
        }

        var nestedKeys = ['document', 'initialDocument', 'state', 'legacy'];
        for (var i = 0; i < nestedKeys.length; i += 1) {
            var key = nestedKeys[i];
            var found = extractBootViewsPayload(value[key]);
            if (found && Array.isArray(found.views) && found.views.length) {
                return found;
            }
        }

        return null;
    }

    function normalizeBootViewsForStore(bootPayload) {
        var source = extractBootViewsPayload(bootPayload && bootPayload.initialState)
            || extractBootViewsPayload(bootPayload && bootPayload.initialDocument);
        if (!source || !Array.isArray(source.views) || !source.views.length) {
            return null;
        }

        var seen = {};
        var views = [];
        source.views.forEach(function (view, index) {
            if (!view || typeof view !== 'object') {
                return;
            }
            var id = view.id != null ? String(view.id) : '';
            if (!id) {
                id = 'view-' + String(index + 1);
            }
            if (seen[id]) {
                return;
            }
            seen[id] = true;
            views.push(Object.assign({}, clonePlainObject(view), { id: id }));
        });

        if (!views.length) {
            return null;
        }

        var activeViewId = source.activeViewId && views.some(function (view) { return String(view.id) === String(source.activeViewId); })
            ? String(source.activeViewId)
            : String(views[0].id);

        return { views: views, activeViewId: activeViewId };
    }

    function enforceBootViews(instance, bootPayload) {
        if (!instance || !instance.store || typeof instance.store.setState !== 'function') {
            return false;
        }

        var normalized = normalizeBootViewsForStore(bootPayload);
        if (!normalized) {
            return false;
        }

        try {
            instance.store.setState(function () {
                return {
                    views: normalized.views,
                    documentViews: normalized.views,
                    activeViewId: normalized.activeViewId
                };
            });
            return true;
        } catch (error) {
            return false;
        }
    }

    function getDocumentViewsForStore(documentPayload) {
        var payload = normalizeDocumentHotStatePayload(documentPayload) || documentPayload;
        if (!payloadHasDirectViews(payload)) {
            payload = chooseBestHotDocumentPayload({
                initialDocument: documentPayload,
                initialState: documentPayload
            }) || payload;
        }
        var source = extractBootViewsPayload(payload);
        if (!source || !Array.isArray(source.views) || !source.views.length) {
            return null;
        }

        var seen = {};
        var views = [];
        source.views.forEach(function (view, index) {
            if (!view || typeof view !== 'object') {
                return;
            }
            var id = view.id != null ? String(view.id) : '';
            if (!id) {
                id = 'view-' + String(index + 1);
            }
            if (seen[id]) {
                return;
            }
            seen[id] = true;
            views.push(Object.assign({}, clonePlainObject(view), { id: id }));
        });

        if (!views.length) {
            return null;
        }

        var activeViewId = source.activeViewId && views.some(function (view) { return String(view.id) === String(source.activeViewId); })
            ? String(source.activeViewId)
            : String(views[0].id);

        return { views: views, activeViewId: activeViewId, payload: payload };
    }

    function getDocumentObjectsForStore(documentPayload) {
        var payload = normalizeDocumentHotStatePayload(documentPayload) || documentPayload || {};
        var byView = getPayloadObjectsByView(payload);
        var next = byView && typeof byView === 'object' && !Array.isArray(byView) ? clonePlainObject(byView) : {};
        var snapshotsByView = getPayloadSnapshotsByView(payload);
        safeObjectKeys(snapshotsByView).forEach(function (viewId) {
            if (Array.isArray(next[viewId]) && next[viewId].length) {
                return;
            }
            var snapshot = snapshotsByView[viewId];
            if (snapshot && Array.isArray(snapshot.objects)) {
                next[viewId] = clonePlainObject(snapshot.objects);
            }
        });
        return next;
    }

    function getDocumentDrawingAreasForStore(documentPayload, activeViewId) {
        var payload = normalizeDocumentHotStatePayload(documentPayload) || documentPayload || {};
        if (payload.drawingAreas && typeof payload.drawingAreas === 'object' && Array.isArray(payload.drawingAreas.zones)) {
            return clonePlainObject(payload.drawingAreas.zones);
        }
        if (Array.isArray(payload.drawingZones)) {
            return clonePlainObject(payload.drawingZones);
        }
        var byView = extractDrawingAreasByViewPayload(payload, activeViewId || '');
        if (byView && typeof byView === 'object') {
            if (activeViewId && Array.isArray(byView[activeViewId])) {
                return clonePlainObject(byView[activeViewId]);
            }
            return flattenDrawingAreasByView(byView);
        }
        return [];
    }

    function getDocumentViewportByViewForStore(documentPayload) {
        var payload = normalizeDocumentHotStatePayload(documentPayload) || documentPayload || {};
        var candidates = [
            payload.viewportByView,
            payload.documentViewportByView,
            payload.viewport && payload.viewport.byView
        ];
        for (var i = 0; i < candidates.length; i += 1) {
            var candidate = candidates[i];
            if (candidate && typeof candidate === 'object' && !Array.isArray(candidate)) {
                return clonePlainObject(candidate);
            }
        }
        return {};
    }

    function getDocumentDrawingAreasByViewForStore(documentPayload, activeViewId) {
        var payload = normalizeDocumentHotStatePayload(documentPayload) || documentPayload || {};
        var byView = extractDrawingAreasByViewPayload(payload, activeViewId || '');
        return byView && typeof byView === 'object' && !Array.isArray(byView) ? clonePlainObject(byView) : {};
    }

    function buildRuntimeDocumentActionSnapshot(documentPayload) {
        var normalizedViews = getDocumentViewsForStore(documentPayload);
        if (!normalizedViews) {
            return null;
        }

        var payload = normalizedViews.payload || normalizeDocumentHotStatePayload(documentPayload) || documentPayload || {};
        var activeViewId = normalizedViews.activeViewId;
        var objectsByView = getDocumentObjectsForStore(payload);
        var viewportByView = getDocumentViewportByViewForStore(payload);
        var drawingAreasByView = getDocumentDrawingAreasByViewForStore(payload, activeViewId);
        var selection = payload.selection && typeof payload.selection === 'object'
            ? clonePlainObject(payload.selection)
            : { activeObjectIds: [], activeDrawingAreaId: payload.activeDrawingAreaId || null };

        var snapshot = {
            views: clonePlainObject(normalizedViews.views || []),
            documentViews: clonePlainObject(normalizedViews.views || []),
            activeViewId: activeViewId,
            objectsByView: clonePlainObject(objectsByView || {}),
            documentObjectsByView: clonePlainObject(objectsByView || {}),
            viewportByView: clonePlainObject(viewportByView || {}),
            documentViewportByView: clonePlainObject(viewportByView || {}),
            selection: clonePlainObject(selection || {}),
            documentSelection: clonePlainObject(selection || {}),
            drawingAreasByView: clonePlainObject(drawingAreasByView || {})
        };

        if (Array.isArray(payload.elements)) {
            snapshot.elements = clonePlainObject(payload.elements);
        }
        if (Array.isArray(payload.fixedSlots)) {
            snapshot.fixedSlots = clonePlainObject(payload.fixedSlots);
            snapshot.fixedSlotActiveId = payload.fixedSlotActiveId || null;
        }

        return {
            views: normalizedViews.views,
            activeViewId: activeViewId,
            payload: payload,
            snapshot: snapshot,
            objectsByView: objectsByView,
            drawingAreasByView: drawingAreasByView,
            viewportByView: viewportByView,
            selection: selection
        };
    }

    function prepareRuntimeDocumentViewsForActionImport(instance, normalized) {
        if (!instance || !normalized || !Array.isArray(normalized.views) || !normalized.views.length) {
            return false;
        }

        var activeViewId = normalized.activeViewId || (normalized.views[0] && normalized.views[0].id != null ? String(normalized.views[0].id) : '');
        var applied = false;
        try {
            if (instance.store && typeof instance.store.setState === 'function') {
                instance.store.setState(function () {
                    return {
                        views: clonePlainObject(normalized.views),
                        documentViews: clonePlainObject(normalized.views),
                        activeViewId: activeViewId
                    };
                });
                applied = true;
            }
        } catch (error) {}

        try {
            var state = instance.store && typeof instance.store.getState === 'function' ? instance.store.getState() : null;
            if (state && typeof state.setDocumentViews === 'function') {
                state.setDocumentViews(clonePlainObject(normalized.views));
                applied = true;
            }
        } catch (error) {}

        return applied;
    }

    function applyRuntimeDocumentActionSnapshot(instance, documentPayload, methodPrefix) {
        if (!instance || !instance.util || !instance.util.state || typeof instance.util.state.importPart !== 'function') {
            return null;
        }

        var normalized = buildRuntimeDocumentActionSnapshot(documentPayload);
        if (!normalized) {
            return null;
        }
        var method = (methodPrefix ? String(methodPrefix) + ':' : '') + 'util.state.importPart(document)';
        try {
            var canonicalState = buildCanonicalDocumentState(normalized.payload, {});
            instance.util.state.importPart('document', canonicalState, { replaceViews: true, replaceSnapshots: true });
            rebuildActiveViewFromImportedPayload(instance, normalized.activeViewId);
            return { method: method, instance: instance, normalized: normalized };
        } catch (error) {
            return null;
        }
    }

    function applyDocumentExactlyToRuntimeStore(instance, documentPayload, reason) {
        if (!instance || !instance.store || typeof instance.store.setState !== 'function') {
            return false;
        }

        var normalizedViews = getDocumentViewsForStore(documentPayload);
        if (!normalizedViews) {
            return false;
        }

        var payload = normalizedViews.payload || normalizeDocumentHotStatePayload(documentPayload) || documentPayload || {};
        var activeViewId = normalizedViews.activeViewId;
        var objectsByView = getDocumentObjectsForStore(payload);
        var drawingAreas = getDocumentDrawingAreasForStore(payload, activeViewId);
        var drawingAreasByView = getDocumentDrawingAreasByViewForStore(payload, activeViewId);
        var viewportByView = getDocumentViewportByViewForStore(payload);
        var selection = payload.selection && typeof payload.selection === 'object'
            ? clonePlainObject(payload.selection)
            : { activeObjectIds: [], activeDrawingAreaId: payload.activeDrawingAreaId || null };

        try {
            instance.store.setState(function () {
                var patch = {
                    views: clonePlainObject(normalizedViews.views || []),
                    documentViews: clonePlainObject(normalizedViews.views || []),
                    activeViewId: String(activeViewId || ''),
                    objectsByView: clonePlainObject(objectsByView || {}),
                    documentObjectsByView: clonePlainObject(objectsByView || {}),
                    drawingAreasByView: clonePlainObject(drawingAreasByView || {}),
                    documentDrawingAreasByView: clonePlainObject(drawingAreasByView || {}),
                    documentDrawingAreas: clonePlainObject(drawingAreas || []),
                    viewportByView: clonePlainObject(viewportByView || {}),
                    documentViewportByView: clonePlainObject(viewportByView || {}),
                    selection: clonePlainObject(selection || {}),
                    documentSelection: clonePlainObject(selection || {})
                };
                if (Array.isArray(payload.elements)) {
                    patch.elements = clonePlainObject(payload.elements);
                }
                if (Array.isArray(payload.fixedSlots)) {
                    patch.fixedSlots = clonePlainObject(payload.fixedSlots);
                    patch.fixedSlotActiveId = payload.fixedSlotActiveId || null;
                }
                return patch;
            });
        } catch (error) {
            return false;
        }

        try {
            var state = instance.store && typeof instance.store.getState === 'function' ? instance.store.getState() : null;
            if (state && typeof state.setDocumentViews === 'function') {
                state.setDocumentViews(clonePlainObject(normalizedViews.views || []), String(activeViewId || ''));
            }
            if (state && typeof state.setActiveView === 'function') {
                state.setActiveView(String(activeViewId || ''));
            }
            if (state && typeof state.setDocumentObjectsForView === 'function') {
                Object.keys(objectsByView || {}).forEach(function (viewId) {
                    state.setDocumentObjectsForView(String(viewId), clonePlainObject(objectsByView[viewId] || []));
                });
            }
            if (state && typeof state.setDocumentDrawingAreas === 'function') {
                state.setDocumentDrawingAreas(clonePlainObject(drawingAreas || []));
            }
            if (state && typeof state.setDocumentViewportForView === 'function') {
                Object.keys(viewportByView || {}).forEach(function (viewId) {
                    state.setDocumentViewportForView(String(viewId), clonePlainObject(viewportByView[viewId] || {}));
                });
            }
            if (state && typeof state.setDocumentSelection === 'function') {
                state.setDocumentSelection(clonePlainObject(selection || {}));
            }
        } catch (error) {}

        var expectedObjects = countPayloadObjects(payload);
        var canvasForced = false;
        if (expectedObjects > 0) {
            canvasForced = forceCanvasFromDocumentPayload(instance || null, payload, 'exact-store:' + String(reason || ''), activeViewId);
        }
        var afterCanvasObjects = countLiveCanvasUserObjects(instance || null);
        var afterDocument = exportDesign(instance || null);
        var afterState = exportState(instance || null);
        var afterStateDocument = afterState && typeof afterState === 'object' ? (afterState.initialDocument || afterState.document || afterState.documentState || afterState) : null;
        var ok = !(countBootViews(payload) > 0 && Math.max(countBootViews(afterDocument), countBootViews(afterStateDocument)) <= 0)
            && !(expectedObjects > 0 && afterCanvasObjects <= 0 && !canvasForced);

        logApdVariationDebug('runtimeBridge:exactDocumentRestore', {
            reason: reason || '',
            ok: ok,
            canvasForced: canvasForced,
            expectedDocument: summarizeViewContainer(payload),
            afterDocument: summarizeViewContainer(afterDocument),
            afterCanvasObjects: afterCanvasObjects
        });
        return ok;
    }


    function applyDocumentDirectlyToRuntimeStore(instance, documentPayload, reason) {
        if (!instance || !instance.store || typeof instance.store.setState !== 'function') {
            return false;
        }

        var normalizedViews = getDocumentViewsForStore(documentPayload);
        if (!normalizedViews) {
            return false;
        }

        var payload = normalizedViews.payload || normalizeDocumentHotStatePayload(documentPayload) || documentPayload || {};
        var activeViewId = normalizedViews.activeViewId;
        var objectsByView = getDocumentObjectsForStore(payload);
        var drawingAreas = getDocumentDrawingAreasForStore(payload, activeViewId);
        var viewportByView = getDocumentViewportByViewForStore(payload);
        var selection = payload.selection && typeof payload.selection === 'object'
            ? clonePlainObject(payload.selection)
            : { activeObjectIds: [], activeDrawingAreaId: payload.activeDrawingAreaId || null };

        var actionResult = applyRuntimeDocumentActionSnapshot(instance || null, payload, 'direct-document');
        if (actionResult && actionResult.method) {
            apdApplyRuntimeUploadConfigToInstance(instance || null, null);
            return true;
        }


        try {
            instance.store.setState(function () {
                return {
                    views: normalizedViews.views,
                    documentViews: normalizedViews.views,
                    activeViewId: activeViewId,
                    documentObjectsByView: objectsByView,
                    documentDrawingAreas: drawingAreas,
                    documentViewportByView: viewportByView,
                    documentSelection: selection
                };
            });
        } catch (error) {
            return false;
        }

        try {
            var state = instance.store && typeof instance.store.getState === 'function' ? instance.store.getState() : null;
            if (state && typeof state.setDocumentViews === 'function') {
                state.setDocumentViews(normalizedViews.views, activeViewId);
            }
            if (state && typeof state.setActiveView === 'function') {
                state.setActiveView(activeViewId);
            }
            if (state && typeof state.setDocumentObjectsForView === 'function') {
                Object.keys(objectsByView || {}).forEach(function (viewId) {
                    state.setDocumentObjectsForView(String(viewId), clonePlainObject(objectsByView[viewId] || []));
                });
            }
            if (state && typeof state.setDocumentDrawingAreas === 'function') {
                state.setDocumentDrawingAreas(clonePlainObject(drawingAreas || []));
            }
            if (state && typeof state.setDocumentViewportForView === 'function') {
                Object.keys(viewportByView || {}).forEach(function (viewId) {
                    state.setDocumentViewportForView(String(viewId), clonePlainObject(viewportByView[viewId] || {}));
                });
            }
            if (state && typeof state.setDocumentSelection === 'function') {
                state.setDocumentSelection(clonePlainObject(selection || {}));
            }
        } catch (error) {}

        var rebuilt = rebuildActiveViewFromImportedPayload(instance, activeViewId);
        var afterDocument = exportDesign(instance || null);
        var afterState = exportState(instance || null);
        var afterStateDocument = afterState && typeof afterState === 'object' ? (afterState.initialDocument || afterState.document || afterState.documentState || afterState) : null;
        var expectedViews = countBootViews(payload);
        var expectedObjects = countPayloadObjects(payload);
        var canvasObjectsBeforeForce = countLiveCanvasUserObjects(instance || null);
        var canvasForced = false;
        if (expectedObjects > 0) {
            // Force the visible canvas too, not only the document store. A base
            // product canvas can have objects and still be the wrong state.
            canvasForced = forceCanvasFromDocumentPayload(instance || null, payload, 'direct-store:' + String(reason || ''), activeViewId);
        }
        var afterCanvasObjects = countLiveCanvasUserObjects(instance || null);
        var afterViews = Math.max(countBootViews(afterDocument), countBootViews(afterStateDocument));
        var afterObjects = Math.max(countPayloadObjects(afterDocument), countPayloadObjects(afterStateDocument));
        var ok = !(expectedViews > 0 && afterViews <= 0)
            && !(expectedObjects > 0 && afterObjects <= 0 && !canvasForced)
            && !(expectedObjects > 0 && afterCanvasObjects <= 0 && !canvasForced);


        return ok;
    }

    function exportedDocumentHasViews(instance) {
        var exported = exportDesign(instance || null);
        return countBootViews(exported) > 0;
    }

    function scheduleBootPayloadFallback(shell, instance, bootPayload, initialMethod) {
        if (!shell || !instance || !bootPayloadHasViews(bootPayload)) {
            return;
        }
        if (bootPayloadRestoreSatisfied(instance, bootPayload)) {
            return;
        }

        var delays = [50, 150, 350, 700];
        delays.forEach(function (delay, index) {
            window.setTimeout(function () {
                if (!shell.isConnected || !shell.__apdInstance) {
                    return;
                }
                if (bootPayloadRestoreSatisfied(shell.__apdInstance, bootPayload)) {
                    return;
                }
                var retryMethod = (withBootImportPermissions(shell.__apdInstance || null, shell.__apdCreateMountConfig && shell.__apdCreateMountConfig.permissions ? shell.__apdCreateMountConfig.permissions : null, function () {
                    return applyBootPayload(shell.__apdInstance, bootPayload);
                }) || '');
                if (!bootPayloadRestoreSatisfied(shell.__apdInstance || null, bootPayload)) {
                    var retryDocument = getBootPayloadExpectedDocument(bootPayload);
                    if (retryDocument && applyDocumentDirectlyToRuntimeStore(shell.__apdInstance || null, retryDocument, 'bootPayloadFallback:' + String(delay))) {
                        retryMethod = retryMethod ? retryMethod + '+direct-store' : 'direct-store';
                    }
                }
                apdApplyRuntimeCatalogAndModuleConfigToInstance(shell.__apdInstance || null, shell.__apdMountConfig || shell.__apdRawMountConfig || shell.__apdCreateMountConfig || {});
                apdApplyRuntimeUploadConfigToInstance(shell.__apdInstance || null, shell.__apdCreateMountConfig && shell.__apdCreateMountConfig.moduleConfig ? shell.__apdCreateMountConfig.moduleConfig.upload : null);
                apdApplyRuntimePermissionsToInstance(shell.__apdInstance || null, shell.__apdCreateMountConfig && shell.__apdCreateMountConfig.permissions ? shell.__apdCreateMountConfig.permissions : null);
                logApdVariationDebug('runtimeBridge:bootPayload:fallback', {
                    shell: summarizeShellDebug(shell),
                    attempt: index + 1,
                    delay: delay,
                    initialMethod: initialMethod || '',
                    retryMethod: retryMethod || '',
                    finalDocument: summarizeViewContainer(exportDesign(shell.__apdInstance || null))
                });
            }, delay);
        });
    }

    function rebuildActiveViewFromImportedPayload(instance, targetViewId) {
        if (!instance || !instance.util || !instance.util.state || typeof instance.util.state.rebuildActiveViewFromDocument !== 'function') {
            return false;
        }

        var viewId = targetViewId != null ? String(targetViewId || '') : undefined;
        try {
            instance.util.state.rebuildActiveViewFromDocument(viewId);
            return true;
        } catch (error) {
            return false;
        }
    }

    function applyBootImportCandidate(shellInstance, expectedPayload, method, importer) {
        if (!shellInstance || typeof importer !== 'function') {
            logApdVariationDebug('runtimeBridge:importCandidate:skip', {
                method: method || '',
                reason: !shellInstance ? 'no-instance' : 'no-importer',
                expected: summarizeViewContainer(expectedPayload)
            });
            return null;
        }

        logApdVariationDebug('runtimeBridge:importCandidate:before', {
            method: method || '',
            expected: summarizeViewContainer(expectedPayload),
            beforeDocument: summarizeViewContainer(exportDesign(shellInstance || null)),
            beforeStateDocument: summarizeViewContainer((function () {
                var state = exportState(shellInstance || null);
                return state && typeof state === 'object' ? (state.initialDocument || state.document || state) : null;
            })())
        });

        try {
            var nextInstance = importer();
            nextInstance = nextInstance || shellInstance;
            var drawingAreasApplied = applyDrawingAreaSnapshotPayload(nextInstance, expectedPayload, method || 'boot-import');
            var rebuilt = rebuildActiveViewFromImportedPayload(nextInstance);
            var afterDocument = exportDesign(nextInstance || null);
            var afterState = exportState(nextInstance || null);
            var afterStateDocument = afterState && typeof afterState === 'object' ? (afterState.initialDocument || afterState.document || afterState) : null;
            var afterHasViews = exportedDocumentHasViews(nextInstance);
            var expectedObjectCount = countPayloadObjects(expectedPayload);
            var afterObjectCount = Math.max(countPayloadObjects(afterDocument), countPayloadObjects(afterStateDocument));
            var accepted = !(payloadHasViews(expectedPayload) && !afterHasViews)
                && !(expectedObjectCount > 0 && afterObjectCount <= 0);

            logApdVariationDebug('runtimeBridge:importCandidate:after', {
                method: method || '',
                rebuilt: rebuilt,
                drawingAreasApplied: drawingAreasApplied,
                expected: summarizeViewContainer(expectedPayload),
                afterDocument: summarizeViewContainer(afterDocument),
                afterStateDocument: summarizeViewContainer(afterStateDocument),
                afterHasViews: afterHasViews,
                expectedObjectCount: expectedObjectCount,
                afterObjectCount: afterObjectCount,
                accepted: accepted
            });

            // Some runtime import methods exist but silently ignore a payload shape
            // they do not own. If the public importer did not hydrate the exported
            // document, write the document bucket directly to the runtime store before
            // trying another strategy. This is the same source of truth used by the
            // AsukaDesigner modular importer internally (views/documentViews/activeViewId).
            if (!accepted && applyDocumentDirectlyToRuntimeStore(nextInstance || shellInstance, expectedPayload, method || 'import-candidate')) {
                afterDocument = exportDesign(nextInstance || shellInstance || null);
                afterState = exportState(nextInstance || shellInstance || null);
                afterStateDocument = afterState && typeof afterState === 'object' ? (afterState.initialDocument || afterState.document || afterState) : null;
                afterHasViews = exportedDocumentHasViews(nextInstance || shellInstance || null);
                afterObjectCount = Math.max(countPayloadObjects(afterDocument), countPayloadObjects(afterStateDocument));
                accepted = !(payloadHasViews(expectedPayload) && !afterHasViews)
                    && !(expectedObjectCount > 0 && afterObjectCount <= 0);
            }

            if (!accepted) {
                return null;
            }

            return { method: method, instance: nextInstance || shellInstance };
        } catch (error) {
            logApdVariationDebug('runtimeBridge:importCandidate:error', {
                method: method || '',
                message: error && error.message ? error.message : String(error),
                expected: summarizeViewContainer(expectedPayload)
            });
            return null;
        }
    }

    function extractHotDocumentPayload(value) {
        if (!value || typeof value !== 'object') {
            return null;
        }

        var candidates = [];
        if (value.initialDocument && typeof value.initialDocument === 'object') {
            candidates.push(value.initialDocument);
        }
        if (value.documentState && typeof value.documentState === 'object') {
            candidates.push(value.documentState);
        }
        if (value.document && typeof value.document === 'object') {
            candidates.push(value.document);
        }
        if (value.state && typeof value.state === 'object') {
            candidates.push(value.state);
        }
        if (value.legacy && typeof value.legacy === 'object') {
            if (value.legacy.document && typeof value.legacy.document === 'object') {
                candidates.push(value.legacy.document);
            }
            if (value.legacy.state && typeof value.legacy.state === 'object') {
                candidates.push(value.legacy.state);
            }
        }

        for (var i = 0; i < candidates.length; i += 1) {
            var nested = extractHotDocumentPayload(candidates[i]);
            if (nested && payloadHasViews(nested)) {
                return nested;
            }
            if (payloadHasViews(candidates[i])) {
                return candidates[i];
            }
        }

        if (payloadHasViews(value)) {
            return value;
        }

        return null;
    }

    function hasDocumentHotStateImporter(instance) {
        return !!(instance && instance.util && instance.util.state && typeof instance.util.state.importPart === 'function');
    }

    function applyDocumentHotState(instance, documentPayload, replaceOptions) {
        if (!documentPayload || typeof documentPayload !== 'object' || !payloadHasViews(documentPayload)) {
            return null;
        }

        if (hasDocumentHotStateImporter(instance)) {
            var canonicalDocumentState = buildCanonicalDocumentState(documentPayload, {});
            return applyBootImportCandidate(instance, canonicalDocumentState, 'util.state.importPart(document)', function () {
                instance.util.state.importPart('document', canonicalDocumentState, replaceOptions);
                return instance;
            });
        }

        return null;
    }

    function applyFullHotState(instance, state, replaceOptions) {
        if (!state || typeof state !== 'object' || !Object.keys(state).length) {
            return null;
        }

        state = buildCanonicalFullState(state, null, {});
        var fullCandidates = [
            function () {
                if (instance.util && instance.util.state && typeof instance.util.state.replaceProduct === 'function') {
                    return applyBootImportCandidate(instance, state, 'util.state.replaceProduct(recreate:true)', function () {
                        return instance.util.state.replaceProduct(state, { recreate: true, replaceViews: true, replaceSnapshots: true }) || instance;
                    });
                }
                return null;
            },
            function () {
                if (instance.util && instance.util.state && typeof instance.util.state.importFull === 'function') {
                    return applyBootImportCandidate(instance, state, 'util.state.importFull', function () {
                        instance.util.state.importFull(state, replaceOptions);
                        return instance;
                    });
                }
                return null;
            }
        ];

        for (var i = 0; i < fullCandidates.length; i += 1) {
            var stateResult = fullCandidates[i]();
            if (stateResult && stateResult.method) {
                return stateResult;
            }
        }

        return null;
    }

    function applyBootPayloadResult(instance, bootPayload) {
        var result = { method: '', instance: instance || null };
        if (!instance || !bootPayload || typeof bootPayload !== 'object') {
            logApdVariationDebug('runtimeBridge:applyBootPayload:skip', {
                reason: !instance ? 'no-instance' : 'no-boot-payload',
                bootPayload: summarizeMountPayload(bootPayload || {})
            });
            return result;
        }

        var replaceOptions = { replaceViews: true, replaceSnapshots: true };
        var documentPayload = chooseBestHotDocumentPayload(bootPayload);

        logApdVariationDebug('runtimeBridge:applyBootPayload:start', {
            bootPayload: summarizeMountPayload(bootPayload || {}),
            initialDocumentCandidate: summarizeViewContainer(bootPayload.initialDocument),
            extractedDocumentPayload: summarizeViewContainer(documentPayload),
            initialStateCandidate: summarizeViewContainer(bootPayload.initialState)
        });

        // Mirror the local working demo exactly: importDocument() must receive the
        // exportDocument()/documentState payload. Do not feed a modular/full
        // initialState to importDocument(), even if it has a views key, because that
        // shape can import no objects and leave the canvas blank. Full states fall
        // through to replaceProduct()/importFull below.
        var documentResult = applyDocumentHotState(instance, documentPayload, replaceOptions);
        if (documentResult && documentResult.method) {
            logApdVariationDebug('runtimeBridge:applyBootPayload:document-applied', {
                method: documentResult.method,
                finalDocument: summarizeViewContainer(exportDesign(documentResult.instance || instance || null))
            });
            return documentResult;
        }

        // If a real document payload was present and importDocument exists, do not
        // continue with replaceProduct()/importFull fallbacks. The local working
        // integration uses importDocument() as the authoritative canvas switch;
        // falling through to full-state strategies after a validation mismatch can
        // destroy/recreate the runtime and leave the canvas blank.
        if (documentPayload && hasDocumentHotStateImporter(instance) && !bootPayload.initialState) {
            logApdVariationDebug('runtimeBridge:applyBootPayload:document-import-not-accepted-stop', {
                extractedDocumentPayload: summarizeViewContainer(documentPayload),
                finalDocument: summarizeViewContainer(exportDesign(instance || null)),
                finalStateDocument: summarizeViewContainer((function () {
                    var stateForLog = exportState(instance || null);
                    return stateForLog && typeof stateForLog === 'object' ? (stateForLog.initialDocument || stateForLog.document || stateForLog) : null;
                })())
            });
            return result;
        }

        var state = bootPayload.initialState;
        var fullResult = applyFullHotState(instance, state, replaceOptions);
        if (fullResult && fullResult.method) {
            logApdVariationDebug('runtimeBridge:applyBootPayload:full-applied', {
                method: fullResult.method,
                finalDocument: summarizeViewContainer(exportDesign(fullResult.instance || instance || null))
            });
            return fullResult;
        }

        logApdVariationDebug('runtimeBridge:applyBootPayload:no-method', {
            bootPayload: summarizeMountPayload(bootPayload || {}),
            extractedDocumentPayload: summarizeViewContainer(documentPayload),
            finalDocument: summarizeViewContainer(exportDesign(instance || null))
        });
        return result;
    }

    function applyBootPayload(instance, bootPayload) {
        return applyBootPayloadResult(instance, bootPayload).method;
    }

    function shouldUseDirectBootPayload(config) {
        // Kept as a compatibility hook for old payloads, but the cart/resume flow
        // must now use the same documented init path as a normal custom product:
        // build the final initialDocument first, then pass it to createAsukaDesigner.
        // Returning false prevents the old post-init exact-canvas restore path from
        // reloading objects after boot and changing their coordinates.
        return false;
    }


    function normalizeViewsPaginationConfig(config) {
        var ui = config && config.ui && typeof config.ui === 'object' ? config.ui : {};
        var enabled = null;
        var mode = '';
        var raw = ui.viewsPagination;
        if (raw === false) {
            enabled = false;
        } else if (raw && typeof raw === 'object') {
            if (Object.prototype.hasOwnProperty.call(raw, 'enabled')) {
                enabled = !!raw.enabled;
            } else if (enabled === null) {
                enabled = true;
            }
            if (typeof raw.mode === 'string') {
                mode = raw.mode;
            }
        }
        if (Object.prototype.hasOwnProperty.call(ui, 'viewsPaginationEnabled')) {
            enabled = !!ui.viewsPaginationEnabled;
        }
        if (!mode && typeof ui.viewsPaginationMode === 'string') {
            mode = ui.viewsPaginationMode;
        }
        mode = String(mode || 'auto').toLowerCase();
        if (['auto', 'thumbnails', 'dots', 'numbers'].indexOf(mode) === -1) {
            mode = 'auto';
        }
        return {
            enabled: enabled === false ? false : true,
            mode: mode
        };
    }

    function findViewsPaginationToolbar(shell) {
        if (!shell || !shell.querySelectorAll) {
            return null;
        }
        var candidates = Array.prototype.slice.call(shell.querySelectorAll('.ask-theme-toolbar > .ask-theme-carousel'));
        for (var i = 0; i < candidates.length; i += 1) {
            var carousel = candidates[i];
            if (!carousel || !carousel.closest) {
                continue;
            }
            // The view switcher carousel is the only toolbar carousel with the
            // counter rendered by AsukaDesigner's Views pagination.
            if (carousel.querySelector('.ask-theme-carousel__counter')) {
                return carousel.closest('.ask-theme-toolbar') || carousel.parentNode;
            }
        }
        return null;
    }

    function applyViewsPaginationUiToShell(shell, config) {
        if (!shell || !config || isAdminEditorRuntimeConfig(config)) {
            return false;
        }
        var settings = normalizeViewsPaginationConfig(config || {});
        shell.setAttribute('data-apd-views-pagination-enabled', settings.enabled ? '1' : '0');
        shell.setAttribute('data-apd-views-pagination-mode', settings.mode || 'auto');
        var mount = shell.querySelector ? shell.querySelector('[data-apd-mount]') : null;
        if (mount && mount.setAttribute) {
            mount.setAttribute('data-apd-views-pagination-enabled', settings.enabled ? '1' : '0');
            mount.setAttribute('data-apd-views-pagination-mode', settings.mode || 'auto');
        }

        var apply = function () {
            var toolbar = findViewsPaginationToolbar(shell);
            if (!toolbar) {
                return false;
            }
            toolbar.setAttribute('data-apd-view-pagination-toolbar', '1');
            toolbar.setAttribute('data-apd-views-pagination-mode', settings.mode || 'auto');
            if (!settings.enabled) {
                toolbar.hidden = true;
                toolbar.style.display = 'none';
                return true;
            }
            toolbar.hidden = false;
            toolbar.style.display = '';
            return true;
        };

        apply();
        [40, 160, 420, 900].forEach(function (delay) {
            window.setTimeout(apply, delay);
        });

        if (!shell.__apdViewsPaginationObserver && typeof MutationObserver !== 'undefined') {
            try {
                shell.__apdViewsPaginationObserver = new MutationObserver(function () {
                    apply();
                });
                shell.__apdViewsPaginationObserver.observe(shell, { childList: true, subtree: true });
            } catch (error) {
                shell.__apdViewsPaginationObserver = null;
            }
        }
        return true;
    }

    function mountOne(shell, attempt) {
        attempt = attempt || 0;
        var mount = shell.querySelector('[data-apd-mount]');
        var configNode = shell.querySelector('.apd-config');
        if (!mount || !configNode) {
            return;
        }

        if (mount.dataset.apdMounted === '1' && shell.__apdInstance) {
            return;
        }

        var rawConfig = parseConfig(configNode);
        var config = apdEnsureRuntimeUploadConfig(sanitizeMountConfig(rawConfig), {
            strategy: 'remote',
            endpoint: (window.APDAdminConfig && window.APDAdminConfig.restUploadUrl) || (window.APD_RUNTIME && window.APD_RUNTIME.restUploadUrl) || '',
            method: 'POST',
            fieldName: 'file',
            source: window.APDAdminConfig ? 'admin' : 'frontend',
            headers: {
                'X-WP-Nonce': (window.APDAdminConfig && window.APDAdminConfig.restNonce) || (window.APD_RUNTIME && window.APD_RUNTIME.nonce) || ''
            }
        });
        var useDirectBootPayload = shouldUseDirectBootPayload(config);
        var bootPayload = extractBootPayload(config);
        // Always strip document/template buckets before creating the runtime.
        // For cart/resume (`direct_boot_payload`), the saved initialDocument must be
        // the only document source. Keeping the product config's top-level views /
        // objects lets the base template win later during AsukaDesigner's async boot.
        var createConfig = stripBootPayload(config);
        forceAdminRuntimePermissions(createConfig);
        apdEnsureRuntimeUploadConfig(createConfig, {
            strategy: 'remote',
            endpoint: (window.APDAdminConfig && window.APDAdminConfig.restUploadUrl) || (window.APD_RUNTIME && window.APD_RUNTIME.restUploadUrl) || '',
            method: 'POST',
            fieldName: 'file',
            source: window.APDAdminConfig ? 'admin' : 'frontend',
            headers: {
                'X-WP-Nonce': (window.APDAdminConfig && window.APDAdminConfig.restNonce) || (window.APD_RUNTIME && window.APD_RUNTIME.nonce) || ''
            }
        });
        var directBootSourceDocument = useDirectBootPayload
            ? (normalizeDocumentHotStatePayload(getBootPayloadExpectedDocument(bootPayload)) || clonePlainObject(getBootPayloadExpectedDocument(bootPayload) || {}))
            : null;
        if (useDirectBootPayload && (!directBootSourceDocument || !payloadHasViews(directBootSourceDocument))) {
            directBootSourceDocument = null;
        }
        // Direct cart/resume boot must not pass initialDocument/initialState to
        // createAsukaDesigner(). The runtime can asynchronously re-import that
        // boot document and normalize/auto-fit element instances after our first
        // restore, which is exactly how saved positions got overwritten. Create a
        // clean runtime, then apply the saved document ourselves as an exact canvas
        // snapshot.
        var designerCreateConfig = makeBootCreateConfig(createConfig, bootPayload);
        apdEnsureRuntimeUploadConfig(designerCreateConfig, {
            strategy: 'remote',
            endpoint: (window.APDAdminConfig && window.APDAdminConfig.restUploadUrl) || (window.APD_RUNTIME && window.APD_RUNTIME.restUploadUrl) || '',
            method: 'POST',
            fieldName: 'file',
            source: window.APDAdminConfig ? 'admin' : 'frontend',
            headers: {
                'X-WP-Nonce': (window.APDAdminConfig && window.APDAdminConfig.restNonce) || (window.APD_RUNTIME && window.APD_RUNTIME.nonce) || ''
            }
        });
        logTemplateLayoutDebug('mount-config', {
            shell: summarizeShellDebug(shell),
            serverDebug: config && config.context && config.context.apdTemplateLayoutDebug ? config.context.apdTemplateLayoutDebug : null,
            rawLayout: summarizeLayoutDebug(rawConfig.layout),
            safeLayout: summarizeLayoutDebug(config.layout),
            createLayout: summarizeLayoutDebug(createConfig.layout),
            bootStateLayout: summarizeLayoutDebug(bootPayload && bootPayload.initialState ? (bootPayload.initialState.layout || (bootPayload.initialState.ui && bootPayload.initialState.ui.layout) || ((bootPayload.initialState.legacy && bootPayload.initialState.legacy.state) ? bootPayload.initialState.legacy.state.layout : null)) : null),
            bootStateScopeLayout: bootPayload && bootPayload.initialState && bootPayload.initialState.scope ? bootPayload.initialState.scope.layout : null,
            bootLegacyScopeLayout: bootPayload && bootPayload.initialState && bootPayload.initialState.legacy && bootPayload.initialState.legacy.scope ? bootPayload.initialState.legacy.scope.layout : null,
            directBoot: useDirectBootPayload
        });
        logApdVariationDebug('runtimeBridge:mountOne:config', {
            shell: summarizeShellDebug(shell),
            raw: summarizeMountPayload(rawConfig),
            safe: summarizeMountPayload(config),
            createConfig: summarizeMountPayload(createConfig),
            designerCreateConfig: summarizeMountPayload(designerCreateConfig),
            directBoot: useDirectBootPayload,
            directBootSourceDocument: summarizeViewContainer(directBootSourceDocument || null),
            bootAppliedAtCreate: !!(designerCreateConfig && ((designerCreateConfig.initialDocument && payloadHasViews(designerCreateConfig.initialDocument)) || (designerCreateConfig.initialState && payloadHasViews(designerCreateConfig.initialState))))
        });
        shell.__apdUseDirectBootPayload = !!useDirectBootPayload;
        shell.__apdDirectBootSourceDocument = directBootSourceDocument ? clonePlainObject(directBootSourceDocument) : null;
        var createFn = getCreateFn();
        if (createFn) {
            try {
                var instance = createFn('#' + mount.id, designerCreateConfig);
                apdKeepRuntimeCatalogAndModuleConfig(instance || null, config || createConfig || {});
                apdKeepRuntimeUploadConfig(instance || null, createConfig && createConfig.moduleConfig ? createConfig.moduleConfig.upload : null);
                var bootAppliedAtCreate = !!(
                    (designerCreateConfig && designerCreateConfig.initialDocument && payloadHasViews(designerCreateConfig.initialDocument))
                    || (designerCreateConfig && designerCreateConfig.initialState && payloadHasViews(designerCreateConfig.initialState))
                );
                var bootApplyResult = bootAppliedAtCreate
                    ? { method: designerCreateConfig.initialDocument ? 'create.initialDocument' : 'create.initialState', instance: instance || null }
                    : (useDirectBootPayload
                        ? { method: 'create.bootPayload', instance: instance || null }
                        : (withBootImportPermissions(instance || null, createConfig && createConfig.permissions ? createConfig.permissions : (config && config.permissions ? config.permissions : null), function () {
                            return applyBootPayloadResult(instance || null, bootPayload);
                        }) || { method: '', instance: instance || null }));
                instance = bootApplyResult.instance || instance;
                if (useDirectBootPayload && bootPayloadHasViews(bootPayload) && instance) {
                    var directBootDocument = shell.__apdDirectBootSourceDocument || directBootSourceDocument || getBootPayloadExpectedDocument(bootPayload);
                    if (directBootDocument && countPayloadObjects(directBootDocument) > 0) {
                        // Direct boot is used for cart/resume. The saved document is the
                        // source of truth. Apply it without the public importDocument()
                        // pipeline so object coordinates are not re-normalized to the
                        // template centre during async boot.
                        var directApplied = withBootImportPermissions(instance || null, createConfig && createConfig.permissions ? createConfig.permissions : (config && config.permissions ? config.permissions : null), function () {
                            return applyDocumentExactlyToRuntimeStore(instance || null, directBootDocument, 'mountOne:direct-boot-exact');
                        });
                        if (directApplied) {
                            scheduleForcedDocumentCanvasRestore(shell, instance || null, directBootDocument, 'mountOne:direct-boot-exact');
                            bootApplyResult.method = bootApplyResult.method ? bootApplyResult.method + '+exact-document-store-canvas' : 'exact-document-store-canvas';
                        }
                    } else if (directBootDocument && !bootPayloadRestoreSatisfied(instance || null, bootPayload) && applyDocumentExactlyToRuntimeStore(instance || null, directBootDocument, 'mountOne:direct-boot-empty')) {
                        bootApplyResult.method = bootApplyResult.method ? bootApplyResult.method + '+exact-store' : 'exact-store';
                    }
                }
                apdKeepRuntimePermissions(instance || null, createConfig && createConfig.permissions ? createConfig.permissions : (config && config.permissions ? config.permissions : null));
                var importMethod = bootApplyResult.method || (useDirectBootPayload ? 'create.bootPayload' : 'create.empty');
                var exportedStateAfterImport = instance && typeof instance === 'object'
                    ? exportState(instance || null)
                    : {};
                if (!useDirectBootPayload && !bootAppliedAtCreate) {
                    scheduleBootPayloadFallback(shell, instance || null, bootPayload, importMethod);
                }
                var currentRuntimeLayout = exportedStateAfterImport && typeof exportedStateAfterImport === 'object'
                    ? normalizeRuntimeLayout(
                        exportedStateAfterImport.layout
                        || (exportedStateAfterImport.ui && typeof exportedStateAfterImport.ui === 'object' ? exportedStateAfterImport.ui.layout : null)
                        || {}
                    )
                    : {};
                var desiredLayout = createConfig && createConfig.layout && typeof createConfig.layout === 'object'
                    ? normalizeRuntimeLayout(createConfig.layout)
                    : {};
                logTemplateLayoutDebug('after-import-before-apply', {
                    shell: summarizeShellDebug(shell),
                    importMethod: importMethod,
                    bootAppliedAtCreate: !!bootAppliedAtCreate,
                    runtimeLayout: summarizeLayoutDebug(currentRuntimeLayout),
                    desiredLayout: summarizeLayoutDebug(desiredLayout),
                    exportedStateLayout: summarizeLayoutDebug(currentRuntimeLayout)
                });
                var layoutApplied = false;
                if (!useDirectBootPayload && instance && typeof instance === 'object' && Object.keys(desiredLayout).length) {
                    layoutApplied = !!withBootImportPermissions(
                        instance,
                        createConfig && createConfig.permissions ? createConfig.permissions : (config && config.permissions ? config.permissions : null),
                        function () {
                            return applyRuntimeLayout(instance, currentRuntimeLayout, desiredLayout);
                        }
                    );
                }
                var runtimeLayoutAfterApply = instance && typeof instance === 'object' ? getExportedRuntimeLayout(instance || null) : {};
                exposeTemplateLayoutDebug(shell, runtimeLayoutAfterApply);
                logTemplateLayoutDebug('after-apply-layout', {
                    shell: summarizeShellDebug(shell),
                    layoutApplied: layoutApplied,
                    runtimeLayoutAfterApply: summarizeLayoutDebug(runtimeLayoutAfterApply),
                    desiredLayout: summarizeLayoutDebug(desiredLayout),
                    finalDocument: summarizeViewContainer(exportDesign(instance || null)),
                    finalStateDocument: summarizeViewContainer((function () {
                        var state = exportState(instance || null);
                        return state && typeof state === 'object' ? (state.initialDocument || state.document || state) : null;
                    })())
                });
                shell.__apdInstance = instance || null;
                shell.__apdMountConfig = config;
                installVariationRuntimeDump(instance || null, shell);
                shell.__apdRawMountConfig = rawConfig;
                shell.__apdCreateMountConfig = createConfig;
                shell.__apdBootPayload = bootPayload;
                shell.__apdBootAppliedAtCreate = !!bootAppliedAtCreate;
                applyRuntimePermissionGuards(shell, instance || null, config);
                installRenderedMenuDebug(shell, instance || null, config.i18n || {}, 'runtime-bridge:mountOne');
                mount.dataset.apdMounted = '1';
                applyViewsPaginationUiToShell(shell, config);
                setStatus(shell, runtimeLabel('runtimeDesignerMounted', 'Designer mounted.'), 'success');
                logApdVariationDebug('runtimeBridge:mountOne:mounted', {
                    shell: summarizeShellDebug(shell),
                    config: summarizeMountPayload(config),
                    createConfig: summarizeMountPayload(createConfig),
                    bootPayload: summarizeMountPayload(bootPayload),
                    importMethod: importMethod,
                    bootAppliedAtCreate: !!bootAppliedAtCreate,
                    layoutApplied: layoutApplied,
                    exportedDocument: summarizeViewContainer(exportDesign(instance || null)),
                    exportedStateDocument: summarizeViewContainer((function () {
                        var state = exportState(instance || null);
                        return state && typeof state === 'object' ? (state.initialDocument || state.document || state) : null;
                    })())
                });
                var mountExpectedPayload = getBootPayloadExpectedDocument(bootPayload);
                if (mountExpectedPayload && typeof mountExpectedPayload === 'object' && countPayloadObjects(mountExpectedPayload) > 0) {
                    scheduleCanvasRestoreWatchdog(shell, instance || null, mountExpectedPayload, 'mountOne');
                }
                [100, 400, 1000].forEach(function (delay) {
                    window.setTimeout(function () {
                        if (!shell.isConnected || !shell.__apdInstance) {
                            return;
                        }
                        var lateState = exportState(shell.__apdInstance || null);
                        logApdVariationDebug('runtimeBridge:mountOne:late-state', {
                            delay: delay,
                            shell: summarizeShellDebug(shell),
                            exportedDocument: summarizeViewContainer(exportDesign(shell.__apdInstance || null)),
                            exportedStateDocument: summarizeViewContainer(lateState && typeof lateState === 'object' ? (lateState.initialDocument || lateState.document || lateState) : null)
                        });
                    }, delay);
                });
                return;
            } catch (error) {
                console.error('[APD] Failed to mount AsukaDesigner.', error);
                logApdVariationDebug('runtimeBridge:mountOne:error', {
                    shell: summarizeShellDebug(shell),
                    message: error && error.message ? error.message : String(error)
                });
                setStatus(shell, runtimeLabel('runtimeDesignerMountFailed', 'Designer mount failed.'), 'danger');
            }
        }

        if (attempt < 20) {
            setStatus(shell, runtimeLabel('runtimeWaitingForDesigner', 'Waiting for AsukaDesigner…'), 'neutral');
            window.setTimeout(function () {
                mountOne(shell, attempt + 1);
            }, 150);
            return;
        }

        mount.innerHTML = '<div style="padding:16px;font-family:sans-serif;">' + runtimeLabel('runtimeDesignerUnavailable', 'AsukaDesigner could not be loaded in this context yet.') + '</div>';
    }

    function rebuildImportedDocument(instance) {
        if (!instance || !instance.util || !instance.util.state || typeof instance.util.state.rebuildActiveViewFromDocument !== 'function') {
            return false;
        }
        try {
            instance.util.state.rebuildActiveViewFromDocument();
            return true;
        } catch (error) {
            return false;
        }
    }


    function getShellStrictRuntimeConfig(shell) {
        if (!shell) {
            return {};
        }
        var node = shell.querySelector ? shell.querySelector('.apd-config') : null;
        var parsedConfig = parseConfig(node);
        if (parsedConfig && typeof parsedConfig === 'object' && Object.keys(parsedConfig).length) {
            return parsedConfig;
        }
        if (shell.__apdCreateMountConfig && typeof shell.__apdCreateMountConfig === 'object') {
            return shell.__apdCreateMountConfig;
        }
        if (shell.__apdMountConfig && typeof shell.__apdMountConfig === 'object') {
            return shell.__apdMountConfig;
        }
        return {};
    }

    function normalizeConfigLayoutItemForFullState(item, fallbackZone, fallbackIndex) {
        item = item && typeof item === 'object' ? item : {};
        var kind = String(item.kind || item.module || item.id || '').trim();
        if (!kind) {
            return null;
        }
        var id = String(item.id || kind).trim() || kind;
        var order = Number(item.order);
        if (!Number.isFinite(order)) {
            order = Number(item.index);
        }
        if (!Number.isFinite(order)) {
            order = Number(item.position);
        }
        if (!Number.isFinite(order)) {
            order = Number(fallbackIndex || 0);
        }
        var normalized = {
            id: id,
            kind: kind,
            label: typeof item.label === 'string' && item.label ? item.label : kind,
            icon: normalizeApdMenuIconName(item.icon, kind),
            order: order,
            type: typeof item.type === 'string' && item.type ? item.type : 'floating',
            collapsed: !!item.collapsed,
            collapsible: item.collapsible !== false,
            zone: fallbackZone
        };
        var mountTarget = typeof item.mountTarget === 'string' ? item.mountTarget.trim() : '';
        if (mountTarget) {
            normalized.mountTarget = mountTarget;
        }
        if (item.renderMode === 'inline' || item.renderMode === 'portal') {
            normalized.renderMode = item.renderMode;
        }
        return normalized;
    }

    function mapConfigZoneTypeToFullStateZoneType(type) {
        type = String(type || '').trim().toLowerCase();
        if (type === 'panels' || type === 'panel' || type.indexOf('panel-') === 0) {
            return 'panels';
        }
        if (type === 'inline') {
            return 'inline';
        }
        return 'default';
    }

    function configLayoutToFullStateLayout(layout) {
        if (!layout || typeof layout !== 'object' || Array.isArray(layout)) {
            return null;
        }
        if (layout.blocksByZone && typeof layout.blocksByZone === 'object') {
            return clonePlainObject(layout);
        }
        var blocksByZone = {};
        var zoneCollapsed = {};
        var zoneCollapsible = {};
        var zoneType = {};
        var hasAnyItem = false;
        ['left', 'right', 'top', 'bottom'].forEach(function (zone) {
            var zoneConfig = layout[zone] && typeof layout[zone] === 'object' ? layout[zone] : {};
            var items = Array.isArray(zoneConfig.items) ? zoneConfig.items.slice() : (Array.isArray(zoneConfig) ? zoneConfig.slice() : []);
            items = items.map(function (item, index) {
                return normalizeConfigLayoutItemForFullState(item, zone, index);
            }).filter(Boolean).sort(function (a, b) {
                return (Number(a.order) || 0) - (Number(b.order) || 0);
            }).map(function (item, index) {
                item.order = index;
                delete item.zone;
                return item;
            });
            if (items.length) {
                hasAnyItem = true;
            }
            blocksByZone[zone] = items;
            zoneCollapsed[zone] = !!zoneConfig.collapsed;
            zoneCollapsible[zone] = zoneConfig.collapsible !== false;
            zoneType[zone] = mapConfigZoneTypeToFullStateZoneType(zoneConfig.type);
        });
        if (!hasAnyItem) {
            return null;
        }
        return {
            blocksByZone: blocksByZone,
            zoneCollapsed: zoneCollapsed,
            zoneCollapsible: zoneCollapsible,
            zoneType: zoneType
        };
    }

    function stripRuntimeLayoutFromFullStatePayload(payload) {
        if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
            return payload;
        }
        delete payload.layout;
        if (payload.ui && typeof payload.ui === 'object') {
            delete payload.ui.layout;
        }
        if (payload.scope && typeof payload.scope === 'object') {
            payload.scope.layout = false;
        }
        if (payload.legacy && typeof payload.legacy === 'object') {
            if (payload.legacy.state && typeof payload.legacy.state === 'object') {
                payload.legacy.state = stripRuntimeLayoutFromFullStatePayload(payload.legacy.state);
            }
            if (payload.legacy.scope && typeof payload.legacy.scope === 'object') {
                payload.legacy.scope.layout = false;
            }
        }
        ['state', 'initialState', 'document', 'documentState', 'initialDocument'].forEach(function (key) {
            if (payload[key] && typeof payload[key] === 'object') {
                payload[key] = stripRuntimeLayoutFromFullStatePayload(payload[key]);
            }
        });
        return payload;
    }

    function summarizeFullStateLayout(layout) {
        layout = layout && typeof layout === 'object' ? layout : {};
        var blocksByZone = layout.blocksByZone && typeof layout.blocksByZone === 'object' ? layout.blocksByZone : {};
        var counts = {};
        var itemIds = [];
        ['left', 'right', 'top', 'bottom'].forEach(function (zone) {
            var items = Array.isArray(blocksByZone[zone]) ? blocksByZone[zone] : [];
            counts[zone] = items.length;
            items.forEach(function (item) {
                if (item && typeof item === 'object') {
                    itemIds.push(String(item.id || item.kind || ''));
                }
            });
        });
        return {
            topKeys: safeObjectKeys(layout),
            zoneItemCounts: counts,
            itemIds: itemIds.filter(Boolean),
            zoneType: layout.zoneType || {},
            zoneCollapsed: layout.zoneCollapsed || {}
        };
    }

    function injectShellConfigIntoFullStatePayload(shell, fullState, options) {
        var payload = clonePlainObject(fullState || {});
        if (!payload || typeof payload !== 'object') {
            return payload;
        }
        if (payload.document && typeof payload.document === 'object') {
            payload.document = normalizeDocumentHotStatePayload(payload.document) || payload.document;
        }
        if (payload.initialDocument && typeof payload.initialDocument === 'object') {
            payload.initialDocument = normalizeDocumentHotStatePayload(payload.initialDocument) || payload.initialDocument;
        }
        if (payload.documentState && typeof payload.documentState === 'object') {
            payload.documentState = normalizeDocumentHotStatePayload(payload.documentState) || payload.documentState;
        }
        var config = getShellStrictRuntimeConfig(shell);
        var runtimeLayout = configLayoutToFullStateLayout(config && config.layout ? config.layout : null);
        if (runtimeLayout) {
            payload.layout = clonePlainObject(runtimeLayout);
            payload.scope = payload.scope && typeof payload.scope === 'object' ? clonePlainObject(payload.scope) : {};
            payload.scope.layout = true;
            payload.ui = payload.ui && typeof payload.ui === 'object' ? clonePlainObject(payload.ui) : {};
            payload.ui.layout = clonePlainObject(runtimeLayout);
            if (payload.legacy && typeof payload.legacy === 'object') {
                payload.legacy = clonePlainObject(payload.legacy);
                payload.legacy.scope = payload.legacy.scope && typeof payload.legacy.scope === 'object' ? clonePlainObject(payload.legacy.scope) : {};
                payload.legacy.scope.layout = true;
                payload.legacy.state = payload.legacy.state && typeof payload.legacy.state === 'object' ? clonePlainObject(payload.legacy.state) : {};
                payload.legacy.state.layout = clonePlainObject(runtimeLayout);
            }
        } else {
            payload = stripRuntimeLayoutFromFullStatePayload(payload);
        }
        if (config && config.permissions && typeof config.permissions === 'object') {
            payload.permissions = clonePlainObject(config.permissions);
            payload.scope = payload.scope && typeof payload.scope === 'object' ? payload.scope : {};
            payload.scope.permissions = true;
        }
        if (config && config.moduleConfig && typeof config.moduleConfig === 'object') {
            payload.moduleConfig = clonePlainObject(config.moduleConfig);
            payload.scope = payload.scope && typeof payload.scope === 'object' ? payload.scope : {};
            payload.scope.moduleConfig = true;
        }
        if (config && config.catalog && typeof config.catalog === 'object') {
            payload.catalog = apdBuildSafeCatalogForFullStateImport(config.catalog, payload);
            payload.scope = payload.scope && typeof payload.scope === 'object' ? payload.scope : {};
            payload.scope.catalog = true;
        }
        if (config && Array.isArray(config.runtimeElements) && config.runtimeElements.length) {
            payload.runtimeElements = apdMergeElementDefinitionGroups([
                Array.isArray(payload.runtimeElements) ? payload.runtimeElements : [],
                config.runtimeElements
            ]);
        }
        ['colors', 'fonts', 'printingMethods', 'pricing', 'pricingRules', 'priceFormat'].forEach(function (key) {
            if (config && Object.prototype.hasOwnProperty.call(config, key)) {
                payload[key] = clonePlainObject(config[key]);
            }
        });
        if (config && Object.prototype.hasOwnProperty.call(config, 'price')) {
            payload.price = Number(config.price) || 0;
        }
        if (config && (config.pricing || config.pricingRules || Object.prototype.hasOwnProperty.call(config, 'price'))) {
            payload.scope = payload.scope && typeof payload.scope === 'object' ? payload.scope : {};
            payload.scope.pricing = true;
        }
        logApdVariationDebug('runtimeBridge:importFullProductStateToShell:payload-prepared', {
            source: options && options.source ? options.source : '',
            key: options && options.key ? options.key : '',
            configLayout: summarizeLayoutDebug(config && config.layout ? config.layout : {}),
            injectedFullStateLayout: summarizeFullStateLayout(runtimeLayout || {}),
            payloadScopeLayout: payload.scope && typeof payload.scope === 'object' ? payload.scope.layout : null,
            shell: summarizeShellDebug(shell)
        });
        return payload;
    }

    function importFullProductStateToShell(shell, fullState, documentState, options) {
        options = options || {};
        if (!shell || !fullState || typeof fullState !== 'object' || !Object.keys(fullState).length) {
            logApdVariationDebug('runtimeBridge:importFullProductStateToShell:skip', {
                reason: !shell ? 'no-shell' : 'no-full-state',
                source: options.source || '',
                key: options.key || '',
                stateKeys: fullState && typeof fullState === 'object' ? Object.keys(fullState) : []
            });
            return false;
        }

        var instance = shell.__apdInstance || null;
        if (!instance) {
            mountOne(shell);
            instance = shell.__apdInstance || null;
        }

        if (!instance) {
            logApdVariationDebug('runtimeBridge:importFullProductStateToShell:skip', {
                reason: 'no-instance-after-mount',
                source: options.source || '',
                key: options.key || '',
                shell: summarizeShellDebug(shell)
            });
            return false;
        }

        var payload = injectShellConfigIntoFullStatePayload(shell, fullState, options);
        if (documentState && typeof documentState === 'object') {
            payload = apdMergeRestorableDocumentIntoFullStatePayload(payload, documentState, 'importFullProductStateToShell');
        }
        payload = buildCanonicalFullState(payload, documentState, shell.__apdCreateMountConfig || shell.__apdMountConfig || {});
        var payloadElementDefinitions = apdCollectElementDefinitionsFromPayload(payload);
        if (payloadElementDefinitions.length) {
            apdRememberShellRuntimeElements(shell, payloadElementDefinitions);
        }
        var replaceOptions = {
            replaceViews: options.replaceViews !== false,
            replaceSnapshots: options.replaceSnapshots !== false
        };

        logApdVariationDebug('runtimeBridge:importFullProductStateToShell:before', {
            source: options.source || '',
            key: options.key || '',
            shell: summarizeShellDebug(shell),
            stateKeys: payload && typeof payload === 'object' ? Object.keys(payload) : [],
            fullStateDocument: summarizeViewContainer(payload && typeof payload === 'object' ? (payload.document || payload.initialDocument || payload.documentState || payload) : null),
            beforeLayout: summarizeLayoutDebug(getExportedRuntimeLayout(instance || null)),
            beforeDocument: summarizeViewContainer(exportDesign(instance || null))
        });

        var method = '';
        try {
            withBootImportPermissions(instance || null, shell && shell.__apdCreateMountConfig ? shell.__apdCreateMountConfig.permissions : null, function () {
                if (instance.util && instance.util.state && typeof instance.util.state.importFull === 'function') {
                    instance.util.state.importFull(clonePlainObject(payload), replaceOptions);
                    method = 'util.state.importFull';
                } else if (instance.util && instance.util.state && typeof instance.util.state.replaceProduct === 'function') {
                    instance.util.state.replaceProduct(clonePlainObject(payload), {
                        recreate: false,
                        replaceViews: replaceOptions.replaceViews,
                        replaceSnapshots: replaceOptions.replaceSnapshots
                    });
                    method = 'util.state.replaceProduct(recreate:false)';
                }
            });
        } catch (error) {
            logApdVariationDebug('runtimeBridge:importFullProductStateToShell:error', {
                source: options.source || '',
                key: options.key || '',
                message: error && error.message ? error.message : String(error),
                stateKeys: payload && typeof payload === 'object' ? Object.keys(payload) : []
            });
            method = '';
        }

        if (method && payloadElementDefinitions.length) {
            apdApplyPreservedRuntimeElements(shell, instance, [payloadElementDefinitions]);
        }
        var drawingAreasApplied = method ? applyDrawingAreaSnapshotPayload(instance, payload, method) : false;
        var rebuilt = method ? rebuildImportedDocument(instance) : false;
        var strictLayoutApplied = method ? applyStrictRuntimeConfigAfterVariationFullState(shell, instance, {
            source: options.source || '',
            key: options.key || '',
            phase: 'after-importFull'
        }) : false;
        var directStoreApplied = false;
        var payloadDocument = payload && typeof payload === 'object' ? (payload.document || payload.initialDocument || payload.documentState || payload) : null;
        var afterFullState = exportState(instance || null);
        var afterFullStateDocument = afterFullState && typeof afterFullState === 'object' ? (afterFullState.initialDocument || afterFullState.document || afterFullState) : null;
        if (method && payloadDocument && payloadHasViews(payloadDocument) && !exportedDocumentHasViews(instance || null) && countBootViews(afterFullStateDocument) <= 0) {
            directStoreApplied = applyDocumentDirectlyToRuntimeStore(instance || null, payloadDocument, 'importFullProductStateToShell');
            if (directStoreApplied) {
                rebuilt = true;
            }
        }
        logApdVariationDebug('runtimeBridge:importFullProductStateToShell:after', {
            source: options.source || '',
            key: options.key || '',
            method: method,
            rebuilt: rebuilt,
            drawingAreasApplied: drawingAreasApplied,
            strictLayoutApplied: strictLayoutApplied,
            directStoreApplied: directStoreApplied,
            shell: summarizeShellDebug(shell),
            afterLayout: summarizeLayoutDebug(getExportedRuntimeLayout(instance || null)),
            afterDocument: summarizeViewContainer(exportDesign(instance || null)),
            afterStateDocument: summarizeViewContainer((function () {
                var state = exportState(instance || null);
                return state && typeof state === 'object' ? (state.initialDocument || state.document || state) : null;
            })())
        });

        if (method && documentState && typeof documentState === 'object' && options.importDocumentFallback !== false) {
            importDocumentStateToShell(shell, documentState, {
                source: (options.source || 'full-state') + ':document-after-importFull',
                key: options.key || '',
                replaceViews: replaceOptions.replaceViews,
                replaceSnapshots: replaceOptions.replaceSnapshots
            });
            applyStrictRuntimeConfigAfterVariationFullState(shell, instance, {
                source: (options.source || 'full-state') + ':after-document-fallback',
                key: options.key || '',
                phase: 'after-document-fallback-schedule'
            });
            scheduleCanvasRestoreWatchdog(shell, instance || null, documentState, (options.source || 'full-state') + ':after-document-fallback');
        } else if (method && payloadDocument && typeof payloadDocument === 'object') {
            scheduleCanvasRestoreWatchdog(shell, instance || null, payloadDocument, (options.source || 'full-state') + ':after-importFull');
        }

        return !!method;
    }

    function importDocumentStateToShell(shell, documentState, options) {
        options = options || {};
        if (!shell || !documentState || typeof documentState !== 'object') {
            logApdVariationDebug('runtimeBridge:importDocumentStateToShell:skip', {
                reason: !shell ? 'no-shell' : 'no-document-state',
                document: summarizeViewContainer(documentState || null)
            });
            return false;
        }

        var instance = shell.__apdInstance || null;
        if (!instance) {
            mountOne(shell);
            instance = shell.__apdInstance || null;
        }

        if (!instance) {
            logApdVariationDebug('runtimeBridge:importDocumentStateToShell:skip', {
                reason: 'no-instance-after-mount',
                shell: summarizeShellDebug(shell),
                document: summarizeViewContainer(documentState)
            });
            return false;
        }

        var payload = normalizeDocumentHotStatePayload(documentState) || clonePlainObject(documentState);
        if (!payloadHasViews(payload)) {
            logApdVariationDebug('runtimeBridge:importDocumentStateToShell:skip', {
                reason: 'document-has-no-views',
                shell: summarizeShellDebug(shell),
                document: summarizeViewContainer(payload)
            });
            return false;
        }

        var replaceOptions = {
            replaceViews: options.replaceViews !== false,
            replaceSnapshots: options.replaceSnapshots !== false
        };
        var importToken = String(Date.now()) + ':' + String(Math.random()).slice(2);
        shell.__apdDocumentImportToken = importToken;
        shell.__apdBootPayload = {
            initialDocument: clonePlainObject(payload),
            initialState: null
        };

        function runDocumentImport(reason, delay) {
            if (!shell.isConnected || shell.__apdDocumentImportToken !== importToken) {
                logApdVariationDebug('runtimeBridge:importDocumentStateToShell:retry-skip', {
                    reason: !shell.isConnected ? 'shell-disconnected' : 'stale-token',
                    source: options.source || '',
                    key: options.key || '',
                    attemptReason: reason || '',
                    delay: delay || 0,
                    shell: summarizeShellDebug(shell)
                });
                return false;
            }

            var liveInstance = shell.__apdInstance || instance || null;
            if (!liveInstance) {
                logApdVariationDebug('runtimeBridge:importDocumentStateToShell:retry-skip', {
                    reason: 'no-live-instance',
                    source: options.source || '',
                    key: options.key || '',
                    attemptReason: reason || '',
                    delay: delay || 0,
                    shell: summarizeShellDebug(shell),
                    document: summarizeViewContainer(payload)
                });
                return false;
            }

            if (reason !== 'immediate' && runtimeDocumentSatisfiesExpectedPayload(liveInstance || null, payload)) {
                shell.__apdDocumentImportToken = '';
                return true;
            }

            logApdVariationDebug('runtimeBridge:importDocumentStateToShell:before', {
                source: options.source || '',
                key: options.key || '',
                attemptReason: reason || '',
                delay: delay || 0,
                shell: summarizeShellDebug(shell),
                document: summarizeViewContainer(payload),
                beforeDocument: summarizeViewContainer(exportDesign(liveInstance || null))
            });

            var preservedElementDefinitions = apdMergeElementDefinitionGroups([
                shell && Array.isArray(shell.__apdRuntimeElementDefinitions) ? shell.__apdRuntimeElementDefinitions : [],
                apdGetRuntimeElementDefinitions(liveInstance || null),
                apdCollectElementDefinitionsFromPayload(shell && shell.__apdBootPayload ? shell.__apdBootPayload : {})
            ]);
            if (preservedElementDefinitions.length) {
                apdRememberShellRuntimeElements(shell, preservedElementDefinitions);
            }

            var method = '';
            try {
                withBootImportPermissions(liveInstance || null, shell && shell.__apdCreateMountConfig ? shell.__apdCreateMountConfig.permissions : null, function () {
                    var canonicalDocumentState = buildCanonicalDocumentState(payload, shell && (shell.__apdCreateMountConfig || shell.__apdMountConfig) ? (shell.__apdCreateMountConfig || shell.__apdMountConfig) : {});
                    if (liveInstance.util && liveInstance.util.state && typeof liveInstance.util.state.importPart === 'function') {
                        liveInstance.util.state.importPart('document', clonePlainObject(canonicalDocumentState), replaceOptions);
                        method = 'util.state.importPart(document)';
                    }
                });
            } catch (error) {
                logApdVariationDebug('runtimeBridge:importDocumentStateToShell:error', {
                    source: options.source || '',
                    key: options.key || '',
                    attemptReason: reason || '',
                    delay: delay || 0,
                    message: error && error.message ? error.message : String(error),
                    document: summarizeViewContainer(payload)
                });
                return false;
            }

            if (!method) {
                var actionImportResult = applyRuntimeDocumentActionSnapshot(liveInstance || null, payload, 'importDocumentStateToShell');
                if (actionImportResult && actionImportResult.method) {
                    method = actionImportResult.method;
                } else {
                    logApdVariationDebug('runtimeBridge:importDocumentStateToShell:skip', {
                        reason: 'importDocument-unavailable',
                        shell: summarizeShellDebug(shell),
                        document: summarizeViewContainer(payload)
                    });
                    return false;
                }
            }

            if (preservedElementDefinitions.length) {
                apdApplyPreservedRuntimeElements(shell, liveInstance, [preservedElementDefinitions]);
            }
            var drawingAreasApplied = applyDrawingAreaSnapshotPayload(liveInstance, payload, method);
            var rebuilt = rebuildImportedDocument(liveInstance);
            var strictLayoutApplied = applyStrictRuntimeConfigAfterVariationFullState(shell, liveInstance, {
                source: options.source || '',
                key: options.key || '',
                phase: 'after-importDocument',
                attemptReason: reason || '',
                delay: delay || 0
            });
            var directStoreApplied = false;
            var afterImportDocument = exportDesign(liveInstance || null);
            var afterImportState = exportState(liveInstance || null);
            var afterImportStateDocument = afterImportState && typeof afterImportState === 'object' ? (afterImportState.initialDocument || afterImportState.document || afterImportState) : null;
            var expectedImportObjects = countPayloadOwnObjects(payload);
            var afterImportObjects = Math.max(countPayloadOwnObjects(afterImportDocument || {}), countPayloadOwnObjects(afterImportStateDocument || {}));
            var afterImportViews = Math.max(countBootViews(afterImportDocument || {}), countBootViews(afterImportStateDocument || {}));
            if ((!exportedDocumentHasViews(liveInstance || null) && afterImportViews <= 0) || (expectedImportObjects > 0 && afterImportObjects <= 0)) {
                directStoreApplied = applyDocumentDirectlyToRuntimeStore(liveInstance || null, payload, 'importDocumentStateToShell:' + String(reason || ''));
                if (directStoreApplied) {
                    rebuilt = true;
                }
            }
            apdApplyRuntimeUploadConfigToInstance(liveInstance || null, shell && shell.__apdCreateMountConfig && shell.__apdCreateMountConfig.moduleConfig ? shell.__apdCreateMountConfig.moduleConfig.upload : null);
            apdApplyRuntimePermissionsToInstance(liveInstance || null, shell && shell.__apdCreateMountConfig ? shell.__apdCreateMountConfig.permissions : null);
            logApdVariationDebug('runtimeBridge:importDocumentStateToShell:after', {
                source: options.source || '',
                key: options.key || '',
                attemptReason: reason || '',
                delay: delay || 0,
                method: method,
                rebuilt: rebuilt,
                drawingAreasApplied: drawingAreasApplied,
                strictLayoutApplied: strictLayoutApplied,
                directStoreApplied: directStoreApplied,
                shell: summarizeShellDebug(shell),
                expectedDocument: summarizeViewContainer(payload),
                afterDocument: summarizeViewContainer(exportDesign(liveInstance || null)),
                afterStateDocument: summarizeViewContainer((function () {
                    var state = exportState(liveInstance || null);
                    return state && typeof state === 'object' ? (state.initialDocument || state.document || state) : null;
                })())
            });
            scheduleCanvasRestoreWatchdog(shell, liveInstance || null, payload, 'importDocumentStateToShell:' + String(reason || ''));
            return true;
        }

        var imported = runDocumentImport('immediate', 0);

        // AsukaDesigner finishes parts of its boot on microtasks / animation frames.
        // The local demo imports after the initial instance is already ready; the
        // WooCommerce switch used to import immediately after createAsukaDesigner(),
        // which could update document state before the Fabric canvas was actually
        // ready to rebuild. Re-apply the exact same document a few times with
        // replaceViews/replaceSnapshots. This is idempotent and keeps the simple
        // importDocument() path while making it run after the runtime has settled.
        [0, 80, 220, 500].forEach(function (delay) {
            window.setTimeout(function () {
                runDocumentImport('post-mount-ready', delay);
            }, delay);
        });

        return !!imported;
    }



    function getShellDebugState(shell) {
        var instance = shell && shell.__apdInstance ? shell.__apdInstance : null;
        var exported = {
            design: exportDesign(instance || null),
            state: exportState(instance || null)
        };
        var exportedState = exported.state || {};
        return {
            shell: summarizeShellDebug(shell),
            mounted: !!instance,
            restoreDiagnostics: apdDebugSummarizeRuntimeRestoreState(instance || null),
            rawMountConfig: summarizeMountPayload(shell && shell.__apdRawMountConfig ? shell.__apdRawMountConfig : {}),
            mountConfig: summarizeMountPayload(shell && shell.__apdMountConfig ? shell.__apdMountConfig : {}),
            createMountConfig: summarizeMountPayload(shell && shell.__apdCreateMountConfig ? shell.__apdCreateMountConfig : {}),
            bootPayload: summarizeMountPayload(shell && shell.__apdBootPayload ? shell.__apdBootPayload : {}),
            runtimeLayout: summarizeLayoutDebug(getExportedRuntimeLayout(instance || null)),
            exportedStateLayout: summarizeLayoutDebug(exportedState && typeof exportedState === 'object' ? exportedState.layout : null),
            exportedUiLayout: summarizeLayoutDebug(exportedState && exportedState.ui && typeof exportedState.ui === 'object' ? exportedState.ui.layout : null),
            exportedDocument: summarizeViewContainer(exported.design || {}),
            exportedStateDocument: summarizeViewContainer(exportedState && typeof exportedState === 'object' ? (exportedState.initialDocument || exportedState.document || exportedState) : null)
        };
    }

    window.APDRuntimeBridge = {
        mountOne: mountOne,
        importDocumentStateToShell: importDocumentStateToShell,
        importFullProductStateToShell: importFullProductStateToShell,
        getShellDebugState: getShellDebugState,
        mountAll: function (scope) {
            (scope || document).querySelectorAll('[data-apd-shell]').forEach(mountOne);
        },
        syncShell: function (shell, options) {
            if (!shell) {
                return { design: {}, state: {}, preview: '', pricing: null };
            }

            var syncNow = Date.now ? Date.now() : (new Date()).getTime();
            shell.__apdInternalSyncInProgress = (shell.__apdInternalSyncInProgress || 0) + 1;
            shell.__apdSuppressRuntimeHookUntil = Math.max(Number(shell.__apdSuppressRuntimeHookUntil || 0), syncNow + 650);

            try {
                var instance = shell.__apdInstance || null;
                var strictPermissions = shell.__apdCreateMountConfig ? shell.__apdCreateMountConfig.permissions : null;
                var exported = withInternalStateExportPermissions(instance || null, strictPermissions, function () {
                    return {
                        design: exportDesign(instance),
                        state: exportState(instance)
                    };
                }) || { design: {}, state: {} };
                var design = exported.design || {};
                var state = exported.state || {};
                var fallbackConfig = shell.__apdCreateMountConfig || shell.__apdMountConfig || shell.__apdRawMountConfig || {};
                var bootPayload = shell.__apdBootPayload && typeof shell.__apdBootPayload === 'object' ? shell.__apdBootPayload : {};
                var jsonField = shell.querySelector('[data-apd-design-json]');
                var stateField = shell.querySelector('[data-apd-state-json]');
                var previousDesign = jsonField ? safeParseJson(jsonField.value || '{}', {}) : {};
                var previousState = stateField ? safeParseJson(stateField.value || '{}', {}) : {};
                var stateDocument = state && typeof state === 'object' ? (state.initialDocument || state.document || state.documentState || state) : null;
                if (!apdDocumentHasRestorableContent(design)) {
                    if (apdDocumentHasRestorableContent(stateDocument)) {
                        design = clonePlainObject(stateDocument);
                    } else if (apdDocumentHasRestorableContent(previousDesign)) {
                        design = clonePlainObject(previousDesign);
                    } else {
                        var previousStateDocument = previousState && typeof previousState === 'object' ? (previousState.initialDocument || previousState.document || previousState.documentState || previousState) : null;
                        if (apdDocumentHasRestorableContent(previousStateDocument)) {
                            design = clonePlainObject(previousStateDocument);
                        }
                    }
                }
                if (!apdDocumentHasRestorableContent(design)) {
                    var bootDocument = bootPayload.initialDocument || (bootPayload.initialState && typeof bootPayload.initialState === 'object' ? (bootPayload.initialState.initialDocument || bootPayload.initialState.document || bootPayload.initialState.documentState) : null);
                    if (apdDocumentHasRestorableContent(bootDocument)) {
                        design = clonePlainObject(bootDocument);
                    }
                }
                if (!apdDocumentHasRestorableContent(design)) {
                    var fallbackDocument = apdBuildDocumentFromRuntimeState(instance || null, fallbackConfig);
                    if (apdDocumentHasRestorableContent(fallbackDocument)) {
                        design = fallbackDocument;
                    }
                }
                stateDocument = state && typeof state === 'object' ? (state.initialDocument || state.document || state.documentState || state) : null;
                if (!apdDocumentHasRestorableContent(stateDocument) && apdDocumentHasRestorableContent(previousState)) {
                    state = clonePlainObject(previousState);
                    stateDocument = state && typeof state === 'object' ? (state.initialDocument || state.document || state.documentState || state) : null;
                }
                if (!apdDocumentHasRestorableContent(stateDocument) && apdDocumentHasRestorableContent(design)) {
                    state = apdBuildFullStateFallbackFromDocument(design, state, fallbackConfig);
                }
                var preview = exportPreview(shell, state, instance);
            logApdVariationDebug('runtimeBridge:syncShell:export', {
                shell: summarizeShellDebug(shell),
                design: summarizeViewContainer(design),
                stateDocument: summarizeViewContainer(state && typeof state === 'object' ? (state.initialDocument || state.document || state) : null)
            });
            var basePrice = options && typeof options.basePrice === 'number' ? options.basePrice : undefined;
            var pricing = getPricingBreakdown(instance, basePrice);

            var previewDataField = shell.querySelector('[data-apd-preview-data]');
            var priceAdjustmentField = shell.querySelector('[data-apd-price-adjustment]');
            var priceTotalField = shell.querySelector('[data-apd-price-total]');
            var priceBreakdownField = shell.querySelector('[data-apd-price-breakdown]');
            var pricingPayloadField = shell.querySelector('[data-apd-pricing-payload]');
            var payloadVersionField = shell.querySelector('[data-apd-payload-version]');

            var designJson = JSON.stringify(design || {});
            var stateJson = JSON.stringify(state || {});

            if (jsonField && jsonField.value !== designJson) {
                jsonField.value = designJson;
            }

            if (stateField && stateField.value !== stateJson) {
                stateField.value = stateJson;
            }

            if (preview) {
                shell.__apdLastPreviewDataUrl = preview;
            }
            if (previewDataField && previewDataField.value !== (preview || '')) {
                previewDataField.value = preview || '';
            }

            var normalizedPricing = pricing ? normalizePricingPayload(pricing, typeof basePrice === 'number' ? basePrice : 0) : null;

            if (priceAdjustmentField) {
                priceAdjustmentField.value = normalizedPricing ? String(Number(normalizedPricing.adjustment_total || 0)) : '0';
            }

            if (priceTotalField) {
                priceTotalField.value = normalizedPricing ? String(Number(normalizedPricing.final_price || 0)) : '0';
            }

            if (priceBreakdownField) {
                priceBreakdownField.value = normalizedPricing ? JSON.stringify(normalizedPricing) : '';
            }

            if (pricingPayloadField) {
                pricingPayloadField.value = normalizedPricing ? JSON.stringify(normalizedPricing) : '';
            }

            if (payloadVersionField) {
                payloadVersionField.value = normalizedPricing ? String(Number(normalizedPricing.payload_version || 1)) : '1';
            }

            if (options && options.showStatus) {
                setStatus(shell, runtimeLabel('runtimeDesignPayloadSynchronized', 'Design payload synchronized.'), 'success');
            }

            return {
                design: design || {},
                state: state || {},
                preview: preview || '',
                pricing: normalizedPricing || null
            };
            } finally {
                shell.__apdInternalSyncInProgress = Math.max(0, (shell.__apdInternalSyncInProgress || 1) - 1);
                var releaseDelay = 700;
                window.setTimeout(function () {
                    if (!shell.__apdInternalSyncInProgress) {
                        var releaseNow = Date.now ? Date.now() : (new Date()).getTime();
                        if (Number(shell.__apdSuppressRuntimeHookUntil || 0) <= releaseNow) {
                            shell.__apdSuppressRuntimeHookUntil = 0;
                        }
                    }
                }, releaseDelay);
            }
        }
    };
})();
