(function (wp) {
    const { registerBlockType } = wp.blocks;
    const { InspectorControls, BlockControls, useBlockProps } = wp.blockEditor || wp.editor;
    const { PanelBody, SelectControl, Spinner, Notice, ToolbarGroup, ToolbarButton, Button } = wp.components;
    const { useEffect, useState, useRef } = wp.element;
    const { __ } = wp.i18n;
    const apiFetch = wp.apiFetch;

    const BLOCK_SLUG = 'griffinforms/form';
    const REST_BASE = '/griffinforms/v1/gutenberg';
    const GF_THEME_FONT_ATTR = 'data-gf-block-theme-font';

    const IconBlock = wp.element.createElement(
        'img',
        { src: griffinformsBlockIcons.block, alt: __('GriffinForms Block', 'griffinforms-form-builder'), width: 20, height: 20 }
    );

    const buildThemeFontUrl = (fontName) => {
        if (!fontName) {
            return '';
        }
        const encoded = encodeURIComponent(fontName.trim()).replace(/%20/g, '+');
        return 'https://fonts.googleapis.com/css2?family=' + encoded + ':wght@400;500;600;700&display=swap';
    };

    const ensureThemeFonts = (fonts) => {
        if (!Array.isArray(fonts) || !fonts.length) {
            return;
        }
        const head = document.head || document.getElementsByTagName('head')[0];
        if (!head) {
            return;
        }
        fonts.forEach((fontName) => {
            const trimmed = String(fontName || '').trim();
            if (!trimmed) {
                return;
            }
            const selector = 'link[' + GF_THEME_FONT_ATTR + '][data-gf-font-name="' + trimmed.replace(/"/g, '\\"') + '"]';
            if (document.querySelector(selector)) {
                return;
            }
            const fontUrl = buildThemeFontUrl(trimmed);
            if (!fontUrl) {
                return;
            }
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = fontUrl;
            link.setAttribute(GF_THEME_FONT_ATTR, '1');
            link.setAttribute('data-gf-font-name', trimmed);
            head.appendChild(link);
        });
    };

    const scopeThemeCss = (themeCss, previewScopeClass) => {
        if (!themeCss || !previewScopeClass) {
            return themeCss || '';
        }

        const scopedSelector = '.' + String(previewScopeClass);
        return String(themeCss).replace(/\.griffinforms-block-preview\b/g, scopedSelector);
    };

    const normalizePreviewFieldType = (rawType) => {
        const type = String(rawType || '').trim().toLowerCase();
        const aliases = {
            text_input: 'inputtext',
            email_input: 'inputemail',
            number_input: 'inputnumber',
            password_input: 'inputpassword',
            url_input: 'inputurl',
            phone_input: 'inputphone',
            date_input: 'inputdate',
            time_input: 'inputtime',
            address_input: 'inputaddress',
            select_input: 'selectfield',
            file_upload: 'fileupload',
            terms_conditions: 'termsconditions',
            radio: 'inputradio',
            checkbox: 'inputcheckbox',
            checkbox_radio: 'checkbox_radio',
        };

        return aliases[type] || type || 'inputtext';
    };

    const resolvePreviewRendererType = (field) => {
        const normalizedType = normalizePreviewFieldType(field && field.field_type);
        const options = Array.isArray(field && field.options) ? field.options : [];
        const hasAddressShape = !!(field && Object.keys(field.address_labels || {}).length);
        const hasPhoneShape = !!(field && field.phone_display_mode);
        const hasTermsShape = !!(field && field.terms && typeof field.terms === 'object' && Object.keys(field.terms).length);

        if (normalizedType === 'inputtext') {
            if (hasAddressShape) {
                return 'inputaddress';
            }
            if (hasPhoneShape) {
                return 'inputphone';
            }
            if (hasTermsShape) {
                return 'termsconditions';
            }
        }

        if (normalizedType === 'checkbox_radio') {
            return 'checkbox_radio';
        }

        if (normalizedType === 'inputtext' && options.length) {
            return 'checkbox_radio';
        }

        return normalizedType;
    };

    const buildProgressBarHtml = (structure, activePage, esc) => {
        const pb = structure && structure.progress_bar;
        if (!pb || !pb.toggle) {
            return '';
        }
        const pages = Array.isArray(structure.pages) ? structure.pages : [];
        if (pages.length < 2) {
            return '';
        }
        const style = pb.style === 'tabs' ? 'tabs' : 'stepper';
        const safeActive = Math.min(Math.max(0, activePage || 0), pages.length - 1);

        let items = '';
        pages.forEach(function (page, i) {
            const state = i < safeActive ? 'complete' : (i === safeActive ? 'active' : 'upcoming');
            const stepData = (page && page.step_data) ? page.step_data : {};
            const showPageHeadings = !!(pb.show_page_headings);
            const stepName = String(stepData.step_name || '').trim();
            const pageHeading = String((page && page.heading) || '').trim();
            const pageName = String((page && page.name) || '').trim();
            let rawLabel;
            if (stepName !== '') {
                rawLabel = stepName;
            } else if (showPageHeadings && pageHeading !== '') {
                rawLabel = pageHeading;
            } else if (showPageHeadings && pageName !== '') {
                rawLabel = pageName;
            } else {
                rawLabel = 'Step ' + (i + 1);
            }
            const label = esc(rawLabel);
            const icon = String(stepData.step_icon || '').trim();
            let markerInner;
            const iconStyle = 'font-family:\'Material Symbols Outlined\' !important;font-size:1.1rem;line-height:1;font-weight:normal;font-style:normal;font-variation-settings:\'FILL\' 0,\'wght\' 400,\'GRAD\' 0,\'opsz\' 24;-webkit-font-smoothing:antialiased;transform:translateY(0);';
            if (state === 'complete') {
                markerInner = '<span class="material-symbols-outlined griffinforms-progress-bar__marker-icon" style="' + iconStyle + '">check</span>';
            } else if (icon) {
                markerInner = '<span class="material-symbols-outlined griffinforms-progress-bar__marker-icon" style="' + iconStyle + '">' + esc(icon) + '</span>';
            } else {
                markerInner = '<span class="griffinforms-progress-bar__marker-number" style="transform:none;">' + (i + 1) + '</span>';
            }
            if (i > 0) {
                const segState = i <= safeActive ? 'complete' : 'upcoming';
                items += '<div class="griffinforms-progress-bar__connector-segment" data-gf-progress-state="' + segState + '"></div>';
            }
            items += '<div class="griffinforms-progress-bar__step" data-gf-progress-state="' + state + '">'
                + '<div class="griffinforms-progress-bar__marker">' + markerInner + '</div>'
                + '<span class="griffinforms-progress-bar__label">' + label + '</span>'
                + '</div>';
        });

        return '<div class="griffinforms-progress-bar" data-gf-progress-style="' + style + '" data-gf-progress-bar="true">'
            + '<div class="griffinforms-progress-bar__track">'
            + items
            + '</div>'
            + '</div>';
    };

    const buildPreviewHtml = (structure, customSubmitLabel, activePage, previewScopeClass) => {
        if (!structure || typeof structure !== 'object') {
            return '';
        }

        const heading = structure.heading || '';
        const description = structure.description || '';
        const submitLabel = structure.submit_label || '';
        const truncated = !!structure.truncated;
        const truncatedNotice = structure.truncated_notice || '';
        const pages = Array.isArray(structure.pages) ? structure.pages : [];
        const safePageIndex = Math.min(Math.max(0, activePage || 0), Math.max(0, pages.length - 1));

        const esc = (text) => {
            return String(text || '')
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#039;');
        };

        const controlRenderers = {
            textarea: (ph, styleAttrs) => '<textarea class="gf-bp-control gf-bp-textarea"' + styleAttrs + ' placeholder="' + ph + '"></textarea>',
            selectfield: (ph, styleAttrs, options) => {
                let selectHtml = '<select class="gf-bp-control gf-bp-select"' + styleAttrs + '>';
                if (options.length) {
                    options.forEach(function (group) {
                        const groupLabel = group.group || '';
                        const groupOptions = Array.isArray(group.options) ? group.options : [];
                        if (groupLabel) {
                            selectHtml += '<optgroup label="' + esc(groupLabel) + '">';
                        }
                        groupOptions.forEach(function (opt) {
                            const label = opt.label ? esc(opt.label) : '';
                            selectHtml += '<option>' + label + '</option>';
                        });
                        if (groupLabel) {
                            selectHtml += '</optgroup>';
                        }
                    });
                } else {
                    selectHtml += '<option>' + (ph || esc(__('Select an option', 'griffinforms-form-builder'))) + '</option>';
                }
                selectHtml += '</select>';
                return selectHtml;
            },
            inputradio: (ph, styleAttrs, options) => {
                let radios = '';
                options.forEach(function (group) {
                    const groupOptions = Array.isArray(group.options) ? group.options : [];
                    if (!groupOptions.length) {
                        return;
                    }
                    radios += '<div class="gf-bp-options-col">';
                    groupOptions.forEach(function (opt) {
                        const label = opt.label ? esc(opt.label) : esc(__('Option', 'griffinforms-form-builder'));
                        radios += '<div class="gf-bp-options"><span class="gf-bp-radio"' + styleAttrs + '></span><span>' + label + '</span></div>';
                    });
                    radios += '</div>';
                });
                return radios ? '<div class="gf-bp-options-wrap">' + radios + '</div>' : '<div class="gf-bp-options"><span class="gf-bp-radio"' + styleAttrs + '></span><span>' + esc(__('Option', 'griffinforms-form-builder')) + '</span></div>';
            },
            inputcheckbox: (ph, styleAttrs, options) => {
                let checks = '';
                options.forEach(function (group) {
                    const groupOptions = Array.isArray(group.options) ? group.options : [];
                    if (!groupOptions.length) {
                        return;
                    }
                    checks += '<div class="gf-bp-options-col">';
                    groupOptions.forEach(function (opt) {
                        const label = opt.label ? esc(opt.label) : esc(__('Option', 'griffinforms-form-builder'));
                        checks += '<div class="gf-bp-options"><span class="gf-bp-checkbox"' + styleAttrs + '></span><span>' + label + '</span></div>';
                    });
                    checks += '</div>';
                });
                return checks ? '<div class="gf-bp-options-wrap">' + checks + '</div>' : '<div class="gf-bp-options"><span class="gf-bp-checkbox"' + styleAttrs + '></span><span>' + esc(__('Option', 'griffinforms-form-builder')) + '</span></div>';
            },
            checkbox_radio: (ph, styleAttrs, options) => {
                let choices = '';
                options.forEach(function (group) {
                    const groupOptions = Array.isArray(group.options) ? group.options : [];
                    if (!groupOptions.length) {
                        return;
                    }
                    choices += '<div class="gf-bp-options-col">';
                    groupOptions.forEach(function (opt) {
                        const label = opt.label ? esc(opt.label) : esc(__('Option', 'griffinforms-form-builder'));
                        choices += '<div class="gf-bp-options"><span class="gf-bp-checkbox"' + styleAttrs + '></span><span>' + label + '</span></div>';
                    });
                    choices += '</div>';
                });
                return choices ? '<div class="gf-bp-options-wrap">' + choices + '</div>' : '<div class="gf-bp-options"><span class="gf-bp-checkbox"' + styleAttrs + '></span><span>' + esc(__('Option', 'griffinforms-form-builder')) + '</span></div>';
            },
            inputrichtext: (_ph, _styleAttrs, _options, field) => {
                const rtHeight = field && field.richtext_min_height ? parseInt(field.richtext_min_height, 10) : 120;
                const rtPlaceholder = field && field.richtext_placeholder ? esc(field.richtext_placeholder) : esc(__('Write something…', 'griffinforms-form-builder'));
                const rtToolbar = Array.isArray(field && field.richtext_toolbar) && field.richtext_toolbar.length
                    ? field.richtext_toolbar
                    : ['bold', 'italic', 'underline', 'bulletlist', 'link'];
                const editorThemeStyle = structure && structure.richtext_editor_style ? structure.richtext_editor_style : '';
                const toolbarLabels = {bold:'B', italic:'I', underline:'U', strike:'S̶', heading1:'H1', heading2:'H2', heading3:'H3', bulletlist:'≡', orderedlist:'1.', blockquote:'❝', code:'</>', link:'🔗', horizontalrule:'—', clearformatting:'Tx'};
                const wrapStyle = editorThemeStyle !== ''
                    ? editorThemeStyle + 'overflow:hidden;'
                    : 'border:1px solid #ccc;border-radius:4px;overflow:hidden;';
                const editorStyle = 'width:100%;box-sizing:border-box;height:' + rtHeight + 'px;display:flex;align-items:center;justify-content:center;border-top:0;';
                let toolbarHtml = '';
                rtToolbar.forEach(function(item) {
                    const lbl = toolbarLabels[item] || item;
                    toolbarHtml += '<span style="font-size:10px;font-weight:600;color:#6c757d;min-width:20px;text-align:center;">' + esc(lbl) + '</span>';
                });
                return '<div style="' + esc(wrapStyle) + '">'
                    + '<div style="background:#f8f9fa;border-bottom:1px solid #dee2e6;padding:4px 6px;display:flex;gap:6px;flex-wrap:wrap;">' + toolbarHtml + '</div>'
                    + '<div style="' + esc(editorStyle) + '">'
                    + '<span style="font-size:12px;color:#aaa;opacity:0.8;">' + rtPlaceholder + '</span>'
                    + '</div>'
                    + '</div>';
            },
            signature: (_ph, _styleAttrs, _options, field) => {
                const padHeight = field && field.pad_height ? parseInt(field.pad_height, 10) : 120;
                const sigPlaceholder = field && field.signature_placeholder ? esc(field.signature_placeholder) : esc(__('Sign here', 'griffinforms-form-builder'));
                const canvasThemeStyle = structure && structure.signature_canvas_style ? structure.signature_canvas_style : '';
                const bgColor = (field && field.signature_bg_color) ? field.signature_bg_color : '#ffffff';
                const penColor = (field && field.signature_pen_color) ? field.signature_pen_color : '#000000';
                let canvasStyle = 'width:100%;height:' + padHeight + 'px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;background-color:' + bgColor + ';';
                canvasStyle += canvasThemeStyle !== '' ? canvasThemeStyle : 'border:1px solid #ccc;border-radius:4px;';
                const clearBtn = canvasThemeStyle !== ''
                    ? '<button type="button" disabled data-gf-button-type="previous">' + esc(__('Clear', 'griffinforms-form-builder')) + '</button>'
                    : '<button type="button" disabled style="font-size:11px;padding:2px 8px;cursor:default;border:1px solid #ccc;border-radius:4px;background:#f5f5f5;">' + esc(__('Clear', 'griffinforms-form-builder')) + '</button>';
                return '<div class="gf-bp-control gf-bp-signature" style="' + esc(canvasStyle) + '">'
                    + '<span style="color:' + esc(penColor) + ';font-size:12px;opacity:0.4;">' + sigPlaceholder + '</span>'
                    + '</div>'
                    + '<div style="text-align:right;margin-top:4px;">' + clearBtn + '</div>';
            },
            inputrating: (_ph, _styleAttrs, _options, field) => {
                const themeSet = !!(structure && structure.theme_css);
                const scale = field && field.rating_scale ? parseInt(field.rating_scale, 10) : 5;
                const iconGroup = field && field.rating_icon_group ? field.rating_icon_group : 'star';
                const iconSize = field && field.rating_icon_size ? parseInt(field.rating_icon_size, 10) : 24;
                const iconSpacing = field && field.rating_icon_spacing ? parseInt(field.rating_icon_spacing, 10) : 4;
                const emptyColor = field && field.rating_color_empty ? field.rating_color_empty : '#d1d5db';
                const filledColor = field && field.rating_color_filled ? field.rating_color_filled : '#f5a623';
                const labels = Array.isArray(field && field.rating_step_labels) ? field.rating_step_labels : [];
                const customImageUrl = field && field.rating_custom_image_url ? field.rating_custom_image_url : '';
                const stepImageUrls = Array.isArray(field && field.rating_step_image_urls) ? field.rating_step_image_urls : [];
                const allowClear = field && String(field.rating_allow_clear || '') === '1';
                const iconMap = {
                    star: 'star-filled.svg',
                    heart: 'heart-filled.svg',
                    thumb: 'thumb-filled.svg',
                    face: 'face-filled.svg',
                    circle: 'circle-filled.svg',
                    flag: 'flag-filled.svg',
                    bolt: 'bolt-filled.svg',
                    diamond: 'diamond-filled.svg'
                };
                const iconBase = '/wp-content/plugins/griffinforms-form-builder-pro/admin/images/rating-icons/';
                let html = '<div class="gf-bp-rating" style="display:flex;flex-wrap:wrap;align-items:flex-start;margin-bottom:12px;row-gap:' + iconSpacing + 'px;">';
                for (let i = 0; i < scale; i++) {
                    const stepStyle = 'display:flex;flex-direction:column;align-items:center;min-width:' + iconSize + 'px;' + (i < scale - 1 ? 'margin-right:' + iconSpacing + 'px;' : '');
                    html += '<div class="gf-bp-rating-item" style="' + stepStyle + '">';
                    const stepImageUrl = stepImageUrls[i] || '';
                    const previewImageUrl = stepImageUrl || (iconGroup === 'custom' ? customImageUrl : '');
                    if (previewImageUrl) {
                        html += '<img src="' + previewImageUrl + '" alt="" style="display:block;width:auto;height:auto;max-height:' + iconSize + 'px;max-width:100%;object-fit:contain;">';
                    } else if (iconMap[iconGroup]) {
                        const iconUrl = iconBase + iconMap[iconGroup];
                        const emptyMaskStyle = [
                            'width:' + iconSize + 'px',
                            'height:' + iconSize + 'px',
                            'background-color:' + emptyColor,
                            '-webkit-mask-image:url(' + iconUrl + ')',
                            'mask-image:url(' + iconUrl + ')',
                            '-webkit-mask-repeat:no-repeat',
                            'mask-repeat:no-repeat',
                            '-webkit-mask-position:center',
                            'mask-position:center',
                            '-webkit-mask-size:contain',
                            'mask-size:contain'
                        ].join(';');
                        const filledMaskStyle = emptyMaskStyle.replace('background-color:' + emptyColor, 'background-color:' + filledColor);
                        html += '<span aria-hidden="true" style="' + emptyMaskStyle + ';display:block;"></span>';
                        html += '<span aria-hidden="true" style="' + filledMaskStyle + ';display:none;"></span>';
                    }
                    if (labels[i]) {
                        html += '<span class="gf-rating-label" style="font-size:11px;line-height:1.2;margin-top:4px;color:#6b7280;text-align:center;">' + esc(labels[i]) + '</span>';
                    }
                    html += '</div>';
                }
                if (allowClear) {
                    if (themeSet) {
                        html += '<div style="width:100%;"><button type="button" class="gf-rating-clear gf-bp-nav-prev griffinforms-previous-button" data-gf-button-type="previous">' + esc(__('Clear', 'griffinforms-form-builder')) + '</button></div>';
                    } else {
                        html += '<div style="width:100%;margin-top:0.25rem;"><button type="button" class="gf-rating-clear" style="display:inline-flex;align-items:center;justify-content:center;min-height:' + iconSize + 'px;padding:0.25rem 0.5rem;background:transparent;border:1px solid currentColor;border-radius:0;cursor:pointer;font-size:0.85rem;line-height:1.2;color:inherit;opacity:0.5;white-space:nowrap;">' + esc(__('Clear', 'griffinforms-form-builder')) + '</button></div>';
                    }
                }
                html += '</div>';
                return html;
            },
            inputlikert: (_ph, _styleAttrs, _options, field) => {
                const rows = Array.isArray(field && field.likert_rows) ? field.likert_rows : [{id:'row_1',label:'Row 1'},{id:'row_2',label:'Row 2'},{id:'row_3',label:'Row 3'}];
                const columns = Array.isArray(field && field.likert_columns) ? field.likert_columns : [{id:'col_1',label:'Strongly Disagree'},{id:'col_2',label:'Disagree'},{id:'col_3',label:'Neutral'},{id:'col_4',label:'Agree'},{id:'col_5',label:'Strongly Agree'}];
                const allowNa = !!(field && field.likert_allow_na);
                const colWidth = (field && field.likert_column_width) === 'equal' ? 'fixed' : 'auto';
                const lkStyle = structure && structure.likert_table_style && typeof structure.likert_table_style === 'object' ? structure.likert_table_style : {};
                const lkWrapper = lkStyle.wrapper ? lkStyle.wrapper : 'border:1px solid #dee2e6;border-radius:4px;';
                const lkBc = lkStyle.border_color ? lkStyle.border_color : '#dee2e6';
                const lkLabelColor = lkStyle.label_color ? lkStyle.label_color : '';
                const lkLabelCss = lkLabelColor ? 'color:' + esc(lkLabelColor) + ';' : '';
                const lkBgColor = lkStyle.bg_color ? lkStyle.bg_color : '';
                const lkBgCss = lkBgColor ? 'background-color:' + esc(lkBgColor) + ';' : '';
                const lkVb = 'border-left:1px solid ' + esc(lkBc) + ';';
                let html = '<div style="overflow:hidden;' + esc(lkWrapper) + '">';
                html += '<div style="overflow-x:auto;">';
                html += '<table style="width:100%;border-collapse:collapse;table-layout:' + colWidth + ';font-size:12px;' + lkBgCss + '">';
                html += '<thead><tr>';
                html += '<th style="text-align:left;padding:5px 8px;border-bottom:1px solid ' + esc(lkBc) + ';min-width:90px;"></th>';
                columns.forEach(function(col) {
                    html += '<th style="text-align:center;padding:5px 8px;border-bottom:1px solid ' + esc(lkBc) + ';' + lkVb + lkLabelCss + 'min-width:80px;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;">' + esc(col.label) + '</th>';
                });
                if (allowNa) {
                    html += '<th style="text-align:center;padding:5px 8px;border-bottom:1px solid ' + esc(lkBc) + ';' + lkVb + 'min-width:44px;color:#aaa;">N/A</th>';
                }
                html += '</tr></thead><tbody>';
                rows.forEach(function(row, ri) {
                    const isLast = ri === rows.length - 1;
                    const cellBorder = isLast ? 'none' : '1px solid ' + esc(lkBc);
                    html += '<tr>';
                    html += '<td style="text-align:left;padding:5px 8px;border-bottom:' + cellBorder + ';white-space:nowrap;' + lkLabelCss + '">' + esc(row.label) + '</td>';
                    columns.forEach(function() {
                        html += '<td style="text-align:center;padding:5px 8px;border-bottom:' + cellBorder + ';' + lkVb + '"><input type="radio" disabled style="opacity:0.6;"></td>';
                    });
                    if (allowNa) {
                        html += '<td style="text-align:center;padding:5px 8px;border-bottom:' + cellBorder + ';' + lkVb + '"><input type="radio" disabled style="opacity:0.35;"></td>';
                    }
                    html += '</tr>';
                });
                html += '</tbody></table></div></div>';
                return html;
            },
            imageselection: (_ph, styleAttrs, _options, field) => {
                const themeSet = !!(structure && structure.theme_css);
                const columnsDesktop = field && field.imagesel_columns_desktop ? Math.max(1, Math.min(6, parseInt(field.imagesel_columns_desktop, 10))) : 3;
                const showTitle = !!(field && field.imagesel_show_title);
                const showDescription = !!(field && field.imagesel_show_description);
                const optionList = Array.isArray(field && field.imagesel_options) ? field.imagesel_options.slice(0, 6) : [];
                const displayOptions = optionList.length ? optionList : [
                    { image_url: '', title: esc(__('Image Option', 'griffinforms-form-builder')), description: '' },
                    { image_url: '', title: esc(__('Image Option', 'griffinforms-form-builder')), description: '' },
                    { image_url: '', title: esc(__('Image Option', 'griffinforms-form-builder')), description: '' }
                ];
                let html = '<div class="gf-bp-imageselection" style="display:grid;grid-template-columns:repeat(' + columnsDesktop + ',minmax(0,1fr));gap:12px;">';
                displayOptions.forEach(function(option, index) {
                    const imageUrl = option && option.image_url ? option.image_url : '';
                    const title = option && option.title ? esc(option.title) : esc(__('Image Option', 'griffinforms-form-builder'));
                    const description = option && option.description ? esc(option.description) : '';
                    const cardBaseStyle = themeSet ? 'overflow:hidden;position:relative;display:flex;flex-direction:column;height:100%;' : 'overflow:hidden;position:relative;display:flex;flex-direction:column;height:100%;border:1px solid #d0d7de;border-radius:8px;background:#fff;';
                    const selectedStyle = !themeSet && index === 0 ? 'border-color:var(--wp-admin-theme-color, #3858e9);z-index:1;box-shadow:none;' : '';
                    html += '<div class="gf-imgsel-card' + (index === 0 ? ' is-selected' : '') + '"' + styleAttrs + ' style="' + cardBaseStyle + selectedStyle + '">';
                    if (imageUrl) {
                        html += '<div class="gf-imgsel-card-media" style="aspect-ratio:1 / 1;background:#f6f7f7 url(' + imageUrl + ') center/cover no-repeat;"></div>';
                    } else {
                        html += '<div class="gf-imgsel-card-media" style="aspect-ratio:1 / 1;background:linear-gradient(135deg,#f6f7f7,#e9ecef);display:flex;align-items:center;justify-content:center;color:#8c8f94;font-size:11px;">' + esc(__('Image', 'griffinforms-form-builder')) + '</div>';
                    }
                    if ((showTitle && title) || (showDescription && description)) {
                        html += '<div class="gf-imgsel-card-body" style="padding:8px 10px;border-top:1px solid #e2e8f0;background:#fff;flex:1 1 auto;">';
                        if (showTitle && title) {
                            html += '<div style="font-size:12px;font-weight:600;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">' + title + '</div>';
                        }
                        if (showDescription && description) {
                            html += '<div style="margin-top:4px;font-size:11px;line-height:1.4;color:#646970;">' + description + '</div>';
                        }
                        html += '</div>';
                    }
                    html += '</div>';
                });
                html += '</div>';
                return html;
            },
            fileupload: (_ph, styleAttrs) => '<input class="gf-bp-control gf-bp-input" type="file"' + styleAttrs + '>',
            inputphone: (_ph, styleAttrs, _options, field) => {
                const displayMode = field && field.phone_display_mode ? field.phone_display_mode : 'flag_code';
                const formatLabel = (flag, code, name) => {
                    if (displayMode === 'code_only') {
                        return code;
                    }
                    if (displayMode === 'flag_code_name') {
                        return flag + ' ' + code + ' ' + name;
                    }
                    return flag + ' ' + code;
                };
                const samples = [
                    { flag: '🇺🇸', code: '+1', name: esc(__('United States', 'griffinforms-form-builder')) },
                    { flag: '🇬🇧', code: '+44', name: esc(__('United Kingdom', 'griffinforms-form-builder')) },
                    { flag: '🇮🇳', code: '+91', name: esc(__('India', 'griffinforms-form-builder')) },
                ];
                const selectStyleAttrs = ' data-gf-style-group="block-preview" data-gf-style-type="select_input"';
                return '<div class="gf-bp-phone-group" style="display:flex;gap:0;">' +
                    '<select class="gf-bp-control gf-bp-select gf-bp-phone-select"' + selectStyleAttrs + ' data-gf-phone-display-mode="' + displayMode + '" style="border-radius:4px 0 0 4px;border-top-right-radius:0;border-bottom-right-radius:0;">' +
                        '<option>' + esc(__('Country', 'griffinforms-form-builder')) + '</option>' +
                        samples.map(function(sample) {
                            return '<option>' + formatLabel(sample.flag, sample.code, sample.name) + '</option>';
                        }).join('') +
                    '</select>' +
                    '<input class="gf-bp-control gf-bp-input gf-bp-phone-input" type="tel"' + styleAttrs + ' placeholder="' + esc(__('Phone number', 'griffinforms-form-builder')) + '" style="border-left:0;border-radius:0 4px 4px 0;border-top-left-radius:0;border-bottom-left-radius:0;">' +
                '</div>';
            },
            inputaddress: (_ph, styleAttrs, _options, field) => {
                const labels = (field && field.address_labels) ? field.address_labels : {};
                const line2Enabled = field && typeof field.line2_enabled !== 'undefined' ? !!field.line2_enabled : true;
                const labelLine1 = esc(labels.line1 || __('Address Line 1', 'griffinforms-form-builder'));
                const labelLine2 = esc(labels.line2 || __('Address Line 2', 'griffinforms-form-builder'));
                const labelCity = esc(labels.city || __('City', 'griffinforms-form-builder'));
                const labelPostal = esc(labels.postal || __('Postal Code', 'griffinforms-form-builder'));
                const labelState = esc(labels.state || __('State / Province', 'griffinforms-form-builder'));
                const labelCountry = esc(labels.country || __('Country', 'griffinforms-form-builder'));

                let html = '<div class="gf-bp-address" style="display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:8px;">';
                html += '<div class="gf-bp-address-col" style="grid-column:1/-1;"><div class="gf-bp-control-wrap"><input class="gf-bp-control gf-bp-input" type="text"' + styleAttrs + ' placeholder="' + labelLine1 + '" aria-label="' + labelLine1 + '"></div></div>';
                if (line2Enabled) {
                    html += '<div class="gf-bp-address-col" style="grid-column:1/-1;"><div class="gf-bp-control-wrap"><input class="gf-bp-control gf-bp-input" type="text"' + styleAttrs + ' placeholder="' + labelLine2 + '" aria-label="' + labelLine2 + '"></div></div>';
                }
                html += '<div class="gf-bp-address-col" style="grid-column:1/9;"><div class="gf-bp-control-wrap"><input class="gf-bp-control gf-bp-input" type="text"' + styleAttrs + ' placeholder="' + labelCity + '" aria-label="' + labelCity + '"></div></div>';
                html += '<div class="gf-bp-address-col" style="grid-column:9/-1;"><div class="gf-bp-control-wrap"><input class="gf-bp-control gf-bp-input" type="text"' + styleAttrs + ' placeholder="' + labelPostal + '" aria-label="' + labelPostal + '"></div></div>';
                html += '<div class="gf-bp-address-col" style="grid-column:1/7;"><div class="gf-bp-control-wrap"><input class="gf-bp-control gf-bp-input" type="text"' + styleAttrs + ' placeholder="' + labelState + '" aria-label="' + labelState + '"></div></div>';
                html += '<div class="gf-bp-address-col" style="grid-column:7/-1;"><div class="gf-bp-control-wrap"><select class="gf-bp-control gf-bp-select"' + styleAttrs + ' aria-label="' + labelCountry + '"><option>' + labelCountry + '</option></select></div></div>';
                html += '</div>';
                return html;
            },
            inputdate: (ph, styleAttrs) => '<input class="gf-bp-control gf-bp-input" type="date"' + styleAttrs + ' placeholder="' + ph + '">',
            inputtime: (ph, styleAttrs) => '<input class="gf-bp-control gf-bp-input" type="time"' + styleAttrs + ' placeholder="' + ph + '">',
            inputpassword: (ph, styleAttrs) => '<input class="gf-bp-control gf-bp-input" type="password"' + styleAttrs + ' placeholder="' + ph + '">',
            inputurl: (ph, styleAttrs) => '<input class="gf-bp-control gf-bp-input" type="url"' + styleAttrs + ' placeholder="' + ph + '">',
            inputnumber: (ph, styleAttrs) => '<input class="gf-bp-control gf-bp-input" type="number"' + styleAttrs + ' placeholder="' + ph + '">',
            termsconditions: (_ph, styleAttrs, _options, field) => {
                const terms = field && field.terms ? field.terms : {};
                const checkboxLabel = esc(terms.checkbox_label || __('I agree to the terms', 'griffinforms-form-builder'));
                const anchorText = esc(terms.anchor_text || __('View terms', 'griffinforms-form-builder'));
                const subtext = terms.subtext ? esc(terms.subtext) : '';
                const url = terms.url ? terms.url : '';

                let html = '<div class="gf-bp-terms">';
                html += '<label class="gf-bp-options"><span class="gf-bp-checkbox"' + styleAttrs + '></span><span>' + checkboxLabel + '</span></label>';
                if (anchorText) {
                    if (url) {
                        html += '<div class="gf-bp-terms-link"><a href="' + url + '" target="_blank" rel="noopener noreferrer">' + anchorText + '</a></div>';
                    } else {
                        html += '<div class="gf-bp-terms-link"><span>' + anchorText + '</span></div>';
                    }
                }
                if (subtext) {
                    html += '<div class="gf-bp-terms-subtext gf-bp-description">' + subtext + '</div>';
                }
                html += '</div>';
                return html;
            },
            payment: (_ph, _styleAttrs, _options, field) => {
                const products = Array.isArray(field && field.payment_products) ? field.payment_products : [];
                const layout   = (field && field.payment_layout) || 'cards';
                if (!products.length) {
                    return '<div style="padding:10px;border:1px dashed #ccc;border-radius:4px;color:#888;font-size:12px;">' + esc(__('No products configured.', 'griffinforms-form-builder')) + '</div>';
                }
                const isList    = layout === 'list';
                const gridStyle = isList
                    ? 'display:grid;gap:10px;'
                    : 'display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px;';
                let html = '<div style="' + gridStyle + '">';
                products.forEach(function (prod) {
                    const name  = esc(prod.name  || __('Product', 'griffinforms-form-builder'));
                    const price = parseFloat(prod.price  || 0).toFixed(2);
                    const desc  = esc(prod.description || '');
                    const img   = prod.image ? esc(prod.image) : '';
                    const incl  = esc(__('Include this item', 'griffinforms-form-builder'));
                    if (isList) {
                        html += '<div style="border:1px solid #e5e7eb;border-radius:8px;padding:10px;display:flex;gap:12px;align-items:flex-start;">';
                        if (img) html += '<img src="' + img + '" style="width:80px;height:80px;object-fit:cover;border-radius:6px;flex-shrink:0;">';
                        html += '<div style="flex:1 1 0;min-width:0;">';
                        html += '<div style="display:flex;justify-content:space-between;gap:8px;margin-bottom:4px;"><span style="font-weight:600;font-size:13px;">' + name + '</span><span style="font-weight:600;font-size:13px;white-space:nowrap;">' + price + '</span></div>';
                        if (desc) html += '<div style="font-size:11px;color:#666;margin-bottom:6px;">' + desc + '</div>';
                        html += '<div style="display:flex;align-items:center;gap:6px;font-size:12px;"><input type="checkbox" disabled style="margin:0;"> <span style="font-weight:600;">' + incl + '</span></div>';
                        html += '</div></div>';
                    } else {
                        html += '<div style="border:1px solid #e5e7eb;border-radius:10px;padding:12px;background:#fff;">';
                        if (img) html += '<img src="' + img + '" style="width:100%;height:120px;object-fit:cover;border-radius:8px;margin-bottom:8px;">';
                        html += '<div style="display:flex;justify-content:space-between;gap:8px;margin-bottom:4px;"><span style="font-weight:600;font-size:13px;">' + name + '</span><span style="font-weight:600;font-size:13px;white-space:nowrap;">' + price + '</span></div>';
                        if (desc) html += '<div style="font-size:11px;color:#666;margin-bottom:6px;">' + desc + '</div>';
                        html += '<div style="display:flex;align-items:center;gap:6px;font-size:12px;"><input type="checkbox" disabled style="margin:0;"> <span style="font-weight:600;">' + incl + '</span></div>';
                        html += '</div>';
                    }
                });
                html += '</div>';
                return html;
            },
        };

        const controlForType = (field) => {
            const type = resolvePreviewRendererType(field);
            const ph = esc(field.placeholder || '');
            const options = Array.isArray(field.options) ? field.options : [];
            const styleGroup = 'block-preview';
            const styleType = getStyleType(type);
            const styleAttrs = ' data-gf-style-group="' + styleGroup + '" data-gf-style-type="' + styleType + '"';
            if (controlRenderers[type]) {
                return controlRenderers[type](ph, styleAttrs, options, field);
            }
            return '<input class="gf-bp-control gf-bp-input" type="text"' + styleAttrs + ' placeholder="' + ph + '">';
        };

        const formStyle = structure.form_style_css ? ' style="' + esc(structure.form_style_css) + '"' : '';
        const previewClass = 'griffinforms-block-preview' + (structure.theme_css ? ' gf-bp-theme' : ' gf-bp-no-theme') + (previewScopeClass ? ' ' + previewScopeClass : '');
        let html = '<div class="' + previewClass + '"' + formStyle + '>';

        if (structure.theme_css) {
            html += '<style class="gf-bp-theme">' + scopeThemeCss(structure.theme_css, previewScopeClass) + '</style>';
        }

        if (heading) {
            html += '<div class="gf-bp-heading">' + esc(heading) + '</div>';
        }

        if (description) {
            html += '<div class="gf-bp-desc">' + esc(description) + '</div>';
        }

        html += buildProgressBarHtml(structure, safePageIndex, esc);

        if (pages.length) {
            const page = pages[safePageIndex];
            const basePageStyle = 'display:block;width:100%;';
            const pageStyle = structure.page_style_css ? ' style="' + esc(structure.page_style_css + ';' + basePageStyle) + '"' : ' style="' + basePageStyle + '"';
            html += '<div class="gf-bp-page"' + pageStyle + '>';
            if (page.heading) {
                html += '<div class="gf-bp-page-title">' + esc(page.heading) + '</div>';
            }

            if (page.description) {
                html += '<div class="gf-bp-page-desc">' + esc(page.description) + '</div>';
            }

            const pageBodyStyle = ' style="display:block;width:100%;"';
            html += '<div class="gf-bp-page-body"' + pageBodyStyle + '>';
            if (Array.isArray(page.rows)) {
                page.rows.forEach(function (row) {
                    const baseRowStyle = 'display:grid !important;grid-template-columns:repeat(12,minmax(0,1fr)) !important;gap:8px !important;width:100% !important;';
                    const themeRow = structure.row_style_css ? esc(structure.row_style_css) + ';' : '';
                    const paddingFallback = 'padding:0.5rem !important;';
                    const rowStyle = ' style="' + themeRow + paddingFallback + baseRowStyle + '"';
                    html += '<div class="gf-bp-row"' + rowStyle + '>';
                    if (row.heading) {
                        html += '<div class="gf-bp-row-heading" style="grid-column:1/-1;">' + esc(row.heading) + '</div>';
                    }
                    if (Array.isArray(row.columns)) {
                        row.columns.forEach(function (column) {
                            const width = column.width ? Math.max(1, Math.min(12, parseInt(column.width, 10))) : 12;
                            html += '<div class="gf-bp-col" style="box-sizing:border-box;grid-column:span ' + width + ';min-width:0;">';
                            if (Array.isArray(column.fields)) {
                                column.fields.forEach(function (field) {
                                    const fieldTypeAttr = field && field.field_type ? ' data-gf-field-type="' + esc(String(field.field_type).toLowerCase()) + '"' : '';
                                    html += '<div class="gf-bp-field"' + fieldTypeAttr + '>';
                                    const label = field.label ? esc(field.label) : esc(__('Untitled field', 'griffinforms-form-builder'));
                                    html += '<label class="gf-bp-label">' + label;
                                    if (field.required) {
                                        const ri = (typeof structure.required_indicator === 'string') ? structure.required_indicator : '*';
                                        if (ri !== '') {
                                            html += ' <span class="gf-bp-required" aria-hidden="true">' + esc(ri) + '</span>';
                                        }
                                    }
                                    html += '</label>';
                                    html += '<div class="gf-bp-control-wrap">' + controlForType(field) + '</div>';
                                    if (field.description) {
                                        html += '<div class="gf-bp-description">' + esc(field.description) + '</div>';
                                    }
                                    html += '</div>';
                                });
                            }
                            html += '</div>';
                        });
                    }
                    if (row.description) {
                        html += '<div class="gf-bp-row-desc" style="grid-column:1/-1;">' + esc(row.description) + '</div>';
                    }
                    html += '</div>';
                });
            }
            html += '</div>'; // end page body

            if (structure && Array.isArray(structure.pages) && structure.pages.length > 1) {
                html += '<div class="gf-bp-nav">';
                if (safePageIndex > 0) {
                    html += '<button type="button" class="gf-bp-submit-btn gf-bp-nav-btn gf-bp-nav-prev">' + esc(__('Previous', 'griffinforms-form-builder')) + '</button>';
                }
                if (safePageIndex < structure.pages.length - 1) {
                    html += '<button type="button" class="gf-bp-submit-btn gf-bp-nav-btn gf-bp-nav-next">' + esc(__('Next', 'griffinforms-form-builder')) + '</button>';
                } else if (submitLabel) {
                    html += '<button type="button" class="gf-bp-submit-btn gf-bp-nav-btn gf-bp-nav-submit">' + esc(submitLabel) + '</button>';
                }
                html += '</div>';
            } else if (submitLabel) {
                html += '<div class="gf-bp-nav">';
                html += '<div></div>';
                html += '<button type="button" class="gf-bp-submit-btn gf-bp-nav-btn gf-bp-nav-submit">' + esc(submitLabel) + '</button>';
                html += '</div>';
            }

            html += '</div>';
        } else {
            html += '<div class="gf-bp-page-desc">' + esc(__('No pages found in this form.', 'griffinforms-form-builder')) + '</div>';
        }

        if (truncated && truncatedNotice) {
            html += '<div class="gf-bp-truncated">' + esc(truncatedNotice) + '</div>';
        }

        html += '</div>';
        return html;
    };

    const getStyleType = (fieldType) => {
        const normalizedType = normalizePreviewFieldType(fieldType);

        switch (normalizedType) {
            case 'textarea':
                return 'textarea';
            case 'selectfield':
                return 'select_input';
            case 'checkbox_radio':
            case 'inputcheckbox':
            case 'inputradio':
            case 'termsconditions':
                return 'checkbox_radio';
            case 'imageselection':
                return 'choice';
            case 'inputphone':
            case 'inputaddress':
            case 'inputdate':
            case 'inputtime':
            case 'inputpassword':
            case 'inputurl':
            case 'inputnumber':
            case 'fileupload':
            case 'payment':
            default:
                return 'text_input';
        }
    };

    const sprintf = function (text) {
        const args = Array.prototype.slice.call(arguments, 1);
        let i = 0;
        return text.replace(/%s|%d/g, function () {
            return typeof args[i] !== 'undefined' ? args[i++] : '';
        });
    };

    const normalizeListResponse = (resp) => {
        if (Array.isArray(resp)) {
            return resp;
        }
        if (resp && Array.isArray(resp.data)) {
            return resp.data;
        }
        return [];
    };

    const normalizeObjectResponse = (resp) => {
        if (!resp || Array.isArray(resp)) {
            return null;
        }
        if (resp.data && typeof resp.data === 'object' && !Array.isArray(resp.data)) {
            return resp.data;
        }
        return resp;
    };

    const FormBlockEdit = (props) => {
        const { attributes, setAttributes, clientId } = props;
        const [forms, setForms] = useState([]);
        const [loadingForms, setLoadingForms] = useState(true);
        const [loadingPreview, setLoadingPreview] = useState(false);
        const [error, setError] = useState('');
        const [structure, setStructure] = useState(null);
        const [previewHtml, setPreviewHtml] = useState('');
        const [activePage, setActivePage] = useState(0);
        const previewRef = useRef(null);
        const previewScopeClass = 'gf-bp-scope-' + String(clientId || '').replace(/[^a-zA-Z0-9_-]/g, '');

        const blockProps = useBlockProps({ className: 'griffinforms-block-editor' });
        const formsList = Array.isArray(forms) ? forms : [];

        useEffect(() => {
            fetchForms();
        }, []);

        useEffect(() => {
            if (attributes.formId) {
                fetchStructure(attributes.formId);
            }
        }, [attributes.formId]);

        useEffect(() => {
            if (structure) {
                setActivePage(0);
            }
        }, [structure]);

        useEffect(() => {
            if (structure) {
                const pageIndex = Math.min(activePage, Math.max(0, (structure.pages || []).length - 1));
                setPreviewHtml(buildPreviewHtml(structure, null, pageIndex, previewScopeClass));
                ensureThemeFonts(structure.theme_fonts || []);
            }
        }, [structure, activePage, previewScopeClass]);

        // Wire up navigation clicks inside the preview markup
        useEffect(() => {
            const root = previewRef.current;
            if (!root || !structure || !Array.isArray(structure.pages) || structure.pages.length < 2) {
                return;
            }
            const prevHandler = function (e) {
                e.preventDefault();
                setActivePage((prev) => Math.max(0, prev - 1));
            };
            const nextHandler = function (e) {
                e.preventDefault();
                setActivePage((prev) => Math.min(structure.pages.length - 1, prev + 1));
            };

            const prevButtons = root.querySelectorAll('.gf-bp-nav-prev');
            const nextButtons = root.querySelectorAll('.gf-bp-nav-next');

            prevButtons.forEach((btn) => btn.addEventListener('click', prevHandler));
            nextButtons.forEach((btn) => btn.addEventListener('click', nextHandler));

            return () => {
                prevButtons.forEach((btn) => btn.removeEventListener('click', prevHandler));
                nextButtons.forEach((btn) => btn.removeEventListener('click', nextHandler));
            };
        }, [previewHtml, structure]);

        const fetchForms = (search) => {
            setLoadingForms(true);
            setError('');
            const query = new URLSearchParams();
            query.set('per_page', '200');
            if (search) {
                query.set('search', search);
            }
            apiFetch({ path: REST_BASE + '/forms?' + query.toString() })
                .then((resp) => {
                    setForms(normalizeListResponse(resp));
                })
                .catch((err) => setError(err.message || __('Could not load forms.', 'griffinforms-form-builder')))
                .finally(() => setLoadingForms(false));
        };

        const fetchStructure = (formId) => {
            if (!formId) {
                setStructure(null);
                setPreviewHtml('');
                return;
            }
            setLoadingPreview(true);
            setError('');
            apiFetch({ path: REST_BASE + '/forms/' + formId + '/structure' })
                .then((resp) => {
                    const normalizedStructure = normalizeObjectResponse(resp);
                    if (!normalizedStructure) {
                        throw new Error(__('Could not load form structure.', 'griffinforms-form-builder'));
                    }
                    setStructure(normalizedStructure);
                    setActivePage(0);
                    setPreviewHtml(buildPreviewHtml(normalizedStructure, null, 0, previewScopeClass));
                    const selected = formsList.find((f) => parseInt(f.id, 10) === parseInt(formId, 10));
                    setAttributes({
                        formId: formId,
                        formName: selected ? selected.name : attributes.formName,
                        formUrl: selected ? selected.form_url : attributes.formUrl,
                        builderUrl: selected ? selected.builder_url : attributes.builderUrl,
                        previewTruncated: normalizedStructure && normalizedStructure.truncated ? true : false,
                    });
                })
                .catch((err) => setError(err.message || __('Could not load form structure.', 'griffinforms-form-builder')))
                .finally(() => setLoadingPreview(false));
        };

        const formOptions = [
            { label: __('Select a form', 'griffinforms-form-builder'), value: 0 },
        ].concat(
            formsList.map((form) => ({
                label: form.name + ' (#' + form.id + ')',
                value: parseInt(form.id, 10),
            }))
        );

        return wp.element.createElement(
            wp.element.Fragment,
            null,
            attributes.formId &&
                wp.element.createElement(
                    BlockControls,
                    null,
                    wp.element.createElement(
                        ToolbarGroup,
                        null,
                        attributes.formUrl &&
                            wp.element.createElement(ToolbarButton, {
                                icon: () => wp.element.createElement('img', { src: griffinformsBlockIcons.edit, alt: __('Edit Form', 'griffinforms-form-builder'), width: 20, height: 20 }),
                                label: __('Edit Form', 'griffinforms-form-builder'),
                                onClick: function () {
                                    window.open(attributes.formUrl, '_blank', 'noopener,noreferrer');
                                },
                            }),
                        attributes.builderUrl &&
                            wp.element.createElement(ToolbarButton, {
                                icon: () => wp.element.createElement('img', { src: griffinformsBlockIcons.builder, alt: __('Open Form Builder', 'griffinforms-form-builder'), width: 20, height: 20 }),
                                label: __('Open Form Builder', 'griffinforms-form-builder'),
                                onClick: function () {
                                    window.open(attributes.builderUrl, '_blank', 'noopener,noreferrer');
                                },
                            })
                    )
                ),
            wp.element.createElement(
                InspectorControls,
                null,
                wp.element.createElement(
                    PanelBody,
                    { title: __('Form', 'griffinforms-form-builder'), initialOpen: true },
                    loadingForms
                        ? wp.element.createElement(Spinner, null)
                        : wp.element.createElement(SelectControl, {
                              label: __('Select form', 'griffinforms-form-builder'),
                              value: attributes.formId || 0,
                              options: formOptions,
                              __next40pxDefaultSize: true,
                              __nextHasNoMarginBottom: true,
                              onChange: function (value) {
                                  const id = parseInt(value, 10) || 0;
                                  setAttributes({ formId: id });
                              },
                          }),
                    error &&
                        wp.element.createElement(Notice, { status: 'error', isDismissible: false }, error)
                ),
                wp.element.createElement(
                    PanelBody,
                    { title: __('About this preview', 'griffinforms-form-builder'), initialOpen: false },
                    wp.element.createElement(
                        Notice,
                        { status: 'info', isDismissible: false },
                        wp.element.createElement(
                            'div',
                            null,
                            __('This is a lightweight form preview inside the editor. Validations, conditional logic, payments, and submissions do not run here.', 'griffinforms-form-builder')
                        ),
                        wp.element.createElement(
                            'div',
                            { style: { marginTop: '6px' } },
                            __('Use the frontend to test the real form behavior.', 'griffinforms-form-builder')
                        )
                    )
                )
            ),
            wp.element.createElement(
                'div',
                blockProps,
                attributes.formId
                    ? wp.element.createElement(
                          'div',
                          { className: 'gf-bp-wrapper' },
                          null,
                          loadingPreview
                              ? wp.element.createElement(
                                    'div',
                                    { className: 'gf-bp-loading' },
                                    wp.element.createElement(Spinner, null),
                                    wp.element.createElement(
                                        'div',
                                        { style: { marginTop: '6px', color: '#555' } },
                                        __('Loading preview…', 'griffinforms-form-builder')
                                    )
                                )
                              : previewHtml
                              ? wp.element.createElement(
                                    wp.element.Fragment,
                                    null,
                                    wp.element.createElement('div', {
                                        ref: previewRef,
                                        className: 'gf-bp-preview',
                                        dangerouslySetInnerHTML: { __html: previewHtml },
                                    })
                                )
                              : wp.element.createElement(
                                    Notice,
                                    { status: 'info', isDismissible: false },
                                    __('No preview available. Select a form to view structure.', 'griffinforms-form-builder')
                                )
                      )
                    : wp.element.createElement(
                          'div',
                          { className: 'gf-bp-placeholder' },
                          wp.element.createElement(
                              'div',
                              { className: 'gf-bp-placeholder-title' },
                              __('Select a form to show its preview.', 'griffinforms-form-builder')
                          )
                      )
            )
        );
    };

    registerBlockType(BLOCK_SLUG, {
        icon: IconBlock,
        edit: FormBlockEdit,
        save: function () {
            return null;
        },
    });
})(window.wp);
