.elementor-kit-825{--e-global-color-primary:#C4C4C4;--e-global-color-secondary:#54595F;--e-global-color-text:#333333;--e-global-color-accent:#69727D;--e-global-color-9cec543:#CF2020;--e-global-color-98fa986:#333333;--e-global-color-f63786a:#69727D;--e-global-color-1c715cb:#C4C4C4;--e-global-typography-primary-font-family:"Roboto";--e-global-typography-primary-font-weight:600;--e-global-typography-secondary-font-family:"Roboto Slab";--e-global-typography-secondary-font-size:22px;--e-global-typography-secondary-font-weight:600;--e-global-typography-secondary-font-style:italic;--e-global-typography-text-font-family:"Arial";--e-global-typography-text-font-weight:400;--e-global-typography-accent-font-family:"Roboto";--e-global-typography-accent-font-weight:500;background-color:#FFFFFF;color:#000000;font-size:16px;font-weight:500;}.elementor-kit-825 e-page-transition{background-color:#FFBC7D;}.elementor-kit-825 h2{font-family:var( --e-global-typography-secondary-font-family ), Sans-serif;font-size:var( --e-global-typography-secondary-font-size );font-weight:var( --e-global-typography-secondary-font-weight );font-style:var( --e-global-typography-secondary-font-style );}.elementor-kit-825 h5{font-style:italic;}.elementor-section.elementor-section-boxed > .elementor-container{max-width:1140px;}.e-con{--container-max-width:1140px;--container-default-padding-top:10px;--container-default-padding-right:10px;--container-default-padding-bottom:10px;--container-default-padding-left:10px;}.elementor-widget:not(:last-child){margin-block-end:20px;}.elementor-element{--widgets-spacing:20px 20px;--widgets-spacing-row:20px;--widgets-spacing-column:20px;}{}h1.entry-title{display:var(--page-title-display);}@media(max-width:1024px){.elementor-kit-825 h2{font-size:var( --e-global-typography-secondary-font-size );}.elementor-section.elementor-section-boxed > .elementor-container{max-width:1024px;}.e-con{--container-max-width:1024px;}}@media(max-width:767px){.elementor-kit-825 h2{font-size:var( --e-global-typography-secondary-font-size );}.elementor-section.elementor-section-boxed > .elementor-container{max-width:767px;}.e-con{--container-max-width:767px;}}:root { --black:#000000; --white:#FFFFFF; --grey-light:#FAFAFA; --grey-mid:#EEEEEE; --xxxlarge:clamp(2.63rem, 2.30172rem + 1.37931vw, 3.25rem); --xxlarge:clamp(2.25rem, 1.99138rem + 1.10345vw, 2.75rem); --xlarge:clamp(1.88rem, 1.68103rem + 0.82759vw, 2.25rem); --large:clamp(1.50rem, 1.37069rem + 0.55172vw, 1.75rem); --medium:clamp(1.13rem, 1.06034rem + 0.27586vw, 1.25rem); --normal:1rem; --small:clamp(0.94rem, 0.93750rem + 0.00000vw, 0.94rem); --xsmall:clamp(0.88rem, 0.87500rem + 0.00000vw, 0.88rem); --primary:#000000; --secondary:#000000; --accent:#000000; --text:#1E1E1E; --grey-dark:#AAAAAA; }
/* Start custom CSS *//**
 * Font Clamp Calculator 4
 */
/*
Plugin Name: Font Clamp Calculator
Description: Adds a Font Clamp Calculator to the WordPress admin dashboard with Class, Tag, and Scale tabs for generating responsive font sizes with persistent data. Includes options to use custom WOFF2 fonts for previews.
Version: 4
*/

// Prevent direct access to the file
if (!defined('ABSPATH')) {
    exit;
}

// Add menu item to the WordPress admin dashboard
function font_clamp_calculator_menu() {
    add_menu_page(
        'Font Clamp Calculator',
        'Font Clamp',
        'manage_options',
        'font-clamp-calculator',
        'font_clamp_calculator_page',
        'dashicons-editor-textcolor',
        80
    );
}
add_action('admin_menu', 'font_clamp_calculator_menu');

// Callback function to render the Font Clamp Calculator page
function font_clamp_calculator_page() {
    // Load saved settings
    $settings = get_option('font_clamp_settings', [
        'rootSize' => 16,
        'minViewport' => 375,
        'maxViewport' => 1100,
        'unitType' => 'px',
        'selectedClassSizeId' => 6,
        'selectedTagSizeId' => 1,
        'selectedScaleSizeId' => 7,
        'activeTab' => 'class',
        'scalePMinFont' => 16,
        'scalePMaxFont' => 16,
        'scaleRatioMin' => 1.333,
        'scaleRatioMax' => 1.4,
        'scalePLineHeight' => 1.4,
        'previewFontUrl' => '',
        'previewFontUrlP' => ''
    ]);
    ?>
    <div class="wrap">
        <h1 class="text-2xl font-bold mb-4">Font Clamp Calculator V4</h1>
        <style>
            .preview-text {
                transition: font-size 0.3s ease;
                line-height: 1.2;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                font-family: var(--preview-font, inherit);
            }
            .preview-text.p {
                font-family: var(--preview-font-p, var(--preview-font, inherit));
            }
            .code-block {
                font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
            }
            .input-field:focus {
                outline: 2px solid #3b82f6;
                outline-offset: !important;
            }
            .size-row {
                transition: background-color 0.2s ease;
                cursor: move;
            }
            .size-row:hover {
                background-color: #f1f5f9;
            }
            .size-row.selected {
                background-color: #e0f2fe;
            }
            .size-row.dragging {
                opacity: 0.5;
                background-color: #dbeafe;
            }
            .drag-over {
                border-top: 2px solid #3b82f6;
            }
            .wrap button,
            .wrap [type=button],
            .wrap [type=submit] {
                border-color: transparent !important;
                outline: none !important;
                box-shadow: none !important;
                --tw-ring-shadow: none !important;
            }
            .tab-button {
                background-color: #f4f4f4;
                color: #444444;
                border: 1px solid #444444;
                transition: background-color 0.2s ease, color 0.2s ease;
            }
            .tab-button:hover {
                background-color: #444444;
                color: #ffffff;
            }
            .tab-button.active {
                background-color: #3b82f6;
                color: #ffffff;
            }
            .copy-button,
            #add-size {
                background-color: #3b82f6;
                color: #ffffff;
                transition: background-color 0.2s ease, color 0.2s ease;
            }
            .copy-button:hover,
            #add-size:hover {
                background-color: #444444;
                color: #ffffff;
            }
            .copy-button:active,
            #add-size:active {
                background-color: #3b82f6;
                color: #ffffff;
            }
            .edit-btn,
            .delete-btn {
                background-color: transparent;
                padding: 4px;
                border-radius: 4px;
                transition: color 0.2s ease;
            }
            .edit-btn {
                color: #3b82f6;
            }
            .edit-btn:hover {
                color: #1e40af;
            }
            .delete-btn {
                color: #ef4444;
            }
            .delete-btn:hover {
                color: #b91c1c;
            }
            #cancel-edit,
            #save-edit-btn {
                background-color: #3b82f6;
                color: #ffffff;
                border: none;
                transition: background-color 0.2s ease, color 0.2s ease;
            }
            #cancel-edit:hover,
            #save-edit-btn:hover {
                background-color: #444444;
                color: #ffffff;
            }
            #cancel-edit:active,
            #save-edit-btn:active {
                background-color: #3b82f6;
                color: #ffffff;
            }
            table#sizes-table,
            table#sizes-table th,
            table#sizes-table td {
                border: 0px solid #d1d5db;
                border-collapse: collapse;
            }
            table#sizes-table th,
            table#sizes-table td {
                padding: 0px 8px;
            }
            .size-row {
                height: 8px;
            }
            #sizes-table tr:hover {
                border-left: 3px solid #3b82f6;
            }
            table.min-w-full,
            table.min-w-full th,
            table.min-w-full td,
            table.min-w-full tr {
                border: none !important;
                border-width: 0 !important;
                border-style: none !important;
                outline: none !important;
                box-shadow: none !important;
            }
            .scale-inputs {
                display: none;
            }
            .scale-inputs.active {
                display: block;
            }
            .disabled-btn {
                background-color: #d1d5db !important;
                cursor: not-allowed !important;
            }
            .disabled-btn:hover {
                background-color: #d1d5db !important;
                color: #ffffff !important;
            }
            #preview-font-url,
            #preview-font-url-p {
                width: 200px;
            }
        </style>

        <div class="max-w-7xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">
            <div class="p-2">
                <div class="flex justify-between items-center mb-2">
                    <div class="flex space-x-2">
                        <button id="class-tab" class="tab-button px-3 py-1 rounded-md text-sm <?php echo $settings['activeTab'] === 'class' ? 'active' : ''; ?>">Class</button>
                        <button id="tag-tab" class="tab-button px-3 py-1 rounded-md text-sm <?php echo $settings['activeTab'] === 'tag' ? 'active' : ''; ?>">Tag</button>
                        <button id="scale-tab" class="tab-button px-3 py-1 rounded-md text-sm <?php echo $settings['activeTab'] === 'scale' ? 'active' : ''; ?>">Scale</button>
                    </div>
                    <div class="flex space-x-2 items-center">
                        <input type="text" id="preview-font-url" class="input-field px-2 py-1 border border-gray-300 rounded-md text-sm" placeholder="Paste WOFF2 font URL" value="<?php echo esc_attr($settings['previewFontUrl']); ?>">
                        <input type="text" id="preview-font-url-p" class="input-field px-2 py-1 border border-gray-300 rounded-md text-sm" placeholder="Paste WOFF2 font URL for p" value="<?php echo esc_attr($settings['previewFontUrlP']); ?>">
                        <button id="push-to-customizer" class="copy-button bg-green-600 hover:bg-green-700 text-white px-2 py-1 rounded-md text-sm">Push to Theme Custom CSS</button>
                        <button id="export-json" class="copy-button bg-yellow-500 hover:bg-yellow-600 text-white px-2 py-1 rounded-md text-sm">Export JSON</button>
                        <button id="import-json" class="copy-button bg-purple-600 hover:bg-purple-700 text-white px-2 py-1 rounded-md text-sm">Import JSON</button>
                        <input type="file" id="import-json-file" accept="application/json" class="hidden" />
                    </div>
                </div>

                <div class="grid grid-cols-1 lg:grid-cols-2 gap-2">
                    <div>
                        <div class="bg-gray-50 p-2 rounded-lg mb-2">
                            <h2 class="text-base font-semibold mb-2">Settings</h2>
                            <div class="mb-2">
                                <label class="block text-sm font-medium text-gray-700 mb-1">Input Unit Type</label>
                                <div class="flex rounded-md overflow-hidden border border-gray-300">
                                    <button id="px-tab" class="tab-button w-1/2 py-1 text-center text-sm font-medium <?php echo $settings['unitType'] === 'px' ? 'active' : ''; ?>">PX</button>
                                    <button id="rem-tab" class="tab-button w-1/2 py-1 text-center text-sm font-medium <?php echo $settings['unitType'] === 'rem' ? 'active' : ''; ?>">REM</button>
                                </div>
                            </div>
                            <div class="grid grid-cols-3 gap-2 global-settings">
                                <div>
                                    <label for="root-size" class="block text-sm font-medium text-gray-700 mb-1">Root Size (px)</label>
                                    <input type="number" id="root-size" value="<?php echo esc_attr($settings['rootSize']); ?>" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
                                </div>
                                <div>
                                    <label for="min-viewport" class="block text-sm font-medium text-gray-700 mb-1">Min Width (px)</label>
                                    <input type="number" id="min-viewport" value="<?php echo esc_attr($settings['minViewport']); ?>" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
                                </div>
                                <div>
                                    <label for="max-viewport" class="block text-sm font-medium text-gray-700 mb-1">Max Width (px)</label>
                                    <input type="number" id="max-viewport" value="<?php echo esc_attr($settings['maxViewport']); ?>" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
                                </div>
                            </div>
                            <div id="scale-inputs" class="scale-inputs grid grid-cols-2 gap-2 mt-2 <?php echo $settings['activeTab'] === 'scale' ? 'active' : ''; ?>">
                                <div>
                                    <label for="scale-p-min-font" class="block text-sm font-medium text-gray-700 mb-1">P Min Font</label>
                                    <input type="number" id="scale-p-min-font" step="0.1" value="<?php echo esc_attr($settings['scalePMinFont']); ?>" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
                                </div>
                                <div>
                                    <label for="scale-p-max-font" class="block text-sm font-medium text-gray-700 mb-1">P Max Font</label>
                                    <input type="number" id="scale-p-max-font" step="0.1" value="<?php echo esc_attr($settings['scalePMaxFont']); ?>" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
                                </div>
                                <div>
                                    <label for="scale-ratio-min" class="block text-sm font-medium text-gray-700 mb-1">Scale Ratio for Min</label>
                                    <input type="number" id="scale-ratio-min" step="0.01" value="<?php echo esc_attr($settings['scaleRatioMin']); ?>" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
                                </div>
                                <div>
                                    <label for="scale-ratio-max" class="block text-sm font-medium text-gray-700 mb-1">Scale Ratio for Max</label>
                                    <input type="number" id="scale-ratio-max" step="0.01" value="<?php echo esc_attr($settings['scaleRatioMax']); ?>" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
                                </div>
                            </div>
                        </div>

                        <div class="bg-gray-50 p-2 rounded-lg">
                            <div class="flex justify-between items-center mb-2">
                                <h2 class="text-base font-semibold" id="table-title">Font Size Classes</h2>
                                <div class="flex space-x-2">
                                    <button id="add-size" class="bg-blue-500 hover:bg-blue-600 text-white px-2 py-1 rounded-md text-sm">Add Size</button>
                                    <button id="reset-defaults" class="bg-gray-600 hover:bg-gray-700 text-white px-2 py-1 rounded-md text-sm">Reset to Default</button>
                                    <button id="clear-sizes" class="bg-red-500 hover:bg-red-600 text-white px-2 py-1 rounded-md text-sm">Clear All</button>
                                </div>
                            </div>
                            <div class="overflow-auto" style="max-height: calc(100vh - 350px)">
                                <table class="min-w-full">
                                    <thead class="bg-gray-100">
                                        <tr>
                                            <th class="px-2 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-8"></th>
                                            <th class="px-2 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" id="name-header">Class Name</th>
                                            <th class="px-2 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Min Size</th>
                                            <th class="px-2 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Max Size</th>
                                            <th class="px-2 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Line Height</th>
                                            <th class="px-2 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-16"></th>
                                        </tr>
                                    </thead>
                                    <tbody id="sizes-table"></tbody>
                                </table>
                            </div>
                        </div>
                    </div>

                    <div>
                        <div class="bg-gray-50 p-2 rounded-lg">
                            <h2 class="text-base font-semibold mb-2">Preview</h2>
                            <div id="preview-container" class="grid grid-cols-1 gap-1 overflow-auto" style="max-height: calc(100vh - 150px)"></div>
                        </div>
                    </div>
                </div>

                <div class="bg-gray-50 p-2 rounded-lg mt-2">
                    <div class="flex justify-between items-center mb-2">
                        <h2 class="text-base font-semibold" id="selected-code-title">Selected Class CSS</h2>
                        <button id="copy-class" class="copy-button bg-blue-500 hover:bg-blue-600 text-white px-2 py-1 rounded-md text-sm">Copy Class</button>
                    </div>
                    <div class="bg-gray-800 rounded-lg p-2">
                        <pre id="class-code" class="code-block text-green-400 text-xs whitespace-pre-wrap"></pre>
                    </div>
                </div>

                <div class="bg-gray-50 p-2 rounded-lg mt-2">
                    <div class="flex justify-between items-center mb-2">
                        <h2 class="text-base font-semibold" id="generated-code-title">Generated CSS (All Classes)</h2>
                        <button id="copy-all" class="copy-button bg-blue-500 hover:bg-blue-600 text-white px-2 py-1 rounded-md text-sm">Copy All</button>
                    </div>
                    <div class="overflow-auto bg-gray-800 rounded-lg p-2" style="max-height: 300px">
                        <pre id="generated-code" class="code-block text-green-400 text-xs whitespace-pre-wrap"></pre>
                    </div>
                </div>
            </div>
        </div>

        <div id="edit-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden">
            <div class="absolute top-[300px] left-[180px] bg-white rounded-lg p-4 w-96 max-w-full shadow-lg">
                <h3 class="text-lg font-semibold mb-3" id="edit-modal-title">Edit Font Size Class</h3>
                <div class="space-y-3">
                    <div>
                        <label for="edit-class-name" class="block text-sm font-medium text-gray-700 mb-1" id="edit-name-label">Class Name</label>
                        <input type="text" id="edit-class-name" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md">
                    </div>
                    <div>
                        <label for="edit-min-size" class="block text-sm font-medium text-gray-700 mb-1">Min Size</label>
                        <input type="number" id="edit-min-size" step="0.1" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md">
                    </div>
                    <div>
                        <label for="edit-max-size" class="block text-sm font-medium text-gray-700 mb-1">Max Size</label>
                        <input type="number" id="edit-max-size" step="0.1" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md">
                    </div>
                    <div>
                        <label for="edit-line-height" class="block text-sm font-medium text-gray-700 mb-1">Line Height</label>
                        <input type="number" step="0.1" id="edit-line-height" placeholder="1.3" class="input-field w-full px-2 py-1 border border-gray-300 rounded-md">
                    </div>
                    <div class="flex justify-end space-x-2 pt-2">
                        <button id="cancel-edit" class="px-3 py-1 border border-gray-300 rounded-md text-sm">Cancel</button>
                        <button id="save-edit-btn" class="px-3 py-1 bg-blue-500 text-white rounded-md text-sm">Save</button>
                    </div>
                </div>
            </div>
        </div>

        <script src="https://cdn.tailwindcss.com"></script>
        <script>
            let classSizes = <?php
                $saved_class_sizes = get_option('font_clamp_class_sizes', false);
                if ($saved_class_sizes === false) {
                    echo json_encode([
                        ['id' => 1, 'className' => 'xxxlarge', 'min' => 42, 'max' => 52, 'lineHeight' => 1.3],
                        ['id' => 2, 'className' => 'xxlarge', 'min' => 36, 'max' => 44, 'lineHeight' => 1.3],
                        ['id' => 3, 'className' => 'xlarge', 'min' => 30, 'max' => 36, 'lineHeight' => 1.3],
                        ['id' => 4, 'className' => 'large', 'min' => 24, 'max' => 28, 'lineHeight' => 1.3],
                        ['id' => 5, 'className' => 'medium', 'min' => 18, 'max' => 20, 'lineHeight' => 1.3],
                        ['id' => 6, 'className' => 'normal', 'min' => 16, 'max' => 16, 'lineHeight' => 1.3],
                        ['id' => 7, 'className' => 'small', 'min' => 15, 'max' => 15, 'lineHeight' => 1.3],
                        ['id' => 8, 'className' => 'xsmall', 'min' => 14, 'max' => 14, 'lineHeight' => 1.3]
                    ]);
                } else {
                    echo json_encode($saved_class_sizes);
                }
            ?>;
            let tagSizes = <?php
                $saved_tag_sizes = get_option('font_clamp_tag_sizes', false);
                if ($saved_tag_sizes === false) {
                    echo json_encode([
                        ['id' => 1, 'tagName' => 'h1', 'min' => 36, 'max' => 48, 'lineHeight' => 1.4],
                        ['id' => 2, 'tagName' => 'h2', 'min' => 30, 'max' => 40, 'lineHeight' => 1.4],
                        ['id' => 3, 'tagName' => 'h3', 'min' => 24, 'max' => 32, 'lineHeight' => 1.4],
                        ['id' => 4, 'tagName' => 'h4', 'min' => 20, 'max' => 28, 'lineHeight' => 1.4],
                        ['id' => 5, 'tagName' => 'h5', 'min' => 18, 'max' => 24, 'lineHeight' => 1.4],
                        ['id' => 6, 'tagName' => 'h6', 'min' => 16, 'max' => 20, 'lineHeight' => 1.4],
                        ['id' => 7, 'tagName' => 'p', 'min' => 14, 'max' => 18, 'lineHeight' => 1.4]
                    ]);
                } else {
                    echo json_encode($saved_tag_sizes);
                }
            ?>;
            let scaleSizes = [];
            let settings = <?php echo json_encode($settings); ?>;
            let unitType = '<?php echo esc_js($settings['unitType']); ?>';
            let rootSize = <?php echo floatval($settings['rootSize']); ?>;
            let minViewport = <?php echo floatval($settings['minViewport']); ?>;
            let maxViewport = <?php echo floatval($settings['maxViewport']); ?>;
            let selectedClassSizeId = <?php echo intval($settings['selectedClassSizeId']); ?>;
            let selectedTagSizeId = <?php echo intval($settings['selectedTagSizeId']); ?>;
            let selectedScaleSizeId = <?php echo intval($settings['selectedScaleSizeId']); ?>;
            let scalePMinFont = <?php echo floatval($settings['scalePMinFont']); ?>;
            let scalePMaxFont = <?php echo floatval($settings['scalePMaxFont']); ?>;
            let scaleRatioMin = <?php echo floatval($settings['scaleRatioMin']); ?>;
            let scaleRatioMax = <?php echo floatval($settings['scaleRatioMax']); ?>;
            let scalePLineHeight = <?php echo floatval($settings['scalePLineHeight']); ?>;
            let previewFontUrl = '<?php echo esc_js($settings['previewFontUrl']); ?>';
            let previewFontUrlP = '<?php echo esc_js($settings['previewFontUrlP']); ?>';
            let activeTab = '<?php echo esc_js($settings['activeTab']); ?>';
            let editingSizeId = null;
            let classNextId = Math.max(...classSizes.map(size => size.id)) + 1;
            let tagNextId = Math.max(...tagSizes.map(size => size.id)) + 1;
            let scaleNextId = 8;

            const classTab = document.getElementById('class-tab');
            const tagTab = document.getElementById('tag-tab');
            const scaleTab = document.getElementById('scale-tab');
            const pxTab = document.getElementById('px-tab');
            const remTab = document.getElementById('rem-tab');
            const rootSizeInput = document.getElementById('root-size');
            const minViewportInput = document.getElementById('min-viewport');
            const maxViewportInput = document.getElementById('max-viewport');
            const scalePMinFontInput = document.getElementById('scale-p-min-font');
            const scalePMaxFontInput = document.getElementById('scale-p-max-font');
            const scaleRatioMinInput = document.getElementById('scale-ratio-min');
            const scaleRatioMaxInput = document.getElementById('scale-ratio-max');
            const scaleInputs = document.getElementById('scale-inputs');
            const sizesTable = document.getElementById('sizes-table');
            const previewContainer = document.getElementById('preview-container');
            const generatedCode = document.getElementById('generated-code');
            const classCode = document.getElementById('class-code');
            const copyAllBtn = document.getElementById('copy-all');
            const copyClassBtn = document.getElementById('copy-class');
            const addSizeBtn = document.getElementById('add-size');
            const clearSizesBtn = document.getElementById('clear-sizes');
            const editModal = document.getElementById('edit-modal');
            const editClassName = document.getElementById('edit-class-name');
            const editLineHeight = document.getElementById('edit-line-height');
            const editMinSize = document.getElementById('edit-min-size');
            const editMaxSize = document.getElementById('edit-max-size');
            const cancelEditBtn = document.getElementById('cancel-edit');
            const saveEditBtn = document.getElementById('save-edit-btn');
            const tableTitle = document.getElementById('table-title');
            const nameHeader = document.getElementById('name-header');
            const selectedCodeTitle = document.getElementById('selected-code-title');
            const generatedCodeTitle = document.getElementById('generated-code-title');
            const editModalTitle = document.getElementById('edit-modal-title');
            const editNameLabel = document.getElementById('edit-name-label');
            const previewFontUrlInput = document.getElementById('preview-font-url');
            const previewFontUrlPInput = document.getElementById('preview-font-url-p');

            function applyPreviewFonts(url, urlP) {
                const siteUrl = '<?php echo esc_js(home_url()); ?>';
                const style = document.createElement('style');
                let fontFaceRules = '';

                document.documentElement.style.setProperty('--preview-font', 'inherit');
                document.documentElement.style.setProperty('--preview-font-p', 'inherit');

                if (url && url.endsWith('.woff2') && url.startsWith(siteUrl)) {
                    const fontName = 'CustomPreviewFont';
                    fontFaceRules += `
                        @font-face {
                            font-family: '${fontName}';
                            src: url('${url}') format('woff2');
                            font-weight: normal;
                            font-style: normal;
                        }
                    `;
                    document.documentElement.style.setProperty('--preview-font', `'${fontName}'`);
                    previewFontUrl = url;
                } else {
                    previewFontUrl = '';
                    previewFontUrlInput.value = '';
                }

                if (urlP && urlP.endsWith('.woff2') && urlP.startsWith(siteUrl)) {
                    const fontNameP = 'CustomPreviewFontP';
                    fontFaceRules += `
                        @font-face {
                            font-family: '${fontNameP}';
                            src: url('${urlP}') format('woff2');
                            font-weight: normal;
                            font-style: normal;
                        }
                    `;
                    document.documentElement.style.setProperty('--preview-font-p', `'${fontNameP}'`);
                    previewFontUrlP = urlP;
                } else {
                    previewFontUrlP = '';
                    previewFontUrlPInput.value = '';
                }

                if (fontFaceRules) {
                    style.textContent = fontFaceRules;
                    document.head.appendChild(style);
                }
            }

            function generateScaleSizes() {
                scaleSizes = [];
                const tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'];
                let minFont = unitType === 'px' ? scalePMinFont : scalePMinFont / rootSize;
                let maxFont = unitType === 'px' ? scalePMaxFont : scalePMaxFont / rootSize;
                for (let i = 0; i < tags.length; i++) {
                    const id = i + 1;
                    const tagName = tags[i];
                    let minSize, maxSize;
                    if (tagName === 'p') {
                        minSize = unitType === 'px' ? scalePMinFont : scalePMinFont;
                        maxSize = unitType === 'px' ? scalePMaxFont : scalePMaxFont;
                    } else {
                        const level = 6 - i;
                        minSize = minFont * Math.pow(scaleRatioMin, level);
                        maxSize = maxFont * Math.pow(scaleRatioMax, level);
                        if (unitType === 'rem') {
                            minSize *= rootSize;
                            maxSize *= rootSize;
                        }
                    }
                    scaleSizes.push({
                        id: id,
                        tagName: tagName,
                        min: minSize,
                        max: maxSize,
                        lineHeight: scalePLineHeight
                    });
                }
            }

            function init() {
                generateScaleSizes();
                updateTabUI();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                applyPreviewFonts(previewFontUrl, previewFontUrlP);
            }

            function updateTabUI() {
                classTab.classList.toggle('active', activeTab === 'class');
                tagTab.classList.toggle('active', activeTab === 'tag');
                scaleTab.classList.toggle('active', activeTab === 'scale');
                pxTab.classList.toggle('active', unitType === 'px');
                remTab.classList.toggle('active', unitType === 'rem');
                scaleInputs.classList.toggle('active', activeTab === 'scale');
                addSizeBtn.classList.toggle('disabled-btn', activeTab === 'scale');
                clearSizesBtn.classList.toggle('disabled-btn', activeTab === 'scale');
                tableTitle.textContent = activeTab === 'class' ? 'Font Size Classes' : (activeTab === 'tag' ? 'Font Size Tags' : 'Font Size Scale');
                nameHeader.textContent = activeTab === 'class' ? 'Class Name' : 'Tag Name';
                selectedCodeTitle.textContent = activeTab === 'class' ? 'Selected Class CSS' : (activeTab === 'tag' ? 'Selected Tag CSS' : 'Selected Scale CSS');
                generatedCodeTitle.textContent = activeTab === 'class' ? 'Generated CSS (All Classes)' : (activeTab === 'tag' ? 'Generated CSS (All Tags)' : 'Generated CSS (All Scale)');
                editModalTitle.textContent = activeTab === 'class' ? 'Edit Font Size Class' : (activeTab === 'tag' ? 'Edit Font Size Tag' : 'Edit Font Size Scale');
                editNameLabel.textContent = activeTab === 'class' ? 'Class Name' : 'Tag Name';
            }

            function saveSettings() {
                fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: new URLSearchParams({
                        'action': 'save_font_clamp_settings',
                        'settings': JSON.stringify({
                            unitType,
                            rootSize,
                            minViewport,
                            maxViewport,
                            selectedClassSizeId,
                            selectedTagSizeId,
                            selectedScaleSizeId,
                            scalePMinFont,
                            scalePMaxFont,
                            scaleRatioMin,
                            scaleRatioMax,
                            scalePLineHeight,
                            previewFontUrl,
                            previewFontUrlP,
                            activeTab
                        }),
                        'nonce': '<?php echo wp_create_nonce('font_clamp_nonce'); ?>'
                    })
                })
                .then(response => response.json())
                .then(data => {
                    if (!data.success) console.error('Failed to save settings:', data.data);
                })
                .catch(error => console.error('Error saving settings:', error));
            }

            function saveFontSizes() {
                fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: new URLSearchParams({
                        'action': 'save_font_clamp_sizes',
                        'class_sizes': JSON.stringify(classSizes),
                        'tag_sizes': JSON.stringify(tagSizes),
                        'nonce': '<?php echo wp_create_nonce('font_clamp_nonce'); ?>'
                    })
                })
                .then(response => response.json())
                .then(data => {
                    if (!data.success) console.error('Failed to save sizes:', data.data);
                })
                .catch(error => console.error('Error saving sizes:', error));
            }

            classTab.addEventListener('click', () => {
                activeTab = 'class';
                updateTabUI();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            tagTab.addEventListener('click', () => {
                activeTab = 'tag';
                updateTabUI();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            scaleTab.addEventListener('click', () => {
                activeTab = 'scale';
                updateTabUI();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            pxTab.addEventListener('click', () => {
                unitType = 'px';
                scalePMinFontInput.value = scalePMinFont;
                scalePMaxFontInput.value = scalePMaxFont;
                generateScaleSizes();
                updateTabUI();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            remTab.addEventListener('click', () => {
                unitType = 'rem';
                scalePMinFontInput.value = (scalePMinFont / rootSize).toFixed(2);
                scalePMaxFontInput.value = (scalePMaxFont / rootSize).toFixed(2);
                generateScaleSizes();
                updateTabUI();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            rootSizeInput.addEventListener('input', () => {
                rootSize = parseFloat(rootSizeInput.value) || 16;
                generateScaleSizes();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            minViewportInput.addEventListener('input', () => {
                minViewport = parseFloat(minViewportInput.value) || 375;
                generateAllCode();
                saveSettings();
            });

            maxViewportInput.addEventListener('input', () => {
                maxViewport = parseFloat(maxViewportInput.value) || 1100;
                generateAllCode();
                saveSettings();
            });

            scalePMinFontInput.addEventListener('input', () => {
                scalePMinFont = unitType === 'px' ? parseFloat(scalePMinFontInput.value) || 16 : (parseFloat(scalePMinFontInput.value) || 1) * rootSize;
                generateScaleSizes();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            scalePMaxFontInput.addEventListener('input', () => {
                scalePMaxFont = unitType === 'px' ? parseFloat(scalePMaxFontInput.value) || 16 : (parseFloat(scalePMaxFontInput.value) || 1) * rootSize;
                generateScaleSizes();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            scaleRatioMinInput.addEventListener('input', () => {
                scaleRatioMin = parseFloat(scaleRatioMinInput.value) || 1.333;
                generateScaleSizes();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            scaleRatioMaxInput.addEventListener('input', () => {
                scaleRatioMax = parseFloat(scaleRatioMaxInput.value) || 1.4;
                generateScaleSizes();
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveSettings();
            });

            previewFontUrlInput.addEventListener('input', () => {
                const url = previewFontUrlInput.value.trim();
                applyPreviewFonts(url, previewFontUrlP);
                renderPreviews();
                saveSettings();
            });

            previewFontUrlPInput.addEventListener('input', () => {
                const urlP = previewFontUrlPInput.value.trim();
                applyPreviewFonts(previewFontUrl, urlP);
                renderPreviews();
                saveSettings();
            });

            copyAllBtn.addEventListener('click', () => {
                copyToClipboard(generatedCode.textContent);
                showCopyFeedback(copyAllBtn);
            });

            copyClassBtn.addEventListener('click', () => {
                copyToClipboard(classCode.textContent);
                showCopyFeedback(copyClassBtn);
            });

            addSizeBtn.addEventListener('click', () => {
                if (activeTab === 'scale') return;
                let newSize;
                if (activeTab === 'class') {
                    newSize = { id: classNextId++, className: `custom-${classNextId - 10}`, min: 16, max: 24, lineHeight: 1.4 };
                    classSizes.push(newSize);
                    selectedClassSizeId = newSize.id;
                } else if (activeTab === 'tag') {
                    newSize = { id: tagNextId++, tagName: `custom${tagNextId - 10}`, min: 16, max: 24, lineHeight: 1.4 };
                    tagSizes.push(newSize);
                    selectedTagSizeId = newSize.id;
                }
                renderSizesTable();
                renderPreviews();
                generateAllCode();
                saveFontSizes();
                saveSettings();
                openEditModal(newSize.id);
            });

            clearSizesBtn.addEventListener('click', () => {
                if (activeTab === 'scale') return;
                if (confirm(`Are you sure you want to delete all ${activeTab === 'class' ? 'font size classes' : 'font size tags'}?`)) {
                    if (activeTab === 'class') {
                        classSizes = [];
                        selectedClassSizeId = null;
                    } else if (activeTab === 'tag') {
                        tagSizes = [];
                        selectedTagSizeId = null;
                    }
                    renderSizesTable();
                    renderPreviews();
                    generateAllCode();
                    saveFontSizes();
                    saveSettings();
                }
            });

            document.getElementById('reset-defaults').addEventListener('click', () => {
                if (confirm(`Reset ${activeTab === 'class' ? 'class' : (activeTab === 'tag' ? 'tag' : 'scale')} sizes and settings to default?`)) {
                    fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                        body: new URLSearchParams({
                            action: 'reset_font_clamp_defaults',
                            tab: activeTab,
                            nonce: '<?php echo wp_create_nonce('font_clamp_nonce'); ?>'
                        })
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.success) {
                            location.reload();
                        } else {
                            alert('Failed to reset to defaults.');
                        }
                    });
                }
            });

            document.getElementById('push-to-customizer').addEventListener('click', () => {
                const css = generatedCode.textContent;
                fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: new URLSearchParams({
                        action: 'font_clamp_push_to_customizer',
                        nonce: '<?php echo wp_create_nonce('font_clamp_nonce'); ?>',
                        css: css
                    })
                })
                .then(res => res.json())
                .then(data => {
                    if (data.success) {
                        alert('CSS added to Customizer successfully!');
                    } else {
                        alert('Failed to update Customizer CSS');
                    }
                });
            });

            document.getElementById('export-json').addEventListener('click', () => {
                let exportData;
                if (activeTab === 'class') {
                    exportData = { settings: { unitType, rootSize, minViewport, maxViewport, selectedClassSizeId, previewFontUrl, previewFontUrlP }, sizes: classSizes };
                } else if (activeTab === 'tag') {
                    exportData = { settings: { unitType, rootSize, minViewport, maxViewport, selectedTagSizeId, previewFontUrl, previewFontUrlP }, sizes: tagSizes };
                } else if (activeTab === 'scale') {
                    exportData = { settings: { unitType, rootSize, minViewport, maxViewport, selectedScaleSizeId, scalePMinFont, scalePMaxFont, scaleRatioMin, scaleRatioMax, scalePLineHeight, previewFontUrl, previewFontUrlP }, sizes: scaleSizes };
                }
                const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `font-clamp-${activeTab}-config.json`;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
            });

            document.getElementById('import-json').addEventListener('click', () => {
                document.getElementById('import-json-file').click();
            });

            document.getElementById('import-json-file').addEventListener('change', (event) => {
                const file = event.target.files[0];
                if (!file) return;
                const reader = new FileReader();
                reader.onload = function(e) {
                    try {
                        const imported = JSON.parse(e.target.result);
                        if (imported.settings && imported.sizes) {
                            unitType = imported.settings.unitType || 'px';
                            rootSize = parseFloat(imported.settings.rootSize) || 16;
                            minViewport = parseFloat(imported.settings.minViewport) || 375;
                            maxViewport = parseFloat(imported.settings.maxViewport) || 1100;
                            previewFontUrl = imported.settings.previewFontUrl || '';
                            previewFontUrlP = imported.settings.previewFontUrlP || '';
                            if (activeTab === 'class') {
                                classSizes = imported.sizes;
                                selectedClassSizeId = imported.settings.selectedClassSizeId || 1;
                                classNextId = Math.max(...classSizes.map(f => f.id)) + 1;
                            } else if (activeTab === 'tag') {
                                tagSizes = imported.sizes;
                                selectedTagSizeId = imported.settings.selectedTagSizeId || 1;
                                tagNextId = Math.max(...tagSizes.map(f => f.id)) + 1;
                            } else if (activeTab === 'scale') {
                                scalePMinFont = parseFloat(imported.settings.scalePMinFont) || 16;
                                scalePMaxFont = parseFloat(imported.settings.scalePMaxFont) || 16;
                                scaleRatioMin = parseFloat(imported.settings.scaleRatioMin) || 1.333;
                                scaleRatioMax = parseFloat(imported.settings.scaleRatioMax) || 1.4;
                                scalePLineHeight = parseFloat(imported.settings.scalePLineHeight) || 1.4;
                                selectedScaleSizeId = imported.settings.selectedScaleSizeId || 7;
                                generateScaleSizes();
                            }
                            rootSizeInput.value = rootSize;
                            minViewportInput.value = minViewport;
                            maxViewportInput.value = maxViewport;
                            scalePMinFontInput.value = scalePMinFont;
                            scalePMaxFontInput.value = scalePMaxFont;
                            scaleRatioMinInput.value = scaleRatioMin;
                            scaleRatioMaxInput.value = scaleRatioMax;
                            previewFontUrlInput.value = previewFontUrl;
                            previewFontUrlPInput.value = previewFontUrlP;
                            applyPreviewFonts(previewFontUrl, previewFontUrlP);
                            renderSizesTable();
                            renderPreviews();
                            generateAllCode();
                            saveSettings();
                            if (activeTab !== 'scale') saveFontSizes();
                        } else {
                            alert('Invalid JSON file format.');
                        }
                    } catch (err) {
                        alert('Failed to parse JSON file.');
                    }
                };
                reader.readAsText(file);
            });

            cancelEditBtn.addEventListener('click', closeEditModal);

            saveEditBtn.addEventListener('click', () => {
                const sizes = activeTab === 'class' ? classSizes : (activeTab === 'tag' ? tagSizes : scaleSizes);
                const sizeIndex = sizes.findIndex(size => size.id === editingSizeId);
                if (sizeIndex !== -1) {
                    const newName = editClassName.value.trim();
                    const newMinSize = parseFloat(editMinSize.value) || 0;
                    const newMaxSize = parseFloat(editMaxSize.value) || 0;
                    const newLineHeight = parseFloat(editLineHeight.value) || 1.4;
                    if (newName && newMinSize > 0 && newMaxSize > 0) {
                        if (activeTab === 'class') sizes[sizeIndex].className = newName;
                        else sizes[sizeIndex].tagName = newName;
                        sizes[sizeIndex].lineHeight = newLineHeight;
                        if (unitType === 'px') {
                            sizes[sizeIndex].min = newMinSize;
                            sizes[sizeIndex].max = newMaxSize;
                        } else {
                            sizes[sizeIndex].min = newMinSize * rootSize;
                            sizes[sizeIndex].max = newMaxSize * rootSize;
                        }
                        if (activeTab === 'scale' && sizes[sizeIndex].tagName === 'p') {
                            scalePMinFont = sizes[sizeIndex].min;
                            scalePMaxFont = sizes[sizeIndex].max;
                            scalePLineHeight = newLineHeight;
                            scalePMinFontInput.value = unitType === 'px' ? scalePMinFont : scalePMinFont / rootSize;
                            scalePMaxFontInput.value = unitType === 'px' ? scalePMaxFont : scalePMaxFont / rootSize;
                            generateScaleSizes();
                        }
                        renderSizesTable();
                        renderPreviews();
                        generateAllCode();
                        if (activeTab !== 'scale') saveFontSizes();
                        saveSettings();
                        closeEditModal();
                    }
                }
            });

            function renderSizesTable() {
                sizesTable.innerHTML = '';
                const sizes = activeTab === 'class' ? classSizes : (activeTab === 'tag' ? tagSizes : scaleSizes);
                const selectedSizeId = activeTab === 'class' ? selectedClassSizeId : (activeTab === 'tag' ? selectedTagSizeId : selectedScaleSizeId);
                sizes.forEach((size, index) => {
                    const row = document.createElement('tr');
                    row.className = `size-row ${size.id === selectedSizeId ? 'selected' : ''}`;
                    row.dataset.id = size.id;
                    const isScaleNonP = activeTab === 'scale' && size.tagName !== 'p';
                    row.draggable = !isScaleNonP;
                    const minSizeDisplay = unitType === 'px' ? size.min.toFixed(2) : (size.min / rootSize).toFixed(2);
                    const maxSizeDisplay = unitType === 'px' ? size.max.toFixed(2) : (size.max / rootSize).toFixed(2);
                    const name = activeTab === 'class' ? size.className : size.tagName;
                    row.innerHTML = `
                        <td class="px-2 py-1"><div class="drag-handle text-gray-400 cursor-move ${isScaleNonP ? 'opacity-0' : ''}">⬍</div></td>
                        <td class="px-2 py-[2px] font-medium">${name}</td>
                        <td class="px-2 py-[2px]">${minSizeDisplay} ${unitType}</td>
                        <td class="px-2 py-[2px]">${maxSizeDisplay} ${unitType}</td>
                        <td class="px-2 py-[2px]">${(size.lineHeight ?? 1.4).toFixed(1)}</td>
                        <td class="px-2 py-[2px] flex space-x-1">
                            <button class="edit-btn text-blue-500 hover:text-blue-700 ${isScaleNonP ? 'opacity-0 pointer-events-none' : ''}">
                                <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
                                </svg>
                            </button>
                            <button id="delete-btn" class="delete-btn text-red-500 hover:text-red-700 ${isScaleNonP ? 'opacity-0 pointer-events-none' : ''}">
                                <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                                </svg>
                            </button>
                        </td>
                    `;
                    row.addEventListener('click', (e) => {
                        if (!e.target.closest('.edit-btn') && !e.target.closest('.delete-btn')) {
                            if (activeTab === 'class') selectedClassSizeId = size.id;
                            else if (activeTab === 'tag') selectedTagSizeId = size.id;
                            else if (activeTab === 'scale') selectedScaleSizeId = size.id;
                            renderSizesTable();
                            renderPreviews();
                            generateAllCode();
                            saveSettings();
                        }
                    });
                    const editBtn = row.querySelector('.edit-btn');
                    editBtn.addEventListener('click', () => openEditModal(size.id));
                    const deleteBtn = row.querySelector('.delete-btn');
                    deleteBtn.addEventListener('click', () => {
                        if (confirm(`Are you sure you want to delete the "${name}"`)) {
                            const sizes = activeTab === 'class' ? classSizes : (activeTab === 'tag' ? tagSizes : scaleSizes);
                            sizes.splice(index, 1);
                            if (activeTab === 'class' && selectedClassSizeId === size.id) {
                                selectedClassSizeId = classSizes.length > 0 ? classSizes[0].id : null;
                            } else if (activeTab === 'tag' && selectedTagSizeId === size.id) {
                                selectedTagSizeId = tagSizes.length > 0 ? tagSizes[0].id : null;
                            } else if (activeTab === 'scale' && selectedScaleSizeId === size.id) {
                                selectedScaleSizeId = scaleSizes.length > 0 ? scaleSizes[0].id : null;
                            }
                            renderSizesTable();
                            renderPreviews();
                            generateAllCode();
                            if (activeTab !== 'scale') saveFontSizes();
                            saveSettings();
                        }
                    });
                    if (!isScaleNonP) {
                        row.addEventListener('dragstart', (e) => {
                            row.classList.add('dragging');
                            e.dataTransfer.setData('text/plain', size.id);
                        });
                        row.addEventListener('dragend', () => {
                            row.classList.remove('dragging');
                            sizesTable.querySelectorAll('.size-row').forEach(r => r.classList.remove('drag-over'));
                        });
                        row.addEventListener('dragover', (e) => {
                            e.preventDefault();
                            row.classList.add('drag-over');
                        });
                        row.addEventListener('dragleave', () => {
                            row.classList.remove('drag-over');
                        });
                        row.addEventListener('drop', (e) => {
                            e.preventDefault();
                            const draggedId = parseInt(e.dataTransfer.getData('text/plain'));
                            const targetId = parseInt(row.dataset.id);
                            const sizes = activeTab === 'class' ? classSizes : (activeTab === 'tag' ? tagSizes : scaleSizes);
                            const draggedIndex = sizes.findIndex(s => s.id === draggedId);
                            const targetIndex = sizes.findIndex(s => s.id === targetId);
                            const [draggedItem] = sizes.splice(draggedIndex, 1);
                            sizes.splice(targetIndex, 0, draggedItem);
                            renderSizesTable();
                            renderPreviews();
                            generateAllCode();
                            if (activeTab !== 'scale') saveFontSizes();
                            sizesTable.querySelectorAll('.size-row').forEach(r => r.classList.remove('drag-over'));
                        });
                    }
                    sizesTable.appendChild(row);
                });
            }

            function renderPreviews() {
                previewContainer.innerHTML = '';
                const sizes = activeTab === 'class' ? classSizes : (activeTab === 'tag' ? tagSizes : scaleSizes);
                const selectedSizeId = activeTab === 'class' ? selectedClassSizeId : (activeTab === 'tag' ? selectedTagSizeId : selectedScaleSizeId);
                sizes.forEach(size => {
                    const previewDiv = document.createElement('div');
                    previewDiv.className = `px-2 py-[0px] border rounded-lg ${size.id === selectedSizeId ? 'border-blue-500 bg-blue-50' : 'border-gray-200'}`;
                    const flexContainer = document.createElement('div');
                    flexContainer.className = 'flex justify-between items-center';
                    const minPreviewContainer = document.createElement('div');
                    minPreviewContainer.className = 'flex-1 text-center';
                    const minPreview = document.createElement('div');
                    minPreview.className = `preview-text ${activeTab !== 'class' && size.tagName === 'p' ? 'p' : ''}`;
                    minPreview.style.fontSize = `${size.min}px`;
                    minPreview.style.lineHeight = `${(size.lineHeight ?? 1.4).toFixed(1)}`;
                    minPreview.textContent = activeTab === 'class' ? size.className : size.tagName;
                    minPreviewContainer.appendChild(minPreview);
                    const maxPreviewContainer = document.createElement('div');
                    maxPreviewContainer.className = 'flex-1 text-center';
                    const maxPreview = document.createElement('div');
                    maxPreview.className = `preview-text ${activeTab !== 'class' && size.tagName === 'p' ? 'p' : ''}`;
                    maxPreview.style.fontSize = `${size.max}px`;
                    maxPreview.style.lineHeight = `${(size.lineHeight ?? 1.4).toFixed(1)}`;
                    maxPreview.textContent = activeTab === 'class' ? size.className : size.tagName;
                    maxPreviewContainer.appendChild(maxPreview);
                    const divider = document.createElement('div');
                    divider.className = 'mx-1 h-8 border-l border-gray-300';
                    flexContainer.appendChild(minPreviewContainer);
                    flexContainer.appendChild(divider);
                    flexContainer.appendChild(maxPreviewContainer);
                    previewDiv.appendChild(flexContainer);
                    previewDiv.addEventListener('click', () => {
                        if (activeTab === 'class') selectedClassSizeId = size.id;
                        else if (activeTab === 'tag') selectedTagSizeId = size.id;
                        else if (activeTab === 'scale') selectedScaleSizeId = size.id;
                        renderSizesTable();
                        renderPreviews();
                        generateAllCode();
                        saveSettings();
                    });
                    previewContainer.appendChild(previewDiv);
                });
            }

            function calculateClamp(minSize, maxSize, minViewport, maxViewport) {
                const minSizePx = minSize;
                const maxSizePx = maxSize;
                const slope = (maxSizePx - minSizePx) / (maxViewport - minViewport);
                const yIntercept = minSizePx - slope * minViewport;
                const slopeVw = slope * 100;
                const minSizeRem = minSizePx / rootSize;
                const maxSizeRem = maxSizePx / rootSize;
                const yInterceptRem = yIntercept / rootSize;
                return `clamp(${minSizeRem.toFixed(2)}rem, ${yInterceptRem.toFixed(5)}rem + ${slopeVw.toFixed(5)}vw, ${maxSizeRem.toFixed(2)}rem)`;
            }

            function generateClassCode(size) {
                const clampValue = calculateClamp(size.min, size.max, minViewport, maxViewport);
                if (activeTab === 'class') {
                    return `:is(.${size.className} :is(h1, h2, h3, h4, h5, h6, p, a, span, button, div, li), .${size.className}:is(.e-heading-base, .e-paragraph-base, .e-button-base)) {
    font-size: ${clampValue};
    line-height: ${(size.lineHeight ?? 1.4).toFixed(1)};
}
`;
                } else {
                    return `${size.tagName} {\n    font-size: ${clampValue};\n    line-height: ${(size.lineHeight ?? 1.4).toFixed(1)};\n}\n`;
                }
            }

            function generateAllCode() {
                const sizes = activeTab === 'class' ? classSizes : (activeTab === 'tag' ? tagSizes : scaleSizes);
                if (sizes.length === 0) {
                    classCode.textContent = '';
                    generatedCode.textContent = `/* No ${activeTab === 'class' ? 'classes' : (activeTab === 'tag' ? 'tags' : 'scale entries')} defined */`;
                    return;
                }
                let code = `html { font-size: ${rootSize}px; } /* Default root size */\n\n`;
                sizes.forEach(size => {
                    code += generateClassCode(size) + '\n';
                });
                generatedCode.textContent = code.trim();
                const selectedSizeId = activeTab === 'class' ? selectedClassSizeId : (activeTab === 'tag' ? selectedTagSizeId : selectedScaleSizeId);
                const selectedSize = sizes.find(size => size.id === selectedSizeId);
                classCode.textContent = selectedSize ? generateClassCode(selectedSize) : '';
            }

            function copyToClipboard(text) {
                navigator.clipboard.writeText(text);
            }

            function showCopyFeedback(button) {
                const originalText = button.textContent;
                button.textContent = 'Copied!';
                button.classList.add('bg-green-600');
                setTimeout(() => {
                    button.textContent = originalText;
                    button.classList.remove('bg-green-600');
                }, 1500);
            }

            let boundUpdateLivePreview = null;

            function openEditModal(sizeId) {
                const sizes = activeTab === 'class' ? classSizes : (activeTab === 'tag' ? tagSizes : scaleSizes);
                const size = sizes.find(s => s.id === sizeId);
                if (!size || (activeTab === 'scale' && size.tagName !== 'p')) return;
                editingSizeId = sizeId;
                editClassName.value = activeTab === 'class' ? size.className : size.tagName;
                if (unitType === 'px') {
                    editMinSize.value = size.min.toFixed(1);
                    editMaxSize.value = size.max.toFixed(1);
                } else {
                    editMinSize.value = (size.min / rootSize).toFixed(2);
                    editMaxSize.value = (size.max / rootSize).toFixed(2);
                }
                editLineHeight.value = size.lineHeight ?? 1.4;
                editClassName.disabled = activeTab === 'scale';
                editModal.classList.remove('hidden');
                editModal.classList.remove('justify-center');
                editModal.classList.add('justify-start');
                boundUpdateLivePreview = function() {
                    const newMin = parseFloat(editMinSize.value) || 0;
                    const newMax = parseFloat(editMaxSize.value) || 0;
                    const tempSize = { ...size };
                    if (unitType === 'px') {
                        tempSize.min = newMin;
                        tempSize.max = newMax;
                    } else {
                        tempSize.min = newMin * rootSize;
                        tempSize.max = newMax * rootSize;
                    }
                    if (activeTab === 'class') tempSize.className = editClassName.value;
                    else tempSize.tagName = editClassName.value;
                    const previewBlock = [...previewContainer.children].find(block => {
                        return block.querySelector('.preview-text')?.textContent === (activeTab === 'class' ? size.className : size.tagName);
                    });
                    if (previewBlock) {
                        const minPreview = previewBlock.querySelector('.flex > div:first-child .preview-text');
                        const maxPreview = previewBlock.querySelector('.flex > div:last-child .preview-text');
                        if (minPreview) minPreview.style.fontSize = `${tempSize.min}px`;
                        if (maxPreview) maxPreview.style.fontSize = `${tempSize.max}px`;
                    }
                    classCode.textContent = generateClassCode(tempSize);
                };
                editMinSize.addEventListener('input', boundUpdateLivePreview);
                editMaxSize.addEventListener('input', boundUpdateLivePreview);
            }

            function closeEditModal() {
                editModal.classList.add('hidden');
                editingSizeId = null;
                editClassName.value = '';
                editMinSize.value = '';
                editMaxSize.value = '';
                editClassName.disabled = false;
                if (boundUpdateLivePreview) {
                    editMinSize.removeEventListener('input', boundUpdateLivePreview);
                    editMaxSize.removeEventListener('input', boundUpdateLivePreview);
                    boundUpdateLivePreview = null;
                }
            }

            init();
        </script>
    </div>
    <?php
}

function save_font_clamp_sizes() {
    check_ajax_referer('font_clamp_nonce', 'nonce');
    if (isset($_POST['class_sizes']) && isset($_POST['tag_sizes'])) {
        $class_sizes = json_decode(stripslashes($_POST['class_sizes']), true);
        $tag_sizes = json_decode(stripslashes($_POST['tag_sizes']), true);
        if (json_last_error() === JSON_ERROR_NONE) {
            update_option('font_clamp_class_sizes', $class_sizes);
            update_option('font_clamp_tag_sizes', $tag_sizes);
            wp_send_json_success();
        } else {
            wp_send_json_error('Invalid JSON data');
        }
    } else {
        wp_send_json_error('No sizes provided');
    }
}
add_action('wp_ajax_save_font_clamp_sizes', 'save_font_clamp_sizes');

function reset_font_clamp_defaults() {
    check_ajax_referer('font_clamp_nonce', 'nonce');
    $tab = isset($_POST['tab']) ? sanitize_text_field($_POST['tab']) : 'class';
    if ($tab === 'class') {
        update_option('font_clamp_class_sizes', [
            ['id' => 1, 'className' => 'xxxlarge', 'min' => 42, 'max' => 52, 'lineHeight' => 1.3],
            ['id' => 2, 'className' => 'xxlarge', 'min' => 36, 'max' => 44, 'lineHeight' => 1.3],
            ['id' => 3, 'className' => 'xlarge', 'min' => 30, 'max' => 36, 'lineHeight' => 1.3],
            ['id' => 4, 'className' => 'large', 'min' => 24, 'max' => 28, 'lineHeight' => 1.3],
            ['id' => 5, 'className' => 'medium', 'min' => 18, 'max' => 20, 'lineHeight' => 1.3],
            ['id' => 6, 'className' => 'normal', 'min' => 16, 'max' => 16, 'lineHeight' => 1.3],
            ['id' => 7, 'className' => 'small', 'min' => 15, 'max' => 15, 'lineHeight' => 1.3],
            ['id' => 8, 'className' => 'xsmall', 'min' => 14, 'max' => 14, 'lineHeight' => 1.3]
        ]);
        update_option('font_clamp_settings', array_merge(get_option('font_clamp_settings', []), [
            'selectedClassSizeId' => 6,
            'previewFontUrl' => '',
            'previewFontUrlP' => ''
        ]));
    } else if ($tab === 'tag') {
        update_option('font_clamp_tag_sizes', [
            ['id' => 1, 'tagName' => 'h1', 'min' => 36, 'max' => 48, 'lineHeight' => 1.4],
            ['id' => 2, 'tagName' => 'h2', 'min' => 30, 'max' => 40, 'lineHeight' => 1.4],
            ['id' => 3, 'tagName' => 'h3', 'min' => 24, 'max' => 32, 'lineHeight' => 1.4],
            ['id' => 4, 'tagName' => 'h4', 'min' => 20, 'max' => 28, 'lineHeight' => 1.4],
            ['id' => 5, 'tagName' => 'h5', 'min' => 18, 'max' => 24, 'lineHeight' => 1.4],
            ['id' => 6, 'tagName' => 'h6', 'min' => 16, 'max' => 20, 'lineHeight' => 1.4],
            ['id' => 7, 'tagName' => 'p', 'min' => 14, 'max' => 18, 'lineHeight' => 1.4]
        ]);
        update_option('font_clamp_settings', array_merge(get_option('font_clamp_settings', []), [
            'selectedTagSizeId' => 1,
            'previewFontUrl' => '',
            'previewFontUrlP' => ''
        ]));
    } else if ($tab === 'scale') {
        update_option('font_clamp_settings', array_merge(get_option('font_clamp_settings', []), [
            'scalePMinFont' => 16,
            'scalePMaxFont' => 16,
            'scaleRatioMin' => 1.333,
            'scaleRatioMax' => 1.4,
            'scalePLineHeight' => 1.4,
            'selectedScaleSizeId' => 7,
            'previewFontUrl' => '',
            'previewFontUrlP' => ''
        ]));
    }
    wp_send_json_success();
}
add_action('wp_ajax_reset_font_clamp_defaults', 'reset_font_clamp_defaults');

function save_font_clamp_settings() {
    check_ajax_referer('font_clamp_nonce', 'nonce');
    if (isset($_POST['settings'])) {
        $settings = json_decode(stripslashes($_POST['settings']), true);
        if (json_last_error() === JSON_ERROR_NONE) {
            update_option('font_clamp_settings', $settings);
            wp_send_json_success();
        } else {
            wp_send_json_error('Invalid JSON data');
        }
    } else {
        wp_send_json_error('No settings provided');
    }
}
add_action('wp_ajax_save_font_clamp_settings', 'save_font_clamp_settings');

function font_clamp_push_to_customizer() {
    check_ajax_referer('font_clamp_nonce', 'nonce');
    if (!current_user_can('edit_theme_options')) {
        wp_send_json_error('Permission denied');
    }
    $new_css = stripslashes($_POST['css'] ?? '');
    $existing_css = wp_get_custom_css();
    $final_css = $existing_css . "\n\n/* Font Clamp Calculator Output */\n" . $new_css;
    $result = wp_update_custom_css_post($final_css);
    if ($result instanceof WP_Post) {
        wp_send_json_success();
    } else {
        wp_send_json_error('Failed to update customizer CSS');
    }
}
add_action('wp_ajax_font_clamp_push_to_customizer', 'font_clamp_push_to_customizer');

function font_clamp_calculator_enqueue_assets() {
    if (isset($_GET['page']) && $_GET['page'] === 'font-clamp-calculator') {
        wp_enqueue_style('font-clamp-tailwind', 'https://cdn.tailwindcss.com', [], null);
    }
}
add_action('admin_enqueue_scripts', 'font_clamp_calculator_enqueue_assets');

add_shortcode('font_clamp_calculator', 'render_font_clamp_calculator_shortcode');

function render_font_clamp_calculator_shortcode() {
    ob_start();
    $settings = get_option('font_clamp_settings', [
        'rootSize' => 16,
        'minViewport' => 375,
        'maxViewport' => 1100,
        'unitType' => 'px',
        'selectedClassSizeId' => 6,
        'selectedTagSizeId' => 1,
        'selectedScaleSizeId' => 7,
        'scalePMinFont' => 16,
        'scalePMaxFont' => 16,
        'scaleRatioMin' => 1.333,
        'scaleRatioMax' => 1.4,
        'scalePLineHeight' => 1.4,
        'previewFontUrl' => '',
        'previewFontUrlP' => '',
        'activeTab' => 'class'
    ]);
    font_clamp_calculator_page();
    return ob_get_clean();
}

add_action('wp_enqueue_scripts', 'enqueue_font_clamp_tailwind_frontend');
function enqueue_font_clamp_tailwind_frontend() {
    if (is_singular()) {
        global $post;
        if (has_shortcode($post->post_content, 'font_clamp_calculator')) {
            wp_enqueue_script('font-clamp-tailwind', 'https://cdn.tailwindcss.com', [], null, true);
        }
    }
}/* End custom CSS */