# easy-invoice/2.2.0/templates/quotes/single.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.2.0. 1,715 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.2.0/code/templates/quotes/single.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.2.0/raw/templates/quotes/single.php
- Modified: 2026-04-29T02:55:08+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/easy-invoice/2.2.0/code/templates/quotes/single.php#L10-L20`.

```php
<?php
/**
 * Single Quote Template (Bare)
 *
 * @package Easy_Invoice
 * @subpackage Templates
 */



// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}


// Hide the admin bar for this view
add_filter('show_admin_bar', '__return_false');

// Get quote from WordPress query
global $post;
$quote = null;

if ($post && $post->post_type === \EasyInvoice\Constants\PostTypes::EASY_INVOICE_QUOTE_POST_TYPE) {
    // Load quote from post using the correct service provider
    $quote = \EasyInvoice\Providers\QuoteServiceProvider::getQuoteRepository()->find($post->ID);

    // Ensure quote has proper slug for pretty URLs
    if ($quote) {
        $quote->ensureProperSlug();
    }
}

if (!$quote) {
    wp_die(__('Quote not found.', 'easy-invoice'));
}

// Get the selected template for this quote
$current_template = $quote->getTemplate();
if (empty($current_template)) {
    $current_template = 'standard';
}

// Initialize formatter for the quote templates
$formatter = new \EasyInvoice\Helpers\QuoteFormatter($quote);

  // Check if the template file exists
$template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/' . $current_template . '.php';

$template_file = file_exists($template_file) ? $template_file : EASY_INVOICE_PLUGIN_DIR . 'templates/quote-templates/default.php';

?><!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
    <meta charset="<?php bloginfo('charset'); ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php echo esc_html($quote->getTitle() ?: __('Quote', 'easy-invoice')); ?></title>

    <!-- Load jQuery and toast system for better user experience -->
    <script src="<?php echo esc_url(includes_url('js/jquery/jquery.min.js')); ?>"></script>
    <script src="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/js/easy-invoice-toast.js'); ?>"></script>
    <script src="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/js/confirmation-modal.js'); ?>"></script>

    <!-- Load jsPDF for PDF generation -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
    <script src="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/js/document-pdf.js?ver=' . rawurlencode(EASY_INVOICE_VERSION)); ?>"></script>
    <!-- Note: Pro version's pdf-watermark.js will be loaded automatically by the Pro plugin -->
    <!-- Add Font Awesome for payment icons -->
    <link rel="stylesheet" href="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/lib/font-awesome/css/all.min.css'); ?>">
    <?php do_action('easy_invoice_head'); ?>
    <!-- Define quote action functions -->
    <script>
    // Global functions for quote actions
    function resetButtonLoading(button, originalText) {
        if (button) {
            button.innerHTML = originalText;
            button.disabled = false;
        }
    }

    // Handle Download PDF
    function handleDownloadPDF(quoteId, button) {
        const originalText = button.innerHTML;
        button.innerHTML = '<?php _e('Generating PDF...', 'easy-invoice'); ?>';
        button.disabled = true;

        try {
            // Use the unified PDF generator
            if (typeof DocumentPdfGenerator !== 'undefined') {
                const pdfGenerator = new DocumentPdfGenerator('quote');
                pdfGenerator.generatePDF();
            } else {
                throw new Error('PDF generator not available');
            }
        } catch (error) {
            console.error('PDF generation error:', error);
            showMessage('<?php _e('Error generating PDF', 'easy-invoice'); ?>', 'error');
        } finally {
            button.innerHTML = originalText;
            button.disabled = false;
        }
    }

    // Handle Send Email
    function handleSendEmail(quoteId, confirmBtn, originalText) {
        // Fallback loading if modal helper is not yet defined
        if (typeof showModalLoading === 'function') {
            showModalLoading('<?php echo esc_js(__('Sending email...', 'easy-invoice')); ?>');
        } else if (confirmBtn) {
            confirmBtn.disabled = true;
            confirmBtn.dataset._oldText = confirmBtn.innerHTML;
            confirmBtn.innerHTML = '<?php echo esc_js(__('Sending...', 'easy-invoice')); ?>';
        }
        jQuery.ajax({
            url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
            type: 'POST',
            data: {
                action: 'easy_invoice_send_quote_email',
                quote_id: quoteId,
                nonce: '<?php echo wp_create_nonce('easy_invoice_send_quote_email'); ?>'
            },
            success: function(response) {
                var msg = '';
                if (response.success) {
                    msg = (response && response.data && (response.data.message || (response.data.toast && response.data.toast.message))) || '<?php _e('Email sent successfully', 'easy-invoice'); ?>';
                    showModalMessage('success', msg);
                } else {
                    // Handle both response.data.message and response.data (direct string)
                    if (response && response.data) {
                        if (response.data.message) {
                            msg = response.data.message;
                        } else if (typeof response.data === 'string') {
                            msg = response.data;
                        } else if (response.data.toast && response.data.toast.message) {
                            msg = response.data.toast.message;
                        }
                    }
                    msg = msg || '<?php _e('Error sending email', 'easy-invoice'); ?>';

                    if (confirmBtn && confirmBtn.dataset._oldText) {
                        confirmBtn.innerHTML = confirmBtn.dataset._oldText;
                        confirmBtn.disabled = false;
                        delete confirmBtn.dataset._oldText;
                    } else {
                        resetButtonLoading(confirmBtn, originalText);
                    }
                    showModalMessage('error', msg);
                }
            },
            error: function(jqXHR) {
                var msg = (jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.data && (jqXHR.responseJSON.data.message || (jqXHR.responseJSON.data.toast && jqXHR.responseJSON.data.toast.message))) || '';
                if (confirmBtn && confirmBtn.dataset._oldText) {
                    confirmBtn.innerHTML = confirmBtn.dataset._oldText;
                    confirmBtn.disabled = false;
                    delete confirmBtn.dataset._oldText;
                } else {
                    resetButtonLoading(confirmBtn, originalText);
                }
                showModalMessage('error', msg || '<?php _e('Error connecting to server', 'easy-invoice'); ?>');
            }
        });
    }

    // Show message function
    function showMessage(message, type) {
        if (typeof EasyInvoiceToast !== 'undefined') {
            if (type === 'success') {
                EasyInvoiceToast.success(message);
            } else {
                EasyInvoiceToast.error(message);
            }
        } else {
            alert(message);
        }
    }

    // Generic confirmation modal (global) - modern ES6 syntax
    function showConfirmationModal(title, message, confirmText, cancelText, confirmType, onConfirm) {
        // Remove existing modal if any
        const existingModal = document.querySelector('.ei-modal-overlay');
        if (existingModal) {
            existingModal.remove();
        }

        // Create modal overlay
        const overlay = document.createElement('div');
        overlay.className = 'ei-modal-overlay';

        // Create modal content
        const modal = document.createElement('div');
        modal.className = 'ei-modal';

        const confirmBtnClass = confirmType === 'danger' ? 'ei-modal-btn-danger' : 'ei-modal-btn-primary';
        const iconClass = confirmType === 'danger' ? 'danger' : 'info';
        const icon = confirmType === 'danger' ?
            '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="none"/><path d="M12 7v4.5M12 16h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>' :
            '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="none"/><path d="M12 16v-4M12 8h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';

        modal.innerHTML = `
            <div class="ei-modal-header">
                <div class="ei-modal-icon ${iconClass}">
                    ${icon}
                </div>
                <h3 class="ei-modal-title">${title}</h3>
            </div>
            <div class="ei-modal-body">
                <div class="ei-modal-message">${message}</div>
            </div>
            <div class="ei-modal-actions">
                <button type="button" class="ei-modal-btn ei-modal-btn-secondary" id="modal-cancel">${cancelText}</button>
                <button type="button" class="ei-modal-btn ${confirmBtnClass}" id="modal-confirm">${confirmText}</button>
            </div>
        `;

        overlay.appendChild(modal);
        document.body.appendChild(overlay);

        // Show modal with animation
        setTimeout(() => {
            overlay.classList.add('show');
            modal.classList.add('show');
        }, 10);

        // Handle button clicks
        const confirmBtn = modal.querySelector('#modal-confirm');
        const cancelBtn = modal.querySelector('#modal-cancel');

        confirmBtn.addEventListener('click', function() {
            const originalText = confirmBtn.innerHTML;
            setButtonLoading(confirmBtn, confirmBtn.textContent.trim());
            onConfirm(modal, confirmBtn, originalText);
        });

        cancelBtn.addEventListener('click', function() {
            hideModal(overlay);
        });

        // Handle overlay click to close
        overlay.addEventListener('click', function(e) {
            if (e.target === overlay) {
                hideModal(overlay);
            }
        });

        // Handle escape key
        const handleEscape = function(e) {
            if (e.key === 'Escape') {
                hideModal(overlay);
                document.removeEventListener('keydown', handleEscape);
            }
        };
        document.addEventListener('keydown', handleEscape);

        // Focus on confirm button
        setTimeout(() => {
            confirmBtn.focus();
        }, 100);
    }

    // Wrapper to confirm sending quote email
    function confirmSendEmail(quoteId) {
        const title = '<?php echo esc_js(__('Send Email', 'easy-invoice')); ?>';
        const message = '<?php echo esc_js(__('Send this quote via email?', 'easy-invoice')); ?>\n\n<?php echo esc_js(__('This will send the quote to the client\'s email address.', 'easy-invoice')); ?>';
        const confirmText = '<?php echo esc_js(__('Send Email', 'easy-invoice')); ?>';
        const cancelText = '<?php echo esc_js(__('Cancel', 'easy-invoice')); ?>';
        showConfirmationModal(title, message, confirmText, cancelText, 'primary', function(modal, confirmBtn, originalText) {
            handleSendEmail(quoteId, confirmBtn, originalText);
        });
    }

    // Global modal helpers
    function hideModal(overlay) {
        const modal = overlay.querySelector('.ei-modal');
        modal.classList.remove('show');
        overlay.classList.remove('show');

        setTimeout(() => {
            if (overlay.parentNode) {
                overlay.remove();
            }
        }, 300);
    }

    // Utility: Show loading spinner in a button
    function setButtonLoading(btn, loadingText) {
        btn.disabled = true;
        btn.innerHTML = `<span class='ei-btn-spinner' style='display:inline-block;vertical-align:middle;width:18px;height:18px;margin-right:8px;'>
            <svg width='18' height='18' viewBox='0 0 50 50'><circle cx='25' cy='25' r='20' fill='none' stroke='#fff' stroke-width='5' stroke-linecap='round' stroke-dasharray='31.415, 31.415' transform='rotate(0 25 25)'><animateTransform attributeName='transform' type='rotate' from='0 25 25' to='360 25 25' dur='0.8s' repeatCount='indefinite'/></circle></svg>
        </span>${loadingText}`;
    }

    function resetButtonLoading(btn, originalText) {
        btn.disabled = false;
        btn.innerHTML = originalText;
    }

    // Show message in modal (used for AJAX responses)
    function showModalMessage(type, message, onClose) {
        // Remove existing modal if any
        const existingModal = document.querySelector('.ei-modal-overlay');
        if (existingModal) {
            existingModal.remove();
        }
        // Create modal overlay
        const overlay = document.createElement('div');
        overlay.className = 'ei-modal-overlay';
        // Create modal content
        const modal = document.createElement('div');
        modal.className = 'ei-modal';
        const iconClass = type === 'success' ? 'info' : 'danger';
        const icon = type === 'success'
            ? '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#10b981"/><path d="M7 13l3 3 7-7" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
            : '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#ef4444"/><path d="M12 7v4.5M12 16h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
        modal.innerHTML = `
            <div class="ei-modal-header">
                <div class="ei-modal-icon ${iconClass}">${icon}</div>
                <h3 class="ei-modal-title">${type === 'success' ? '<?php echo esc_js(__('Success', 'easy-invoice')); ?>' : '<?php echo esc_js(__('Error', 'easy-invoice')); ?>'}</h3>
            </div>
            <div class="ei-modal-body">
                <div class="ei-modal-message">${message}</div>
            </div>
            <div class="ei-modal-actions">
                <button type="button" class="ei-modal-btn ei-modal-btn-primary" id="modal-close"><?php echo esc_js(__('Close', 'easy-invoice')); ?></button>
            </div>
        `;
        overlay.appendChild(modal);
        document.body.appendChild(overlay);
        setTimeout(() => {
            overlay.classList.add('show');
            modal.classList.add('show');
        }, 10);
        const closeBtn = modal.querySelector('#modal-close');
        closeBtn.addEventListener('click', function() {
            hideModal(overlay);
            if (onClose) onClose();
        });
        overlay.addEventListener('click', function(e) {
            if (e.target === overlay) {
                hideModal(overlay);
                if (onClose) onClose();
            }
        });
        const handleEscape = function(e) {
            if (e.key === 'Escape') {
                hideModal(overlay);
                document.removeEventListener('keydown', handleEscape);
                if (onClose) onClose();
            }
        };
        document.addEventListener('keydown', handleEscape);
        setTimeout(() => {
            closeBtn.focus();
        }, 100);
    }

    // Show loading state in modal
    function showModalLoading(message) {
        // Remove existing modal if any
        const existingModal = document.querySelector('.ei-modal-overlay');
        if (existingModal) {
            existingModal.remove();
        }
        // Create modal overlay
        const overlay = document.createElement('div');
        overlay.className = 'ei-modal-overlay';
        // Create modal content
        const modal = document.createElement('div');
        modal.className = 'ei-modal';
        modal.innerHTML = `
            <div class="ei-modal-header">
                <div class="ei-modal-icon info">
                    <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#3b82f6"/><circle cx="12" cy="12" r="6" fill="#fff"/><animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/></svg>
                </div>
                <h3 class="ei-modal-title"><?php echo esc_js(__('Please wait...', 'easy-invoice')); ?></h3>
            </div>
            <div class="ei-modal-body">
                <div class="ei-modal-message">${message}</div>
            </div>
        `;
        overlay.appendChild(modal);
        document.body.appendChild(overlay);
        setTimeout(() => {
            overlay.classList.add('show');
            modal.classList.add('show');
        }, 10);
    }


    </script>

    <style>
        body { margin: 0; padding: 0; font-family: sans-serif; background: #eaeaea; color: #222; }
        .easy-invoice-quote-container { max-width: 800px; margin: 40px auto; }
        h1, h2, h3 { margin-top: 0; }
        .quote-actions { margin-top: 32px; text-align: center; }
        .quote-actions button, .quote-actions a { margin: 0 8px; padding: 10px 24px; border: none; border-radius: 4px; background: #6366f1; color: #fff; font-size: 1rem; cursor: pointer; text-decoration: none; }
        .quote-actions button.decline { background: #f87171; }
        .quote-actions button:disabled { opacity: 0.6; cursor: not-allowed; }
        .template-not-found { text-align: center; padding: 40px; background: #fff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        .template-not-found-icon { font-size: 48px; color: #dc3545; margin-bottom: 20px; }
        .template-not-found h3 { font-size: 24px; color: #32325d; margin-bottom: 10px; }
        .template-not-found p { color: #8898aa; margin-bottom: 10px; }
        .quote-content { flex: 1; min-width: 0; position: relative; }

        /* Custom Modal Styles */
        .ei-modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.6);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10000;
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            backdrop-filter: blur(4px);
        }

        .ei-modal-overlay.show {
            opacity: 1;
            visibility: visible;
        }

        .ei-modal {
            background: white;
            border-radius: 16px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            max-width: 480px;
            width: 90%;
            max-height: 85vh;
            overflow: hidden;
            transform: scale(0.95) translateY(20px);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            border: 1px solid rgba(0, 0, 0, 0.05);
        }

        .ei-modal.show {
            transform: scale(1) translateY(0);
        }

        .ei-modal-header {
            padding: 32px 32px 0 32px;
            text-align: center;
            position: relative;
        }

        .ei-modal-icon {
            width: 64px;
            height: 64px;
            border-radius: 50%;
            margin: 0 auto 20px auto;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 28px;
            color: white;
        }

        .ei-modal-icon.success {
            background: linear-gradient(135deg, #10b981, #059669);
        }

        .ei-modal-icon.warning {
            background: linear-gradient(135deg, #f59e0b, #d97706);
        }

        .ei-modal-icon.danger {
            background: linear-gradient(135deg, #ef4444, #dc2626);
        }

        .ei-modal-icon.info {
            background: linear-gradient(135deg, #3b82f6, #2563eb);
        }

        .ei-modal-title {
            font-size: 24px;
            font-weight: 700;
            color: #111827;
            margin: 0 0 8px 0;
            line-height: 1.3;
        }

        .ei-modal-subtitle {
            font-size: 16px;
            color: #6b7280;
            margin: 0;
            line-height: 1.5;
        }

        .ei-modal-body {
            padding: 24px 32px 32px 32px;
        }

        .ei-modal-message {
            font-size: 16px;
            line-height: 1.6;
            color: #374151;
            margin: 0;
            white-space: pre-line;
            text-align: center;
        }

        .ei-modal-actions {
            display: flex;
            gap: 12px;
            justify-content: center;
            padding: 0 32px 32px 32px;
        }

        .ei-modal-btn {
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            font-size: 15px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
            min-width: 100px;
            position: relative;
            overflow: hidden;
        }

        .ei-modal-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
            transition: left 0.5s;
        }

        .ei-modal-btn:hover::before {
            left: 100%;
        }

        .ei-modal-btn-secondary {
            background: #f9fafb;
            color: #374151;
            border: 1px solid #e5e7eb;
        }

        .ei-modal-btn-secondary:hover {
            background: #f3f4f6;
            border-color: #d1d5db;
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }

        .ei-modal-btn-primary {
            background: linear-gradient(135deg, #007cba, #005a87);
            color: white;
            box-shadow: 0 4px 12px rgba(0, 124, 186, 0.3);
        }

        .ei-modal-btn-primary:hover {
            background: linear-gradient(135deg, #005a87, #004a6f);
            transform: translateY(-1px);
            box-shadow: 0 6px 16px rgba(0, 124, 186, 0.4);
        }

        .ei-modal-btn-danger {
            background: linear-gradient(135deg, #ef4444, #dc2626);
            color: white;
            box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
        }

        .ei-modal-btn-danger:hover {
            background: linear-gradient(135deg, #dc2626, #b91c1c);
            transform: translateY(-1px);
            box-shadow: 0 6px 16px rgba(239, 68, 68, 0.4);
        }

        .ei-modal-btn:active {
            transform: translateY(0);
        }

        .ei-modal-btn:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none !important;
        }

        /* Reason Field Styles */
        .ei-modal-reason-field {
            margin-top: 28px;
        }
        .ei-modal-label {
            display: block;
            font-size: 15px;
            font-weight: 600;
            color: #374151;
            margin-bottom: 10px;
            text-align: left;
        }
        .ei-modal-textarea {
            width: 100%;
            max-width: 100%;
            box-sizing: border-box;
            padding: 14px 18px;
            border: 1.5px solid #d1d5db;
            border-radius: 10px;
            font-size: 15px;
            line-height: 1.6;
            color: #374151;
            background: #f8fafc;
            transition: border-color 0.2s, box-shadow 0.2s;
            resize: vertical;
            min-height: 90px;
            font-family: inherit;
            box-shadow: 0 1px 2px rgba(0,0,0,0.03);
        }
        .ei-modal-textarea:focus {
            outline: none;
            border-color: #ef4444;
            background: #fff;
            box-shadow: 0 0 0 2px #fee2e2;
        }
        .ei-modal-textarea::placeholder {
            color: #9ca3af;
        }
        .ei-modal-textarea.error {
            border-color: #ef4444;
            background: #fef2f2;
        }
        .ei-modal-header {
            padding: 36px 36px 0 36px;
            text-align: center;
            position: relative;
        }
        .ei-modal-icon.danger {
            background: linear-gradient(135deg, #f87171, #dc2626);
            width: 60px;
            height: 60px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            margin: 0 auto 18px auto;
            box-shadow: 0 2px 8px rgba(239,68,68,0.10);
        }
        .ei-modal-icon.danger svg {
            width: 32px;
            height: 32px;
            display: block;
        }
        .ei-modal-icon.info {
            background: linear-gradient(135deg, #60a5fa, #3b82f6);
            width: 60px;
            height: 60px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            margin: 0 auto 18px auto;
            box-shadow: 0 2px 8px rgba(59,130,246,0.10);
        }
        .ei-modal-icon.info svg {
            width: 32px;
            height: 32px;
            display: block;
        }
        .ei-modal-title {
            font-size: 23px;
            font-weight: 700;
            color: #111827;
            margin: 0 0 10px 0;
            line-height: 1.3;
        }
        .ei-modal-body {
            padding: 28px 36px 36px 36px;
        }
        .ei-modal-message {
            font-size: 16px;
            line-height: 1.7;
            color: #374151;
            margin: 0 0 18px 0;
            white-space: pre-line;
            text-align: center;
        }
        .ei-modal-actions {
            display: flex;
            gap: 16px;
            justify-content: center;
            padding: 0 36px 36px 36px;
            margin-top: 18px;
        }
        .ei-modal {
            background: white;
            border-radius: 18px;
            box-shadow: 0 30px 60px -10px rgba(0,0,0,0.22), 0 2px 8px rgba(0,0,0,0.08);
            max-width: 420px;
            width: 95%;
            max-height: 90vh;
            overflow: hidden;
            transform: scale(0.95) translateY(20px);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            border: 1px solid rgba(0, 0, 0, 0.04);
        }
        @media (max-width: 640px) {
            .ei-modal {
                width: 99%;
                margin: 10px;
            }
            .ei-modal-header, .ei-modal-body, .ei-modal-actions {
                padding-left: 12px;
                padding-right: 12px;
            }
        }

        @media print {
            .quote-actions { display: none; }
            body { background: white; }
            .quote-content { box-shadow: none; }
        }
    </style>
</head>
<body>
    <?php
    // Get global quote settings
    $settings_controller = new \EasyInvoice\Controllers\SettingsController();
    $accept_button_text = $settings_controller::getQuoteAcceptText();
    $accept_action = $settings_controller::getQuoteAcceptAction();
    $declined_message = $settings_controller::getDeclinedQuoteMessage();

    // Determine what happens when quote is accepted based on global settings
    $accept_action_description = '';
    switch ($accept_action) {
        case 'convert':
            $accept_action_description = __('This will convert the quote to an invoice.', 'easy-invoice');
            break;
        case 'convert_send':
            $accept_action_description = __('This will convert the quote to an invoice and send it to the client.', 'easy-invoice');
            break;
        case 'duplicate':
            $accept_action_description = __('This will create a new invoice while keeping this quote unchanged.', 'easy-invoice');
            break;
        case 'duplicate_send':
            $accept_action_description = __('This will create a new invoice and send it to the client, while keeping this quote unchanged.', 'easy-invoice');
            break;
        case 'do_nothing':
        default:
            $accept_action_description = __('This will mark the quote as accepted.', 'easy-invoice');
            break;
    }
    ?>

    <div class="easy-invoice-quote-container">
        <!-- Accept Action Information - Show at the top -->
        <?php
        // Get text settings for quote actions
        $text_settings = \EasyInvoice\Helpers\TemplateTextHelper::getQuoteTextSettings();
        ?>

        <?php if (in_array($quote->getStatus(), ['available', 'sent', 'draft']) && $accept_action_description): ?>
            <div class="accept-action-info" style="margin-bottom: 16px; padding: 12px; background: #f8f9fa; border-left: 4px solid #007cba; border-radius: 4px; font-size: 0.9em; color: #666;">
                <i class="fas fa-info-circle" style="margin-right: 8px; color: #007cba;"></i>
                <strong><?php echo esc_html($text_settings['accept_quote']); ?>:</strong>
                <?php echo esc_html($accept_action_description); ?>
            </div>
        <?php endif; ?>

        <!-- Quote Actions - All buttons in one line -->
        <div class="quote-actions" style="margin-bottom: 32px; display: flex; gap: 12px; flex-wrap: wrap; align-items: center;">
            <?php if (in_array($quote->getStatus(), ['available', 'sent', 'draft'])): ?>
                <button type="button" class="accept" style="background: #28a745; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500; min-width: 120px; white-space: nowrap; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
                    <?php echo esc_html($text_settings['accept_quote']); ?>
                </button>
                <button type="button" class="decline" style="background: #dc3545; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">
                    <?php echo esc_html($text_settings['decline_quote']); ?>
                </button>
            <?php endif; ?>

            <!-- Additional action buttons -->
            <button type="button" onclick="printQuoteContent()" style="background: #10b981; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">
                <?php echo esc_html($text_settings['print']); ?>
            </button>

            <button type="button"  class="download-pdf-btn" style="background: #f59e0b; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">
                <?php echo esc_html($text_settings['download_pdf']); ?>
            </button>

            <button type="button" onclick="confirmSendEmail(<?php echo esc_js($quote->getId()); ?>)" class="send-email-button" style="background: #8b5cf6; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">
                <?php echo esc_html($text_settings['send_email']); ?>
            </button>
        </div>

        <!-- Quote Content Container -->
        <div class="quote-content" id="quote-content" style="flex: 1; min-width: 0; position: relative;">
            <?php
            // Add Additional CSS button for admin users
            if (is_user_logged_in() && current_user_can('manage_options')):
                $additional_css = get_post_meta($quote->getId(), '_easy_invoice_additional_css', true) ?: '';
                $has_css = !empty($additional_css);
            ?>
            <button type="button" id="additional-css-btn" style="position: absolute; top: 0; left: -40px; background: <?php echo $has_css ? '#10b981' : '#3b82f6'; ?>; color: white; border: none; padding: 6px 10px; border-radius: 3px; cursor: pointer; font-weight: 500; font-size: 11px; line-height: 1; z-index: 1000;" title="Additional CSS<?php echo $has_css ? ' (CSS already added)' : ''; ?>">
                <i class="fas fa-code"></i>
                <?php if ($has_css): ?>
                <span style="position: absolute; top: -4px; right: -4px; background: #ef4444; color: white; border-radius: 50%; width: 8px; height: 8px; font-size: 6px; display: flex; align-items: center; justify-content: center;">•</span>
                <?php endif; ?>
            </button>
            <?php endif; ?>

            <?php do_action('easy_invoice_quote_view_content_top', $quote); ?>
            <?php if (file_exists($template_file)): ?>
                <?php
                // Include the selected template file
                include $template_file;
                ?>
            <?php else: ?>
            <!-- Fallback basic quote display -->
            <div class="quote-header" style="position: relative;">
                <h1><?php echo esc_html($quote->getTitle() ?: __('Quote', 'easy-invoice')); ?>
                    <span class="quote-status"><?php echo esc_html(ucfirst($quote->getStatus())); ?></span>
                </h1>
                                        <div><?php echo esc_html($quote->getNumber()); ?> &bull; <?php echo esc_html(\EasyInvoice\Controllers\SettingsController::formatDate($quote->getCreatedDate())); ?></div>
                <?php if ($quote->getCustomerName()): ?>
                    <div style="margin-top: 12px;">
                        <strong><?php echo esc_html($quote->getCustomerName()); ?></strong><br>
                        <?php echo esc_html($quote->getCustomerEmail()); ?><br>
                        <?php echo esc_html($quote->getCustomerAddress()); ?>
                    </div>
                <?php endif; ?>
            </div>

            <?php if ($quote->getNotes()): ?>
                <div style="margin-bottom: 24px; color: #555;">
                    <?php echo nl2br(esc_html($quote->getNotes())); ?>
                </div>
            <?php endif; ?>

            <table class="quote-items">
                <thead>
                    <tr>
                        <th><?php _e('Item', 'easy-invoice'); ?></th>
                        <th><?php _e('Description', 'easy-invoice'); ?></th>
                        <th><?php _e('Qty', 'easy-invoice'); ?></th>
                        <th><?php _e('Unit Price', 'easy-invoice'); ?></th>
                        <th><?php _e('Adjust (%)', 'easy-invoice'); ?></th>
                        <th><?php _e('Total', 'easy-invoice'); ?></th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($quote->getItems() as $item): ?>
                        <tr>
                            <td><?php echo esc_html($item->getName()); ?></td>
                            <td><?php echo esc_html($item->getDescription()); ?></td>
                            <td><?php echo esc_html($item->getQuantity()); ?></td>
                            <td><?php echo esc_html(number_format_i18n($item->getPrice(), 2)); ?></td>
                            <td><?php
                                $adjust_percentage = $item->getAdjustPercentage();
                                if ($adjust_percentage != 0) {
                                    echo esc_html($adjust_percentage > 0 ? '+' : '') . esc_html($adjust_percentage) . '%';
                                } else {
                                    echo esc_html__('—', 'easy-invoice');
                                }
                            ?></td>
                            <td><?php echo esc_html(number_format_i18n($item->getAmount(), 2)); ?></td>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>

            <div class="quote-summary">
                <div><strong><?php _e('Subtotal', 'easy-invoice'); ?>:</strong> <?php echo esc_html(number_format_i18n($quote->getSubtotal(), 2)); ?></div>
                <?php if ($quote->getDiscountValue() > 0): ?>
                    <div><strong><?php _e('Discount', 'easy-invoice'); ?>:</strong> -<?php echo esc_html(number_format_i18n($quote->getDiscountValue(), 2)); ?></div>
                <?php endif; ?>
                <?php if ($quote->getTaxRate() > 0): ?>
                    <div><strong><?php _e('Tax', 'easy-invoice'); ?> (<?php echo esc_html($quote->getTaxRate()); ?>%):</strong> <?php echo esc_html(number_format_i18n($quote->getTaxAmount(), 2)); ?></div>
                <?php endif; ?>
                <?php do_action('easy_invoice_quote_totals_after_tax', $quote); ?>
                <div style="font-size: 1.2em; margin-top: 8px;"><strong><?php _e('Total', 'easy-invoice'); ?>:</strong> <?php echo esc_html(number_format_i18n($quote->getTotal(), 2)); ?></div>
            </div>
        <?php endif; ?>

        <?php do_action('easy_invoice_quote_content_after', $quote); ?>
        </div>
    </div>

    <script type="text/javascript">
    // Print Quote Content - Global function
    function printQuoteContent() {
        // Get the quote content
        const quoteContent = document.querySelector('.quote-content');

        if (!quoteContent) {
            alert('<?php _e('Quote content not found', 'easy-invoice'); ?>');
            return;
        }

        // Create a new window for printing
        const printWindow = window.open('', '_blank', 'width=800,height=600');

        // Create the print HTML with comprehensive styles
        const printHTML = `
            <!DOCTYPE html>
            <html>
            <head>
                <title><?php echo esc_js($quote->getNumber() ?: __('Quote', 'easy-invoice')); ?></title>
                <meta charset="utf-8">
                <style>
                    /* Reset and base styles */
                    * {
                        margin: 0;
                        padding: 0;
                        box-sizing: border-box;
                    }

                    body {
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        line-height: 1.6;
                        color: #333;
                        background: white;
                        padding: 20px;
                    }

                    /* Quote container styles */
                    .quote-container {
                        max-width: 800px;
                        margin: 0 auto;
                        background: white;
                        padding: 30px;
                        border: 1px solid #e5e7eb;
                        border-radius: 8px;
                    }

                    /* Header styles */
                    .quote-header {
                        margin-bottom: 30px;
                        padding-bottom: 20px;
                        border-bottom: 2px solid #e5e7eb;
                    }

                    .quote-title {
                        font-size: 2em;
                        font-weight: bold;
                        color: #1f2937;
                        margin-bottom: 10px;
                    }

                    .quote-number {
                        font-size: 1.1em;
                        color: #6b7280;
                        margin-bottom: 15px;
                    }

                    .quote-date {
                        color: #6b7280;
                        font-size: 0.9em;
                    }

                    /* Customer info styles */
                    .customer-info {
                        margin-bottom: 30px;
                        padding: 15px;
                        background: #f9fafb;
                        border-radius: 6px;
                    }

                    .customer-name {
                        font-weight: bold;
                        font-size: 1.1em;
                        margin-bottom: 5px;
                    }

                    .customer-email, .customer-address {
                        color: #6b7280;
                        margin-bottom: 3px;
                    }

                    /* Items table styles */
                    .quote-items {
                        width: 100%;
                        border-collapse: collapse;
                        margin-bottom: 30px;
                    }

                    .quote-items th {
                        background: #f9fafb;
                        padding: 12px;
                        text-align: left;
                        font-weight: 600;
                        border-bottom: 2px solid #e5e7eb;
                        color: #374151;
                    }

                    .quote-items td {
                        padding: 12px;
                        border-bottom: 1px solid #e5e7eb;
                        vertical-align: top;
                    }

                    .quote-items tr:nth-child(even) {
                        background: #f9fafb;
                    }

                    /* Summary styles */
                    .quote-summary {
                        margin-top: 30px;
                        padding: 20px;
                        background: #f9fafb;
                        border-radius: 6px;
                        text-align: right;
                    }

                    .quote-summary div {
                        margin-bottom: 8px;
                        font-size: 1em;
                    }

                    .quote-summary .total {
                        font-size: 1.2em;
                        font-weight: bold;
                        color: #1f2937;
                        border-top: 2px solid #e5e7eb;
                        padding-top: 10px;
                        margin-top: 10px;
                    }

                    /* Notes styles */
                    .quote-notes {
                        margin-top: 30px;
                        padding: 15px;
                        background: #f9fafb;
                        border-left: 4px solid #3b82f6;
                        border-radius: 4px;
                    }

                    .quote-notes h4 {
                        margin-bottom: 10px;
                        color: #1f2937;
                    }

                    /* Status styles */
                    .quote-status {
                        display: inline-block;
                        padding: 4px 12px;
                        border-radius: 20px;
                        font-size: 0.8em;
                        font-weight: 600;
                        text-transform: uppercase;
                        margin-left: 10px;
                    }

                    .status-draft { background: #e5e7eb; color: #374151; }
                    .status-sent { background: #dbeafe; color: #1e40af; }
                    .status-accepted { background: #d1fae5; color: #065f46; }
                    .status-declined { background: #fee2e2; color: #991b1b; }
                    .status-available { background: #eff6ff; color: #1e40af; }

                    /* Print-specific styles */
                    @media print {
                        body {
                            margin: 0;
                            padding: 0;
                        }

                        .quote-container {
                            border: none;
                            padding: 0;
                            max-width: none;
                        }

                        .quote-items th {
                            background: #f9fafb !important;
                            -webkit-print-color-adjust: exact;
                            color-adjust: exact;
                        }

                        .quote-notes {
                            background: #f9fafb !important;
                            -webkit-print-color-adjust: exact;
                            color-adjust: exact;
                        }

                        .status-draft { background: #e5e7eb !important; }
                        .status-sent { background: #dbeafe !important; }
                        .status-accepted { background: #d1fae5 !important; }
                        .status-declined { background: #fee2e2 !important; }
                        .status-available { background: #eff6ff !important; }

                        /* Ensure proper page breaks */
                        .quote-content {
                            page-break-inside: avoid;
                        }

                        table {
                            page-break-inside: avoid;
                        }

                        tr {
                            page-break-inside: avoid;
                        }
                    }
                </style>
            </head>
            <body>
                ${quoteContent.outerHTML}
            </body>
            </html>
        `;

        // Write the content to the new window
        printWindow.document.write(printHTML);
        printWindow.document.close();

        // Wait for content to load, then print
        printWindow.onload = function() {
            setTimeout(function() {
                printWindow.print();
                printWindow.close();
            }, 500);
        };
    }

    document.addEventListener('DOMContentLoaded', function() {
        const quoteId = '<?php echo esc_js($quote->getId()); ?>';
        const acceptActionDescription = '<?php echo esc_js($accept_action_description); ?>';
        const declinedMessage = '<?php echo esc_js($declined_message); ?>';
        const isDeclineReasonRequired = <?php echo json_encode($settings_controller::isDeclineReasonRequired()); ?>;

        // Utility: Show loading spinner in a button
        function setButtonLoading(btn, loadingText) {
            btn.disabled = true;
            btn.innerHTML = `<span class='ei-btn-spinner' style='display:inline-block;vertical-align:middle;width:18px;height:18px;margin-right:8px;'>
                <svg width='18' height='18' viewBox='0 0 50 50'><circle cx='25' cy='25' r='20' fill='none' stroke='#fff' stroke-width='5' stroke-linecap='round' stroke-dasharray='31.415, 31.415' transform='rotate(0 25 25)'><animateTransform attributeName='transform' type='rotate' from='0 25 25' to='360 25 25' dur='0.8s' repeatCount='indefinite'/></circle></svg>
            </span>${loadingText}`;
        }
        // resetButtonLoading function is now defined globally above

        // Accept Quote Button
        const acceptButton = document.querySelector('.quote-actions .accept');
        if (acceptButton) {
            acceptButton.addEventListener('click', function() {
                let message = '<?php echo esc_js(__('Accept this quote?', 'easy-invoice')); ?>';
                if (acceptActionDescription) {
                    message += '\n\n' + acceptActionDescription;
                }
                showConfirmationModal(
                    '<?php echo esc_js($text_settings['accept_quote']); ?>',
                    message,
                    '<?php echo esc_js($text_settings['accept_quote']); ?>',
                    '<?php echo esc_js(__('Cancel', 'easy-invoice')); ?>',
                    'primary',
                    function(modal, confirmBtn, originalText) {
                        handleAcceptQuote(quoteId, confirmBtn, originalText);
                    }
                );
            });
        }

        // Decline Quote Button
        const declineButton = document.querySelector('.quote-actions .decline');
        if (declineButton) {
            declineButton.addEventListener('click', function() {
                let message = '<?php echo esc_js(__('Decline this quote?', 'easy-invoice')); ?>';
                if (declinedMessage) {
                    message += '\n\n' + declinedMessage;
                }

                if (isDeclineReasonRequired) {
                    showDeclineModalWithReason();
                } else {
                    showConfirmationModal(
                        '<?php echo esc_js($text_settings['decline_quote']); ?>',
                        message,
                        '<?php echo esc_js($text_settings['decline_quote']); ?>',
                        '<?php echo esc_js(__('Cancel', 'easy-invoice')); ?>',
                        'danger',
                        function(modal, confirmBtn, originalText) {
                            handleDeclineQuote(quoteId, confirmBtn, originalText);
                        }
                    );
                }
            });
        }



        // Note: Download and Send Email buttons are handled via inline onclick attributes to avoid duplicate bindings

        // Custom Modal System
        function showConfirmationModal(title, message, confirmText, cancelText, confirmType, onConfirm) {
            // Remove existing modal if any
            const existingModal = document.querySelector('.ei-modal-overlay');
            if (existingModal) {
                existingModal.remove();
            }

            // Create modal overlay
            const overlay = document.createElement('div');
            overlay.className = 'ei-modal-overlay';

            // Create modal content
            const modal = document.createElement('div');
            modal.className = 'ei-modal';

            const confirmBtnClass = confirmType === 'danger' ? 'ei-modal-btn-danger' : 'ei-modal-btn-primary';
            const iconClass = confirmType === 'danger' ? 'danger' : 'info';
            const icon = confirmType === 'danger' ?
                '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="none"/><path d="M12 7v4.5M12 16h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>' :
                '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="none"/><path d="M12 16v-4M12 8h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';

            modal.innerHTML = `
                <div class="ei-modal-header">
                    <div class="ei-modal-icon ${iconClass}">
                        ${icon}
                    </div>
                    <h3 class="ei-modal-title">${title}</h3>
                </div>
                <div class="ei-modal-body">
                    <div class="ei-modal-message">${message}</div>
                </div>
                <div class="ei-modal-actions">
                    <button type="button" class="ei-modal-btn ei-modal-btn-secondary" id="modal-cancel">${cancelText}</button>
                    <button type="button" class="ei-modal-btn ${confirmBtnClass}" id="modal-confirm">${confirmText}</button>
                </div>
            `;

            overlay.appendChild(modal);
            document.body.appendChild(overlay);

            // Show modal with animation
            setTimeout(() => {
                overlay.classList.add('show');
                modal.classList.add('show');
            }, 10);

            // Handle button clicks
            const confirmBtn = modal.querySelector('#modal-confirm');
            const cancelBtn = modal.querySelector('#modal-cancel');

            confirmBtn.addEventListener('click', function() {
                const originalText = confirmBtn.innerHTML;
                setButtonLoading(confirmBtn, confirmBtn.textContent.trim());
                onConfirm(modal, confirmBtn, originalText);
            });

            cancelBtn.addEventListener('click', function() {
                hideModal(overlay);
            });

            // Handle overlay click to close
            overlay.addEventListener('click', function(e) {
                if (e.target === overlay) {
                    hideModal(overlay);
                }
            });

            // Handle escape key
            const handleEscape = function(e) {
                if (e.key === 'Escape') {
                    hideModal(overlay);
                    document.removeEventListener('keydown', handleEscape);
                }
            };
            document.addEventListener('keydown', handleEscape);

            // Focus on confirm button
            setTimeout(() => {
                confirmBtn.focus();
            }, 100);
        }

        // Decline Modal with Reason Field
        function showDeclineModalWithReason() {
            // Remove existing modal if any
            const existingModal = document.querySelector('.ei-modal-overlay');
            if (existingModal) {
                existingModal.remove();
            }
            // Create modal overlay
            const overlay = document.createElement('div');
            overlay.className = 'ei-modal-overlay';
            // Create modal content
            const modal = document.createElement('div');
            modal.className = 'ei-modal';
            let message = '<?php echo esc_js(__('Decline this quote?', 'easy-invoice')); ?>';
            if (declinedMessage) {
                message += '\n\n' + declinedMessage;
            }
            modal.innerHTML = `
                <div class="ei-modal-header">
                    <div class="ei-modal-icon danger">
                        <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="none"/><path d="M12 7v4.5M12 16h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
                    </div>
                    <h3 class="ei-modal-title"><?php echo esc_js($text_settings['decline_quote']); ?></h3>
                </div>
                <div class="ei-modal-body">
                    <div class="ei-modal-message">${message}</div>
                    <div class="ei-modal-reason-field">
                        <label for="decline-reason" class="ei-modal-label"><?php echo esc_js($text_settings['decline_reason']); ?>:</label>
                        <textarea id="decline-reason" class="ei-modal-textarea" rows="4" placeholder="<?php echo esc_js(__('Please provide a reason for declining this quote...', 'easy-invoice')); ?>" required></textarea>
                    </div>
                </div>
                <div class="ei-modal-actions">
                    <button type="button" class="ei-modal-btn ei-modal-btn-secondary" id="modal-cancel"><?php echo esc_js(__('Cancel', 'easy-invoice')); ?></button>
                    <button type="button" class="ei-modal-btn ei-modal-btn-danger" id="modal-confirm"><?php echo esc_js($text_settings['decline_quote']); ?></button>
                </div>
            `;
            overlay.appendChild(modal);
            document.body.appendChild(overlay);
            setTimeout(() => {
                overlay.classList.add('show');
                modal.classList.add('show');
            }, 10);
            // Handle button clicks
            const confirmBtn = modal.querySelector('#modal-confirm');
            const cancelBtn = modal.querySelector('#modal-cancel');
            const reasonField = modal.querySelector('#decline-reason');
            confirmBtn.addEventListener('click', function() {
                const reason = reasonField.value.trim();
                if (!reason) {
                    reasonField.focus();
                    reasonField.classList.add('error');
                    return;
                }
                const originalText = confirmBtn.innerHTML;
                setButtonLoading(confirmBtn, confirmBtn.textContent.trim());
                handleDeclineQuote(quoteId, confirmBtn, reason, originalText);
            });
            cancelBtn.addEventListener('click', function() {
                hideModal(overlay);
            });
            overlay.addEventListener('click', function(e) {
                if (e.target === overlay) {
                    hideModal(overlay);
                }
            });
            const handleEscape = function(e) {
                if (e.key === 'Escape') {
                    hideModal(overlay);
                    document.removeEventListener('keydown', handleEscape);
                }
            };
            document.addEventListener('keydown', handleEscape);
            setTimeout(() => {
                reasonField.focus();
            }, 100);
            reasonField.addEventListener('input', function() {
                this.classList.remove('error');
            });
        }

        function hideModal(overlay) {
            const modal = overlay.querySelector('.ei-modal');
            modal.classList.remove('show');
            overlay.classList.remove('show');

            setTimeout(() => {
                if (overlay.parentNode) {
                    overlay.remove();
                }
            }, 300);
        }

        // Show message in modal (used for AJAX responses)
        function showModalMessage(type, message, onClose) {
            // Remove existing modal if any
            const existingModal = document.querySelector('.ei-modal-overlay');
            if (existingModal) {
                existingModal.remove();
            }
            // Create modal overlay
            const overlay = document.createElement('div');
            overlay.className = 'ei-modal-overlay';
            // Create modal content
            const modal = document.createElement('div');
            modal.className = 'ei-modal';
            const iconClass = type === 'success' ? 'info' : 'danger';
            const icon = type === 'success'
                ? '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#10b981"/><path d="M7 13l3 3 7-7" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
                : '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#ef4444"/><path d="M12 7v4.5M12 16h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
            modal.innerHTML = `
                <div class="ei-modal-header">
                    <div class="ei-modal-icon ${iconClass}">${icon}</div>
                    <h3 class="ei-modal-title">${type === 'success' ? '<?php echo esc_js(__('Success', 'easy-invoice')); ?>' : '<?php echo esc_js(__('Error', 'easy-invoice')); ?>'}</h3>
                </div>
                <div class="ei-modal-body">
                    <div class="ei-modal-message">${message}</div>
                </div>
                <div class="ei-modal-actions">
                    <button type="button" class="ei-modal-btn ei-modal-btn-primary" id="modal-close"><?php echo esc_js(__('Close', 'easy-invoice')); ?></button>
                </div>
            `;
            overlay.appendChild(modal);
            document.body.appendChild(overlay);
            setTimeout(() => {
                overlay.classList.add('show');
                modal.classList.add('show');
            }, 10);
            const closeBtn = modal.querySelector('#modal-close');
            closeBtn.addEventListener('click', function() {
                hideModal(overlay);
                if (onClose) onClose();
            });
            overlay.addEventListener('click', function(e) {
                if (e.target === overlay) {
                    hideModal(overlay);
                    if (onClose) onClose();
                }
            });
            const handleEscape = function(e) {
                if (e.key === 'Escape') {
                    hideModal(overlay);
                    document.removeEventListener('keydown', handleEscape);
                    if (onClose) onClose();
                }
            };
            document.addEventListener('keydown', handleEscape);
            setTimeout(() => {
                closeBtn.focus();
            }, 100);
        }
        // Show loading state in modal
        function showModalLoading(message) {
            // Remove existing modal if any
            const existingModal = document.querySelector('.ei-modal-overlay');
            if (existingModal) {
                existingModal.remove();
            }
            // Create modal overlay
            const overlay = document.createElement('div');
            overlay.className = 'ei-modal-overlay';
            // Create modal content
            const modal = document.createElement('div');
            modal.className = 'ei-modal';
            modal.innerHTML = `
                <div class="ei-modal-header">
                    <div class="ei-modal-icon info">
                        <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#3b82f6"/><circle cx="12" cy="12" r="6" fill="#fff"/><animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/></svg>
                    </div>
                    <h3 class="ei-modal-title"><?php echo esc_js(__('Please wait...', 'easy-invoice')); ?></h3>
                </div>
                <div class="ei-modal-body">
                    <div class="ei-modal-message">${message}</div>
                </div>
            `;
            overlay.appendChild(modal);
            document.body.appendChild(overlay);
            setTimeout(() => {
                overlay.classList.add('show');
                modal.classList.add('show');
            }, 10);
        }

        // Handle Accept Quote
        function handleAcceptQuote(quoteId, confirmBtn, originalText) {
            showModalLoading('<?php echo esc_js(__('Accepting quote...', 'easy-invoice')); ?>');
            jQuery.ajax({
                url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
                type: 'POST',
                data: {
                    action: 'easy_invoice_accept_quote',
                    quote_id: quoteId,
                    nonce: '<?php echo esc_js(wp_create_nonce('easy_invoice_quote_action_' . (int) $quote->getId())); ?>'
                },
                success: function(response) {
                    if (response.success) {
                        // Check if an invoice was created and redirect to it
                        if (response.data && response.data.invoice_id) {
                            // Use the PHP-generated URL (secure URL first, then regular URL)
                            let invoiceUrl = response.data.secure_url || response.data.invoice_url;

                            if (invoiceUrl) {
                                showModalMessage('success', response.data.message || '<?php _e('Quote accepted successfully! Redirecting to invoice...', 'easy-invoice'); ?>', function() {
                                    window.location.href = invoiceUrl;
                                });
                            } else {
                                // Fallback to reload if no URL available
                                showModalMessage('success', response.data.message || '<?php _e('Quote accepted successfully', 'easy-invoice'); ?>', function() { location.reload(); });
                            }
                        } else {
                            // No invoice created, just show success message
                            showModalMessage('success', response.data && response.data.message ? response.data.message : '<?php _e('Quote accepted successfully', 'easy-invoice'); ?>', function() { location.reload(); });
                        }
                    } else {
                        resetButtonLoading(confirmBtn, originalText);
                        showModalMessage('error', response.data || '<?php _e('Error accepting quote', 'easy-invoice'); ?>');
                    }
                },
                error: function() {
                    resetButtonLoading(confirmBtn, originalText);
                    showModalMessage('error', '<?php _e('Error connecting to server', 'easy-invoice'); ?>');
                }
            });
        }

        // Handle Decline Quote
        function handleDeclineQuote(quoteId, confirmBtn, reason = '', originalText) {
            showModalLoading('<?php echo esc_js(__('Declining quote...', 'easy-invoice')); ?>');
            const ajaxData = {
                action: 'easy_invoice_decline_quote',
                quote_id: quoteId,
                nonce: '<?php echo esc_js(wp_create_nonce('easy_invoice_quote_action_' . (int) $quote->getId())); ?>'
            };
            if (reason) {
                ajaxData.decline_reason = reason;
            }
            jQuery.ajax({
                url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
                type: 'POST',
                data: ajaxData,
                success: function(response) {
                    if (response.success) {
                        showModalMessage('success', response.data && response.data.message ? response.data.message : '<?php _e('Quote declined successfully', 'easy-invoice'); ?>', function() { location.reload(); });
                    } else {
                        resetButtonLoading(confirmBtn, originalText);
                        showModalMessage('error', response.data || '<?php _e('Error declining quote', 'easy-invoice'); ?>');
                    }
                },
                error: function() {
                    resetButtonLoading(confirmBtn, originalText);
                    showModalMessage('error', '<?php _e('Error connecting to server', 'easy-invoice'); ?>');
                }
            });
        }

        // Functions moved to global scope above
    });
    </script>

    <script>
    document.addEventListener('DOMContentLoaded', function() {
        // Auto-download PDF if ?auto_download_pdf=1 is present
        if (window.location.search.indexOf('auto_download_pdf=1') !== -1) {
            setTimeout(function() {
                if (typeof DocumentPdfGenerator !== 'undefined') {
                    const pdfGenerator = new DocumentPdfGenerator('quote');
                    pdfGenerator.generatePDF();
                }
            }, 800);
        }
    });
    </script>

    <?php
    // Load additional CSS for all users (not just admin)
    $additional_css = get_post_meta($quote->getId(), '_easy_invoice_additional_css', true) ?: '';
    if (!empty($additional_css)):
    ?>
    <style id="custom-quote-css">
        <?php echo esc_html($additional_css); ?>
    </style>
    <?php endif; ?>

    <?php
    // Add Additional CSS feature for admin users
    if (is_user_logged_in() && current_user_can('manage_options')):
    ?>
    <!-- CSS Panel -->
    <div id="css-panel" style="display: none; position: fixed; top: 0; left: 0; width: 400px; height: 100vh; background: white; box-shadow: 2px 0 10px rgba(0,0,0,0.1); z-index: 1001; overflow-y: auto;">
        <div style="padding: 20px; border-bottom: 1px solid #e5e7eb; display: flex; justify-content: space-between; align-items: center;">
            <h3 style="margin: 0; font-size: 18px; font-weight: 600;">Additional CSS</h3>
            <button type="button" id="close-css-panel" style="background: none; border: none; font-size: 24px; cursor: pointer; color: #6b7280;">&times;</button>
        </div>
        <div style="padding: 20px;">
            <div style="margin-bottom: 15px;">
                <label style="display: block; margin-bottom: 8px; font-weight: 500; color: #374151;">Custom CSS for this quote:</label>
                <textarea id="additional-css-textarea" style="width: calc(100% - 24px); height: 300px; padding: 12px; border: 1px solid #d1d5db; border-radius: 6px; font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 13px; resize: vertical; box-sizing: border-box;" placeholder="Enter your custom CSS here..."><?php echo esc_textarea($additional_css); ?></textarea>
            </div>
            <div style="display: flex; gap: 10px;">
                <button type="button" id="save-css-btn" style="background: #10b981; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">Save CSS</button>
                <button type="button" id="preview-css-btn" style="background: #6366f1; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">Preview</button>
                <button type="button" id="clear-css-btn" style="background: #ef4444; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">Clear</button>
            </div>
            <div id="css-status" style="margin-top: 15px; padding: 10px; border-radius: 4px; display: none;"></div>
        </div>
    </div>

    <!-- Overlay -->
    <div id="css-overlay" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000;"></div>

    <script>
    // Additional CSS functionality
    document.addEventListener('DOMContentLoaded', function() {
        const cssBtn = document.getElementById('additional-css-btn');
        const cssPanel = document.getElementById('css-panel');
        const closeBtn = document.getElementById('close-css-panel');
        const overlay = document.getElementById('css-overlay');
        const saveBtn = document.getElementById('save-css-btn');
        const previewBtn = document.getElementById('preview-css-btn');
        const clearBtn = document.getElementById('clear-css-btn');
        const textarea = document.getElementById('additional-css-textarea');
        const status = document.getElementById('css-status');

        if (!cssBtn) return; // Exit if CSS button doesn't exist

        let originalCSS = textarea.value;

        // Toggle panel
        cssBtn.addEventListener('click', function() {
            cssPanel.style.display = 'block';
            overlay.style.display = 'block';
        });

        // Close panel
        function closePanel() {
            cssPanel.style.display = 'none';
            overlay.style.display = 'none';
        }

        closeBtn.addEventListener('click', closePanel);
        overlay.addEventListener('click', closePanel);

        // Save CSS
        saveBtn.addEventListener('click', function() {
            const css = textarea.value;

            // AJAX request to save CSS
            fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    'action': 'save_additional_css',
                    'post_id': <?php echo $quote->getId(); ?>,
                    'css': css,
                    'nonce': '<?php echo wp_create_nonce('save_additional_css_nonce'); ?>'
                })
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    originalCSS = css;
                    status.textContent = 'CSS saved successfully!';
                    status.style.background = '#d1fae5';
                    status.style.color = '#065f46';
                    status.style.display = 'block';

                    // Apply the saved CSS
                    applyCustomCSS(css);

                    setTimeout(() => {
                        status.style.display = 'none';
                    }, 3000);
                } else {
                    status.textContent = 'Error saving CSS: ' + data.message;
                    status.style.background = '#fee2e2';
                    status.style.color = '#991b1b';
                    status.style.display = 'block';
                }
            })
            .catch(error => {
                status.textContent = 'Error saving CSS: ' + error.message;
                status.style.background = '#fee2e2';
                status.style.color = '#991b1b';
                status.style.display = 'block';
            });
        });

        // Preview CSS
        previewBtn.addEventListener('click', function() {
            const css = textarea.value;
            applyCustomCSS(css);

            status.textContent = 'CSS preview applied';
            status.style.background = '#dbeafe';
            status.style.color = '#1e40af';
            status.style.display = 'block';

            setTimeout(() => {
                status.style.display = 'none';
            }, 2000);
        });

        // Clear CSS
        clearBtn.addEventListener('click', function() {
            if (confirm('Are you sure you want to clear all custom CSS?')) {
                textarea.value = '';
                applyCustomCSS('');

                status.textContent = 'CSS cleared';
                status.style.background = '#fee2e2';
                status.style.color = '#991b1b';
                status.style.display = 'block';

                setTimeout(() => {
                    status.style.display = 'none';
                }, 2000);
            }
        });

        // Apply custom CSS function
        function applyCustomCSS(css) {
            // Remove existing custom CSS
            const existingStyle = document.getElementById('custom-quote-css');
            if (existingStyle) {
                existingStyle.remove();
            }

            // Add new custom CSS if not empty
            if (css.trim()) {
                const style = document.createElement('style');
                style.id = 'custom-quote-css';
                style.textContent = css;
                document.head.appendChild(style);
            }
        }

        // Apply saved CSS on page load
        applyCustomCSS(originalCSS);
    });
    </script>
    <?php endif; ?>
</body>
</html>

```
