<?php
/**
 * VMO GrapesJS Server-Side Composer
 *
 * Mirrors the client-side vmo-grapes-adapter.js composition engine.
 * Used by the 12-chunk pipeline and other server-side generation paths
 * to produce premium React/Tailwind/GSAP website output.
 *
 * @since 9.1.0
 */
if (!defined('ABSPATH')) exit;

class VMO_Grapes_Composer {

    /* ────────────────── CDN CONFIGURATION ────────────────── */

    const CDN = [
        'font'        => 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap',
        'tailwind'    => 'https://cdn.tailwindcss.com',
        'react'       => 'https://unpkg.com/react@18/umd/react.production.min.js',
        'react_dom'   => 'https://unpkg.com/react-dom@18/umd/react-dom.production.min.js',
        'gsap'        => 'https://unpkg.com/gsap@3.12.5/dist/gsap.min.js',
        'scrolltrigger' => 'https://unpkg.com/gsap@3.12.5/dist/ScrollTrigger.min.js',
        'lenis'       => 'https://cdn.jsdelivr.net/npm/lenis@1.1.13/dist/lenis.min.js',
        'swiper_css'  => 'https://unpkg.com/swiper@11/swiper-bundle.min.css',
        'swiper_js'   => 'https://unpkg.com/swiper@11/swiper-bundle.min.js',
        'lottie'      => 'https://unpkg.com/lottie-web@5.12.2/build/player/lottie.min.js',
        'aos_css'     => 'https://unpkg.com/aos@2.3.4/dist/aos.css',
        'aos_js'      => 'https://unpkg.com/aos@2.3.4/dist/aos.js',
    ];

    /* ────────────────── PUBLIC API ────────────────── */

    /**
     * Wrap existing HTML in the premium React/Tailwind/GSAP shell.
     * Used by the 12-chunk pipeline to upgrade raw AI-generated HTML.
     *
     * @param string $html  Raw page HTML from AI generation.
     * @param array  $meta  Optional metadata: primary_color, accent_color, tech_stack, business_name.
     * @return string Full HTML with CDN references, base styles, and initialization scripts.
     */
    public static function wrap_in_premium_shell($html, $meta = []) {
        $html = self::sanitize_output_html($html);
        $primary = esc_attr($meta['primary_color'] ?? '#0f172a');
        $accent  = esc_attr($meta['accent_color']  ?? '#0ea5e9');
        $biz     = esc_attr($meta['business_name']  ?? '');
        $tech    = is_array($meta['tech_stack'] ?? null) ? $meta['tech_stack'] : ['React 18', 'Tailwind CSS', 'GSAP'];

        $cdn_head     = self::build_cdn_head($tech, $primary, $accent);
        $base_css     = self::build_base_css($primary, $accent);
        $init_scripts = self::build_init_scripts();

        return $cdn_head
            . "\n<style data-vmo-premium=\"base\">" . $base_css . "</style>\n"
            . '<div id="vmo-gjs-page" class="vmo-gjs-page font-[Inter,system-ui,sans-serif]" '
            . 'data-vmo-generated="grapesjs-shell" data-business="' . $biz . '">' . "\n"
            . $html . "\n"
            . "</div>\n"
            . $init_scripts;
    }

    /**
     * Compose a full page from a strategy JSON plan (mirrors JS adapter composeWebsite).
     *
     * @param array $plan    Strategy plan with site, brand, tech_stack, integrations, sections.
     * @param array $context Optional: phone_number, email_address.
     * @return string Full premium HTML.
     */
    public static function compose_from_strategy($plan, $context = []) {
        if (!is_array($plan)) $plan = [];

        $site         = is_array($plan['site'] ?? null) ? $plan['site'] : [];
        $brand        = is_array($plan['brand'] ?? null) ? $plan['brand'] : [];
        $integrations = is_array($plan['integrations'] ?? null) ? $plan['integrations'] : [];
        $sections     = is_array($plan['sections'] ?? null) ? $plan['sections'] : [];
        $tech         = is_array(($plan['tech_stack'] ?? [])['selected'] ?? null) ? $plan['tech_stack']['selected'] : ['React 18', 'Tailwind CSS', 'GSAP'];

        // ✅ v9.2.0: Auto-select design mode from business type/industry
        $design_mode = $plan['design_mode'] ?? '';
        if (empty($design_mode) && class_exists('VMO_Elite_Consultation_Prompts')) {
            $biz_type = $site['business_type'] ?? $site['industry'] ?? '';
            $industry = $site['industry'] ?? '';
            $design_mode = VMO_Elite_Consultation_Prompts::get_instance()
                ->get_design_mode_for_business($biz_type, $industry);
        }
        if ($design_mode) {
            self::set_design_mode($design_mode);
        }

        // Merge contact info from context
        if (!empty($context['phone_number']) && empty($integrations['phone_number'])) {
            $integrations['phone_number'] = $context['phone_number'];
            $integrations['phone_enabled'] = true;
        }
        if (!empty($context['email_address']) && empty($integrations['email_address'])) {
            $integrations['email_address'] = $context['email_address'];
            $integrations['email_enabled'] = true;
        }

        $biz     = esc_html($site['business_name'] ?? 'Business Website');
        $tagline = esc_html($site['tagline'] ?? '');
        $goal    = esc_html($site['goal'] ?? '');
        // ✅ v9.2.0: Use mode palette as defaults (brand overrides if provided)
        $pal     = self::palette();
        $primary = $brand['primary_color'] ?? $pal['text'];
        $accent  = $brand['accent_color']  ?? $pal['accent'];

        $total = count($sections);
        $sections_html = '';
        foreach ($sections as $i => $section) {
            $sections_html .= self::render_section($section, $i, $total, $integrations);
        }

        $header = self::render_header($biz, $tagline, $tech);
        $footer = self::render_footer($biz, $goal);

        return self::wrap_in_premium_shell(
            $header . $sections_html . $footer,
            ['primary_color' => $primary, 'accent_color' => $accent, 'tech_stack' => $tech, 'business_name' => $biz]
        );
    }

    private static function sanitize_output_html($html) {
        $html = (string) $html;
        if ($html === '') {
            return '';
        }

        $html = preg_replace('/<!--.*?-->/s', '', $html);
        $html = preg_replace('/AI\s+Image\s+Generating\.\.\./i', '', $html);
        $html = preg_replace('/AI\s+Video\s+Generating\.\.\./i', '', $html);
        $html = preg_replace('/A professional (image|video) will appear here/i', '', $html);

        return is_string($html) ? $html : '';
    }

    /* ────────────────── HEADER / FOOTER ────────────────── */

    private static function render_header($biz, $tagline, $tech) {
        $pal = self::palette();
        $chips = '';
        foreach (array_slice($tech, 0, 5) as $t) {
            $te = esc_html($t);
            $chips .= '<span class="px-3 py-1 text-[11px] font-semibold rounded-full" style="background:' . esc_attr($pal['accent']) . '12;color:' . esc_attr($pal['accent']) . ';border:1px solid ' . esc_attr($pal['accent']) . '22;">' . $te . '</span>';
        }
        return '<header class="sticky top-0 z-50 backdrop-blur-xl border-b" style="background:' . esc_attr($pal['bg']) . 'cc;border-color:' . esc_attr($pal['muted']) . '22;">'
            . '<div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">'
            . '<div><h1 class="text-xl font-bold tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $biz . '</h1>'
            . ($tagline ? '<p class="text-sm mt-0.5" style="color:' . esc_attr($pal['muted']) . ';">' . $tagline . '</p>' : '')
            . '</div>'
            . '<nav class="hidden md:flex items-center gap-6 text-sm font-medium" style="color:' . esc_attr($pal['muted']) . ';">'
            . '<a href="#section-1" class="hover:opacity-80 transition">Home</a>'
            . '<a href="#section-footer" class="hover:opacity-80 transition">Contact</a>'
            . '</nav>'
            . '<div class="hidden lg:flex flex-wrap gap-1.5">' . $chips . '</div>'
            . '</div></header>' . "\n";
    }

    private static function render_footer($biz, $goal) {
        $year = date('Y');
        $pal = self::palette();
        return '<footer id="section-footer" class="py-16" style="background:' . esc_attr($pal['text']) . ';color:' . esc_attr($pal['muted']) . ';">'
            . '<div class="max-w-7xl mx-auto px-6 flex flex-col md:flex-row justify-between gap-8">'
            . '<div><p class="font-semibold text-lg" style="color:' . esc_attr($pal['bg']) . ';">' . $biz . '</p>'
            . '<p class="mt-2 text-sm max-w-md">' . ($goal ?: 'Built to convert and scale.') . '</p></div>'
            . '<div class="text-sm"><p>&copy; ' . $year . ' ' . $biz . '. All rights reserved.</p>'
            . '<p class="mt-1">Powered by VMO AI</p></div>'
            . '</div></footer>' . "\n";
    }

    /* ────────────────── DESIGN MODE STATE ────────────────── */

    /** @var string Active design mode slug (set by compose_from_strategy or set_design_mode) */
    private static $design_mode = 'premium_service_authority';

    /** @var array|null Cached palette from the active design mode */
    private static $mode_palette = null;

    /** @var array|null Cached typography from the active design mode */
    private static $mode_typography = null;

    /**
     * Set the active design mode. Call BEFORE compose_from_strategy().
     *
     * @param string $mode Design mode slug from VMO_Elite_Consultation_Prompts::get_design_modes().
     */
    public static function set_design_mode($mode) {
        self::$design_mode = $mode;
        self::$mode_palette = null;
        self::$mode_typography = null;

        if (class_exists('VMO_Elite_Consultation_Prompts')) {
            $prompts = VMO_Elite_Consultation_Prompts::get_instance();
            self::$mode_palette = $prompts->get_palette($mode);
            self::$mode_typography = $prompts->get_typography($mode);
        }
    }

    /**
     * Get the resolved palette (falls back to defaults).
     */
    private static function palette() {
        if (self::$mode_palette) return self::$mode_palette;
        return ['bg' => '#ffffff', 'surface' => '#f7f8fa', 'accent' => '#1a56db', 'text' => '#111827', 'muted' => '#6b7280'];
    }

    /**
     * Get a CSS variable block for accent/primary injection.
     */
    private static function css_vars($primary = null, $accent = null) {
        $p = $primary ?? self::palette()['text'];
        $a = $accent ?? self::palette()['accent'];
        return $p . '|' . $a; // used internally only
    }

    /**
     * Pick a variant index for a section type based on the design mode.
     * Deterministic: same mode + section type + index => same variant.
     *
     * @param string $section_type e.g. 'hero', 'services'
     * @param int    $index Section index on the page
     * @return int Variant number (0-based)
     */
    private static function pick_variant($section_type, $index) {
        $mode_hash = crc32(self::$design_mode . $section_type);
        $variant_counts = [
            'hero' => 4, 'services' => 3, 'about' => 3, 'testimonials' => 3,
            'products' => 3, 'pricing' => 2, 'contact' => 2, 'gallery' => 2,
            'team' => 2, 'faq' => 2, 'cta' => 3,
        ];
        $max = $variant_counts[$section_type] ?? 2;
        return abs($mode_hash + $index) % $max;
    }

    /* ────────────────── SECTION DISPATCHER ────────────────── */

    private static function render_section($section, $index, $total, $integrations) {
        if (!is_array($section)) $section = [];
        $type = sanitize_key($section['type'] ?? 'section');

        switch ($type) {
            case 'hero':         return self::section_hero($section, $index);
            case 'services':
            case 'features':     return self::section_services($section, $index);
            case 'about':        return self::section_about($section, $index);
            case 'testimonials':
            case 'reviews':      return self::section_testimonials($section, $index);
            case 'products':
            case 'shop':
            case 'ecommerce':    return self::section_products($section, $index);
            case 'pricing':      return self::section_pricing($section, $index);
            case 'contact':      return self::section_contact($section, $index, $integrations);
            case 'gallery':
            case 'portfolio':    return self::section_gallery($section, $index);
            case 'team':         return self::section_team($section, $index);
            case 'faq':          return self::section_faq($section, $index);
            case 'cta':          return self::section_cta($section, $index);
            default:             return self::section_default($section, $index);
        }
    }

    /* ────────────────── MEDIA HELPER ────────────────── */

    private static function media_placeholder($type_hint, $media_type = 'image', $index = 0) {
        $id = 'gjs-media-' . $index . '-' . wp_rand(1000, 9999);
        $seed = urlencode($type_hint . '-' . $index);
        
        // ✅ Generate AI media prompt based on the type hint for post-render generation
        $ai_prompt = 'Professional, high-quality ' . $type_hint . ' image for a modern business website, photorealistic, cinematic lighting, premium feel';
        
        if ($media_type === 'video') {
            $video_prompt = 'Cinematic ' . $type_hint . ' video, smooth camera movement, professional lighting, modern business atmosphere, 4K quality';
            return '<div class="relative group">'
                . '<div class="vmo-media-placeholder w-full min-h-[280px] rounded-2xl flex items-center justify-center" '
                . 'data-media-id="' . $id . '" data-type="video" '
                . 'data-vmo-sora="true" data-vmo-sora-prompt="' . esc_attr($video_prompt) . '" '
                . 'style="background:linear-gradient(135deg,#0f172a,#1e293b);position:relative;color:transparent;font-size:0;line-height:0;"></div>'
                . self::replace_button_overlay($id) . '</div>';
        }
        
        // ✅ Use a gradient placeholder with AI generation marker instead of picsum.photos
        return '<div class="relative group">'
            . '<div class="vmo-media-placeholder w-full min-h-[280px] rounded-2xl flex items-center justify-center" '
            . 'data-media-id="' . $id . '" data-type="image" '
            . 'data-vmo-generate="true" data-vmo-prompt="' . esc_attr($ai_prompt) . '" '
            . 'style="background:linear-gradient(135deg,#1e293b,#334155);position:relative;color:transparent;font-size:0;line-height:0;"></div>'
            . self::replace_button_overlay($id) . '</div>';
    }

    private static function replace_button_overlay($media_id) {
        return '<button class="vmo-replace-btn absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/40 '
            . 'opacity-0 group-hover:opacity-100 transition-all duration-300 rounded-2xl cursor-pointer" '
            . 'data-vmo-editor-only="media-replace-overlay" '
            . 'data-replace-media="' . esc_attr($media_id) . '" title="Replace media">'
            . '<span class="px-4 py-2 bg-white/90 backdrop-blur-sm text-gray-900 text-sm font-semibold rounded-lg shadow-lg">'
            . '&#x1F504; Replace</span></button>';
    }

    /* ────────────────── SECTION RENDERERS (MULTI-VARIANT) ────────────────── */

    /**
     * Hero section — 4 premium variants selected by design mode.
     * V0: Dark cinematic overlay (SaaS, Ecommerce, Luxury)
     * V1: Split content + media (DTC, Service, Medical)
     * V2: Centered typographic hero (Education, Hospitality)
     * V3: Video-first hero (Hospitality, Immersive)
     */
    private static function section_hero($s, $i) {
        $variant = self::pick_variant('hero', $i);
        $id = 'section-' . ($i + 1) . '-hero';
        $hl = esc_html($s['headline'] ?? 'Welcome');
        $sub = esc_html($s['subheadline'] ?? '');
        $body = esc_html($s['body'] ?? '');
        $cta1 = esc_html($s['cta_primary'] ?? '');
        $cta2 = esc_html($s['cta_secondary'] ?? '');
        $media = self::media_placeholder('hero', ($s['media'] ?? 'image'), $i);
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);

        $cta_block = '<div class="mt-10 flex flex-wrap gap-4">'
            . ($cta1 ? '<a href="#" class="inline-flex items-center px-8 py-4 font-semibold rounded-xl shadow-lg hover:shadow-xl hover:-translate-y-0.5 transition-all duration-300" style="background:' . $accent . ';color:#fff;">' . $cta1 . '</a>' : '')
            . ($cta2 ? '<a href="#" class="inline-flex items-center px-8 py-4 bg-white/10 backdrop-blur-sm text-white font-semibold rounded-xl border border-white/20 hover:bg-white/20 transition-all duration-300">' . $cta2 . '</a>' : '')
            . '</div>';

        $wrap = function($inner) use ($id, $i) {
            return '<!-- SECTION ' . ($i + 1) . ' -->' . $inner . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
        };

        switch ($variant) {
            case 1: // Split content + media
                return $wrap(
                    '<section id="' . $id . '" class="relative min-h-[85vh] flex items-center overflow-hidden" style="background:' . esc_attr($pal['bg']) . ';" data-vmo-section-type="hero" data-vmo-animate>'
                    . '<div class="max-w-7xl mx-auto px-6 py-24 lg:py-32 grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center">'
                    . '<div>'
                    . '<h2 class="text-4xl sm:text-5xl md:text-6xl font-extrabold leading-[1.08] tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
                    . ($sub ? '<p class="mt-5 text-xl md:text-2xl font-medium" style="color:' . esc_attr($pal['muted']) . ';">' . $sub . '</p>' : '')
                    . ($body ? '<p class="mt-4 text-lg leading-relaxed" style="color:' . esc_attr($pal['muted']) . ';">' . $body . '</p>' : '')
                    . $cta_block
                    . '</div>'
                    . '<div class="relative">' . $media . '</div>'
                    . '</div></section>'
                );

            case 2: // Centered typographic hero
                return $wrap(
                    '<section id="' . $id . '" class="relative min-h-[85vh] flex items-center justify-center overflow-hidden" style="background:' . esc_attr($pal['surface']) . ';" data-vmo-section-type="hero" data-vmo-animate>'
                    . '<div class="relative z-10 max-w-4xl mx-auto px-6 py-28 lg:py-36 text-center">'
                    . '<h2 class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-extrabold leading-[1.08] tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
                    . ($sub ? '<p class="mt-6 text-xl md:text-2xl font-medium max-w-2xl mx-auto" style="color:' . esc_attr($pal['muted']) . ';">' . $sub . '</p>' : '')
                    . ($body ? '<p class="mt-4 text-lg max-w-xl mx-auto leading-relaxed" style="color:' . esc_attr($pal['muted']) . ';">' . $body . '</p>' : '')
                    . '<div class="mt-10 flex flex-wrap gap-4 justify-center">'
                    . ($cta1 ? '<a href="#" class="inline-flex items-center px-10 py-5 font-bold text-lg rounded-2xl shadow-xl hover:shadow-2xl hover:-translate-y-1 transition-all duration-300" style="background:' . $accent . ';color:#fff;">' . $cta1 . '</a>' : '')
                    . ($cta2 ? '<a href="#" class="inline-flex items-center px-10 py-5 font-semibold text-lg rounded-2xl border transition-all duration-300" style="border-color:' . esc_attr($pal['muted']) . ';color:' . esc_attr($pal['text']) . ';">' . $cta2 . '</a>' : '')
                    . '</div>'
                    . '</div></section>'
                );

            case 3: // Video-first hero
                return $wrap(
                    '<section id="' . $id . '" class="relative min-h-[90vh] flex items-center overflow-hidden bg-gray-950" data-vmo-section-type="hero" data-vmo-animate>'
                    . '<div class="absolute inset-0 z-0">' . self::media_placeholder('hero-video', 'video', $i)
                    . '<div class="absolute inset-0 bg-gradient-to-t from-gray-950 via-gray-950/60 to-gray-950/30"></div></div>'
                    . '<div class="relative z-10 max-w-7xl mx-auto px-6 py-28 lg:py-44">'
                    . '<h2 class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-extrabold text-white leading-[1.08] tracking-tight max-w-4xl">' . $hl . '</h2>'
                    . ($sub ? '<p class="mt-5 text-xl md:text-2xl text-white/80 font-medium max-w-2xl">' . $sub . '</p>' : '')
                    . $cta_block
                    . '</div></section>'
                );

            default: // V0: Dark cinematic overlay (original enhanced)
                return $wrap(
                    '<section id="' . $id . '" class="relative min-h-[85vh] flex items-center overflow-hidden bg-gray-950" data-vmo-section-type="hero" data-vmo-animate>'
                    . '<div class="absolute inset-0 z-0">' . $media
                    . '<div class="absolute inset-0 bg-gradient-to-r from-gray-950/80 via-gray-950/50 to-transparent"></div></div>'
                    . '<div class="relative z-10 max-w-7xl mx-auto px-6 py-28 lg:py-36">'
                    . '<h2 class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-extrabold text-white leading-[1.08] tracking-tight max-w-4xl">' . $hl . '</h2>'
                    . ($sub ? '<p class="mt-5 text-xl md:text-2xl text-white/80 font-medium max-w-2xl">' . $sub . '</p>' : '')
                    . ($body ? '<p class="mt-4 text-lg text-white/60 max-w-xl leading-relaxed">' . $body . '</p>' : '')
                    . $cta_block
                    . '</div></section>'
                );
        }
    }

    /**
     * Services/Features section — 3 variants.
     * V0: Card grid (default)
     * V1: Icon + description list (minimal)
     * V2: Alternating image + text blocks
     */
    private static function section_services($s, $i) {
        $variant = self::pick_variant('services', $i);
        $id = 'section-' . ($i + 1) . '-services';
        $hl = esc_html($s['headline'] ?? 'Our Services');
        $sub = esc_html($s['subheadline'] ?? '');
        $body = esc_html($s['body'] ?? '');
        $bullets = is_array($s['bullets'] ?? null) ? $s['bullets'] : [];
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);
        $icons = ['&#x1F680;', '&#x2B50;', '&#x1F4A1;', '&#x1F3AF;', '&#x26A1;', '&#x1F527;'];

        $header = '<div class="text-center max-w-3xl mx-auto mb-16">'
            . ($sub ? '<p class="font-semibold tracking-wide uppercase text-sm mb-3" style="color:' . $accent . ';">' . $sub . '</p>' : '')
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . ($body ? '<p class="mt-5 text-lg leading-relaxed" style="color:' . esc_attr($pal['muted']) . ';">' . $body . '</p>' : '')
            . '</div>';

        $wrap = function($inner) use ($id, $i, $pal) {
            return '<!-- SECTION ' . ($i + 1) . ' -->'
                . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['surface']) . ';" data-vmo-section-type="services" data-vmo-animate>'
                . '<div class="max-w-7xl mx-auto px-6">' . $inner . '</div></section>'
                . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
        };

        switch ($variant) {
            case 1: // Minimal icon + text list
                $items = '';
                foreach ($bullets as $bi => $item) {
                    $icon = $icons[$bi % count($icons)];
                    $items .= '<div class="flex items-start gap-5 py-6 border-b" style="border-color:' . esc_attr($pal['muted']) . '33;">'
                        . '<div class="w-12 h-12 flex-shrink-0 flex items-center justify-center rounded-xl text-2xl" style="background:' . $accent . '22;">' . $icon . '</div>'
                        . '<div><h3 class="text-lg font-bold" style="color:' . esc_attr($pal['text']) . ';">' . esc_html($item) . '</h3>'
                        . '<p class="mt-1 text-sm" style="color:' . esc_attr($pal['muted']) . ';">Premium service tailored to your needs.</p></div>'
                        . '</div>';
                }
                return $wrap($header . '<div class="max-w-2xl mx-auto">' . $items . '</div>');

            case 2: // Alternating image + text
                $blocks = '';
                foreach ($bullets as $bi => $item) {
                    $swap = ($bi % 2 === 1) ? 'md:order-last' : '';
                    $media = self::media_placeholder('service-' . $bi, 'image', $i * 10 + $bi);
                    $blocks .= '<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center py-12">'
                        . '<div class="' . $swap . '"><h3 class="text-2xl font-bold" style="color:' . esc_attr($pal['text']) . ';">' . esc_html($item) . '</h3>'
                        . '<p class="mt-3 leading-relaxed" style="color:' . esc_attr($pal['muted']) . ';">Expert solutions designed for measurable results.</p></div>'
                        . '<div>' . $media . '</div></div>';
                }
                return $wrap($header . $blocks);

            default: // V0: Card grid (original enhanced)
                $cards = '';
                foreach ($bullets as $bi => $item) {
                    $icon = $icons[$bi % count($icons)];
                    $cards .= '<div class="group p-8 rounded-2xl border shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all duration-300" style="background:' . esc_attr($pal['bg']) . ';border-color:' . esc_attr($pal['muted']) . '22;">'
                        . '<div class="w-12 h-12 flex items-center justify-center rounded-xl text-2xl mb-5" style="background:' . $accent . '15;">' . $icon . '</div>'
                        . '<h3 class="text-lg font-bold" style="color:' . esc_attr($pal['text']) . ';">' . esc_html($item) . '</h3>'
                        . '</div>';
                }
                return $wrap($header . '<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">' . $cards . '</div>');
        }
    }

    /**
     * About section — 3 variants.
     * V0: Image + text split
     * V1: Stats bar below content
     * V2: Full-width image above text
     */
    private static function section_about($s, $i) {
        $variant = self::pick_variant('about', $i);
        $id = 'section-' . ($i + 1) . '-about';
        $hl = esc_html($s['headline'] ?? 'About Us');
        $sub = esc_html($s['subheadline'] ?? '');
        $body = esc_html($s['body'] ?? '');
        $media = self::media_placeholder('about', ($s['media'] ?? 'image'), $i);
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);
        $swap = ($i % 2 === 1);
        $order = $swap ? 'md:order-last' : '';

        $text_block = '<div class="' . $order . '">'
            . ($sub ? '<p class="font-semibold tracking-wide uppercase text-sm mb-3" style="color:' . $accent . ';">' . $sub . '</p>' : '')
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight leading-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . ($body ? '<p class="mt-5 text-lg leading-relaxed" style="color:' . esc_attr($pal['muted']) . ';">' . $body . '</p>' : '')
            . '</div>';

        switch ($variant) {
            case 1: // Stats bar
                $stats = '<div class="grid grid-cols-3 gap-8 mt-12 pt-12 border-t" style="border-color:' . esc_attr($pal['muted']) . '22;">'
                    . '<div class="text-center"><p class="text-3xl font-bold" style="color:' . $accent . ';">10+</p><p class="text-sm mt-1" style="color:' . esc_attr($pal['muted']) . ';">Years</p></div>'
                    . '<div class="text-center"><p class="text-3xl font-bold" style="color:' . $accent . ';">500+</p><p class="text-sm mt-1" style="color:' . esc_attr($pal['muted']) . ';">Clients</p></div>'
                    . '<div class="text-center"><p class="text-3xl font-bold" style="color:' . $accent . ';">99%</p><p class="text-sm mt-1" style="color:' . esc_attr($pal['muted']) . ';">Satisfaction</p></div>'
                    . '</div>';
                return '<!-- SECTION ' . ($i + 1) . ' -->'
                    . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['bg']) . ';" data-vmo-section-type="about" data-vmo-animate>'
                    . '<div class="max-w-7xl mx-auto px-6 grid grid-cols-1 md:grid-cols-2 gap-12 lg:gap-20 items-center">'
                    . $text_block . '<div>' . $media . '</div>'
                    . '</div>' . $stats
                    . '</section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";

            case 2: // Full-width image above
                return '<!-- SECTION ' . ($i + 1) . ' -->'
                    . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['surface']) . ';" data-vmo-section-type="about" data-vmo-animate>'
                    . '<div class="max-w-7xl mx-auto px-6">'
                    . '<div class="aspect-[21/9] overflow-hidden rounded-2xl mb-16">' . $media . '</div>'
                    . '<div class="max-w-3xl mx-auto text-center">' . str_replace($order, '', $text_block) . '</div>'
                    . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";

            default: // V0: Image + text split
                return '<!-- SECTION ' . ($i + 1) . ' -->'
                    . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['bg']) . ';" data-vmo-section-type="about" data-vmo-animate>'
                    . '<div class="max-w-7xl mx-auto px-6 grid grid-cols-1 md:grid-cols-2 gap-12 lg:gap-20 items-center">'
                    . $text_block . '<div>' . $media . '</div>'
                    . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
        }
    }

    /**
     * Testimonials section — 3 variants.
     * V0: Swiper carousel  V1: Masonry grid  V2: Large single quote
     */
    private static function section_testimonials($s, $i) {
        $variant = self::pick_variant('testimonials', $i);
        $id = 'section-' . ($i + 1) . '-testimonials';
        $hl = esc_html($s['headline'] ?? 'What Our Clients Say');
        $sub = esc_html($s['subheadline'] ?? '');
        $bullets = is_array($s['bullets'] ?? null) ? $s['bullets'] : ['Great service and results!', 'Absolutely transformed our business.', 'Highly recommend to anyone.'];
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);

        $header = '<div class="text-center max-w-3xl mx-auto mb-16">'
            . ($sub ? '<p class="font-semibold tracking-wide uppercase text-sm mb-3" style="color:' . $accent . ';">' . $sub . '</p>' : '')
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . '</div>';

        switch ($variant) {
            case 1: // Masonry grid
                $cards = '';
                foreach ($bullets as $bi => $quote) {
                    $cards .= '<div class="p-8 rounded-2xl border shadow-sm" style="background:' . esc_attr($pal['bg']) . ';border-color:' . esc_attr($pal['muted']) . '22;">'
                        . '<p class="text-lg leading-relaxed italic" style="color:' . esc_attr($pal['text']) . ';">&ldquo;' . esc_html($quote) . '&rdquo;</p>'
                        . '<p class="mt-4 text-sm font-semibold" style="color:' . esc_attr($pal['text']) . ';">Client ' . ($bi + 1) . '</p>'
                        . '</div>';
                }
                return '<!-- SECTION ' . ($i + 1) . ' -->'
                    . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['surface']) . ';" data-vmo-section-type="testimonials" data-vmo-animate>'
                    . '<div class="max-w-7xl mx-auto px-6">' . $header
                    . '<div class="columns-1 md:columns-2 lg:columns-3 gap-6 space-y-6">' . $cards . '</div>'
                    . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";

            case 2: // Large single featured quote
                $featured = esc_html($bullets[0] ?? 'Outstanding experience.');
                return '<!-- SECTION ' . ($i + 1) . ' -->'
                    . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['bg']) . ';" data-vmo-section-type="testimonials" data-vmo-animate>'
                    . '<div class="max-w-4xl mx-auto px-6 text-center">'
                    . '<p class="text-5xl" style="color:' . $accent . ';">&ldquo;</p>'
                    . '<blockquote class="text-2xl md:text-3xl font-medium leading-relaxed italic" style="color:' . esc_attr($pal['text']) . ';">' . $featured . '</blockquote>'
                    . '<p class="mt-8 text-sm font-semibold" style="color:' . esc_attr($pal['muted']) . ';">— Featured Client</p>'
                    . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";

            default: // V0: Swiper carousel
                $slides = '';
                foreach ($bullets as $bi => $quote) {
                    $slides .= '<div class="swiper-slide"><div class="p-8 rounded-2xl border shadow-sm" style="background:' . esc_attr($pal['bg']) . ';border-color:' . esc_attr($pal['muted']) . '22;">'
                        . '<p class="text-lg leading-relaxed italic" style="color:' . esc_attr($pal['text']) . ';">&ldquo;' . esc_html($quote) . '&rdquo;</p>'
                        . '<p class="mt-4 text-sm font-semibold" style="color:' . esc_attr($pal['text']) . ';">Client ' . ($bi + 1) . '</p>'
                        . '</div></div>';
                }
                return '<!-- SECTION ' . ($i + 1) . ' -->'
                    . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['surface']) . ';" data-vmo-section-type="testimonials" data-vmo-animate>'
                    . '<div class="max-w-7xl mx-auto px-6">' . $header
                    . '<div class="swiper vmo-testimonial-swiper"><div class="swiper-wrapper">' . $slides . '</div>'
                    . '<div class="swiper-pagination mt-8"></div></div>'
                    . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
        }
    }

    private static function section_products($s, $i) {
        $id = 'section-' . ($i + 1) . '-products';
        $hl = esc_html($s['headline'] ?? 'Our Products');
        $sub = esc_html($s['subheadline'] ?? '');
        $bullets = is_array($s['bullets'] ?? null) ? $s['bullets'] : ['Product A', 'Product B', 'Product C'];
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);
        $cards = '';
        foreach ($bullets as $pi => $product) {
            $media_id = 'product-media-' . $i . '-' . $pi . '-' . wp_rand(1000, 9999);
            $seed = urlencode('product-' . $pi);
            $cards .= '<div class="rounded-2xl border overflow-hidden shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all duration-300 group" style="background:' . esc_attr($pal['bg']) . ';border-color:' . esc_attr($pal['muted']) . '22;">'
                . '<div class="relative aspect-[4/3] overflow-hidden">'
                . '<img class="vmo-media-placeholder w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" '
                . 'data-media-id="' . $media_id . '" data-type="image" loading="lazy" '
                . 'src="https://picsum.photos/seed/' . $seed . '/800/600" alt="' . esc_attr($product) . '" />'
                . self::replace_button_overlay($media_id)
                . '</div>'
                . '<div class="p-6"><h3 class="text-lg font-bold" style="color:' . esc_attr($pal['text']) . ';">' . esc_html($product) . '</h3>'
                . '<p class="mt-2 text-sm" style="color:' . esc_attr($pal['muted']) . ';">Premium quality product</p>'
                . '<div class="mt-4 flex items-center justify-between">'
                . '<span class="text-2xl font-bold" style="color:' . esc_attr($pal['text']) . ';">$99</span>'
                . '<button class="vmo-pay-btn px-6 py-2.5 text-white font-semibold rounded-xl hover:shadow-lg transition-all duration-300" '
                . 'style="background:' . $accent . ';" data-vmo-product="' . esc_attr($product) . '">Buy Now</button>'
                . '</div></div></div>';
        }
        return '<!-- SECTION ' . ($i + 1) . ' -->'
            . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['bg']) . ';" data-vmo-section-type="products" data-vmo-animate>'
            . '<div class="max-w-7xl mx-auto px-6">'
            . '<div class="text-center max-w-3xl mx-auto mb-16">'
            . ($sub ? '<p class="font-semibold tracking-wide uppercase text-sm mb-3" style="color:' . $accent . ';">' . $sub . '</p>' : '')
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . '</div>'
            . '<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">' . $cards . '</div>'
            . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
    }

    private static function section_pricing($s, $i) {
        $id = 'section-' . ($i + 1) . '-pricing';
        $hl = esc_html($s['headline'] ?? 'Pricing');
        $sub = esc_html($s['subheadline'] ?? '');
        $bullets = is_array($s['bullets'] ?? null) ? $s['bullets'] : ['Starter — $29/mo', 'Pro — $79/mo', 'Enterprise — $199/mo'];
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);
        $cards = '';
        $featured_index = (int) floor(count($bullets) / 2);
        foreach ($bullets as $pi => $plan_label) {
            $is_featured = ($pi === $featured_index);
            $ring = $is_featured ? 'ring-2 scale-105' : '';
            $ring_style = $is_featured ? 'ring-color:' . $accent . ';--tw-ring-color:' . $accent . ';' : '';
            $badge = $is_featured ? '<span class="absolute -top-3 left-1/2 -translate-x-1/2 px-4 py-1 text-white text-xs font-bold rounded-full" style="background:' . $accent . ';">Popular</span>' : '';
            $cards .= '<div class="relative p-8 rounded-2xl border shadow-sm ' . $ring . '" style="background:' . esc_attr($pal['bg']) . ';border-color:' . esc_attr($pal['muted']) . '22;' . $ring_style . '">'
                . $badge
                . '<h3 class="text-xl font-bold" style="color:' . esc_attr($pal['text']) . ';">' . esc_html($plan_label) . '</h3>'
                . '<a href="#" class="mt-6 block w-full text-center px-6 py-3 text-white font-semibold rounded-xl hover:shadow-lg transition-all duration-300" style="background:' . $accent . ';">Get Started</a>'
                . '</div>';
        }
        return '<!-- SECTION ' . ($i + 1) . ' -->'
            . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['surface']) . ';" data-vmo-section-type="pricing" data-vmo-animate>'
            . '<div class="max-w-7xl mx-auto px-6">'
            . '<div class="text-center max-w-3xl mx-auto mb-16">'
            . ($sub ? '<p class="font-semibold tracking-wide uppercase text-sm mb-3" style="color:' . $accent . ';">' . $sub . '</p>' : '')
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . '</div>'
            . '<div class="grid grid-cols-1 md:grid-cols-3 gap-8 items-start">' . $cards . '</div>'
            . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
    }

    private static function section_contact($s, $i, $integrations) {
        $id = 'section-' . ($i + 1) . '-contact';
        $hl = esc_html($s['headline'] ?? 'Get In Touch');
        $sub = esc_html($s['subheadline'] ?? '');
        $body = esc_html($s['body'] ?? '');
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);

        $chips = '';
        if (!empty($integrations['phone_enabled']) && !empty($integrations['phone_number'])) {
            $phone = esc_html($integrations['phone_number']);
            $href  = 'tel:' . preg_replace('/[^+\d]/', '', $integrations['phone_number']);
            $chips .= '<a href="' . esc_attr($href) . '" class="flex items-center gap-3 px-5 py-3 rounded-xl font-semibold hover:opacity-80 transition" style="background:' . $accent . '18;color:' . $accent . ';">&#x1F4DE; ' . $phone . '</a>';
        }
        if (!empty($integrations['email_enabled']) && !empty($integrations['email_address'])) {
            $email = esc_html($integrations['email_address']);
            $chips .= '<a href="mailto:' . esc_attr($integrations['email_address']) . '" class="flex items-center gap-3 px-5 py-3 rounded-xl font-semibold hover:opacity-80 transition" style="background:' . $accent . '18;color:' . $accent . ';">&#x2709; ' . $email . '</a>';
        }

        return '<!-- SECTION ' . ($i + 1) . ' -->'
            . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['bg']) . ';" data-vmo-section-type="contact" data-vmo-animate>'
            . '<div class="max-w-7xl mx-auto px-6 grid grid-cols-1 md:grid-cols-2 gap-16">'
            . '<div>'
            . ($sub ? '<p class="font-semibold tracking-wide uppercase text-sm mb-3" style="color:' . $accent . ';">' . $sub . '</p>' : '')
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . ($body ? '<p class="mt-5 text-lg leading-relaxed" style="color:' . esc_attr($pal['muted']) . ';">' . $body . '</p>' : '')
            . ($chips ? '<div class="mt-8 flex flex-col sm:flex-row gap-4">' . $chips . '</div>' : '')
            . '</div>'
            . '<form class="space-y-5" data-vmo-form="lead" onsubmit="event.preventDefault();">'
            . '<input type="text" name="name" placeholder="Your name" required class="w-full px-5 py-3.5 rounded-xl border outline-none transition" style="border-color:' . esc_attr($pal['muted']) . '33;background:' . esc_attr($pal['surface']) . ';color:' . esc_attr($pal['text']) . ';">'
            . '<input type="email" name="email" placeholder="Your email" required class="w-full px-5 py-3.5 rounded-xl border outline-none transition" style="border-color:' . esc_attr($pal['muted']) . '33;background:' . esc_attr($pal['surface']) . ';color:' . esc_attr($pal['text']) . ';">'
            . '<textarea name="message" rows="4" placeholder="How can we help?" class="w-full px-5 py-3.5 rounded-xl border outline-none transition resize-none" style="border-color:' . esc_attr($pal['muted']) . '33;background:' . esc_attr($pal['surface']) . ';color:' . esc_attr($pal['text']) . ';"></textarea>'
            . '<button type="submit" class="w-full px-8 py-4 text-white font-semibold rounded-xl shadow-lg hover:shadow-xl hover:-translate-y-0.5 transition-all duration-300" style="background:' . $accent . ';">Send Message</button>'
            . '</form></div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
    }

    private static function section_gallery($s, $i) {
        $id = 'section-' . ($i + 1) . '-gallery';
        $hl = esc_html($s['headline'] ?? 'Gallery');
        $bullets = is_array($s['bullets'] ?? null) ? $s['bullets'] : ['Project A', 'Project B', 'Project C', 'Project D'];
        $pal = self::palette();
        $items = '';
        foreach ($bullets as $gi => $item) {
            $media_id = 'gallery-media-' . $i . '-' . $gi . '-' . wp_rand(1000, 9999);
            $seed = urlencode('gallery-' . $gi);
            $items .= '<div class="relative group overflow-hidden rounded-2xl aspect-square">'
                . '<img class="vmo-media-placeholder w-full h-full object-cover group-hover:scale-110 transition-transform duration-700" '
                . 'data-media-id="' . $media_id . '" data-type="image" loading="lazy" '
                . 'src="https://picsum.photos/seed/' . $seed . '/800/800" alt="' . esc_attr($item) . '" />'
                . '<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end p-6">'
                . '<p class="text-white font-semibold">' . esc_html($item) . '</p></div>'
                . self::replace_button_overlay($media_id)
                . '</div>';
        }
        return '<!-- SECTION ' . ($i + 1) . ' -->'
            . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['surface']) . ';" data-vmo-section-type="gallery" data-vmo-animate>'
            . '<div class="max-w-7xl mx-auto px-6">'
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight text-center mb-16" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . '<div class="grid grid-cols-2 lg:grid-cols-4 gap-4">' . $items . '</div>'
            . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
    }

    private static function section_team($s, $i) {
        $id = 'section-' . ($i + 1) . '-team';
        $hl = esc_html($s['headline'] ?? 'Meet the Team');
        $bullets = is_array($s['bullets'] ?? null) ? $s['bullets'] : ['Team Member A', 'Team Member B', 'Team Member C'];
        $pal = self::palette();
        $cards = '';
        foreach ($bullets as $ti => $member) {
            $seed = urlencode('team-' . $ti);
            $cards .= '<div class="text-center">'
                . '<img class="w-32 h-32 rounded-full object-cover mx-auto shadow-lg" loading="lazy" '
                . 'src="https://picsum.photos/seed/' . $seed . '/300/300" alt="' . esc_attr($member) . '" />'
                . '<h3 class="mt-5 text-lg font-bold" style="color:' . esc_attr($pal['text']) . ';">' . esc_html($member) . '</h3>'
                . '<p class="text-sm mt-1" style="color:' . esc_attr($pal['muted']) . ';">Team Member</p></div>';
        }
        return '<!-- SECTION ' . ($i + 1) . ' -->'
            . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['bg']) . ';" data-vmo-section-type="team" data-vmo-animate>'
            . '<div class="max-w-7xl mx-auto px-6">'
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight text-center mb-16" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . '<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-10">' . $cards . '</div>'
            . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
    }

    private static function section_faq($s, $i) {
        $id = 'section-' . ($i + 1) . '-faq';
        $hl = esc_html($s['headline'] ?? 'Frequently Asked Questions');
        $bullets = is_array($s['bullets'] ?? null) ? $s['bullets'] : ['How does this work?', 'What is the pricing?', 'Do you offer support?'];
        $pal = self::palette();
        $items = '';
        foreach ($bullets as $fi => $question) {
            $items .= '<details class="group border rounded-xl overflow-hidden" style="border-color:' . esc_attr($pal['muted']) . '22;" ' . ($fi === 0 ? 'open' : '') . '>'
                . '<summary class="flex items-center justify-between px-6 py-4 cursor-pointer font-semibold transition" style="color:' . esc_attr($pal['text']) . ';">'
                . esc_html($question) . '<span class="ml-4 group-open:rotate-45 transition-transform duration-200 text-xl" style="color:' . esc_attr($pal['muted']) . ';">+</span></summary>'
                . '<div class="px-6 pb-5 leading-relaxed" style="color:' . esc_attr($pal['muted']) . ';">Our team is here to help with all your needs. Contact us for detailed information.</div>'
                . '</details>';
        }
        return '<!-- SECTION ' . ($i + 1) . ' -->'
            . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['surface']) . ';" data-vmo-section-type="faq" data-vmo-animate>'
            . '<div class="max-w-3xl mx-auto px-6">'
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight text-center mb-16" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . '<div class="space-y-3">' . $items . '</div>'
            . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
    }

    /**
     * CTA section — 3 variants.
     * V0: Dark gradient centered
     * V1: Split CTA with media
     * V2: Full-bleed accent background
     */
    private static function section_cta($s, $i) {
        $variant = self::pick_variant('cta', $i);
        $id = 'section-' . ($i + 1) . '-cta';
        $hl = esc_html($s['headline'] ?? 'Ready to Get Started?');
        $sub = esc_html($s['subheadline'] ?? '');
        $cta1 = esc_html($s['cta_primary'] ?? 'Get Started');
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);

        $wrap = function($inner) use ($i) {
            return '<!-- SECTION ' . ($i + 1) . ' -->' . $inner . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
        };

        switch ($variant) {
            case 1: // Split CTA with media
                $media = self::media_placeholder('cta', 'image', $i);
                return $wrap(
                    '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($pal['bg']) . ';" data-vmo-section-type="cta" data-vmo-animate>'
                    . '<div class="max-w-7xl mx-auto px-6 grid grid-cols-1 md:grid-cols-2 gap-16 items-center">'
                    . '<div>'
                    . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
                    . ($sub ? '<p class="mt-5 text-xl" style="color:' . esc_attr($pal['muted']) . ';">' . $sub . '</p>' : '')
                    . '<a href="#" class="mt-10 inline-flex items-center px-10 py-5 font-bold text-lg rounded-2xl shadow-xl hover:shadow-2xl hover:-translate-y-1 transition-all duration-300" style="background:' . $accent . ';color:#fff;">' . $cta1 . '</a>'
                    . '</div>'
                    . '<div>' . $media . '</div>'
                    . '</div></section>'
                );

            case 2: // Full-bleed accent
                return $wrap(
                    '<section id="' . $id . '" class="py-24 lg:py-32 text-white" style="background:' . $accent . ';" data-vmo-section-type="cta" data-vmo-animate>'
                    . '<div class="max-w-4xl mx-auto px-6 text-center">'
                    . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight">' . $hl . '</h2>'
                    . ($sub ? '<p class="mt-5 text-xl text-white/80">' . $sub . '</p>' : '')
                    . '<a href="#" class="mt-10 inline-flex items-center px-10 py-5 bg-white font-bold text-lg rounded-2xl shadow-xl hover:shadow-2xl hover:-translate-y-1 transition-all duration-300" style="color:' . $accent . ';">' . $cta1 . '</a>'
                    . '</div></section>'
                );

            default: // V0: Dark gradient centered
                return $wrap(
                    '<section id="' . $id . '" class="py-24 lg:py-32 bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 text-white" data-vmo-section-type="cta" data-vmo-animate>'
                    . '<div class="max-w-4xl mx-auto px-6 text-center">'
                    . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight">' . $hl . '</h2>'
                    . ($sub ? '<p class="mt-5 text-xl text-white/70">' . $sub . '</p>' : '')
                    . '<a href="#" class="mt-10 inline-flex items-center px-10 py-5 font-bold text-lg rounded-2xl shadow-xl hover:shadow-2xl hover:-translate-y-1 transition-all duration-300" style="background:' . $accent . ';color:#fff;box-shadow:0 10px 30px ' . $accent . '40;">' . $cta1 . '</a>'
                    . '</div></section>'
                );
        }
    }

    private static function section_default($s, $i) {
        $id = 'section-' . ($i + 1);
        $hl = esc_html($s['headline'] ?? 'Section');
        $sub = esc_html($s['subheadline'] ?? '');
        $body = esc_html($s['body'] ?? '');
        $media = self::media_placeholder('section', ($s['media'] ?? 'image'), $i);
        $pal = self::palette();
        $accent = esc_attr($pal['accent']);
        $swap = ($i % 2 === 1);
        $order = $swap ? 'md:order-last' : '';
        $bg = ($i % 2 === 0) ? $pal['bg'] : $pal['surface'];

        return '<!-- SECTION ' . ($i + 1) . ' -->'
            . '<section id="' . $id . '" class="py-24 lg:py-32" style="background:' . esc_attr($bg) . ';" data-vmo-section-type="default" data-vmo-animate>'
            . '<div class="max-w-7xl mx-auto px-6 grid grid-cols-1 md:grid-cols-2 gap-12 lg:gap-20 items-center">'
            . '<div class="' . $order . '">'
            . ($sub ? '<p class="font-semibold tracking-wide uppercase text-sm mb-3" style="color:' . $accent . ';">' . $sub . '</p>' : '')
            . '<h2 class="text-3xl md:text-5xl font-bold tracking-tight leading-tight" style="color:' . esc_attr($pal['text']) . ';">' . $hl . '</h2>'
            . ($body ? '<p class="mt-5 text-lg leading-relaxed" style="color:' . esc_attr($pal['muted']) . ';">' . $body . '</p>' : '')
            . '</div><div>' . $media . '</div>'
            . '</div></section>' . "\n<!-- END SECTION " . ($i + 1) . " -->\n";
    }

    /* ────────────────── CDN / STYLES / SCRIPTS ────────────────── */

    /**
     * Build CDN head tags (stylesheets + scripts + Tailwind config).
     */
    private static function build_cdn_head($tech, $primary = '#0f172a', $accent = '#0ea5e9') {
        $out = '';
        // Fonts
        $out .= '<link rel="preconnect" href="https://fonts.googleapis.com">';
        $out .= '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>';
        $out .= '<link rel="stylesheet" href="' . self::CDN['font'] . '">';
        // Tailwind CDN
        $out .= '<script src="' . self::CDN['tailwind'] . '"></script>';
        $out .= '<script>tailwind.config={theme:{extend:{colors:{primary:"' . $primary . '",accent:"' . $accent . '"},fontFamily:{sans:["Inter","system-ui","sans-serif"]}}}}</script>';
        // Swiper CSS
        $out .= '<link rel="stylesheet" href="' . self::CDN['swiper_css'] . '">';
        // AOS CSS
        $out .= '<link rel="stylesheet" href="' . self::CDN['aos_css'] . '">';
        return $out . "\n";
    }

    /**
     * Build base CSS that complements Tailwind.
     */
    private static function build_base_css($primary, $accent) {
        return <<<CSS
:root{--vmo-primary:{$primary};--vmo-accent:{$accent};}
html{scroll-behavior:smooth;}
body{margin:0;font-family:Inter,system-ui,-apple-system,sans-serif;-webkit-font-smoothing:antialiased;}
[data-vmo-animate]{opacity:0;transform:translateY(32px);transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1);}
[data-vmo-animate].vmo-visible{opacity:1;transform:translateY(0);}
.swiper-pagination-bullet-active{background:var(--vmo-accent)!important;}
.vmo-overlay-container{position:absolute;inset:0;pointer-events:none;overflow:hidden;z-index:1;}
CSS;
    }

    /**
     * Build initialization scripts (GSAP, Lenis, Swiper, AOS, media replace buttons).
     */
    private static function build_init_scripts() {
        return '<script src="' . self::CDN['gsap'] . '"></script>'
            . '<script src="' . self::CDN['scrolltrigger'] . '"></script>'
            . '<script src="' . self::CDN['lenis'] . '"></script>'
            . '<script src="' . self::CDN['swiper_js'] . '"></script>'
            . '<script src="' . self::CDN['aos_js'] . '"></script>'
            . '<script>'
            . self::build_init_js()
            . '</script>' . "\n";
    }

    /**
     * Build the JS initialization code for GSAP, Lenis, Swiper, AOS, overlays, and media replace.
     */
    private static function build_init_js() {
        return <<<'JS'
(function(){
  "use strict";

  /* ── Lenis smooth scroll ── */
  if(window.Lenis){
    var lenis=new Lenis({duration:1.2,easing:function(t){return Math.min(1,1.001-Math.pow(2,-10*t))},smoothWheel:true});
    function raf(time){lenis.raf(time);requestAnimationFrame(raf);}
    requestAnimationFrame(raf);
    if(window.gsap&&window.ScrollTrigger){
      lenis.on("scroll",function(){window.ScrollTrigger.update();});
      window.gsap.ticker.add(function(time){lenis.raf(time*1000);});
      window.gsap.ticker.lagSmoothing(0);
    }
  }

  /* ── GSAP ScrollTrigger reveal ── */
  if(window.gsap&&window.ScrollTrigger){
    window.gsap.registerPlugin(window.ScrollTrigger);
    document.querySelectorAll("[data-vmo-animate]").forEach(function(el){
      window.gsap.fromTo(el,{opacity:0,y:40},{opacity:1,y:0,duration:0.8,ease:"power3.out",scrollTrigger:{trigger:el,start:"top 88%",once:true}});
    });
  }else{
    /* Fallback: IntersectionObserver */
    var obs=new IntersectionObserver(function(entries){entries.forEach(function(e){if(e.isIntersecting){e.target.classList.add("vmo-visible");obs.unobserve(e.target);}});},{threshold:0.1});
    document.querySelectorAll("[data-vmo-animate]").forEach(function(el){obs.observe(el);});
  }

  /* ── AOS init ── */
  if(window.AOS){window.AOS.init({once:true,duration:700});}

  /* ── Swiper carousels ── */
  if(window.Swiper){
    document.querySelectorAll(".vmo-testimonial-swiper").forEach(function(el){
      new Swiper(el,{slidesPerView:1,spaceBetween:24,pagination:{el:el.querySelector(".swiper-pagination"),clickable:true},breakpoints:{768:{slidesPerView:2},1024:{slidesPerView:3}}});
    });
  }

  /* ── Media replace buttons ── */
  document.querySelectorAll(".vmo-replace-btn").forEach(function(btn){
    btn.addEventListener("click",function(e){
      e.preventDefault();
      e.stopPropagation();
      var mediaId=btn.getAttribute("data-replace-media");
      if(window.vmoOpenMediaPicker){window.vmoOpenMediaPicker(mediaId);}
      else if(window.parent&&window.parent.vmoOpenMediaPicker){window.parent.vmoOpenMediaPicker(mediaId);}
    });
  });

  /* ── Overlay containers ── */
  document.querySelectorAll("[data-vmo-section-type='hero']").forEach(function(hero){
    if(!hero.querySelector(".vmo-overlay-container")){
      var c=document.createElement("div");c.className="vmo-overlay-container";c.setAttribute("data-vmo-overlay-slot","hero");
      hero.insertBefore(c,hero.firstChild);
    }
  });

  /* ── VMO Pay buttons ── */
  document.querySelectorAll(".vmo-pay-btn").forEach(function(btn){
    btn.addEventListener("click",function(e){
      e.preventDefault();
      var product=btn.getAttribute("data-vmo-product")||"Product";
      if(window.vmoPayCheckout){window.vmoPayCheckout(product);}
      else{alert("VMO Pay checkout for: "+product);}
    });
  });

})();
JS;
    }
}
