<?php
declare(strict_types=1);

namespace Help4BuilderSuite\Modules\Demos;

use Help4BuilderSuite\Support\RobotsContract;

use Help4BuilderSuite\Contracts\ModuleContract;
use Help4BuilderSuite\Support\ContactRoutes;

if (! defined('ABSPATH')) {
    exit;
}

final class Module implements ModuleContract
{
    /**
     * @var array<string, string>
     */
    private static array $mirrorTokens = [];

    public function key(): string
    {
        return 'demos';
    }

    public function boot(): void
    {
        add_action('admin_menu', [$this, 'registerAdminPage']);
        add_action('admin_menu', [$this, 'registerShowcaseToolsPages']);
        add_action('admin_init', [$this, 'handleActions']);
        add_action('admin_init', [$this, 'maybeAutoBootstrapStagingDemo'], 30);
        add_action('init', [$this, 'maybeAutoRefreshMarketingSeed'], 45);
        add_action('admin_post_h4bs_generate_grouped_showcase', [$this, 'handleGenerateGroupedShowcase']);
        add_action('admin_notices', [$this, 'renderNotice']);
        add_filter('the_content', [$this, 'renderMirroredContent'], 6);
        add_filter('the_content', [$this, 'restoreMirroredContentAfterFilters'], 9999);
        add_action('wp_enqueue_scripts', [$this, 'enqueueMirroredAssets'], 120);
        add_filter('body_class', [$this, 'addMirrorBodyClass'], 20);
        add_filter('h4bs_seo_llms_priority_page_slugs', [$this, 'prioritizeLlmsPages']);
        add_action('wp_head', [$this, 'renderTutorialCatalogSchema'], 25);
        add_filter('query_vars', [$this, 'registerTutorialCaptionQueryVar']);
        add_action('template_redirect', [$this, 'serveTutorialCaption'], 0);
    }

    /**
     * @param array<int, string> $queryVars
     * @return array<int, string>
     */
    public function registerTutorialCaptionQueryVar(array $queryVars): array
    {
        $queryVars[] = 'h4bs_tutorial_caption';
        return array_values(array_unique($queryVars));
    }

    public function serveTutorialCaption(): void
    {
        if (! $this->isHelp4WordPressMarketingSite()) {
            return;
        }

        $requested = sanitize_file_name((string) get_query_var('h4bs_tutorial_caption'));
        $allowedCaptions = array_values(
            array_filter(
                array_map(
                    static fn (array $video): string => sanitize_file_name((string) ($video['captions'] ?? '')),
                    $this->h4BuilderTutorialVideoCatalog()
                )
            )
        );
        if ($requested === '' || ! in_array($requested, $allowedCaptions, true)) {
            return;
        }

        $directory = realpath(H4BS_PATH . 'assets/tutorial-videos/2026-08');
        $path = realpath(H4BS_PATH . 'assets/tutorial-videos/2026-08/' . $requested);
        if (
            ! is_string($directory)
            || ! is_string($path)
            || ! str_starts_with($path, trailingslashit($directory))
            || ! is_readable($path)
        ) {
            status_header(404);
            exit;
        }

        global $wp_filesystem;
        if (! function_exists('WP_Filesystem')) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }
        if (! WP_Filesystem() || ! $wp_filesystem instanceof \WP_Filesystem_Base) {
            status_header(500);
            exit;
        }
        $contents = $wp_filesystem->get_contents($path);
        if (! is_string($contents)) {
            status_header(500);
            exit;
        }

        status_header(200);
        header('Content-Type: text/vtt; charset=UTF-8');
        header('X-Content-Type-Options: nosniff');
        header('Cache-Control: public, max-age=86400, immutable');
        header('Content-Length: ' . (string) strlen($contents));
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Packaged WebVTT text is selected from a strict filename allowlist.
        echo $contents;
        exit;
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    private function h4BuilderTutorialVideoCatalog(): array
    {
        static $catalog = null;
        if (is_array($catalog)) {
            return $catalog;
        }

        $catalogPath = H4BS_PATH . 'includes/Modules/Demos/tutorial-video-catalog.php';
        if (! is_readable($catalogPath)) {
            $catalog = [];
            return $catalog;
        }

        $loaded = require $catalogPath;
        if (! is_array($loaded)) {
            $catalog = [];
            return $catalog;
        }

        $catalog = [];
        foreach ($loaded as $video) {
            if (! is_array($video)) {
                continue;
            }
            $number = absint($video['number'] ?? 0);
            $filename = sanitize_file_name((string) ($video['filename'] ?? ''));
            $poster = sanitize_file_name((string) ($video['poster'] ?? ''));
            $captions = sanitize_file_name((string) ($video['captions'] ?? ''));
            if (
                $number < 1
                || $number > 49
                || ! preg_match('/^[0-9]{2}-[a-z0-9-]+\.mp4$/', $filename)
                || ! preg_match('/^[0-9]{2}-[a-z0-9-]+\.(?:png|webp)$/', $poster)
                || ! preg_match('/^[0-9]{2}-[a-z0-9-]+\.vtt$/', $captions)
            ) {
                continue;
            }

            $video['number'] = $number;
            $video['filename'] = $filename;
            $video['poster'] = $poster;
            $video['captions'] = $captions;
            $catalog[$number] = $video;
        }

        ksort($catalog);
        return $catalog;
    }

    private function h4BuilderTutorialVideoMediaBaseUrl(): string
    {
        $homeHost = strtolower((string) wp_parse_url(home_url('/'), PHP_URL_HOST));
        $defaultHost = $homeHost === 'md.help4wordpress.com' ? 'md.help4wordpress.com' : 'help4wordpress.com';
        $default = 'https://' . $defaultHost . '/help4-builder-tutorial-media/2026-08/';
        $stored = esc_url_raw((string) get_option('h4bs_tutorial_video_media_base_url', ''), ['http', 'https']);
        $filtered = apply_filters('h4bs_tutorial_video_media_base_url', $stored !== '' ? $stored : $default);
        $base = esc_url_raw(is_string($filtered) ? $filtered : '', ['http', 'https']);

        return trailingslashit($base !== '' ? $base : $default);
    }

    /**
     * @return array<int, int>
     */
    private function h4BuilderTutorialVideoNumbersForContext(string $context): array
    {
        $context = strtolower(remove_accents(wp_strip_all_tags($context)));
        $rules = [
            49 => ['click to edit', 'first change', 'select exact element', 'replace image', 'editor controls'],
            48 => ['accessibility audit', 'keyboard contrast', 'reduced motion', 'visible focus', 'screen reader'],
            47 => ['cache assets and performance', 'performance diagnostic', 'performance cache', 'help4 performance', 'cache boundary', 'page speed'],
            46 => ['security hardening', 'recovery access', 'proxy trust', 'login protection'],
            45 => ['google business profile', 'google business and reviews', 'place id', 'local proof'],
            44 => ['multisite network', 'network seo', 'wordpress multisite', 'network setup'],
            43 => ['form entries', 'forms lead capture', 'forms and lead capture', 'delivery diagnostic', 'spam diagnostic', 'lead delivery'],
            42 => ['commerce catalog', 'tax shipping', 'order operation', 'commerce launch'],
            41 => ['builder fields', 'structured fields', 'repeater', 'relationship', 'dynamic template', 'field group'],
            40 => ['widget library', 'widget favorite', 'addon module', 'recent widget'],
            39 => ['faq accordion', 'faq schema', 'accessible disclosure'],
            38 => ['five-plan', 'five plan', 'pricing comparison', 'pricing table'],
            37 => ['sales homepage', 'landing page', 'conversion page', 'blank canvas'],
            36 => ['publish launch', 'launch qa', 'save preview publish', 'save and publish', 'publishing workflow', 'rollback', 'public verification'],
            35 => ['module control', 'dependency', 'dependencies', 'update diagnostic', 'release identity', 'release operation', 'plugin update'],
            34 => ['migration', 'import export', 'cutover', 'layout hash', 'migration bundle'],
            33 => ['help4 blank', 'theme catalog', 'companion theme', 'theme setup'],
            32 => ['website snapshot', 'portfolio proof', 'recent work', 'website screenshot'],
            31 => ['lms', 'course', 'certificate', 'protected video', 'learning site'],
            30 => ['mega menu', 'complex navigation', 'submenu', 'mobile menu'],
            29 => ['site search', 'advanced search', 'search result', 'empty result'],
            28 => ['redirect', '404 monitoring', 'broken url', 'redirect chain'],
            27 => ['custom css', 'css class', 'page-level style', 'pseudo-element'],
            26 => ['navigator', 'layer', 'reusable section', 'element tree'],
            25 => ['live preview', 'responsive viewport', 'device preset', 'preview parity'],
            24 => ['i.g.o.r', 'igor', 'feedback', 'diagnostic', 'fresh log', 'issue report'],
            23 => ['security', 'hardening', 'dependency', 'update diagnostic', 'release operation'],
            22 => ['performance', 'cache', 'asset optimization', 'image optimization', 'site speed'],
            21 => ['newsletter', 'subscriber', 'campaign readiness', 'suppression'],
            20 => ['payment routing', 'gateway', 'order lifecycle', 'refund', 'commerce launch'],
            19 => ['customer field', 'subscription', 'variant', 'quantity rule', 'advanced commerce'],
            18 => ['advanced seo and discovery', 'configure local, international', 'local seo', 'international seo', 'indexnow', 'business profile', 'service area'],
            17 => ['prepare a page for launch', 'seo score', 'readability', 'social image', 'structured data', 'canonical'],
            16 => ['slider', 'motion', 'hls', 'video fallback', 'background video'],
            15 => ['dynamic data', 'custom field', 'repeater', 'relationship', 'field binding'],
            14 => ['template condition', 'theme builder', 'reusable template', 'display condition'],
            13 => ['global style', 'theme pack', 'design token', 'style-only'],
            12 => ['commerce', 'product', 'checkout', 'cart', 'order lifecycle', 'variation', 'pricing comparison'],
            11 => ['seo', 'search visibility', 'indexnow', 'readability', 'social sharing', 'schema', 'google business'],
            10 => ['template', 'site kit', 'starter site', 'theme pack', 'global style', 'import', 'export'],
            9 => ['form', 'lead capture', 'email marketing', 'newsletter', 'drip campaign'],
            8 => ['header', 'footer', 'menu', 'navigation', 'mega menu'],
            7 => ['section', 'container', 'column', 'page structure', 'layout hierarchy'],
            6 => ['button', 'typography', 'design control', 'spacing control'],
            5 => ['safe editing', 'recovery', 'troubleshooting', 'migration rescue'],
            4 => ['page settings', 'history', 'save and publish', 'revision'],
            3 => ['image', 'media replacement', 'image studio'],
            2 => ['edit text', 'responsive design', 'editor control', 'live preview'],
            1 => ['install', 'builder pages', 'open builder', 'navigator', 'first page'],
        ];

        $matches = [];
        foreach ($rules as $number => $needles) {
            foreach ($needles as $needle) {
                if (str_contains($context, $needle)) {
                    $matches[] = $number;
                    break;
                }
            }
            if (count($matches) >= 2) {
                break;
            }
        }

        return array_values(array_unique($matches));
    }

    /**
     * @param array<int, int> $numbers
     */
    private function h4BuilderTutorialVideoSection(array $numbers, bool $completeLibrary = false): string
    {
        $catalog = $this->h4BuilderTutorialVideoCatalog();
        $numbers = $completeLibrary
            ? array_values(array_unique(array_merge([49], array_keys($catalog))))
            : $numbers;
        $numbers = array_values(array_unique(array_map('absint', $numbers)));
        $videos = array_values(
            array_filter(
                array_map(static fn (int $number): ?array => $catalog[$number] ?? null, $numbers)
            )
        );
        if ($videos === []) {
            return '';
        }

        $videoBase = $this->h4BuilderTutorialVideoMediaBaseUrl();
        $posterBase = trailingslashit(H4BS_URL . 'assets/tutorial-videos/2026-08');
        $headingId = $completeLibrary ? 'h4-video-library-title' : 'h4-video-guide-title';
        $preload = $completeLibrary ? 'none' : 'metadata';
        $html = '<!-- H4 TUTORIAL VIDEO START -->'
            . '<section class="h4-tutorial-videos' . ($completeLibrary ? ' h4-tutorial-videos--library' : '') . '"' . ($completeLibrary ? ' data-h4bs-tutorial-library' : '') . ' aria-labelledby="' . esc_attr($headingId) . '">'
            . '<div class="h4-tutorial-section-heading"><p class="h4-product-eyebrow">Watch the real workflow</p>'
            . '<h2 id="' . esc_attr($headingId) . '">' . esc_html($completeLibrary ? sprintf('Follow %d short, narrated Builder lessons.', count($videos)) : 'Watch the clicks before making the change.') . '</h2>'
            . '<p>' . esc_html($completeLibrary ? 'Each lesson uses a current, privacy-safe Builder screen, natural narration, synchronized English captions, and a complete written transcript.' : 'Use the narrated walkthrough first, then follow the written steps and verification checks on this page.') . '</p></div>'
            . '<div class="h4-tutorial-videos__grid">';

        foreach ($videos as $video) {
            $number = absint($video['number'] ?? 0);
            $slug = sanitize_title((string) ($video['slug'] ?? 'tutorial-' . $number));
            $title = sanitize_text_field((string) ($video['title'] ?? 'Help4 Builder tutorial'));
            $description = sanitize_text_field((string) ($video['description'] ?? ''));
            $filename = sanitize_file_name((string) ($video['filename'] ?? ''));
            $poster = sanitize_file_name((string) ($video['poster'] ?? ''));
            $captions = sanitize_file_name((string) ($video['captions'] ?? ''));
            $guidePath = '/' . ltrim(sanitize_text_field((string) ($video['guidePath'] ?? 'help4-builder-tutorials/')), '/');
            $segments = is_array($video['segments'] ?? null) ? $video['segments'] : [];
            $descriptionId = 'h4-video-' . $slug . '-description';
            $captionUrl = add_query_arg('h4bs_tutorial_caption', $captions, home_url('/'));
            $videoUrl = $videoBase . $filename;
            $posterUrl = $posterBase . $poster;
            $mediaAttributes = $completeLibrary
                ? ' data-h4bs-lazy-tutorial-video data-src="' . esc_url($videoUrl) . '" data-poster="' . esc_url($posterUrl) . '"'
                : ' src="' . esc_url($videoUrl) . '" poster="' . esc_url($posterUrl) . '"';
            $trackAttributes = $completeLibrary
                ? ' data-src="' . esc_url($captionUrl) . '"'
                : ' src="' . esc_url($captionUrl) . '"';

            $html .= '<article class="h4-tutorial-video" id="h4-video-' . esc_attr($slug) . '" data-h4bs-tutorial-video="' . esc_attr((string) $number) . '">'
                . '<div class="h4-tutorial-video__media"><video controls playsinline preload="' . esc_attr($preload) . '"' . $mediaAttributes . ' aria-label="' . esc_attr($title) . '" aria-describedby="' . esc_attr($descriptionId) . '">'
                . '<track kind="captions"' . $trackAttributes . ' srclang="en" label="English" default>'
                . '<a href="' . esc_url($videoUrl) . '">Download the narrated tutorial video.</a>'
                . '</video><noscript><p><a href="' . esc_url($videoUrl) . '">Download the narrated tutorial video.</a></p></noscript></div>'
                . '<div class="h4-tutorial-video__copy"><p class="h4-tutorial-video__number">Lesson ' . esc_html((string) $number) . '</p>'
                . '<h3>' . esc_html($title) . '</h3><p id="' . esc_attr($descriptionId) . '">' . esc_html($description) . '</p>'
                . '<p><a class="button" href="' . esc_url(home_url($guidePath)) . '">Open the written guide</a></p>'
                . '<details><summary>Read the complete transcript</summary><ol>';
            foreach ($segments as $index => $segment) {
                if (! is_array($segment)) {
                    continue;
                }
                $label = sanitize_text_field((string) ($segment['label'] ?? 'Step ' . ($index + 1)));
                $narration = sanitize_text_field((string) ($segment['narration'] ?? ''));
                $html .= '<li><strong>' . esc_html($label) . '</strong><p>' . esc_html($narration) . '</p></li>';
            }
            $html .= '</ol></details></div></article>';
        }

        return $html . '</div></section><!-- H4 TUTORIAL VIDEO END -->';
    }

    /**
     * Keep the Help4 product and learning paths in the bounded LLM discovery guide.
     *
     * @param array<int, string> $slugs
     * @return array<int, string>
     */
    public function prioritizeLlmsPages(array $slugs): array
    {
        if (! $this->isHelp4WordPressMarketingSite()) {
            return $slugs;
        }

        return array_values(array_unique(array_merge(
            $slugs,
            [
                'free-wordpress-builder',
                'plugins',
                'plugin-help4-builder-suite',
                'help4-builder-tutorials',
                'help4-builder-template-library',
                'help4-builder-beginner-templates',
                'help4-builder-quick-help',
                'help4-builder-find-settings',
                'help4-product-insights-download-stats',
                'help4-builder-site-kits-starter-sites',
                'help4-builder-widget-library',
                'help4-builder-video-hls-backgrounds',
                'help4-builder-sections-containers-columns',
                'help4-builder-custom-css-advanced-controls',
                'help4-builder-buttons-typography-spacing',
                'help4-builder-accessibility-audit',
                'help4-builder-menus-headers-footers',
                'help4-builder-forms-lead-capture',
                'help4-seo-local-international-indexnow',
                'help4-commerce-products-variations-customer-fields',
                'help4-email-marketing-newsletters-drip-campaigns',
                'help4-email-marketing-first-campaign',
                'help4-email-marketing-reports-automations',
                'help4-security-hardening-guide',
                'help4-performance-cache-assets-guide',
                'stripe-router-tutorial',
                'stripe-router-pro-vs-enterprise',
                'help4-net-wordpress-cdn-waf',
                'wordpress-hosting',
                'wordpress-support-services',
            ]
        )));
    }

    public function renderTutorialCatalogSchema(): void
    {
        if (! $this->isHelp4WordPressMarketingSite() || ! is_singular('page')) {
            return;
        }

        $isHub = is_page('help4-builder-tutorials');
        $graph = [];
        if ($isHub) {
            $items = [];
            foreach ($this->h4BuilderTutorialCards() as $position => $card) {
                $url = esc_url_raw((string) ($card[3] ?? ''), ['http', 'https']);
                $name = sanitize_text_field((string) ($card[1] ?? ''));
                if ($url === '' || $name === '') {
                    continue;
                }
                $items[] = [
                    '@type' => 'ListItem',
                    'position' => $position + 1,
                    'name' => $name,
                    'url' => $url,
                ];
            }

            if ($items !== []) {
                $graph[] = [
                    '@type' => 'ItemList',
                    '@id' => home_url('/help4-builder-tutorials/#guide-catalog'),
                    'name' => 'Help4 Builder Suite tutorial library',
                    'numberOfItems' => count($items),
                    'itemListElement' => $items,
                ];
            }
        }

        $videoCatalog = $this->h4BuilderTutorialVideoCatalog();
        $videoNumbers = $isHub
            ? array_keys($videoCatalog)
            : $this->h4BuilderTutorialVideoNumbersForContext((string) get_the_title() . ' ' . (string) get_post_field('post_name'));
        $videoBase = $this->h4BuilderTutorialVideoMediaBaseUrl();
        $posterBase = trailingslashit(H4BS_URL . 'assets/tutorial-videos/2026-08');
        foreach ($videoNumbers as $number) {
            $video = $videoCatalog[absint($number)] ?? null;
            if (! is_array($video)) {
                continue;
            }
            $segments = is_array($video['segments'] ?? null) ? $video['segments'] : [];
            $transcript = [];
            foreach ($segments as $segment) {
                if (is_array($segment) && ! empty($segment['narration'])) {
                    $transcript[] = sanitize_text_field((string) $segment['narration']);
                }
            }
            $slug = sanitize_title((string) ($video['slug'] ?? 'tutorial-' . absint($number)));
            $graph[] = [
                '@type' => 'VideoObject',
                '@id' => home_url('/help4-builder-tutorials/#h4-video-' . $slug),
                'name' => sanitize_text_field((string) ($video['title'] ?? 'Help4 Builder tutorial')),
                'description' => sanitize_text_field((string) ($video['description'] ?? '')),
                'thumbnailUrl' => [$posterBase . sanitize_file_name((string) ($video['poster'] ?? ''))],
                'uploadDate' => '2026-08-06T00:00:00-04:00',
                'duration' => sanitize_text_field((string) ($video['duration'] ?? '')),
                'contentUrl' => $videoBase . sanitize_file_name((string) ($video['filename'] ?? '')),
                'inLanguage' => 'en-US',
                'transcript' => implode(' ', $transcript),
                'isFamilyFriendly' => true,
            ];
        }

        if ($graph === [] || ! RobotsContract::isIndexable()) {
            return;
        }

        $schema = ['@context' => 'https://schema.org', '@graph' => $graph];

        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON_HEX flags protect the structured JSON script context.
        echo '<script type="application/ld+json" class="h4bs-tutorial-catalog-schema">' . wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) . "</script>\n";
    }

    public function registerAdminPage(): void
    {
        add_submenu_page(
            'h4bs-settings',
            __('Demo Lab', 'help4-builder-suite'),
            __('Demo Lab', 'help4-builder-suite'),
            'manage_options',
            'h4bs-demo-lab',
            [$this, 'renderAdminPage']
        );
    }

    public function registerShowcaseToolsPages(): void
    {
        if (! $this->isStagingShowcaseMode()) {
            return;
        }

        add_management_page(
            __('Help4 Showcase Tools', 'help4-builder-suite'),
            __('Help4 Showcase', 'help4-builder-suite'),
            'manage_options',
            'h4bs-showcase-tools',
            [$this, 'renderShowcaseToolsPage']
        );

        add_submenu_page(
            'tools.php',
            __('Showcase: Layout + Content', 'help4-builder-suite'),
            __('Help4 Layout Gallery', 'help4-builder-suite'),
            'manage_options',
            'h4bs-showcase-layout-content',
            [$this, 'renderShowcaseLayoutToolsPage']
        );
        add_submenu_page(
            'tools.php',
            __('Showcase: Media + Motion', 'help4-builder-suite'),
            __('Help4 Media Gallery', 'help4-builder-suite'),
            'manage_options',
            'h4bs-showcase-media-motion',
            [$this, 'renderShowcaseMediaToolsPage']
        );
        add_submenu_page(
            'tools.php',
            __('Showcase: Commerce + Payments', 'help4-builder-suite'),
            __('Help4 Commerce Gallery', 'help4-builder-suite'),
            'manage_options',
            'h4bs-showcase-commerce-payments',
            [$this, 'renderShowcaseCommerceToolsPage']
        );
        add_submenu_page(
            'tools.php',
            __('Showcase: SEO + Security', 'help4-builder-suite'),
            __('Help4 SEO/Security Gallery', 'help4-builder-suite'),
            'manage_options',
            'h4bs-showcase-seo-security',
            [$this, 'renderShowcaseSeoToolsPage']
        );
    }

    public function handleGenerateGroupedShowcase(): void
    {
        if (! current_user_can('manage_options') || ! $this->isStagingShowcaseMode()) {
            wp_die(esc_html__('Unauthorized request.', 'help4-builder-suite'));
        }
        check_admin_referer('h4bs_generate_grouped_showcase', 'h4bs_generate_grouped_showcase_nonce');

        $sliderId = $this->seedSlider();
        $this->seedShowcasePages($sliderId);
        $this->seedGroupedShowcasePages($sliderId);
        set_transient('h4bs_demo_lab_notice', __('Grouped showcase pages were generated.', 'help4-builder-suite'), 30);

        wp_safe_redirect(admin_url('tools.php?page=h4bs-showcase-tools'));
        exit;
    }

    public function renderShowcaseToolsPage(): void
    {
        if (! current_user_can('manage_options')) {
            return;
        }
        $links = $this->showcasePageLinks();
        ?>
        <div class="wrap h4bs-admin-wrap">
            <h1><?php esc_html_e('Help4 Showcase Tools', 'help4-builder-suite'); ?></h1>
            <p><?php esc_html_e('Generate grouped feature gallery pages for an approved Help4 beta install only.', 'help4-builder-suite'); ?></p>
            <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
                <?php wp_nonce_field('h4bs_generate_grouped_showcase', 'h4bs_generate_grouped_showcase_nonce'); ?>
                <input type="hidden" name="action" value="h4bs_generate_grouped_showcase">
                <?php submit_button(__('Generate / Refresh Grouped Showcase Pages', 'help4-builder-suite')); ?>
            </form>
            <h2><?php esc_html_e('Open Showcase Pages', 'help4-builder-suite'); ?></h2>
            <ul>
                <?php foreach ($links as $label => $url) : ?>
                    <li><a href="<?php echo esc_url($url); ?>" target="_blank" rel="noopener"><?php echo esc_html($label); ?></a></li>
                <?php endforeach; ?>
            </ul>
        </div>
        <?php
    }

    public function renderShowcaseLayoutToolsPage(): void
    {
        $this->renderShowcaseLinkCard(
            __('Layout + Content Gallery', 'help4-builder-suite'),
            home_url('/help4-gallery-layout-content/'),
            __('Sections, inner sections, containers, text, spacing, and structural elements.', 'help4-builder-suite')
        );
    }

    public function renderShowcaseMediaToolsPage(): void
    {
        $this->renderShowcaseLinkCard(
            __('Media + Motion Gallery', 'help4-builder-suite'),
            home_url('/help4-gallery-media-motion/'),
            __('Image, gallery, video, slider, icon, CTA, quote, and visual modules.', 'help4-builder-suite')
        );
    }

    public function renderShowcaseCommerceToolsPage(): void
    {
        $this->renderShowcaseLinkCard(
            __('Commerce + Payments Gallery', 'help4-builder-suite'),
            home_url('/help4-gallery-commerce-payments/'),
            __('Product/search/checkout bridge, payment-routing, and commerce flow examples.', 'help4-builder-suite')
        );
    }

    public function renderShowcaseSeoToolsPage(): void
    {
        $this->renderShowcaseLinkCard(
            __('SEO + Security Gallery', 'help4-builder-suite'),
            home_url('/help4-gallery-seo-security/'),
            __('FAQ/schema-style content, counters/progress metrics, maps, and security/SEO messaging blocks.', 'help4-builder-suite')
        );
    }

    private function renderShowcaseLinkCard(string $title, string $url, string $description): void
    {
        if (! current_user_can('manage_options')) {
            return;
        }
        ?>
        <div class="wrap h4bs-admin-wrap">
            <h1><?php echo esc_html($title); ?></h1>
            <p><?php echo esc_html($description); ?></p>
            <p><a class="button button-primary" href="<?php echo esc_url($url); ?>" target="_blank" rel="noopener"><?php esc_html_e('Open Front-End Gallery Page', 'help4-builder-suite'); ?></a></p>
            <p><a class="button" href="<?php echo esc_url(admin_url('tools.php?page=h4bs-showcase-tools')); ?>"><?php esc_html_e('Back to Help4 Showcase Tools', 'help4-builder-suite'); ?></a></p>
        </div>
        <?php
    }

    private function isStagingShowcaseMode(): bool
    {
        $host = wp_parse_url(home_url('/'), PHP_URL_HOST);
        return is_string($host) && strtolower($host) === 'md.help4wordpress.com';
    }

    private function isHelp4WordPressMarketingSite(): bool
    {
        $host = wp_parse_url(home_url('/'), PHP_URL_HOST);
        if (! is_string($host)) {
            return false;
        }

        return in_array(strtolower($host), ['help4wordpress.com', 'www.help4wordpress.com', 'md.help4wordpress.com'], true);
    }

    /**
     * @return array<string, string>
     */
    private function showcasePageLinks(): array
    {
        return [
            'Help4 Builder Landing' => home_url('/help4-builder/'),
            'Elements Gallery' => home_url('/help4-builder-elements-gallery/'),
            'Layout + Content Gallery' => home_url('/help4-gallery-layout-content/'),
            'Media + Motion Gallery' => home_url('/help4-gallery-media-motion/'),
            'Commerce + Payments Gallery' => home_url('/help4-gallery-commerce-payments/'),
            'SEO + Security Gallery' => home_url('/help4-gallery-seo-security/'),
            'Download Page' => home_url('/help4-builder-download/'),
            'Screenshots Page' => home_url('/help4-builder-screenshots/'),
        ];
    }

    public function renderAdminPage(): void
    {
        if (! current_user_can('manage_options')) {
            return;
        }
        $last = (string) get_option('h4bs_demo_seed_last_run', '');
        ?>
        <div class="wrap h4bs-admin-wrap">
            <h1><?php esc_html_e('Help4 Demo Lab', 'help4-builder-suite'); ?></h1>
            <p><?php esc_html_e('Seed demo content for builder, templates, slider, products, search, and checkout testing.', 'help4-builder-suite'); ?></p>
            <p><?php echo $last !== '' ? esc_html__('Last seeded:', 'help4-builder-suite') . ' ' . esc_html($last) : esc_html__('No demo seed has run yet.', 'help4-builder-suite'); ?></p>
            <h2><?php esc_html_e('Core Seed', 'help4-builder-suite'); ?></h2>
            <form method="post">
                <?php wp_nonce_field('h4bs_seed_demo_lab', 'h4bs_seed_demo_lab_nonce'); ?>
                <input type="hidden" name="h4bs_demo_action" value="seed_core_demo">
                <?php submit_button(__('Seed Core Demos', 'help4-builder-suite')); ?>
            </form>
            <h2><?php esc_html_e('Help4WordPress Demo Sync', 'help4-builder-suite'); ?></h2>
            <p><?php esc_html_e('Copies public pages from help4wordpress.com into the approved beta install and rewrites commerce links to Help4 WordPress checkout endpoints.', 'help4-builder-suite'); ?></p>
            <form method="post">
                <?php wp_nonce_field('h4bs_seed_demo_lab', 'h4bs_seed_demo_lab_nonce'); ?>
                <input type="hidden" name="h4bs_demo_action" value="seed_help4wordpress_demo">
                <?php submit_button(__('Sync Help4WordPress Demo', 'help4-builder-suite'), 'secondary'); ?>
            </form>
        </div>
        <?php
    }

    public function handleActions(): void
    {
        if (! current_user_can('manage_options')) {
            return;
        }
        if (! isset($_POST['h4bs_demo_action'])) {
            return;
        }
        check_admin_referer('h4bs_seed_demo_lab', 'h4bs_seed_demo_lab_nonce');

        $action = sanitize_key((string) wp_unslash($_POST['h4bs_demo_action']));
        if ($action === 'seed_core_demo') {
            $sliderId = $this->seedSlider();
            $this->seedProducts(24);
            $this->seedFeaturePages($sliderId);
            set_transient('h4bs_demo_lab_notice', __('Core demos seeded successfully.', 'help4-builder-suite'), 30);
        } elseif ($action === 'seed_help4wordpress_demo') {
            $count = $this->syncHelp4wordpressDemoSite();
            if ($count > 0) {
                set_transient(
                    'h4bs_demo_lab_notice',
                    sprintf(
                        /* translators: %d imported pages */
                        __('Help4WordPress demo synced (%d pages updated).', 'help4-builder-suite'),
                        $count
                    ),
                    30
                );
            } else {
                set_transient(
                    'h4bs_demo_lab_notice',
                    __('Help4WordPress sync could not pull live pages. Fallback pages were generated for demo use.', 'help4-builder-suite'),
                    30
                );
            }
        } else {
            return;
        }

        update_option('h4bs_demo_seed_last_run', gmdate('Y-m-d H:i:s') . ' UTC');

        wp_safe_redirect(admin_url('admin.php?page=h4bs-demo-lab'));
        exit;
    }

    public function maybeAutoBootstrapStagingDemo(): void
    {
        if (! is_admin() || wp_doing_ajax()) {
            return;
        }
        if (! current_user_can('manage_options') || ! $this->isHelp4WordPressMarketingSite()) {
            return;
        }
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This only skips auto-bootstrap when a separate admin form action is present.
        if (isset($_POST['h4bs_demo_action'])) {
            return;
        }

        $versionMarker = defined('H4BS_VERSION') ? (string) H4BS_VERSION : 'dev';
        $bootstrappedVersion = (string) get_option('h4bs_demo_sync_bootstrapped', '');
        if ($bootstrappedVersion === $versionMarker) {
            return;
        }

        if (! $this->isStagingShowcaseMode()) {
            $this->seedExternalCommerceBridgePages();
            $this->ensureGlobalThemeBuilderTemplates();
            update_option('h4bs_demo_sync_bootstrapped', $versionMarker);
            return;
        }

        // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- One-row bootstrap marker lookup for demo import state.
        $hasImportedPage = get_posts(
            [
                'post_type'      => 'page',
                'posts_per_page' => 1,
                'post_status'    => ['publish', 'draft', 'private', 'pending', 'future'],
                'fields'         => 'ids',
                'meta_key'       => '_h4_imported_help4wp',
                'meta_value'     => '1',
            ]
        );
        // phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value

        if (is_array($hasImportedPage) && ! empty($hasImportedPage[0])) {
            $this->seedExternalCommerceBridgePages();
            $this->ensureGlobalThemeBuilderTemplates();
            update_option('h4bs_demo_sync_bootstrapped', $versionMarker);
            return;
        }

        $count = $this->syncHelp4wordpressDemoSite();
        update_option('h4bs_demo_sync_bootstrapped', $versionMarker);

        if ($count > 0) {
            set_transient(
                'h4bs_demo_lab_notice',
                sprintf(
                    /* translators: %d imported pages */
                    __('Staging auto-sync complete (%d pages imported from help4wordpress.com).', 'help4-builder-suite'),
                    $count
                ),
                30
            );
            return;
        }

        set_transient(
            'h4bs_demo_lab_notice',
            __('Staging auto-sync used fallback content because live pages could not be fetched.', 'help4-builder-suite'),
            30
        );
    }

    public function maybeAutoRefreshMarketingSeed(): void
    {
        if (is_admin() || wp_doing_ajax() || wp_doing_cron() || ! $this->isHelp4WordPressMarketingSite()) {
            return;
        }

        $versionMarker = defined('H4BS_VERSION') ? (string) H4BS_VERSION : 'dev';
        $seedMarker = (string) get_option('h4bs_marketing_seed_bootstrapped', '');
        if ($seedMarker === $versionMarker) {
            return;
        }

        $this->seedHelp4wordpressSalesPages();
        $this->ensureGlobalThemeBuilderTemplates();
        $this->ensureMarketingHomeUsesGlobalChrome();
        $this->deduplicatePrimaryMenuLinks();
        update_option('h4bs_marketing_seed_bootstrapped', $versionMarker);
    }

    public function runMarketingMaintenance(): void
    {
        if (! $this->isHelp4WordPressMarketingSite()) {
            return;
        }

        $this->refreshBuilderStudioScreenshotUrls();
        $this->deduplicatePrimaryMenuLinks();
    }

    /**
     * @return array<string, mixed>
     */
    public function refreshMarketingContent(bool $dryRun = false): array
    {
        if (! $this->isHelp4WordPressMarketingSite()) {
            return [
                'ok' => false,
                'code' => 'unsupported_host',
            ];
        }

        $guideSlugs = array_keys($this->h4BuilderOperationsGuideCatalog());
        if (! $dryRun) {
            $this->seedHelp4wordpressSalesPages();
            $this->seedExternalCommerceBridgePages();
            $this->ensureGlobalThemeBuilderTemplates();
            $this->ensureMarketingHomeUsesGlobalChrome();
            $this->deduplicatePrimaryMenuLinks();
            $versionMarker = defined('H4BS_VERSION') ? (string) H4BS_VERSION : 'dev';
            update_option('h4bs_demo_sync_bootstrapped', $versionMarker);
            update_option('h4bs_marketing_seed_bootstrapped', $versionMarker);
        }

        $hub = get_page_by_path('help4-builder-tutorials', OBJECT, 'page');
        $hubContent = $hub instanceof \WP_Post ? (string) $hub->post_content : '';
        $guideIds = [];
        $missing = [];
        foreach ($guideSlugs as $slug) {
            $page = get_page_by_path($slug, OBJECT, 'page');
            if ($page instanceof \WP_Post && $page->post_status === 'publish') {
                $guideIds[$slug] = (int) $page->ID;
                continue;
            }
            $missing[] = $slug;
        }

        return [
            'ok' => true,
            'dry_run' => $dryRun,
            'version' => defined('H4BS_VERSION') ? (string) H4BS_VERSION : 'dev',
            'hub_id' => $hub instanceof \WP_Post ? (int) $hub->ID : 0,
            'hub_search_roots' => substr_count($hubContent, 'data-h4-doc-search-root'),
            'hub_search_items' => substr_count($hubContent, 'data-h4-doc-item'),
            'expected_search_items' => count($this->h4BuilderTutorialCards()),
            'hub_video_lessons' => substr_count($hubContent, 'data-h4bs-tutorial-video'),
            'hub_caption_tracks' => substr_count($hubContent, 'kind="captions"'),
            'hub_transcripts' => substr_count($hubContent, 'Read the complete transcript'),
            'expected_video_lessons' => count($this->h4BuilderTutorialVideoCatalog()),
            'guided_screen_assets' => count($this->h4BuilderGuidedScreenCatalog()),
            'managed_guides' => count($guideSlugs),
            'published_guide_ids' => $guideIds,
            'missing_guides' => $missing,
        ];
    }

    private function refreshBuilderStudioScreenshotUrls(): void
    {
        $replacement = '/wp-content/plugins/help4-builder-suite/assets/demo/builder-studio-workspace-20260716.png';
        $oldRelative = '/wp-content/uploads/help4-tutorial-screens/2026-05/h4bs-builder-studio-default-crop-20260515.png';
        $slugs = [
            'help4-builder',
            'help4-builder-screenshots',
            'help4-builder-tutorials',
            'plugin-help4-builder-suite',
        ];

        foreach ($slugs as $slug) {
            $page = get_page_by_path($slug, OBJECT, 'page');
            if (! $page instanceof \WP_Post) {
                continue;
            }

            $content = (string) $page->post_content;
            $updated = (string) preg_replace(
                '~https?://[^\s"\'<>]+/wp-content/uploads/help4-tutorial-screens/2026-05/h4bs-builder-studio-default-crop-20260515\.png~i',
                $replacement,
                $content
            );
            $updated = str_replace($oldRelative, $replacement, $updated);
            if ($updated !== $content) {
                wp_update_post([
                    'ID'           => (int) $page->ID,
                    'post_content' => $updated,
                ]);
            }

            $layout = get_post_meta((int) $page->ID, '_h4_builder_layout', true);
            if (! is_string($layout) || $layout === '') {
                continue;
            }
            $layoutData = json_decode($layout, true);
            if (! is_array($layoutData)) {
                continue;
            }
            $encodedLayout = wp_json_encode($layoutData, JSON_UNESCAPED_SLASHES);
            if (! is_string($encodedLayout) || $encodedLayout === '') {
                continue;
            }
            $updatedLayout = (string) preg_replace(
                '~https?://[^\s"\'<>]+/wp-content/uploads/help4-tutorial-screens/2026-05/h4bs-builder-studio-default-crop-20260515\.png~i',
                $replacement,
                $encodedLayout
            );
            $updatedLayout = str_replace($oldRelative, $replacement, $updatedLayout);
            if ($updatedLayout !== $encodedLayout) {
                $validatedLayout = json_decode($updatedLayout, true);
                if (is_array($validatedLayout)) {
                    update_post_meta(
                        (int) $page->ID,
                        '_h4_builder_layout',
                        wp_json_encode($validatedLayout, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
                    );
                }
            }
        }
    }

    public function renderNotice(): void
    {
        if (! current_user_can('manage_options')) {
            return;
        }
        $notice = get_transient('h4bs_demo_lab_notice');
        if (! is_string($notice) || $notice === '') {
            return;
        }
        delete_transient('h4bs_demo_lab_notice');
        printf('<div class="notice notice-success is-dismissible"><p>%s</p></div>', esc_html($notice));
    }

    /**
     * @param array<int, string> $classes
     * @return array<int, string>
     */
    public function addMirrorBodyClass(array $classes): array
    {
        if ($this->currentRequestIsMirroredPage()) {
            $classes[] = 'h4bs-mirror-page';
        }

        if ($this->isHelp4WordPressMarketingSite()) {
            if (is_front_page()) {
                $classes[] = 'h4wp-sales-light';
                $classes[] = 'h4wp-sales-home-page';
            } elseif (is_page('packages')) {
                $classes[] = 'h4wp-sales-light';
                $classes[] = 'h4wp-sales-packages-page';
            } elseif (is_page('shop')) {
                $classes[] = 'h4wp-sales-light';
                $classes[] = 'h4wp-sales-shop-page';
            } elseif (is_page('fully-managed-wordpress-hosting')) {
                $classes[] = 'h4wp-sales-light';
                $classes[] = 'h4wp-sales-managed-page';
            }
        }

        return array_values(array_unique($classes));
    }

    public function renderMirroredContent(string $content): string
    {
        if (is_admin() || wp_doing_ajax() || is_feed()) {
            return $content;
        }
        if (! is_singular() || ! in_the_loop() || ! is_main_query()) {
            return $content;
        }

        $postId = get_queried_object_id();
        if (! $postId || ! $this->isMirroredPage($postId)) {
            return $content;
        }

        $builderEnabled = (string) get_post_meta($postId, '_h4_builder_enabled', true) === '1'
            && (string) get_post_meta($postId, '_h4_builder_mode', true) === 'help4';
        if ($builderEnabled) {
            return $content;
        }

        $mirrorHtml = (string) get_post_meta($postId, '_h4_mirror_html', true);
        $mirrorHtml = trim($mirrorHtml);
        if ($mirrorHtml === '') {
            return $content;
        }

        $mirrorHtml = $this->normalizeMirroredMarkup($mirrorHtml);
        $mirrorHtml = $this->stripMirrorOnlyPromoSections($mirrorHtml);
        $mirrorHtml = $this->rewriteCommerceLinks($mirrorHtml);
        $rendered = '<div class="h4bs-mirror-content" data-h4bs-mirror-content="1">' . $mirrorHtml . '</div>';
        $token = sprintf('%%H4BS_MIRROR_%d_%s%%', (int) $postId, substr(md5($rendered), 0, 12));
        self::$mirrorTokens[$token] = $rendered;

        return $token;
    }

    public function restoreMirroredContentAfterFilters(string $content): string
    {
        if ($content === '' || self::$mirrorTokens === []) {
            return $content;
        }

        foreach (self::$mirrorTokens as $token => $rendered) {
            if (! str_contains($content, $token)) {
                continue;
            }

            $wrappedNeedles = [
                '<p>' . $token . '</p>',
                "<p>\n" . $token . "\n</p>",
                "<p>\r\n" . $token . "\r\n</p>",
                '<p>' . "\n" . $token . "\n" . '</p>',
                '<p>' . "\r\n" . $token . "\r\n" . '</p>',
            ];
            $content = str_replace($wrappedNeedles, $rendered, $content);
            $content = str_replace($token, $rendered, $content);
            unset(self::$mirrorTokens[$token]);
        }

        return $content;
    }

    private function normalizeMirroredMarkup(string $html): string
    {
        $html = trim($html);
        if ($html === '') {
            return '';
        }

        if (preg_match('#<body[^>]*>(.*)</body>#is', $html, $matches) === 1 && isset($matches[1])) {
            $bodyInner = trim((string) $matches[1]);
            if ($bodyInner !== '') {
                return $bodyInner;
            }
        }

        if (preg_match('#<html[^>]*>(.*)</html>#is', $html, $matches) === 1 && isset($matches[1])) {
            $htmlInner = trim((string) $matches[1]);
            if ($htmlInner !== '') {
                return $htmlInner;
            }
        }

        return $html;
    }

    private function stripMirrorOnlyPromoSections(string $mirrorHtml): string
    {
        if (! str_contains($mirrorHtml, 'h4bs-optimized-screen-section')) {
            return $mirrorHtml;
        }

        $cleaned = preg_replace(
            '#<section[^>]*class="[^"]*h4bs-optimized-screen-section[^"]*"[^>]*>.*?</section>#is',
            '',
            $mirrorHtml
        );

        return is_string($cleaned) ? $cleaned : $mirrorHtml;
    }

    public function enqueueMirroredAssets(): void
    {
        if (! is_singular()) {
            return;
        }

        $postId = get_queried_object_id();
        if (! $postId || ! $this->isMirroredPage($postId)) {
            return;
        }

        $styles = $this->loadMirrorAssetList($postId, '_h4_mirror_styles');
        $scripts = $this->loadMirrorAssetList($postId, '_h4_mirror_scripts');
        $inlineCss = (string) get_post_meta($postId, '_h4_mirror_inline_css', true);
        $inlineJs = '';
        $inlineCss = $this->rewriteMainSiteLinksToLocal($inlineCss);

        foreach ($styles as $index => $styleUrl) {
            $styleUrl = $this->rewriteMainSiteLinksToLocal($styleUrl);
            if ($this->shouldSkipMirrorStyle($styleUrl) || $this->mirrorAssetAlreadyRegistered($styleUrl, 'style')) {
                continue;
            }
            wp_enqueue_style(
                'h4bs-mirror-style-' . $postId . '-' . $index,
                $styleUrl,
                [],
                H4BS_VERSION
            );
        }
        $fontAwesomeHandle = 'h4bs-fontawesome-free-frontend';
        if (! wp_style_is($fontAwesomeHandle, 'enqueued')) {
            $fontAwesomeHandle = 'h4bs-mirror-fa-local';
            wp_enqueue_style(
                $fontAwesomeHandle,
                H4BS_URL . 'assets/vendor/fontawesome/css/help4-fa-local.css',
                [],
                H4BS_VERSION
            );
        }
        wp_enqueue_style('dashicons');
        wp_enqueue_style(
            'h4bs-mirror-redesign',
            H4BS_URL . 'assets/css/mirror-redesign.css',
            [$fontAwesomeHandle, 'dashicons'],
            H4BS_VERSION
        );

        $scriptHandles = [];
        $mirrorBootstrapHandle = 'h4bs-mirror-bootstrap-' . $postId;
        wp_register_script($mirrorBootstrapHandle, '', [], H4BS_VERSION, true);
        wp_enqueue_script($mirrorBootstrapHandle);
        wp_add_inline_script(
            $mirrorBootstrapHandle,
            '(function(){'
            . 'window.elementorFrontendConfig=window.elementorFrontendConfig||{};'
            . 'window.ElementorProFrontendConfig=window.ElementorProFrontendConfig||{};'
            . 'window.elementorFrontend=window.elementorFrontend||{};'
            . 'window.elementorModules=window.elementorModules||{};'
            . 'window.elementor=window.elementor||{};'
            . '})();'
        );

        foreach ($scripts as $index => $scriptUrl) {
            $scriptUrl = $this->rewriteMainSiteLinksToLocal($scriptUrl);
            if ($this->shouldSkipMirrorScript($scriptUrl) || $this->mirrorAssetAlreadyRegistered($scriptUrl, 'script')) {
                continue;
            }
            $handle = 'h4bs-mirror-script-' . $postId . '-' . $index;
            wp_enqueue_script(
                $handle,
                $scriptUrl,
                [$mirrorBootstrapHandle],
                H4BS_VERSION,
                true
            );
            $scriptHandles[] = $handle;
        }

        wp_register_style('h4bs-mirror-runtime', false, [], H4BS_VERSION);
        wp_enqueue_style('h4bs-mirror-runtime');

        $baselineCss = '
            body.h4bs-mirror-page {
                background: transparent !important;
                overflow-x: hidden;
            }
            body.h4bs-mirror-page .site-main {
                width: 100% !important;
                max-width: none !important;
                padding: 0 !important;
                margin: 0 !important;
                background: transparent !important;
            }
            body.h4bs-mirror-page .content-panel {
                width: 100% !important;
                max-width: none !important;
                border: 0 !important;
                box-shadow: none !important;
                border-radius: 0 !important;
                padding: 0 !important;
                background: transparent !important;
            }
            body.h4bs-mirror-page .site-header,
            body.h4bs-mirror-page .site-footer {
                display: none !important;
            }
            body.h4bs-mirror-page .h4bs-template-slot-header,
            body.h4bs-mirror-page .h4bs-template-slot-footer {
                display: block !important;
            }
            body.h4bs-mirror-page .h4bs-mirror-content {
                width: 100%;
                max-width: 100%;
                overflow-x: hidden;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-location-header,
            body.h4bs-mirror-page .h4bs-mirror-content .elementor.elementor-location-header,
            body.h4bs-mirror-page .h4bs-mirror-content .hfe-header-wrap,
            body.h4bs-mirror-page .h4bs-mirror-content header.hfe-header {
                display: none !important;
            }
            body.h4bs-mirror-page .h4bs-mirror-content i.fas,
            body.h4bs-mirror-page .h4bs-mirror-content i.fa-solid,
            body.h4bs-mirror-page .h4bs-mirror-content i.fa,
            body.h4bs-mirror-page .elementor i.fas,
            body.h4bs-mirror-page .elementor i.fa-solid,
            body.h4bs-mirror-page .elementor i.fa {
                font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons" !important;
                font-weight: 900 !important;
            }
            body.h4bs-mirror-page .h4bs-mirror-content i.far,
            body.h4bs-mirror-page .h4bs-mirror-content i.fa-regular,
            body.h4bs-mirror-page .elementor i.far,
            body.h4bs-mirror-page .elementor i.fa-regular {
                font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons" !important;
                font-weight: 400 !important;
            }
            body.h4bs-mirror-page .h4bs-mirror-content i.fab,
            body.h4bs-mirror-page .h4bs-mirror-content i.fa-brands,
            body.h4bs-mirror-page .elementor i.fab,
            body.h4bs-mirror-page .elementor i.fa-brands {
                font-family: "Font Awesome 5 Brands", "Font Awesome 6 Brands", "dashicons" !important;
                font-weight: 400 !important;
            }
            body.h4bs-mirror-page .h4bs-mirror-content i.eicon-lock::before { content: "\f023"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .h4bs-mirror-content i.eicon-plus::before { content: "\2b"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .h4bs-mirror-content i.eicon-mail::before { content: "\f0e0"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .h4bs-mirror-content i.eicon-chevron-left::before { content: "\f053"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .h4bs-mirror-content i.eicon-chevron-right::before { content: "\f054"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .h4bs-mirror-content i.eicon-star::before { content: "\f005"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .elementor i.eicon-lock::before { content: "\f023"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .elementor i.eicon-plus::before { content: "\2b"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .elementor i.eicon-mail::before { content: "\f0e0"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .elementor i.eicon-chevron-left::before { content: "\f053"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .elementor i.eicon-chevron-right::before { content: "\f054"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .elementor i.eicon-star::before { content: "\f005"; font-family: "Font Awesome 5 Free", "Font Awesome 6 Free", "dashicons"; font-weight: 900; }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-star-rating i {
                position: relative;
                display: inline-block;
                width: 1em;
                height: 1em;
                overflow: hidden;
                text-indent: -9999px;
                line-height: 1;
            }
            body.h4bs-mirror-page .elementor .elementor-star-rating i {
                position: relative;
                display: inline-block;
                width: 1em;
                height: 1em;
                overflow: hidden;
                text-indent: -9999px;
                line-height: 1;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-star-rating i::before {
                content: "\2605";
                position: absolute;
                left: 0;
                top: 0;
                text-indent: 0;
                color: #f5b301;
            }
            body.h4bs-mirror-page .elementor .elementor-star-rating i::before {
                content: "\2605";
                position: absolute;
                left: 0;
                top: 0;
                text-indent: 0;
                color: #f5b301;
            }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fas::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-solid::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.far::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-regular::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fab::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-brands::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fas::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-solid::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.far::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-regular::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fab::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-brands::before {
                font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", sans-serif !important;
                font-weight: 400 !important;
                line-height: 1;
                speak: none;
            }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-ticket-alt::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-ticket-alt::before { content: "\1F3AB"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-mail-bulk::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-mail-bulk::before { content: "\2709"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-toolbox::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-toolbox::before { content: "\1F9F0"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-tools::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-tools::before { content: "\1F6E0"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-hand-holding-heart::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-hand-holding-heart::before { content: "\1F91D"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-server::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-server::before { content: "\1F5A5"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-lock::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-lock::before { content: "\1F512"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-shipping-fast::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-shipping-fast::before { content: "\1F69A"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-check::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-check::before { content: "\2713"; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-facebook::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-facebook::before { content: "f"; font-family: "Inter", "Segoe UI", sans-serif !important; font-weight: 700 !important; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-yelp::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-yelp::before { content: "y"; font-family: "Inter", "Segoe UI", sans-serif !important; font-weight: 700 !important; }
            body.h4bs-mirror-page.h4bs-mirror-no-fa .h4bs-mirror-content i.fa-google::before,
            body.h4bs-mirror-page.h4bs-mirror-no-fa .elementor i.fa-google::before { content: "G"; font-family: "Inter", "Segoe UI", sans-serif !important; font-weight: 700 !important; }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-main-swiper,
            body.h4bs-mirror-page .elementor .elementor-main-swiper,
            body.h4bs-mirror-page .h4bs-mirror-content .swiper-container {
                position: relative;
                overflow: hidden;
            }
            body.h4bs-mirror-page .elementor .swiper-container {
                position: relative;
                overflow: hidden;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .swiper-container.h4bs-mirror-fallback:not(.h4bs-mirror-fallback-review) .swiper-slide {
                display: none;
            }
            body.h4bs-mirror-page .elementor .swiper-container.h4bs-mirror-fallback:not(.h4bs-mirror-fallback-review) .swiper-slide {
                display: none;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .swiper-container.h4bs-mirror-fallback:not(.h4bs-mirror-fallback-review) .swiper-slide.h4bs-mirror-slide-active,
            body.h4bs-mirror-page .h4bs-mirror-content .swiper-container.h4bs-mirror-fallback:not(.h4bs-mirror-fallback-review) .swiper-slide.swiper-slide-active {
                display: block;
            }
            body.h4bs-mirror-page .elementor .swiper-container.h4bs-mirror-fallback:not(.h4bs-mirror-fallback-review) .swiper-slide.h4bs-mirror-slide-active,
            body.h4bs-mirror-page .elementor .swiper-container.h4bs-mirror-fallback:not(.h4bs-mirror-fallback-review) .swiper-slide.swiper-slide-active {
                display: block;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-widget-slides .swiper-container:not(.swiper-initialized):not(.h4bs-mirror-fallback) .swiper-slide,
            body.h4bs-mirror-page .elementor .elementor-widget-slides .swiper-container:not(.swiper-initialized):not(.h4bs-mirror-fallback) .swiper-slide {
                display: none;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-widget-slides .swiper-container:not(.swiper-initialized):not(.h4bs-mirror-fallback) .swiper-slide:first-child,
            body.h4bs-mirror-page .elementor .elementor-widget-slides .swiper-container:not(.swiper-initialized):not(.h4bs-mirror-fallback) .swiper-slide:first-child {
                display: block;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-swiper-button,
            body.h4bs-mirror-page .h4bs-mirror-content .swiper-button-prev,
            body.h4bs-mirror-page .h4bs-mirror-content .swiper-button-next {
                z-index: 30;
                pointer-events: auto;
                cursor: pointer;
            }
            body.h4bs-mirror-page .elementor .elementor-swiper-button,
            body.h4bs-mirror-page .elementor .swiper-button-prev,
            body.h4bs-mirror-page .elementor .swiper-button-next {
                z-index: 30;
                pointer-events: auto;
                cursor: pointer;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .swiper-pagination {
                position: relative;
                z-index: 30;
            }
            body.h4bs-mirror-page .elementor .swiper-pagination {
                position: relative;
                z-index: 30;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .h4bs-mirror-dot {
                width: 10px;
                height: 10px;
                border-radius: 999px;
                border: 0;
                background: rgba(255, 255, 255, 0.55);
                margin: 0 4px;
                padding: 0;
                cursor: pointer;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .h4bs-mirror-dot.is-active {
                background: #ffffff;
            }
            body.h4bs-mirror-page .elementor .h4bs-mirror-dot.is-active {
                background: #ffffff;
            }
        ';

        wp_add_inline_style('h4bs-mirror-runtime', $baselineCss);

        $inlineCss = trim($inlineCss);
        if ($inlineCss !== '') {
            wp_add_inline_style('h4bs-mirror-runtime', $this->rewriteCssUrls($inlineCss, 'https://help4wordpress.com/'));
        }
        wp_add_inline_style('h4bs-mirror-runtime', $this->mirrorLateOverrideCss());

        $runtimeHandle = 'h4bs-mirror-inline-' . $postId;
        wp_register_script($runtimeHandle, '', $scriptHandles, H4BS_VERSION, true);
        wp_enqueue_script($runtimeHandle);
        // Keep one slider runtime to avoid dual-engine race conditions
        // (inline fallback + runtime patches) that can freeze or clip slides.
        wp_enqueue_script(
            'h4bs-mirror-runtime-patches',
            H4BS_URL . 'assets/js/mirror-runtime-patches.js',
            [$runtimeHandle],
            H4BS_VERSION,
            true
        );

        // Do not execute JavaScript imported from mirrored source pages on this origin.
        // Local mirror-runtime-patches.js owns the safe interactive behavior.
    }

    private function shouldSkipMirrorScript(string $scriptUrl): bool
    {
        $normalized = strtolower(trim($scriptUrl));
        if ($normalized === '') {
            return false;
        }

        $blocked = [
            '/wp-content/plugins/help4-builder-suite/',
            '/wp-content/plugins/elementor/assets/js/frontend',
            '/wp-content/plugins/elementor/assets/js/webpack.runtime',
            '/wp-content/plugins/elementor-pro/assets/js/frontend',
            '/wp-content/plugins/elementor-pro/assets/js/webpack-pro.runtime',
            '/wp-content/plugins/elementor-pro/assets/js/elements-handlers',
        ];

        foreach ($blocked as $fragment) {
            if (str_contains($normalized, $fragment)) {
                return true;
            }
        }

        return false;
    }

    private function shouldSkipMirrorStyle(string $styleUrl): bool
    {
        $normalized = strtolower(trim($styleUrl));
        if ($normalized === '') {
            return false;
        }

        $blocked = [
            '/wp-content/plugins/help4-builder-suite/',
            '/wp-content/uploads/elementor/google-fonts/css/',
            '/wp-content/plugins/elementor/assets/lib/eicons/css/',
        ];

        foreach ($blocked as $fragment) {
            if (str_contains($normalized, $fragment)) {
                return true;
            }
        }

        return false;
    }

    private function mirrorAssetAlreadyRegistered(string $assetUrl, string $assetType): bool
    {
        $candidatePath = (string) wp_parse_url($assetUrl, PHP_URL_PATH);
        if ($candidatePath === '') {
            return false;
        }

        $registry = $assetType === 'script' ? wp_scripts() : wp_styles();
        foreach ((array) ($registry->registered ?? []) as $dependency) {
            $source = is_object($dependency) ? (string) ($dependency->src ?? '') : '';
            if ($source === '') {
                continue;
            }
            $registeredPath = (string) wp_parse_url($source, PHP_URL_PATH);
            if ($registeredPath !== '' && '/' . ltrim($registeredPath, '/') === '/' . ltrim($candidatePath, '/')) {
                return true;
            }
        }

        return false;
    }

    private function wrapMirrorInlineJs(string $inlineJs): string
    {
        $payload = wp_json_encode($inlineJs, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        if (! is_string($payload) || $payload === '') {
            return '';
        }
        return '';
    }

    private function mirrorSliderFallbackJs(): string
    {
        return <<<'JS'
(function () {
    const ensureIconFallbackClass = function () {
        if (!document.body || !document.body.classList.contains('h4bs-mirror-page')) {
            return;
        }
        let hasFa = false;
        try {
            if (document.fonts && typeof document.fonts.check === 'function') {
                hasFa =
                    document.fonts.check('900 1em "Font Awesome 5 Free"') ||
                    document.fonts.check('400 1em "Font Awesome 5 Brands"') ||
                    document.fonts.check('900 1em "Font Awesome 6 Free"') ||
                    document.fonts.check('400 1em "Font Awesome 6 Brands"');
            }
        } catch (_error) {
            hasFa = false;
        }
        if (!hasFa) {
            document.body.classList.add('h4bs-mirror-no-fa');
            return;
        }
        document.body.classList.remove('h4bs-mirror-no-fa');
    };

    const parseMaybeJson = function (value) {
        if (typeof value !== 'string' || value.trim() === '') {
            return {};
        }
        try {
            const parsed = JSON.parse(value);
            return parsed && typeof parsed === 'object' ? parsed : {};
        } catch (_error) {
            return {};
        }
    };

    const readSizeValue = function (value, fallback) {
        if (value && typeof value === 'object' && typeof value.size !== 'undefined') {
            const parsed = parseInt(String(value.size || ''), 10);
            return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
        }
        const parsed = parseInt(String(value || ''), 10);
        return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
    };

    const resolveSlidesPerView = function (settings, root) {
        const viewport = Math.max(
            root && root.ownerDocument && root.ownerDocument.defaultView ? root.ownerDocument.defaultView.innerWidth || 0 : 0,
            window.innerWidth || 0,
            0
        );
        if (viewport <= 767) {
            return readSizeValue(settings.slides_per_view_mobile, 1);
        }
        if (viewport <= 1024) {
            return readSizeValue(settings.slides_per_view_tablet, readSizeValue(settings.slides_per_view, 1));
        }
        return readSizeValue(settings.slides_per_view, 1);
    };

    const tryNativeSwiperInit = function (root) {
        if (!(root instanceof HTMLElement)) {
            return false;
        }
        if (root.swiper && typeof root.swiper.slideNext === 'function') {
            root.dataset.h4bsMirrorSliderInit = 'native-existing';
            return true;
        }
        return false;
    };

    const boot = function () {
        if (!document.body || !document.body.classList.contains('h4bs-mirror-page')) {
            return;
        }
        ensureIconFallbackClass();
        // Slider state is managed by Help4 runtime patch script to avoid mixed-controller conflicts.
        return;
        document
            .querySelectorAll(
                '.h4bs-mirror-content .elementor-main-swiper,' +
                ' .h4bs-mirror-content .swiper-container,' +
                ' .elementor-main-swiper,' +
                ' .elementor-widget-reviews .swiper-container,' +
                ' .elementor-widget-slides .swiper-container'
            )
            .forEach(function (root) {
                if (!(root instanceof HTMLElement)) {
                    return;
                }
                if (String(root.dataset.h4bsMirrorSliderInit || '') !== '') {
                    return;
                }
                if (tryNativeSwiperInit(root)) {
                    return;
                }

                const wrapper = root.querySelector('.swiper-wrapper');
                if (!(wrapper instanceof HTMLElement)) {
                    return;
                }

                const slides = Array.from(wrapper.children).filter(function (child) {
                    return child instanceof HTMLElement && child.classList.contains('swiper-slide');
                });
                if (slides.length < 1) {
                    return;
                }

                root.classList.add('h4bs-mirror-fallback');
                const widget =
                    root.closest('.elementor-widget-slides, .elementor-widget-reviews, .elementor-widget-image-carousel, .elementor-widget-testimonial-carousel') ||
                    null;
                const container =
                    widget ||
                    root.closest('.elementor-swiper') ||
                    root.parentElement ||
                    root;
                const isReviewWidget = widget instanceof HTMLElement && widget.classList.contains('elementor-widget-reviews');
                if (isReviewWidget) {
                    root.classList.add('h4bs-mirror-fallback-review');
                }
                const widgetSettings = parseMaybeJson(widget instanceof HTMLElement ? widget.getAttribute('data-settings') || '' : '');
                const prevButton = container.querySelector('.elementor-swiper-button-prev, .swiper-button-prev');
                const nextButton = container.querySelector('.elementor-swiper-button-next, .swiper-button-next');
                const pagination = container.querySelector('.swiper-pagination');
                const autoplayRaw =
                    root.getAttribute('data-autoplay') || root.getAttribute('data-swiper-autoplay') || '';
                let autoplayMs = parseInt(String(autoplayRaw || ''), 10);
                if (!Number.isFinite(autoplayMs) || autoplayMs < 1200) {
                    autoplayMs = isReviewWidget ? 5000 : 4200;
                }
                let perView = Math.max(1, resolveSlidesPerView(widgetSettings, root));
                if (isReviewWidget) {
                    perView = 1;
                }
                const slideGapPx = 12;
                if (isReviewWidget) {
                    wrapper.style.setProperty('display', 'flex', 'important');
                    wrapper.style.setProperty('gap', '0', 'important');
                    wrapper.style.setProperty('width', '100%', 'important');
                    wrapper.style.setProperty('transition', 'transform 360ms ease', 'important');
                    wrapper.style.setProperty('will-change', 'transform', 'important');
                    root.style.setProperty('overflow', 'hidden', 'important');
                }
                const applyReviewLayout = function () {
                    if (!isReviewWidget) {
                        return;
                    }
                    perView = Math.max(1, resolveSlidesPerView(widgetSettings, root));
                    perView = 1;
                    const width = (100 / perView).toFixed(6) + '%';
                    slides.forEach(function (slide) {
                        if (!(slide instanceof HTMLElement)) {
                            return;
                        }
                        slide.style.setProperty('display', 'block', 'important');
                        slide.style.setProperty('width', width, 'important');
                        slide.style.setProperty('max-width', width, 'important');
                        slide.style.setProperty('flex', '0 0 ' + width, 'important');
                        slide.style.setProperty('margin', '0', 'important');
                        slide.style.setProperty('padding-left', String(slideGapPx / 2) + 'px', 'important');
                        slide.style.setProperty('padding-right', String(slideGapPx / 2) + 'px', 'important');
                        slide.style.setProperty('box-sizing', 'border-box', 'important');
                        slide.style.setProperty('transform', 'none', 'important');
                    });
                };
                applyReviewLayout();

                let activeIndex = slides.findIndex(function (slide) {
                    return (
                        slide.classList.contains('swiper-slide-active') ||
                        slide.classList.contains('swiper-slide-visible') ||
                        slide.classList.contains('h4bs-mirror-slide-active')
                    );
                });
                if (activeIndex < 0) {
                    activeIndex = 0;
                }

                let timer = null;
                const stopTimer = function () {
                    if (timer) {
                        window.clearInterval(timer);
                        timer = null;
                    }
                };
                const startTimer = function () {
                    stopTimer();
                    if (isReviewWidget) {
                        return;
                    }
                    if (slides.length > 1) {
                        timer = window.setInterval(function () {
                            setActive(activeIndex + 1);
                        }, autoplayMs);
                    }
                };

                const setActive = function (index) {
                    if (!slides.length) {
                        return;
                    }
                    let safeIndex = ((index % slides.length) + slides.length) % slides.length;
                    if (isReviewWidget) {
                        const maxLead = Math.max(0, slides.length - perView);
                        safeIndex = Math.max(0, Math.min(index, maxLead));
                    }
                    slides.forEach(function (slide, i) {
                        const offset = ((i - safeIndex) % slides.length + slides.length) % slides.length;
                        const isVisible = isReviewWidget ? i >= safeIndex && i < safeIndex + perView : offset < perView;
                        const isLead = i === safeIndex;
                        slide.classList.toggle('swiper-slide-active', isLead);
                        slide.classList.toggle('h4bs-mirror-slide-active', isLead);
                        slide.style.setProperty('display', isReviewWidget || isVisible ? 'block' : 'none', 'important');
                        slide.style.setProperty('opacity', isVisible ? '1' : '0', 'important');
                        slide.setAttribute('aria-hidden', isVisible ? 'false' : 'true');
                        if (isReviewWidget) {
                            slide.style.setProperty('visibility', isVisible ? 'visible' : 'hidden', 'important');
                        }
                    });
                    if (isReviewWidget) {
                        const shift = ((100 / Math.max(1, perView)) * safeIndex).toFixed(6);
                        wrapper.style.setProperty('transform', 'translate3d(-' + shift + '%, 0, 0)', 'important');
                    }
                    activeIndex = safeIndex;

                    if (pagination instanceof HTMLElement) {
                        pagination
                            .querySelectorAll('[data-h4bs-mirror-dot]')
                            .forEach(function (dotNode, dotIndex) {
                                if (!(dotNode instanceof HTMLElement)) {
                                    return;
                                }
                                const activeDot = dotIndex === safeIndex;
                                dotNode.classList.toggle('is-active', activeDot);
                                dotNode.setAttribute('aria-selected', activeDot ? 'true' : 'false');
                            });
                    }
                };

                if (pagination instanceof HTMLElement) {
                    pagination.innerHTML = '';
                    const dotCount = isReviewWidget ? Math.max(1, slides.length - perView + 1) : slides.length;
                    if (dotCount > 1) {
                        Array.from({ length: dotCount }).forEach(function (_slide, i) {
                            const dot = document.createElement('button');
                            dot.type = 'button';
                            dot.className = 'h4bs-mirror-dot';
                            dot.setAttribute('data-h4bs-mirror-dot', String(i));
                            dot.setAttribute('aria-label', 'Go to slide ' + String(i + 1));
                            dot.addEventListener('click', function (event) {
                                event.preventDefault();
                                event.stopPropagation();
                                setActive(i);
                                startTimer();
                            });
                            pagination.appendChild(dot);
                        });
                    }
                }

                const bindNav = function (button, direction) {
                    if (!(button instanceof HTMLElement)) {
                        return;
                    }
                    button.setAttribute('type', 'button');
                    const navigate = function (event) {
                        event.preventDefault();
                        event.stopPropagation();
                        setActive(activeIndex + direction);
                        startTimer();
                    };
                    button.addEventListener('pointerdown', function (event) {
                        event.preventDefault();
                        event.stopPropagation();
                    });
                    button.addEventListener('click', function (event) {
                        navigate(event);
                    });
                };

                bindNav(prevButton, -1);
                bindNav(nextButton, 1);

                wrapper.addEventListener('mouseenter', stopTimer);
                wrapper.addEventListener('mouseleave', startTimer);
                if (isReviewWidget) {
                    let resizeTimer = null;
                    window.addEventListener(
                        'resize',
                        function () {
                            if (resizeTimer) {
                                window.clearTimeout(resizeTimer);
                            }
                            resizeTimer = window.setTimeout(function () {
                                applyReviewLayout();
                                setActive(activeIndex);
                            }, 120);
                        },
                        { passive: true }
                    );
                }

                setActive(activeIndex);
                startTimer();
                root.dataset.h4bsMirrorSliderInit = 'fallback';
            });
    };

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', boot, { once: true });
    } else {
        boot();
    }
    window.addEventListener('load', boot);
    window.setTimeout(ensureIconFallbackClass, 1200);
    window.setTimeout(ensureIconFallbackClass, 2800);
    let observer = null;
    if (typeof MutationObserver !== 'undefined') {
        observer = new MutationObserver(function () {
            boot();
        });
        const observerTarget = document.documentElement || document.body;
        if (observerTarget && typeof observerTarget.nodeType === 'number') {
            observer.observe(observerTarget, { childList: true, subtree: true });
        }
        window.setTimeout(function () {
            if (observer) {
                observer.disconnect();
            }
        }, 15000);
    }
})();
JS;
    }

    private function mirrorLateOverrideCss(): string
    {
        return '
            body.h4bs-mirror-page,
            body.h4bs-mirror-page #page,
            body.h4bs-mirror-page #content,
            body.h4bs-mirror-page .site,
            body.h4bs-mirror-page .site-main,
            body.h4bs-mirror-page .content-area,
            body.h4bs-mirror-page .hentry,
            body.h4bs-mirror-page .entry-content {
                background: #0b0f12 !important;
                color: #aab4ba !important;
            }
            body.h4bs-mirror-page .h4bs-mirror-content,
            body.h4bs-mirror-page .h4bs-mirror-content .elementor,
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-section-wrap,
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-column,
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-widget-wrap {
                background: transparent !important;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-widget-heading .elementor-heading-title {
                opacity: 1 !important;
                color: #f7f8f8 !important;
            }
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-widget-text-editor,
            body.h4bs-mirror-page .h4bs-mirror-content .elementor-widget-text-editor p,
            body.h4bs-mirror-page .h4bs-mirror-content p {
                color: #aab4ba !important;
            }
        ';
    }

    private function seedSlider(): int
    {
        $existing = get_posts(
            [
                'post_type'      => 'h4_slider',
                'posts_per_page' => 1,
                'title'          => 'Help4 Demo Slider',
                'fields'         => 'ids',
            ]
        );
        if (is_array($existing) && ! empty($existing[0])) {
            return (int) $existing[0];
        }

        $sliderId = wp_insert_post(
            [
                'post_type'   => 'h4_slider',
                'post_status' => 'publish',
                'post_title'  => 'Help4 Demo Slider',
            ],
            true
        );
        if (is_wp_error($sliderId) || ! $sliderId) {
            return 0;
        }

        $slides = [
            [
                'image_id' => 0,
                'image_url' => 'https://picsum.photos/1600/700?random=101',
                'title' => 'Fast Visual Builder',
                'caption' => 'Demo slide for performance + design tests.',
                'link' => home_url('/help4-feature-lab/'),
            ],
            [
                'image_id' => 0,
                'image_url' => 'https://picsum.photos/1600/700?random=102',
                'title' => 'Commerce + Conversion',
                'caption' => 'Checkout and search modules in one stack.',
                'link' => home_url('/help4-builder-lab/'),
            ],
        ];
        update_post_meta((int) $sliderId, '_h4_slider_slides', wp_json_encode($slides, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
        return (int) $sliderId;
    }

    private function seedProducts(int $count): void
    {
        global $wpdb;
        $table = $wpdb->prefix . 'h4_products';
        $cacheGroup = 'h4bs_demos';
        $countCacheKey = 'demo_product_count_' . hash('sha256', $table);
        $cachedCount = wp_cache_get($countCacheKey, $cacheGroup);
        if (is_int($cachedCount)) {
            $existingCount = $cachedCount;
        } else {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Demo product count is cached and checks the native Help4 custom product table.
            $existingCount = (int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(*) FROM %i WHERE sku LIKE %s', $table, $wpdb->esc_like('H4-DEMO-') . '%'));
            wp_cache_set($countCacheKey, $existingCount, $cacheGroup, MINUTE_IN_SECONDS * 10);
        }
        if ($existingCount >= $count) {
            return;
        }

        for ($i = $existingCount + 1; $i <= $count; $i++) {
            $sku = 'H4-DEMO-' . str_pad((string) $i, 4, '0', STR_PAD_LEFT);
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Seeds native Help4 demo product rows in the custom product table.
            $wpdb->insert(
                $table,
                [
                    'sku'      => $sku,
                    'name'     => 'Demo Product ' . $i,
                    'slug'     => sanitize_title('demo-product-' . $i),
                    'status'   => 'active',
                    'price'    => (float) (($i % 99) + 19.99),
                    'currency' => 'USD',
                    'stock_qty'=> (int) (($i % 300) + 25),
                    'payload'  => wp_json_encode(['demo' => true, 'index' => $i]),
                ],
                ['%s', '%s', '%s', '%s', '%f', '%s', '%d', '%s']
            );
        }
        wp_cache_set($countCacheKey, $count, $cacheGroup, MINUTE_IN_SECONDS * 10);
    }

    private function seedFeaturePages(int $sliderId): void
    {
        $featurePageId = $this->upsertPage(
            'help4-feature-lab',
            'Help4 Feature Lab',
            '[h4_search type="all" placeholder="Search products and posts..."]

[h4_products limit="12" bg_color="#08121f" bg_gradient="linear-gradient(135deg,rgba(5,18,34,.92),rgba(9,95,125,.72))" panel_bg="rgba(255,255,255,.94)" panel_border="rgba(133,183,218,.35)" panel_padding="18px" panel_radius="16px"]

[h4_checkout]

[h4_slider id="' . max(1, $sliderId) . '" autoplay="3500"]

[h4_template_library limit="140"]'
        );
        if ($featurePageId > 0) {
            update_post_meta($featurePageId, '_h4_builder_mode', 'wp');
            update_post_meta($featurePageId, '_h4_builder_enabled', '0');
            update_post_meta($featurePageId, '_h4_builder_page_layout', 'full_width');
        }

        $starterTemplatesPageId = $this->upsertPage(
            'help4-starter-templates',
            'Help4 Starter Templates',
            wp_kses_post(
                '<p>Choose a starter by the job it needs to do: commerce, subscriptions, SEO, support, builder onboarding, and launch.</p>'
                . '[h4_template_library limit="140"]'
            )
        );
        if ($starterTemplatesPageId > 0) {
            update_post_meta($starterTemplatesPageId, '_h4_builder_mode', 'wp');
            update_post_meta($starterTemplatesPageId, '_h4_builder_enabled', '0');
            update_post_meta($starterTemplatesPageId, '_h4_builder_page_layout', 'full_width');
        }

        $builderPageId = $this->upsertPage(
            'help4-builder-lab',
            'Help4 Builder Lab',
            ''
        );

        update_post_meta($builderPageId, '_h4_builder_mode', 'help4');
        update_post_meta($builderPageId, '_h4_builder_enabled', '1');
        update_post_meta(
            $builderPageId,
            '_h4_builder_layout',
            wp_slash((string) wp_json_encode(
                [
                    [
                        'id' => 'demo_heading',
                        'type' => 'heading',
                        'settings' => ['text' => 'Help4 Builder Demo', 'tag' => 'h1'],
                    ],
                    [
                        'id' => 'demo_intro',
                        'type' => 'text',
                        'settings' => ['text' => 'This page runs in Help4 Builder mode with shortcode/module rendering.'],
                    ],
                    [
                        'id' => 'demo_products',
                        'type' => 'shortcode',
                        'settings' => ['shortcode' => '[h4_products limit="6" bg_color="#08121f" bg_gradient="linear-gradient(135deg,rgba(5,18,34,.92),rgba(9,95,125,.72))" panel_bg="rgba(255,255,255,.94)" panel_border="rgba(133,183,218,.35)" panel_padding="18px" panel_radius="16px"]'],
                    ],
                ],
                JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
            ))
        );

        $this->seedShowcasePages($sliderId);

        if ($featurePageId > 0 && $builderPageId > 0) {
            $this->setFrontPageForDemo();
        }
    }

    private function seedShowcasePages(int $sliderId): void
    {
        if (! $this->isStagingShowcaseMode()) {
            return;
        }

        $version = defined('H4BS_VERSION') ? (string) H4BS_VERSION : 'latest';
        $latestZip = home_url('/help4-builder-suite/help4-builder-suite.zip');
        $versionedZip = home_url('/help4-builder-suite/help4-builder-suite-' . rawurlencode($version) . '.zip');
        $themeZip = home_url('/help4-blank/help4-blank.zip');
        $screensBase = defined('H4BS_PLUGIN_FILE')
            ? trailingslashit((string) plugins_url('assets/demo', H4BS_PLUGIN_FILE))
            : trailingslashit((string) content_url('/plugins/help4-builder-suite/assets/demo'));

        $landingId = $this->upsertPage(
            'help4-builder',
            'Help4 Builder Suite',
            wp_kses_post(
                '<h1>Help4 Builder Suite</h1>
                <p>Drag-and-drop visual builder by Help4 WordPress. Build pages, templates, and feature-rich layouts with fast preview + production-safe rendering.</p>
                <p><a class="button button-primary" href="' . esc_url($latestZip) . '">Download Plugin ZIP</a> <a class="button" href="' . esc_url($themeZip) . '">Download Theme ZIP</a></p>
                <h3>Explore</h3>
                <ul>
                    <li><a href="' . esc_url(home_url('/help4-builder-elements-gallery/')) . '">Element Showcase Gallery</a></li>
                    <li><a href="' . esc_url(home_url('/help4-builder-screenshots/')) . '">Builder Screenshots</a></li>
                    <li><a href="' . esc_url(home_url('/help4-builder-download/')) . '">Download + Install Instructions</a></li>
                    <li><a href="' . esc_url(home_url('/help4-builder-lab/')) . '">Live Builder Lab Page</a></li>
                </ul>'
            )
        );

        $this->upsertPage(
            'help4-builder-download',
            'Help4 Builder Download',
            wp_kses_post(
                '<h1>Download Help4 Builder</h1>
                <p>Use this section to download the latest public build and install it on any WordPress site.</p>
                <p><strong>Latest plugin:</strong> <a href="' . esc_url($latestZip) . '">' . esc_html($latestZip) . '</a></p>
                <p><strong>Versioned plugin:</strong> <a href="' . esc_url($versionedZip) . '">' . esc_html($versionedZip) . '</a></p>
                <p><strong>Companion theme:</strong> <a href="' . esc_url($themeZip) . '">' . esc_html($themeZip) . '</a></p>
                <p><strong>Why two ZIP files?</strong> WordPress.org treats plugins and themes as separate packages, so the builder plugin and the Help4 Blank companion theme are distributed separately. If the theme files are missing, download <code>help4-blank.zip</code> from the companion theme link above and install it under Appearance &gt; Themes.</p>
                <h3>Install in 3 steps</h3>
                <ol>
                    <li>WordPress Admin -> Plugins -> Add New -> Upload Plugin -> upload <code>help4-builder-suite.zip</code>.</li>
                    <li>WordPress Admin -> Appearance -> Themes -> Add New -> Upload Theme -> upload <code>help4-blank.zip</code>.</li>
                    <li>Create/Edit a page and click <strong>Edit with Help4 Builder</strong>.</li>
                </ol>'
            )
        );

        $this->upsertPage(
            'help4-builder-screenshots',
            'Help4 Builder Screenshots',
            wp_kses_post(
                '<h1>Help4 Builder Screenshots</h1>
                <p>UI snapshots from the live builder and demo pages.</p>
                <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px;">
                    <figure><img loading="lazy" src="' . esc_url($screensBase . 'editor-shell.webp') . '" alt="Help4 Builder shell view"><figcaption>Builder shell + viewport controls</figcaption></figure>
                    <figure><img loading="lazy" src="' . esc_url($screensBase . 'editor-canvas.webp') . '" alt="Help4 canvas and settings modal"><figcaption>Canvas editing + element settings modal</figcaption></figure>
                    <figure><img loading="lazy" src="' . esc_url($screensBase . 'showcase-home.webp') . '" alt="Help4 showcase front-end"><figcaption>Showcase page output</figcaption></figure>
                </div>'
            )
        );

        $elementsPageId = $this->upsertPage(
            'help4-builder-elements-gallery',
            'Help4 Builder Elements Gallery',
            ''
        );

        if ($elementsPageId > 0) {
            update_post_meta($elementsPageId, '_h4_builder_mode', 'help4');
            update_post_meta($elementsPageId, '_h4_builder_enabled', '1');
            update_post_meta($elementsPageId, '_h4_builder_page_layout', 'full_width');
            update_post_meta(
                $elementsPageId,
                '_h4_builder_layout',
                wp_slash((string) wp_json_encode(
                    $this->buildElementsShowcaseLayout($sliderId),
                    JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
                ))
            );
        }

        $this->seedGroupedShowcasePages($sliderId);

        $downloadPage = get_page_by_path('help4-builder-download', OBJECT, 'page');
        $downloadPageId = $downloadPage instanceof \WP_Post ? (int) $downloadPage->ID : 0;

        $this->ensurePrimaryMenuLinks(
            array_filter(
                [
                    $landingId > 0 ? $landingId : 0,
                    $elementsPageId > 0 ? $elementsPageId : 0,
                    $downloadPageId,
                ],
                static fn ($id): bool => (int) $id > 0
            )
        );
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    private function buildElementsShowcaseLayout(int $sliderId): array
    {
        $layout = [
            [
                'id' => 'showcase-title',
                'type' => 'heading',
                'settings' => [
                    'tag' => 'h1',
                    'text' => 'Help4 Builder Elements Showcase',
                    'design_font_size' => '44',
                    'design_font_size_unit' => 'px',
                    'design_text_color' => '#12324f',
                ],
            ],
            [
                'id' => 'showcase-intro',
                'type' => 'text',
                'settings' => [
                    'text' => 'Every core element is rendered below in one public gallery page for QA and demos.',
                    'design_font_size' => '18',
                    'design_font_size_unit' => 'px',
                    'design_padding_bottom' => '16',
                    'design_padding_bottom_unit' => 'px',
                ],
            ],
            [
                'id' => 'showcase-hero',
                'type' => 'section',
                'settings' => [
                    'columns' => 2,
                    'gap' => 28,
                    'min_height' => 260,
                    'column_labels' => 'Hero Copy|Visual',
                    'design_background_image' => 'https://picsum.photos/1920/1080?random=210',
                    'design_background_gradient' => 'linear-gradient(118deg, rgba(12,40,68,0.82), rgba(10,155,122,0.62))',
                    'design_background_size' => 'cover',
                    'design_background_position' => 'center center',
                    'design_background_repeat' => 'no-repeat',
                    'design_border_radius' => '18',
                    'design_border_radius_unit' => 'px',
                    'design_padding_top' => '20',
                    'design_padding_right' => '20',
                    'design_padding_bottom' => '20',
                    'design_padding_left' => '20',
                    'design_padding_unit' => 'px',
                ],
            ],
            [
                'id' => 'hero-heading',
                'type' => 'heading',
                'parent_id' => 'showcase-hero',
                'slot' => 0,
                'settings' => [
                    'tag' => 'h2',
                    'text' => 'Section Background + Layout Controls',
                    'design_text_color' => '#ffffff',
                    'design_font_size' => '34',
                    'design_font_size_unit' => 'px',
                    'design_margin_bottom' => '8',
                    'design_margin_bottom_unit' => 'px',
                ],
            ],
            [
                'id' => 'hero-text',
                'type' => 'text',
                'parent_id' => 'showcase-hero',
                'slot' => 0,
                'settings' => [
                    'text' => 'This section demonstrates background image, gradient overlay, spacing, and rounded corners.',
                    'design_text_color' => '#ffffff',
                    'design_font_size' => '16',
                    'design_font_size_unit' => 'px',
                ],
            ],
            [
                'id' => 'hero-button',
                'type' => 'button',
                'parent_id' => 'showcase-hero',
                'slot' => 0,
                'settings' => [
                    'label' => 'Download Help4 Builder',
                    'url' => home_url('/help4-builder-download/'),
                ],
            ],
            [
                'id' => 'hero-image',
                'type' => 'image',
                'parent_id' => 'showcase-hero',
                'slot' => 1,
                'settings' => [
                    'src' => 'https://picsum.photos/900/560?random=211',
                    'alt' => 'Demo showcase visual',
                    'caption' => 'Image block with radius + overlay support',
                    'align' => 'center',
                    'max_width' => '100',
                    'max_width_unit' => '%',
                    'border_radius' => '14',
                    'border_radius_unit' => 'px',
                ],
            ],
            [
                'id' => 'showcase-divider-1',
                'type' => 'divider',
                'settings' => [
                    'thickness' => 2,
                    'style' => 'solid',
                    'color' => '#d2dfeb',
                ],
            ],
            [
                'id' => 'showcase-text',
                'type' => 'text',
                'settings' => [
                    'text' => 'Text block with typography controls.',
                ],
            ],
            [
                'id' => 'showcase-image',
                'type' => 'image',
                'settings' => [
                    'src' => 'https://picsum.photos/1040/520?random=216',
                    'alt' => 'Standalone image demo',
                    'caption' => 'Standalone image element (outside sections)',
                    'align' => 'center',
                    'max_width' => '100',
                    'max_width_unit' => '%',
                    'border_radius' => '12',
                    'border_radius_unit' => 'px',
                ],
            ],
            [
                'id' => 'showcase-video',
                'type' => 'video',
                'settings' => [
                    'provider' => 'youtube',
                    'src' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
                    'height' => 420,
                ],
            ],
            [
                'id' => 'showcase-icon',
                'type' => 'icon',
                'settings' => [
                    'icon_set' => 'dashicons',
                    'icon' => 'dashicons-admin-customizer',
                    'size' => 34,
                    'color' => '#0f6cbf',
                    'label' => 'Icon block',
                ],
            ],
            [
                'id' => 'showcase-list',
                'type' => 'list',
                'settings' => [
                    'items' => "Drag and drop editing\nResponsive viewport controls\nGlobal template support",
                    'ordered' => '0',
                ],
            ],
            [
                'id' => 'showcase-quote',
                'type' => 'quote',
                'settings' => [
                    'text' => 'Designers should be able to build at speed without touching code.',
                    'cite' => 'Help4 QA Team',
                ],
            ],
            [
                'id' => 'showcase-cta',
                'type' => 'cta',
                'settings' => [
                    'title' => 'CTA Element',
                    'text' => 'Use CTA blocks for lead capture and conversion sections.',
                    'button_label' => 'Open Feature Lab',
                    'button_url' => home_url('/help4-feature-lab/'),
                ],
            ],
            [
                'id' => 'showcase-gallery',
                'type' => 'gallery',
                'settings' => [
                    'images' => implode(
                        ',',
                        [
                            'https://picsum.photos/500/360?random=212',
                            'https://picsum.photos/500/360?random=213',
                            'https://picsum.photos/500/360?random=214',
                            'https://picsum.photos/500/360?random=215',
                        ]
                    ),
                    'columns' => 4,
                ],
            ],
            [
                'id' => 'showcase-map',
                'type' => 'map',
                'settings' => [
                    'embed_url' => 'https://www.openstreetmap.org/export/embed.html?bbox=-74.019,40.699,-73.971,40.739&layer=mapnik',
                    'height' => 360,
                ],
            ],
            [
                'id' => 'showcase-faq',
                'type' => 'faq',
                'settings' => [
                    'items' => "Can this be used for production?::Yes, this page is generated from the plugin seed system.\nCan designers use this for QA?::Yes, every core element is visible here.",
                    'open_first' => '1',
                ],
            ],
            [
                'id' => 'showcase-counter',
                'type' => 'counter',
                'settings' => [
                    'prefix' => '',
                    'value' => 128,
                    'suffix' => '+',
                    'label' => 'Active demo checks',
                ],
            ],
            [
                'id' => 'showcase-progress',
                'type' => 'progress',
                'settings' => [
                    'label' => 'Element Coverage',
                    'value' => 100,
                    'max' => 100,
                ],
            ],
            [
                'id' => 'showcase-menu',
                'type' => 'menu',
                'settings' => [
                    'menu_slug' => 'primary',
                    'orientation' => 'horizontal',
                ],
            ],
            [
                'id' => 'showcase-container',
                'type' => 'container',
                'settings' => [
                    'layout' => 'grid',
                    'columns' => 3,
                    'gap' => 14,
                    'min_height' => 120,
                    'note' => 'Container block (grid mode)',
                ],
            ],
            [
                'id' => 'showcase-inner-section',
                'type' => 'inner_section',
                'settings' => [
                    'columns' => 2,
                    'gap' => 16,
                    'min_height' => 120,
                    'column_labels' => 'Inner Left|Inner Right',
                ],
            ],
            [
                'id' => 'showcase-inner-left',
                'type' => 'text',
                'parent_id' => 'showcase-inner-section',
                'slot' => 0,
                'settings' => [
                    'text' => 'Inner section slot 1 content.',
                ],
            ],
            [
                'id' => 'showcase-inner-right',
                'type' => 'text',
                'parent_id' => 'showcase-inner-section',
                'slot' => 1,
                'settings' => [
                    'text' => 'Inner section slot 2 content.',
                ],
            ],
            [
                'id' => 'showcase-shortcode',
                'type' => 'shortcode',
                'settings' => [
                    'shortcode' => '[h4_search type="all" placeholder="Search the showcase and products..."]',
                ],
            ],
            [
                'id' => 'showcase-slider',
                'type' => 'slider',
                'settings' => [
                    'slider_id' => max(1, $sliderId),
                ],
            ],
            [
                'id' => 'showcase-html',
                'type' => 'html',
                'settings' => [
                    'html' => '<div style="padding:12px;border:1px dashed #8fb6da;border-radius:10px;background:#f4f9ff;"><strong>HTML Block:</strong> Custom markup rendered in builder output.</div>',
                ],
            ],
            [
                'id' => 'showcase-spacer',
                'type' => 'spacer',
                'settings' => [
                    'height' => 32,
                ],
            ],
        ];

        return $layout;
    }

    private function seedGroupedShowcasePages(int $sliderId): void
    {
        $all = $this->buildElementsShowcaseLayout($sliderId);
        $byId = [];
        foreach ($all as $block) {
            if (! is_array($block)) {
                continue;
            }
            $id = (string) ($block['id'] ?? '');
            if ($id !== '') {
                $byId[$id] = $block;
            }
        }

        $groups = [
            [
                'slug' => 'help4-gallery-layout-content',
                'title' => 'Help4 Gallery: Layout + Content',
                'ids' => [
                    'showcase-title',
                    'showcase-intro',
                    'showcase-hero',
                    'hero-heading',
                    'hero-text',
                    'hero-button',
                    'hero-image',
                    'showcase-divider-1',
                    'showcase-text',
                    'showcase-menu',
                    'showcase-container',
                    'showcase-inner-section',
                    'showcase-inner-left',
                    'showcase-inner-right',
                    'showcase-html',
                    'showcase-spacer',
                ],
            ],
            [
                'slug' => 'help4-gallery-media-motion',
                'title' => 'Help4 Gallery: Media + Motion',
                'ids' => [
                    'showcase-title',
                    'showcase-intro',
                    'showcase-image',
                    'showcase-video',
                    'showcase-slider',
                    'showcase-gallery',
                    'showcase-icon',
                    'showcase-quote',
                    'showcase-cta',
                ],
            ],
            [
                'slug' => 'help4-gallery-commerce-payments',
                'title' => 'Help4 Gallery: Commerce + Payments',
                'ids' => [
                    'showcase-title',
                    'showcase-intro',
                    'showcase-shortcode',
                    'showcase-slider',
                    'showcase-progress',
                    'showcase-counter',
                    'showcase-cta',
                ],
            ],
            [
                'slug' => 'help4-gallery-seo-security',
                'title' => 'Help4 Gallery: SEO + Security',
                'ids' => [
                    'showcase-title',
                    'showcase-intro',
                    'showcase-list',
                    'showcase-faq',
                    'showcase-map',
                    'showcase-progress',
                    'showcase-counter',
                ],
            ],
        ];

        foreach ($groups as $group) {
            $layout = [];
            foreach ((array) ($group['ids'] ?? []) as $id) {
                $id = (string) $id;
                if ($id === '' || ! isset($byId[$id])) {
                    continue;
                }
                $layout[] = $byId[$id];
            }
            if (! $layout) {
                continue;
            }
            $this->upsertBuilderLayoutPage(
                (string) $group['slug'],
                (string) $group['title'],
                $layout
            );
        }
    }

    /**
     * @param array<int, array<string, mixed>> $layout
     */
    private function upsertBuilderLayoutPage(string $slug, string $title, array $layout): int
    {
        $pageId = $this->upsertPage($slug, $title, '');
        if ($pageId <= 0) {
            return 0;
        }
        update_post_meta($pageId, '_h4_builder_mode', 'help4');
        update_post_meta($pageId, '_h4_builder_enabled', '1');
        update_post_meta($pageId, '_h4_builder_page_layout', 'full_width');
        update_post_meta(
            $pageId,
            '_h4_builder_layout',
            wp_slash((string) wp_json_encode($layout, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES))
        );
        return $pageId;
    }

    /**
     * @param array<int, int> $pageIds
     */
    private function ensurePrimaryMenuLinks(array $pageIds): void
    {
        $locations = get_nav_menu_locations();
        if (! is_array($locations)) {
            $locations = [];
        }

        $menuId = isset($locations['primary']) ? (int) $locations['primary'] : 0;
        if ($menuId <= 0) {
            $existingPrimary = wp_get_nav_menu_object('Primary');
            if ($existingPrimary instanceof \WP_Term) {
                $menuId = (int) $existingPrimary->term_id;
            } else {
                $created = wp_create_nav_menu('Primary');
                if (is_wp_error($created) || (int) $created <= 0) {
                    return;
                }
                $menuId = (int) $created;
            }

            $locations['primary'] = $menuId;
            set_theme_mod('nav_menu_locations', $locations);
        }

        $existing = wp_get_nav_menu_items($menuId, ['post_status' => 'any']);
        $existingObjectItems = [];
        $existingCustomUrls = [];
        $existingItemUrls = [];
        if (is_array($existing)) {
            foreach ($existing as $item) {
                if (! $item instanceof \WP_Post) {
                    continue;
                }

                $itemUrl = strtolower(untrailingslashit((string) ($item->url ?? '')));
                if ($itemUrl !== '') {
                    if (in_array($itemUrl, $existingItemUrls, true)) {
                        wp_delete_post((int) $item->ID, true);
                        continue;
                    }
                    $existingItemUrls[] = $itemUrl;
                }

                if ((int) ($item->object_id ?? 0) > 0) {
                    $objectId = (int) $item->object_id;
                    if (isset($existingObjectItems[$objectId])) {
                        wp_delete_post((int) $item->ID, true);
                        continue;
                    }
                    $existingObjectItems[$objectId] = $item;
                }

                if ((string) ($item->type ?? '') === 'custom') {
                    $customUrl = strtolower(untrailingslashit((string) ($item->url ?? '')));
                    if ($customUrl !== '') {
                        if (in_array($customUrl, $existingCustomUrls, true)) {
                            wp_delete_post((int) $item->ID, true);
                            continue;
                        }
                        $existingCustomUrls[] = $customUrl;
                    }
                }
            }
        }

        foreach ($pageIds as $pageId) {
            $pageId = (int) $pageId;
            if ($pageId <= 0) {
                continue;
            }

            if (isset($existingObjectItems[$pageId])) {
                $existingItem = $existingObjectItems[$pageId];
                if ($existingItem instanceof \WP_Post && $existingItem->post_status !== 'publish') {
                    wp_update_nav_menu_item(
                        $menuId,
                        (int) $existingItem->ID,
                        [
                            'menu-item-object-id' => $pageId,
                            'menu-item-object'    => 'page',
                            'menu-item-type'      => 'post_type',
                            'menu-item-status'    => 'publish',
                        ]
                    );
                }
                continue;
            }

            wp_update_nav_menu_item(
                $menuId,
                0,
                [
                    'menu-item-object-id' => $pageId,
                    'menu-item-object'    => 'page',
                    'menu-item-type'      => 'post_type',
                    'menu-item-status'    => 'publish',
                ]
            );
        }

        $customLinks = [
            ['title' => 'Support Ticket', 'url' => ContactRoutes::supportTicketUrl()],
            ['title' => 'Account Rep', 'url' => ContactRoutes::supportRepUrl()],
            ['title' => 'Text Sales', 'url' => ContactRoutes::salesSmsUrl()],
            ['title' => 'WhatsApp Sales', 'url' => ContactRoutes::salesWhatsAppUrl()],
            ['title' => 'Call Sales', 'url' => ContactRoutes::salesCallUrl()],
        ];

        foreach ($customLinks as $link) {
            $url = esc_url_raw((string) ($link['url'] ?? ''));
            if ($url === '') {
                continue;
            }
            $normalized = strtolower(untrailingslashit($url));
            if ($normalized !== '' && in_array($normalized, $existingCustomUrls, true)) {
                continue;
            }

            wp_update_nav_menu_item(
                $menuId,
                0,
                [
                    'menu-item-title'  => sanitize_text_field((string) ($link['title'] ?? 'Link')),
                    'menu-item-url'    => $url,
                    'menu-item-status' => 'publish',
                    'menu-item-type'   => 'custom',
                ]
            );

            if ($normalized !== '') {
                $existingCustomUrls[] = $normalized;
            }
        }
    }

    private function deduplicatePrimaryMenuLinks(): void
    {
        $locations = get_nav_menu_locations();
        $menuId = is_array($locations) && isset($locations['primary'])
            ? (int) $locations['primary']
            : 0;

        if ($menuId <= 0) {
            $primary = wp_get_nav_menu_object('Primary');
            $menuId = $primary instanceof \WP_Term ? (int) $primary->term_id : 0;
        }

        if ($menuId <= 0) {
            return;
        }

        $items = wp_get_nav_menu_items($menuId, ['post_status' => 'any']);
        if (! is_array($items)) {
            return;
        }

        $seen = [];
        foreach ($items as $item) {
            if (! $item instanceof \WP_Post) {
                continue;
            }

            $url = strtolower(untrailingslashit((string) ($item->url ?? '')));
            if ($url === '') {
                continue;
            }

            if (isset($seen[$url])) {
                wp_delete_post((int) $item->ID, true);
                continue;
            }

            $seen[$url] = (int) $item->ID;
        }
    }

    private function upsertPage(string $slug, string $title, string $content): int
    {
        $existing = get_page_by_path($slug, OBJECT, 'page');
        if ($existing) {
            $content = $this->preserveTutorialVideoBlock((string) $existing->post_content, $content);
            wp_update_post(
                [
                    'ID'           => (int) $existing->ID,
                    'post_title'   => $title,
                    'post_content' => $content,
                    'post_status'  => 'publish',
                ]
            );
            return (int) $existing->ID;
        }

        $pageId = wp_insert_post(
            [
                'post_type'    => 'page',
                'post_status'  => 'publish',
                'post_name'    => $slug,
                'post_title'   => $title,
                'post_content' => $content,
            ],
            true
        );

        if (is_wp_error($pageId) || ! $pageId) {
            return 0;
        }

        return (int) $pageId;
    }

    private function preserveTutorialVideoBlock(string $existingContent, string $generatedContent): string
    {
        $start = '<!-- H4 TUTORIAL VIDEO START -->';
        $end = '<!-- H4 TUTORIAL VIDEO END -->';

        if (str_contains($generatedContent, $start)) {
            return $generatedContent;
        }

        $startOffset = strpos($existingContent, $start);
        if ($startOffset === false) {
            return $generatedContent;
        }

        $endOffset = strpos($existingContent, $end, $startOffset);
        if ($endOffset === false) {
            return $generatedContent;
        }

        $videoBlock = substr(
            $existingContent,
            $startOffset,
            ($endOffset + strlen($end)) - $startOffset
        );
        if (! is_string($videoBlock) || $videoBlock === '') {
            return $generatedContent;
        }

        $tutorialRoot = '<div class="h4-tutorial">';
        $rootOffset = strpos($generatedContent, $tutorialRoot);
        if ($rootOffset === false) {
            return $videoBlock . $generatedContent;
        }

        $insertAt = $rootOffset + strlen($tutorialRoot);
        return substr($generatedContent, 0, $insertAt)
            . $videoBlock
            . substr($generatedContent, $insertAt);
    }

    private function syncHelp4wordpressDemoSite(): int
    {
        $base = 'https://help4wordpress.com';
        $imported = 0;
        $page = 1;

        while ($page <= 10) {
            $response = wp_remote_get(
                $base . '/wp-json/wp/v2/pages?per_page=50&page=' . $page . '&orderby=menu_order&order=asc',
                [
                    'timeout' => 20,
                    'headers' => [
                        'Accept' => 'application/json',
                    ],
                ]
            );

            if (is_wp_error($response)) {
                break;
            }

            $statusCode = (int) wp_remote_retrieve_response_code($response);
            if ($statusCode < 200 || $statusCode >= 300) {
                break;
            }

            $decoded = json_decode((string) wp_remote_retrieve_body($response), true);
            if (! is_array($decoded) || ! $decoded) {
                break;
            }

            foreach ($decoded as $row) {
                if (! is_array($row)) {
                    continue;
                }
                $slug = sanitize_title((string) ($row['slug'] ?? ''));
                $title = wp_strip_all_tags((string) ($row['title']['rendered'] ?? ''), true);
                $content = (string) ($row['content']['rendered'] ?? '');
                $sourceUrl = esc_url_raw((string) ($row['link'] ?? $base . '/' . ltrim($slug, '/')));
                $status = sanitize_key((string) ($row['status'] ?? 'publish'));
                if ($slug === '' || $title === '' || $status !== 'publish') {
                    continue;
                }
                $mirrorPayload = $this->fetchRenderedMirrorPayload($sourceUrl);
                $content = $mirrorPayload['content_html'] !== ''
                    ? (string) $mirrorPayload['content_html']
                    : $content;
                $content = $this->rewriteCommerceLinks($content);
                $id = $this->upsertPage($slug, $title, wp_kses_post($content));
                if ($id > 0) {
                    update_post_meta($id, '_h4_imported_help4wp', '1');
                    update_post_meta($id, '_h4_imported_help4wp_source', $sourceUrl);
                    update_post_meta($id, '_h4_builder_mode', 'wp');
                    update_post_meta($id, '_h4_builder_enabled', '0');
                    update_post_meta(
                        $id,
                        '_h4_builder_page_layout',
                        $mirrorPayload['content_html'] !== '' ? 'canvas' : 'full_width'
                    );
                    if ($mirrorPayload['content_html'] !== '') {
                        $this->persistMirrorPayload($id, $mirrorPayload);
                    } else {
                        $this->clearMirrorPayload($id);
                    }
                    $imported++;
                }
            }

            $page++;
        }

        $importedFromKnownPages = $this->syncHelp4wordpressKnownPages();
        if ($importedFromKnownPages > 0) {
            $imported += $importedFromKnownPages;
        }

        if ($imported <= 0) {
            $this->seedHelp4wordpressFallbackPages();
            return 0;
        }

        $this->seedExternalCommerceBridgePages();
        $this->ensureGlobalThemeBuilderTemplates();
        $this->forcePageLayoutForAllPages('full_width', true);
        $this->seedShowcasePages($this->seedSlider());
        $this->setFrontPageForDemo();
        $this->ensureMarketingHomeUsesGlobalChrome();

        return $imported;
    }

    private function syncHelp4wordpressKnownPages(): int
    {
        $targets = [
            [
                'slug' => 'home',
                'title' => 'Help4 WordPress',
                'source' => 'https://help4wordpress.com/',
            ],
            [
                'slug' => 'fully-managed-servers',
                'title' => 'Fully Managed Servers',
                'source' => 'https://help4wordpress.com/fully-managed-servers/',
            ],
            [
                'slug' => 'packages',
                'title' => 'Packages',
                'source' => 'https://help4wordpress.com/packages/',
            ],
            [
                'slug' => 'self-help',
                'title' => 'Self Help',
                'source' => 'https://help4wordpress.com/self-help/',
            ],
            [
                'slug' => 'about-us',
                'title' => 'About Us',
                'source' => 'https://help4wordpress.com/about-us/',
            ],
            [
                'slug' => 'contact-us',
                'title' => 'Contact Us',
                'source' => 'https://help4wordpress.com/contact-us/',
            ],
            [
                'slug' => 'account',
                'title' => 'Account',
                'source' => 'https://help4wordpress.com/account/',
            ],
        ];

        $imported = 0;
        foreach ($targets as $target) {
            $slug = sanitize_title((string) ($target['slug'] ?? ''));
            $title = sanitize_text_field((string) ($target['title'] ?? ''));
            $sourceUrl = esc_url_raw((string) ($target['source'] ?? ''));
            if ($slug === '' || $title === '' || $sourceUrl === '') {
                continue;
            }

            $mirrorPayload = $this->fetchRenderedMirrorPayload($sourceUrl);
            $content = (string) ($mirrorPayload['content_html'] ?? '');
            if ($content === '') {
                continue;
            }
            $content = $this->rewriteCommerceLinks($content);

            $id = $this->upsertPage($slug, $title, wp_kses_post($content));
            if ($id <= 0) {
                continue;
            }

            update_post_meta($id, '_h4_imported_help4wp', '1');
            update_post_meta($id, '_h4_imported_help4wp_source', $sourceUrl);
            update_post_meta($id, '_h4_builder_mode', 'wp');
            update_post_meta($id, '_h4_builder_enabled', '0');
            update_post_meta($id, '_h4_builder_page_layout', 'canvas');
            $this->persistMirrorPayload($id, $mirrorPayload);
            $imported++;
        }

        return $imported;
    }

    private function seedHelp4wordpressFallbackPages(): void
    {
        $this->seedHelp4wordpressSalesPages();
        $this->seedExternalCommerceBridgePages();
        $this->ensureGlobalThemeBuilderTemplates();
        $this->ensureMarketingHomeUsesGlobalChrome();
        $this->forcePageLayoutForAllPages('full_width');
        $this->seedShowcasePages($this->seedSlider());
    }

    private function seedHelp4wordpressSalesPages(): void
    {
        $salesCallUrl = esc_url(ContactRoutes::salesCallUrl());
        $supportTicketUrl = esc_url(ContactRoutes::supportTicketUrl());
        $clientAreaUrl = esc_url(ContactRoutes::supportClientAreaUrl());
        $wordpressStoreUrl = 'https://help4network.com/store/help-4-wordpress/';
        $cartUrl = 'https://help4network.com/cart/';

        $homeId = $this->upsertPage(
            'home',
            'Help4 WordPress Hosting and Support',
            wp_kses_post($this->h4SalesHomepageContent($salesCallUrl, $supportTicketUrl))
        );
        $shopId = $this->upsertPage(
            'shop',
            'Managed WordPress Hosting Plans',
            wp_kses_post($this->h4ProductShopPage($wordpressStoreUrl, $cartUrl, $supportTicketUrl, $salesCallUrl, '', ''))
        );
        $packagesId = $this->upsertPage(
            'packages',
            'WordPress Hosting Plans from $4.95/mo',
            wp_kses_post($this->h4ProductPackagesPage($wordpressStoreUrl, $cartUrl, $supportTicketUrl, $clientAreaUrl, $salesCallUrl, '', ''))
        );
        $managedId = $this->upsertPage(
            'fully-managed-wordpress-hosting',
            'Fully Managed WordPress Hosting',
            wp_kses_post($this->h4ProductManagedHostingPage($wordpressStoreUrl, $cartUrl, $supportTicketUrl, $clientAreaUrl, '', $salesCallUrl, '', ''))
        );
        $portfolioHtml = $this->h4SalesPortfolioPageContent($supportTicketUrl);
        $portfolioId = $this->upsertPage(
            'portfolio',
            'Recent WordPress Work',
            wp_kses_post($portfolioHtml)
        );
        $blankThemeId = $this->upsertBlankThemePage($supportTicketUrl);

        foreach ([$homeId, $shopId, $packagesId, $managedId, $portfolioId, $blankThemeId] as $pageId) {
            $pageId = (int) $pageId;
            if ($pageId <= 0) {
                continue;
            }
            $this->clearMirrorPayload($pageId);
            update_post_meta($pageId, '_h4_builder_mode', 'wp');
            update_post_meta($pageId, '_h4_builder_enabled', '0');
            update_post_meta($pageId, '_h4_builder_page_layout', 'full_width');
        }

        if ($portfolioId > 0) {
            $portfolioLayout = [
                [
                    'schema_version' => '1.0',
                    'id' => 'h4wp-portfolio-showcase',
                    'type' => 'html',
                    'settings' => [
                        'html' => $portfolioHtml,
                    ],
                    'visibility' => [],
                    'parent_id' => '',
                    'slot' => 0,
                    'extensions' => [],
                ],
            ];
            update_post_meta(
                $portfolioId,
                '_h4_builder_layout',
                wp_slash((string) wp_json_encode($portfolioLayout, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE))
            );
            update_post_meta($portfolioId, '_h4_builder_mode', 'help4');
            update_post_meta($portfolioId, '_h4_builder_enabled', '1');
        }

        if ($homeId > 0) {
            update_option('show_on_front', 'page');
            update_option('page_on_front', $homeId);
        }

        $this->applySalesSeoMeta(
            (int) $homeId,
            'WordPress Hosting from $4.95/mo + Real Help | Help4',
            'Start WordPress hosting at $4.95/mo, then add human help for updates, security, speed, SEO, migrations, page builds, and emergency support.'
        );
        $this->applySalesSeoMeta(
            (int) $shopId,
            'WordPress Hosting and Support Plans | Help4 WordPress',
            'Buy $4.95/mo WordPress hosting or choose managed care, growth support, migration, security, and emergency Help4 service paths.'
        );
        $this->applySalesSeoMeta(
            (int) $packagesId,
            'WordPress Hosting Plans from $4.95/mo | Help4',
            'Compare Help4 WordPress hosting from $4.95/mo with managed maintenance, speed, SEO, page work, security, migration, and priority support.'
        );
        $this->applySalesSeoMeta(
            (int) $managedId,
            'Fully Managed WordPress Hosting and Site Care | Help4',
            'Hand off WordPress updates, backups, plugin conflicts, forms, SSL, malware cleanup, page work, speed, SEO, and ongoing support to Help4.'
        );
        $this->applySalesSeoMeta(
            (int) $portfolioId,
            'WordPress Website Portfolio and Client Results | Help4',
            'See Help4 website builds for Realtors and nonprofits, including Jonathan Hetrick Realty and Find Your Voice Foundation, with live website proof.'
        );

        $homeFaq = [
            [
                'question' => 'What is included with the $4.95 per month WordPress hosting plan?',
                'answer' => 'The DIY starter path is for owners who handle normal WordPress work. Help4 handles hosting stability, backups, firewall coverage, malware scanning and removal help, and restore assistance.',
            ],
            [
                'question' => 'Can Help4 manage my WordPress website for me?',
                'answer' => 'Yes. Managed care can cover WordPress core and plugin updates, backups, plugin conflicts, forms, SSL problems, malware cleanup, routine tickets, and additional growth work.',
            ],
            [
                'question' => 'Can Help4 migrate an existing WordPress website?',
                'answer' => 'Yes. Help4 can move an existing WordPress site and verify its pages, links, forms, SSL, and public behavior after migration.',
            ],
            [
                'question' => 'What if I am not sure which Help4 plan I need?',
                'answer' => 'Call Help4 sales or open a support request with the site URL, the problem, and the outcome you want. Help4 will route you to the most appropriate plan or custom scope.',
            ],
        ];
        $this->applyFaqSchema((int) $homeId, $homeFaq);
        $this->applyFaqSchema((int) $packagesId, $homeFaq);
        $this->applyFaqSchema((int) $managedId, $homeFaq);
        $this->applyFaqSchema(
            (int) $portfolioId,
            [
                [
                    'question' => 'Can Help4 build and manage a complete business website?',
                    'answer' => 'Yes. Help4 can combine Builder implementation, hosting, responsive design, content structure, forms, search optimization, security, performance, and ongoing support in one engagement.',
                ],
                [
                    'question' => 'Does Help4 work with nonprofit organizations?',
                    'answer' => 'Yes. Help4 can rebuild nonprofit websites around the mission, programs, donations, events, volunteers, accessibility, and an editing workflow the organization can maintain.',
                ],
                [
                    'question' => 'Can Help4 rebuild an existing website in Help4 Builder?',
                    'answer' => 'Yes. Help4 can use the current site, supplied designs, screenshots, brand files, and business requirements as the source for a responsive Builder-controlled rebuild.',
                ],
            ]
        );
        $this->ensureMarketingSeoContentDepth();
    }

    private function ensureMarketingSeoContentDepth(): void
    {
        $sections = [
            'help4-blank-theme' => [
                'eyebrow' => 'Clean WordPress foundation',
                'heading' => 'Why a blank WordPress theme makes visual building easier',
                'focus_keyword' => 'blank WordPress theme',
                'paragraphs' => [
                    'A blank WordPress theme gives Help4 Builder a predictable canvas without forcing another theme company\'s header, footer, typography, spacing, or store styles into every page. That matters when you want the Builder template assigned to the page to be the design, instead of fighting inherited theme decisions before the real work begins.',
                    'Help4 Blank keeps the normal WordPress theme boundary in place while Builder Suite handles page layouts, global templates, responsive controls, forms, structured content, SEO, and optional commerce features. It is recommended for the cleanest workflow, but Builder Suite can still work with another properly coded WordPress theme when an existing site cannot change themes.',
                    'The downloadable package is intentionally clean. It does not contain the Help4WordPress marketing design, staging rules, customer-specific logos, or demo-site customizations. Install it when you want a lightweight starting point, then choose a starter template or build the header and footer through Theme Builder.',
                    'After activation, set the site identity, permalink structure, global colors, and typography, then assign Builder templates deliberately. A blank theme does not replace normal launch work: navigation, accessibility, forms, analytics, search metadata, backups, caching, and update testing still need decisions. Its advantage is clarity. When something changes, you can trace the result to WordPress, Builder, or the selected module instead of untangling a second design system.',
                ],
                'bullets' => [
                    'Use Help4 Blank for new sites, design handoffs, and full Builder-controlled rebuilds.',
                    'Keep an existing theme when changing it would disrupt a production site or required integration.',
                    'Create global header, footer, 404, archive, and page templates inside Builder Suite.',
                    'Test desktop, tablet, and mobile output before replacing an established production design.',
                ],
                'links' => [
                    ['label' => 'Download Help4 Blank', 'url' => $this->h4TrackedDownloadUrl('blank-theme')],
                    ['label' => 'Help4 Blank setup and compatibility', 'url' => home_url('/help4-blank-theme/')],
                    ['label' => 'Download Builder Suite', 'url' => $this->h4TrackedDownloadUrl('builder-suite')],
                    ['label' => 'Build your first page', 'url' => home_url('/help4-builder-first-page/')],
                    ['label' => 'Open the template library guide', 'url' => home_url('/help4-builder-template-library/')],
                ],
            ],
            'help4-builder' => [
                'eyebrow' => 'Visual building plus site operations',
                'heading' => 'A WordPress website builder for the page and the work behind it',
                'focus_keyword' => 'WordPress website builder',
                'paragraphs' => [
                    'Help4 Builder Suite combines visual page building with the practical tools a WordPress site needs after launch. Build responsive pages and global templates, then manage forms, fields, sliders, SEO checks, performance work, security settings, native commerce, and payment routing from one modular plugin.',
                    'Modules stay compartmentalized so a simple brochure site does not need every commerce or operations feature loaded on every page. Start with a blank canvas or a starter template, adjust the design system, and add advanced features only when the site requires them.',
                ],
                'bullets' => [
                    'Use reusable templates for headers, footers, landing pages, 404 pages, and content sections.',
                    'Review responsive behavior at real device widths before publishing.',
                    'Hand Help4 a design when you want the finished WordPress implementation built for you.',
                ],
                'links' => [
                    ['label' => 'Download the current public build', 'url' => home_url('/help4-builder-download/')],
                    ['label' => 'Browse starter templates', 'url' => home_url('/help4-starter-templates/')],
                    ['label' => 'Follow the Builder tutorials', 'url' => home_url('/help4-builder-tutorials/')],
                ],
            ],
            'help4-gallery-commerce-payments' => [
                'eyebrow' => 'Native catalog and checkout workflows',
                'heading' => 'Plan a WordPress commerce builder around products, customers, and payment rules',
                'focus_keyword' => 'WordPress commerce builder',
                'paragraphs' => [
                    'Help4 Commerce is the native catalog and order layer inside Builder Suite. It is designed for simple products, large indexed catalogs, variations, subscriptions, customer records, imports, and checkout experiences without requiring a separate store plugin to define the entire site architecture.',
                    'Payment Router separates the storefront from processor decisions. Route transactions by product, subscription, region, processor availability, or custom business rules, then test webhooks and failure paths before enabling live credentials. The gallery demonstrates presentation blocks; the setup guides explain the operational sequence behind them.',
                ],
                'bullets' => [
                    'Model products and variations before styling product cards or category pages.',
                    'Test checkout, email, tax, shipping, subscription, and refund paths with non-production data.',
                    'Keep processor keys and webhook secrets outside page content and template exports.',
                ],
                'links' => [
                    ['label' => 'Start the Help4 Commerce guide', 'url' => home_url('/help4-commerce-getting-started/')],
                    ['label' => 'Review Payment Router setup', 'url' => home_url('/help4-payment-router/')],
                    ['label' => 'Get commerce implementation help', 'url' => home_url('/commerce-support/')],
                ],
            ],
            'help4-gallery-media-motion' => [
                'eyebrow' => 'Images, sliders, galleries, and motion',
                'heading' => 'Build visual WordPress sections that remain fast and understandable',
                'focus_keyword' => 'WordPress media builder',
                'paragraphs' => [
                    'Media should explain the product, service, place, or result instead of acting as decoration. Help4 Builder supports images, galleries, video, sliders, icons, quotes, calls to action, and controlled motion so visual pages can carry real information without becoming difficult to scan.',
                    'Use the right source dimensions, meaningful alternative text, modern image formats, and restrained movement. Check cropping at every breakpoint and avoid autoplay behavior that competes with forms or primary calls to action. The same assets can be saved inside templates when the pattern needs to repeat.',
                ],
                'bullets' => [
                    'Use descriptive media and captions when a visitor needs context or proof.',
                    'Keep motion optional, short, and compatible with reduced-motion preferences.',
                    'Confirm that mobile crops preserve the subject and do not create horizontal overflow.',
                ],
                'links' => [
                    ['label' => 'Build sliders and forms', 'url' => home_url('/help4-builder-sliders-forms/')],
                    ['label' => 'Reuse sections through templates', 'url' => home_url('/help4-builder-template-library/')],
                    ['label' => 'See step-by-step tutorials', 'url' => home_url('/help4-builder-tutorials/')],
                ],
            ],
            'help4-gallery-seo-security' => [
                'eyebrow' => 'Search visibility, speed, and protection',
                'heading' => 'Treat WordPress SEO and security as ongoing site operations',
                'focus_keyword' => 'WordPress SEO and security',
                'paragraphs' => [
                    'Search visibility starts with useful pages that answer a real question, expose clear internal paths, and render reliably for visitors and crawlers. Builder Suite adds search titles, descriptions, canonical controls, schema, social cards, readability guidance, sitemaps, redirects, and IndexNow support around the content workflow.',
                    'Security and speed support that visibility. A compromised, unstable, or painfully slow site loses trust before stronger copy can help. Use least-privilege access, tested backups, current software, safe headers, logging, caching, image optimization, and post-update checks as one operating routine rather than unrelated plugin dashboards.',
                ],
                'bullets' => [
                    'Write for the customer question first, then refine titles, descriptions, headings, and schema.',
                    'Verify sitemap, robots, canonical, redirect, and social-image behavior from the public edge.',
                    'Review fresh PHP and browser logs after every WordPress, theme, or Builder update.',
                ],
                'links' => [
                    ['label' => 'Use the SEO, security, and performance guide', 'url' => home_url('/help4-builder-seo-security-performance/')],
                    ['label' => 'Improve WordPress speed', 'url' => home_url('/wordpress-speed-optimization/')],
                    ['label' => 'Get malware cleanup help', 'url' => home_url('/wordpress-malware-removal/')],
                ],
            ],
            'portfolio' => [
                'eyebrow' => 'Real website implementation examples',
                'heading' => 'What these WordPress website examples prove',
                'focus_keyword' => 'WordPress website portfolio',
                'paragraphs' => [
                    'A useful WordPress website portfolio shows more than a polished home page. Review whether the live site communicates the organization quickly, works on mobile, exposes clear next actions, and supports the listings, forms, donations, publishing, catalog, events, or support workflow the organization actually needs.',
                    'Help4 projects can begin with an existing site, supplied design files, a migration request, a performance problem, or a blank Builder installation. The live website captures here show real-estate and nonprofit work, while each engagement can combine design implementation, content structure, hosting, maintenance, speed, security, SEO, integrations, and ongoing support.',
                ],
                'bullets' => [
                    'Compare live mobile behavior, navigation, calls to action, accessibility, and content clarity.',
                    'Use a design handoff when the visual direction exists but the WordPress build does not.',
                    'Use a complete managed engagement when the website, search visibility, operations, and support need one accountable team.',
                ],
                'links' => [
                    ['label' => 'Turn a design into WordPress', 'url' => home_url('/design-to-wordpress/')],
                    ['label' => 'Plan a WordPress migration', 'url' => home_url('/wordpress-migration-service/')],
                    ['label' => 'Compare managed care', 'url' => home_url('/fully-managed-wordpress-hosting/')],
                ],
            ],
            'about-us' => [
                'eyebrow' => 'Human WordPress operations',
                'heading' => 'Managed WordPress support that can own the implementation',
                'focus_keyword' => 'managed WordPress support',
                'paragraphs' => [
                    'Help4 WordPress is the WordPress service line of Help4 Network. The work spans affordable hosting, migrations, maintenance, security cleanup, performance, SEO implementation, page building, design handoffs, native commerce, and urgent troubleshooting for owners who do not want to become their own technical department.',
                    'Customers can start with the $4.95 per month hosting path and keep day-to-day control, or move into managed service when updates, failures, content work, and growth tasks should be handled by a team. Requests can be written in plain language; the important details are the site URL, what is happening, and the outcome the business needs.',
                ],
                'bullets' => [
                    'Tracked support paths keep normal work, urgent problems, and account questions organized.',
                    'Beta testing on the md track prepares Builder and site changes before production updates.',
                    'Help4 can work from an existing website, a blank install, or supplied design files.',
                ],
                'links' => [
                    ['label' => 'Compare WordPress packages', 'url' => home_url('/packages/')],
                    ['label' => 'Explore WordPress services', 'url' => home_url('/help-4-wordpress/')],
                    ['label' => 'Contact Help4 WordPress', 'url' => home_url('/contact-us/')],
                ],
            ],
            'contact-us' => [
                'eyebrow' => 'Route the request correctly',
                'heading' => 'Contact WordPress support with the details that speed up a solution',
                'focus_keyword' => 'WordPress support contact',
                'paragraphs' => [
                    'Send the website URL, the affected page or admin screen, what you expected, what happened instead, and whether the problem blocks sales, leads, staff, or visitors. Add the last change you remember and a screenshot when it makes the issue easier to recognize.',
                    'Billing, service, and tracked support messages may receive replies from Help4Network.com or Help4.us. Check spam, junk, promotions, and filtered folders when a response is not visible. Never send passwords, payment keys, or private customer data through an unprotected contact message.',
                ],
                'bullets' => [
                    'Use the Help4 Network contact path for sales, service selection, and general account routing.',
                    'Use the client area or support ticket path for work tied to an existing service.',
                    'Call when the issue is urgent or the correct plan is not obvious.',
                ],
                'links' => [
                    ['label' => 'Open the Help4 Network contact page', 'url' => 'https://help4network.com/contact'],
                    ['label' => 'Compare Help4 WordPress packages', 'url' => home_url('/packages/')],
                    ['label' => 'Review emergency support', 'url' => home_url('/emergency-wordpress-support/')],
                ],
            ],
            'self-help' => [
                'eyebrow' => 'Diagnose before changing production',
                'heading' => 'Use WordPress self help without turning one problem into three',
                'focus_keyword' => 'WordPress self help',
                'paragraphs' => [
                    'Start by recording the affected URL, exact error, time, device, and last known change. Confirm whether the problem affects every visitor or only one browser or signed-in account. A backup and a reproducible symptom are more valuable than a fast sequence of random plugin changes.',
                    'Use a staging copy for theme, plugin, PHP, and WordPress core tests whenever possible. Change one variable at a time, clear the relevant cache, check the public page, and review fresh logs. Stop when the site handles revenue, customer data, payments, or a failure you cannot safely reverse.',
                ],
                'bullets' => [
                    'Check status, backups, disk space, DNS, SSL, and recent changes before editing code.',
                    'Do not post passwords, API keys, payment credentials, or private logs in public forums.',
                    'Escalate malware, checkout failures, database errors, and widespread outages quickly.',
                ],
                'links' => [
                    ['label' => 'Read more WordPress help at FixItPhill', 'url' => 'https://fixitphill.com/category/wordpress/'],
                    ['label' => 'Open Help4 support guidance', 'url' => home_url('/wordpress-support/')],
                    ['label' => 'Use the Builder tutorials', 'url' => home_url('/help4-builder-tutorials/')],
                ],
            ],
            'help4-builder-elements-gallery' => [
                'eyebrow' => 'Choose blocks by purpose',
                'heading' => 'Use WordPress builder elements as a reusable design system',
                'focus_keyword' => 'WordPress builder elements',
                'paragraphs' => [
                    'Builder elements are the raw parts of a page: sections, containers, headings, text, images, menus, forms, galleries, sliders, calls to action, commerce output, and supporting utility blocks. The strongest pages use a small set consistently instead of stacking every available widget into one layout.',
                    'Define typography, colors, spacing, buttons, fields, and responsive behavior first. Save repeated combinations as templates, then change the shared pattern rather than rebuilding it on every page. The gallery is for visual inspection; the tutorials explain how to assemble and publish the pieces safely.',
                ],
                'bullets' => [
                    'Start with page structure and content hierarchy before decorative controls.',
                    'Use native menu, form, and media components when they match the required behavior.',
                    'Check focus states, contrast, labels, keyboard access, and mobile wrapping before launch.',
                ],
                'links' => [
                    ['label' => 'Build the first page', 'url' => home_url('/help4-builder-first-page/')],
                    ['label' => 'Reuse the design with templates', 'url' => home_url('/help4-builder-template-library/')],
                    ['label' => 'Download Builder Suite', 'url' => home_url('/help4-builder-download/')],
                ],
            ],
            'help4-builder-lab' => [
                'eyebrow' => 'Safe Builder experimentation',
                'heading' => 'Use the WordPress builder demo to test a workflow before production',
                'focus_keyword' => 'WordPress builder demo',
                'paragraphs' => [
                    'The Help4 Builder Lab is a working page for checking real frontend output, not a replacement for a staging environment. Use it to understand how blocks render, how templates interact, and how responsive controls change the page before applying the same pattern to a customer-facing route.',
                    'A useful test covers more than appearance. Save the layout, reload the frontend, open the mobile menu, submit test forms, inspect links, check browser and PHP logs, and confirm that no hidden element expands the page beyond the viewport. Move the pattern into a reusable template only after those checks pass.',
                ],
                'bullets' => [
                    'Experiment with disposable content and non-production credentials.',
                    'Compare desktop, tablet, and small mobile widths after every structural change.',
                    'Keep the current public ZIP available before testing an upcoming beta release.',
                ],
                'links' => [
                    ['label' => 'Inspect every Builder element', 'url' => home_url('/help4-builder-elements-gallery/')],
                    ['label' => 'Follow the Builder tutorials', 'url' => home_url('/help4-builder-tutorials/')],
                    ['label' => 'Download the current build', 'url' => home_url('/help4-builder-download/')],
                ],
            ],
        ];

        foreach ($sections as $slug => $section) {
            $page = get_page_by_path((string) $slug, OBJECT, 'page');
            if (! $page instanceof \WP_Post || $page->post_status !== 'publish') {
                continue;
            }

            $html = $this->buildMarketingSeoDepthHtml($section);
            if ($html === '') {
                continue;
            }

            $layoutRaw = (string) get_post_meta($page->ID, '_h4_builder_layout', true);
            $builderEnabled = (string) get_post_meta($page->ID, '_h4_builder_enabled', true) === '1';
            $layout = $builderEnabled && $layoutRaw !== '' ? json_decode($layoutRaw, true) : null;
            if (is_array($layout)) {
                $layout = array_values(
                    array_filter(
                        $layout,
                        static fn ($block): bool => ! is_array($block) || (string) ($block['id'] ?? '') !== 'h4wp-seo-depth'
                    )
                );
                $layout[] = [
                    'id' => 'h4wp-seo-depth',
                    'type' => 'html',
                    'settings' => [
                        'html' => $html,
                    ],
                ];
                update_post_meta(
                    $page->ID,
                    '_h4_builder_layout',
                    wp_slash((string) wp_json_encode($layout, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE))
                );
            } else {
                $content = (string) $page->post_content;
                $pattern = '#<section\b(?=[^>]*\bclass="[^"]*\bh4wp-seo-depth\b[^"]*")[^>]*>.*?</section>#s';
                $content = rtrim((string) preg_replace($pattern, '', $content));
                $content .= "\n\n" . $html;
                wp_update_post(
                    wp_slash([
                        'ID' => (int) $page->ID,
                        'post_content' => $content,
                    ])
                );
            }

            update_post_meta($page->ID, '_h4_seo_focus_keyword', sanitize_text_field((string) ($section['focus_keyword'] ?? '')));
            update_post_meta($page->ID, '_h4_seo_schema_type', 'webpage');
            clean_post_cache($page->ID);
        }
    }

    /**
     * @param array<string, mixed> $section
     */
    private function buildMarketingSeoDepthHtml(array $section): string
    {
        $heading = sanitize_text_field((string) ($section['heading'] ?? ''));
        if ($heading === '') {
            return '';
        }

        $paragraphs = '';
        foreach ((array) ($section['paragraphs'] ?? []) as $paragraph) {
            $paragraph = sanitize_text_field((string) $paragraph);
            if ($paragraph !== '') {
                $paragraphs .= '<p>' . esc_html($paragraph) . '</p>';
            }
        }

        $bullets = '';
        foreach ((array) ($section['bullets'] ?? []) as $bullet) {
            $bullet = sanitize_text_field((string) $bullet);
            if ($bullet !== '') {
                $bullets .= '<li>' . esc_html($bullet) . '</li>';
            }
        }

        $links = '';
        foreach ((array) ($section['links'] ?? []) as $link) {
            if (! is_array($link)) {
                continue;
            }
            $label = sanitize_text_field((string) ($link['label'] ?? ''));
            $url = esc_url((string) ($link['url'] ?? ''));
            if ($label === '' || $url === '') {
                continue;
            }
            $external = wp_parse_url($url, PHP_URL_HOST) !== wp_parse_url(home_url('/'), PHP_URL_HOST);
            $links .= '<a href="' . $url . '"' . ($external ? ' target="_blank" rel="noopener"' : '') . '>' . esc_html($label) . '</a>';
        }

        $version = defined('H4BS_VERSION') ? (string) H4BS_VERSION : 'dev';

        return '<section class="h4wp-seo-depth" data-h4wp-seo-depth="' . esc_attr($version) . '">'
            . '<div class="h4wp-seo-depth__inner">'
            . '<p class="h4wp-seo-depth__eyebrow">' . esc_html((string) ($section['eyebrow'] ?? 'WordPress guidance')) . '</p>'
            . '<h2>' . esc_html($heading) . '</h2>'
            . '<div class="h4wp-seo-depth__copy">' . $paragraphs . '</div>'
            . ($bullets !== '' ? '<ul class="h4wp-seo-depth__list">' . $bullets . '</ul>' : '')
            . ($links !== '' ? '<nav class="h4wp-seo-depth__links" aria-label="Related Help4 WordPress guidance">' . $links . '</nav>' : '')
            . '</div></section>';
    }

    private function h4SalesHomepageContent(string $callUrl, string $ticketUrl): string
    {
        $diyUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/basic-hosting-4-me';
        $standardUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/help-4-me-standard';
        $growthUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/help-4-me-more';
        $priorityUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/help-4-me-always';
        $heroImage = H4BS_URL . 'assets/images/marketing/help4-wordpress-hosting-hero-20260716.jpg';
        $jonathanImage = H4BS_URL . 'assets/images/marketing/client-work/jonathan-hetrick-realty-20260719.jpg';
        $findYourVoiceImage = H4BS_URL . 'assets/images/marketing/client-work/find-your-voice-foundation-20260719.jpg';

        return '<div class="h4-sales-home">'
            . '<section class="h4-sales-hero"><div class="h4-sales-shell h4-sales-hero__grid"><div class="h4-sales-hero__copy">'
            . '<h1>WordPress hosting from <span>$4.95/mo.</span> Real people when you need more.</h1>'
            . '<p>Launch affordably without getting stranded. Help4 gives you a low-cost WordPress starting point, plus a direct path to managed care, speed, security, SEO, migrations, page builds, and emergency support.</p>'
            . '<div class="h4-sales-actions"><a class="h4-sales-button h4-sales-button--primary" href="' . esc_url($diyUrl) . '" target="_blank" rel="noopener">Start for $4.95/mo</a><a class="h4-sales-button h4-sales-button--secondary" href="' . esc_url($callUrl) . '">Call Sales</a></div>'
            . '<ul class="h4-sales-trust"><li>Direct checkout</li><li>Upgrade anytime</li><li>WordPress 7.1 beta tested</li></ul>'
            . '</div><figure class="h4-sales-hero__media"><img src="' . esc_url($heroImage) . '" alt="Small business WordPress website with Help4 support and hosting health checks" width="1400" height="875" loading="eager" decoding="async" fetchpriority="high"></figure></div></section>'
            . '<section class="h4-sales-journey"><div class="h4-sales-shell"><div class="h4-sales-section-heading"><h2>Start lean. Add help when the site becomes real business.</h2><p>You do not have to guess at server tiers. Choose how much responsibility you want Help4 to carry.</p></div><div class="h4-sales-journey__rail">'
            . '<article><span>01</span><h3>Host</h3><p>Get WordPress online at the lowest entry cost.</p></article>'
            . '<article><span>02</span><h3>Protect</h3><p>Add updates, backups, security, and routine care.</p></article>'
            . '<article><span>03</span><h3>Improve</h3><p>Work on speed, SEO, forms, pages, and conversions.</p></article>'
            . '<article><span>04</span><h3>Hand it off</h3><p>Give Help4 the outcome and let the technical work move.</p></article>'
            . '</div></div></section>'
            . '<section class="h4-sales-pricing"><div class="h4-sales-shell"><div class="h4-sales-section-heading"><h2>One WordPress path. Four levels of help.</h2><p>Begin with hosting, then move up when maintenance, growth work, or urgent problems are worth handing off.</p></div><div class="h4-sales-plan-rail">'
            . $this->h4SalesPlan('DIY Starter', '$4.95', '/mo', 'For owners who handle day-to-day WordPress tasks.', ['Hosting stability', 'Backups and restore assistance', 'Firewall and malware coverage'], $diyUrl, 'Start DIY', true)
            . $this->h4SalesPlan('Managed Care', 'Site care', '', 'For owners who want recurring WordPress chores handled.', ['Core and plugin updates', 'Forms, SSL, and plugin conflicts', 'Routine support tickets'], $standardUrl, 'Choose Managed', false)
            . $this->h4SalesPlan('Growth Support', 'Improve', '', 'For businesses that need the website to produce more.', ['Landing and service pages', 'Speed and conversion work', 'Practical SEO implementation'], $growthUrl, 'Choose Growth', false)
            . $this->h4SalesPlan('Priority Operations', 'Escalate', '', 'For critical sites where delays and failures cost money.', ['Accelerated triage', 'Urgent change requests', 'Critical plugin and theme failures'], $priorityUrl, 'Choose Priority', false)
            . '</div><p class="h4-sales-pricing__help">Not sure which level fits? <a href="' . esc_url($callUrl) . '">Call Help4 sales</a> and describe the site in plain English.</p></div></section>'
            . '<section class="h4-sales-services"><div class="h4-sales-shell h4-sales-services__grid"><div class="h4-sales-section-heading"><h2>Hosting is the starting point. Help4 can do the work around it.</h2><p>Buy only what you need today. The same support path can keep the site healthy, move it, repair it, or turn a design into a working WordPress build.</p><a class="h4-sales-text-link" href="' . esc_url(home_url('/help-4-wordpress/')) . '">Explore every WordPress service</a></div><div class="h4-sales-service-list">'
            . $this->h4SalesService('managed-hosting', 'Managed care', 'Updates, backups, recurring fixes, and routine WordPress support.', home_url('/wordpress-maintenance-care-plans/'))
            . $this->h4SalesService('migration-path', 'WordPress migration', 'Move an existing site and verify links, forms, SSL, and public behavior.', home_url('/wordpress-migration-service/'))
            . $this->h4SalesService('security-shield', 'Security and cleanup', 'Get help with malware symptoms, recovery, hardening, and next steps.', home_url('/wordpress-malware-removal/'))
            . $this->h4SalesService('speed-tuning', 'Speed optimization', 'Improve frontend weight, caching, images, and Core Web Vitals issues.', home_url('/wordpress-speed-optimization/'))
            . $this->h4SalesService('seo-growth', 'SEO and sales pages', 'Build useful service content, metadata, schema, forms, and conversion paths.', home_url('/help-4-wordpress/'))
            . $this->h4SalesService('design-handoff', 'Design to WordPress', 'Hand Help4 a design and get a responsive WordPress implementation.', home_url('/design-to-wordpress/'))
            . '</div></div></section>'
            . '<section class="h4-sales-builder"><div class="h4-sales-shell h4-sales-builder__grid"><figure class="h4-sales-builder__media"><img src="' . esc_url(H4BS_URL . 'assets/tutorial-screens/blank-install/h4bs-blank-builder-studio-20260723.png') . '" alt="Help4 Builder Studio running with the Help4 Blank WordPress theme" width="1440" height="960" loading="lazy" decoding="async"></figure><div class="h4-sales-builder__copy">'
            . '<p class="h4-product-eyebrow">Free builder and companion theme</p><h2>Download the clean WordPress starting point.</h2><p>Help4 Builder Suite handles pages, templates, responsive controls, fields, forms, SEO, security, performance, and commerce. Help4 Blank is the separate lightweight theme that gives the builder a clean site shell without another theme design fighting it.</p>'
            . '<div class="h4-sales-actions"><a class="h4-sales-button h4-sales-button--primary" href="' . esc_url($this->h4TrackedDownloadUrl('blank-theme')) . '">Download Blank Theme</a><a class="h4-sales-button h4-sales-button--dark" href="' . esc_url($this->h4TrackedDownloadUrl('builder-suite')) . '">Download Builder Suite</a></div>'
            . '<ul class="h4-sales-builder__facts"><li>Free public ZIP files</li><li>Works with WordPress 6.5+</li><li>Theme remains a clean starter</li></ul><a class="h4-sales-text-link h4-sales-text-link--light" href="' . esc_url(home_url('/help4-blank-theme/')) . '">See Help4 Blank setup and compatibility</a>'
            . '</div></div></section>'
            . '<section class="h4-sales-proof"><div class="h4-sales-shell"><div class="h4-sales-section-heading"><h2>Real websites for businesses and nonprofits.</h2><p>See Help4 Builder and managed services working together across real estate, community programs, retail, publishing, and the arts.</p></div><div class="h4-sales-proof__rail">'
            . '<article>[h4_website_snapshot url="https://jonathanhetrick.com/" image_url="' . esc_url($jonathanImage) . '" width="800" height="500" refresh="3600" link="false" caption="Jonathan Hetrick Realty"]<h3><a href="https://jonathanhetrick.com/" target="_blank" rel="noopener">Jonathan Hetrick Realty</a></h3></article>'
            . '<article>[h4_website_snapshot url="https://findyourvoice.foundation/" image_url="' . esc_url($findYourVoiceImage) . '" width="800" height="500" refresh="3600" link="false" caption="Find Your Voice Foundation"]<h3><a href="https://findyourvoice.foundation/" target="_blank" rel="noopener">Find Your Voice Foundation</a></h3></article>'
            . '<article>[h4_website_snapshot url="https://zqcreations.com/" width="800" height="500" refresh="3600" link="false" caption="ZQ Creations"]<h3><a href="https://zqcreations.com/" target="_blank" rel="noopener">ZQ Creations</a></h3></article>'
            . '</div><p><a class="h4-sales-text-link" href="' . esc_url(home_url('/portfolio/')) . '">View more recent work</a></p></div></section>'
            . '<section class="h4-sales-faq"><div class="h4-sales-shell h4-sales-faq__grid"><div class="h4-sales-section-heading"><h2>Questions before you start?</h2><p>The short version: start cheap when you can handle WordPress, and call Help4 when you want the work owned.</p></div><div class="h4-sales-faq__list">'
            . '<details><summary>What comes with the $4.95 hosting plan?</summary><p>The DIY plan is for owners who handle normal site tasks. Help4 handles hosting stability, backups, firewall coverage, malware scanning and removal help, and restore assistance.</p></details>'
            . '<details><summary>Can Help4 manage the website for me?</summary><p>Yes. Managed care can cover updates, backups, plugin conflicts, forms, SSL issues, malware cleanup, and routine support requests.</p></details>'
            . '<details><summary>Can you move or rebuild my existing site?</summary><p>Yes. Help4 handles WordPress migration and can turn supplied designs into responsive WordPress pages.</p></details>'
            . '<details><summary>How do I choose a plan?</summary><p>Call sales or send the site URL, the problem, and the outcome you want. Help4 will route you to hosting, managed care, growth work, rescue, or custom scope.</p></details>'
            . '</div></div></section>'
            . '<section class="h4-sales-final"><div class="h4-sales-shell h4-sales-final__inner"><div><h2>Start at $4.95/mo, or tell Help4 what you need handled.</h2><p>You do not need the technical vocabulary. Bring the URL and the business outcome.</p></div><div class="h4-sales-actions"><a class="h4-sales-button h4-sales-button--primary" href="' . esc_url($diyUrl) . '" target="_blank" rel="noopener">Start hosting</a><a class="h4-sales-button h4-sales-button--dark" href="' . esc_url($callUrl) . '">Call sales</a><a class="h4-sales-text-link h4-sales-text-link--light" href="' . esc_url($ticketUrl) . '" target="_blank" rel="noopener">Send a request</a></div></div></section>'
            . '</div>';
    }

    private function h4SalesPortfolioPageContent(string $ticketUrl): string
    {
        $realtorCase = $this->h4PortfolioCaseCard(
            'Full-service Realtor website',
            'Jonathan Hetrick Realty',
            'https://jonathanhetrick.com/',
            'Jonathan Hetrick Realty website screenshot',
            'A custom luxury real-estate website showing how Help4 Builder and managed services can work as one system. The engagement connects branded design, property discovery, seller and buyer conversion paths, publishing, real-estate search data, technical SEO, and ongoing operations.',
            [
                'Responsive Help4 Builder implementation',
                'Property listings and lead-generation paths',
                'Real-estate schema, sitemap, social, and IndexNow support',
                'Managed performance, updates, and technical support',
            ],
            H4BS_URL . 'assets/images/marketing/client-work/jonathan-hetrick-realty-20260719.jpg'
        );
        $nonprofitCase = $this->h4PortfolioCaseCard(
            'Nonprofit Builder rebuild',
            'Find Your Voice Foundation',
            'https://findyourvoice.foundation/',
            'Find Your Voice Foundation website screenshot',
            'A nonprofit rebuild centered on mission clarity and community action. Help4 Builder supports the organization\'s programs, donations, events, scholarship information, responsive navigation, and performing and healing arts story without making the team maintain a developer-only theme.',
            [
                'Mission, program, and community storytelling',
                'Donation, event, scholarship, and contact routes',
                'Responsive navigation and accessible content structure',
                'Builder-controlled pages for easier nonprofit updates',
            ],
            H4BS_URL . 'assets/images/marketing/client-work/find-your-voice-foundation-20260719.jpg'
        );

        $moreCases = [
            ['Service brand', 'ZQ Creations', 'https://zqcreations.com/', 'Visual-first service presentation with direct contact paths, clear proof, and a structure local customers can understand quickly.'],
            ['Migration service', 'Migration Monkey', 'https://migrationmonkey.com/', 'Migration-focused positioning and action paths for customers who need a WordPress move handled without sorting through the technical details.'],
            ['Commerce and content', 'Live & Signed', 'https://liveandsigned.com/', 'Commerce and event-style content where brand proof, catalog movement, and checkout confidence have to work together.'],
            ['Regional storefront', 'Live & Signed US', 'https://liveandsigned.us/', 'Regional storefront presentation with a shared brand system, useful content rhythm, and a supportable operating model.'],
            ['Organization site', 'BADPD', 'https://badpd.com/', 'Community and organizational site work shaped around clear navigation, trust, security, and reliable delivery.'],
            ['Events and arts', 'Barclay Performing Arts', 'https://barclayperformingarts.com/', 'Arts and events work where schedules, trust, imagery, and conversion paths need polish without becoming difficult to manage.'],
            ['Publisher site', 'AK Vape News', 'https://akvapenews.com/', 'Content-heavy WordPress work with publishing flow, topical structure, and room to grow without turning the reading experience into clutter.'],
        ];
        $moreCards = '';
        foreach ($moreCases as [$category, $name, $url, $summary]) {
            $moreCards .= $this->h4PortfolioCompactCard($category, $name, $url, $summary);
        }

        return '<div class="h4-portfolio-page">'
            . '<section class="h4-product-hero h4wp-noise-overlay h4wp-soft-glow"><div class="h4-product-hero__grid"><div class="h4-product-hero__body">'
            . '<p class="h4-product-eyebrow">Client work</p><h2>Websites built around what each organization actually needs.</h2>'
            . '<p class="h4-product-lede">Help4 combines visual Builder implementation with hosting, integrations, performance, security, search visibility, content structure, and ongoing support. These live examples show a real-estate professional and a nonprofit organization using different parts of that system.</p>'
            . '<p class="h4-product-hero__actions"><a class="button button-primary" href="' . esc_url(home_url('/design-to-wordpress/')) . '">Plan a Website Build</a> <a class="button" href="' . esc_url($ticketUrl) . '" target="_blank" rel="noopener">Request Site Work</a></p>'
            . '</div><aside class="h4-product-command"><p class="h4-product-command__label">Live client proof</p><div class="h4-product-command__row"><span>Examples</span><strong>9 public websites</strong></div><div class="h4-product-command__row"><span>Organizations</span><strong>Realtor and nonprofit</strong></div><div class="h4-product-command__row"><span>Stack</span><strong>Builder plus managed services</strong></div></aside></div></section>'
            . '<section class="h4wp-section h4-client-showcase" id="brands-and-organizations"><div class="h4wp-section__header"><p class="h4-product-eyebrow">Brands and organizations we help</p><h2>Different missions need different website systems.</h2><p>The strongest Help4 work is not a repeated demo with a new logo. The Builder, data, search, conversion, and support layers are shaped around the organization\'s actual customers and operating needs.</p></div>'
            . '<div class="h4-client-category" data-client-category="realtors"><div class="h4-client-category__header"><p class="h4-client-category__label">Realtors and real estate</p><h3>Real-estate websites built to market properties and win qualified clients.</h3><p>Property discovery, seller and buyer lead paths, listing data, local visibility, performance, and ongoing technical ownership can stay under one Help4 engagement.</p></div>' . $realtorCase . '</div>'
            . '<div class="h4-client-category" data-client-category="nonprofit"><div class="h4-client-category__header"><p class="h4-client-category__label">Nonprofits</p><h3>Mission-first websites that make action easier.</h3><p>Programs, donations, events, volunteers, and community stories need a clear public path and an editing workflow the organization can continue using.</p></div>' . $nonprofitCase . '</div>'
            . '</section>'
            . '<section class="h4wp-section h4-portfolio-more" id="more-client-work"><div class="h4wp-section__header"><p class="h4-product-eyebrow">More client work</p><h2>Brands across services, commerce, publishing, organizations, and the arts.</h2><p>Each website links to the live public result and uses Help4 Builder Website Snapshot for current visual proof.</p></div><div class="h4wp-card-grid h4-recent-work-grid">' . $moreCards . '</div></section>'
            . '<section class="h4wp-section h4wp-section--contrast"><div class="h4wp-section__header"><p class="h4-product-eyebrow">Your website path</p><h2>Bring the business outcome, not a list of plugin names.</h2><p>Help4 can start from an existing website, a supplied design, screenshots, brand files, a migration, or a blank installation. The work can stop at hosting or expand into a complete build and long-term managed operation.</p></div><div class="h4wp-card-grid"><article class="h4wp-card"><h3>Build it</h3><p>Turn designs, requirements, content, products, listings, programs, and forms into a responsive Help4 Builder website.</p></article><article class="h4wp-card"><h3>Improve it</h3><p>Repair mobile behavior, performance, search metadata, schema, accessibility, conversion paths, and content structure.</p></article><article class="h4wp-card"><h3>Run it</h3><p>Keep hosting, updates, security, monitoring, support, and future website changes connected to the same team.</p></article></div></section>'
            . '</div>';
    }

    /**
     * @param array<int, string> $features
     */
    private function h4PortfolioCaseCard(
        string $category,
        string $name,
        string $url,
        string $caption,
        string $summary,
        array $features,
        string $imageUrl = ''
    ): string {
        $items = '';
        foreach ($features as $feature) {
            $items .= '<li>' . esc_html($feature) . '</li>';
        }

        $imageAttribute = $imageUrl !== '' ? ' image_url="' . esc_url($imageUrl) . '"' : '';

        return '<article class="h4-client-case"><div class="h4-client-case__media">[h4_website_snapshot url="' . esc_url($url) . '"' . $imageAttribute . ' width="1200" height="760" refresh="21600" link="false" caption="' . esc_attr($caption) . '" class="h4-client-case__snapshot"]</div><div class="h4-client-case__body">'
            . '<p class="h4-client-category__label">' . esc_html($category) . '</p><h4><a href="' . esc_url($url) . '" target="_blank" rel="noopener">' . esc_html($name) . '</a></h4><p>' . esc_html($summary) . '</p>'
            . ($items !== '' ? '<ul class="h4-client-case__features">' . $items . '</ul>' : '')
            . '<a class="h4-client-case__link" href="' . esc_url($url) . '" target="_blank" rel="noopener">Visit ' . esc_html($name) . '</a>'
            . '</div></article>';
    }

    private function h4PortfolioCompactCard(string $category, string $name, string $url, string $summary): string
    {
        return '<article class="h4wp-card h4-work-card"><p class="h4-product-eyebrow">' . esc_html($category) . '</p>'
            . '[h4_website_snapshot url="' . esc_url($url) . '" width="960" height="540" refresh="21600" link="false" caption="' . esc_attr($name . ' website screenshot') . '" class="h4-recent-work-snapshot"]'
            . '<h3><a href="' . esc_url($url) . '" target="_blank" rel="noopener">' . esc_html($name) . '</a></h3><p>' . esc_html($summary) . '</p>'
            . '<p><a class="button" href="' . esc_url($url) . '" target="_blank" rel="noopener">Visit ' . esc_html($name) . '</a></p></article>';
    }

    /**
     * @param array<int, string> $features
     */
    private function h4SalesPlan(string $name, string $price, string $suffix, string $fit, array $features, string $url, string $button, bool $featured): string
    {
        $html = '<article class="h4-sales-plan' . ($featured ? ' is-featured' : '') . '"><p class="h4-sales-plan__name">' . esc_html($name) . '</p><p class="h4-sales-plan__price">' . esc_html($price) . '<span>' . esc_html($suffix) . '</span></p><p class="h4-sales-plan__fit">' . esc_html($fit) . '</p><ul>';
        foreach ($features as $feature) {
            $html .= '<li>' . esc_html($feature) . '</li>';
        }
        return $html . '</ul><a class="h4-sales-plan__link" href="' . esc_url($url) . '" target="_blank" rel="noopener">' . esc_html($button) . '</a></article>';
    }

    private function h4SalesService(string $icon, string $title, string $description, string $url): string
    {
        $iconUrl = H4BS_URL . 'assets/icons/defaults/' . sanitize_file_name($icon) . '.svg';
        return '<article class="h4-sales-service"><img src="' . esc_url($iconUrl) . '" alt="" width="40" height="40" loading="lazy" decoding="async"><div><h3><a href="' . esc_url($url) . '">' . esc_html($title) . '</a></h3><p>' . esc_html($description) . '</p></div></article>';
    }
    private function seedExternalCommerceBridgePages(): void
    {
        $salesCallUrl = esc_url(ContactRoutes::salesCallUrl());
        $salesSmsUrl = esc_url(ContactRoutes::salesSmsUrl());
        $salesWhatsAppUrl = esc_url(ContactRoutes::salesWhatsAppUrl());
        $salesPhoneDisplay = esc_html(ContactRoutes::salesPhoneDisplay());
        $supportTicketUrl = esc_url(ContactRoutes::supportTicketUrl());
        $supportRepUrl = esc_url(ContactRoutes::supportRepUrl());
        $clientAreaUrl = esc_url(ContactRoutes::supportClientAreaUrl());

        $salesActions = '<div class="h4-sales-actions">'
            . '<a class="button button-primary" href="' . $salesSmsUrl . '">Text Sales</a> '
            . '<a class="button" href="' . $salesWhatsAppUrl . '" target="_blank" rel="noopener">WhatsApp Sales</a> '
            . '<a class="button" href="' . $salesCallUrl . '">Call Sales</a>'
            . '</div>';
        $salesActionsNote = '<p><small>Sales line: <a href="' . $salesCallUrl . '">' . $salesPhoneDisplay . '</a>. '
            . 'For escalations, text is fastest: <a href="' . $salesSmsUrl . '">SMS ' . $salesPhoneDisplay . '</a>.</small></p>';
        $supportRoutingNote = '<p><strong>Support routing:</strong> Self-managed plans use ticket support only. '
            . 'Fully managed plans can open a ticket or contact their account rep. '
            . 'Calls can request escalation, but SMS escalations are normally fastest.</p>';

        $shopId = $this->upsertPage(
            'shop',
            'Managed WordPress Hosting Plans',
            wp_kses_post(
                '<section class="h4-product-hero h4-product-hero--shop h4wp-noise-overlay h4wp-soft-glow">'
                . '<div class="h4-product-hero__grid">'
                . '<div class="h4-product-hero__body">'
                . '<p class="h4-product-eyebrow">Managed WordPress Hosting</p>'
                . '<h2>Start small. Get serious support the moment WordPress gets real.</h2>'
                . '<p class="h4-product-lede">Help4 gives you the cheap entry point budget hosts advertise, then adds the human execution most managed hosts hide behind dashboards. Launch at $4.95/mo, or move straight into done-for-you care.</p>'
                . '<div class="h4-product-hero__actions">'
                . '<a class="button button-primary" href="https://help4network.com/store/" target="_blank" rel="noopener">Browse Hosting Plans</a> '
                . '<a class="button" href="https://help4network.com/cart/" target="_blank" rel="noopener">Open Cart</a>'
                . '</div>'
                . '<div class="h4-product-hero__proof">'
                . '<span>DIY launch lane</span><span>Managed upgrade path</span><span>Ticket + rep routing</span>'
                . '</div>'
                . $salesActions
                . $salesActionsNote
                . '</div>'
                . '<aside class="h4-product-command" aria-label="Help4 hosting snapshot">'
                . '<p class="h4-product-command__label">Help4 Hosting Path</p>'
                . '<div class="h4-product-command__price"><strong>$4.95</strong><span>/mo starter</span></div>'
                . '<div class="h4-product-command__row"><span>Launch</span><strong>cPanel + Installatron</strong></div>'
                . '<div class="h4-product-command__row"><span>Protect</span><strong>SSL, DNS, hardening checks</strong></div>'
                . '<div class="h4-product-command__row"><span>Grow</span><strong>SEO + performance support</strong></div>'
                . '<div class="h4-product-command__row"><span>Escalate</span><strong>Tickets, text, account rep paths</strong></div>'
                . '</aside>'
                . '</div>'
                . '</section>'
                . '<section class="h4-product-lanes">'
                . '<div class="h4-section-kicker"><p class="h4-product-eyebrow">Choose your lane</p><h2>Not every WordPress site needs the same amount of help.</h2><p>Pick the lane that matches how much you want Help4 to handle. You can start lean and climb when traffic, revenue, or sanity requires it.</p></div>'
                . '<div class="h4-product-lane-grid">'
                . '<article class="h4-product-lane">'
                . '<p class="h4-product-lane__meta">DIY Launch</p>'
                . '<h3>Self Hosting 4 Me</h3>'
                . '<p class="h4-product-lane__price">$4.95<span>/mo</span></p>'
                . '<p class="h4-product-lane__fit">Best for new projects, test sites, and owners who can handle routine WordPress tasks.</p>'
                . '<ul><li>Low-cost WordPress hosting</li><li>cPanel + one-click installer workflow</li><li>Ticket-first support</li></ul>'
                . '<p><a class="button" href="https://help4network.com/store/?s=self+hosting" target="_blank" rel="noopener">Start at $4.95/mo</a></p>'
                . '</article>'
                . '<article class="h4-product-lane">'
                . '<p class="h4-product-lane__meta">Managed Baseline</p>'
                . '<h3>Help4 Me Standard</h3>'
                . '<p class="h4-product-lane__fit">Best when updates, edits, and basic upkeep should stop eating your day.</p>'
                . '<ul><li>Core and plugin maintenance</li><li>Content and layout help</li><li>Security and uptime checks</li></ul>'
                . '<p><a class="button" href="https://help4network.com/store/?s=standard" target="_blank" rel="noopener">Select Standard</a></p>'
                . '</article>'
                . '<article class="h4-product-lane h4-product-lane--featured">'
                . '<p class="h4-product-lane__meta">Growth Care</p>'
                . '<h3>Help4 Me Advanced</h3>'
                . '<p class="h4-product-lane__fit">Best for active businesses that need speed, search visibility, and conversion work moving together.</p>'
                . '<ul><li>Performance tuning</li><li>SEO-aware implementation</li><li>Faster turnaround priority</li></ul>'
                . '<p><a class="button button-primary" href="https://help4network.com/store/?s=advanced" target="_blank" rel="noopener">Select Advanced</a></p>'
                . '</article>'
                . '<article class="h4-product-lane">'
                . '<p class="h4-product-lane__meta">Priority Ops</p>'
                . '<h3>Pro / Enterprise</h3>'
                . '<p class="h4-product-lane__fit">Best for revenue-critical sites, multi-site owners, and teams that need escalation paths.</p>'
                . '<ul><li>Priority queues</li><li>Account rep routing</li><li>Custom launch and migration scope</li></ul>'
                . '<p><a class="button" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Request Priority Scope</a></p>'
                . '</article>'
                . '</div>'
                . '</section>'
                . '<section class="h4-product-feature-band">'
                . '<div><p class="h4-product-eyebrow">Why Help4</p><h2>Budget-host entry. Managed-host brains. One path.</h2></div>'
                . '<div class="h4-product-feature-grid">'
                . '<article><strong>No rebuild trap</strong><p>Bring the site you have and improve it in phases.</p></article>'
                . '<article><strong>Performance is part of the work</strong><p>Cache, image, frontend, and Core Web Vitals checks sit inside the service path.</p></article>'
                . '<article><strong>Support is routed like operations</strong><p>Tickets stay tracked, and qualified managed tiers can escalate through account reps.</p></article>'
                . '</div>'
                . '</section>'
                . '<section class="h4-product-compare-cards">'
                . '<article class="h4-product-compare-card"><h3>Budget hosts</h3><p>Cheap entry, but you own the troubleshooting, tuning, plugins, and cleanup.</p></article>'
                . '<article class="h4-product-compare-card"><h3>Big managed hosts</h3><p>Strong infrastructure, but support often stops at platform boundaries.</p></article>'
                . '<article class="h4-product-compare-card h4-product-compare-card--featured"><h3>Help4 WordPress</h3><p>Hosting plus implementation help, support routing, and a real path from DIY to managed.</p></article>'
                . '</section>'
                . '<section class="h4-sales-cta h4-product-cta">'
                . '<div><p class="h4-product-eyebrow">Need custom scope?</p><h2>Tell us what is broken, slow, risky, or ready to grow.</h2><p>We will map the fastest plan path for your business without making you decode a server sizing chart.</p></div>'
                . '<p><a class="button button-primary" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Open a Ticket</a> <a class="button" href="' . $supportRepUrl . '" target="_blank" rel="noopener">Contact Account Rep</a></p>'
                . '</section>'
                . $supportRoutingNote
                . '<section class="h4-shop-catalog h4-product-catalog">'
                . '<h2>Plan Catalog</h2>'
                . '<p>Filter products fast and route checkout to Help4 WordPress securely.</p>'
                . '[h4_products limit="8" show_filters="1" bg_color="#08121f" bg_gradient="linear-gradient(135deg,rgba(5,18,34,.92),rgba(9,95,125,.72))" panel_bg="rgba(255,255,255,.94)" panel_border="rgba(133,183,218,.35)" panel_padding="18px" panel_radius="16px"]'
                . '</section>'
            )
        );

        $packagesId = $this->upsertPage(
            'packages',
            'WordPress Packages from $4.95/mo',
            wp_kses_post(
                '<section class="h4-product-hero h4-product-hero--packages h4wp-noise-overlay h4wp-soft-glow">'
                . '<div class="h4-product-hero__grid">'
                . '<div class="h4-product-hero__body">'
                . '<p class="h4-product-eyebrow">Packages built by support level</p>'
                . '<h2>Choose the level of help, not just a server size.</h2>'
                . '<p class="h4-product-lede">Most hosting pages make you compare visits, storage, and buzzwords. Help4 packages are simpler: decide how much work you want off your plate, then route checkout through Help4 WordPress.</p>'
                . '<div class="h4-product-hero__actions">'
                . '<a class="button button-primary" href="https://help4network.com/store/" target="_blank" rel="noopener">View Live Pricing</a> '
                . '<a class="button" href="https://help4network.com/cart/" target="_blank" rel="noopener">Open Cart</a>'
                . '</div>'
                . $salesActions
                . $salesActionsNote
                . '</div>'
                . '<aside class="h4-product-command">'
                . '<p class="h4-product-command__label">Package Ladder</p>'
                . '<div class="h4-tier-mini"><span>DIY</span><span>Standard</span><span>Advanced</span><span>Pro</span><span>Enterprise</span></div>'
                . '<p>Move up when the site becomes important enough that mistakes, delays, and slow pages cost more than the plan.</p>'
                . '</aside>'
                . '</div>'
                . '</section>'
                . '<section class="h4-tier-ladder">'
                . '<div class="h4-section-kicker"><p class="h4-product-eyebrow">The ladder</p><h2>From cheap hosting to full operating support.</h2></div>'
                . '<div class="h4-tier-ladder__track">'
                . '<article><span>01</span><h3>Launch</h3><p>DIY hosting and first-site setup.</p></article>'
                . '<article><span>02</span><h3>Stabilize</h3><p>Updates, security, and routine WordPress help.</p></article>'
                . '<article><span>03</span><h3>Grow</h3><p>Speed, SEO, content, and conversion improvements.</p></article>'
                . '<article><span>04</span><h3>Operate</h3><p>Priority workflows for sites that matter every day.</p></article>'
                . '</div>'
                . '</section>'
                . '<section class="h4wp-package-block">'
                . '<div class="h4-section-kicker"><p class="h4-product-eyebrow">Plan cards</p><h2>Package tiers with actual fit guidance.</h2></div>'
                . '<div class="h4-package-grid">'
                . '<article class="h4-package-card">'
                . '<div class="h4-package-card__top"><span>DIY</span><strong>$4.95/mo</strong></div>'
                . '<h3>Self Hosting 4 Me</h3>'
                . '<p class="h4-package-card__fit">For owners who want the lowest launch cost and can handle the basics.</p>'
                . '<ul><li>cPanel + Installatron workflow</li><li>SSL and DNS checks</li><li>Ticket-first support</li></ul>'
                . '<p><a class="button" href="https://help4network.com/store/?s=self+hosting" target="_blank" rel="noopener">Start at $4.95/mo</a></p>'
                . '</article>'
                . '<article class="h4-package-card">'
                . '<div class="h4-package-card__top"><span>Managed</span><strong>Standard</strong></div>'
                . '<h3>Help4 Me Standard</h3>'
                . '<p class="h4-package-card__fit">For small businesses that need WordPress upkeep handled consistently.</p>'
                . '<ul><li>Core and plugin maintenance</li><li>Security and uptime checks</li><li>Content and layout edits</li></ul>'
                . '<p><a class="button" href="https://help4network.com/store/?s=standard" target="_blank" rel="noopener">Select Standard</a></p>'
                . '</article>'
                . '<article class="h4-package-card h4-package-card--featured">'
                . '<div class="h4-package-card__top"><span>Best Fit</span><strong>Advanced</strong></div>'
                . '<h3>Help4 Me Advanced</h3>'
                . '<p class="h4-package-card__fit">For businesses that need performance, SEO, and conversion work moving faster.</p>'
                . '<ul><li>Core Web Vitals focus</li><li>SEO-aware implementation</li><li>Faster turnaround priority</li></ul>'
                . '<p><a class="button button-primary" href="https://help4network.com/store/?s=advanced" target="_blank" rel="noopener">Select Advanced</a></p>'
                . '</article>'
                . '<article class="h4-package-card">'
                . '<div class="h4-package-card__top"><span>Priority</span><strong>Pro</strong></div>'
                . '<h3>Help4 Me Pro</h3>'
                . '<p class="h4-package-card__fit">For revenue-critical sites that need stronger oversight and faster escalation.</p>'
                . '<ul><li>Priority support queues</li><li>Advanced hardening</li><li>Operational guidance</li></ul>'
                . '<p><a class="button" href="https://help4network.com/store/?s=pro" target="_blank" rel="noopener">Select Pro</a></p>'
                . '</article>'
                . '<article class="h4-package-card">'
                . '<div class="h4-package-card__top"><span>Custom</span><strong>Enterprise</strong></div>'
                . '<h3>Help4 Me Enterprise</h3>'
                . '<p class="h4-package-card__fit">For agencies, larger teams, high-traffic sites, and custom support workflows.</p>'
                . '<ul><li>Custom onboarding</li><li>Team-level process integration</li><li>Account rep + strategic support</li></ul>'
                . '<p><a class="button" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Request Enterprise Scope</a></p>'
                . '</article>'
                . '</div>'
                . '</section>'
                . '<section class="h4-product-feature-band">'
                . '<div><p class="h4-product-eyebrow">Included mindset</p><h2>Every managed tier is built around outcomes.</h2></div>'
                . '<div class="h4-product-feature-grid">'
                . '<article><strong>Security</strong><p>Hardening, patching, and response workflows aligned to WordPress reality.</p></article>'
                . '<article><strong>Speed</strong><p>Cache, image, query, and frontend improvements that support real visitors.</p></article>'
                . '<article><strong>Execution</strong><p>Implementation help for fixes, edits, pages, and improvements instead of advice-only support.</p></article>'
                . '</div>'
                . '</section>'
                . '<section class="h4wp-compare">'
                . '<table>'
                . '<thead><tr><th>Capability</th><th>DIY Starter ($4.95/mo)</th><th>Standard/Advanced/Pro/Enterprise</th></tr></thead>'
                . '<tbody>'
                . '<tr><td>Hosting platform</td><td>Managed baseline</td><td>Managed + expanded support layers</td></tr>'
                . '<tr><td>Support routing</td><td>Ticket-first</td><td>Ticket + account rep for qualified plans</td></tr>'
                . '<tr><td>Performance optimization</td><td>Core checks</td><td>Advanced tuning and guidance</td></tr>'
                . '<tr><td>Security posture</td><td>Baseline hardening</td><td>Deeper hardening and response workflows</td></tr>'
                . '<tr><td>Business growth support</td><td>Limited</td><td>Strong focus on SEO, conversion, and reliability</td></tr>'
                . '</tbody>'
                . '</table>'
                . '</section>'
                . '<section class="h4wp-final-cta h4-product-cta">'
                . '<div><p class="h4-product-eyebrow">Need a recommendation?</p><h2>Tell us your traffic, stack, and what you cannot afford to break.</h2><p>We will map you to the right package quickly, then send you to the correct Help4 WordPress checkout path.</p></div>'
                . '<p><a class="button button-primary" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Talk to Help4</a> <a class="button" href="https://help4network.com/store/" target="_blank" rel="noopener">Browse Plans</a></p>'
                . '</section>'
                . $supportRoutingNote
            )
        );

        $checkoutId = $this->upsertPage(
            'checkout',
            'Checkout',
            wp_kses_post(
                '<h1>Secure Checkout</h1>'
                . '<p>Checkout is processed on the Help4 WordPress commerce stack for secure payment routing and order handling.</p>'
                . '<p><a class="button button-primary" href="https://help4network.com/cart/" target="_blank" rel="noopener">Continue to Cart</a></p>'
                . '<p><a class="button" href="https://help4network.com/store/" target="_blank" rel="noopener">Browse Plans</a></p>'
                . $salesActions
                . $salesActionsNote
            )
        );

        $clientAreaId = $this->upsertPage(
            'client-area',
            'Client Area',
            wp_kses_post(
                '<h1>Client Area & Billing</h1>'
                . '<p>Manage invoices, services, support requests, and account details from your secure client portal.</p>'
                . '<p><a class="button button-primary" href="' . $clientAreaUrl . '" target="_blank" rel="noopener">Open Client Area</a></p>'
                . '<p><a class="button" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Create Support Ticket</a></p>'
            )
        );

        $hostingPageId = $this->upsertPage(
            'fully-managed-wordpress-hosting',
            'Fully Managed WordPress Hosting',
            wp_kses_post(
                '<h1>WordPress Hosting That Starts at $4.95/mo and Scales to Fully Managed</h1>'
                . '<p>Start with affordable DIY hosting, then switch on done-for-you execution anytime. Help4 gives you a clean growth path without rebuilding your stack.</p>'
                . '<h2>How It Works</h2>'
                . '<ol>'
                . '<li>You request work in plain language.</li>'
                . '<li>Our team executes design, content, maintenance, and optimization tasks.</li>'
                . '<li>You review and approve changes while we keep your stack stable and secure.</li>'
                . '</ol>'
                . '<h2>Best For</h2>'
                . '<ul>'
                . '<li>Agencies that need white-label production support</li>'
                . '<li>Local businesses that need reliable updates without hiring in-house</li>'
                . '<li>Growing brands that need speed, SEO, and security built into operations</li>'
                . '</ul>'
                . '<p><a class="button button-primary" href="https://help4network.com/store/" target="_blank" rel="noopener">Start Managed Hosting</a></p>'
                . $salesActions
                . $salesActionsNote
            )
        );

        $supportPageId = $this->upsertPage(
            'wordpress-support',
            'WordPress Support',
            wp_kses_post(
                '<h2>WordPress Support</h2>'
                . '<p>Every support request starts in ticketing so nothing is missed.</p>'
                . '<h2>What To Include In The Request</h2>'
                . '<p>Send the site URL, the page or screen involved, what you expected to happen, what happened instead, and whether the problem blocks sales, leads, staff, or visitors. Include the last change you remember, the time the issue started, and a screenshot when it makes the problem easier to see.</p>'
                . '<ul><li>Do not place passwords, payment keys, private customer records, or authentication codes in the first message.</li><li>Say whether Help4 may work immediately or whether changes need approval before publishing.</li><li>List any deadline, active campaign, checkout impact, or legal/compliance concern that changes the priority.</li></ul>'
                . '<h2>What Happens Next</h2>'
                . '<p>Help4 records the request, confirms the affected site and business impact, then routes the work to the right support, design, commerce, security, or infrastructure lane. A complex request may be split into diagnosis, approval, implementation, and verification so the customer can see what is happening instead of receiving a vague answer.</p>'
                . '<h2>Self-Managed Support</h2>'
                . '<p>Self-managed plans use ticket-first support. The ticket keeps the request, site details, replies, and completion evidence together. Work outside the active plan may need a separate scope before implementation begins.</p>'
                . '<p><a class="button button-primary" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Create Support Ticket</a></p>'
                . '<h2>Fully Managed Support</h2>'
                . '<p>Fully managed customers can use ticketing or contact their account rep directly. Routine requests still belong in the ticket so updates, page edits, plugin conflicts, forms, security checks, speed work, and follow-up testing are not lost between messages.</p>'
                . '<p>'
                . '<a class="button button-primary" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Open Ticket</a> '
                . '<a class="button" href="' . $supportRepUrl . '" target="_blank" rel="noopener">Contact Account Rep</a>'
                . '</p>'
                . '<h2>Escalations</h2>'
                . '<p>Calls can request escalation, but SMS usually escalates faster than the sales queue. Mark a request urgent when checkout is unavailable, a production page is broken, the site shows a security warning, customer data may be exposed, or a time-sensitive campaign cannot run. Urgent does not replace the ticket; it helps the team find the existing record faster.</p>'
                . '<p>'
                . '<a class="button" href="' . $salesCallUrl . '">Call ' . $salesPhoneDisplay . '</a> '
                . '<a class="button" href="' . $salesSmsUrl . '">SMS ' . $salesPhoneDisplay . '</a> '
                . '<a class="button" href="' . $salesWhatsAppUrl . '" target="_blank" rel="noopener">WhatsApp</a>'
                . '</p>'
                . '<h2>Before The Request Is Closed</h2>'
                . '<p>Verify the original problem on the public site, not only in the editor or server. Check the affected desktop and phone view, the important link or button, and any form, checkout, login, or account action involved. Confirm that caches were cleared when needed and that the final page does not show a private preview, maintenance screen, mixed-content warning, duplicate template, or horizontal clipping.</p>'
                . '<p>Reply on the same ticket if the result is incomplete. Include the exact URL and what still differs from the requested outcome so the team can continue from the existing evidence instead of starting the diagnosis again.</p>'
            )
        );

        $commerceSupportId = $this->upsertPage(
            'commerce-support',
            'Help4 Commerce Support',
            wp_kses_post($this->h4ProductCommerceSupportPage($supportTicketUrl, $clientAreaUrl))
        );
        $legacyCommerceSupportId = 0;

        $faqPageId = $this->upsertPage(
            'wordpress-hosting-faq',
            'WordPress Hosting FAQ',
            wp_kses_post(
                '<h2>WordPress Hosting FAQ</h2>'
                . '<p>Answers for customers moving to fully managed WordPress with Help4.</p>'
                . '<details open><summary><strong>What does "fully managed WordPress" mean?</strong></summary><p>It means Help4 handles the technical operations for your WordPress site: updates, security, performance, troubleshooting, and requested changes.</p></details>'
                . '<details><summary><strong>Can I just ask for changes in plain English?</strong></summary><p>Yes. Many customers simply send "Do this" style requests. Our team translates that into implementation tasks.</p></details>'
                . '<details><summary><strong>Do you migrate existing WordPress websites?</strong></summary><p>Yes. We can migrate sites, preserve URLs where possible, and validate SEO + performance after migration.</p></details>'
                . '<details><summary><strong>Where do payments and checkout run?</strong></summary><p>Checkout and billing are processed on Help4 WordPress to keep payment routing centralized and reliable.</p></details>'
                . '<details><summary><strong>Can you support stores, membership sites, and booking flows?</strong></summary><p>Yes. We support business sites, commerce flows, subscriptions, booking workflows, and integration-heavy projects.</p></details>'
                . '<details><summary><strong>What if I need custom development?</strong></summary><p>We can scope custom work and route it to the right team, then maintain it under your managed plan.</p></details>'
                . '<details><summary><strong>What is included in the $4.95 hosting path?</strong></summary><p>The entry plan is for customers who want an affordable WordPress starting point and expect to handle normal content, plugin, theme, and day-to-day site decisions themselves. The final Help4 Network product page controls current billing and included service terms.</p></details>'
                . '<details><summary><strong>Can I start with hosting and add help later?</strong></summary><p>Yes. The Help4 path is designed so a customer can begin with hosting, then move into managed maintenance, growth work, priority support, migration, security cleanup, page building, or a custom scope when the site needs more ownership.</p></details>'
                . '<details><summary><strong>How do I choose between DIY and managed care?</strong></summary><p>Choose DIY when you are comfortable handling routine WordPress work and only need the hosting path. Choose managed care when updates, plugin conflicts, backups, forms, site edits, security, or technical decisions should have a person responsible for completing and verifying them.</p></details>'
                . '<details><summary><strong>What should I send when asking for a plan recommendation?</strong></summary><p>Send the site URL, the main business goal, the problems you want off your list, any deadline, and whether the website handles leads, payments, bookings, memberships, or customer accounts. Help4 can route the request without requiring you to know the technical vocabulary.</p></details>'
                . '<details><summary><strong>How are support replies delivered?</strong></summary><p>Help4 replies may arrive from help4network.com or help4.us. Check spam, promotions, and other filtered folders when you are waiting for a response, and keep the ticket number in the email subject so the conversation stays connected.</p></details>'
                . '<p><a class="button button-primary" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Ask a Question</a></p>'
                . $supportRoutingNote
                . $salesActions
            )
        );

        $mediaBase = trailingslashit(home_url('/help4-media/screenshots'));

        $builderTutorialsId = $this->upsertPage(
            'help4-builder-tutorials',
            'Help4 Builder Tutorials',
            $this->sanitizeTutorialHubHtml($this->h4BuilderDocsHubPage($supportTicketUrl))
        );
        $builderScreenshotsId = $this->upsertPage(
            'help4-builder-screenshots',
            'Help4 Builder Screenshots',
            wp_kses_post($this->h4BuilderScreenshotsPage($supportTicketUrl))
        );
        $builderGuideId = $this->upsertPage(
            'help4-builder-guide',
            'Help4 Builder Guide',
            wp_kses_post($this->h4BuilderInstallGuidePage($supportTicketUrl))
        );
        $builderFirstPageId = $this->upsertPage(
            'help4-builder-first-page',
            'Build Your First Help4 Builder Page',
            wp_kses_post($this->h4BuilderFirstPageGuide($supportTicketUrl))
        );
        $builderEditorControlsId = $this->upsertPage(
            'help4-builder-editor-controls',
            'Help4 Builder Editor Controls Explained',
            wp_kses_post($this->h4BuilderEditorControlsGuide($supportTicketUrl))
        );
        $builderWpCliRunnersId = $this->upsertPage(
            'help4-builder-wp-cli-runners',
            'Help4 Builder WP-CLI Runner Guide',
            wp_kses_post($this->h4BuilderWpCliRunnersGuide($supportTicketUrl))
        );
        $builderTemplatesId = $this->upsertPage(
            'help4-builder-templates',
            'Help4 Builder Templates and Icons',
            wp_kses_post($this->h4BuilderTemplatesGuide($supportTicketUrl))
        );
        $builderTemplateLibraryId = $this->upsertPage(
            'help4-builder-template-library',
            'Help4 Builder Template Library',
            wp_kses_post($this->h4BuilderTemplateLibraryGuide($supportTicketUrl))
        );
        $builderIconsId = $this->upsertPage(
            'help4-builder-icons',
            'Help4 Builder Default Icon Library',
            wp_kses_post($this->h4BuilderIconsGuide($supportTicketUrl))
        );
        $builderModuleControlsId = $this->upsertPage(
            'help4-builder-module-controls',
            'Help4 Builder Module Controls',
            wp_kses_post($this->h4BuilderModuleControlsGuide($supportTicketUrl))
        );
        $builderFieldsId = $this->upsertPage(
            'help4-builder-fields',
            'Help4 Builder Structured Fields',
            wp_kses_post($this->h4BuilderFieldsGuide($supportTicketUrl))
        );
        $builderCommerceId = $this->upsertPage(
            'help4-commerce-getting-started',
            'Help4 Commerce Getting Started',
            wp_kses_post($this->h4BuilderCommerceGuide($supportTicketUrl))
        );
        $builderSlidersFormsId = $this->upsertPage(
            'help4-builder-sliders-forms',
            'Help4 Builder Sliders and Forms',
            wp_kses_post($this->h4BuilderSlidersFormsGuide($supportTicketUrl))
        );
        $builderWebsiteSnapshotId = $this->upsertPage(
            'help4-builder-website-snapshot',
            'Help4 Builder Website Snapshot',
            wp_kses_post($this->h4BuilderWebsiteSnapshotGuide($supportTicketUrl))
        );
        $builderLaunchId = $this->upsertPage(
            'help4-builder-seo-security-performance',
            'Help4 Builder SEO, Security and Performance',
            wp_kses_post($this->h4BuilderLaunchGuide($supportTicketUrl))
        );
        $builderUpdatesId = $this->upsertPage(
            'help4-builder-updates-wordpress-7',
            'Help4 Builder Updates and WordPress 7 Readiness',
            wp_kses_post($this->h4BuilderUpdatesGuide($supportTicketUrl))
        );
        $builderSafeEditingId = $this->upsertPage(
            'help4-builder-safe-editing-recovery',
            'Help4 Builder Safe Editing and Page Recovery',
            wp_kses_post($this->h4BuilderSafeEditingGuide($supportTicketUrl))
        );
        $builderResponsiveId = $this->upsertPage(
            'help4-builder-responsive-design',
            'Help4 Builder Responsive Design',
            wp_kses_post($this->h4BuilderResponsiveGuide($supportTicketUrl))
        );
        $builderGlobalsId = $this->upsertPage(
            'help4-builder-global-styles-theme-packs',
            'Help4 Builder Global Styles and Theme Packs',
            wp_kses_post($this->h4BuilderGlobalStylesGuide($supportTicketUrl))
        );
        $builderNavigationId = $this->upsertPage(
            'help4-builder-menus-headers-footers',
            'Help4 Builder Menus, Headers and Footers',
            wp_kses_post($this->h4BuilderNavigationGuide($supportTicketUrl))
        );
        $builderCommerceAdvancedId = $this->upsertPage(
            'help4-commerce-products-variations-customer-fields',
            'Help4 Commerce Products, Variations and Customer Fields',
            wp_kses_post($this->h4BuilderCommerceAdvancedGuide($supportTicketUrl))
        );
        $builderSeoAdvancedId = $this->upsertPage(
            'help4-seo-local-international-indexnow',
            'Help4 SEO Local, International and IndexNow Guide',
            wp_kses_post($this->h4BuilderSeoAdvancedGuide($supportTicketUrl))
        );
        $builderMultisiteId = $this->upsertPage(
            'help4-builder-multisite-guide',
            'Help4 Builder Multisite Guide',
            wp_kses_post($this->h4BuilderMultisiteGuide($supportTicketUrl))
        );
        $builderTroubleshootingId = $this->upsertPage(
            'help4-builder-migration-troubleshooting',
            'Help4 Builder Migration and Troubleshooting',
            wp_kses_post($this->h4BuilderTroubleshootingGuide($supportTicketUrl))
        );
        $builderLivePreviewId = $this->upsertPage(
            'help4-builder-live-preview-workflow',
            'Help4 Builder Live Preview Workflow',
            wp_kses_post($this->h4BuilderLivePreviewGuide($supportTicketUrl))
        );
        $builderMediaId = $this->upsertPage(
            'help4-builder-images-media',
            'Help4 Builder Images and Media',
            wp_kses_post($this->h4BuilderMediaGuide($supportTicketUrl))
        );
        $builderDesignControlsId = $this->upsertPage(
            'help4-builder-buttons-typography-spacing',
            'Help4 Builder Buttons, Typography and Spacing',
            wp_kses_post($this->h4BuilderDesignControlsGuide($supportTicketUrl))
        );
        $builderDynamicDataId = $this->upsertPage(
            'help4-builder-dynamic-data',
            'Help4 Builder Dynamic Data',
            wp_kses_post($this->h4BuilderDynamicDataGuide($supportTicketUrl))
        );
        $builderFormsId = $this->upsertPage(
            'help4-builder-forms-lead-capture',
            'Help4 Builder Forms and Lead Capture',
            wp_kses_post($this->h4BuilderFormsGuide($supportTicketUrl))
        );
        $builderMotionId = $this->upsertPage(
            'help4-builder-motion-sliders',
            'Help4 Builder Motion and Sliders',
            wp_kses_post($this->h4BuilderMotionGuide($supportTicketUrl))
        );
        $builderMigrationId = $this->upsertPage(
            'help4-builder-import-export-migrations',
            'Help4 Builder Import, Export and Migrations',
            wp_kses_post($this->h4BuilderImportExportGuide($supportTicketUrl))
        );
        $builderNavigatorId = $this->upsertPage(
            'help4-builder-navigator-layers',
            'Help4 Builder Navigator and Layers',
            wp_kses_post($this->h4BuilderNavigatorGuide($supportTicketUrl))
        );
        $builderPublishId = $this->upsertPage(
            'help4-builder-save-preview-publish',
            'Help4 Builder Save, Preview and Publish Workflow',
            wp_kses_post($this->h4BuilderPublishGuide($supportTicketUrl))
        );
        $builderConditionsId = $this->upsertPage(
            'help4-theme-builder-template-conditions',
            'Help4 Theme Builder Template Conditions',
            wp_kses_post($this->h4BuilderTemplateConditionsGuide($supportTicketUrl))
        );
        $builderReusableId = $this->upsertPage(
            'help4-builder-reusable-global-sections',
            'Help4 Builder Reusable and Global Sections',
            wp_kses_post($this->h4BuilderReusableSectionsGuide($supportTicketUrl))
        );
        $builderCommerceLaunchId = $this->upsertPage(
            'help4-commerce-launch-testing',
            'Help4 Commerce Launch Testing',
            wp_kses_post($this->h4BuilderCommerceLaunchGuide($supportTicketUrl))
        );
        $builderSalesHomepageId = $this->upsertPage(
            'help4-builder-sales-homepage',
            'Help4 Builder Sales Homepage Tutorial',
            wp_kses_post($this->h4BuilderSalesHomepageGuide($supportTicketUrl))
        );
        $builderPricingId = $this->upsertPage(
            'help4-builder-pricing-comparison',
            'Help4 Builder Pricing Comparison Tutorial',
            wp_kses_post($this->h4BuilderPricingComparisonGuide($supportTicketUrl))
        );
        $builderFaqId = $this->upsertPage(
            'help4-builder-faq-accordion-schema',
            'Help4 Builder FAQ Accordion and Schema Tutorial',
            wp_kses_post($this->h4BuilderFaqGuide($supportTicketUrl))
        );
        $builderSiteChromeId = $this->upsertPage(
            'help4-builder-header-footer-launch',
            'Help4 Builder Header and Footer Launch Tutorial',
            wp_kses_post($this->h4BuilderSiteChromeGuide($supportTicketUrl))
        );
        $builderSectionsId = $this->upsertPage(
            'help4-builder-sections-containers-columns',
            'Help4 Builder Sections, Containers and Columns',
            wp_kses_post($this->h4BuilderSectionsGuide($supportTicketUrl))
        );
        $builderSiteKitsId = $this->upsertPage(
            'help4-builder-site-kits-starter-sites',
            'Help4 Builder Site Kits and Starter Sites',
            wp_kses_post($this->h4BuilderSiteKitsGuide($supportTicketUrl))
        );
        $builderWidgetsId = $this->upsertPage(
            'help4-builder-widget-library',
            'Help4 Builder Widget Library',
            wp_kses_post($this->h4BuilderWidgetsGuide($supportTicketUrl))
        );
        $builderVideoId = $this->upsertPage(
            'help4-builder-video-hls-backgrounds',
            'Help4 Builder Video, HLS and Background Video',
            wp_kses_post($this->h4BuilderVideoGuide($supportTicketUrl))
        );
        $builderCustomCssId = $this->upsertPage(
            'help4-builder-custom-css-advanced-controls',
            'Help4 Builder Custom CSS and Advanced Controls',
            wp_kses_post($this->h4BuilderCustomCssGuide($supportTicketUrl))
        );

        $builderOperationsGuides = $this->h4BuilderOperationsGuideCatalog();
        $builderOperationsGuideIds = [];
        foreach ($builderOperationsGuides as $guideSlug => $guide) {
            $builderOperationsGuideIds[$guideSlug] = $this->upsertPage(
                $guideSlug,
                (string) ($guide['title'] ?? ''),
                wp_kses_post($this->h4BuilderOperationsGuidePage($guide, $supportTicketUrl))
            );
        }

        $themeBuilderGuideId = $this->upsertPage(
            'help4-theme-builder-guide',
            'Help4 Theme Builder Guide',
            wp_kses_post(
                '<h2>Help4 Theme Builder Guide</h2>'
                . '<p>Use Theme Builder to control global header/footer and reusable template parts across the site.</p>'
                . '<h2>Global Header & Footer</h2>'
                . '<ul>'
                . '<li>Create/update header and footer templates.</li>'
                . '<li>Assign scope to entire site or specific page types.</li>'
                . '<li>Use include/exclude rules for targeted pages.</li>'
                . '</ul>'
                . '<h2>Template Conditions</h2>'
                . '<ul>'
                . '<li>Choose role: header, footer, section, popup.</li>'
                . '<li>Set scope: entire site, include list, exclude list.</li>'
                . '<li>Use priority values to resolve template conflicts.</li>'
                . '</ul>'
                . '<h2>Best Practice</h2>'
                . '<ul>'
                . '<li>Keep header nav consistent and lightweight.</li>'
                . '<li>Use reusable templates for repeated sections.</li>'
                . '<li>Verify each template at desktop and mobile breakpoints.</li>'
                . '</ul>'
                . '<h2>Build A Site Shell In The Right Order</h2>'
                . '<p>Start with the global header and footer because those parts frame every normal page. Add the logo, navigation hierarchy, contact route, primary call to action, legal links, and customer support path before creating special page exceptions. Then build a default page shell, a canvas landing-page shell, a 404 template, and any archive or single-content layouts the site actually uses.</p>'
                . '<ol><li>Create each reusable template and give it a name that explains its role.</li><li>Assign the normal header and footer to the entire site.</li><li>Add narrower include rules only for pages that truly need a different shell.</li><li>Use exclusions for checkout, funnels, or canvas pages that intentionally remove normal navigation.</li><li>Set priorities only when two valid rules can match the same request.</li></ol>'
                . '<h2>Menus, Dropdowns, And Mobile Navigation</h2>'
                . '<p>Use the real WordPress menu hierarchy for parent and child links so desktop dropdowns and the mobile menu share one source. Test the pointer path from a parent item into its submenu, keyboard focus, touch opening, menu close behavior, and the space between the trigger and submenu. A dropdown should not disappear while the visitor is moving toward it.</p>'
                . '<h2>Before Publishing A Template Change</h2>'
                . '<p>Preview the homepage, one normal page, one long page, one conversion page, and the 404 route. Check desktop and phone widths for clipped content, duplicate headers, missing footers, unreadable contrast, broken fixed positioning, and links hidden behind the mobile menu. Clear page/CDN caches only after the saved template and assignment rules are confirmed.</p>'
                . '<h2>Troubleshooting</h2>'
                . '<p>If a template does not appear, confirm it is published, its role is correct, and its include/exclude rules match the current URL. If two templates appear, review overlapping conditions and priority values. If the canvas has a white frame, inspect the page layout and HTML block wrapper controls for background and padding before adding site-specific CSS.</p>'
                . '<p><a class="button button-primary" href="' . esc_url(home_url('/help4-feature-lab/')) . '">View Starter Templates</a> '
                . '<a class="button" href="' . esc_url(home_url('/help4-builder-guide/')) . '">Builder Guide</a></p>'
                . '<p><a class="button" href="' . $supportTicketUrl . '" target="_blank" rel="noopener">Theme Builder Support</a></p>'
            )
        );

        $paymentRouterGuideId = $this->upsertPage(
            'help4-payment-router',
            'Help4 Payment Router',
            wp_kses_post($this->h4PaymentRouterGuidePage($supportTicketUrl))
        );
        $stripeRouterTutorialId = $this->upsertPage(
            'stripe-router-tutorial',
            'Stripe Router Setup Tutorial',
            wp_kses_post($this->h4StripeRouterTutorialPage($supportTicketUrl))
        );
        $stripeRouterPlansId = $this->upsertPage(
            'stripe-router-pro-vs-enterprise',
            'Stripe Router Pro vs Enterprise',
            wp_kses_post($this->h4StripeRouterPlansPage($supportTicketUrl))
        );
        $help4NetCdnId = $this->upsertPage(
            'help4-net-wordpress-cdn-waf',
            'Help4 Net WordPress CDN, GeoDNS and WAF',
            wp_kses_post($this->h4Help4NetCdnPage($supportTicketUrl))
        );
        $legacyStripeRouterGuideId = 0;

        $pluginBuilderId = $this->upsertPage(
            'plugin-help4-builder-suite',
            'Help4 Builder Suite Plugin',
            wp_kses_post(
                '<section class="h4wp-hero h4wp-soft-glow">'
                . '<p class="h4wp-hero__eyebrow">Plugin Overview</p>'
                . '<h1>Help4 Builder Suite</h1>'
                . '<p>A full visual builder, theme builder, performance toolkit, and enterprise-ready WordPress operations stack in one package.</p>'
                . '</section>'
                . '<section class="h4-plugin-shot-grid">'
                . '<article class="h4-plugin-shot-card"><div class="h4-plugin-shot-media"><img src="' . esc_url($mediaBase . 'help4-builder-editor.png') . '" alt="Help4 Builder visual editor screenshot" loading="lazy" decoding="async" /></div><h3>Visual Builder Studio</h3><p>Drag-and-drop page building with responsive controls, popups, and live preview parity.</p></article>'
                . '<article class="h4-plugin-shot-card"><div class="h4-plugin-shot-media"><img src="' . esc_url($mediaBase . 'help4-builder-widget.png') . '" alt="Help4 Builder widget settings screenshot" loading="lazy" decoding="async" /></div><h3>Element Editing</h3><p>Edit widgets with grouped controls for content, design, spacing, and advanced behavior.</p></article>'
                . '</section>'
                . '<p><a class="button button-primary" href="' . esc_url(home_url('/help4-builder-guide/')) . '">Open Builder Guide</a> <a class="button" href="' . esc_url(home_url('/help4-builder/')) . '">Feature Overview</a></p>'
            )
        );

        $pluginThemeId = $this->upsertPage(
            'plugin-help4-theme-builder',
            'Help4 Theme Builder Plugin Features',
            wp_kses_post(
                '<section class="h4wp-hero h4wp-soft-glow">'
                . '<p class="h4wp-hero__eyebrow">Theme Builder</p>'
                . '<h1>Global Header, Footer, and Template Conditions</h1>'
                . '<p>Build reusable global templates, assign them by conditions, and keep page output consistent across every viewport.</p>'
                . '</section>'
                . '<section class="h4-plugin-shot-grid">'
                . '<article class="h4-plugin-shot-card"><div class="h4-plugin-shot-media"><img src="' . esc_url($mediaBase . 'help4-theme-catalog.png') . '" alt="Help4 theme catalog screenshot" loading="lazy" decoding="async" /></div><h3>Theme Catalog</h3><p>Install starter themes and industry packs from a centralized catalog.</p></article>'
                . '<article class="h4-plugin-shot-card"><div class="h4-plugin-shot-media"><img src="' . esc_url($mediaBase . 'help4-packages-layout.png') . '" alt="Help4 responsive packages page screenshot" loading="lazy" decoding="async" /></div><h3>Output Consistency</h3><p>Theme-level styling keeps frontend output clean and fast across desktop, tablet, and mobile.</p></article>'
                . '</section>'
                . '<p><a class="button button-primary" href="' . esc_url(home_url('/help4-theme-builder-guide/')) . '">Open Theme Builder Guide</a></p>'
            )
        );

        $pluginPaymentRouterId = $this->upsertPage(
            'plugin-help4-payment-router',
            'Help4 Payment Router Plugin',
            wp_kses_post($this->h4ProductPaymentRouterPage($supportTicketUrl))
        );
        $pluginStripeId = 0;

        $pluginCatalogId = $this->upsertPage(
            'plugins',
            'Help4 Plugin Catalog',
            wp_kses_post(
                '<section class="h4wp-hero h4wp-soft-glow">'
                . '<p class="h4wp-hero__eyebrow">Help4 Add-ons</p>'
                . '<h1>Plugin Catalog</h1>'
                . '<p>Production-ready plugins designed for managed WordPress operations, design teams, and native commerce workflows.</p>'
                . '</section>'
                . '<section class="h4wp-card-grid">'
                . '<article class="h4wp-card"><h3>Help4 Builder Suite</h3><p>Visual builder, theme builder, and performance tooling for modern WordPress teams.</p><p><a class="button button-primary" href="' . esc_url(home_url('/plugin-help4-builder-suite/')) . '">View Plugin</a></p></article>'
                . '<article class="h4wp-card"><h3>Help4 Theme Builder</h3><p>Global header/footer control, template assignment rules, and reusable layout logic.</p><p><a class="button button-primary" href="' . esc_url(home_url('/plugin-help4-theme-builder/')) . '">View Plugin</a></p></article>'
                . '<article class="h4wp-card"><h3>Help4 Payment Router</h3><p>Multi-processor checkout routing with conditions and resilience workflows.</p><p><a class="button button-primary" href="' . esc_url(home_url('/plugin-help4-payment-router/')) . '">View Router</a></p></article>'
                . '</section>'
            )
        );

        $shopId = $this->upsertPage(
            'shop',
            'Managed WordPress Hosting Plans',
            wp_kses_post($this->h4ProductShopPage('https://help4network.com/store/', 'https://help4network.com/cart/', $supportTicketUrl, $salesCallUrl, $salesSmsUrl, $salesWhatsAppUrl))
        );
        $packagesId = $this->upsertPage(
            'packages',
            'WordPress Packages from $4.95/mo',
            wp_kses_post($this->h4ProductPackagesPage('https://help4network.com/store/', 'https://help4network.com/cart/', $supportTicketUrl, $clientAreaUrl, $salesCallUrl, $salesSmsUrl, $salesWhatsAppUrl))
        );
        $hostingPageId = $this->upsertPage(
            'fully-managed-wordpress-hosting',
            'Fully Managed WordPress Hosting',
            wp_kses_post($this->h4ProductManagedHostingPage('https://help4network.com/store/', 'https://help4network.com/cart/', $supportTicketUrl, $clientAreaUrl, $supportRepUrl, $salesCallUrl, $salesSmsUrl, $salesWhatsAppUrl))
        );
        $pluginCatalogId = $this->upsertPage(
            'plugins',
            'Help4 Plugin Catalog',
            wp_kses_post($this->h4ProductPluginCatalogPage($supportTicketUrl))
        );
        $pluginBuilderId = $this->upsertPage(
            'plugin-help4-builder-suite',
            'Help4 Builder Suite Plugin',
            wp_kses_post($this->h4ProductBuilderSuitePage($supportTicketUrl))
        );
        $freeBuilderId = $this->upsertPage(
            'free-wordpress-builder',
            'Free WordPress Builder',
            wp_kses_post($this->h4ProductFreeBuilderPage($supportTicketUrl))
        );
        $blankThemeId = $this->upsertBlankThemePage($supportTicketUrl);
        $aiImagePromptsId = $this->upsertPage(
            'help4-builder-ai-image-prompts',
            'Help4 Builder AI Image Prompts',
            wp_kses_post($this->h4ProductAiImagePromptsPage($supportTicketUrl))
        );
        $pluginThemeId = $this->upsertPage(
            'plugin-help4-theme-builder',
            'Help4 Theme Builder Plugin Features',
            wp_kses_post($this->h4ProductThemeBuilderPage($supportTicketUrl))
        );
        $paymentRouterGuideId = $this->upsertPage(
            'help4-payment-router',
            'Help4 Payment Router',
            wp_kses_post($this->h4PaymentRouterGuidePage($supportTicketUrl))
        );
        $legacyStripeRouterGuideId = 0;
        $commerceSupportId = $this->upsertPage(
            'commerce-support',
            'Help4 Commerce Support',
            wp_kses_post($this->h4ProductCommerceSupportPage($supportTicketUrl, $clientAreaUrl))
        );
        $legacyCommerceSupportId = 0;
        $pluginPaymentRouterId = $this->upsertPage(
            'plugin-help4-payment-router',
            'Help4 Payment Router Plugin',
            wp_kses_post($this->h4ProductPaymentRouterPage($supportTicketUrl))
        );
        $pluginStripeId = 0;

        foreach ([$shopId, $packagesId, $checkoutId, $clientAreaId, $hostingPageId, $supportPageId, $commerceSupportId, $legacyCommerceSupportId, $faqPageId, $builderTutorialsId, $builderScreenshotsId, $builderGuideId, $builderFirstPageId, $builderEditorControlsId, $builderWpCliRunnersId, $builderTemplatesId, $builderTemplateLibraryId, $builderIconsId, $builderModuleControlsId, $builderFieldsId, $builderCommerceId, $builderSlidersFormsId, $builderWebsiteSnapshotId, $builderLaunchId, $builderUpdatesId, $builderSafeEditingId, $builderResponsiveId, $builderGlobalsId, $builderNavigationId, $builderCommerceAdvancedId, $builderSeoAdvancedId, $builderMultisiteId, $builderTroubleshootingId, $builderLivePreviewId, $builderMediaId, $builderDesignControlsId, $builderDynamicDataId, $builderFormsId, $builderMotionId, $builderMigrationId, $builderNavigatorId, $builderPublishId, $builderConditionsId, $builderReusableId, $builderCommerceLaunchId, $builderSalesHomepageId, $builderPricingId, $builderFaqId, $builderSiteChromeId, $builderSectionsId, $builderSiteKitsId, $builderWidgetsId, $builderVideoId, $builderCustomCssId, $themeBuilderGuideId, $paymentRouterGuideId, $stripeRouterTutorialId, $stripeRouterPlansId, $help4NetCdnId, $legacyStripeRouterGuideId, $pluginBuilderId, $freeBuilderId, $blankThemeId, $aiImagePromptsId, $pluginThemeId, $pluginPaymentRouterId, $pluginStripeId, $pluginCatalogId] as $pageId) {
            $pageId = (int) $pageId;
            if ($pageId <= 0) {
                continue;
            }
            $this->clearMirrorPayload($pageId);
            update_post_meta($pageId, '_h4_builder_mode', 'wp');
            update_post_meta($pageId, '_h4_builder_enabled', '0');
            update_post_meta($pageId, '_h4_builder_page_layout', 'full_width');
        }

        $this->applySalesSeoMeta((int) $shopId, 'Managed WordPress Hosting Plans | DIY to Done-For-You Help4', 'Start with affordable WordPress hosting, then upgrade into Help4 managed care, page edits, speed optimization, security, and support.');
        $this->applySalesSeoMeta((int) $packagesId, 'WordPress Packages from $4.95/mo | Help4 WordPress', 'Compare Help4 WordPress packages from $4.95 DIY hosting to managed care, speed, security, SEO, migration, and priority support.');
        $this->applySalesSeoMeta((int) $hostingPageId, 'Fully Managed WordPress Hosting | Help4 Done-For-You Site Care', 'Fully managed WordPress hosting with updates, support, security, performance, migrations, edits, SEO pages, and plain-English requests.');
        $this->applySalesSeoMeta((int) $supportPageId, 'WordPress Support | Help4 WordPress', 'Get WordPress support for broken pages, updates, forms, plugins, security, speed, billing, and managed-care requests through a tracked Help4 support path.');
        $this->applySalesSeoMeta((int) $commerceSupportId, 'Help4 Commerce Support | Catalogs, Subscriptions and Checkout', 'Get help with Help4 Commerce catalogs, variations, subscriptions, product pages, payment routing, checkout handoff, and large-store operations.');
        $this->applySalesSeoMeta((int) $legacyCommerceSupportId, 'Help4 Commerce Support | Catalogs, Subscriptions and Checkout', 'Get help with Help4 Commerce catalogs, variations, subscriptions, product pages, payment routing, checkout handoff, and large-store operations.');
        $this->applySalesSeoMeta((int) $faqPageId, 'WordPress Hosting FAQ | Help4 WordPress', 'Read answers about managed WordPress hosting, migrations, support, billing, and how Help4 handles day-to-day technical operations.');
        $this->applySalesSeoMeta((int) $checkoutId, 'Checkout | Secure Help4 WordPress Checkout', 'Continue to secure checkout for Help4 managed WordPress plans and services.');
        $this->applySalesSeoMeta((int) $clientAreaId, 'Client Area | Billing, Services and Support | Help4', 'Access client billing, invoices, services, and support from the Help4 client portal.');
        $this->applySalesSeoMeta((int) $builderTutorialsId, 'Help4 Builder Tutorials | Search Every Setup and Workflow Guide', 'Search the complete Help4 Builder Suite knowledge center for visual editing, templates, media, forms, email, commerce, SEO, local business, security, speed, LMS, updates, and recovery.');
        update_post_meta((int) $builderTutorialsId, '_h4_seo_schema_type', 'webpage');
        update_post_meta((int) $builderTutorialsId, '_h4_seo_focus_keyword', 'Help4 Builder tutorials');
        update_post_meta((int) $builderTutorialsId, '_h4_seo_conversion_goal', 'learn');
        $this->applySalesSeoMeta((int) $builderScreenshotsId, 'Help4 Builder Screenshots | Blank Install Admin Screens', 'View Help4 Builder Suite screenshots captured from a blank WordPress install: settings, Builder Pages, Studio, templates, fields, commerce, forms, SEO, security, and updates.');
        $this->applySalesSeoMeta((int) $builderGuideId, 'Help4 Builder Guide | How To Use Help4 Visual Builder', 'Step-by-step guide to building responsive pages with Help4 Visual Builder, from section layout to responsive editing and publish workflow.');
        $this->applySalesSeoMeta((int) $builderFirstPageId, 'Build Your First Help4 Builder Page | Beginner Tutorial', 'Learn how to open Builder Pages, launch Builder Studio, structure the first page, check mobile, and publish safely with Help4 Builder Suite.');
        $this->applySalesSeoMeta((int) $builderEditorControlsId, 'Help4 Builder Editor Controls | Content, Design and Advanced', 'Learn exactly what the Content, Design, and Advanced tabs control, how live preview works, and how to publish a Help4 Builder element safely.');
        $this->applySalesSeoMeta((int) $builderWpCliRunnersId, 'Help4 Builder WP-CLI Eval-File Runner Guide', 'Build guarded WordPress seed, migration, launch, repair, audit, and recovery runners that work safely with wp eval-file.');
        $this->applySalesSeoMeta((int) $builderTemplatesId, 'Help4 Builder Templates and Icons | Starter Pages and Theme Packs', 'Use Help4 Builder starter templates, theme packs, reusable sections, and default SVG icons to start a WordPress site faster.');
        $this->applySalesSeoMeta((int) $builderTemplateLibraryId, 'Help4 Builder Template Library | 135 Starter Specs for WordPress Sites', 'Choose Help4 Builder Suite starter templates for service pages, product collections, support docs, release notes, checkout recovery, and launch workflows.');
        $this->applySalesSeoMeta((int) $builderIconsId, 'Help4 Builder Default Icon Library | 230 SVG Icons for WordPress Pages', 'Use Help4 Builder Suite default SVG icons for builder setup, commerce, support, SEO, security, launch, update, and documentation sections.');
        $this->applySalesSeoMeta((int) $builderModuleControlsId, 'Help4 Builder Modules | Enable Only the Features You Need', 'Learn how Help4 Builder Suite module controls keep WordPress sites faster by enabling only the builder, commerce, fields, forms, SEO, security, and performance tools needed.');
        $this->applySalesSeoMeta((int) $builderFieldsId, 'Help4 Builder Fields | Repeaters, Groups and Dynamic Content', 'Use structured field groups, repeaters, galleries, relationships, and dynamic output in Help4 Builder Suite without one-off admin screens.');
        $this->applySalesSeoMeta((int) $builderCommerceId, 'Help4 Commerce Setup | Catalogs, Variations and Payments', 'Start with Help4 Commerce catalog setup, product fields, variations, subscriptions, checkout context, and payment-routing workflows.');
        $this->applySalesSeoMeta((int) $builderSlidersFormsId, 'Help4 Builder Sliders and Forms | Motion Sections and Lead Capture', 'Build Help4 Builder sliders and forms that support conversion without loading unnecessary assets on every WordPress page.');
        $this->applySalesSeoMeta((int) $builderWebsiteSnapshotId, 'Help4 Builder Website Snapshot | Website Screenshots for Recent Work', 'Use Help4 Builder Website Snapshot to turn public URLs into safe website screenshots for portfolios, migrations, support notes, and launch proof.');
        $this->applySalesSeoMeta((int) $builderLaunchId, 'Help4 Builder SEO, Security and Performance Checklist', 'Use Help4 Builder Suite to prepare WordPress pages for launch with metadata, schema, redirects, SSL, headers, image optimization, readability, and mobile QA.');
        $this->applySalesSeoMeta((int) $builderUpdatesId, 'Help4 Builder Updates | WordPress 7 Readiness', 'Learn how Help4 uses live production WordPress and the md WordPress beta track to test Builder Suite updates, package channels, and upgrade readiness.');
        $this->applySalesSeoMeta((int) $builderSafeEditingId, 'Safe Help4 Builder Editing and Page Recovery Guide', 'Replace images, edit content, resolve stale drafts, and restore page-local Builder history without losing neighboring sections or responsive styles.');
        $this->applySalesSeoMeta((int) $builderResponsiveId, 'Help4 Builder Responsive Design Guide | Desktop, Tablet and Mobile', 'Set real breakpoint-specific spacing, typography, widths, columns, alignment, and mobile gutters in Help4 Builder without fragile custom CSS.');
        $this->applySalesSeoMeta((int) $builderGlobalsId, 'Help4 Builder Global Styles and Theme Packs Guide', 'Manage semantic colors, typography, spacing, shape, and style-only theme packs while preserving the current WordPress page structure and content.');
        $this->applySalesSeoMeta((int) $builderNavigationId, 'Help4 Builder Menus, Headers and Footers Guide', 'Build accessible WordPress menu hierarchies, reliable desktop dropdowns, mobile navigation, and globally assigned headers and footers in Help4 Builder.');
        $this->applySalesSeoMeta((int) $builderCommerceAdvancedId, 'Help4 Commerce Products, Variations and Customer Fields Guide', 'Configure products, large catalogs, variations, subscriptions, dynamic customer fields, checkout routes, and order lifecycle testing in Help4 Commerce.');
        $this->applySalesSeoMeta((int) $builderSeoAdvancedId, 'Help4 SEO Guide | Local, International, Social and IndexNow', 'Configure local and international SEO, social metadata, structured data, sitemaps, IndexNow, readability, and indexing health with Help4 Builder Suite.');
        $this->applySalesSeoMeta((int) $builderMultisiteId, 'Help4 Builder Multisite Setup and SEO Guide', 'Provision Help4 Builder across WordPress multisite while preserving site-level ownership, data isolation, scalable SEO, and bounded background work.');
        $this->applySalesSeoMeta((int) $builderTroubleshootingId, 'Help4 Builder Migration and Troubleshooting Guide', 'Diagnose preview differences, missing images, lost styling, cache issues, theme conflicts, and migration problems using evidence-first Help4 Builder checks.');
        $this->applySalesSeoMeta((int) $builderLivePreviewId, 'Help4 Builder Live Preview Guide | See Edits Before Publishing', 'Use Help4 Builder Studio live preview, viewport controls, draft state, refresh checks, and public parity testing without publishing unfinished changes.');
        $this->applySalesSeoMeta((int) $builderMediaId, 'Help4 Builder Images and Media Guide | Replace Images Safely', 'Upload, replace, crop, size, optimize, and add accessible image text in Help4 Builder without deleting neighboring content or page styles.');
        $this->applySalesSeoMeta((int) $builderDesignControlsId, 'Help4 Builder Buttons, Typography and Spacing Guide', 'Control button padding, font sizing, line height, colors, radius, section spacing, and responsive values in Help4 Builder Studio.');
        $this->applySalesSeoMeta((int) $builderDynamicDataId, 'Help4 Builder Dynamic Data Guide | Fields, Posts and Products', 'Connect Help4 fields, WordPress posts, taxonomies, authors, site data, products, variants, and repeaters to Builder widgets safely.');
        $this->applySalesSeoMeta((int) $builderFormsId, 'Help4 Builder Forms Tutorial | Lead Capture and Delivery Testing', 'Build accessible Help4 forms, configure fields and consent, connect actions, test validation and delivery, and verify mobile lead capture.');
        $this->applySalesSeoMeta((int) $builderMotionId, 'Help4 Builder Motion and Slider Guide | Accessible Animation', 'Build responsive sliders and motion effects with duration, delay, easing, triggers, keyboard controls, and reduced-motion fallbacks.');
        $this->applySalesSeoMeta((int) $builderMigrationId, 'Help4 Builder Import, Export and Migration Guide', 'Move layouts, style packs, media, menus, fields, and templates into Help4 Builder while preserving URLs, content, IDs, and responsive behavior.');
        $this->applySalesSeoMeta((int) $builderNavigatorId, 'Help4 Builder Navigator Guide | Layers, Containers and Widgets', 'Use the Help4 Builder Navigator to find, rename, reorder, duplicate, and safely remove nested sections, containers, columns, and widgets.');
        $this->applySalesSeoMeta((int) $builderPublishId, 'Help4 Builder Save, Preview and Publish Guide', 'Understand element publishing, page drafts, live preview, revision conflicts, recovery history, and public verification in Help4 Builder Studio.');
        $this->applySalesSeoMeta((int) $builderConditionsId, 'Help4 Theme Builder Template Conditions and Priority Guide', 'Assign headers, footers, single templates, archives, search, 404, and canvas layouts using clear include, exclude, and priority rules.');
        $this->applySalesSeoMeta((int) $builderReusableId, 'Help4 Builder Reusable Global Sections Guide', 'Create reusable calls to action, proof bands, forms, and global sections without unintentionally changing every page on the site.');
        $this->applySalesSeoMeta((int) $builderCommerceLaunchId, 'Help4 Commerce Launch Testing Checklist', 'Test products, variations, customer fields, tax, shipping, payments, webhooks, subscriptions, refunds, email, mobile checkout, and recovery before launch.');
        $this->applySalesSeoMeta((int) $builderSalesHomepageId, 'How to Build a WordPress Sales Homepage with Help4 Builder', 'Build a focused WordPress sales homepage with open content bands, clear offers, proof, services, pricing, FAQ, contact actions, and responsive checks.');
        $this->applySalesSeoMeta((int) $builderPricingId, 'Help4 Builder Pricing Table and Five-Plan Comparison Guide', 'Create accessible pricing comparisons for up to five plans with feature rows, honest labels, responsive stacking, clear calls to action, and no mobile clipping.');
        $this->applySalesSeoMeta((int) $builderFaqId, 'Help4 Builder FAQ Accordion and FAQ Schema Guide', 'Build keyboard-accessible FAQ accordions, write useful answers, add valid FAQPage schema, and avoid hidden or duplicated structured data.');
        $this->applySalesSeoMeta((int) $builderSiteChromeId, 'Help4 Builder Header Footer and Mobile Menu Launch Guide', 'Launch reusable headers and footers with exact logos, native menu hierarchy, reliable dropdowns, mobile navigation, legal links, and template conditions.');
        $this->applySalesSeoMeta((int) $builderSectionsId, 'Help4 Builder Sections Containers and Columns Guide', 'Build responsive Help4 Builder sections, nested containers, grid or flex columns, gaps, widths, alignment, and mobile stacking without page overflow.');
        $this->applySalesSeoMeta((int) $builderSiteKitsId, 'Help4 Builder Site Kits and Starter Sites Guide', 'Import Help4 Builder starter site kits as reviewable drafts, apply optional style tokens, preserve existing content, and launch a complete responsive site safely.');
        $this->applySalesSeoMeta((int) $builderWidgetsId, 'Help4 Builder Widget Library Guide | Elements and Addons', 'Find, insert, configure, favorite, and test Help4 Builder widgets for content, media, forms, commerce, SEO, navigation, and dynamic data.');
        $this->applySalesSeoMeta((int) $builderVideoId, 'Help4 Builder Video and HLS Background Guide', 'Configure accessible Help4 Builder video with HLS, MP4 and WebM fallbacks, posters, failure images, responsive focal points, overlays, controls, and reduced motion.');
        $this->applySalesSeoMeta((int) $builderCustomCssId, 'Help4 Builder Custom CSS and Advanced Controls Guide', 'Use scoped custom CSS, pseudo-elements, media queries, keyframes, classes, attributes, visibility, and recovery tools safely in Help4 Builder Studio.');
        foreach ($builderOperationsGuides as $guideSlug => $guide) {
            $guideId = (int) ($builderOperationsGuideIds[$guideSlug] ?? 0);
            $this->applyTutorialSeoMeta(
                $guideId,
                (string) ($guide['seo_title'] ?? $guide['title'] ?? ''),
                (string) ($guide['seo_description'] ?? $guide['lede'] ?? ''),
                (string) ($guide['focus_keyword'] ?? '')
            );
            $this->applyFaqSchema($guideId, is_array($guide['faq'] ?? null) ? $guide['faq'] : []);
        }
        $this->applySalesSeoMeta((int) $themeBuilderGuideId, 'Help4 Theme Builder Guide | Global Header Footer and Templates', 'Learn how to configure Help4 Theme Builder templates, conditions, and global layout assignments for headers, footers, and reusable sections.');
        $this->applySalesSeoMeta((int) $paymentRouterGuideId, 'Help4 Payment Router | Multi-Processor Checkout Routing Guide', 'Configure Help4 Payment Router with multi-processor routes, subscriptions, product context, failover rules, and go-live checklist steps.');
        $this->applySalesSeoMeta((int) $stripeRouterTutorialId, 'Stripe Router Tutorial | Multiple Stripe Accounts for WooCommerce', 'Connect multiple Stripe accounts, create product and geographic assignment rules, test checkout, validate webhooks, and launch Payment Router for Stripe safely.');
        $this->applySalesSeoMeta((int) $stripeRouterPlansId, 'Stripe Router Pro vs Enterprise | Plans and Use Cases', 'Compare the $24.92 monthly Stripe Router Pro plan and $49.92 monthly Enterprise plan for multi-account WooCommerce payment routing.');
        $this->applySalesSeoMeta((int) $help4NetCdnId, 'WordPress CDN, GeoDNS and WAF | Help4 Net Plans', 'Compare Help4 Net free plugin onboarding, the $8 Pro WordPress CDN and GeoDNS plan, and the $20 managed full-proxy WAF service from Help4 Network.');
        $this->applySalesSeoMeta((int) $legacyStripeRouterGuideId, 'Help4 Payment Router | Multi-Processor Checkout Routing Guide', 'Configure Help4 Payment Router with multi-processor routes, subscriptions, product context, failover rules, and go-live checklist steps.');
        $this->applySalesSeoMeta((int) $pluginCatalogId, 'Help4 Plugin Catalog | WordPress Builder, Theme and Commerce Tools', 'Explore Help4 WordPress plugins for visual building, global templates, starter pages, commerce routing, performance, and operations.');
        $this->applySalesSeoMeta((int) $pluginBuilderId, 'Help4 Builder Suite | Visual Builder, Commerce and Security', 'Help4 Builder Suite adds visual building, blank-theme templates, structured custom fields, slider tools, Help4 Commerce, 135 starter specs, 230 default icons, SEO, performance, and security modules.');
        $this->applySalesSeoMeta((int) $freeBuilderId, 'Free WordPress Builder | Visual Editing, Templates and SEO', 'Download Help4 Builder Suite free for live visual WordPress editing, responsive templates, dynamic fields, sliders, forms, SEO, security, performance, and native commerce.');
        if ((int) $freeBuilderId > 0) {
            update_post_meta((int) $freeBuilderId, '_h4_seo_schema_type', 'software_application');
            update_post_meta((int) $freeBuilderId, '_h4_seo_focus_keyword', 'free WordPress builder');
            update_post_meta((int) $freeBuilderId, '_h4_seo_conversion_goal', 'download');
            update_post_meta((int) $freeBuilderId, '_h4_seo_primary_cta', 'Download Free Builder');
        }
        $this->applySalesSeoMeta((int) $aiImagePromptsId, 'Help4 Builder AI Image Prompts | Hero, Product and Tutorial Visuals', 'Use plain-English AI image prompts for Help4 Builder hero images, service proof, product mockups, tutorial screenshots, social previews, and portfolio visuals.');
        $this->applySalesSeoMeta((int) $pluginThemeId, 'Help4 Theme Builder Plugin | Headers, Footers and Template Rules', 'Help4 Theme Builder controls global headers, footers, reusable templates, template assignments, starter page systems, and responsive output.');
        $this->applySalesSeoMeta((int) $pluginPaymentRouterId, 'Help4 Payment Router Plugin | Checkout Routing Rules', 'Help4 Payment Router helps route checkout traffic by product, cart, region, processor availability, failover, and order context.');
        $this->applySalesSeoMeta((int) $pluginStripeId, 'Help4 Payment Router Plugin | Checkout Routing Rules', 'Help4 Payment Router helps route checkout traffic by product, cart, region, processor availability, failover, and order context.');
        $this->markLegacySalesAlias((int) $legacyCommerceSupportId, (int) $commerceSupportId);
        $this->markLegacySalesAlias((int) $legacyStripeRouterGuideId, (int) $paymentRouterGuideId);
        $this->markLegacySalesAlias((int) $pluginStripeId, (int) $pluginPaymentRouterId);
        $this->applyFaqSchema(
            (int) $faqPageId,
            [
                [
                    'question' => 'What does fully managed WordPress mean?',
                    'answer' => 'Help4 manages updates, security, speed, troubleshooting, and requested changes so you can focus on your business.',
                ],
                [
                    'question' => 'Can I request tasks in plain English?',
                    'answer' => 'Yes. Customers can submit simple requests and our team handles implementation.',
                ],
                [
                    'question' => 'Do you migrate existing sites?',
                    'answer' => 'Yes. We migrate WordPress websites and validate SEO, links, and performance afterward.',
                ],
                [
                    'question' => 'Where is checkout handled?',
                    'answer' => 'Checkout is processed on the Help4 WordPress commerce stack for centralized payment routing.',
                ],
            ]
        );
        foreach ([$paymentRouterGuideId, $legacyStripeRouterGuideId] as $routerFaqPageId) {
            $this->applyFaqSchema(
                (int) $routerFaqPageId,
                [
                    [
                        'question' => 'Can Help4 Payment Router send traffic to different processors?',
                        'answer' => 'Yes. Routes can target Stripe, PayPal, Square, Braintree, Authorize.net, Wise, and custom adapters based on rules and conditions.',
                    ],
                    [
                        'question' => 'Can digital products, subscriptions, and shipped products use different rules?',
                        'answer' => 'Yes. Product and subscription context can drive routing so each checkout path gets the right processor behavior.',
                    ],
                    [
                        'question' => 'How should I test routing safely?',
                        'answer' => 'Enable test mode, validate webhooks, run checkout scenarios, then switch to live keys after successful tests.',
                    ],
                ]
            );
        }
        $this->applyFaqSchema(
            (int) $freeBuilderId,
            [
                [
                    'question' => 'Is Help4 Builder Suite free to download?',
                    'answer' => 'Yes. The current public Builder Suite ZIP can be downloaded and used without buying a Help4 hosting plan. Hosting, managed service, migration, and custom implementation are separate services.',
                ],
                [
                    'question' => 'Does Help4 Builder Suite require the Help4 Blank theme?',
                    'answer' => 'No. Builder Suite is designed to work with properly coded WordPress themes. Help4 Blank is the recommended separate companion theme when you want the cleanest Builder-controlled canvas.',
                ],
                [
                    'question' => 'Can I build headers, footers, and mobile layouts?',
                    'answer' => 'Yes. Builder Suite includes global template assignments and responsive controls for layout, spacing, typography, widths, columns, alignment, visibility, and other per-device design values.',
                ],
                [
                    'question' => 'Does the free builder guarantee search rankings?',
                    'answer' => 'No. Builder Suite provides metadata, schema, readability, internal-link, sitemap, discovery, and launch checks. Search engines decide crawling, indexing, display, and ranking.',
                ],
            ]
        );
        foreach ([$commerceSupportId, $legacyCommerceSupportId] as $commerceFaqPageId) {
            $this->applyFaqSchema(
                (int) $commerceFaqPageId,
                [
                    [
                        'question' => 'Is Help4 Commerce built on a third-party store plugin?',
                        'answer' => 'No. Help4 Commerce is the native catalog, variation, subscription, product-context, and checkout-routing layer inside Help4 Builder Suite.',
                    ],
                    [
                        'question' => 'Can Help4 Commerce handle large catalogs?',
                        'answer' => 'Yes. The commerce tools are designed around indexed catalog data, importer workflows, variations, subscriptions, and operational patterns for very large product sets.',
                    ],
                    [
                        'question' => 'How does Help4 explain commerce setup to nontechnical clients?',
                        'answer' => 'Help4 breaks catalog, checkout, subscription, and payment-routing decisions into plain-language steps so clients can hand off the technical work.',
                    ],
                ]
            );
        }
        foreach ([$pluginPaymentRouterId, $pluginStripeId] as $paymentPluginFaqPageId) {
            $this->applyFaqSchema(
                (int) $paymentPluginFaqPageId,
                [
                    [
                        'question' => 'What does Help4 Payment Router do?',
                        'answer' => 'It routes checkout traffic by product, cart, subscription, region, risk, processor availability, and failover rules across supported processors and custom adapters.',
                    ],
                    [
                        'question' => 'Does Help4 Payment Router support more than one processor?',
                        'answer' => 'Yes. It is built for multi-processor routing across Stripe, PayPal, Square, Braintree, Authorize.net, Wise, and Help4-managed processor connections.',
                    ],
                    [
                        'question' => 'Who should configure payment routing?',
                        'answer' => 'A Help4 technician or qualified site administrator should map processors, routes, webhooks, subscriptions, and test-mode scenarios before live checkout.',
                    ],
                ]
            );
        }
        $this->applyFaqSchema(
            (int) $builderGuideId,
            [
                [
                    'question' => 'How do I start building a page with Help4 Builder?',
                    'answer' => 'Open a page, set Help4 Builder mode, launch the visual editor, add section layout first, then place widgets.',
                ],
                [
                    'question' => 'Can I edit content directly in live preview?',
                    'answer' => 'Yes. Click elements on canvas to edit and use responsive controls for each viewport before publishing.',
                ],
                [
                    'question' => 'How do I check that frontend matches builder view?',
                    'answer' => 'Save layout, preview frontend, and validate desktop/tablet/mobile breakpoints before publishing.',
                ],
            ]
        );
        $this->applyFaqSchema(
            (int) $themeBuilderGuideId,
            [
                [
                    'question' => 'What does Theme Builder control?',
                    'answer' => 'It controls global templates such as header, footer, and reusable sections across the website.',
                ],
                [
                    'question' => 'Can templates target only specific pages?',
                    'answer' => 'Yes. You can use include/exclude rules and template priority settings for scoped assignments.',
                ],
                [
                    'question' => 'How do I avoid template conflicts?',
                    'answer' => 'Set one default global template per role and use higher priority only where exceptions are needed.',
                ],
            ]
        );

        $this->ensureSeoMetaCoverageForAllPublishedPages();
        $this->markLegacySalesAlias((int) $legacyCommerceSupportId, (int) $commerceSupportId);
        $this->markLegacySalesAlias((int) $legacyStripeRouterGuideId, (int) $paymentRouterGuideId);
        $this->markLegacySalesAlias((int) $pluginStripeId, (int) $pluginPaymentRouterId);
        $this->ensureSalesLegacyRedirects(
            [
                ["/\x77\x6f\x6f\x63\x6f\x6d\x6d\x65\x72\x63\x65-support/", home_url('/commerce-support/')],
                ["/stripe-router-for-\x77\x6f\x6f\x63\x6f\x6d\x6d\x65\x72\x63\x65/", home_url('/help4-payment-router/')],
                ["/plugin-stripe-router-\x77\x6f\x6f\x63\x6f\x6d\x6d\x65\x72\x63\x65/", home_url('/plugin-help4-payment-router/')],
            ]
        );

        $this->ensurePrimaryMenuLinks(
            array_filter(
                [
                    (int) $shopId,
                    (int) $packagesId,
                    (int) $hostingPageId,
                    (int) $supportPageId,
                    (int) $faqPageId,
                    (int) $builderTutorialsId,
                    (int) $builderScreenshotsId,
                    (int) $builderGuideId,
                    (int) $builderFirstPageId,
                    (int) $builderTemplateLibraryId,
                    (int) $blankThemeId,
                    (int) $themeBuilderGuideId,
                    (int) $commerceSupportId,
                    (int) $paymentRouterGuideId,
                ],
                static fn (int $id): bool => $id > 0
            )
        );
    }

    private function h4ProductActions(string $primaryUrl, string $primaryText, string $secondaryUrl, string $secondaryText): string
    {
        return '<div class="h4-product-hero__actions"><a class="button button-primary" href="' . esc_url($primaryUrl) . '" target="_blank" rel="noopener">' . esc_html($primaryText) . '</a> <a class="button" href="' . esc_url($secondaryUrl) . '" target="_blank" rel="noopener">' . esc_html($secondaryText) . '</a></div>';
    }

    private function h4TrackedDownloadUrl(string $product): string
    {
        $builder = $product === 'builder-suite';
        $path = $builder ? '/get/help4-builder-suite/' : '/get/help4-blank/';
        $args = [
            'source' => 'help4wordpress',
            'campaign' => 'site-downloads',
        ];
        if ($builder) {
            $args['version'] = H4BS_VERSION;
        }
        return add_query_arg($args, home_url($path));
    }

    private function h4ProductSalesActions(string $callUrl, string $smsUrl, string $whatsAppUrl): string
    {
        return '<div class="h4-product-hero__actions"><a class="button" href="' . esc_url($smsUrl) . '">Text Sales</a> <a class="button" href="' . esc_url($whatsAppUrl) . '" target="_blank" rel="noopener">WhatsApp Sales</a> <a class="button" href="' . esc_url($callUrl) . '">Call Sales</a></div>';
    }

    /**
     * @param array<int, array{0:string, 1:string}> $rows
     */
    private function h4ProductCommand(array $rows, string $label): string
    {
        $html = '<aside class="h4-product-command"><p class="h4-product-command__label">' . esc_html($label) . '</p>';
        foreach ($rows as $row) {
            $html .= '<div class="h4-product-command__row"><span>' . esc_html((string) $row[0]) . '</span><strong>' . esc_html((string) $row[1]) . '</strong></div>';
        }
        return $html . '</aside>';
    }

    private function h4ProductHero(string $eyebrow, string $headline, string $lede, string $actions, string $command): string
    {
        return '<section class="h4-product-hero h4wp-noise-overlay h4wp-soft-glow"><div class="h4-product-hero__grid"><div class="h4-product-hero__body"><p class="h4-product-eyebrow">' . esc_html($eyebrow) . '</p><h2>' . esc_html($headline) . '</h2><p class="h4-product-lede">' . esc_html($lede) . '</p>' . $actions . '</div>' . $command . '</div></section>';
    }

    /**
     * @param array<int, array{0:string, 1:string}> $cards
     */
    private function h4ProductFeatureBand(string $eyebrow, string $headline, string $lede, array $cards): string
    {
        $html = '<section class="h4-product-feature-band"><div><p class="h4-product-eyebrow">' . esc_html($eyebrow) . '</p><h2>' . esc_html($headline) . '</h2><p>' . esc_html($lede) . '</p></div><div class="h4-product-feature-grid">';
        foreach ($cards as $card) {
            $html .= '<article><h3>' . esc_html((string) $card[0]) . '</h3><p>' . esc_html((string) $card[1]) . '</p></article>';
        }
        return $html . '</div></section>';
    }

    /**
     * @param array<int, array{0:string, 1:string, 2:string, 3:string, 4:string}> $cards
     */
    private function h4ProductCardGrid(array $cards): string
    {
        $html = '<section class="h4wp-card-grid">';
        foreach ($cards as $card) {
            $html .= '<article class="h4wp-card"><p class="h4-product-eyebrow">' . esc_html((string) $card[0]) . '</p><h3>' . esc_html((string) $card[1]) . '</h3><p>' . esc_html((string) $card[2]) . '</p>';
            if (! empty($card[3]) && ! empty($card[4])) {
                $html .= '<p><a class="button button-primary" href="' . esc_url((string) $card[3]) . '">' . esc_html((string) $card[4]) . '</a></p>';
            }
            $html .= '</article>';
        }
        return $html . '</section>';
    }

    /**
     * @param array<int, array{0:string, 1:string, 2:string, 3:string}> $screens
     */
    private function h4ProductScreenGrid(array $screens): string
    {
        $html = '<section class="h4-product-screen-grid" aria-label="Help4 Builder Suite screenshots">';
        foreach ($screens as $screen) {
            $html .= '<article class="h4-product-screen-card"><div class="h4-product-screen-card__media"><img src="' . esc_url((string) $screen[0]) . '" alt="' . esc_attr((string) $screen[1]) . '" loading="lazy" decoding="async" /></div><h3>' . esc_html((string) $screen[2]) . '</h3><p>' . esc_html((string) $screen[3]) . '</p></article>';
        }
        return $html . '</section>';
    }

    /**
     * @param array<int, string> $headers
     * @param array<int, array<int, string>> $rows
     */
    private function h4ProductCompare(array $headers, array $rows): string
    {
        $html = '<section class="h4wp-compare"><table><thead><tr>';
        foreach ($headers as $header) {
            $html .= '<th>' . esc_html((string) $header) . '</th>';
        }
        $html .= '</tr></thead><tbody>';
        foreach ($rows as $row) {
            $html .= '<tr>';
            foreach ($row as $cell) {
                $html .= '<td>' . esc_html((string) $cell) . '</td>';
            }
            $html .= '</tr>';
        }
        return $html . '</tbody></table></section>';
    }

    private function h4ProductFinalCta(string $eyebrow, string $headline, string $body, string $primaryUrl, string $primaryText, string $secondaryUrl, string $secondaryText): string
    {
        return '<section class="h4wp-final-cta h4-product-cta"><div><p class="h4-product-eyebrow">' . esc_html($eyebrow) . '</p><h2>' . esc_html($headline) . '</h2><p>' . esc_html($body) . '</p></div><div class="h4-product-hero__actions"><a class="button button-primary" href="' . esc_url($primaryUrl) . '" target="_blank" rel="noopener">' . esc_html($primaryText) . '</a> <a class="button" href="' . esc_url($secondaryUrl) . '" target="_blank" rel="noopener">' . esc_html($secondaryText) . '</a></div></section>';
    }

    private function h4ProductPackagesPage(string $storeUrl, string $cartUrl, string $ticketUrl, string $clientAreaUrl, string $callUrl, string $smsUrl, string $whatsAppUrl): string
    {
        return $this->h4SalesPlansPageContent(
            'WordPress hosting from $4.95/mo. Add help when you need it.',
            'Choose how much WordPress responsibility you want to keep. Start with DIY hosting, or move into managed care, growth work, and priority operations.',
            $callUrl,
            $ticketUrl,
            $clientAreaUrl,
            false
        );
    }

    private function h4ProductShopPage(string $storeUrl, string $cartUrl, string $ticketUrl, string $callUrl, string $smsUrl, string $whatsAppUrl): string
    {
        return $this->h4SalesPlansPageContent(
            'Buy WordPress hosting and real help without decoding a server chart.',
            'The Help4 shop is organized around the work you want handled. Pick an entry point, complete checkout on Help4 Network, and keep one support path as the site grows.',
            $callUrl,
            $ticketUrl,
            ContactRoutes::supportClientAreaUrl(),
            true
        );
    }

    private function h4SalesPlansPageContent(string $headline, string $lede, string $callUrl, string $ticketUrl, string $clientAreaUrl, bool $showServiceRoutes): string
    {
        $diyUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/basic-hosting-4-me';
        $standardUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/help-4-me-standard';
        $growthUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/help-4-me-more';
        $priorityUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/help-4-me-always';
        $enterpriseUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/help4-me-enterprise';
        $heroImage = H4BS_URL . 'assets/images/marketing/help4-wordpress-hosting-hero-20260716.jpg';

        $serviceRoutes = '';
        if ($showServiceRoutes) {
            $serviceRoutes = '<section class="h4-sales-services h4-sales-services--compact"><div class="h4-sales-shell"><div class="h4-sales-section-heading"><h2>Need a one-time fix before a monthly plan?</h2><p>Use the same Help4 support path for migration, malware cleanup, speed work, emergency troubleshooting, or a design-to-WordPress build.</p></div><div class="h4-sales-service-list h4-sales-service-list--grid">'
                . $this->h4SalesService('migration-path', 'Migration', 'Move an existing WordPress site and verify the public result.', home_url('/wordpress-migration-service/'))
                . $this->h4SalesService('malware-cleanup', 'Malware cleanup', 'Recover from suspicious behavior and build a safer next step.', home_url('/wordpress-malware-removal/'))
                . $this->h4SalesService('speed-tuning', 'Speed work', 'Reduce page weight, caching problems, and Core Web Vitals friction.', home_url('/wordpress-speed-optimization/'))
                . $this->h4SalesService('emergency-support', 'Emergency help', 'Open a tracked request when the site is broken or blocked.', home_url('/emergency-wordpress-support/'))
                . '</div></div></section>';
        }

        return '<div class="h4-sales-home h4-sales-plans-page">'
            . '<section class="h4-sales-subhero"><div class="h4-sales-shell h4-sales-subhero__grid"><div><h1>' . esc_html($headline) . '</h1><p>' . esc_html($lede) . '</p><div class="h4-sales-actions"><a class="h4-sales-button h4-sales-button--primary" href="' . esc_url($diyUrl) . '" target="_blank" rel="noopener">Start for $4.95/mo</a><a class="h4-sales-button h4-sales-button--secondary" href="' . esc_url($callUrl) . '">Call Sales</a></div><p class="h4-sales-subhero__note">Checkout is completed on Help4 Network. Service email may arrive from help4network.com or help4.us, so check spam and other filtered folders.</p></div><figure><img src="' . esc_url($heroImage) . '" alt="Help4 WordPress hosting, site health, and human support" width="1400" height="875" loading="eager" decoding="async" fetchpriority="high"></figure></div></section>'
            . '<section class="h4-sales-pricing"><div class="h4-sales-shell"><div class="h4-sales-section-heading"><h2>Choose by responsibility, not technical buzzwords.</h2><p>These are clear starting points. The live checkout page contains the current billing terms and final product details.</p></div><div class="h4-sales-plan-rail">'
            . $this->h4SalesPlan('DIY Starter', '$4.95', '/mo', 'You manage daily WordPress work. Help4 keeps the hosting path available.', ['Hosting stability', 'Backups and restore assistance', 'Firewall and malware coverage'], $diyUrl, 'Start DIY', true)
            . $this->h4SalesPlan('Managed Care', 'Site care', '', 'Help4 handles recurring technical chores and routine support.', ['Core and plugin updates', 'Forms, SSL, and conflicts', 'Backups and malware cleanup'], $standardUrl, 'Choose Managed', false)
            . $this->h4SalesPlan('Growth Support', 'Improve', '', 'Help4 works on the site as a sales and service surface.', ['Landing and service pages', 'Speed and conversion work', 'Practical SEO implementation'], $growthUrl, 'Choose Growth', false)
            . $this->h4SalesPlan('Priority Operations', 'Escalate', '', 'Help4 adds faster triage and deeper ownership for critical sites.', ['Urgent change requests', 'Critical failures', 'High-priority fixes'], $priorityUrl, 'Choose Priority', false)
            . '</div><div class="h4-sales-enterprise"><div><h3>Agency, multi-site, or enterprise scope?</h3><p>Use the enterprise path when several sites, deadlines, clients, or internal teams depend on the work.</p></div><a class="h4-sales-text-link" href="' . esc_url($enterpriseUrl) . '" target="_blank" rel="noopener">View enterprise path</a></div></div></section>'
            . '<section class="h4-sales-fit"><div class="h4-sales-shell"><div class="h4-sales-section-heading"><h2>A plain-English fit guide.</h2></div><div class="h4-sales-fit__rail"><article><h3>I only need hosting</h3><p>Start DIY. You keep normal WordPress tasks and Help4 provides the hosting path.</p></article><article><h3>I hate updates and plugin problems</h3><p>Managed Care gives recurring maintenance and support a real owner.</p></article><article><h3>I need more leads or sales</h3><p>Growth Support connects speed, pages, forms, SEO, and conversion work.</p></article><article><h3>I cannot afford long delays</h3><p>Priority Operations is the stronger escalation path for critical sites.</p></article></div></div></section>'
            . $serviceRoutes
            . '<section class="h4-sales-faq"><div class="h4-sales-shell h4-sales-faq__grid"><div class="h4-sales-section-heading"><h2>Before checkout.</h2><p>Use the final Help4 Network product page for current billing terms. Call when the right tier is not obvious.</p></div><div class="h4-sales-faq__list"><details><summary>Can I upgrade from the $4.95 plan?</summary><p>Yes. The Help4 path is designed so an owner can begin with hosting and move into managed care, growth work, or priority support when needed.</p></details><details><summary>Who handles normal WordPress tasks on DIY?</summary><p>The site owner handles normal content, plugin, and theme decisions. Help4 handles the hosting path described on the product page.</p></details><details><summary>Where is billing handled?</summary><p>Checkout, billing, and service management are handled through Help4 Network. The WordPress site links directly to the matching product page.</p></details><details><summary>Can Help4 recommend a plan?</summary><p>Yes. Call sales or send the site URL, the current problem, and the outcome you want.</p></details></div></div></section>'
            . '<section class="h4-sales-final"><div class="h4-sales-shell h4-sales-final__inner"><div><h2>Still deciding? Let a person route the problem.</h2><p>Describe what you want off your plate. Help4 will point you to the closest plan or a custom scope.</p></div><div class="h4-sales-actions"><a class="h4-sales-button h4-sales-button--primary" href="' . esc_url($diyUrl) . '" target="_blank" rel="noopener">Start hosting</a><a class="h4-sales-button h4-sales-button--dark" href="' . esc_url($callUrl) . '">Call sales</a><a class="h4-sales-text-link h4-sales-text-link--light" href="' . esc_url($ticketUrl) . '" target="_blank" rel="noopener">Send a request</a><a class="h4-sales-text-link h4-sales-text-link--light" href="' . esc_url($clientAreaUrl) . '" target="_blank" rel="noopener">Client area</a></div></div></section>'
            . '</div>';
    }

    private function h4ProductManagedHostingPage(string $storeUrl, string $cartUrl, string $ticketUrl, string $clientAreaUrl, string $supportRepUrl, string $callUrl, string $smsUrl, string $whatsAppUrl): string
    {
        $managedUrl = 'https://help4network.com/index.php?rp=/store/help-4-wordpress/help-4-me-standard';
        $heroImage = H4BS_URL . 'assets/images/marketing/help4-wordpress-hosting-hero-20260716.jpg';

        return '<div class="h4-sales-home h4-sales-managed-page"><section class="h4-sales-subhero"><div class="h4-sales-shell h4-sales-subhero__grid"><div><h1>Stop becoming the WordPress person just because you own the website.</h1><p>Send Help4 the outcome. Managed care can own updates, backups, plugin conflicts, forms, SSL problems, malware cleanup, routine requests, and the ongoing work that keeps a business site useful.</p><div class="h4-sales-actions"><a class="h4-sales-button h4-sales-button--primary" href="' . esc_url($managedUrl) . '" target="_blank" rel="noopener">Start managed care</a><a class="h4-sales-button h4-sales-button--secondary" href="' . esc_url($callUrl) . '">Call Sales</a></div></div><figure><img src="' . esc_url($heroImage) . '" alt="Help4 technician supporting a WordPress small business website" width="1400" height="875" loading="eager" decoding="async" fetchpriority="high"></figure></div></section>'
            . '<section class="h4-sales-journey"><div class="h4-sales-shell"><div class="h4-sales-section-heading"><h2>One request path from problem to finished work.</h2></div><div class="h4-sales-journey__rail"><article><span>01</span><h3>You ask</h3><p>Describe the result in plain English.</p></article><article><span>02</span><h3>Help4 maps it</h3><p>We identify scope, risk, access, and priority.</p></article><article><span>03</span><h3>Help4 does it</h3><p>Build, fix, tune, test, and publish the work.</p></article><article><span>04</span><h3>You review</h3><p>Approve the result and keep the business moving.</p></article></div></div></section>'
            . '<section class="h4-sales-services"><div class="h4-sales-shell h4-sales-services__grid"><div class="h4-sales-section-heading"><h2>Managed means the website has an operating path.</h2><p>A server alone cannot fix a broken form, a plugin conflict, a slow service page, or a design waiting to be built.</p></div><div class="h4-sales-service-list">'
            . $this->h4SalesService('managed-hosting', 'Site care', 'Core and plugin updates, backups, security posture, and routine technical requests.', home_url('/wordpress-maintenance-care-plans/'))
            . $this->h4SalesService('design-handoff', 'Site work', 'Content edits, landing pages, service pages, forms, CTAs, and design handoff.', home_url('/design-to-wordpress/'))
            . $this->h4SalesService('emergency-support', 'Site rescue', 'Broken pages, migrations, malware symptoms, checkout issues, and urgent troubleshooting.', home_url('/emergency-wordpress-support/'))
            . $this->h4SalesService('seo-growth', 'Site growth', 'Speed, useful search content, conversion sections, and practical SEO implementation.', home_url('/help-4-wordpress/'))
            . '</div></div></section>'
            . '<section class="h4-sales-fit"><div class="h4-sales-shell"><div class="h4-sales-section-heading"><h2>When managed care is worth it.</h2></div><div class="h4-sales-fit__rail"><article><h3>The site makes money</h3><p>Forms, checkout, pages, and uptime should have a tracked support path.</p></article><article><h3>The chores keep slipping</h3><p>Updates, backups, conflicts, and small fixes stop living on your list.</p></article><article><h3>A team depends on it</h3><p>Requests need ownership, status, and an escalation route.</p></article><article><h3>You want a result, not a lesson</h3><p>Give Help4 the design or business outcome and let the implementation move.</p></article></div></div></section>'
            . '<section class="h4-sales-faq"><div class="h4-sales-shell h4-sales-faq__grid"><div class="h4-sales-section-heading"><h2>What managed care changes.</h2><p>The plan creates an operating relationship around the site. It does not turn every possible redesign or custom system into unlimited routine work.</p></div><div class="h4-sales-faq__list"><details open><summary>How do I request work?</summary><p>Open a tracked request with the site URL, desired outcome, affected page, business impact, and deadline. Help4 confirms whether the request fits routine care or needs a separate project scope.</p></details><details><summary>What should stay out of a normal ticket?</summary><p>Do not send passwords, private keys, payment credentials, customer exports, or authentication codes in ordinary messages. Help4 can establish a safer access path when sensitive access is actually needed.</p></details><details><summary>How are changes verified?</summary><p>The work path can include backup, staging or controlled editing, desktop/mobile checks, form or checkout testing, cache clearing, and a final public check depending on the request and risk.</p></details><details><summary>Can Help4 build from a design?</summary><p>Yes. Send the design, content, assets, target pages, and expected behavior. Help4 can map it into reusable Builder templates and responsive page output.</p></details></div></div></section>'
            . '<section class="h4-sales-final"><div class="h4-sales-shell h4-sales-final__inner"><div><h2>Hand off the next WordPress problem.</h2><p>Send the URL, the desired outcome, and what you want Help4 to own.</p></div><div class="h4-sales-actions"><a class="h4-sales-button h4-sales-button--primary" href="' . esc_url($managedUrl) . '" target="_blank" rel="noopener">Start managed care</a><a class="h4-sales-button h4-sales-button--dark" href="' . esc_url($callUrl) . '">Call sales</a><a class="h4-sales-text-link h4-sales-text-link--light" href="' . esc_url($ticketUrl) . '" target="_blank" rel="noopener">Open a request</a><a class="h4-sales-text-link h4-sales-text-link--light" href="' . esc_url($clientAreaUrl) . '" target="_blank" rel="noopener">Client area</a></div></div></section></div>';
    }

    private function h4ProductCommerceSupportPage(string $ticketUrl, string $clientAreaUrl): string
    {
        return $this->h4ProductHero(
            'Help4 Commerce support',
            'Product catalogs, subscriptions, checkout routing, and store pages without the plugin pileup.',
            'Help4 Commerce is the native commerce path inside the Builder Suite: large catalog handling, variations, subscriptions, product metadata, payment-router handoff, and support workflows built for owners who want the store handled.',
            $this->h4ProductActions($ticketUrl, 'Request Commerce Help', home_url('/help4-payment-router/'), 'Payment Router Guide'),
            $this->h4ProductCommand(
                [
                    ['Catalog', 'Large product data'],
                    ['Products', 'Variations and metadata'],
                    ['Billing', 'Subscriptions and renewals'],
                    ['Checkout', 'Processor routing and handoff'],
                ],
                'Commerce stack'
            )
        )
        . $this->h4ProductCardGrid(
            [
                ['Catalogs', 'Native Product Engine', 'Products, imports, categories, search, filters, and cursor paging are built for serious catalog sizes instead of tiny demo stores.', home_url('/shop/'), 'View Shop'],
                ['Products', 'Variations + Product Context', 'Variable, digital, downloadable, virtual, booking, service, subscription, and shipped product types can carry the data checkout needs.', $ticketUrl, 'Scope Products'],
                ['Billing', 'Subscriptions and Plans', 'Subscription-style products, plan pages, renewal context, and customer support paths connect to Help4 WordPress checkout and account handling.', home_url('/packages/'), 'View Packages'],
                ['Payments', 'Multi-Processor Routing', 'Route checkout through Stripe, PayPal, Square, Braintree, Authorize.net, Wise, and custom Help4 payment-router adapters.', home_url('/plugin-help4-payment-router/'), 'View Router'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Plain-English store help',
            'Customers should not need to know the stack to buy the fix.',
            'The page explains the store problem in business terms: products need to load, buying paths need to work, renewals need to stay clear, and payment failures need a fallback.',
            [
                ['For owners', 'Send the product list, plan idea, or checkout problem. Help4 maps the data model, page structure, and payment path.'],
                ['For designers', 'Hand over product-page designs and Help4 turns them into reusable commerce templates without bloated theme output.'],
                ['For large catalogs', 'Use imports, native catalog mode, filters, and load-test guidance when product counts move past normal small-store assumptions.'],
            ]
        )
        . $this->h4ProductCompare(
            ['What is confusing the customer', 'Help4 Commerce answer', 'Why it matters'],
            [
                ['I have too many products', 'Import, map, search, filter, and paginate catalogs with large-store patterns', 'Visitors find products without the admin or frontend grinding down.'],
                ['Products have options', 'Use variation and metadata support for product context', 'The checkout path knows what kind of thing is being sold.'],
                ['I sell recurring access', 'Subscription products and plan pages connect to Help4 billing workflows', 'Renewals and support stay connected to the account.'],
                ['One processor is risky', 'Payment Router can choose and fail over between processors', 'A bad payment path does not have to stop the whole store.'],
                ['I need it built for me', 'Help4 can build product templates, checkout handoff, SEO pages, and support flows', 'The customer hires the work out and gets back to business.'],
            ]
        )
        . $this->h4ProductFinalCta('Need the store mapped?', 'Send the products, processors, and what buying failure costs.', 'Help4 will turn the catalog, subscriptions, checkout path, and support needs into a build plan or managed request.', $ticketUrl, 'Open Commerce Request', $clientAreaUrl, 'Client Area');
    }

    private function h4PaymentRouterGuidePage(string $supportTicketUrl): string
    {
        return '<h1>Help4 Payment Router</h1>'
            . '<p>Route checkout traffic by rules instead of betting the business on one processor path. Choose the standalone Payment Router for Stripe when a WooCommerce store needs multiple Stripe accounts, or use the native Help4 Payment Router inside Builder Suite for Help4 Commerce and broader processor routing.</p>'
            . '<h2>Choose The Right Router</h2>'
            . '<div class="h4wp-card-grid">'
            . '<article class="h4wp-card"><h3>Payment Router for Stripe</h3><p>For WooCommerce stores routing transactions across multiple Stripe accounts by product, category, ZIP code, state, or country.</p><p><a class="button button-primary" href="' . esc_url(home_url('/stripe-router-tutorial/')) . '">Open Stripe Tutorial</a></p></article>'
            . '<article class="h4wp-card"><h3>Builder Suite Payment Router</h3><p>For Help4 Commerce stores that need product-aware rules across Stripe, PayPal, Square, Braintree, Authorize.net, Wise, or custom adapters.</p><p><a class="button" href="' . esc_url(home_url('/help4-commerce-products-variations-customer-fields/')) . '">Open Commerce Guide</a></p></article>'
            . '</div>'
            . '<h2>What You Configure</h2>'
            . '<ul>'
            . '<li>Route definitions with name, priority, status, and fallback behavior.</li>'
            . '<li>Processor targets for Stripe, PayPal, Square, Braintree, Authorize.net, Wise, and custom adapters.</li>'
            . '<li>Conditions for digital products, subscriptions, bookings, shipping-required items, totals, geo, and support workflows.</li>'
            . '</ul>'
            . '<h2>Product Context</h2>'
            . '<ul>'
            . '<li>Use Help4 Commerce product types, variations, subscriptions, and metadata to decide the payment route.</li>'
            . '<li>Send fulfillment and renewal context to the processor adapter so support can see what happened.</li>'
            . '<li>Keep checkout connected to Help4 WordPress account, billing, and service operations.</li>'
            . '</ul>'
            . '<h2>Go Live Checklist</h2>'
            . '<ol>'
            . '<li>Enable test mode per processor.</li>'
            . '<li>Validate webhook and signature handling.</li>'
            . '<li>Run checkout tests for physical, digital, subscription, and booking items.</li>'
            . '<li>Switch to live keys and monitor first transactions.</li>'
            . '</ol>'
            . '<h2>Plan The Routes Before Adding Credentials</h2>'
            . '<p>Write the business rules in plain language first: which products can use each processor, whether subscriptions need a separate route, which countries or currencies are supported, what happens when a processor is unavailable, and when checkout should stop instead of falling back. This keeps routing logic reviewable and prevents credentials from hiding a bad plan.</p>'
            . '<h2>Use A Real Checkout Test Matrix</h2>'
            . '<p>Test more than one perfect card payment. Cover a successful payment, a declined payment, a customer retry, webhook delay, duplicate notification, refund, cancellation, subscription renewal, failed renewal, variation change, shipping-required item, digital item, and a mixed cart when the store allows one. Confirm the order status, customer message, processor record, fulfillment context, and support trail for each case.</p>'
            . '<h2>Failure And Recovery Rules</h2>'
            . '<p>A fallback route should be intentional. Decide whether the second processor can legally and technically handle the same product, currency, subscription schedule, tax context, and customer location. Record why a route changed, avoid repeatedly charging the same attempt, and give support enough non-secret order context to explain what happened.</p>'
            . '<h2>What To Send Help4</h2>'
            . '<p>Include the store URL, product types, currencies, countries, processors, subscription requirements, current checkout problem, and the business impact of failure. Also identify the order states, refunds, renewals, fulfillment steps, and customer messages that must stay connected. Never place live secret keys in a normal support message. Help4 can establish a protected credential path after the routing plan and scope are confirmed.</p>'
            . '<p><a class="button button-primary" href="' . esc_url(home_url('/plugin-help4-payment-router/')) . '">Payment Router Plugin Page</a> '
            . '<a class="button" href="' . esc_url($supportTicketUrl) . '" target="_blank" rel="noopener">Request Routing Setup</a></p>'
            . '<p><a class="button" href="' . esc_url(home_url('/stripe-router-pro-vs-enterprise/')) . '">Compare Pro and Enterprise</a> '
            . '<a class="button" href="' . esc_url(home_url('/commerce-support/')) . '">Commerce Support</a></p>';
    }

    private function h4StripeRouterTutorialPage(string $supportTicketUrl): string
    {
        $base = trailingslashit(home_url('/wp-content/plugins/help4-builder-suite/assets/tutorial-screens/payment-router'));
        $screens = [
            ['settings-page.png', 'Payment Router for Stripe settings page', 'Start in settings', 'Review mode, checkout behavior, logging, and the license state before creating live routes.'],
            ['connections-list.png', 'Stripe connection list', 'Review connections', 'Give each Stripe account a clear business name so assignments and support records remain understandable.'],
            ['connections-add.png', 'Add Stripe connection form', 'Add a connection', 'Create the processor connection through the protected admin form. Never paste live secret keys into a page or support message.'],
            ['connection-edit.png', 'Edit Stripe connection screen', 'Edit deliberately', 'Change one connection at a time and retest every assignment that can select it.'],
            ['assignments-list.png', 'Stripe Router assignments list', 'See rule priority', 'Review route order and status before checkout. Narrow, intentional rules should be easier to explain than overlapping catchalls.'],
            ['assignments-add.png', 'Add Stripe Router assignment', 'Build an assignment', 'Choose the connection and add product, category, ZIP, state, or country conditions that match the business rule.'],
            ['assignment-edit.png', 'Edit Stripe Router assignment', 'Maintain a route', 'Document why the route exists, confirm priority, then repeat the matching and non-matching checkout tests.'],
            ['settings.png', 'Stripe Router checkout settings', 'Finish checkout setup', 'Validate test mode, checkout display, webhooks, logging, and failure behavior before enabling production traffic.'],
        ];
        $cards = '';
        foreach ($screens as $screen) {
            $cards .= '<article class="h4-plugin-shot-card"><div class="h4-plugin-shot-media"><img src="' . esc_url($base . $screen[0]) . '" alt="' . esc_attr($screen[1]) . '" loading="lazy" decoding="async"></div><h3>' . esc_html($screen[2]) . '</h3><p>' . esc_html($screen[3]) . '</p></article>';
        }

        return $this->h4ProductHero(
            'Payment Router for Stripe tutorial',
            'Route WooCommerce payments across the right Stripe accounts.',
            'Use product, category, ZIP code, state, and country rules to select a Stripe connection. This walkthrough shows the real router screens and the test sequence needed before live payments.',
            $this->h4ProductActions(home_url('/stripe-router-pro-vs-enterprise/'), 'Compare Plans', 'https://help4network.com/cart.php?gid=9#product40', 'Buy Pro'),
            $this->h4ProductCommand([['Current package', 'Payment Router for Stripe 1.1.38'], ['Rules', 'Product + geography'], ['Plans', 'Pro and Enterprise'], ['Checkout', 'Help4 Network']], 'Router setup')
        )
        . '<section class="h4wp-section"><div class="h4wp-section__header"><p class="h4-product-eyebrow">Real admin screens</p><h2>Follow the same path inside WordPress.</h2><p>Names and keys shown on a customer site are private. These screenshots focus on the workflow so an administrator can configure the plugin without exposing payment credentials.</p></div><div class="h4-plugin-shot-grid">' . $cards . '</div></section>'
        . $this->h4ProductCompare(
            ['Step', 'What to do', 'What to prove'],
            [
                ['1. Plan', 'Write which Stripe account should receive each product and geographic case', 'Every rule has a business owner and no unexplained overlap.'],
                ['2. Connect', 'Add each Stripe account with a distinct name and test credentials first', 'Connection validation succeeds without storing credentials in page content.'],
                ['3. Assign', 'Create the narrowest product/category/geographic rules and set priority', 'Matching and non-matching carts resolve to the expected account.'],
                ['4. Validate', 'Test success, decline, retry, refund, webhook delay, duplicate event, and mixed carts', 'Order status, customer message, Stripe record, and support trail agree.'],
                ['5. Launch', 'Move to live credentials through a protected path and monitor first transactions', 'No duplicate charges, unexplained fallbacks, or missing webhook updates.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Common use cases',
            'Use routing when the business structure requires it.',
            'More accounts do not automatically make checkout better. Add a route when products, legal entities, regions, merchant relationships, or operational ownership genuinely require separate Stripe destinations.',
            [
                ['Multi-entity business', 'Send products owned by different business entities to their approved Stripe accounts.'],
                ['Regional operations', 'Route approved states, countries, or ZIP areas while keeping a clear blocked/fallback policy.'],
                ['Product ownership', 'Select the destination using exact products or categories when teams or brands own different revenue.'],
                ['Staged migration', 'Move selected products to a new account first, verify the trail, then expand the assignment.'],
            ]
        )
        . $this->h4ProductFinalCta('Need the routes checked before launch?', 'Have Help4 review the plan and test matrix.', 'Send the store URL, product/category map, approved regions, required Stripe accounts, and the business result expected from each rule. Do not send secret keys in a normal ticket.', $supportTicketUrl, 'Request Router Setup', 'https://help4network.com/cart.php?gid=9#product41', 'Buy Enterprise');
    }

    private function h4StripeRouterPlansPage(string $supportTicketUrl): string
    {
        $pro = 'https://help4network.com/cart.php?gid=9#product40';
        $enterprise = 'https://help4network.com/cart.php?gid=9#product41';

        return $this->h4ProductHero(
            'Stripe Router plans',
            'Choose Pro or Enterprise without guessing at checkout.',
            'Both plans serve WooCommerce stores that route payments across Stripe accounts by product or geography. Start with the published use case and ask Help4 to confirm current licensing, support, and deployment entitlements when the difference matters.',
            $this->h4ProductActions($pro, 'Buy Pro - $24.92/mo', $enterprise, 'Buy Enterprise - $49.92/mo'),
            $this->h4ProductCommand([['Pro', '$24.92/month'], ['Enterprise', '$49.92/month'], ['Rules', 'Product + geography'], ['Billing', 'Help4 Network']], 'Plan comparison')
        )
        . $this->h4ProductCompare(
            ['Plan', 'Practical fit', 'Before ordering'],
            [
                ['Pro', 'A production WooCommerce store that needs defined multi-account product or geographic routing', 'Confirm the licensed main domain, staging subdomain, route count, and support expectations shown at checkout.'],
                ['Enterprise', 'A more complex multi-entity or enterprise deployment that needs the broader Help4 commercial path', 'Send Help4 the entities, domains, staging workflow, geographic rules, support needs, and launch date for entitlement confirmation.'],
                ['Not sure', 'The store has overlapping rules, subscriptions, marketplace behavior, or unusual legal/merchant constraints', 'Open a routing request before purchase so the implementation and plan match.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Two package paths',
            'Do not confuse the standalone Stripe plugin with Builder Suite commerce routing.',
            'Payment Router for Stripe is the WooCommerce-focused package. Builder Suite includes a native Help4 Commerce routing layer intended for Help4 products, subscriptions, and multiple processor adapters.',
            [
                ['WooCommerce + multiple Stripe accounts', 'Choose Payment Router for Stripe Pro or Enterprise.'],
                ['Help4 Commerce + multiple processors', 'Use Builder Suite Payment Router and its Stripe, PayPal, Square, Braintree, Authorize.net, Wise, or custom adapters.'],
                ['Existing Stripe Router installation', 'Back up settings, record connections and assignments, update through the supported package path, then rerun checkout and webhook tests.'],
            ]
        )
        . $this->h4ProductFinalCta('Need Help4 to choose the path?', 'Send the routing requirements before buying.', 'Include WooCommerce or Help4 Commerce, account count, products, categories, regions, subscriptions, domains, staging setup, and required support response.', $supportTicketUrl, 'Ask Help4', home_url('/stripe-router-tutorial/'), 'Open Setup Tutorial');
    }

    private function h4Help4NetCdnPage(string $supportTicketUrl): string
    {
        return $this->h4ProductHero(
            'Help4 Net CDN and edge security',
            'Speed up WordPress, steer traffic, and protect the origin.',
            'Help4 Net combines plugin-based CDN onboarding with optional Help4 DNS, GeoDNS routing, full proxy delivery, WAF controls, cache operations, and managed origin protection.',
            $this->h4ProductActions('https://help4.net/downloads/help4-cdn-plugin.zip', 'Download Free Plugin', 'https://help4network.com/cart.php?gid=9', 'Buy Through Help4 Network'),
            $this->h4ProductCommand([['Free', 'Plugin onboarding'], ['Pro', '$8 speed plan'], ['Enterprise', '$20 starting WAF/proxy'], ['Service', 'Help4 Network']], 'Edge delivery')
        )
        . $this->h4ProductCompare(
            ['Path', 'Use it when', 'Next step'],
            [
                ['Free plugin', 'You want to install the WordPress connector and start plugin-managed onboarding', 'Download the plugin directly from Help4.net.'],
                ['$8 Pro', 'One production domain needs Help4 DNS, GeoDNS, full proxy, WAF controls, broader POP reach, and stronger cache controls', 'Buy through the Help4 Network CDN catalog.'],
                ['$20 Enterprise starting path', 'The full site needs managed GeoDNS proxy delivery, origin shielding, WAF policy, and advanced operational visibility', 'Request an Enterprise scope through Help4 Network.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Why the layers matter',
            'A CDN cache and a managed proxy solve different parts of delivery.',
            'The WordPress plugin handles onboarding and sync. DNS and GeoDNS decide where traffic should go. Proxy and WAF controls inspect and protect requests before they reach the origin. The right plan depends on whether the goal is asset acceleration, production route control, or full-site protection.',
            [
                ['Performance', 'Reduce unnecessary origin trips and use edge cache controls suited to the site.'],
                ['GeoDNS', 'Steer requests using managed routing policy instead of relying on one fragile path.'],
                ['WAF', 'Apply managed request controls and virtual-patching workflows ahead of WordPress.'],
                ['Origin safety', 'Reduce direct exposure and keep controlled fallback behavior for full-proxy deployments.'],
            ]
        )
        . $this->h4ProductFinalCta('Need the CDN path selected?', 'Start with the site and the problem, not a feature checklist.', 'Send the domain, current DNS/CDN, traffic regions, cache problem, security concern, ecommerce/login behavior, and whether nameserver changes are acceptable.', $supportTicketUrl, 'Ask Help4 WordPress', 'https://help4.net/', 'Explore Help4 Net');
    }

    private function upsertBlankThemePage(string $ticketUrl): int
    {
        $pageId = $this->upsertPage(
            'help4-blank-theme',
            'Help4 Blank WordPress Theme',
            wp_kses_post($this->h4ProductBlankThemePage($ticketUrl))
        );
        if ($pageId <= 0) {
            return 0;
        }

        $this->clearMirrorPayload($pageId);
        update_post_meta($pageId, '_h4_builder_mode', 'wp');
        update_post_meta($pageId, '_h4_builder_enabled', '0');
        update_post_meta($pageId, '_h4_builder_page_layout', 'full_width');
        update_post_meta($pageId, '_h4_seo_schema_type', 'software_application');
        update_post_meta($pageId, '_h4_seo_focus_keyword', 'blank WordPress theme');
        update_post_meta($pageId, '_h4_seo_conversion_goal', 'download');
        update_post_meta($pageId, '_h4_seo_primary_cta', 'Download Help4 Blank');
        $this->applySalesSeoMeta(
            $pageId,
            'Free Blank WordPress Theme for Help4 Builder | Help4 Blank',
            'Download Help4 Blank, the free lightweight companion theme for Help4 Builder Suite, with installation steps, compatibility guidance, and direct stable ZIP access.'
        );
        $this->applyFaqSchema(
            $pageId,
            [
                [
                    'question' => 'Is Help4 Blank free to download?',
                    'answer' => 'Yes. Help4 Blank is a free public WordPress theme package and does not require a Help4 hosting purchase.',
                ],
                [
                    'question' => 'Do I need Help4 Blank to use Builder Suite?',
                    'answer' => 'No. Builder Suite works with properly coded WordPress themes. Help4 Blank is recommended when you want the cleanest Builder-controlled site shell.',
                ],
                [
                    'question' => 'How do I install Help4 Blank?',
                    'answer' => 'Download the theme ZIP, open Appearance > Themes > Add New > Upload Theme, choose the ZIP, install it, and activate it when you are ready to use the blank Builder shell.',
                ],
                [
                    'question' => 'Does the public theme contain the Help4 WordPress website design?',
                    'answer' => 'No. The downloadable theme is a neutral starter and does not include Help4 WordPress marketing content, customer branding, staging rules, or site-specific customizations.',
                ],
            ]
        );

        return $pageId;
    }

    private function h4ProductBlankThemePage(string $ticketUrl): string
    {
        $screensBase = trailingslashit(H4BS_URL . 'assets/tutorial-screens/blank-install');
        $themeZip = $this->h4TrackedDownloadUrl('blank-theme');
        $builderZip = $this->h4TrackedDownloadUrl('builder-suite');

        return $this->h4ProductHero(
            'Free blank WordPress theme',
            'Help4 Blank gives the Builder a clean site shell without theme clutter.',
            'Download the lightweight companion theme for Help4 Builder Suite. It preserves the normal WordPress theme boundary, contains mobile-overflow safeguards, and stays neutral so your global templates, colors, typography, spacing, and content become the design.',
            $this->h4ProductActions($themeZip, 'Download Help4 Blank', $builderZip, 'Download Builder Suite'),
            $this->h4ProductCommand(
                [
                    ['Price', 'Free public ZIP'],
                    ['WordPress', '6.5 or newer'],
                    ['PHP', '8.1 or newer'],
                    ['Purpose', 'Clean Builder shell'],
                    ['Package', 'Theme only'],
                ],
                'Current stable theme'
            )
        )
        . $this->h4ProductScreenGrid(
            [
                [$screensBase . 'h4bs-blank-theme-builder-20260723.png', 'Help4 Theme Builder on a clean WordPress installation', 'Build the site shell', 'Create and assign headers, footers, page shells, archives, and 404 layouts without inherited theme styling controlling the result.'],
                [$screensBase . 'h4bs-blank-builder-studio-20260723.png', 'Help4 Builder Studio running on the Help4 Blank theme', 'Edit the real layout', 'Use Builder Studio for content, design, responsive settings, dynamic fields, and reusable sections while Help4 Blank stays out of the way.'],
                [$screensBase . 'h4bs-blank-template-library-20260723.png', 'Help4 Builder template library on a blank installation', 'Start with a template', 'Choose a header, footer, page, section, archive, 404, or complete site-pack direction instead of beginning from an empty screen.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Why use a blank theme',
            'The theme handles WordPress compatibility. Builder Suite handles the design system.',
            'A clean theme reduces conflicts from duplicate headers, forced container widths, inherited typography, unexplained padding, store styles, and mobile overflow. The plugin remains usable with other themes, but Help4 Blank is the recommended base for new Builder-controlled sites.',
            [
                ['Neutral by default', 'No Help4 WordPress marketing pages, customer logos, staging behavior, or finished-site customizations ship in the public theme.'],
                ['Responsive foundation', 'The theme supplies broad containment guards for pages, media, embeds, tables, and common full-viewport layouts without replacing deliberate site-specific fixes.'],
                ['Normal WordPress updates', 'The theme stays a separate package because WordPress plugins and themes have different installation and directory rules.'],
            ]
        )
        . $this->h4ProductCardGrid(
            [
                ['Step 1', 'Download the theme ZIP', 'Use the stable latest.zip route. Do not unzip it before uploading through WordPress.', $themeZip, 'Download Theme ZIP'],
                ['Step 2', 'Upload under Appearance', 'Open Appearance > Themes > Add New > Upload Theme, select the ZIP, and install it.', home_url('/help4-builder-guide/'), 'Open Install Guide'],
                ['Step 3', 'Activate intentionally', 'Activate Help4 Blank when you are ready for Builder templates to control the public shell. Existing sites can keep their current theme during testing.', home_url('/help4-builder-first-page/'), 'Build the First Page'],
                ['Step 4', 'Verify every viewport', 'Check the homepage, navigation, global templates, forms, 404 output, desktop, tablet, 390px, and 360px before replacing a production design.', home_url('/help4-builder-updates-wordpress-7/'), 'Review Update Safety'],
            ]
        )
        . $this->h4ProductCompare(
            ['Situation', 'Recommended theme path', 'Reason'],
            [
                ['New Builder site', 'Install Help4 Blank', 'Begin from a predictable shell with no inherited design system.'],
                ['Existing production site', 'Keep the current theme while testing', 'Avoid replacing working public templates until Builder output is verified.'],
                ['Complete redesign', 'Build on staging with Help4 Blank', 'Move headers, footers, pages, archives, and responsive rules together.'],
                ['Theme-dependent integration', 'Confirm compatibility before switching', 'Some plugins or custom code may expect hooks or templates from the current theme.'],
            ]
        )
        . $this->h4BuilderTutorialVideoSection([33])
        . $this->h4ProductFinalCta(
            'Ready for the clean Builder path?',
            'Download Help4 Blank and Builder Suite as separate WordPress packages.',
            'Upload the theme under Appearance and the plugin under Plugins. Activate each only after testing the target site or staging copy.',
            $themeZip,
            'Download Help4 Blank',
            $ticketUrl,
            'Ask Help4 for Setup'
        );
    }

    private function h4ProductPluginCatalogPage(string $ticketUrl): string
    {
        return $this->h4ProductHero(
            'Help4 plugin stack',
            'Builder tools for people who want WordPress finished, not merely editable.',
            'The Help4 plugin catalog is built around a blank theme plus a modular builder stack: visual layout, global templates, structured fields, sliders, starter specs, default icons, SEO and performance helpers, security, and Help4 Commerce workflows.',
            $this->h4ProductActions($this->h4TrackedDownloadUrl('builder-suite'), 'Download Builder Suite', $this->h4TrackedDownloadUrl('blank-theme'), 'Download Blank Theme'),
            $this->h4ProductCommand(
                [
                    ['Build', 'Pages, sections, templates'],
                    ['Start', '135 starter specs'],
                    ['Design', '230 default SVG icons'],
                    ['Protect', 'SEO, speed, security'],
                ],
                'Plugin roles'
            )
        )
        . $this->h4ProductCardGrid(
            [
                ['Core plugin', 'Help4 Builder Suite', 'Visual builder, template library, structured fields, sliders, icons, commerce, SEO, performance, and security tools in one compartmentalized plugin.', home_url('/plugin-help4-builder-suite/'), 'View Builder Suite'],
                ['Free start', 'Free WordPress Builder', 'See the complete free install path, real blank-install screenshots, responsive workflow, module boundaries, launch checks, and direct public ZIP download.', home_url('/free-wordpress-builder/'), 'Start Free'],
                ['Companion theme', 'Help4 Blank', 'Download the clean public theme ZIP used when Builder Suite should control the site shell without inherited theme design.', $this->h4TrackedDownloadUrl('blank-theme'), 'Download Theme'],
                ['Theme guide', 'Help4 Blank Setup', 'Review compatibility, installation, clean-package boundaries, screenshots, update behavior, and the safe activation checklist.', home_url('/help4-blank-theme/'), 'View Theme Guide'],
                ['Site templates', 'Help4 Theme Builder', 'Headers, footers, reusable templates, display conditions, and blank-theme-friendly layout structure for clean output.', home_url('/plugin-help4-theme-builder/'), 'View Theme Builder'],
                ['Commerce path', 'Help4 Payment Router', 'Checkout routing rules for catalogs, subscriptions, processor adapters, failover logic, and Help4 WordPress checkout handoff.', home_url('/plugin-help4-payment-router/'), 'View Router'],
                ['Start faster', 'Template Library', 'Use starter specs for home pages, services, quote pages, reviews, case studies, products, support articles, release notes, content briefs, and conversion pages.', home_url('/help4-builder-template-library/'), 'Browse Templates'],
                ['Make it yours', 'Default Icons', 'Start with a useful SVG icon drawer instead of hunting for interface, commerce, builder, security, proof, AI image planning, documentation, and rollback icons.', home_url('/help4-builder-icons/'), 'View Icons'],
                ['Make the media', 'AI Image Prompts', 'Use plain-English prompt briefs for hero images, service proof, product mockups, tutorial visuals, social previews, and portfolio screenshots.', home_url('/help4-builder-ai-image-prompts/'), 'Prompt Guide'],
                ['Keep it lean', 'Module Controls', 'Turn on the parts a site actually uses so builder, commerce, forms, slider, SEO, speed, and security assets stay controlled.', home_url('/help4-builder-module-controls/'), 'Module Guide'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Plain-English plugin choices',
            'Customers should know what to click without knowing the stack.',
            'The catalog explains each tool by the job it handles: build the page, control the site shell, sell products, route checkout, improve speed, and protect the install.',
            [
                ['For do-it-yourself users', 'Download the Builder Suite, install the blank theme, pick a starter, and edit the words/images first.'],
                ['For done-for-you clients', 'Send Help4 the site goal, rough notes, screenshots, or a design file and let the build path turn it into pages.'],
                ['For agencies', 'Use the starter specs, reusable templates, and module switches as a repeatable handoff system for client builds.'],
            ]
        )
        . $this->h4ProductFinalCta('Need the stack configured?', 'Tell Help4 what kind of site you are building.', 'Send the site type, required pages, checkout needs, and whether you want starter templates or custom page builds.', $ticketUrl, 'Request Plugin Setup', home_url('/help4-builder-guide/'), 'Builder Guide');
    }

    private function h4ProductFreeBuilderPage(string $ticketUrl): string
    {
        $screensBase = trailingslashit(H4BS_URL . 'assets/tutorial-screens/blank-install');
        $hero = $this->h4ProductHero(
            'Free WordPress builder download',
            'Build the whole WordPress site, not just a pretty page.',
            'Help4 Builder Suite is a free, modular WordPress builder with live visual editing, responsive controls, global templates, structured fields, sliders, forms, SEO guidance, security and performance tools, native commerce, and a separate blank companion theme.',
            $this->h4ProductActions($this->h4TrackedDownloadUrl('builder-suite'), 'Download Free Builder', $this->h4TrackedDownloadUrl('blank-theme'), 'Download Blank Theme'),
            $this->h4ProductCommand(
                [
                    ['Current build', H4BS_VERSION],
                    ['Starter specs', '135 included'],
                    ['Default icons', '230 included'],
                    ['Editing', 'Desktop, tablet, mobile'],
                    ['Theme', 'Help4 Blank separate ZIP'],
                ],
                'Free builder path'
            )
        );
        $hero = str_replace(['<h2>', '</h2>'], ['<h1>', '</h1>'], $hero);

        return $hero . $this->h4ProductScreenGrid(
            [
                [$screensBase . 'h4bs-blank-settings-dashboard-20260723.png', 'Help4 Builder Suite settings on a blank WordPress installation', 'Guided setup', 'Choose the kind of site you are building and start from sensible module, design, SEO, and business defaults that remain editable.'],
                [$screensBase . 'h4bs-blank-builder-studio-20260723.png', 'Help4 Builder Studio live visual editing workspace', 'Live Builder Studio', 'Select an element, change its content or design controls, and review the page in the same editing workspace before saving.'],
                [$screensBase . 'h4bs-blank-template-library-20260723.png', 'Help4 Builder template library with starter layouts', 'Starter structure', 'Begin with a page job, section, header, footer, archive, 404, or site-pack direction instead of staring at an empty canvas.'],
                [$screensBase . 'h4bs-blank-seo-control-20260723.png', 'Help4 Builder Suite SEO score playbook and content audit', 'Launch checks', 'Review search, readability, analytics-readiness, content quality, schema, and page-specific actions before publishing.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'One install, modular responsibilities',
            'Turn on the capabilities the site needs and leave the rest quiet.',
            'Builder Suite is broad by design, but its modules are compartmentalized. A brochure site can use the visual builder, templates, forms, SEO, and security without loading commerce or slider assets on every page. A store or membership project can enable the deeper layers when the data model calls for them.',
            [
                ['Visual building', 'Create sections, containers, columns, content elements, menus, forms, galleries, sliders, dynamic data, and reusable templates with responsive values for real breakpoints.'],
                ['Site design system', 'Control global colors, typography, spacing, buttons, fields, container width, motion, headers, footers, archives, single-content shells, and 404 output.'],
                ['Structured content', 'Create field groups, repeaters, relationships, galleries, calculated values, product data, and dynamic bindings for pages that need more than a block of text.'],
                ['Site operations', 'Use launch checks, metadata, schema, international discovery, local SEO, redirects, image tools, performance controls, hardening, update channels, and feedback reporting.'],
            ]
        )
        . $this->h4ProductCardGrid(
            [
                ['Start clean', 'Use Help4 Blank', 'Install the separate blank companion theme when you want Builder templates to control the site shell without inherited theme design fighting every decision.', $this->h4TrackedDownloadUrl('blank-theme'), 'Download Theme ZIP'],
                ['Understand the split', 'Theme setup and compatibility', 'See why WordPress requires separate theme and plugin packages, what Help4 Blank contains, and how to switch an existing site safely.', home_url('/help4-blank-theme/'), 'Open Theme Guide'],
                ['Start guided', 'Choose a starter', 'Pick a starter by the page job or business need, then replace the sample copy, media, proof, navigation, forms, and calls to action.', home_url('/help4-builder-template-library/'), 'Browse Starter Specs'],
                ['Build deliberately', 'Learn the editor', 'Follow screenshot-based guides for installation, the first page, responsive editing, template assignment, structured fields, sliders, forms, commerce, SEO, and updates.', home_url('/help4-builder-tutorials/'), 'Open Tutorials'],
                ['Go beyond DIY', 'Hand Help4 the build', 'Send the existing site, design file, screenshot, rough notes, or business goal when you want the finished WordPress implementation handled for you.', home_url('/design-to-wordpress/'), 'Request a Build'],
            ]
        )
        . $this->h4ProductCompare(
            ['Job', 'Builder Suite approach', 'Before publishing'],
            [
                ['Build a landing page', 'Use canvas layout, reusable sections, responsive spacing, forms, and one clear conversion path.', 'Verify the real public URL at desktop, tablet, 390px, and 360px.'],
                ['Replace the theme shell', 'Assign Builder headers, footers, archives, single templates, and 404 output through explicit conditions.', 'Check representative routes and confirm navigation works by pointer, keyboard, and touch.'],
                ['Create dynamic content', 'Model fields and relationships first, then bind elements to the saved values.', 'Test empty, normal, long, and permission-restricted values.'],
                ['Launch search-ready content', 'Set the page intent, title, description, canonical, schema, social image, internal links, and readable copy.', 'Confirm sitemap status and rendered metadata; no tool can promise rankings or ad approval.'],
                ['Sell products or subscriptions', 'Enable Help4 Commerce, define product and customer data, then configure checkout and processor routing.', 'Use test credentials and validate orders, webhooks, retries, refunds, email, and failure messages.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'What free does and does not mean',
            'The public ZIP is a real starting point, not a substitute for launch judgment.',
            'You can download and use the current public Builder Suite package without buying a Help4 hosting plan. Hosting, custom implementation, migration, managed maintenance, emergency work, and account-specific support are separate services. The builder provides controls and checks; the website owner still decides what is truthful, lawful, accessible, secure, and ready to publish.',
            [
                ['No forced theme lock-in', 'Builder Suite is designed to work with properly coded WordPress themes. Help4 Blank is recommended when you want the cleanest Builder-owned canvas.'],
                ['No ranking promises', 'SEO tools report implementation signals and opportunities. Search engines decide crawling, indexing, display, and ranking.'],
                ['No hidden live credentials', 'Payment keys, customer records, and private service data belong in protected settings and processor workflows, never page templates or support screenshots.'],
            ]
        )
        . $this->h4ProductFinalCta('Ready to build?', 'Download Builder Suite and its optional blank companion theme.', 'Install the plugin on a staging copy or backed-up WordPress site, add Help4 Blank when you want the clean theme path, and verify responsive output before replacing an existing production design.', $this->h4TrackedDownloadUrl('builder-suite'), 'Download Free Builder', $this->h4TrackedDownloadUrl('blank-theme'), 'Download Blank Theme');
    }

    private function h4ProductBuilderSuitePage(string $ticketUrl): string
    {
        $screensBase = $this->h4BuilderTutorialAssetBase();
        $setupWizardScreenshot = home_url('/wp-content/uploads/help4-tutorial-screens/2026-05/h4bs-setup-wizard-crop-20260515.png');
        $studioScreenshot = '/wp-content/plugins/help4-builder-suite/assets/demo/builder-studio-workspace-20260716.png';

        return $this->h4ProductHero(
            'Builder, fields, sliders, commerce, and security',
            'A blank-theme builder stack that feels complete without dragging the whole toolbox onto every page.',
            'Help4 Builder Suite gives users visual building, starter templates, global layout support, structured custom fields, slider features, Website Snapshot website screenshots, Help4 Commerce, payment routing, SEO helpers, performance tools, and security modules in one compartmentalized system.',
            $this->h4ProductActions($this->h4TrackedDownloadUrl('builder-suite'), 'Download Latest ZIP', $this->h4TrackedDownloadUrl('blank-theme'), 'Download Blank Theme'),
            $this->h4ProductCommand(
                [
                    ['Version', H4BS_VERSION . ' current build'],
                    ['Templates', '135 starter specs'],
                    ['Icons', '230 default SVG icons'],
                    ['Fields', 'Groups, repeaters, dynamic data'],
                    ['Modules', 'Builder, commerce, slider, security'],
                ],
                'What is included'
            )
        )
        . $this->h4ProductScreenGrid(
            [
                [$screensBase . 'h4bs-blank-settings-dashboard-20260723.png', 'Help4 Builder Suite settings dashboard screenshot', 'Settings dashboard', 'Enable the parts this site actually needs, then keep support, commerce, SEO, security, and builder settings in one place.'],
                [$setupWizardScreenshot, 'Help4 Builder setup wizard screenshot', 'Setup wizard', 'Walk a fresh install through the defaults that make the blank theme and plugin behave like one builder system.'],
                [$screensBase . 'h4bs-blank-builder-pages-20260723.png', 'Help4 Builder pages screen screenshot', 'Builder pages', 'See which pages are builder-enabled, open the editor, and keep launch pages organized.'],
                [$studioScreenshot, 'Help4 Builder Studio three-pane editing workspace', 'Builder Studio', 'Use the element library, live canvas, and Content, Design, and Advanced inspector without covering the page.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Why it exists',
            'Think blank theme plus the controls customers expect from a serious builder.',
            'The theme stays lean. The plugin brings page building, structured content fields, slider tools, commerce, icon defaults, operations modules, and starter structure without forcing every asset onto every page.',
            [
                ['Starter templates', 'Home, service, quote, review, case study, migration rescue, knowledge-base, lead-intake, product collection, support article, release notes, content brief, local SEO, and checkout recovery specs give users a sane starting point.'],
                ['Structured fields', 'Field groups, conditional logic, repeaters, groups, galleries, relationships, and dynamic rendering support richer sites than plain pages.'],
                ['Compartment modules', 'SEO, performance, forms, commerce, search, sliders, security, and support tooling stay modular so unused CSS and JS do not ride every page.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Plugin and theme downloads',
            'If the theme files are missing, download Help4 Blank separately.',
            'WordPress.org treats plugins and themes as separate packages, so Builder Suite ships as the plugin and Help4 Blank ships as the clean companion theme ZIP. Install Builder Suite first, then upload help4-blank.zip from the theme release page when you want the blank-theme workflow.',
            [
                ['Plugin ZIP', 'Use /help4-builder-suite/latest.zip for Builder Suite. This is the builder, templates, modules, SEO, commerce, security, and update layer.'],
                ['Theme ZIP', 'Use /help4-blank/help4-blank.zip for the Help4 Blank companion theme. This is the quiet WordPress shell the builder can control.'],
                ['Install path', 'Plugins > Add New > Upload Plugin for Builder Suite, then Appearance > Themes > Add New > Upload Theme for Help4 Blank.'],
            ]
        )
        . $this->h4ProductCardGrid(
            [
                ['Free install path', 'Start with the current public ZIP', 'Use the focused free-builder page to understand the package, theme boundary, responsive workflow, and launch responsibilities before installing.', home_url('/free-wordpress-builder/'), 'Free Builder Guide'],
                ['New install path', 'Start with the blank theme', 'Use Help4 Blank Theme as the quiet shell, then let Builder Suite handle pages, templates, styling controls, icons, and modules.', home_url('/help4-blank-theme/'), 'Theme Download and Setup'],
                ['Documentation path', 'Follow the screenshot guides', 'Use the tutorial hub and blank-install screenshots to understand each Builder Suite admin page before editing a live site.', home_url('/help4-builder-tutorials/'), 'Tutorial Hub'],
                ['Template path', 'Pick a starter spec', 'Choose the page job first: home, service, support, product, release notes, content brief, checkout recovery, or local SEO.', home_url('/help4-builder-template-library/'), 'Template Library'],
                ['Media path', 'Generate useful images', 'Use the AI image prompt guide to create hero images, service visuals, product scenes, tutorial screenshots, social previews, and portfolio proof without starting from a blank prompt.', home_url('/help4-builder-ai-image-prompts/'), 'AI Prompt Guide'],
                ['Website screenshot path', 'Show recent work with Website Snapshot', 'Turn public URLs into responsive website screenshots for portfolios, migration audits, support context, and launch proof.', home_url('/help4-builder-website-snapshot/'), 'Website Snapshot Tutorial'],
                ['Design handoff path', 'Hand us the design', 'Send screenshots, copy, rough ideas, or a finished design and Help4 can build the WordPress pages with the same stack.', home_url('/design-to-wordpress/'), 'Design to WordPress'],
                ['Commerce path', 'Products without a tiny-store ceiling', 'Use native catalog patterns, variations, subscriptions, checkout context, and payment routing for stores that need room to grow.', home_url('/help4-commerce-getting-started/'), 'Commerce Guide'],
                ['Operations path', 'SEO, speed, security', 'Keep metadata, schema, performance, image handling, forms, search, and hardening close to the builder workflow.', home_url('/help4-builder-seo-security-performance/'), 'Launch Hardening'],
                ['Release path', 'Beta and stable channels', 'The md site runs the beta track while the public site keeps the stable download and production WordPress channel.', home_url('/help4-builder-updates-wordpress-7/'), 'Update Notes'],
            ]
        )
        . $this->h4ProductCompare(
            ['User need', 'Builder Suite answer', 'Plain-English benefit'],
            [
                ['I need a page quickly', 'Starter template specs and reusable sections', 'Start from a real page type instead of a blank white screen.'],
                ['I need the site to match', 'Theme/template controls', 'Headers, footers, and reusable sections stay consistent.'],
                ['I need custom data', 'Structured field groups, repeaters, and dynamic output', 'Complex content can be edited cleanly without custom one-off admin screens.'],
                ['I need motion and sliders', 'Slider and Website Snapshot modules with transitions, website screenshot output, motion settings, and shortcode output', 'Hero sliders, promo sections, and website proof screenshots can be built without dragging extra assets onto every page.'],
                ['I need products', 'Help4 Commerce catalog, variations, subscriptions, and payment routing', 'Stores can scale past tiny product lists while checkout stays connected.'],
                ['I need SEO, speed, and security', 'Built-in metadata, performance, image, security, and form modules', 'The page can be built to rank, load, convert, and stay safer.'],
            ]
        )
        . $this->h4ProductFinalCta('Want Help4 to build with it?', 'Send the design, rough idea, or competitor example.', 'Help4 can use the builder stack to turn a sketch, screenshot, copy doc, or existing site mess into finished WordPress pages.', $ticketUrl, 'Request Page Build', home_url('/design-to-wordpress/'), 'Design to WordPress');
    }

    private function h4BuilderTutorialAssetBase(): string
    {
        if (defined('H4BS_PLUGIN_FILE')) {
            $base = (string) plugins_url('assets/tutorial-screens/blank-install', H4BS_PLUGIN_FILE);
            return trailingslashit(set_url_scheme($base, 'https'));
        }

        $base = (string) content_url('/plugins/help4-builder-suite/assets/tutorial-screens/blank-install');
        return trailingslashit(set_url_scheme($base, 'https'));
    }

    private function h4BuilderGuidedTutorialAssetBase(): string
    {
        if (defined('H4BS_PLUGIN_FILE')) {
            $base = (string) plugins_url('assets/tutorial-screens/guided/2026-08', H4BS_PLUGIN_FILE);
            return trailingslashit(set_url_scheme($base, 'https'));
        }

        $base = (string) content_url('/plugins/help4-builder-suite/assets/tutorial-screens/guided/2026-08');
        return trailingslashit(set_url_scheme($base, 'https'));
    }

    /**
     * @return array<string, array{0:string, 1:string, 2:string, 3:string}>
     */
    private function h4BuilderGuidedScreenCatalog(): array
    {
        $base = $this->h4BuilderGuidedTutorialAssetBase();

        return [
            'settings' => [$base . '14-page-settings.png', 'Help4 Builder Page Settings and recovery controls', 'Page Settings and recovery', 'Confirm page-level layout, history, preview, and recovery controls before a larger edit.'],
            'builder_pages' => [$base . '01-builder-pages.png', 'Current Help4 Builder Pages screen', 'Open the correct page', 'Find the intended page and open Studio without confusing it with a reusable template or similarly named draft.'],
            'studio' => [$base . '02-studio-overview.png', 'Current Help4 Builder Studio workspace', 'Current Studio workspace', 'See the element library, device controls, live page frame, inspector, performance guidance, and save state together.'],
            'templates' => [$base . '11-template-library.png', 'Current Help4 Builder template library', 'Templates in Studio', 'Browse reusable structures and choose an insertion or replacement path intentionally.'],
            'beginner_templates' => [$base . '64-beginner-template-library.png', 'Help4 Builder Studio showing the beginner template library and live preview', 'Beginner templates in Studio', 'Use search and category filters, compare Insert with Replace Page, and keep the live preview visible while choosing a starter.'],
            'quick_help' => [$base . '65-builder-quick-help.png', 'Help4 Builder Studio searchable Quick Help panel with task-based documentation links', 'Searchable Quick Help in Builder Studio', 'Search the task guides without leaving the page-editing context, then open the matching workflow in a separate tab.'],
            'edit_open' => [$base . '66-click-to-edit-open.png', 'Help4 Builder Studio opened on the confirmed page before an edit', 'Open the correct page in Studio', 'Confirm the page title and public route, then keep the center Live Preview and right inspector visible.'],
            'edit_image' => [$base . '67-click-to-edit-image.png', 'Help4 Builder Studio image quick editor after selecting the visible image', 'Click the visible image', 'Select the image itself, use Replace Image, add useful alternative text, and leave the neighboring text and button intact.'],
            'edit_text' => [$base . '68-click-to-edit-text.png', 'Help4 Builder Studio text quick editor showing the unsaved words in Live Preview', 'Edit the selected words', 'Type in Selected heading text and confirm the same unsaved words remain visible in Live Preview before publishing.'],
            'edit_verify' => [$base . '69-click-to-edit-public-verify.png', 'Published Help4 Builder tutorial fixture showing the saved text and unchanged neighboring content', 'Verify the public page', 'Open the real page after Save Element and Publish, then confirm the edited words and every untouched sibling remain present.'],
            'email_campaign' => [$base . '62-email-campaign-create.png', 'Help4 Email Marketing campaign reports and campaign draft controls', 'Create and test a campaign', 'Confirm sender readiness, choose the intended audience, prepare subject and preview text, and save a draft before scheduling.'],
            'email_automation' => [$base . '63-email-campaign-automation.png', 'Help4 Email Marketing reusable template and drip automation controls', 'Build a drip automation', 'Set ordered delays and messages for confirmed subscribers, then verify suppression and sender-compliance settings before activation.'],
            'theme_builder' => [$base . '15-theme-builder.png', 'Current Help4 Theme Builder assignments screen', 'Theme Builder assignments', 'Review reusable headers, footers, content shells, archive templates, 404 output, conditions, and priorities.'],
            'forms' => [$base . '16-forms.png', 'Current Help4 Forms administration screen', 'Forms and delivery', 'Create and verify forms, delivery, submissions, consent, and spam controls as one complete workflow.'],
            'seo' => [$base . '17-seo-control.png', 'Current Help4 SEO Control screen', 'SEO Control', 'Review metadata, social sharing, schema, readability, indexing, and site-level discovery signals.'],
            'commerce' => [$base . '18-commerce.png', 'Current Help4 Commerce dashboard', 'Commerce operations', 'Review catalog, orders, customers, subscriptions, payment routing, and store health from the native commerce hub.'],
            'products' => [$base . '21-product-quantity-rules.png', 'Help4 Commerce product quantity rules', 'Product quantity rules', 'Choose selectable quantity, fixed one-per-line packages, whole-order limits, minimum, maximum, and quantity steps.'],
        ];
    }

    /**
     * @return array<string, array{0:string, 1:string, 2:string, 3:string}>
     */
    private function h4BuilderScreenCatalog(): array
    {
        $base = $this->h4BuilderTutorialAssetBase();

        return [
            'settings' => [$base . 'h4bs-blank-settings-dashboard-20260723.png', 'Help4 Builder Suite launch center on a clean WordPress install', 'Settings and launch center', 'Choose a launch plan, confirm modules, download Help4 Blank, review readiness, and keep the site configuration in one place.'],
            'builder_pages' => [$base . 'h4bs-blank-builder-pages-20260723.png', 'Help4 Builder Pages screen on a clean WordPress install', 'Builder Pages', 'Find Builder-enabled pages, open Builder Studio, and keep drafts separate from live customer pages.'],
            'studio' => [$base . 'h4bs-blank-builder-studio-20260723.png', 'Help4 Builder Studio editing a Help4 WordPress page', 'Builder Studio', 'Use the live page frame, element library, template library, inspector, responsive controls, performance guidance, and save state in one workspace.'],
            'templates' => [$base . 'h4bs-blank-template-library-20260723.png', 'Help4 Builder template library inside Builder Studio', 'Template Library', 'Search page-purpose starters, insert a section, or deliberately replace a page instead of beginning from an empty screen.'],
            'theme_builder' => [$base . 'h4bs-blank-theme-builder-20260723.png', 'Help4 Theme Builder headers footers and page templates screen', 'Theme Builder', 'Create global headers, footers, 404s, page shells, canvas landing pages, popups, and display conditions.'],
            'fields' => [$base . 'h4bs-blank-fields-lab-20260723.png', 'Help4 Fields Lab structured fields screen', 'Fields Lab', 'Plan field groups, repeaters, images, relationships, and dynamic output for content that should not be edited as fragile page text.'],
            'commerce' => [$base . 'h4bs-blank-commerce-dashboard-20260723.png', 'Help4 Commerce dashboard on a clean WordPress install', 'Commerce dashboard', 'Review products, orders, customers, subscriptions, gateway routing, imports, and migration tools from one commerce hub.'],
            'products' => [$base . 'h4bs-blank-commerce-products-20260723.png', 'Help4 Commerce products screen on a clean WordPress install', 'Commerce products', 'Create products, variations, subscriptions, product images, quantity rules, catalog fields, and checkout context.'],
            'forms' => [$base . 'h4bs-blank-forms-20260723.png', 'Help4 Forms screen on a clean WordPress install', 'Forms', 'Create quote, contact, newsletter, booking, and support forms with clear routing and confirmation messages.'],
            'seo' => [$base . 'h4bs-blank-seo-control-20260723.png', 'Help4 SEO score playbook and content audit on a clean WordPress install', 'SEO score playbook', 'Understand search, readability, analytics-readiness, content-quality, and business-intent scores, then act on page-specific checks.'],
            'security' => [$base . 'h4bs-blank-security-20260723.png', 'Help4 Security control center on a clean WordPress install', 'Security', 'Review SSL, headers, login hardening, XML-RPC controls, checkout safety, and production hardening settings.'],
            'updates' => [$base . 'h4bs-blank-updates-20260723.png', 'Help4 live update channel on a clean WordPress install', 'Updates', 'Confirm the installed version, free update status, manifest URLs, beta or stable channel behavior, and package checks.'],
        ];
    }

    /**
     * @param array<int, string> $keys
     */
    private function h4BuilderScreenGrid(array $keys): string
    {
        $catalog = $this->h4BuilderScreenCatalog();
        $screens = [];
        foreach ($keys as $key) {
            if (isset($catalog[$key])) {
                $screens[] = $catalog[$key];
            }
        }

        return $screens ? $this->h4ProductScreenGrid($screens) : '';
    }

    /**
     * @param array<int, string> $keys
     */
    private function h4BuilderTutorialVisualWalkthrough(array $keys): string
    {
        $catalog = $this->h4BuilderScreenCatalog();
        $guidedCatalog = $this->h4BuilderGuidedScreenCatalog();
        $screens = [];
        foreach ($keys as $key) {
            if (isset($guidedCatalog[$key])) {
                $screens[] = $guidedCatalog[$key];
            }
            if (isset($catalog[$key])) {
                $screens[] = $catalog[$key];
            }
        }
        $screens = array_slice($screens, 0, 6);
        if (! $screens) {
            return '';
        }

        $html = '<section class="h4-tutorial-visual" aria-labelledby="h4-tutorial-visual-title">'
            . '<div class="h4-tutorial-section-heading"><p class="h4-product-eyebrow">Visual orientation</p>'
            . '<h2 id="h4-tutorial-visual-title">Match the screen before following the steps.</h2>'
            . '<p>Open each image at full size. The numbered notes explain what the screen controls and what to confirm before changing customer content.</p></div>'
            . '<div class="h4-tutorial-visual__grid">';

        foreach ($screens as $index => $screen) {
            $position = $index === 0 ? ' h4-tutorial-screen--primary' : '';
            $html .= '<article class="h4-tutorial-screen' . $position . '">'
                . '<div class="h4-tutorial-screen__chrome" aria-hidden="true"><span></span><span></span><span></span><strong>Help4 Builder</strong></div>'
                . '<a class="h4-tutorial-screen__media" href="' . esc_url((string) $screen[0]) . '" target="_blank" rel="noopener">'
                . '<img src="' . esc_url((string) $screen[0]) . '" alt="' . esc_attr((string) $screen[1]) . '" loading="' . ($index === 0 ? 'eager' : 'lazy') . '" decoding="async" />'
                . '<span class="h4-tutorial-screen__number" aria-hidden="true">' . esc_html((string) ($index + 1)) . '</span>'
                . '<span class="h4-tutorial-screen__zoom">Open full-size screen</span></a>'
                . '<div class="h4-tutorial-screen__copy"><p class="h4-product-eyebrow">Screen ' . esc_html((string) ($index + 1)) . '</p>'
                . '<h3>' . esc_html((string) $screen[2]) . '</h3><p>' . esc_html((string) $screen[3]) . '</p>'
                . '<p class="h4-tutorial-screen__check"><strong>Confirm:</strong> the page title, selected item, plugin version, and intended responsive view match the task.</p></div>'
                . '</article>';
        }

        return $html . '</div></section>';
    }

    /**
     * @param array<int, array{0:string, 1:string}> $steps
     */
    private function h4BuilderTutorialWalkthrough(array $steps): string
    {
        $html = '<section class="h4-tutorial-walkthrough" aria-labelledby="h4-tutorial-walkthrough-title">'
            . '<div class="h4-tutorial-section-heading"><p class="h4-product-eyebrow">Guided walkthrough</p>'
            . '<h2 id="h4-tutorial-walkthrough-title">Make one verified change at a time.</h2>'
            . '<p>Each step includes the action, why it belongs in this order, and the checkpoint to verify before moving forward.</p></div>'
            . '<ol class="h4-tutorial-steps">';

        $lastIndex = count($steps) - 1;
        foreach ($steps as $index => $step) {
            $title = sanitize_text_field((string) ($step[0] ?? ''));
            $description = sanitize_text_field((string) ($step[1] ?? ''));
            if ($index === 0) {
                $reason = 'Starting from a confirmed target prevents a correct edit from being applied to the wrong page, template, product, or responsive view.';
            } elseif ($index === $lastIndex) {
                $reason = 'The final verification separates an editor preview from a result that is actually saved, responsive, interactive, and ready for visitors.';
            } else {
                $reason = 'Completing and checking this step creates a known-good checkpoint before the next control changes the page state again.';
            }
            $doneWhen = sprintf(
                'The %s result is visible, remains after reselecting the item, and has not changed unrelated content or styling.',
                strtolower($title !== '' ? $title : 'expected')
            );

            $html .= '<li class="h4-tutorial-step"><span class="h4-tutorial-step__number" aria-hidden="true">'
                . esc_html(str_pad((string) ($index + 1), 2, '0', STR_PAD_LEFT))
                . '</span><div class="h4-tutorial-step__body"><h3>' . esc_html($title) . '</h3><p class="h4-tutorial-step__action">' . esc_html($description) . '</p>'
                . '<div class="h4-tutorial-step__proof"><p><strong>Why now</strong>' . esc_html($reason) . '</p>'
                . '<p><strong>Done when</strong>' . esc_html($doneWhen) . '</p></div></div></li>';
        }

        return $html . '</ol></section>';
    }

    private function h4BuilderTutorialMistakes(): string
    {
        return '<section class="h4-tutorial-mistakes" aria-labelledby="h4-tutorial-mistakes-title">'
            . '<div class="h4-tutorial-section-heading"><p class="h4-product-eyebrow">Avoid the expensive mistakes</p>'
            . '<h2 id="h4-tutorial-mistakes-title">Stop when the page stops behaving predictably.</h2>'
            . '<p>More edits do not repair a bad state. Preserve the evidence, return to a known revision, and reproduce the smallest failing action.</p></div>'
            . '<div class="h4-tutorial-mistakes__grid">'
            . '<article><span aria-hidden="true">01</span><h3>Changing several controls at once</h3><p>Change one content, design, or responsive value, then confirm it in the preview. A small edit is easier to understand and recover.</p></article>'
            . '<article><span aria-hidden="true">02</span><h3>Editing the wrong layer</h3><p>Use Navigator and read the inspector heading. Deleting a parent section can remove every child even when the selected text or image looked harmless.</p></article>'
            . '<article><span aria-hidden="true">03</span><h3>Checking only desktop</h3><p>Review tablet, 390px, and 360px before publish. Width, gap, padding, type, alignment, controls, and menus can inherit differently.</p></article>'
            . '<article><span aria-hidden="true">04</span><h3>Publishing before values persist</h3><p>Reselect the element and reopen the responsive view. If the value disappears or another tab has a newer revision, reconcile it before publishing.</p></article>'
            . '</div></section>';
    }

    /**
     * @return array<int, array{0:string, 1:string, 2:string, 3:string, 4:string}>
     */
    private function h4BuilderTutorialCards(): array
    {
        return [
                ['Start here', 'Install and setup', 'Download the ZIP, activate Builder Suite, understand the blank-theme path, and run the first clean check.', home_url('/help4-builder-guide/'), 'Install Guide'],
                ['First page', 'Build a page safely', 'Open Builder Pages, launch Studio, build structure first, check mobile, then publish or hand it to Help4.', home_url('/help4-builder-first-page/'), 'First Page'],
                ['Editor controls', 'Know which tab changes what', 'Use Content for information, Design for appearance and responsive values, and Advanced for identity, attributes, visibility, and motion.', home_url('/help4-builder-editor-controls/'), 'Controls Guide'],
                ['Find a setting', 'Stop hunting through inspector tabs', 'Search Content, Design, and Advanced together, jump to the matching control, and continue editing without losing draft changes.', home_url('/help4-builder-find-settings/'), 'Setting Finder'],
                ['Quick help', 'Find the right guide inside Studio', 'Open task-based help, follow the guide that matches the selected job, and return to the same page with the editing context intact.', home_url('/help4-builder-quick-help/'), 'Quick Help Guide'],
                ['Page structure', 'Sections, containers and columns', 'Build valid nested structure, choose grid or flex, control widths and gaps, and stack content intentionally on mobile.', home_url('/help4-builder-sections-containers-columns/'), 'Structure Guide'],
                ['Widget library', 'Choose the right element', 'Search, favorite, insert, configure, and test Builder widgets and addon modules without loading unrelated features.', home_url('/help4-builder-widget-library/'), 'Widget Guide'],
                ['WP-CLI runners', 'Automate guarded site work', 'Prepare compatible seed, migration, launch, repair, audit, and recovery runners without removing safety checks.', home_url('/help4-builder-wp-cli-runners/'), 'Runner Guide'],
                ['Sales homepage', 'Turn an offer into a complete page', 'Build open content bands for the offer, proof, services, pricing, process, FAQ, and final contact action.', home_url('/help4-builder-sales-homepage/'), 'Homepage Guide'],
                ['Pricing comparison', 'Compare up to five plans clearly', 'Use semantic feature rows, honest plan labels, readable calls to action, and mobile layouts that never squeeze five columns.', home_url('/help4-builder-pricing-comparison/'), 'Pricing Guide'],
                ['FAQ accordion', 'Answer objections accessibly', 'Build keyboard-ready disclosure controls and valid FAQPage schema without hidden or duplicate answers.', home_url('/help4-builder-faq-accordion-schema/'), 'FAQ Guide'],
                ['Live preview', 'See edits before publish', 'Use isolated draft preview, responsive views, interactive asset checks, and explicit publishing.', home_url('/help4-builder-live-preview-workflow/'), 'Preview Guide'],
                ['Save and publish', 'Know what becomes public', 'Understand element publishing, page drafts, revision conflicts, History, and the final public verification step.', home_url('/help4-builder-save-preview-publish/'), 'Publishing Guide'],
                ['Navigator', 'Understand page layers', 'Rename, reorder, duplicate, and remove nested sections, containers, columns, and widgets without damaging the tree.', home_url('/help4-builder-navigator-layers/'), 'Navigator Guide'],
                ['Recovery', 'Edit without losing work', 'Replace media safely, recognize stale drafts, and restore a known-good page snapshot from Page Settings History.', home_url('/help4-builder-safe-editing-recovery/'), 'Recovery Guide'],
                ['Images', 'Work with media safely', 'Replace, crop, size, optimize, describe, and verify images without resetting sibling content or styles.', home_url('/help4-builder-images-media/'), 'Media Guide'],
                ['Design controls', 'Buttons, type and spacing', 'Control tokens, typography, padding, gap, radius, states, and responsive values in Studio.', home_url('/help4-builder-buttons-typography-spacing/'), 'Design Guide'],
                ['Responsive', 'Control every viewport', 'Set spacing, widths, columns, alignment, and typography independently for desktop, tablet, and mobile.', home_url('/help4-builder-responsive-design/'), 'Responsive Guide'],
                ['Templates', 'Choose a starter', 'Pick a starter spec by page job: service, product, support, recent work, local SEO, launch, or checkout recovery.', home_url('/help4-builder-template-library/'), 'Template Guide'],
                ['Beginner templates', 'Insert a starter without losing the page', 'Search the library, choose Insert or Replace Page deliberately, personalize content, and verify responsive output before publishing.', home_url('/help4-builder-beginner-templates/'), 'Beginner Template Guide'],
                ['Site kits', 'Start a complete site safely', 'Import draft pages, templates, navigation, and optional style tokens without replacing the current site or publishing automatically.', home_url('/help4-builder-site-kits-starter-sites/'), 'Site Kit Guide'],
                ['Design system', 'Globals and theme packs', 'Control semantic colors, type, spacing, and style-only packs without replacing the current page layout.', home_url('/help4-builder-global-styles-theme-packs/'), 'Global Styles'],
                ['Theme layer', 'Headers and footers', 'Use Theme Builder for global headers, footers, 404s, page shells, canvas pages, popups, and conditions.', home_url('/help4-theme-builder-guide/'), 'Theme Guide'],
                ['Header/footer launch', 'Finish the shared site shell', 'Preserve the exact logo, build native navigation and mobile controls, add legal/support routes, and test template assignments.', home_url('/help4-builder-header-footer-launch/'), 'Site Shell Guide'],
                ['Template conditions', 'Control where templates appear', 'Use role, scope, content type, includes, excludes, and priority without duplicate or missing site shells.', home_url('/help4-theme-builder-template-conditions/'), 'Condition Guide'],
                ['Reusable sections', 'Update shared content safely', 'Choose between copied, reusable, and truly global sections for calls to action, proof, forms, and repeated content.', home_url('/help4-builder-reusable-global-sections/'), 'Reusable Guide'],
                ['Navigation', 'Menus that stay usable', 'Build hierarchy, hover dropdowns, keyboard paths, mobile menus, and global header assignments.', home_url('/help4-builder-menus-headers-footers/'), 'Navigation Guide'],
                ['Fields', 'Structured content', 'Use fields when content repeats: FAQs, service areas, specs, team members, galleries, relationships, and product data.', home_url('/help4-builder-fields/'), 'Fields Guide'],
                ['Dynamic data', 'Bind reusable templates', 'Connect approved post, taxonomy, author, site, product, variant, relationship, and repeater values to widgets.', home_url('/help4-builder-dynamic-data/'), 'Dynamic Data'],
                ['Commerce', 'Products and payments', 'Plan catalog data, variations, subscriptions, checkout context, and payment routing before launch.', home_url('/help4-commerce-getting-started/'), 'Commerce Guide'],
                ['Commerce operations', 'Products and customer fields', 'Configure variants, subscriptions, dynamic customer data, payment routes, and full order-lifecycle checks.', home_url('/help4-commerce-products-variations-customer-fields/'), 'Advanced Commerce'],
                ['Commerce launch', 'Test the entire order lifecycle', 'Verify catalog, variation, customer-field, tax, shipping, payment, webhook, subscription, refund, email, and mobile paths.', home_url('/help4-commerce-launch-testing/'), 'Launch Test Guide'],
                ['Stripe routing', 'Multiple Stripe accounts', 'Connect accounts, build product and geographic assignments, validate checkout, and compare Pro with Enterprise.', home_url('/stripe-router-tutorial/'), 'Stripe Tutorial'],
                ['CDN and WAF', 'Help4 Net edge delivery', 'Compare free plugin onboarding, the $8 Pro GeoDNS/CDN path, and the $20 managed proxy/WAF service.', home_url('/help4-net-wordpress-cdn-waf/'), 'CDN Guide'],
                ['Capture leads', 'Forms and sliders', 'Use forms and motion only where they support the page goal and do not load extra assets everywhere.', home_url('/help4-builder-sliders-forms/'), 'Forms Guide'],
                ['Forms', 'Test lead delivery', 'Configure accessible fields, consent, actions, validation, spam controls, delivery, and complete submission states.', home_url('/help4-builder-forms-lead-capture/'), 'Forms Tutorial'],
                ['Motion', 'Build accessible sliders', 'Set triggers, duration, delay, easing, controls, responsive behavior, and reduced-motion fallbacks.', home_url('/help4-builder-motion-sliders/'), 'Motion Guide'],
                ['Video', 'HLS, fallbacks and hero backgrounds', 'Configure HLS and file fallbacks, posters, failure images, overlays, responsive focal points, autoplay, controls, and reduced motion.', home_url('/help4-builder-video-hls-backgrounds/'), 'Video Guide'],
                ['Advanced controls', 'Use custom CSS safely', 'Scope page CSS with :builder, use classes and attributes intentionally, and verify media queries, pseudo-elements, keyframes, and recovery.', home_url('/help4-builder-custom-css-advanced-controls/'), 'Advanced Guide'],
                ['Migration', 'Import and export safely', 'Map layouts, tokens, templates, fields, media, links, and extension data with structural verification.', home_url('/help4-builder-import-export-migrations/'), 'Migration Guide'],
                ['Launch QA', 'SEO, speed, security', 'Check metadata, schema, readability, AdSense-style quality, Analytics intent, SSL, headers, images, and mobile.', home_url('/help4-builder-seo-security-performance/'), 'Launch Checklist'],
                ['Search visibility', 'Local and international SEO', 'Configure business entities, social previews, schema, languages, IndexNow, sitemaps, and indexing health.', home_url('/help4-seo-local-international-indexnow/'), 'Advanced SEO'],
                ['Networks', 'WordPress multisite', 'Provision sensible defaults while keeping each site isolated, editable, indexable, and operationally bounded.', home_url('/help4-builder-multisite-guide/'), 'Multisite Guide'],
                ['Troubleshooting', 'Migrate with evidence', 'Check preview parity, media URLs, active theme assets, caching, logs, and recovery history before changing code.', home_url('/help4-builder-migration-troubleshooting/'), 'Troubleshooting'],
                ['Proof', 'Website Snapshot', 'Turn public URLs into safe website screenshots for recent work, migrations, support notes, and launch recaps.', home_url('/help4-builder-website-snapshot/'), 'Snapshot Guide'],
                ['Release safety', 'Updates', 'Use stable live packages and md beta testing to keep Builder Suite ready for the next WordPress line.', home_url('/help4-builder-updates-wordpress-7/'), 'Update Guide'],
                ['Email marketing', 'Newsletters and drip campaigns', 'Configure subscribed audiences, sender gates, segments, templates, scheduled campaigns, automations, suppression, privacy tools, and engagement reports.', home_url('/help4-email-marketing-newsletters-drip-campaigns/'), 'Email Guide'],
                ['Email marketing', 'Create the first campaign', 'Complete sender gates, choose a confirmed audience, write and test the message, schedule carefully, and verify the resulting campaign report.', home_url('/help4-email-marketing-first-campaign/'), 'Campaign Guide'],
                ['Email marketing', 'Read reports and build automations', 'Interpret accepted delivery, human opens, clicks, failures, suppressions, and ordered drip steps without repeatedly contacting the wrong audience.', home_url('/help4-email-marketing-reports-automations/'), 'Reports and Drips'],
                ['Image workflow', 'Optimization and Image Studio', 'Prepare responsive images, preserve originals, create controlled derivatives, generate modern formats, write useful alternative text, and verify public delivery.', home_url('/help4-image-optimization-image-studio/'), 'Image Guide'],
                ['On-site search', 'Pages, posts and products', 'Choose search scope, exclusions, result behavior, fallback, keyboard states, and global placement for a reliable visitor search path.', home_url('/help4-site-search-setup/'), 'Search Guide'],
                ['URL recovery', 'Redirects and 404 monitoring', 'Map broken paths to the closest replacement, choose narrow match rules, avoid chains, and align internal links, canonicals, and sitemaps.', home_url('/help4-redirects-404-monitoring/'), 'Redirect Guide'],
                ['Diagnostics', 'Insights and Site Health', 'Review versions, module checks, REST routes, reserved shortcode ownership, page estimates, public behavior, and fresh logs in one evidence path.', home_url('/help4-insights-site-health-shortcodes/'), 'Insights Guide'],
                ['Security', 'WordPress hardening', 'Configure HTTPS, headers, login limits, proxy trust, origin controls, permissions, salts, commerce protection, recovery access, and regression tests.', home_url('/help4-security-hardening-guide/'), 'Security Guide'],
                ['Performance', 'Cache and asset optimization', 'Measure cold and warm responses, reduce unused module cost, optimize media, tune scripts, verify bypass rules, and protect interaction parity.', home_url('/help4-performance-cache-assets-guide/'), 'Performance Guide'],
                ['Accessibility', 'Keyboard, contrast and reduced motion', 'Audit structure, names, focus order, keyboard operation, color contrast, responsive reflow, media controls, and motion alternatives.', home_url('/help4-builder-accessibility-audit/'), 'Accessibility Guide'],
                ['Issue reporting', 'I.G.O.R. diagnostics', 'Turn a vague Builder problem into a privacy-safe report with one target, reproduction path, version inventory, fresh evidence, and expected result.', home_url('/help4-feedback-igor-diagnostics/'), 'Feedback Guide'],
                ['Product insights', 'Understand download and adoption stats', 'Separate anonymous download-start totals from administrator-consented installation domains, inspect the exact payload, and revoke sharing.', home_url('/help4-product-insights-download-stats/'), 'Insights Guide'],
                ['Learning sites', 'LMS courses and protected media', 'Build course, progress, certificate, dashboard, video, and protected resource surfaces across anonymous, member, editor, and completed states.', home_url('/help4-lms-courses-progress-certificates/'), 'LMS Guide'],
                ['Local proof', 'Google Business and reviews', 'Keep business identity, locations, service areas, maps, reviews, visible content, and structured data accurate and consistent.', home_url('/help4-google-business-reviews-guide/'), 'Local Business Guide'],
                ['Advanced navigation', 'Mega menus', 'Organize larger menus with native hierarchy, grouped destinations, reliable hover, keyboard focus, touch controls, and responsive global headers.', home_url('/help4-mega-menu-guide/'), 'Mega Menu Guide'],
                ['Release operations', 'Dependencies and update diagnostics', 'Verify stable or beta identity, immutable ZIPs, manifests, companion theme boundaries, runtime compatibility, rollback, and post-update QA.', home_url('/help4-dependency-update-diagnostics/'), 'Release Guide'],
        ];
    }

    private function h4BuilderTutorialNav(bool $completeCatalog = false): string
    {
        $cards = $this->h4BuilderTutorialCards();
        if (! $completeCatalog) {
            $compactHeadlines = [
                'Install and setup',
                'Build a page safely',
                'Know which tab changes what',
                'Edit without losing work',
                'Control every viewport',
                'Choose a starter',
            ];
            $cards = array_values(
                array_filter(
                    $cards,
                    static fn (array $card): bool => in_array((string) ($card[1] ?? ''), $compactHeadlines, true)
                )
            );
        }

        return '<section class="h4-tutorial-next" aria-labelledby="h4-tutorial-next-title">'
            . '<div class="h4-tutorial-section-heading"><p class="h4-product-eyebrow">' . ($completeCatalog ? 'Complete documentation library' : 'Continue learning') . '</p>'
            . '<h2 id="h4-tutorial-next-title">' . ($completeCatalog ? 'Choose the job you need to finish.' : 'Use the next guide that matches the work in front of you.') . '</h2>'
            . '<p>' . ($completeCatalog ? 'Search by task or narrow the library by category. Every guide remains present in the page source and includes real product screens, ordered steps, verification checks, recovery guidance, and a support handoff.' : 'The full tutorial hub remains available without repeating dozens of unrelated cards on this page.') . '</p></div>'
            . ($completeCatalog ? $this->h4BuilderTutorialSearchGrid($cards) : $this->h4ProductCardGrid($cards))
            . (! $completeCatalog ? '<p class="h4-tutorial-next__all"><a class="button" href="' . esc_url(home_url('/help4-builder-tutorials/')) . '">Browse every tutorial</a></p>' : '')
            . '</section>';
    }

    /**
     * @param array<int, array{0:string, 1:string, 2:string, 3:string, 4:string}> $cards
     */
    private function h4BuilderTutorialSearchGrid(array $cards): string
    {
        $categories = [
            'all' => 'All guides',
            'start' => 'Start and edit',
            'design' => 'Build and design',
            'templates' => 'Templates and navigation',
            'content' => 'Content and media',
            'marketing' => 'Forms and marketing',
            'commerce' => 'Commerce',
            'seo' => 'SEO and discovery',
            'performance' => 'Performance and security',
            'operations' => 'Operations',
            'learning' => 'Learning sites',
        ];

        $html = '<div class="h4-doc-search" data-h4-doc-search-root>'
            . '<div class="h4-doc-search__controls">'
            . '<div class="h4-doc-search__field"><label for="h4-doc-search-input">Search every Help4 guide</label><div><input id="h4-doc-search-input" type="search" inputmode="search" autocomplete="off" placeholder="Try mobile menu, checkout, HLS, redirects, or email" data-h4-doc-search-input><button type="button" data-h4-doc-search-clear aria-label="Clear tutorial search" title="Clear tutorial search" hidden><span aria-hidden="true">&times;</span></button></div></div>'
            . '<div class="h4-doc-search__filters" role="group" aria-label="Filter tutorials by category">';
        foreach ($categories as $key => $label) {
            $html .= '<button type="button" data-h4-doc-filter="' . esc_attr($key) . '" aria-pressed="' . ($key === 'all' ? 'true' : 'false') . '">' . esc_html($label) . '</button>';
        }
        $html .= '</div><p class="h4-doc-search__status" data-h4-doc-search-status aria-live="polite">' . esc_html(sprintf('%d guides available.', count($cards))) . '</p></div>'
            . '<div class="h4wp-card-grid h4-doc-search__results" data-h4-doc-search-results>';

        foreach ($cards as $card) {
            $url = (string) ($card[3] ?? '');
            $category = $this->h4BuilderTutorialCategory($url);
            $searchText = strtolower(wp_strip_all_tags(implode(' ', array_map('strval', $card))));
            $html .= '<article class="h4wp-card h4-doc-search__item" data-h4-doc-item data-h4-doc-category="' . esc_attr($category) . '" data-h4-doc-text="' . esc_attr($searchText) . '">'
                . '<p class="h4-product-eyebrow">' . esc_html((string) ($card[0] ?? 'Guide')) . '</p>'
                . '<h3>' . esc_html((string) ($card[1] ?? 'Help4 guide')) . '</h3>'
                . '<p>' . esc_html((string) ($card[2] ?? '')) . '</p>'
                . '<p><a class="button button-primary" href="' . esc_url($url) . '">' . esc_html((string) ($card[4] ?? 'Open Guide')) . '</a></p>'
                . '</article>';
        }

        return $html . '</div><div class="h4-doc-search__empty" data-h4-doc-search-empty hidden><h3>No guide matched that search.</h3><p>Try a shorter task such as menu, image, product, email, SEO, cache, or update. You can also clear the filter to browse every guide.</p></div></div>';
    }

    private function h4BuilderTutorialCategory(string $url): string
    {
        $path = strtolower((string) wp_parse_url($url, PHP_URL_PATH));
        $rules = [
            'learning' => ['lms-courses'],
            'commerce' => ['commerce-', 'stripe-router', 'payment-router'],
            'marketing' => ['email-marketing', 'forms-lead', 'sliders-forms', 'sales-homepage', 'pricing-comparison', 'faq-accordion', 'motion-sliders'],
            'performance' => ['security-hardening', 'performance-cache', 'image-optimization', 'accessibility-audit'],
            'seo' => ['seo-', 'google-business', 'site-search', 'redirects-404', 'website-snapshot'],
            'templates' => ['template', 'site-kits', 'global-styles', 'header-footer', 'menus-headers', 'mega-menu', 'reusable-global', 'theme-builder'],
            'content' => ['widget-library', 'images-media', 'builder-fields', 'dynamic-data', 'builder-icons', 'custom-css', 'video-hls'],
            'operations' => ['wp-cli', 'module-controls', 'multisite', 'migration-troubleshooting', 'import-export', 'insights-site-health', 'feedback-igor', 'dependency-update', 'updates-wordpress'],
            'design' => ['sections-containers', 'responsive-design', 'buttons-typography'],
            'start' => ['builder-guide', 'first-page', 'editor-controls', 'builder-quick-help', 'navigator-layers', 'live-preview', 'save-preview', 'safe-editing'],
        ];

        foreach ($rules as $category => $needles) {
            foreach ($needles as $needle) {
                if (str_contains($path, $needle)) {
                    return $category;
                }
            }
        }

        return 'operations';
    }

    /**
     * @param array<int, array{0:string, 1:string}> $steps
     * @param array<int, array{0:string, 1:string}> $checks
     * @param array<int, string> $screenKeys
     * @param array<int, array{0:string, 1:string}> $stats
     */
    private function h4BuilderTutorialPage(string $eyebrow, string $headline, string $lede, array $stats, array $screenKeys, string $sectionEyebrow, string $sectionHeadline, string $sectionLede, array $steps, array $checks, string $ticketUrl): string
    {
        $videoNumbers = $this->h4BuilderTutorialVideoNumbersForContext($eyebrow . ' ' . $headline . ' ' . $sectionHeadline);
        if ($videoNumbers === []) {
            $videoNumbers = [1];
        }

        return '<div class="h4-tutorial">'
        . $this->h4ProductHero(
            $eyebrow,
            $headline,
            $lede,
            $this->h4ProductActions($this->h4TrackedDownloadUrl('builder-suite'), 'Download Latest ZIP', home_url('/help4-builder-tutorials/'), 'Tutorial Hub'),
            $this->h4ProductCommand($stats, 'Guide map')
        )
        . $this->h4ProductFeatureBand(
            'Before the first click',
            'Confirm what you are editing and where each kind of change belongs.',
            'Read the page or template title first, select the exact element in the canvas or Navigator, then use the inspector tab that matches the job. This prevents a content change from becoming an accidental layout change.',
            [
                ['Content', 'Change words, links, images, icons, data sources, shortcodes, and element-specific information.'],
                ['Design', 'Change colors, typography, spacing, borders, radius, alignment, states, and desktop, tablet, or mobile values.'],
                ['Advanced', 'Change labels, anchors, classes, attributes, visibility rules, motion, and other expert controls.'],
                ['Page Settings', 'Use page-wide history, globals, publishing, template assignment, and recovery controls instead of editing one element.'],
            ]
        )
        . $this->h4BuilderTutorialVisualWalkthrough($screenKeys)
        . $this->h4BuilderTutorialVideoSection($videoNumbers)
        . $this->h4ProductFeatureBand($sectionEyebrow, $sectionHeadline, $sectionLede, $checks)
        . $this->h4BuilderTutorialWalkthrough($steps)
        . $this->h4ProductFeatureBand(
            'How to know it worked',
            'Verify the edit in Studio and on the real page.',
            'A successful edit stays visible when the element is reselected, matches the intended responsive view, survives publish, and appears on the public URL without clipping or lost styling.',
            [
                ['Studio preview', 'Reselect the element and confirm the saved value and visual result are still present.'],
                ['Responsive preview', 'Check desktop, tablet, 390px, and 360px widths for overflow, squeezed controls, and inherited values.'],
                ['Public page', 'Open the public route in a new tab after publishing and confirm content, interactions, assets, and spacing.'],
                ['Recovery', 'If the result is wrong, stop editing and use History or a known-good revision instead of rebuilding the page.'],
            ]
        )
        . $this->h4BuilderTutorialMistakes()
        . $this->h4BuilderTutorialNav()
        . $this->h4ProductFinalCta('Need help with this step?', 'Send Help4 the page, screenshot, or site goal.', 'Include the URL, what you are trying to build, what looks wrong, and whether this is a draft, staging site, or live customer page.', $ticketUrl, 'Open Help4 Ticket', home_url('/help4-builder-screenshots/'), 'View Screenshots')
        . '</div>';
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function h4BuilderOperationsGuideCatalog(): array
    {
        return [
            'help4-builder-find-settings' => [
                'title' => 'Find Any Setting in Help4 Builder Studio',
                'eyebrow' => 'Inspector navigation',
                'headline' => 'Jump directly to typography, spacing, media, responsive, visibility, and advanced controls without guessing which tab owns them.',
                'lede' => 'Select the element you want to change, use the inspector-wide setting finder, and open the matching control in Content, Design, or Advanced while preserving the current draft.',
                'seo_title' => 'Find Any Help4 Builder Setting | Studio Inspector Guide',
                'seo_description' => 'Use Help4 Builder Studio setting search to find content, design, typography, spacing, media, responsive, visibility, and advanced controls across every inspector tab.',
                'focus_keyword' => 'find Help4 Builder settings',
                'stats' => [['Scope', 'Every inspector tab'], ['Keyboard', 'Slash to focus'], ['Results', 'Label and group'], ['Safety', 'Draft stays intact']],
                'screens' => ['studio', 'quick_help'],
                'section_eyebrow' => 'One inspector search',
                'section_headline' => 'Search by the result you want, then edit the real control in place.',
                'section_lede' => 'The finder indexes labels, setting keys, tab names, and control groups after the selected element loads. Choosing a result opens its tab and group, scrolls the field into view, and moves keyboard focus to the control.',
                'checks' => [
                    ['Correct element selected', 'Confirm the canvas outline and inspector title identify the exact text, image, button, container, slider, or widget you intend to change.'],
                    ['Useful search phrase', 'Search for a result such as padding, font size, image, URL, columns, visibility, animation, or background instead of the page title.'],
                    ['Responsive context', 'Check the current desktop, tablet, or mobile design context before changing a value that can inherit or differ by device.'],
                    ['Visible saved result', 'Save the element, reload Studio, and verify the same public or preview output before publishing the page.'],
                ],
                'steps' => [
                    ['Select the element', 'Click the visible text, image, button, or container on the canvas, or choose it in Navigator when elements overlap.'],
                    ['Focus Find a setting', 'Use the search field above Content, Design, and Advanced. With the inspector open and focus outside an input, press slash to reach it by keyboard.'],
                    ['Describe the control', 'Type a setting name such as typography, background, padding, URL, columns, hide, motion, or alt text.'],
                    ['Choose a result', 'Read the tab and group shown beside each result, then click it or use Arrow keys and Enter.'],
                    ['Edit in context', 'The matching tab and accordion open automatically. Change the real field while watching the isolated live preview.'],
                    ['Check each viewport', 'Switch desktop, tablet, and mobile when the setting supports responsive values and confirm no clipping, overlap, or accidental inheritance.'],
                    ['Save and reopen', 'Save the element and page, reload Studio, then confirm the value and preview survived normalization before publishing.'],
                ],
                'faq' => [
                    ['question' => 'Does search change or hide my settings?', 'answer' => 'No. It indexes the controls already loaded for the selected element and only navigates to the field you choose.'],
                    ['question' => 'Why is a setting missing from results?', 'answer' => 'Confirm the correct element is selected. Different widgets expose different controls, and some global page settings live under Page Settings rather than the element inspector.'],
                    ['question' => 'Can I use the setting finder without a mouse?', 'answer' => 'Yes. Press slash while the inspector is open, type a query, use Arrow keys to choose a result, press Enter, and continue in the focused field.'],
                ],
            ],
            'help4-product-insights-download-stats' => [
                'title' => 'Help4 Product Insights, Download Starts and Adoption Stats',
                'eyebrow' => 'Privacy-first product measurement',
                'headline' => 'Know what a download number proves, what an opted-in domain record means, and how administrators control sharing.',
                'lede' => 'Help4 counts first-party download-route starts without visitor IP records and keeps installed-domain reporting off until an administrator explicitly consents to the exact weekly payload.',
                'seo_title' => 'Help4 Product Insights Guide | Downloads and Opt-In Adoption',
                'seo_description' => 'Understand Help4 download-start totals, optional installation-domain adoption reporting, exact payload fields, retention, privacy controls, and remote deletion.',
                'focus_keyword' => 'WordPress plugin download tracking',
                'stats' => [['Downloads', 'Start redirects'], ['Domains', 'Administrator opt-in'], ['Schedule', 'Weekly status'], ['Control', 'Stop and delete']],
                'screens' => ['settings', 'quick_help'],
                'section_eyebrow' => 'Two different measurements',
                'section_headline' => 'Do not confuse a clicked ZIP route with an active installation.',
                'section_lede' => 'Download-start aggregates help measure which product, source, campaign, and referrer host initiated a first-party redirect. Installation records exist only after consent and report public site/version facts, never customer content or visitor behavior.',
                'checks' => [
                    ['Download definition', 'Treat the count as a non-bot GET request that started the redirect to a ZIP, not proof that the file completed, activated, or remained installed.'],
                    ['Consent state', 'Installed-domain reporting is off by default and requires a managing administrator to review the payload and enable it.'],
                    ['Payload boundary', 'The weekly status includes site address, version/build, WordPress/PHP, theme, enabled module names, channel, environment, multisite state, and an installation identity.'],
                    ['Deletion path', 'Stopping sharing disables the local heartbeat immediately and requests deletion of the matching remote installation record.'],
                ],
                'steps' => [
                    ['Open Product Insights', 'In Help4 Builder Suite, open Product Insights and confirm sharing is Off before making a consent decision.'],
                    ['Review every field', 'Read the exact payload preview and verify that it contains no page content, users, customers, forms, emails, cookies, secrets, or raw logs.'],
                    ['Choose deliberately', 'Leave sharing off or check the consent box and send the first status. There is no dashboard takeover or implied consent.'],
                    ['Read the result', 'Check the last attempt, last successful send, response status, and release environment instead of assuming delivery.'],
                    ['Interpret Help4 reports', 'Use active consented domains for adoption and download-start aggregates for campaign interest; never combine them into a fabricated install count.'],
                    ['Stop and delete', 'Use Stop sharing and delete record. Local sharing stops immediately; if the collector is unavailable, remote deletion stays queued for retry.'],
                    ['Update the privacy notice', 'Use the WordPress privacy-policy suggestion when the site enables sharing and keep the public notice aligned with the actual choice.'],
                ],
                'faq' => [
                    ['question' => 'Does Help4 track every site automatically?', 'answer' => 'No. Installed-domain reporting is disabled by default and starts only after explicit administrator consent.'],
                    ['question' => 'Are download starts the same as installations?', 'answer' => 'No. A start means a qualifying request reached the tracked first-party download redirect; it cannot prove download completion, activation, or continued use.'],
                    ['question' => 'What happens when sharing is disabled?', 'answer' => 'The weekly heartbeat stops locally and Help4 requests deletion of the installation record identified by that site token, retrying if the collector is temporarily unavailable.'],
                ],
            ],
            'help4-builder-accessibility-audit' => [
                'title' => 'Help4 Builder Accessibility Audit',
                'eyebrow' => 'Accessible page operations',
                'headline' => 'Verify structure, keyboard access, contrast, responsive reflow, media, and motion before visitors find the barrier.',
                'lede' => 'Use Builder semantics, native controls, responsive previews, public keyboard testing, contrast checks, meaningful alternatives, and reduced-motion behavior as one repeatable release gate.',
                'seo_title' => 'Help4 Builder Accessibility Guide | Keyboard, Contrast and Motion',
                'seo_description' => 'Audit Help4 Builder pages for headings, landmarks, accessible names, keyboard operation, focus, contrast, responsive reflow, forms, media, and reduced motion.',
                'focus_keyword' => 'WordPress accessibility audit',
                'stats' => [['Structure', 'Headings and landmarks'], ['Input', 'Keyboard and touch'], ['Visual', 'Contrast and reflow'], ['Motion', 'Reduced-motion path']],
                'screens' => ['studio', 'settings'],
                'section_eyebrow' => 'Accessibility release gate',
                'section_headline' => 'Test the complete task, not only an automated score.',
                'section_lede' => 'Automated checks can find useful patterns, but a real audit also follows the page in reading order, completes interactions by keyboard, reviews responsive states, and confirms that every message survives without color or motion.',
                'checks' => [
                    ['Meaningful structure', 'Use one descriptive page heading, a logical heading sequence, landmarks, lists, labels, and controls that match their real purpose.'],
                    ['Complete keyboard path', 'Reach and operate navigation, disclosures, forms, dialogs, media, sliders, checkout, and other custom controls with visible focus and no trap.'],
                    ['Readable visual states', 'Check text, controls, focus, errors, disabled states, and content on images for sufficient contrast at every responsive state.'],
                    ['Equivalent calm experience', 'Honor reduced-motion preferences without removing information, actions, progress, or a usable media fallback.'],
                ],
                'steps' => [
                    ['Review the document outline', 'Confirm the title, one H1, section heading order, landmarks, real lists, link purpose, button names, form labels, and image alternatives.'],
                    ['Navigate without a pointer', 'Use Tab and Shift Tab through the public page, then operate menus, accordions, forms, dialogs, sliders, and media with their expected keys.'],
                    ['Inspect focus and status messages', 'Verify focus is always visible, follows a useful order, returns after overlays close, and reaches validation, success, loading, and error messages.'],
                    ['Check contrast and noncolor meaning', 'Measure text and control states on their real backgrounds and confirm errors, selection, charts, and instructions do not depend on color alone.'],
                    ['Test zoom and responsive reflow', 'Review desktop, tablet, 390px, 360px, and browser zoom for clipping, lost controls, unreadable content, and horizontal document scrolling.'],
                    ['Test normal and reduced motion', 'Verify timing, autoplay, parallax, sliders, ambient animation, and background media in both preference states, including pause or manual controls where needed.'],
                    ['Repeat on the public page', 'Publish only after Studio checks pass, then repeat the critical keyboard, screen-size, media, form, and motion paths on the real anonymous URL.'],
                ],
                'faq' => [
                    ['question' => 'Does a perfect automated score prove the page is accessible?', 'answer' => 'No. Automated tools find only part of the problem; keyboard operation, reading order, clear language, meaningful alternatives, and complete user tasks still require human review.'],
                    ['question' => 'Should focus outlines be removed to match the design?', 'answer' => 'No. Focus must remain clearly visible; style it to fit the design while preserving a strong, consistent indicator.'],
                    ['question' => 'Does reduced motion mean every transition must disappear?', 'answer' => 'It means unnecessary or potentially harmful motion should be removed or simplified while every message, control, and task remains available.'],
                ],
            ],
            'help4-email-marketing-newsletters-drip-campaigns' => [
                'title' => 'Help4 Email Marketing, Newsletters and Drip Campaigns',
                'eyebrow' => 'Email marketing operations',
                'headline' => 'Build subscribed audiences, useful campaigns, and measured follow-up without losing control of delivery.',
                'lede' => 'Configure sender identity, signup forms, segments, reusable templates, scheduled campaigns, automations, suppression, privacy tools, and engagement reports from the self-hosted Help4 email module.',
                'seo_title' => 'Help4 Email Marketing Guide | Newsletters and Drip Campaigns',
                'seo_description' => 'Configure Help4 email signup forms, consent, segments, templates, newsletters, drip campaigns, suppression, delivery gates, open estimates, and click reporting.',
                'focus_keyword' => 'WordPress email marketing guide',
                'stats' => [['Audience', 'Subscribed contacts'], ['Delivery', 'Queue with daily cap'], ['Reports', 'Clicks, opens, failures'], ['Privacy', 'Export and erasure']],
                'screens' => ['settings', 'forms'],
                'section_eyebrow' => 'Campaign foundation',
                'section_headline' => 'Treat deliverability, consent, and suppression as product requirements.',
                'section_lede' => 'A polished email is not ready until the sender, audience source, unsubscribe path, postal address, privacy URL, daily cap, and test delivery are verified.',
                'checks' => [
                    ['Sender identity', 'Use a monitored From address and Reply-To address on a domain with the required mail authentication records.'],
                    ['Audience state', 'Send only to the intended subscribed segment and keep unsubscribed, bounced, complained, or suppressed contacts out of every queue.'],
                    ['Message quality', 'Use a descriptive subject, honest preview text, readable mobile layout, useful links, and a plain destination for every action.'],
                    ['Measurement', 'Treat accepted mail as transport acceptance, open rates as estimates, and unique clicks as the stronger engagement signal.'],
                ],
                'steps' => [
                    ['Enable Email Marketing', 'Open Help4 Builder settings, enable Email Marketing, then open Help4 Builder > Email Marketing.'],
                    ['Verify sender settings', 'Set From name, From email, Reply-To, postal address, privacy URL, daily cap, and both delivery verification gates.'],
                    ['Create the signup path', 'Add the h4_email_signup form where people expect it, name the source clearly, and complete a real confirmation and unsubscribe test.'],
                    ['Build segments and templates', 'Create focused segments from tags or source data and save reusable branded templates before drafting campaigns.'],
                    ['Draft one campaign', 'Write the subject, preview text, accessible HTML content, destination links, and optional UTC schedule without queueing it yet.'],
                    ['Test delivery and suppression', 'Send to a controlled test audience, inspect desktop and mobile mail, then confirm unsubscribe and suppression prevent another send.'],
                    ['Queue and review reports', 'Queue only after the gates pass, then review accepted, failed, unique-click, open-estimate, unsubscribe, and automated-activity values.'],
                ],
                'faq' => [
                    ['question' => 'Does accepted mean the email reached the inbox?', 'answer' => 'No. Accepted means the configured WordPress mail transport accepted the message; inbox placement still depends on the receiving system and sender reputation.'],
                    ['question' => 'Why are open rates estimates?', 'answer' => 'Image blocking, privacy relays, and automated scanners can hide or inflate opens, so unique human clicks are usually the stronger engagement signal.'],
                    ['question' => 'Can an unsubscribed contact enter a drip campaign again?', 'answer' => 'The suppression state should keep unsubscribed contacts out of later campaign and automation queues unless they complete a new lawful subscription action.'],
                ],
            ],
            'help4-image-optimization-image-studio' => [
                'title' => 'Help4 Image Optimization and Image Studio',
                'eyebrow' => 'Image workflow',
                'headline' => 'Prepare sharp, responsive images without turning every upload into a performance problem.',
                'lede' => 'Use Media Library metadata, Help4 Image Studio, optional enhancement, generated WebP files, responsive image output, accessible alternative text, and public page checks as one repeatable workflow.',
                'seo_title' => 'Help4 Image Optimization and Image Studio Guide',
                'seo_description' => 'Use Help4 Image Studio, WebP generation, responsive image sizes, crop and overlay controls, alternative text, cache checks, and safe media replacement in WordPress.',
                'focus_keyword' => 'WordPress image optimization guide',
                'stats' => [['Input', 'WordPress attachments'], ['Editor', 'Help4 Image Studio'], ['Output', 'Responsive formats'], ['Check', 'Quality and page weight']],
                'screens' => ['settings', 'studio'],
                'section_eyebrow' => 'Image decisions',
                'section_headline' => 'Optimize for the rendered slot, not the largest file you can upload.',
                'section_lede' => 'Preserve the original, edit a controlled derivative, describe meaningful images, and verify the browser receives an appropriate source at each viewport.',
                'checks' => [
                    ['Source quality', 'Start from a clean original with enough resolution for the largest real display slot.'],
                    ['Crop and focus', 'Keep the subject visible at desktop, tablet, and mobile aspect ratios before publishing.'],
                    ['Meaningful text alternative', 'Describe the purpose of informative images and leave decorative images empty instead of stuffing keywords.'],
                    ['Delivery proof', 'Confirm dimensions, format, file size, lazy-loading behavior, and cache response on the public URL.'],
                ],
                'steps' => [
                    ['Inventory the rendered slot', 'Measure where the image appears and record the largest desktop width plus the mobile crop before editing the asset.'],
                    ['Open the attachment', 'Use Media Library to confirm the file type, pixel dimensions, title, caption, description, and alternative text.'],
                    ['Edit in Image Studio', 'Crop, rotate, draw, or apply an overlay only to a deliberate derivative and keep the original available for recovery.'],
                    ['Choose optimization settings', 'Enable optimization and WebP generation only after confirming the server supports the required image pipeline.'],
                    ['Replace through the widget', 'Select the Image element in Builder, choose the intended attachment, and confirm the surrounding layout remains unchanged.'],
                    ['Check responsive output', 'Inspect desktop, tablet, 390px, and 360px for subject cropping, blur, stretching, oversized downloads, and layout shifts.'],
                    ['Verify the public response', 'Publish, clear the relevant caches, then inspect the public image URL, responsive source selection, and broken-image state.'],
                ],
                'faq' => [
                    ['question' => 'Should every uploaded image be enhanced?', 'answer' => 'No. Enhancement is optional and should be used only when it improves a controlled derivative without changing brand assets or documented originals.'],
                    ['question' => 'Does WebP replace the original file?', 'answer' => 'The safe workflow preserves the original attachment and creates optimized delivery formats or derivatives that can be regenerated.'],
                    ['question' => 'What should decorative image alternative text contain?', 'answer' => 'Decorative images should normally use empty alternative text so assistive technology can skip them.'],
                ],
            ],
            'help4-site-search-setup' => [
                'title' => 'Help4 Site Search Setup and Testing',
                'eyebrow' => 'On-site search',
                'headline' => 'Give visitors one reliable search path across pages, posts, and native products.',
                'lede' => 'Configure the Help4 search element or shortcode, choose its scope, exclude inappropriate records, test REST results, and verify keyboard, empty, error, and mobile states before placing search in a global header.',
                'seo_title' => 'Help4 Site Search Guide | Pages, Posts and Products',
                'seo_description' => 'Configure Help4 site search for WordPress pages, posts, and native products with scope controls, exclusions, REST checks, accessible results, and mobile testing.',
                'focus_keyword' => 'WordPress site search setup',
                'stats' => [['Scopes', 'Pages, posts, products'], ['Endpoint', 'Help4 REST search'], ['Fallback', 'Optional web search'], ['QA', 'Keyboard and mobile']],
                'screens' => ['settings', 'studio'],
                'section_eyebrow' => 'Search contract',
                'section_headline' => 'Decide what belongs in search before styling the box.',
                'section_lede' => 'Search quality depends on published titles, excerpts, product names, and a scope that matches visitor intent; the visual field cannot repair weak source data.',
                'checks' => [
                    ['Scope', 'Choose all, pages, posts, products, or an intentional fallback and document excluded IDs.'],
                    ['Result clarity', 'Every result needs a recognizable title, useful excerpt or product detail, and a valid destination.'],
                    ['Interaction', 'The form, scope selector, submit control, results, and links must remain usable by keyboard and touch.'],
                    ['Failure behavior', 'Empty queries, zero results, endpoint errors, and slow responses need a clear state without a blank panel.'],
                ],
                'steps' => [
                    ['Enable Search', 'Enable the Search module and confirm the Help4 REST search route is registered before placing a search widget.'],
                    ['Choose the content scope', 'Decide whether this surface searches all records, only products, only pages, only posts, or an explicit web fallback.'],
                    ['Add the search surface', 'Insert the Search widget or h4_search shortcode and set its placeholder, exclusions, scope control, and fallback behavior.'],
                    ['Improve source records', 'Give searchable pages, posts, and products accurate titles, excerpts, names, SKUs, and published status.'],
                    ['Test representative queries', 'Search exact names, partial phrases, product SKUs, a misspelling, a zero-result phrase, and a deliberately excluded record.'],
                    ['Test interaction states', 'Use keyboard-only navigation and check loading, results, zero results, error, focus, and back-button behavior.'],
                    ['Verify global placement', 'If search sits in a header or menu, test every assigned route at desktop, tablet, 390px, and 360px.'],
                ],
                'faq' => [
                    ['question' => 'What content can Help4 search?', 'answer' => 'The native search route can return published WordPress pages, posts, and Help4 Commerce products according to the selected scope.'],
                    ['question' => 'Can specific records be excluded?', 'answer' => 'Yes. The search configuration supports separate exclusion lists for posts, pages, and products.'],
                    ['question' => 'Should every search box use all content types?', 'answer' => 'No. A product catalog, documentation hub, and global website header can have different visitor intent and should use the narrowest useful scope.'],
                ],
            ],
            'help4-redirects-404-monitoring' => [
                'title' => 'Help4 Redirects and 404 Monitoring',
                'eyebrow' => 'URL recovery',
                'headline' => 'Repair broken paths without creating redirect chains, loops, or misleading destinations.',
                'lede' => 'Use the Redirect Manager and 404 log to map old paths to the closest valid replacement, choose the correct status code, verify canonical and sitemap state, and monitor real hits after launch.',
                'seo_title' => 'Help4 Redirects and 404 Monitoring Guide',
                'seo_description' => 'Create and test exact, prefix, wildcard, and regex redirects; review WordPress 404 logs; avoid chains and loops; and preserve canonical and sitemap integrity.',
                'focus_keyword' => 'WordPress redirects and 404 monitoring',
                'stats' => [['Rules', 'Exact, prefix, wildcard, regex'], ['Codes', '301, 302, 307, 308'], ['Evidence', '404 hit log'], ['Goal', 'One-hop recovery']],
                'screens' => ['seo', 'security'],
                'section_eyebrow' => 'Redirect discipline',
                'section_headline' => 'Map intent first, then create the smallest rule that solves it.',
                'section_lede' => 'A redirect is correct only when the old URL, destination, status, canonical, sitemap, and internal links agree.',
                'checks' => [
                    ['Closest replacement', 'Send an old URL to the page that best satisfies the same visitor intent, not automatically to the home page.'],
                    ['Narrow match', 'Use exact paths by default and reserve prefix, wildcard, or regex rules for reviewed patterns.'],
                    ['One hop', 'The source should reach its final HTTPS canonical in one redirect without loops or host drift.'],
                    ['Discovery cleanup', 'Update internal links and keep retired URLs out of canonical tags and XML sitemaps.'],
                ],
                'steps' => [
                    ['Collect the failing URL', 'Copy the full public URL, response status, referrer, and intended replacement before creating a rule.'],
                    ['Review the 404 log', 'Confirm the path is a real visitor or crawler request and not scanner noise or a mistyped admin route.'],
                    ['Choose the match type', 'Use exact for one path; use broader patterns only after listing every URL the rule could capture.'],
                    ['Choose the response code', 'Use a permanent code for a completed move and a temporary code only when the old URL may return.'],
                    ['Save and test anonymously', 'Request the old URL without an admin session and follow the response chain to its final destination.'],
                    ['Repair discovery signals', 'Update internal links, canonical tags, menus, feeds, and sitemaps so crawlers stop learning the retired path.'],
                    ['Monitor hits and regressions', 'Watch rule hits and new 404s after launch, then remove accidental chains instead of layering more redirects.'],
                ],
                'faq' => [
                    ['question' => 'Should every 404 redirect to the home page?', 'answer' => 'No. Redirect only when a close replacement exists; otherwise a useful 404 response is more accurate than a misleading home-page redirect.'],
                    ['question' => 'When should an exact redirect be used?', 'answer' => 'Use an exact redirect for a known old path when only that path should move to the selected destination.'],
                    ['question' => 'Why should internal links be updated after adding a redirect?', 'answer' => 'Direct internal links reduce unnecessary requests and keep navigation, canonical signals, and crawl paths aligned with the final URL.'],
                ],
            ],
            'help4-insights-site-health-shortcodes' => [
                'title' => 'Help4 Insights, Site Health and Shortcode Diagnostics',
                'eyebrow' => 'Operational diagnostics',
                'headline' => 'Read site evidence before a warning becomes a production failure.',
                'lede' => 'Use Help4 Insights to review module readiness, reserved shortcode ownership, page weight estimates, route availability, and health checks before and after plugin, theme, or WordPress updates.',
                'seo_title' => 'Help4 Insights and Site Health Diagnostics Guide',
                'seo_description' => 'Use Help4 Insights, reserved shortcode checks, REST route checks, page performance estimates, and WordPress Site Health evidence to diagnose update and rendering problems.',
                'focus_keyword' => 'WordPress site health diagnostics',
                'stats' => [['Checks', 'Modules and routes'], ['Registry', 'Reserved shortcodes'], ['Estimate', 'Page cost guidance'], ['Routine', 'Before and after updates']],
                'screens' => ['settings', 'updates'],
                'section_eyebrow' => 'Evidence order',
                'section_headline' => 'Separate a configuration warning from a reproducible public failure.',
                'section_lede' => 'Record versions and affected routes, run the narrow check, then verify the actual public behavior and fresh logs before changing settings.',
                'checks' => [
                    ['Version inventory', 'Record WordPress, active theme, Builder, addon, PHP, and database versions before diagnosis.'],
                    ['Route and registry health', 'Confirm required post types, REST routes, and Help4 shortcode tags exist and retain their expected owners.'],
                    ['Page evidence', 'Compare the affected public URL, Studio preview, response status, console, PHP log, and performance estimate.'],
                    ['After-change proof', 'Repeat the same checks after the narrow correction and preserve the before/after result.'],
                ],
                'steps' => [
                    ['Define the failing behavior', 'Write the exact URL, user state, viewport, action, expected result, and actual result before opening diagnostics.'],
                    ['Record the runtime inventory', 'Capture core, PHP, database, theme, plugin, and Builder build versions without assuming the updater screen is current.'],
                    ['Run Help4 health checks', 'Open Insights and review module, route, table, shortcode, and integration checks for the affected feature.'],
                    ['Inspect shortcode ownership', 'Confirm every used h4_ shortcode is registered by the expected Help4 module and has not been replaced by another plugin.'],
                    ['Compare page cost and assets', 'Use the estimate as guidance, then inspect real network requests, rendered widgets, cache headers, and public response time.'],
                    ['Read fresh logs', 'Reproduce once, then inspect the new PHP and browser entries rather than relying on old unrelated warnings.'],
                    ['Retest the same matrix', 'After the correction, repeat the original route, state, viewport, interaction, and log checks before closing the issue.'],
                ],
                'faq' => [
                    ['question' => 'Is a Builder performance estimate the same as public response time?', 'answer' => 'No. It is guidance based on layout and feature cost; public timing also depends on hosting, cache, database, network, media, and visitor state.'],
                    ['question' => 'Why audit reserved shortcodes?', 'answer' => 'A missing or replaced shortcode can turn dynamic content into blank output or literal shortcode text even when the page layout is intact.'],
                    ['question' => 'Should old log entries block a release?', 'answer' => 'Only current reproducible failures should block the release; preserve older entries as context but verify the timestamp and affected request.'],
                ],
            ],
            'help4-security-hardening-guide' => [
                'title' => 'Help4 WordPress Security Hardening Guide',
                'eyebrow' => 'Security operations',
                'headline' => 'Harden WordPress in layers without locking out the people and systems the site needs.',
                'lede' => 'Review SSL, security headers, login limits, XML-RPC, bad-query filtering, trusted proxy addresses, origin controls, file permissions, salt rotation, commerce requirements, and recovery access before enabling stricter controls.',
                'seo_title' => 'Help4 WordPress Security Hardening Guide',
                'seo_description' => 'Configure Help4 WordPress security headers, login protection, XML-RPC, proxy trust, origin controls, file permissions, salt rotation, commerce SSL, and recovery checks.',
                'focus_keyword' => 'WordPress security hardening guide',
                'stats' => [['Transport', 'HTTPS and HSTS'], ['Access', 'Login protections'], ['Origin', 'Proxy trust controls'], ['Recovery', 'Verified admin path']],
                'screens' => ['security', 'settings'],
                'section_eyebrow' => 'Safe hardening',
                'section_headline' => 'Know the recovery path before tightening the control.',
                'section_lede' => 'Security settings must match the real hosting, proxy, commerce, API, and administrator paths; copying an aggressive preset can cause an outage without reducing the actual risk.',
                'checks' => [
                    ['Recovery access', 'Keep one verified administrator and hosting recovery path outside the rule being changed.'],
                    ['HTTPS truth', 'Confirm the certificate, canonical host, forwarded protocol, mixed content, and checkout transport before enabling HSTS.'],
                    ['Proxy identity', 'Trust forwarding headers only from documented proxy ranges so visitor identity cannot be forged.'],
                    ['Functional regression', 'Retest login, forms, REST, cron, updates, checkout, webhooks, media, and Builder Studio after each change.'],
                ],
                'steps' => [
                    ['Record the current access path', 'Verify WordPress admin, hosting control panel, file access, and a rollback path before changing a security control.'],
                    ['Confirm SSL and canonical host', 'Test HTTP to HTTPS, www or apex behavior, certificate names, mixed content, and logged-out checkout before HSTS.'],
                    ['Review login and XML-RPC needs', 'Set bounded login attempts and disable XML-RPC only when no required publishing or integration workflow depends on it.'],
                    ['Configure headers gradually', 'Enable security headers one group at a time and use a report-first content security policy before enforcement.'],
                    ['Validate proxy and origin rules', 'Enter only current trusted proxy ranges and verify direct-origin restrictions do not block required health or management paths.'],
                    ['Check files, salts, and commerce', 'Review configuration permissions, salt-rotation recovery, secure cookies, and forced SSL for payment and customer actions.'],
                    ['Run the functional matrix', 'Test anonymous, member, editor, administrator, form, checkout, webhook, cron, update, REST, and Builder paths plus fresh logs.'],
                ],
                'faq' => [
                    ['question' => 'Should HSTS be enabled before HTTPS is fully correct?', 'answer' => 'No. Verify the certificate, canonical host, redirects, subdomain scope, and all required HTTPS routes before telling browsers to enforce HTTPS.'],
                    ['question' => 'Can every site disable XML-RPC?', 'answer' => 'No. Disable it only after confirming that no mobile publishing, remote management, or integration workflow still requires it.'],
                    ['question' => 'Why test Builder Studio after hardening?', 'answer' => 'Builder save, preview, REST, media, and AJAX requests can reveal an overly broad firewall or header rule that ordinary page views do not exercise.'],
                ],
            ],
            'help4-performance-cache-assets-guide' => [
                'title' => 'Help4 Performance, Cache and Asset Optimization',
                'eyebrow' => 'Performance operations',
                'headline' => 'Make pages faster by measuring the real bottleneck and changing one delivery layer at a time.',
                'lede' => 'Use compartment modules, image optimization, cache headers, script deferral, lazy loading, supported cache integrations, Builder estimates, public timing, and cache-state checks without hiding broken output behind a warm cache.',
                'seo_title' => 'Help4 WordPress Performance, Cache and Asset Guide',
                'seo_description' => 'Tune Help4 WordPress performance with module controls, image optimization, cache headers, script deferral, lazy loading, cache integrations, public timing, and regression tests.',
                'focus_keyword' => 'WordPress performance optimization guide',
                'stats' => [['Measure', 'Cold and warm requests'], ['Assets', 'Page-specific loading'], ['Cache', 'HIT, MISS, bypass'], ['QA', 'Layout and interactions']],
                'screens' => ['settings', 'studio'],
                'section_eyebrow' => 'Performance evidence',
                'section_headline' => 'A fast status code is not enough if the page shifts, clips, or stops responding.',
                'section_lede' => 'Measure public visitor behavior, asset cost, visual stability, and required interactions before and after each optimization.',
                'checks' => [
                    ['Module scope', 'Disable unused modules and confirm each enabled feature loads assets only where its output appears.'],
                    ['Cache truth', 'Distinguish anonymous cacheable pages from logged-in, query, cart, checkout, preview, and cookie bypass requests.'],
                    ['Media cost', 'Deliver appropriately sized images, posters, and video fallbacks without lazy-loading the first meaningful visual.'],
                    ['Behavior parity', 'Retest menus, forms, sliders, video, search, cart, checkout, and Studio after defer or cache changes.'],
                ],
                'steps' => [
                    ['Choose representative routes', 'Select the home page, a content page, a media-heavy page, a form, and any search, account, cart, or checkout route.'],
                    ['Capture a baseline', 'Record cold and warm timing, transfer size, request count, key assets, cache headers, layout stability, console, and server errors.'],
                    ['Remove unused module cost', 'Disable only modules the site does not use, then verify no shortcode, widget, template, or route depended on them.'],
                    ['Optimize media delivery', 'Right-size images and posters, confirm responsive sources, and reserve lazy loading for content below the initial viewport.'],
                    ['Tune scripts and cache', 'Enable deferral and supported cache integrations one at a time while preserving dependency order and private-route bypass.'],
                    ['Purge and test cache states', 'Check first MISS, warm HIT, logged-in bypass, query bypass, cart or checkout bypass, and content freshness after a save.'],
                    ['Compare the same matrix', 'Repeat the baseline at desktop and mobile and reject any change that improves a score while breaking layout or interaction.'],
                ],
                'faq' => [
                    ['question' => 'Should the first visible image be lazy loaded?', 'answer' => 'Usually no. The primary above-the-fold image or poster should be available promptly while lower content can use lazy loading.'],
                    ['question' => 'Why test both cache HIT and MISS?', 'answer' => 'A warm cache can hide slow generation, while an uncached response can expose stale purge rules, server errors, or missing assets.'],
                    ['question' => 'Can script deferral break a working page?', 'answer' => 'Yes. Deferral can change execution order, so menus, forms, sliders, search, video, commerce, and editor requests must be retested.'],
                ],
            ],
            'help4-feedback-igor-diagnostics' => [
                'title' => 'Help4 I.G.O.R. Feedback and Diagnostic Reports',
                'eyebrow' => 'Issue reporting',
                'headline' => 'Turn a vague Builder problem into a report another person can reproduce.',
                'lede' => 'Use I.G.O.R. feedback to send the affected URL, feature, action, expected result, actual result, versions, viewport, diagnostics, and optional screenshot without including credentials or private customer data.',
                'seo_title' => 'Help4 I.G.O.R. Feedback and Builder Diagnostics Guide',
                'seo_description' => 'Report Help4 Builder issues with reproducible steps, safe diagnostics, versions, URLs, viewport evidence, screenshots, privacy checks, and support follow-up.',
                'focus_keyword' => 'WordPress builder issue report',
                'stats' => [['Meaning', 'Integrated Graphical Organized Response'], ['Evidence', 'Steps and environment'], ['Privacy', 'No secrets'], ['Outcome', 'Reproducible handoff']],
                'screens' => ['settings', 'studio'],
                'section_eyebrow' => 'Useful reports',
                'section_headline' => 'Describe the smallest action that changes a working state into a failing state.',
                'section_lede' => 'A support report is strongest when it contains one affected route, one user state, one viewport, one failing action, and fresh evidence from the same attempt.',
                'checks' => [
                    ['Exact target', 'Include the public or admin URL, page or template ID, and feature name.'],
                    ['Reproduction', 'List the smallest ordered steps and whether the failure happens every time.'],
                    ['Safe evidence', 'Include versions, viewport, status, console or PHP message, and screenshot while removing secrets and customer data.'],
                    ['Expected outcome', 'State what should have remained visible, saved, interactive, or unchanged after the action.'],
                ],
                'steps' => [
                    ['Stop repeated edits', 'When the page begins losing content or style, stop and preserve the current state instead of trying more controls.'],
                    ['Record the target', 'Copy the URL, page or template ID, selected element, user role, viewport, and current Builder version.'],
                    ['Reproduce once', 'Start from a known state and perform only the smallest action that causes the failure.'],
                    ['Capture fresh evidence', 'Save the exact error text, response status, console line, PHP log timestamp, and a screenshot showing the selected control and result.'],
                    ['Remove sensitive data', 'Redact passwords, nonces, license keys, payment details, private messages, customer records, and server credentials.'],
                    ['Submit through I.G.O.R.', 'Enable feedback, confirm the destination, review the payload, and send one complete report instead of several partial reports.'],
                    ['Keep the ticket connected', 'Reply on the same support record with new evidence and confirm the public result before considering the issue complete.'],
                ],
                'faq' => [
                    ['question' => 'What does I.G.O.R. stand for?', 'answer' => 'I.G.O.R. stands for Integrated Graphical Organized Response, the Help4 issue-reporting path for reproducible diagnostics.'],
                    ['question' => 'Should passwords or private keys be included?', 'answer' => 'No. Never include credentials, nonces, payment secrets, license keys, or private customer data in a feedback report.'],
                    ['question' => 'What makes a screenshot useful?', 'answer' => 'Show the full relevant control, selected element, page context, and visible result while keeping private data out of the image.'],
                ],
            ],
            'help4-lms-courses-progress-certificates' => [
                'title' => 'Help4 LMS Courses, Progress, Certificates and Protected Media',
                'eyebrow' => 'Learning sites',
                'headline' => 'Build course, progress, certificate, video, and protected resource surfaces that respect member access.',
                'lede' => 'Connect Builder templates to LMS module contracts, place course and progress output, configure protected HLS or file video, verify certificate codes, and test anonymous, member, editor, completed, and denied states.',
                'seo_title' => 'Help4 LMS Guide | Courses, Progress, Certificates and Video',
                'seo_description' => 'Build Help4 LMS course, library, progress, certificate, protected video, and resource pages with Builder templates, access checks, responsive QA, and member-state testing.',
                'focus_keyword' => 'WordPress LMS builder guide',
                'stats' => [['Surfaces', 'Course and library'], ['State', 'Progress and access'], ['Proof', 'Certificates'], ['Media', 'Protected video']],
                'screens' => ['studio', 'theme_builder'],
                'section_eyebrow' => 'Member-state design',
                'section_headline' => 'Every learning page has more than one correct state.',
                'section_lede' => 'Design and test the anonymous, enrolled, unenrolled, in-progress, completed, certificate, media-failure, and access-denied outcomes instead of judging only an administrator preview.',
                'checks' => [
                    ['Template context', 'Assign the correct Builder template to course, archive, dashboard, certificate, video, and protected-resource routes.'],
                    ['Access state', 'Verify protected content never appears in source, preview, or fallback output for an unauthorized visitor.'],
                    ['Progress truth', 'Completion and progress values must persist for the correct user and course after refresh and login changes.'],
                    ['Media and certificate fallback', 'Test HLS, native file fallback, poster, failure image, reduced motion, and certificate lookup using valid and invalid values.'],
                ],
                'steps' => [
                    ['Inventory LMS routes and states', 'List every library, course, lesson, membership, dashboard, progress, certificate, video, and protected resource route.'],
                    ['Build assigned templates', 'Create Builder templates with explicit LMS conditions and preserve required module wrapper or shortcode output.'],
                    ['Place course and progress modules', 'Add the appropriate LMS output and confirm its module contract inherits global tokens without hardcoded site-specific selectors.'],
                    ['Configure protected media', 'Set HLS primary, native file fallbacks, poster, failure image, controls, preload, access behavior, and reduced-motion handling.'],
                    ['Verify certificates', 'Test direct certificate output and code-based lookup with valid, invalid, missing, and unauthorized values.'],
                    ['Run the member matrix', 'Check anonymous, unenrolled, enrolled, in-progress, completed, editor, and administrator states at desktop and mobile.'],
                    ['Confirm public parity', 'Compare Studio and public computed styles, scripts, access decisions, progress state, and protected network requests before launch.'],
                ],
                'faq' => [
                    ['question' => 'Why does an LMS page need several test users?', 'answer' => 'Course, progress, certificate, video, and protected-resource output changes according to enrollment, completion, role, and access state.'],
                    ['question' => 'Can protected video rely only on a hidden player?', 'answer' => 'No. Access must be enforced by the protected media delivery path; hiding a visible player is not access control.'],
                    ['question' => 'Should Studio use different LMS styles than the public page?', 'answer' => 'No. Studio should load the effective frontend assets and module contracts so the preview matches public output before publishing.'],
                ],
            ],
            'help4-google-business-reviews-guide' => [
                'title' => 'Help4 Google Business Profile and Reviews Guide',
                'eyebrow' => 'Local business proof',
                'headline' => 'Connect accurate business identity and selected review proof without inventing locations or promises.',
                'lede' => 'Configure the business profile, location details, service areas, map content, review source, cache, attribution, and Builder output so local pages use the same truthful name, phone, hours, URL, and entity data.',
                'seo_title' => 'Help4 Google Business Profile and Reviews Guide',
                'seo_description' => 'Configure Help4 local business identity, Google Business Profile data, reviews, locations, service areas, maps, attribution, cache, schema, and Builder output.',
                'focus_keyword' => 'Google Business Profile WordPress guide',
                'stats' => [['Identity', 'Name, phone, URL'], ['Locations', 'Address or service area'], ['Proof', 'Selected reviews'], ['Schema', 'Matching public facts']],
                'screens' => ['seo', 'studio'],
                'section_eyebrow' => 'Local identity',
                'section_headline' => 'Use one accurate business entity across pages, schema, maps, and profiles.',
                'section_lede' => 'Local visibility begins with consistent public facts and useful service content; a review widget or schema block cannot repair a false address, stale hours, or mismatched phone number.',
                'checks' => [
                    ['Business truth', 'Use the real customer-facing name, primary phone, canonical website, category, hours, and address or service-area model.'],
                    ['Location ownership', 'Create a location only when the business genuinely operates or serves customers according to platform rules.'],
                    ['Review integrity', 'Display genuine review text and source attribution without rewriting sentiment or inventing ratings.'],
                    ['Entity consistency', 'Keep visible content, local schema, maps, contact pages, and external profiles aligned.'],
                ],
                'steps' => [
                    ['Complete the business profile wizard', 'Choose the truthful business type and review the recommended defaults before saving site-owned settings.'],
                    ['Enter identity and contact data', 'Set brand name, phone, support URL, social profiles, location, hours, and service-area details that visitors can verify.'],
                    ['Configure the profile connection', 'Use the approved Google project and least-privilege credentials, then confirm the intended business and location before importing data.'],
                    ['Place local business content', 'Add the Google Business or local business widget to the relevant page and choose only the details that support that page.'],
                    ['Review maps and service areas', 'Verify map destination, address privacy, service-area wording, mobile interaction, and no duplicate location pages.'],
                    ['Verify review output', 'Check source attribution, rating math, review text, cache age, zero-review state, and link destination.'],
                    ['Audit public local SEO', 'Compare visible facts, LocalBusiness schema, canonical, social preview, sitemap, contact page, and the external profile.'],
                ],
                'faq' => [
                    ['question' => 'Should a service-area business publish a private home address?', 'answer' => 'No. Use the truthful service-area configuration and publish an address only when it is a legitimate customer-facing location.'],
                    ['question' => 'Can review wording be rewritten?', 'answer' => 'Do not change the meaning or sentiment of a customer review; preserve genuine text and provide clear source attribution.'],
                    ['question' => 'Does adding local schema guarantee local rankings?', 'answer' => 'No. Structured data helps systems understand truthful page content, but no setting can guarantee indexing, display, or ranking.'],
                ],
            ],
            'help4-mega-menu-guide' => [
                'title' => 'Help4 Mega Menu and Complex Navigation Guide',
                'eyebrow' => 'Advanced navigation',
                'headline' => 'Organize large navigation systems without losing keyboard, touch, or mobile users.',
                'lede' => 'Start with native WordPress menu hierarchy, then use Help4 menu and mega-menu controls for grouped destinations, clear disclosure behavior, reliable hover transitions, keyboard focus, touch activation, and responsive mobile panels.',
                'seo_title' => 'Help4 Mega Menu and Complex Navigation Guide',
                'seo_description' => 'Build Help4 mega menus with WordPress hierarchy, grouped links, keyboard and touch behavior, hover bridges, mobile panels, template assignments, and responsive testing.',
                'focus_keyword' => 'WordPress mega menu guide',
                'stats' => [['Source', 'WordPress menu hierarchy'], ['Desktop', 'Hover and keyboard'], ['Mobile', 'Touch disclosure'], ['Template', 'Global header']],
                'screens' => ['theme_builder', 'studio'],
                'section_eyebrow' => 'Navigation architecture',
                'section_headline' => 'Make the information hierarchy work before turning it into a large panel.',
                'section_lede' => 'A mega menu should reduce decisions, not display every page the site owns; group destinations by visitor task and keep one predictable mobile version.',
                'checks' => [
                    ['Hierarchy', 'Use clear parent labels, short child labels, and a manageable number of grouped destinations.'],
                    ['Pointer bridge', 'The desktop panel must stay open while the pointer moves from its trigger into the submenu.'],
                    ['Keyboard and touch', 'Triggers expose expanded state, focus can enter and leave every link, Escape closes, and touch never depends on hover.'],
                    ['Mobile containment', 'The panel, controls, text, and focus indicators fit 390px and 360px without horizontal clipping.'],
                ],
                'steps' => [
                    ['Map visitor tasks', 'Group destinations by what visitors need to accomplish and remove links that do not belong in primary navigation.'],
                    ['Build WordPress hierarchy', 'Create parent and child menu items in WordPress so the navigation remains structured outside the visual styling layer.'],
                    ['Insert the menu element', 'Place Menu in the assigned global header and select the intended menu, desktop behavior, and mobile breakpoint.'],
                    ['Configure the large panel', 'Use grouped headings, columns, optional descriptions, and one highlighted action without nesting interactive cards.'],
                    ['Test desktop transitions', 'Move the pointer slowly and quickly across the trigger-panel gap, neighboring items, panel edges, and nested links.'],
                    ['Test keyboard and touch', 'Use Tab, Shift-Tab, Enter, Space, Escape, outside click, and touch at tablet and phone widths.'],
                    ['Verify every assigned route', 'Test the global header on normal pages, templates, archives, search, 404, account, and checkout routes.'],
                ],
                'faq' => [
                    ['question' => 'Does a mega menu replace WordPress menu hierarchy?', 'answer' => 'No. Keep the WordPress menu as the content structure and use Builder controls to present it as a larger responsive panel.'],
                    ['question' => 'Why does a submenu disappear before it can be clicked?', 'answer' => 'A pointer gap or immediate close handler can end the hover state before the pointer reaches the panel; the trigger and panel need a continuous interaction region.'],
                    ['question' => 'Should mobile navigation depend on hover?', 'answer' => 'No. Mobile navigation needs explicit touch controls, visible expanded state, focus management, and a reliable close action.'],
                ],
            ],
            'help4-builder-beginner-templates' => [
                'title' => 'Help4 Builder Beginner Templates Guide',
                'eyebrow' => 'Beginner template workflow',
                'headline' => 'Start with a useful layout without replacing work you meant to keep.',
                'lede' => 'Use the Template Library to search by page job, inspect the starter, choose Insert or Replace Page deliberately, personalize every visible placeholder, and verify the result before publishing.',
                'seo_title' => 'Help4 Builder Beginner Templates | Insert and Customize Safely',
                'seo_description' => 'Learn how to search Help4 Builder templates, choose Insert or Replace Page, customize starter content, preserve existing work, and verify desktop and mobile output.',
                'focus_keyword' => 'Help4 Builder beginner templates',
                'stats' => [['Find', 'Search by page job'], ['Choose', 'Insert or replace'], ['Edit', 'Real content and media'], ['Verify', 'Desktop through 360px']],
                'screens' => ['beginner_templates', 'templates', 'studio'],
                'section_eyebrow' => 'Template decision',
                'section_headline' => 'Insert adds a pattern; Replace Page intentionally starts the page over.',
                'section_lede' => 'The two actions solve different jobs. Read the page title, review its current content, and choose the action only after deciding whether the existing layout belongs in the finished page.',
                'checks' => [
                    ['Correct target', 'Confirm the page or template title, publication state, and current layout before opening the library.'],
                    ['Correct action', 'Use Insert for an additional section and Replace Page only when the complete current layout is meant to be replaced.'],
                    ['Real content', 'Replace every sample heading, paragraph, image, link, business detail, proof item, and call to action.'],
                    ['Responsive result', 'Check structure, type, spacing, images, buttons, menus, and overflow at desktop, tablet, 390px, and 360px.'],
                ],
                'steps' => [
                    ['Open the intended draft', 'Use Builder Pages to open a draft or recoverable page, then read the title and save state shown at the top of Studio.'],
                    ['Open Templates and search by job', 'Choose Templates in the left library, search for the page purpose, and narrow by category when the first results are too broad.'],
                    ['Inspect the starter summary', 'Read its category, native block count, page mode, and whether it is a section pattern or complete page before inserting it.'],
                    ['Choose Insert or Replace Page', 'Insert appends the starter to the current layout; Replace Page should be used only after confirming the current layout is disposable or recoverable.'],
                    ['Personalize from the top down', 'Replace the main offer, proof, services, images, links, contact details, and final action before spending time on small styling changes.'],
                    ['Check page structure and globals', 'Use Navigator to confirm valid parents and order, then verify global colors, type, header, footer, and menu assignments still match the site.'],
                    ['Verify and publish deliberately', 'Save, reselect edited blocks, review every responsive viewport, open the frontend preview, and publish only when the real page is ready.'],
                ],
                'faq' => [
                    ['question' => 'What is the difference between Insert and Replace Page?', 'answer' => 'Insert adds the selected starter to the current layout, while Replace Page intentionally substitutes the complete page layout after confirmation.'],
                    ['question' => 'Should a starter template be published with its sample copy?', 'answer' => 'No. Replace every placeholder with accurate business content, media, links, proof, and calls to action before publishing.'],
                    ['question' => 'Can a template change the global header or footer?', 'answer' => 'A page starter should be reviewed alongside Theme Builder assignments so the intended global header, footer, menu, and page mode remain active.'],
                ],
            ],
            'help4-email-marketing-first-campaign' => [
                'title' => 'Help4 Email Marketing First Campaign Guide',
                'eyebrow' => 'First campaign workflow',
                'headline' => 'Prepare, test, and schedule the first email campaign with every sending gate visible.',
                'lede' => 'Use a permission-appropriate audience, complete sender and privacy settings, authenticate the sending domain, save a draft, send a controlled test, and schedule only after the message and opt-out path are verified.',
                'seo_title' => 'Help4 Email Marketing | Create and Test Your First Campaign',
                'seo_description' => 'Create a Help4 email campaign with sender readiness, confirmed contacts, subject and preview text, HTML and plain text, testing, scheduling, opt-out, and report checks.',
                'focus_keyword' => 'Help4 email marketing campaign',
                'stats' => [['Audience', 'Confirmed and eligible'], ['Message', 'HTML plus plain text'], ['Safety', 'Sender gates complete'], ['Launch', 'Test before schedule']],
                'screens' => ['email_campaign', 'forms', 'settings'],
                'section_eyebrow' => 'Sending readiness',
                'section_headline' => 'A campaign draft is not ready until identity, authentication, privacy, and unsubscribe behavior pass.',
                'section_lede' => 'The readiness notice is a release gate. Resolve every listed requirement and keep the audience source and communication basis documented for the site operating the campaign.',
                'checks' => [
                    ['Sender identity', 'Use an accurate From name, monitored Reply-To mailbox, physical postal address, privacy URL, and consistent site identity.'],
                    ['Domain authentication', 'Verify SPF, DKIM, and DMARC for the real sending path and complete a mailbox delivery test before enabling volume.'],
                    ['Eligible audience', 'Send only to the intended confirmed and nonsuppressed contacts, with a lawful and documented communication basis.'],
                    ['Complete message', 'Provide a useful subject, honest preview text, readable HTML, plain-text fallback, working links, identity, and a functional unsubscribe path.'],
                ],
                'steps' => [
                    ['Complete sender settings', 'Set From, Reply-To, postal address, privacy URL, daily attempt cap, consent wording, and confirmation message, then save the sender configuration.'],
                    ['Authenticate and test delivery', 'Verify SPF, DKIM, and DMARC, confirm the sending mailbox, and test delivery through the same WordPress mail transport the campaign will use.'],
                    ['Prepare the audience', 'Use confirmed, nonsuppressed subscribers or a properly defined eligible segment; remove test, stale, bounced, and unrelated contacts.'],
                    ['Create a campaign draft', 'Give the campaign an internal name, choose the audience and optional reusable template, then write the subject and preview text.'],
                    ['Write both message versions', 'Prepare accessible HTML and a useful plain-text fallback with consistent claims, links, sender identity, privacy information, and unsubscribe behavior.'],
                    ['Run a controlled test', 'Send to internal review addresses, check desktop and phone inboxes, click every link, reply to the message, and complete the unsubscribe path.'],
                    ['Schedule and verify the report', 'Choose the intended UTC schedule only after readiness passes, then confirm accepted, failed, clicked, opened, and suppressed outcomes in Campaign reports.'],
                ],
                'faq' => [
                    ['question' => 'Why does Help4 keep campaign sending locked?', 'answer' => 'Sending remains locked until required identity, privacy, mailbox, and domain-authentication gates are confirmed.'],
                    ['question' => 'Why include a plain-text version?', 'answer' => 'A plain-text fallback improves compatibility and gives recipients a usable message when HTML is unavailable or intentionally blocked.'],
                    ['question' => 'Does an accepted send mean the message reached the inbox?', 'answer' => 'No. Accepted means the configured WordPress mail transport accepted the attempt; inbox placement and recipient engagement require separate evidence.'],
                ],
            ],
            'help4-email-marketing-reports-automations' => [
                'title' => 'Help4 Email Reports and Drip Automations Guide',
                'eyebrow' => 'Reports and automation',
                'headline' => 'Read engagement honestly and build follow-up sequences that stop when a contact should not receive them.',
                'lede' => 'Use campaign reports to distinguish accepted delivery, estimated human opens, unique clicks, failures, and suppression; then build ordered automation steps only for confirmed, eligible contacts.',
                'seo_title' => 'Help4 Email Reports and Drip Automations | Opens, Clicks and Suppression',
                'seo_description' => 'Understand Help4 campaign reports and configure drip automations with ordered delays, confirmed contacts, segments, suppression, failure handling, privacy, and safe activation.',
                'focus_keyword' => 'Help4 drip automation reports',
                'stats' => [['Delivery', 'Accepted is transport'], ['Engagement', 'Clicks are stronger'], ['Automation', 'Ordered delays'], ['Stop rule', 'Global suppression']],
                'screens' => ['email_automation', 'email_campaign', 'forms'],
                'section_eyebrow' => 'Honest measurement',
                'section_headline' => 'Treat opens as estimates and clicks as a stronger engagement signal.',
                'section_lede' => 'Privacy protections and automated scanners can affect open and click events. Use the report to understand patterns, delivery failures, and real actions without presenting every recorded event as a person reading the message.',
                'checks' => [
                    ['Status meaning', 'Separate draft, scheduled, running, completed, paused, failed, and suppressed outcomes.'],
                    ['Engagement meaning', 'Report human-classified opens as estimates and use unique clicks, replies, forms, calls, and purchases as stronger signals.'],
                    ['Sequence timing', 'Measure each delay after the prior accepted step and test the complete sequence with internal addresses first.'],
                    ['Stop behavior', 'Global suppression, unsubscribe, invalid address, and other ineligible states must prevent later automation steps.'],
                ],
                'steps' => [
                    ['Read the delivery totals', 'Compare audience size, accepted attempts, failures, and suppressions before interpreting opens or clicks.'],
                    ['Review unique engagement', 'Use unique clicks and completed downstream actions as stronger signals, while treating human opens as directional estimates.'],
                    ['Investigate failures', 'Review transport and address failures, correct the underlying problem, and avoid repeatedly retrying an invalid or suppressed address.'],
                    ['Create a reusable template', 'Save consistent sender identity, message structure, footer, privacy, and unsubscribe presentation before building several steps.'],
                    ['Define automation eligibility', 'Choose the trigger, segment, and confirmed-contact requirements, then document when a contact should enter, pause, complete, or leave.'],
                    ['Write ordered steps', 'Set each delay, subject, HTML message, and plain-text message, with one useful action and no repeated claim that ignores the prior step.'],
                    ['Test, activate, and monitor', 'Run the complete sequence with internal contacts, verify timing and suppression, activate deliberately, and review fresh reports for failures or unexpected enrollment.'],
                ],
                'faq' => [
                    ['question' => 'Are email opens exact?', 'answer' => 'No. Privacy protections, cached images, blocked images, and scanners can affect open events, so Help4 presents human opens as estimates.'],
                    ['question' => 'What should happen after a contact unsubscribes?', 'answer' => 'The address should enter global suppression and later campaign or automation steps must skip it.'],
                    ['question' => 'When is an automation delay measured?', 'answer' => 'Each delay is measured after the previous step was accepted, which keeps the sequence timing ordered and understandable.'],
                ],
            ],
            'help4-builder-quick-help' => [
                'title' => 'Help4 Builder Quick Help Guide',
                'eyebrow' => 'Help inside Studio',
                'headline' => 'Open the right tutorial from the Builder without losing the page you are editing.',
                'lede' => 'Quick Help provides 25 searchable task guides while Builder Studio keeps the selected page, preview, library, inspector, and save state visible.',
                'seo_title' => 'Help4 Builder Quick Help | Find Tutorials Inside Studio',
                'seo_description' => 'Search 25 Help4 Builder Quick Help tasks covering direct click editing, pages, text, responsive structure, templates, site kits, globals, navigation, media, forms, dynamic data, custom CSS, commerce, SEO, recovery, and publishing.',
                'focus_keyword' => 'Help4 Builder Quick Help',
                'stats' => [['Open', 'Question-mark help'], ['Search', '25 task guides'], ['Return', 'Same editing context'], ['Escalate', 'Evidence-ready support']],
                'screens' => ['quick_help', 'studio', 'builder_pages'],
                'section_eyebrow' => 'Contextual documentation',
                'section_headline' => 'Choose the guide by the job in front of you, not by a feature name you have to guess.',
                'section_lede' => 'Search by a plain task, widget, or setting, then use the inspector link for element-specific guidance. The full tutorial hub remains available for specialized workflows.',
                'checks' => [
                    ['Page context', 'Read the current page or template title and save state before opening a guide.'],
                    ['Task match', 'Search for the current outcome: content, structure, Navigator, templates, site kits, globals, navigation, media, forms, commerce, SEO, recovery, or publishing.'],
                    ['Return path', 'Keep Studio open, follow one guide, and return to the same selected page rather than reopening a similarly named object.'],
                    ['Support evidence', 'When a guide does not resolve the issue, capture the URL, version, selected element, smallest reproduction, screenshot, and fresh error evidence.'],
                ],
                'steps' => [
                    ['Confirm the current page', 'Read the title under Help4 Builder and verify whether you are editing a page, post, header, footer, archive, or another template.'],
                    ['Open Quick Help', 'Use the question-mark help control in the Builder header to open the task guide panel.'],
                    ['Search in plain language', 'Type a short task such as mobile, image, site kit, global styles, CSS, campaign, SEO, or recovery. Every word must match the guide label or task key.'],
                    ['Choose the matching task', 'Open the one visible link that best describes what you need to finish rather than opening several broad manuals at once.'],
                    ['Follow the guide one step at a time', 'Keep the documentation in a separate tab and verify each checkpoint in the current Studio page before continuing.'],
                    ['Use contextual inspector help', 'After selecting a widget, use the inspector help link when the problem belongs to that content type or control group.'],
                    ['Clear or expand the search', 'Use the clear icon to restore all 25 tasks, or open All tutorials for specialized guides, screenshots, narrated lessons, and transcripts.'],
                    ['Escalate with reproducible evidence', 'If the task still fails, stop changing the page and send Help4 the exact target, steps, expected result, actual result, versions, screenshot, and fresh log detail.'],
                ],
                'faq' => [
                    ['question' => 'Does opening Quick Help publish or change the page?', 'answer' => 'No. It opens documentation links and leaves the current Builder page and save state unchanged.'],
                    ['question' => 'Where is help for a specific widget?', 'answer' => 'Select the widget and use its inspector help link when available; otherwise search Quick Help or the tutorial hub by the task or widget name.'],
                    ['question' => 'What should be included in a support report?', 'answer' => 'Include the exact URL, page or template title, selected element, plugin and WordPress versions, smallest reproduction, expected and actual behavior, screenshot, and fresh error evidence.'],
                ],
            ],
            'help4-dependency-update-diagnostics' => [
                'title' => 'Help4 Dependencies, Updates and Release Diagnostics',
                'eyebrow' => 'Release operations',
                'headline' => 'Install the right package, preserve required companions, and prove the update worked beyond the version label.',
                'lede' => 'Use stable and beta channels deliberately, verify immutable ZIP hashes and manifests, keep the plugin and Help4 Blank theme packages separate, review dependencies, update on a recoverable site, and run public plus editor regression checks.',
                'seo_title' => 'Help4 Builder Dependencies and Update Diagnostics Guide',
                'seo_description' => 'Verify Help4 Builder ZIPs, manifests, stable and beta channels, Help4 Blank theme compatibility, dependency checks, WordPress updates, rollback, and post-update QA.',
                'focus_keyword' => 'Help4 Builder update guide',
                'stats' => [['Stable', 'Public production channel'], ['Beta', 'md validation channel'], ['Identity', 'Version and build hash'], ['Proof', 'Editor and public QA']],
                'screens' => ['updates', 'settings'],
                'section_eyebrow' => 'Release identity',
                'section_headline' => 'The version, build hash, ZIP hash, manifest, updater, and installed files must describe the same release.',
                'section_lede' => 'A green updater screen is only inventory; a release is ready when the package identity is exact and the affected workflows pass on the real runtime.',
                'checks' => [
                    ['Immutable artifact', 'Record the versioned ZIP URL, byte size, SHA-256, plugin build hash, and manifest before installation.'],
                    ['Package boundary', 'Install Builder Suite as a plugin and Help4 Blank as a separate theme package when the blank-theme workflow is desired.'],
                    ['Runtime compatibility', 'Confirm WordPress, PHP, database, active theme, addons, and required modules meet the release requirements.'],
                    ['Regression evidence', 'Verify public routes, Studio, save and preview, responsive output, forms, commerce, SEO, and fresh logs after the update.'],
                ],
                'steps' => [
                    ['Choose the correct channel', 'Use stable for public production and beta only on an approved validation site that can expose the next WordPress or Builder line safely.'],
                    ['Record package identity', 'Capture the exact versioned ZIP, SHA-256, size, build hash, manifest response, and updater latest alias before installing.'],
                    ['Prepare recovery', 'Keep a recoverable database, current plugin directory or prior immutable ZIP, and any page or global layout data at risk.'],
                    ['Check dependencies and theme boundary', 'Confirm required companion plugins and the separately packaged Help4 Blank theme without bundling site-specific customizations.'],
                    ['Install and verify files', 'Update through WordPress or the approved installer, then confirm active version, build hash, changed asset versions, database state, and update inventory.'],
                    ['Run functional regression', 'Check public pages, Studio open and save, templates, mobile menus, forms, search, commerce, SEO output, cache, and fresh PHP or browser errors.'],
                    ['Promote only the tested artifact', 'Point latest aliases and manifests to the immutable artifact that passed QA, then verify public bytes and clear only the relevant caches.'],
                ],
                'faq' => [
                    ['question' => 'Why are Help4 Builder Suite and Help4 Blank separate downloads?', 'answer' => 'WordPress distributes plugins and themes as separate packages, so Builder Suite supplies plugin features while Help4 Blank supplies the optional theme shell.'],
                    ['question' => 'Is the installed version number enough to prove the update?', 'answer' => 'No. Also verify the build hash, artifact hash, manifest, asset versions, database state, public behavior, editor behavior, and fresh logs.'],
                    ['question' => 'When should the beta channel be used?', 'answer' => 'Use beta on an approved recoverable validation site to test upcoming WordPress and Builder changes before promoting the exact tested artifact to stable.'],
                ],
            ],
        ];
    }

    /**
     * @param array<string, mixed> $guide
     */
    private function h4BuilderOperationsGuidePage(array $guide, string $ticketUrl): string
    {
        $faq = is_array($guide['faq'] ?? null) ? $guide['faq'] : [];
        $videoNumbers = $this->h4BuilderTutorialVideoNumbersForContext(
            (string) ($guide['title'] ?? '') . ' ' . (string) ($guide['headline'] ?? '')
        );

        return '<div class="h4-tutorial">'
            . $this->h4ProductHero(
                (string) ($guide['eyebrow'] ?? 'Help4 operations'),
                (string) ($guide['headline'] ?? $guide['title'] ?? 'Help4 guide'),
                (string) ($guide['lede'] ?? ''),
                $this->h4ProductActions($this->h4TrackedDownloadUrl('builder-suite'), 'Download Latest ZIP', home_url('/help4-builder-tutorials/'), 'Search Every Tutorial'),
                $this->h4ProductCommand(is_array($guide['stats'] ?? null) ? $guide['stats'] : [], 'Guide map')
            )
            . $this->h4ProductFeatureBand(
                'Before changing settings',
                'Confirm the site, user state, current version, and recovery path.',
                'Open the exact site and feature named in the request, record its current behavior, and keep a bounded recovery option. Change one setting group at a time so the verification can identify what actually changed.',
                [
                    ['Target', 'Record the domain, URL or admin screen, user role, viewport, and specific outcome before changing configuration.'],
                    ['Current state', 'Capture the relevant version, enabled module, existing value, and a fresh public or runtime check.'],
                    ['Recovery', 'Keep the previous immutable package, WordPress revision, export, or narrow data snapshot needed for this feature.'],
                    ['Privacy', 'Keep credentials, private customer data, payment secrets, nonces, and protected files out of screenshots and support reports.'],
                ]
            )
            . $this->h4BuilderTutorialVisualWalkthrough(is_array($guide['screens'] ?? null) ? $guide['screens'] : ['settings'])
            . $this->h4BuilderTutorialVideoSection($videoNumbers)
            . $this->h4ProductFeatureBand(
                (string) ($guide['section_eyebrow'] ?? 'Feature setup'),
                (string) ($guide['section_headline'] ?? 'Configure the feature in a verifiable order.'),
                (string) ($guide['section_lede'] ?? ''),
                is_array($guide['checks'] ?? null) ? $guide['checks'] : []
            )
            . $this->h4BuilderTutorialWalkthrough(is_array($guide['steps'] ?? null) ? $guide['steps'] : [])
            . $this->h4ProductFeatureBand(
                'Release check',
                'Test the real public or member outcome, not only the settings screen.',
                'Reopen the saved setting, run the intended workflow in the correct visitor state, test desktop and phone behavior where a frontend surface exists, and inspect fresh browser or PHP errors from the same attempt.',
                [
                    ['Persistence', 'The saved values remain correct after reload and do not overwrite newer settings from another session.'],
                    ['Public behavior', 'The intended visitor can complete the workflow and an unintended visitor cannot access protected output.'],
                    ['Responsive behavior', 'Controls, text, tables, media, dialogs, and focus stay visible and usable at 768px, 390px, and 360px.'],
                    ['Fresh evidence', 'The final request has the expected status, output, cache state, and no new related console or PHP error.'],
                ]
            )
            . $this->h4BuilderOperationsGuideFaq($faq)
            . $this->h4BuilderTutorialNav()
            . $this->h4ProductFinalCta('Need a second set of eyes?', 'Send one complete, privacy-safe support record.', 'Include the affected URL or admin screen, current Builder version, user state, exact steps, expected result, actual result, and one screenshot or fresh error when available.', $ticketUrl, 'Open Help4 Ticket', home_url('/help4-builder-tutorials/'), 'Search Tutorials')
            . '</div>';
    }

    /**
     * @param array<int, array<string, string>> $faq
     */
    private function h4BuilderOperationsGuideFaq(array $faq): string
    {
        if ($faq === []) {
            return '';
        }

        $html = '<section class="h4-tutorial-faq" aria-labelledby="h4-tutorial-faq-title"><div class="h4-tutorial-section-heading"><p class="h4-product-eyebrow">Common questions</p><h2 id="h4-tutorial-faq-title">Answers for the decisions that block this setup most often.</h2></div><div class="h4-tutorial-faq__items">';
        foreach ($faq as $index => $item) {
            $question = sanitize_text_field((string) ($item['question'] ?? ''));
            $answer = sanitize_text_field((string) ($item['answer'] ?? ''));
            if ($question === '' || $answer === '') {
                continue;
            }
            $html .= '<details' . ($index === 0 ? ' open' : '') . '><summary>' . esc_html($question) . '</summary><p>' . esc_html($answer) . '</p></details>';
        }

        return $html . '</div></section>';
    }

    private function h4BuilderDocsHubPage(string $ticketUrl): string
    {
        return $this->h4ProductHero(
            'Builder documentation',
            'Learn Help4 Builder Suite in the order real site work happens.',
            'These tutorials use screenshots captured from a disposable blank WordPress install with Builder Suite active, so users can compare their own admin screens against a clean starting point.',
            $this->h4ProductActions(home_url('/help4-builder-guide/'), 'Start Install Guide', home_url('/help4-builder-screenshots/'), 'View Screenshots'),
            $this->h4ProductCommand(
                [
                    ['Guides', count($this->h4BuilderTutorialCards()) . ' task-based tutorials'],
                    ['Search', 'Task and category filters'],
                    ['Screenshots', '48 current guided captures'],
                    ['Videos', count($this->h4BuilderTutorialVideoCatalog()) . ' narrated lessons'],
                    ['Templates', '135 starter specs'],
                    ['Icons', '230 default SVG icons'],
                ],
                'Documentation set'
            )
        )
        . $this->h4BuilderScreenGrid(['settings', 'builder_pages', 'studio', 'theme_builder'])
        . $this->h4BuilderTutorialVideoSection([], true)
        . $this->h4ProductFeatureBand(
            'Use the docs by job',
            'The customer does not need module trivia. They need the next useful click.',
            'Each guide explains what the screen is for, what to do first, what to check before publishing, and when to hand the work to Help4.',
            [
                ['Blank install', 'Start with settings, Builder Pages, and Studio so the user knows what a healthy install looks like.'],
                ['Theme files', 'Builder Suite and Help4 Blank are separate downloads because WordPress.org treats plugins and themes as separate packages. Use the install guide when the theme ZIP is missing.'],
                ['Template path', 'Pick templates by page job, then customize copy, proof, images, forms, and calls to action.'],
                ['Launch path', 'Use the SEO, readability, security, performance, and update checks before pushing a page live.'],
            ]
        )
        . $this->h4BuilderTutorialNav(true)
        . $this->h4ProductFinalCta('Need the builder configured?', 'Tell Help4 what kind of site this is.', 'Send the site type, pages needed, checkout needs, design examples, current URL, and whether you want starter templates or custom page builds.', $ticketUrl, 'Request Builder Setup', home_url('/plugin-help4-builder-suite/'), 'Plugin Overview');
    }

    private function sanitizeTutorialHubHtml(string $html): string
    {
        $allowed = wp_kses_allowed_html('post');
        $searchAttributes = [
            'data-h4-doc-search-root',
            'data-h4-doc-search-results',
            'data-h4-doc-search-status',
            'data-h4-doc-search-empty',
            'data-h4-doc-item',
            'data-h4-doc-category',
            'data-h4-doc-text',
            'data-h4-doc-filter',
            'data-h4-doc-search-clear',
            'data-h4-doc-search-input',
        ];
        foreach (['div', 'article', 'button', 'p', 'input'] as $tag) {
            if (! isset($allowed[$tag]) || ! is_array($allowed[$tag])) {
                $allowed[$tag] = [];
            }
            foreach ($searchAttributes as $attribute) {
                $allowed[$tag][$attribute] = true;
            }
            $allowed[$tag]['hidden'] = true;
        }
        $allowed['input'] = [
            ...$allowed['input'],
            'id' => true,
            'type' => true,
            'inputmode' => true,
            'autocomplete' => true,
            'placeholder' => true,
            'data-h4-doc-search-input' => true,
        ];

        return wp_kses($html, $allowed);
    }

    private function h4BuilderScreenshotsPage(string $ticketUrl): string
    {
        $catalog = $this->h4BuilderScreenCatalog();

        return $this->h4ProductHero(
            'Blank-install screenshots',
            'See what Help4 Builder Suite looks like before you start clicking.',
            'These images were captured from a clean WordPress install with Builder Suite active: settings, page list, Studio, templates, fields, commerce, forms, SEO, security, and updates.',
            $this->h4ProductActions(home_url('/help4-builder-guide/'), 'Open Install Guide', $ticketUrl, 'Ask for Setup Help'),
            $this->h4ProductCommand(
                [
                    ['Captured', 'July 23, 2026'],
                    ['Source', 'Blank WordPress install'],
                    ['Viewport', '1401 x 960'],
                    ['Purpose', 'User orientation'],
                ],
                'Screenshot proof'
            )
        )
        . $this->h4ProductScreenGrid(array_values($catalog))
        . $this->h4ProductCompare(
            ['Screen', 'Use it for', 'First safe action'],
            [
                ['Settings dashboard', 'Modules, setup, support, release state', 'Confirm only needed modules are enabled.'],
                ['Builder Pages', 'Page selection and builder launch', 'Open a draft page before touching live content.'],
                ['Builder Studio', 'Visual page building and responsive checks', 'Build sections first, then content, then mobile.'],
                ['Theme Builder', 'Global headers, footers, templates, 404s, popups', 'Create one global header/footer before exceptions.'],
                ['Fields Lab', 'Structured custom content', 'Create a field group only when content repeats.'],
                ['Commerce', 'Catalog, variations, subscriptions, routing', 'Plan product data before checkout.'],
                ['SEO/Security', 'Launch quality and hardening', 'Check readability, metadata, SSL, and headers before launch.'],
            ]
        )
        . $this->h4BuilderTutorialNav(true)
        . $this->h4ProductFinalCta('Screen does not match your install?', 'Send Help4 a screenshot before guessing.', 'A clean install is easy to fix. Send the admin screen, plugin version, WordPress version, and the page you were trying to edit.', $ticketUrl, 'Open Support Ticket', home_url('/help4-builder-tutorials/'), 'Tutorial Hub');
    }

    private function h4BuilderInstallGuidePage(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Install guide',
            'Install Builder Suite, run setup, and open the first builder page.',
            'Use this when a non-technical site owner needs the normal free install path: download the ZIP, upload it, activate it, compare the blank-install screens, then build a draft page.',
            [['Start', 'Download plugin ZIP'], ['Then', 'Check settings'], ['Build', 'Open Builder Studio']],
            ['settings', 'builder_pages', 'studio', 'updates'],
            'Healthy first run',
            'A fresh install should show the same core screens.',
            'Do not turn on every module just because it exists. The first job is confirming the plugin loaded cleanly and the builder can open a safe draft page.',
            [
                ['Download the current ZIP', 'Use the public latest.zip package and keep it zipped for WordPress upload.'],
                ['Upload in WordPress', 'Go to Plugins, Add New, Upload Plugin, choose the ZIP, install, and activate.'],
                ['Download the theme ZIP separately', 'WordPress.org treats plugins and themes as separate packages. If Help4 Blank is missing, download help4-blank.zip from /help4-blank/help4-blank.zip and install it under Appearance > Themes. The public manifest lives at /help4-blank/manifest.json.'],
                ['Use the blank theme path', 'Help4 Blank is the clean shell; Builder Suite controls the pages, templates, icons, and modules.'],
                ['Check Settings first', 'Confirm support links, module state, release channel, and update information.'],
                ['Open Builder Pages', 'Choose a draft or test page and launch Builder Studio before editing live pages.'],
                ['Preview before publish', 'Save the draft, preview the front end, and check mobile before customers see it.'],
            ],
            [
                ['Settings dashboard', 'This proves the plugin loaded and gives the site owner one control room.'],
                ['Builder Pages', 'This keeps the first editing step obvious and avoids digging through WordPress menus.'],
                ['Builder Studio', 'This proves the visual builder, responsive controls, and element library are ready.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderFirstPageGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'First page tutorial',
            'Build the first Help4 Builder page without breaking a live site.',
            'The safest first page is a draft service, landing, contact, or product page. Prove the workflow first: structure, content, mobile, preview, publish.',
            [['Best page', 'Draft service page'], ['Order', 'Structure before style'], ['Before live', 'Mobile QA']],
            ['builder_pages', 'studio', 'theme_builder'],
            'Page workflow',
            'Do layout before tiny styling details.',
            'A useful page explains what the business does, why it matters, what proof exists, and what the visitor should do next.',
            [
                ['Create or choose a draft page', 'Use a real page type, but keep it out of the live navigation until it is checked.'],
                ['Launch Builder Studio', 'Open Builder Pages and choose the draft so you can work in the visual editor.'],
                ['Add sections before details', 'Hero, proof, services/products, FAQs, and CTA come before small visual tweaks.'],
                ['Replace starter copy', 'Use the customer offer, service areas, product names, proof, and real next action.'],
                ['Check responsive views', 'Use monitor, tablet, mobile, and large-screen controls before publishing.'],
                ['Publish only after frontend preview', 'The public page should match the builder and have no right-edge clipping.'],
            ],
            [
                ['Structure', 'Use sections and containers first so the design has stable layout bones.'],
                ['Copy', 'Short clear copy beats a polished page that does not explain the offer.'],
                ['Mobile', 'Look for wide images, long buttons, tables, embedded URLs, and headings that push off screen.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderEditorControlsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Editor controls',
            'Click the image or words you want to change, then publish one verified edit.',
            'Open the correct page in Builder Studio, click the visible image, heading, paragraph, button, or link, and use the controls that appear on the right. This works for native Builder elements and for safely mapped items inside a migrated one-element HTML page.',
            [['Select', 'Click the visible item'], ['Edit', 'Controls on the right'], ['Preview', 'Before publish'], ['Verify', 'Public page']],
            ['edit_open', 'edit_image', 'edit_text', 'edit_verify'],
            'Your first complete edit',
            'Change the intended item without deleting the page around it.',
            'Click the visible target first. The inspector must name that target, Live Preview must show the unsaved result, and Save Element and Publish must preserve every sibling you did not edit.',
            [
                ['Open the correct page', 'In WordPress, choose Help4 Builder and Builder Pages, find the page title, and open Studio. Confirm the title under Help4 Builder before editing.'],
                ['Click the visible item', 'Click the exact image, heading, paragraph, button, or link in the center Live Preview. The right inspector should identify the selected item.'],
                ['Use Navigator only when needed', 'Open Navigator when overlapping layers make the intended section, container, column, or widget difficult to click. Select the smallest child that owns the content.'],
                ['Replace an image safely', 'Choose Replace Image, select the approved file, write useful alternative text, and update the link only when the image should lead somewhere. Do not remove the parent row.'],
                ['Edit only the words', 'Type in the Selected heading text or Selected text field. If the item contains nested formatting, Studio leaves it untouched and directs an experienced editor to the advanced source instead of flattening it.'],
                ['Recognize a migrated one-element page', 'Navigator may show one HTML Block even though the page contains many visible items. Click a supported inner item and use Quick edit what you clicked; the rest of the HTML block stays unchanged.'],
                ['Watch the unsaved result', 'The new image or words must remain visible in Live Preview, including after switching desktop, tablet, or mobile views. If the old value returns, do not publish and report the page and selected item.'],
                ['Save Element and Publish', 'Use the blue button only after the intended result is visible. Then open the public page and verify the saved item, links, typography, image, and neighboring content.'],
            ],
            [
                ['What to click', 'Click the visible content itself. Use Navigator only for overlap or when you need the parent container rather than the words or image.'],
                ['Image preparation', 'Match the target block aspect ratio, use WebP for most photographic or illustrated graphics, and use PNG when real transparency is required. Confirm the target contract before choosing fixed pixel dimensions.'],
                ['Migrated-page protection', 'Quick edit changes only the mapped text, image source, alternative text, or link. It refuses nested markup that could lose formatting.'],
                ['No collateral changes', 'The selected value persists after save while unrelated markup, fonts, colors, spacing, links, and sibling content remain unchanged.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderWpCliRunnersGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'WP-CLI runner guide',
            'Run guarded Builder seed, migration, launch, repair, audit, and recovery jobs safely.',
            'WordPress loads bootstrap code before a file passed to wp eval-file. Runner files must avoid first-statement assumptions while retaining every environment, authorization, draft, noindex, no-publish, and rollback guard.',
            [['Applies to', 'Every eval-file runner'], ['Default', 'Dry run or draft'], ['Required', 'Guards stay intact']],
            ['settings', 'updates', 'builder_pages', 'security'],
            'Runner contract',
            'Compatibility is not permission to remove safety checks.',
            'Omit constructs that require the first physical PHP statement, including declare(strict_types=1). Keep the checks that prevent the correct script from mutating the wrong site, environment, object, release, or publication state.',
            [
                ['Define the bounded job', 'State whether the runner seeds, migrates, launches, repairs, audits, or recovers content and list the exact objects it may touch.'],
                ['Remove first-statement assumptions', 'Do not include declare(strict_types=1) or another construct that assumes it runs before the WordPress bootstrap prepended by wp eval-file.'],
                ['Keep environment guards', 'Validate the host, path, WordPress and Builder versions, current user capability, expected object state, and any explicit authorization constant.'],
                ['Default to a non-public outcome', 'Use dry run, draft, noindex, and no-publish defaults until a separately authorized launch step passes QA.'],
                ['Preserve Builder structure', 'Keep element IDs, parent references, slots, order, extension data, page mode, template conditions, and SEO metadata unless the job explicitly owns them.'],
                ['Lint and run a read-only harness', 'Check PHP syntax, expected counts, duplicate IDs, dangling parents, invalid slots, status, robots state, and intended responsive values before mutation.'],
                ['Execute one bounded mutation', 'Capture created, updated, skipped, and failed counts without printing secrets, customer data, raw logs, or credentials.'],
                ['Verify, recover, and clean up', 'Compare before/after structure, preview the affected routes, use the defined rollback when needed, and remove temporary runner files.'],
            ],
            [
                ['All runner types', 'Use the same compatibility rule for seed, migration, launch, repair, audit, and recovery files.'],
                ['Publication safety', 'A failed preflight must leave drafts unpublished and the public hold unchanged.'],
                ['Data safety', 'Unknown namespaced extension data and existing Builder relationships must survive a round trip.'],
                ['Operational hygiene', 'Use a bounded rollback artifact when needed; do not create repeated server backups of the same package.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderTemplatesGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Templates and icons',
            'Start from a real page pattern instead of a blank screen.',
            'Builder Suite includes starter specs, theme parts, and bundled SVG icons so a new site has structure from the first hour.',
            [['Starter specs', '135'], ['Icons', '230 SVG defaults'], ['Best habit', 'Choose by job']],
            ['templates', 'theme_builder', 'studio'],
            'Template path',
            'Pick a starter by the page job, not by prettiness.',
            'Templates are starting points. Choose the closest business goal, then change words, proof, images, layout, and calls to action.',
            [
                ['Choose the page job', 'Service, product, recent work, support, local SEO, launch announcement, checkout recovery, or docs.'],
                ['Import to a draft', 'Do not apply a starter directly to a live revenue page without reviewing it first.'],
                ['Replace sample content', 'Use real offers, locations, product terms, proof, and next-step buttons.'],
                ['Use icons sparingly', 'One icon per card or step is enough; the words still do the selling.'],
                ['Save reusable pieces', 'Headers, footers, CTAs, and service blocks should become templates when repeated.'],
            ],
            [
                ['Starter templates', 'Use them to avoid blank-page paralysis and speed up first drafts.'],
                ['Theme Builder', 'Use it for global pieces so pages do not each get separate header/footer work.'],
                ['Default icons', 'Use local icons so a fresh install does not depend on random remote icon packs.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderTemplateLibraryGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Template library',
            'Choose the starter closest to the customer problem.',
            'The template library is organized around jobs: launch, support, commerce, local SEO, recent work, forms, documentation, and recovery flows.',
            [['Starters', '135'], ['Sections', 'Job-based'], ['Best use', 'Import then customize']],
            ['templates', 'builder_pages', 'studio'],
            'Starter strategy',
            'Do not make every page start from the same layout.',
            'A service page, product collection, support article, and release note need different structures. Pick by outcome first.',
            [
                ['Search by the page goal', 'Use words like service, product, support, local, recent work, launch, docs, or checkout.'],
                ['Preview the starter', 'Confirm the starter has the right sections before importing it.'],
                ['Import into a draft', 'Use the draft to replace content and remove sections that do not fit.'],
                ['Run mobile early', 'Templates still need long headings, images, buttons, and cards checked on small screens.'],
                ['Keep a best version', 'Save cleaned-up versions as reusable patterns for future pages.'],
            ],
            [
                ['Launch starters', 'Use for first-site setup, landing pages, announcements, and service launch pages.'],
                ['Commerce starters', 'Use for product collections, subscriptions, checkout support, and recovery pages.'],
                ['Documentation starters', 'Use for tutorials, knowledge-base indexes, support articles, and release notes.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderIconsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Default icon library',
            'Use the bundled Help4 SVG icons so pages do not start empty.',
            'The plugin ships local default icons for builder setup, commerce, support, SEO, security, launch, updates, forms, documentation, and proof sections.',
            [['Icons', '230 SVG defaults'], ['Use', 'Cards and steps'], ['Format', 'Local assets']],
            ['templates', 'studio', 'settings'],
            'Icon usage',
            'Icons should clarify the card, not decorate the page into noise.',
            'Use one icon per feature card or process step. Keep labels plain and do not use icons as a replacement for important copy.',
            [
                ['Pick the card purpose', 'Choose the icon after the card title and benefit are written.'],
                ['Use local defaults first', 'The bundled set avoids dependency on a third-party icon CDN.'],
                ['Keep labels clear', 'The icon supports the label; it should not be the only explanation.'],
                ['Check contrast', 'Icons should remain visible in dark and light sections.'],
                ['Preview mobile', 'Icons should not squeeze the copy or enlarge cards unpredictably.'],
            ],
            [
                ['Builder icons', 'Use quickstart, template, module, responsive, and launch icons for setup pages.'],
                ['Commerce icons', 'Use catalog, variation, subscription, payment route, and checkout icons for store flows.'],
                ['Support icons', 'Use ticket, docs, health, uptime, email, and emergency icons for help paths.'],
            ],
            $ticketUrl
        )
        . $this->h4BuilderIconPreviewGrid();
    }

    private function h4BuilderIconPreviewGrid(): string
    {
        $icons = [
            ['builder-quickstart', 'Builder quickstart', 'First safe page setup'],
            ['template-pack', 'Template pack', 'Starter layouts and sections'],
            ['theme-builder', 'Theme builder', 'Headers, footers, and rules'],
            ['commerce-cart', 'Commerce cart', 'Catalog and checkout flows'],
            ['payment-router', 'Payment router', 'Processor routing paths'],
            ['seo-growth', 'SEO growth', 'Search and content checks'],
            ['security-shield', 'Security shield', 'Hardening and launch safety'],
            ['speed-tuning', 'Performance', 'Speed and asset discipline'],
            ['website-snapshot-gallery', 'Website Snapshot', 'Recent work and proof images'],
            ['support-ticket', 'Support ticket', 'Help paths and triage'],
            ['ai-image-prompt', 'AI image prompt', 'Starter visuals and prompts'],
            ['mobile-overflow-check', 'Mobile overflow', 'Right-edge clipping checks'],
        ];

        $html = '<section class="h4-icon-preview-section"><div class="h4-icon-preview-section__intro"><p class="h4-product-eyebrow">Branded default set</p><h2>Start with Help4 icons that look intentional.</h2><p>The bundled SVGs are local, reusable, and now styled as Help4-branded defaults instead of plain placeholder glyphs. Existing icon filenames stay the same, so older pages keep loading.</p></div><div class="h4-icon-preview-grid" aria-label="Help4 Builder Suite branded default icon examples">';

        foreach ($icons as $icon) {
            $slug = sanitize_key((string) $icon[0]);
            $file = H4BS_PATH . 'assets/icons/defaults/' . $slug . '.svg';
            if (! is_readable($file)) {
                continue;
            }

            $html .= '<article class="h4-icon-preview-card">'
                . '<img src="' . esc_url(H4BS_URL . 'assets/icons/defaults/' . $slug . '.svg') . '" alt="' . esc_attr((string) $icon[1]) . ' icon" loading="lazy" decoding="async" />'
                . '<h3>' . esc_html((string) $icon[1]) . '</h3>'
                . '<p>' . esc_html((string) $icon[2]) . '</p>'
                . '</article>';
        }

        return $html . '</div></section>';
    }

    private function h4BuilderModuleControlsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Module controls',
            'Turn on the features the site needs and keep the rest quiet.',
            'Builder Suite is large by design, but each site should only enable the modules that match the job so CSS, scripts, admin screens, and workflows stay easier to reason about.',
            [['Goal', 'Only what is needed'], ['Benefit', 'Faster pages'], ['Best check', 'Review before launch']],
            ['settings', 'updates', 'security'],
            'Module discipline',
            'Do not enable everything just because it exists.',
            'A brochure site, catalog, support portal, and landing-page stack need different modules. Keep the enabled set honest.',
            [
                ['Start in Settings', 'Confirm which major systems are currently enabled.'],
                ['Match modules to the site goal', 'Builder, fields, commerce, forms, SEO, security, and performance should each have a reason.'],
                ['Keep unused features quiet', 'Leave modules off when the site does not need their admin pages or frontend assets.'],
                ['Re-check before launch', 'A module used during build may not need to stay active for a simple finished site.'],
                ['Document the choices', 'Leave notes so the next editor knows why the site is configured this way.'],
            ],
            [
                ['Builder and templates', 'Enable for visual editing, starters, global templates, and blank-theme launch work.'],
                ['Fields and commerce', 'Enable when content repeats or product/catalog data needs a real structure.'],
                ['SEO, security, performance', 'Enable for metadata, redirects, readability, SSL, headers, images, and launch checks.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderFieldsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Structured fields',
            'Use fields when normal page text is not enough.',
            'Fields help customers edit repeatable data like team members, service areas, FAQs, galleries, plan features, product specs, locations, and relationships without custom one-off admin screens.',
            [['Use for', 'Repeatable data'], ['Avoid', 'Copy-paste chaos'], ['Output', 'Dynamic sections']],
            ['fields', 'studio', 'templates'],
            'When to use fields',
            'Fields keep complex content clean for the person editing it later.',
            'If the same kind of information appears over and over, structure it instead of asking someone to edit a fragile layout by hand.',
            [
                ['Name the real object', 'Service, location, team member, product spec, FAQ, gallery, plan, or testimonial.'],
                ['Group related fields', 'Keep fields together around the object people understand.'],
                ['Use repeaters for rows', 'FAQs, features, steps, gallery items, and service areas should not be copy-pasted blocks.'],
                ['Validate required values', 'Optional everything creates empty sections and confusing pages.'],
                ['Render through templates', 'Let customers update data while the design stays consistent.'],
            ],
            [
                ['Field groups', 'Use for related content that belongs together.'],
                ['Repeaters', 'Use for lists that grow or shrink.'],
                ['Dynamic output', 'Use Builder templates so data edits do not break design.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderCommerceGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Help4 Commerce',
            'Set up native catalog, variations, subscriptions, and payment routing.',
            'Help4 Commerce is the Builder Suite commerce path for product catalogs, very large product sets, variations, recurring billing, checkout context, and processor routing.',
            [['Catalogs', 'Small to huge'], ['Products', 'Variations supported'], ['Payments', 'Router-ready']],
            ['commerce', 'products', 'seo'],
            'Commerce path',
            'Build commerce around catalog data first, then checkout.',
            'A store only works when product data, variations, subscriptions, checkout routing, emails, support, and order status all agree.',
            [
                ['Choose the product model', 'Simple products, variations, subscriptions, digital goods, service packages, and imports need different defaults.'],
                ['Clean catalog fields', 'Titles, SKUs, descriptions, images, categories, prices, stock, variation labels, and subscription terms must be consistent.'],
                ['Set payment routes', 'Use routing rules when products, subscriptions, regions, or processor fallbacks need different payment paths.'],
                ['Test checkout context', 'Checkout should know product, variation, subscription, customer, price, tax/shipping needs, and return path.'],
                ['Add trust signals', 'Policy links, support links, SSL, security headers, reviews, FAQs, and fulfillment notes reduce confusion.'],
                ['Load-test big catalogs', 'Large stores need import checks, search checks, image checks, cache checks, and admin edit checks.'],
            ],
            [
                ['Catalog first', 'Good commerce starts with product data, not a pretty checkout button.'],
                ['Routing second', 'Payment rules should follow product, subscription, customer, and processor reality.'],
                ['Support always', 'Customers need receipts, statuses, policies, and a clear help path.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderSlidersFormsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Sliders and forms',
            'Add motion and lead capture without making every page heavy.',
            'Use sliders for hero, promo, and proof sections when motion helps the message. Use forms when the next step is a quote, ticket, consult, booking, newsletter, or handoff.',
            [['Slider rule', 'Motion must help'], ['Form rule', 'Ask only what matters'], ['Asset rule', 'Load only when used']],
            ['forms', 'studio', 'settings'],
            'Use carefully',
            'Motion and forms should make the page easier, not louder.',
            'Most customers need one clear action. Sliders and forms should support that action instead of distracting from it.',
            [
                ['Write the goal first', 'Know whether the page needs a quote request, contact form, booking, support request, or newsletter signup.'],
                ['Ask fewer questions', 'Name, email, phone, site URL, and the smallest number of qualifying questions usually wins.'],
                ['Route the form', 'Send leads to the right inbox, ticket queue, or follow-up path and test confirmations.'],
                ['Keep motion readable', 'Use short slide copy, compressed images, reduced-motion respect, and no distracting autoplay.'],
                ['Test the full path', 'Submit the form, read the email, check spam folders, and verify the confirmation message.'],
            ],
            [
                ['Form fields', 'Every field should earn its place.'],
                ['Form routing', 'A lead is only useful if it reaches the right person.'],
                ['Slider performance', 'Motion should not make the page slower or harder to read.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderWebsiteSnapshotGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Website Snapshot',
            'Turn public URLs into website screenshots for proof and support.',
            'Website Snapshot helps show recent work, migration targets, support context, launch checks, and before/after proof without hand-cropping browser images every time.',
            [['Use', 'Public URL screenshots'], ['Blocks', 'Private paths protected'], ['Best pages', 'Recent work and support']],
            ['studio', 'templates', 'security'],
            'Screenshot workflow',
            'Use website screenshots where proof matters.',
            'Recent-work pages, migration audits, support tickets, and launch recaps are easier to understand when the customer can see the actual public page.',
            [
                ['Use a public URL', 'Capture public home, service, portfolio, or article pages. Do not use admin, account, cart, checkout, billing, or payment URLs.'],
                ['Choose the right size', 'Use a wide screenshot for cards and a taller capture for audits or before/after proof.'],
                ['Write a caption', 'Explain what the screenshot proves instead of leaving it as a decorative image.'],
                ['Link carefully', 'Use nofollow/noopener behavior for external proof links when appropriate.'],
                ['Re-capture after launch', 'Refresh screenshots after redesign, migration, or major content changes.'],
            ],
            [
                ['Recent work', 'Show public URLs such as zqcreations.com, migrationmonkey.com, liveandsigned.com, and other portfolio sites.'],
                ['Support context', 'Attach a screenshot so the technician sees the reported page state quickly.'],
                ['Migration audit', 'Compare the current site, target design, and launch result without vague notes.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderLaunchGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'SEO, security, speed',
            'Prepare a page for launch, not just for a pretty screenshot.',
            'A finished page needs helpful metadata, headings, internal links, schema where useful, readable copy, redirects, SSL, headers, optimized images, mobile checks, and fast asset loading.',
            [['SEO', 'Metadata and readability'], ['Security', 'SSL and headers'], ['Speed', 'Images and assets']],
            ['seo', 'security', 'studio'],
            'Launch checklist',
            'Check the boring stuff before customers find the page.',
            'The goal is simple: rankable, readable, secure, fast, and easy to act on.',
            [
                ['Write for humans first', 'Use one clear H1, useful sections, plain answers, and enough copy to explain the offer.'],
                ['Set metadata', 'Title tag, meta description, canonical URL, schema, social image, and internal links should match the page purpose.'],
                ['Check readability', 'Short paragraphs, clear headings, plain labels, and direct calls to action help both customers and quality checks.'],
                ['Check Analytics intent', 'The page should have measurable actions such as calls, forms, checkout clicks, downloads, or support requests.'],
                ['Check AdSense-style quality', 'Avoid thin pages, broken layout, misleading claims, missing contact paths, and useless filler.'],
                ['Harden the page', 'Use SSL, headers, login controls, sane XML-RPC rules, image optimization, lazy loading, and mobile overflow checks.'],
            ],
            [
                ['SEO basics', 'One real H1, helpful title, useful meta description, clean slug, internal links, and real answers.'],
                ['Security basics', 'SSL, headers, login protection, checkout SSL enforcement, and no private URLs in public screenshots.'],
                ['Performance basics', 'Compressed images, lazy-loaded media, limited assets, and mobile proof before launch.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderUpdatesGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Updates and WordPress readiness',
            'Keep live stable while md tests the next WordPress line.',
            'Live should run the current public Builder Suite package. The md track is where Help4 tests upcoming WordPress behavior before core upgrades move to customer sites.',
            [['Live', 'Public package'], ['md', 'Beta testing'], ['Plugin', 'latest.zip']],
            ['updates', 'settings', 'studio'],
            'Upgrade safety',
            'Do not turn customer sites into the test track.',
            'Release candidates and beta behavior belong on md first. Production can move when package, pages, admin screens, and mobile checks pass.',
            [
                ['Check package channel', 'Use /help4-builder-suite/latest.zip for the current public release and manifest checks for updates.'],
                ['Check admin screens', 'Settings, Builder Pages, Studio, templates, fields, forms, commerce, SEO, and security should load cleanly after updates.'],
                ['Check frontend pages', 'Open important pages with cache bypass and look for missing CSS, clipped mobile layout, and broken buttons.'],
                ['Check logs', 'Tail PHP logs after upgrade and fix fresh warnings before calling a package ready.'],
                ['Keep rollback notes', 'Know the prior version, backup path, and package URL before pushing a major change.'],
            ],
            [
                ['Stable channel', 'Use this for live customers and public downloads.'],
                ['Beta track', 'Use md for upcoming WordPress checks and next package testing.'],
                ['After failure', 'Restore, disable the failing module if needed, capture exact errors, and retest from a clean page.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderSafeEditingGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Safe editing and recovery',
            'Change images and layouts without losing the rest of the page.',
            'Use the element inspector for one-element changes, publish deliberately, and use Page Settings > History when a saved layout needs to be reviewed or recovered.',
            [['Edit', 'One element at a time'], ['History', 'Five recovery points'], ['Restore', 'Preview before publish']],
            ['studio', 'builder_pages', 'updates'],
            'Protected workflow',
            'Know what changes now, what remains a draft, and how to recover.',
            'Builder blocks stale sessions and malformed element trees before they overwrite a published layout. Recovery points load as drafts so the public page does not change until you approve it.',
            [
                ['Open the correct page', 'Confirm the page title and public URL in Builder Studio before editing.'],
                ['Select the exact element', 'Use Navigator or the canvas toolbar, then change content in the element inspector instead of replacing whole-page HTML.'],
                ['Replace an image safely', 'Choose the media item, confirm its preview, alt text, and crop, then save the element. Unrelated typography and sibling blocks should remain unchanged.'],
                ['Review responsive views', 'Check monitor, tablet, 390px, and 360px before publishing.'],
                ['Use History when needed', 'Open Page Settings > History and load a verified recovery point as an unsaved draft. Review it before publishing.'],
                ['Stop on a conflict', 'If Builder says the page changed elsewhere, reload and reconcile the newer page instead of forcing the stale tab to save.'],
            ],
            [
                ['Before editing', 'Record the page URL and confirm whether it is draft, staging, or live.'],
                ['Before publishing', 'Check image, fonts, navigation, forms, and right-edge mobile overflow on the real preview.'],
                ['After a problem', 'Do not keep clicking. Capture the screen, page title, plugin version, and exact action that triggered it.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderResponsiveGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Responsive design',
            'Tune spacing, typography, columns, widths, and alignment for every screen.',
            'Builder responsive controls are real per-device values, not only hide/show switches. Start with desktop structure, then deliberately set tablet and phone behavior.',
            [['Views', 'Desktop, tablet, phone'], ['Control', 'Spacing through alignment'], ['Goal', 'Zero horizontal clipping']],
            ['studio', 'builder_pages', 'theme_builder'],
            'Viewport workflow',
            'Responsive design is not shrinking desktop until it fits.',
            'Each breakpoint needs readable type, useful gutters, predictable stacking, touch-friendly controls, and images that stay inside the document.',
            [
                ['Set desktop structure', 'Choose layout mode, columns, widths, gap, alignment, and maximum content width.'],
                ['Tune tablet independently', 'Adjust columns, wrap, padding, heading sizes, CTA gaps, and image behavior at the tablet breakpoint.'],
                ['Build the phone stack', 'Use one-column flow where appropriate and set phone-specific side gutters, text sizes, button widths, and media sizing.'],
                ['Check breakpoint edges', 'Verify 1025, 1024, 861, 860, 768, 767, 390, and 360 pixels so rules do not jump unexpectedly.'],
                ['Find overflow', 'Inspect wide images, tables, embeds, long URLs, fixed widths, negative margins, and unwrapped navigation labels.'],
                ['Verify the public page', 'Studio preview and the real frontend should compute the same spacing, typography, backgrounds, and radius.'],
            ],
            [
                ['No clipping', 'The document width must never exceed the viewport.'],
                ['No overlap', 'Text, buttons, menus, and fixed elements must not cover nearby content.'],
                ['No fake mobile', 'Do not rely on scaling the desktop page down; set intentional device values.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderGlobalStylesGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Global design system',
            'Control colors, typography, spacing, buttons, fields, and theme packs once.',
            'Global settings give the site a reusable visual system. Theme packs can apply styles without replacing the page layout or its content.',
            [['Colors', 'Semantic tokens'], ['Type', 'Display through UI'], ['Packs', 'Style-only application']],
            ['studio', 'templates', 'settings'],
            'Design-system order',
            'Set shared decisions before polishing individual cards.',
            'A global primary-color change should update Builder buttons and registered modules in Studio before save and on public pages after save.',
            [
                ['Name the brand colors', 'Set primary, secondary, accent, surfaces, text, borders, success, warning, danger, and accessible on-color values.'],
                ['Set the type system', 'Choose display, heading, body, and interface families plus weights, sizes, and line heights.'],
                ['Set spacing and shape', 'Define section padding, card gaps, button padding, field height, radii, and shadows.'],
                ['Preview global changes', 'Check buttons, cards, forms, menus, commerce, and addon modules before saving.'],
                ['Apply theme packs carefully', 'Use style-only mode to preserve element IDs, content, parent relationships, and layout order.'],
                ['Override only when necessary', 'Use element-level styling for intentional exceptions, not to rebuild the global system on every block.'],
            ],
            [
                ['Contrast', 'Check text and controls against every surface.'],
                ['Consistency', 'The same semantic role should use the same token across Builder and modules.'],
                ['Preservation', 'A style pack must not replace page content or the saved element graph.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderNavigationGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Navigation and Theme Builder',
            'Build headers, dropdowns, mobile menus, footers, and conditions that stay usable.',
            'Use the WordPress menu hierarchy as the shared source, then assign Builder templates for the global shell and special routes.',
            [['Desktop', 'Hover and keyboard'], ['Mobile', 'Hamburger and touch'], ['Templates', 'Conditions and priority']],
            ['theme_builder', 'studio', 'templates'],
            'Navigation acceptance',
            'A menu is finished only when visitors can reach every item.',
            'Dropdowns must remain open while the pointer moves into the submenu, keyboard focus must be visible, and mobile controls must open and close without clipping.',
            [
                ['Create the menu hierarchy', 'Build parent and child links in WordPress so desktop and mobile navigation use one source.'],
                ['Build the global header', 'Add logo, menu, contact path, and primary action, then assign it to the intended site scope.'],
                ['Test dropdown movement', 'Move from the parent label into every submenu item without the submenu disappearing across the pointer gap.'],
                ['Test keyboard access', 'Tab through triggers and links, open submenus, and confirm visible focus and Escape behavior.'],
                ['Test the mobile menu', 'Verify the hamburger is visible, touch targets work, nested items expand, the panel closes, and body scrolling recovers.'],
                ['Assign footer and exceptions', 'Use include/exclude conditions and priorities for canvas pages, checkout, archives, singles, search, and 404 routes.'],
            ],
            [
                ['Representative routes', 'Check home, normal page, long page, archive, single, checkout, search, and 404.'],
                ['No duplicate shell', 'Only one matching header/footer/template should render per request.'],
                ['No mobile overflow', 'Menu panels and long labels must remain within the viewport.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderCommerceAdvancedGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Advanced Help4 Commerce',
            'Model products, variations, subscriptions, customers, and checkout as one system.',
            'Start with clean catalog and customer data, then connect pricing, inventory, dynamic fields, checkout, processors, orders, and account experiences.',
            [['Catalog', 'Large product ready'], ['Customers', 'Dynamic field rules'], ['Checkout', 'Processor routing']],
            ['commerce', 'products', 'fields'],
            'Commerce build order',
            'Product and customer data come before checkout styling.',
            'Every option shown to a buyer must resolve to a valid product, variation, price, subscription term, inventory state, and payment route on the server.',
            [
                ['Define product types', 'Separate simple, variable, digital, service, subscription, and imported products.'],
                ['Build variation attributes', 'Use consistent attribute names, values, SKUs, prices, images, stock, and availability.'],
                ['Create customer field groups', 'Add account, delivery, qualification, consent, and business fields with conditions and authoritative server validation.'],
                ['Bind dynamic output', 'Use product and customer fields in templates without exposing private values or secrets.'],
                ['Configure payment routes', 'Map products, subscriptions, regions, and fallback processors, then use test credentials.'],
                ['Test the lifecycle', 'Verify cart, checkout, failure recovery, order, receipt, subscription, webhook, refund, customer account, and support paths.'],
            ],
            [
                ['Empty and long data', 'Test missing values, long labels, many variations, and large customer histories.'],
                ['Security', 'Never place processor keys, private customer data, or webhook secrets in page content.'],
                ['Scale', 'Test import, search, filtering, pagination, cache behavior, and admin editing with realistic catalog volume.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderSeoAdvancedGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Advanced SEO and discovery',
            'Configure local, international, social, structured, and fast-indexing signals.',
            'Help4 SEO combines page scoring with indexing health, schema, local entities, social previews, sitemaps, IndexNow, international targeting, and internal-link review.',
            [['Search', 'Google, Bing and more'], ['Local', 'Locations and service areas'], ['IndexNow', 'Queued URL changes']],
            ['seo', 'settings', 'studio'],
            'Search workflow',
            'Use standards-based signals and verify rendered output.',
            'SEO tools report implementation quality; search engines still decide crawling, indexing, display, and ranking.',
            [
                ['Set the real site identity', 'Use the organization or person name, logo, phone, contact URL, sameAs profiles, and default social image.'],
                ['Configure each page', 'Set intent, title, description, canonical, robots, social title/image, schema, keyphrase coverage, readability, and useful internal links.'],
                ['Build local entities', 'Add each location, category, address, phone, coordinates, hours, service areas, map details, and location URL.'],
                ['Add international targeting', 'Use valid hreflang language/region pairs and reciprocal canonical pages only when translated equivalents exist.'],
                ['Enable IndexNow appropriately', 'Use a generated key on a public production site, review queued changes/deletions, retries, and last response, and keep staging guarded.'],
                ['Audit discovery', 'Verify robots, XML sitemap pages and HTTP status, structured data, missing/duplicate metadata, social previews, and orphaned content.'],
            ],
            [
                ['No fake guarantees', 'Do not promise rankings, indexing, ad approval, or social display.'],
                ['No Google sitemap ping', 'Google retired the unauthenticated ping endpoint; use sitemap discovery and verified Search Console.'],
                ['No listing misuse', 'Do not use Google Indexing API for normal real-estate or product inventory.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderMultisiteGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'WordPress multisite',
            'Provision Builder, database, and SEO defaults across a network without leaking site data.',
            'Network Admin provides fleet visibility and bounded actions while each site keeps its own customer records, payment data, verification tokens, IndexNow key, and editable settings.',
            [['Scope', 'Network and site'], ['Data', 'Per-site isolation'], ['Jobs', 'Bounded background work']],
            ['settings', 'updates', 'seo'],
            'Network workflow',
            'Use defaults to assist sites, not overwrite their owners.',
            'Provision one site at a time in bounded background work and keep sensitive values isolated to the site that owns them.',
            [
                ['Network-activate deliberately', 'Confirm the plugin is intended for every site before network activation.'],
                ['Provision site databases', 'Use the network readiness view to create or repair each site table set and version marker.'],
                ['Apply fill-only defaults', 'Use network SEO and Builder defaults only for missing values unless a super administrator explicitly enables narrow enforcement.'],
                ['Review indexing per site', 'Check public status, robots, sitemap, verification, metadata health, and IndexNow independently.'],
                ['Run bounded bulk work', 'Queue selected provisioning and audits rather than doing the whole network in one request.'],
                ['Check mapped domains', 'Verify canonical URLs, robots output, sitemap hosts, SSL, and physical robots.txt conflicts for each domain.'],
            ],
            [
                ['Isolation', 'Never share payment keys, customers, search tokens, or IndexNow keys across sites.'],
                ['Ownership', 'Site administrators keep control unless a documented network policy explicitly enforces a setting.'],
                ['Performance', 'Large network audits must resume in small background steps.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderTroubleshootingGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage(
            'Migration and troubleshooting',
            'Diagnose editor, preview, CSS, media, menu, and migration problems without guessing.',
            'Capture the exact page, action, version, viewport, and error before changing more. Use staging for migration work and verify the public result after every repair.',
            [['First', 'Stop destructive editing'], ['Capture', 'URL, screen and logs'], ['Verify', 'Studio and public']],
            ['studio', 'updates', 'security'],
            'Triage order',
            'Preserve evidence before trying random fixes.',
            'The fastest repair starts with a reproducible action and a known before/after state, not repeated edits on a damaged live page.',
            [
                ['Stop and record', 'Capture the page title, URL, Builder version, WordPress version, viewport, and exact click that caused the problem.'],
                ['Check History', 'Load a verified recovery point as a draft when content or styling changed unexpectedly.'],
                ['Compare Studio and public', 'Check computed spacing, typography, media, menus, forms, and module assets in both contexts.'],
                ['Check source assets', 'Preserve uploaded-media URLs during migration and map old source URLs instead of substituting similar images.'],
                ['Check theme and cache layers', 'Confirm active parent/child theme assets, duplicate stylesheets, page cache, CDN cache, and query/cookie bypass behavior.'],
                ['Escalate with evidence', 'Send the screenshot, route, element label, browser console, fresh PHP log lines, and whether the issue reproduces on a clean draft.'],
            ],
            [
                ['Editor crash', 'Do not keep deleting or adding blocks; reload only after recording the last safe state.'],
                ['Missing styles', 'Verify Builder assets and addon module handles load on singular, archive, search, and 404 templates.'],
                ['Media operations', 'Confirm WordPress temporary storage is writable before imports or large media changes.'],
            ],
            $ticketUrl
        );
    }

    private function h4BuilderLivePreviewGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Builder Studio live preview', 'See the page change before you publish it.', 'Studio keeps the element inspector, layout tree, and isolated frontend preview connected so content and design changes can be reviewed in context.', [['Preview', 'Unsaved draft'], ['Views', 'Desktop through phone'], ['Publish', 'Explicit save']], ['studio', 'builder_pages', 'updates'], 'Preview workflow', 'Treat the preview as the page under test.', 'Select one element, change one control, and verify the visible result before moving to the next decision.', [
            ['Confirm the editing target', 'Check the page or template title, public route, and element count before changing anything.'],
            ['Select one element', 'Use the canvas or Navigator and confirm the inspector heading matches the visible element.'],
            ['Change one control', 'Edit content, color, type, spacing, media, or layout and watch the preview update without publishing.'],
            ['Change viewports', 'Review desktop, tablet, 390px, and 360px; device-specific values should appear only at their intended breakpoint.'],
            ['Refresh suspicious previews', 'If a shortcode, form, checkout, video, or addon does not initialize, refresh the isolated preview and compare its loaded assets with public output.'],
            ['Publish deliberately', 'Save only after the draft preview, Navigator structure, responsive views, and public parity check agree.'],
        ], [['Preview is not public', 'Unsaved changes stay in Studio until an authorized editor publishes.'], ['Scripts matter', 'Interactive modules need their normal styles and scripts, not an HTML-only approximation.'], ['Conflict means stop', 'Reload and reconcile when a newer page revision exists.']], $ticketUrl);
    }

    private function h4BuilderMediaGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Images and media', 'Replace an image without deleting the page around it.', 'Edit the selected image field, preserve the element tree, add useful alternative text, and verify crop and loading behavior at every viewport.', [['Select', 'Exact image widget'], ['Protect', 'Sibling content'], ['Optimize', 'Size and alt text']], ['studio', 'builder_pages', 'settings'], 'Media workflow', 'Choose the right file and preserve the right structure.', 'An image replacement should change the media reference and its intentional settings, not reset fonts, remove HTML, or rewrite neighboring elements.', [
            ['Select the image element', 'Click the visible image in Live Preview. Use Navigator only when overlapping media, background layers, or containers prevent selecting the image itself.'],
            ['Handle migrated HTML pages', 'When Navigator shows one HTML Block, click the visible image and use Quick edit what you clicked. Replace Image changes that mapped source without deleting the surrounding page.'],
            ['Choose or upload media', 'Use the WordPress media library and confirm the selected attachment, dimensions, format, and ownership.'],
            ['Write useful alt text', 'Describe the image purpose when it conveys content; leave decorative images empty instead of stuffing keywords.'],
            ['Set fit and focal point', 'Choose contain or cover, position the subject, and check desktop, tablet, and phone crops.'],
            ['Use an appropriate source size', 'Avoid tiny source files for large heroes and avoid serving an enormous original inside a small card.'],
            ['Verify after save', 'Confirm the public image URL, lazy/eager loading choice, width, height, layout stability, and sibling content.'],
        ], [
            ['Hero, banner and slider', 'Start at 1920 x 1080 px (16:9), keep the important subject inside the center safe area, and target 350 KB or less.'],
            ['Social sharing', 'Use 1200 x 630 px (1.91:1) so link previews have a predictable branded crop across major social and messaging apps.'],
            ['Portrait and staff photo', 'Use 1200 x 1500 px (4:5), leave breathing room around the face, and set focal position per device when the card crops the image.'],
            ['Product and gallery', 'Use 1600 x 1600 px (1:1) for product images and 1600 x 1200 px (4:3) for general galleries; keep every image in one gallery at a consistent ratio.'],
            ['Event and program artwork', 'Use 1600 x 900 px (16:9) for landscape cards unless the component explicitly calls for portrait artwork.'],
            ['Logo and site icon', 'Use a trusted SVG or transparent WebP/PNG logo at least 512 px wide. Site icons must be a square 512 x 512 px source.'],
            ['Email and screenshots', 'Use 1200 x 628 px for campaign images and at least 1600 x 900 px for website screenshots; keep important text legible on a phone.'],
            ['Target shape first', 'Match the aspect ratio of the actual image block before choosing dimensions. Use the confirmed asset contract rather than guessing landscape or portrait pixels.'],
            ['File format', 'Use WebP for most photos and illustrations, PNG for needed transparency, and SVG only for trusted vector assets.'],
            ['Hero images', 'Use a stable aspect ratio and eager loading only when the image is truly the primary above-fold visual.'],
            ['External media', 'Preserve approved source URLs during migration and never expose private asset URLs.'],
        ], $ticketUrl);
    }

    private function h4BuilderDesignControlsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Design controls', 'Control buttons, typography, spacing, color, and shape without fighting the editor.', 'Use global tokens for shared decisions and element controls for intentional exceptions. Every responsive value should update the preview where it is edited.', [['Buttons', 'Padding and states'], ['Type', 'Size and line height'], ['Spacing', 'Margin, padding and gap']], ['studio', 'settings', 'templates'], 'Control order', 'Style from the system outward.', 'Set global brand rules first, then layout spacing, then component appearance, and finally responsive exceptions.', [
            ['Choose the semantic token', 'Use primary, accent, surface, text, border, success, warning, or danger rather than repeating unrelated hex values.'],
            ['Set typography', 'Choose family, weight, size, line height, alignment, and text decoration; check long words and real content.'],
            ['Set button dimensions', 'Control horizontal/vertical padding, width mode, radius, border, icon gap, and hover/focus/disabled states.'],
            ['Set layout spacing', 'Use container gap for siblings, padding for interior space, and margin only for intentional exterior separation.'],
            ['Set responsive values', 'Adjust phone type, button width, section gutters, and stacking without changing desktop.'],
            ['Test interaction states', 'Keyboard focus, hover, active, disabled, loading, and long labels must remain readable and stable.'],
        ], [['No mystery overrides', 'Check globals and inherited device values before adding custom CSS.'], ['No viewport font scaling', 'Use deliberate breakpoint sizes rather than viewport-width font formulas.'], ['No clipped labels', 'Allow wrapping or flexible width when translated or long text is used.']], $ticketUrl);
    }

    private function h4BuilderDynamicDataGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Dynamic data', 'Build one template that safely displays many records.', 'Connect Builder widgets to WordPress content, Help4 fields, taxonomies, authors, site information, commerce products, variants, and repeaters through validated sources.', [['Sources', 'Posts through products'], ['Fields', 'Groups and repeaters'], ['Fallbacks', 'Empty-state ready']], ['fields', 'studio', 'products'], 'Binding workflow', 'Model the data before designing its output.', 'A dynamic template is reliable when its source, allowed fields, fallbacks, escaping, and empty states are clear.', [
            ['Define the content model', 'Create named field groups for the post type, product, location, team member, event, or other record.'],
            ['Choose the source', 'Select current post, related record, taxonomy, author, site value, product, variant, or approved custom source.'],
            ['Bind a widget value', 'Connect text, image, URL, price, list, or condition to one validated field.'],
            ['Add fallbacks', 'Decide whether missing data hides the widget, uses a default, or displays a clear empty state.'],
            ['Render repeaters safely', 'Use bounded item counts, predictable child templates, and no private fields in public output.'],
            ['Test multiple records', 'Review empty, normal, long, multilingual, private, and high-item-count examples before assigning the template broadly.'],
        ], [['Privacy', 'Private options, customer data, request values, credentials, and secrets remain denied by default.'], ['Escaping', 'URLs, HTML, attributes, numbers, and text need context-appropriate output.'], ['Performance', 'Avoid unbounded relationship or repeater queries on archive pages.']], $ticketUrl);
    }

    private function h4BuilderFormsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Forms and lead capture', 'Build forms people can finish and your team can actually receive.', 'Configure fields, validation, consent, actions, delivery, spam controls, success states, and mobile behavior as one complete workflow.', [['Fields', 'Accessible inputs'], ['Actions', 'Delivery and webhooks'], ['Proof', 'End-to-end test']], ['forms', 'studio', 'settings'], 'Form workflow', 'A form is not done when it looks correct.', 'The submission must validate on the server, reach the intended destination, protect private data, and give the visitor a clear result.', [
            ['Choose the form goal', 'Use only fields needed to answer, qualify, quote, register, or support the visitor.'],
            ['Build accessible fields', 'Add visible labels, useful instructions, correct input types, autocomplete, required state, and understandable errors.'],
            ['Configure consent', 'Use explicit consent when collecting marketing permission or sending data to an external service.'],
            ['Choose actions', 'Configure email, storage, webhook, redirect, CRM, or other approved actions and document what data each receives.'],
            ['Harden submission', 'Use nonce, capability where appropriate, sanitization, rate limits, spam controls, and protected secrets.'],
            ['Test delivery', 'Submit valid, invalid, duplicate, spam-like, mobile, slow-network, and attachment cases; check inbox, spam, logs, and success behavior.'],
        ], [['Email reality', 'Tell users replies may arrive from help4network.com or help4.us and to check filtered folders.'], ['No secret fields', 'Do not collect passwords, payment keys, or authentication codes in a normal contact form.'], ['Failure state', 'Preserve entered non-sensitive values and explain how to retry.']], $ticketUrl);
    }

    private function h4BuilderMotionGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Motion and sliders', 'Use animation to explain hierarchy, not distract from the page.', 'Build layered sliders and element motion with responsive timing, controls, readable static states, and reduced-motion behavior.', [['Motion', 'Duration and easing'], ['Slider', 'Layers and controls'], ['Access', 'Reduced-motion ready']], ['studio', 'templates', 'settings'], 'Motion workflow', 'Design the still frame first.', 'Content and calls to action must remain understandable before autoplay, transitions, or scroll effects are enabled.', [
            ['Build the static composition', 'Set content, hierarchy, contrast, crop, spacing, and responsive layout before motion.'],
            ['Choose the trigger', 'Use load, viewport, hover, click, or slide change only when the interaction is predictable.'],
            ['Set timing', 'Configure duration, delay, easing, direction, iteration, and sequencing without making the interface feel blocked.'],
            ['Add slider controls', 'Provide visible previous/next controls, meaningful pagination, keyboard support, pause behavior, and touch gestures.'],
            ['Set per-device behavior', 'Simplify layers, movement, and autoplay on smaller screens when needed.'],
            ['Respect reduced motion', 'Disable nonessential movement and expose the same content and actions when prefers-reduced-motion is enabled.'],
        ], [['Avoid layout shift', 'Reserve dimensions before media and animated layers load.'], ['Avoid trapped focus', 'Hidden slides must not expose unreachable keyboard controls.'], ['Avoid endless autoplay', 'Give visitors control and pause when the page or component is not active.']], $ticketUrl);
    }

    private function h4BuilderImportExportGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Import, export and migration', 'Move the design without losing the site behind it.', 'Migrate layouts, tokens, templates, menus, fields, and media with explicit mapping and preservation checks instead of rebuilding blindly.', [['Export', 'Versioned data'], ['Map', 'URLs and sources'], ['Verify', 'Structure and output']], ['templates', 'studio', 'updates'], 'Migration workflow', 'Preserve structure before polishing the destination.', 'A successful migration keeps content, IDs, relationships, media ownership, URLs, responsive intent, and public behavior understandable.', [
            ['Inventory the source', 'Record pages, templates, menus, custom fields, post types, forms, shortcodes, media URLs, redirects, and third-party dependencies.'],
            ['Export versioned data', 'Keep layout schema, global tokens, theme packs, template conditions, and namespaced extension data together.'],
            ['Map media and links', 'Preserve uploaded-media URLs when valid and explicitly map old source URLs, internal links, and canonical destinations.'],
            ['Choose import mode', 'Use style-only for tokens, append for selected sections, and replacement only after confirming the target layout may be replaced.'],
            ['Check structure', 'Compare ordered element IDs, parent graph, content hashes, template assignments, and full-width/canvas settings before and after.'],
            ['Run acceptance', 'Verify public and Studio styles, responsive widths, menus, forms, dynamic data, shortcodes, SEO, redirects, and logs.'],
        ], [['Back up once', 'Keep a bounded recovery package and avoid filling the server with repeated archive copies.'], ['No visual substitutions', 'Do not replace source media with merely similar images during migration.'], ['No silent loss', 'Unknown namespaced extension data should survive a round trip.']], $ticketUrl);
    }

    private function h4BuilderNavigatorGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Navigator and layers', 'Understand the page tree before moving or deleting anything.', 'Navigator shows the hierarchy of sections, containers, columns, and widgets so complex pages can be edited without selecting the wrong layer.', [['Tree', 'Parent and child'], ['Actions', 'Rename through delete'], ['Safety', 'Descendant aware']], ['studio', 'builder_pages', 'templates'], 'Navigator workflow', 'Use names and hierarchy to make complex pages predictable.', 'A useful layer name explains the page job, while valid parent relationships prevent missing or duplicated content.', [
            ['Open Navigator', 'Use the Studio toolbar and close it with its close control or Escape when finished.'],
            ['Rename important layers', 'Use names such as Hero, Proof Grid, Pricing CTA, Contact Form, or Mobile Menu instead of repeated generic labels.'],
            ['Expand the tree', 'Confirm which widgets belong to each section, container, column, tab, slide, or reusable block.'],
            ['Reorder carefully', 'Move one branch, confirm its new parent and slot, then review the preview before moving another.'],
            ['Duplicate intentionally', 'Rename the copy immediately and replace duplicate IDs or content through the supported Builder action.'],
            ['Delete a branch safely', 'Confirm the selected parent and all descendants; undo or use History when the wrong branch was removed.'],
        ], [['No dangling children', 'Every non-root element needs a valid parent.'], ['No duplicate IDs', 'Each element ID must remain unique after duplicate, import, or recovery.'], ['No accidental page reset', 'Deleting one HTML or image widget must never clear unrelated page elements.']], $ticketUrl);
    }

    private function h4BuilderPublishGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Save and publish', 'Know exactly when a Builder change becomes public.', 'Builder Studio separates unsaved control changes, the isolated draft preview, element publishing, and public verification so editors can work quickly without guessing what visitors see.', [['Edit', 'Local control state'], ['Preview', 'Unsaved draft'], ['Publish', 'Saved page revision']], ['studio', 'builder_pages', 'updates'], 'Publishing workflow', 'Move from one verified state to the next.', 'The safest workflow confirms the target, changes one element, reviews responsive output, publishes once, and verifies the public URL before continuing.', [
            ['Confirm the target', 'Read the page or template title, element count, layout mode, and public route before selecting a widget.'],
            ['Edit one element', 'Change content or design in the inspector and confirm the same selected element changes in the live preview.'],
            ['Use Save Element & Publish', 'Commit the selected element and page layout together; wait for the success state before closing Studio.'],
            ['Handle revision conflicts', 'If another editor or tab saved a newer revision, stop and reconcile instead of overwriting it.'],
            ['Check responsive output', 'Review desktop, tablet, 390px, and 360px after publishing, including hover, focus, menus, forms, and media crops.'],
            ['Verify the public route', 'Open a clean public request, confirm the new content and asset version, and use History if the published result is wrong.'],
        ], [['Draft is not public', 'Inspector edits and isolated preview state remain private until the authorized publish request succeeds.'], ['One success message', 'Do not click publish repeatedly while a request is running.'], ['History is recovery', 'Load a verified snapshot as a draft, inspect it, then publish intentionally.']], $ticketUrl);
    }

    private function h4BuilderTemplateConditionsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Template conditions', 'Put each header, footer, archive, single, search, and 404 layout in the right place.', 'Theme Builder conditions combine a template role, request scope, content type, include or exclude rules, and priority. A narrow rule should win intentionally, not by accident.', [['Role', 'Header through 404'], ['Scope', 'Site or request type'], ['Priority', 'Explicit conflict order']], ['theme_builder', 'studio', 'builder_pages'], 'Condition workflow', 'Start broad, then add deliberate exceptions.', 'Use one normal site shell, add only the exceptions the design requires, and test a representative route for every rule.', [
            ['Choose the role', 'Select header, footer, single, archive, search, 404, canvas page, popup, or reusable section based on the output job.'],
            ['Choose the scope', 'Use entire site only for true defaults; use singular, archive, search, 404, or content-type scope for targeted templates.'],
            ['Add includes', 'Limit the template to approved post types, records, taxonomies, or routes when the scope is still too broad.'],
            ['Add exclusions', 'Remove checkout, landing pages, protected content, or other intentional exceptions from a broad assignment.'],
            ['Resolve priority', 'Give the narrower valid rule a higher priority and avoid equal-priority overlaps that are hard to explain.'],
            ['Test the matrix', 'Check home, normal page, post, custom post, archive, search, 404, checkout, logged-in state, and mobile navigation.'],
        ], [['No duplicate shell', 'A request should render one winning header, footer, and content template.'], ['Assets follow assignment', 'Assigned archive, search, and 404 templates need the same Builder assets as singular output.'], ['Studio uses template layout', 'Editing a template must preview its own saved or draft layout, not the front page.']], $ticketUrl);
    }

    private function h4BuilderReusableSectionsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Reusable sections', 'Reuse a design without accidentally changing the whole site.', 'Choose whether a section should be copied, linked as reusable content, or assigned globally. The choice determines whether later edits affect one page or every placement.', [['Copy', 'Independent instance'], ['Reusable', 'Shared content'], ['Global', 'Condition assigned']], ['templates', 'theme_builder', 'studio'], 'Reuse workflow', 'Match the sharing model to the maintenance promise.', 'A global emergency banner should update everywhere; a copied service call to action should remain editable for one page.', [
            ['Name the page job', 'Use names such as Global Support CTA, Realtor Proof Band, Course Signup Form, or Product Warranty Block.'],
            ['Choose copy or shared', 'Copy when the destination needs independent edits; use reusable when content and design must stay synchronized.'],
            ['Choose global assignment', 'Use Theme Builder conditions only when the section belongs on every matching request.'],
            ['Preserve dynamic context', 'Bind current post, product, location, course, or customer-safe values through validated dynamic sources.'],
            ['Edit with impact visible', 'Show where a reusable or global item is assigned before an editor publishes a change.'],
            ['Test representative pages', 'Verify a normal placement, a long-content placement, mobile stacking, empty dynamic data, and every exclusion.'],
        ], [['Avoid hidden blast radius', 'Editors should know whether a change affects one instance or every placement.'], ['Keep IDs valid', 'Copy and import operations must create unique element IDs while preserving valid parent relationships.'], ['Keep fallbacks useful', 'Shared dynamic sections need an intentional empty state when a record lacks data.']], $ticketUrl);
    }

    private function h4BuilderCommerceLaunchGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Commerce launch testing', 'Prove the complete order lifecycle before accepting live money.', 'A storefront is ready only when catalog choices, customer fields, totals, payment routing, order state, communication, fulfillment, refunds, and renewals agree.', [['Catalog', 'Product through variant'], ['Checkout', 'Totals and payment'], ['After sale', 'Order through refund']], ['commerce', 'products', 'forms', 'security'], 'Launch matrix', 'Test outcomes, not just buttons.', 'Use test credentials and documented cases first, then run a bounded live transaction and refund after every production credential or webhook change.', [
            ['Build catalog cases', 'Test simple, variable, subscription, sale, out-of-stock, high-price, zero-price, digital, and large-catalog product paths that the store uses.'],
            ['Test customer fields', 'Verify required, optional, conditional, repeatable, private, account, guest, confirmation, and invalid-value behavior.'],
            ['Verify totals', 'Check quantity, variation price, promotion, tax, shipping, currency rounding, recurring totals, and displayed versus charged amount.'],
            ['Test payment outcomes', 'Run success, decline, authentication, timeout, retry, duplicate click, processor failover, and mixed-cart routing.'],
            ['Verify asynchronous events', 'Test signed webhook success, duplicate delivery, out-of-order delivery, delayed delivery, and rejected signatures.'],
            ['Complete the lifecycle', 'Verify order state, inventory, email, customer account, fulfillment, renewal, cancellation, partial/full refund, and reporting.'],
            ['Repeat on mobile', 'Complete checkout at 390px and 360px with keyboard open, long labels, validation errors, and no horizontal clipping.'],
        ], [['Never expose secrets', 'Store processor credentials through protected settings and redact them from tickets, logs, exports, and page content.'], ['Idempotency matters', 'Retries and duplicate webhooks must not create duplicate charges, orders, renewals, or refunds.'], ['Keep evidence', 'Record the test case, order ID, processor event, expected result, actual result, and cleanup action.']], $ticketUrl);
    }

    private function h4BuilderSalesHomepageGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Sales homepage', 'Build the page customers need, not a pile of decorative boxes.', 'A strong homepage names the offer, shows who it helps, proves the work, explains the next step, and stays easy to scan on a phone.', [['Offer', 'Clear first viewport'], ['Bands', 'Open page sections'], ['Action', 'One primary path']], ['templates', 'studio', 'seo'], 'Homepage workflow', 'Give every section one job.', 'Use full-width open bands with a constrained inner container. Reserve cards for repeated items such as plans, testimonials, services, or case studies.', [
            ['Define the offer', 'Write the literal service or product, starting price when useful, target customer, primary outcome, and one clear call to action.'],
            ['Build the first viewport', 'Place the exact brand, concise headline, supporting copy, primary action, and real product or work proof above the fold while leaving the next section visible.'],
            ['Add proof', 'Use recognizable outcomes, recent work, reviews, credentials, response expectations, or supported customer types instead of vague claims.'],
            ['Explain services', 'Group services by the customer problem they solve and link each important topic to a focused page.'],
            ['Compare packages', 'Show meaningful differences, recurring versus one-time cost, limitations, support level, and the next action without hiding required facts.'],
            ['Answer objections', 'Use a visible FAQ section for setup, ownership, billing, support, migration, cancellation, and what the customer must provide.'],
            ['Finish the path', 'Repeat the primary action, add contact and support routes, verify metadata/social preview, and test desktop through 360px.'],
        ], [['No nested cards', 'Keep page sections open and use cards only for repeated comparable items.'], ['No mystery action', 'Buttons should say what happens next and point to a real route.'], ['No mobile shove', 'Long words, tables, media, and buttons must not create horizontal overflow.']], $ticketUrl);
    }

    private function h4BuilderPricingComparisonGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Pricing comparison', 'Compare five packages without making phone users decode a spreadsheet.', 'Use semantic plan names, consistent feature rows, visible price terms, and a responsive transformation that keeps every label attached to its value.', [['Plans', 'One through five'], ['Rows', 'Feature-by-feature'], ['Mobile', 'Stacked and labeled']], ['templates', 'studio', 'commerce'], 'Pricing workflow', 'Make differences easy to understand and hard to misread.', 'A comparison should help someone choose. Do not fill cells with vague checkmarks when the actual limit, service level, or billing term matters.', [
            ['Name each plan', 'Use names tied to customer fit and add a short best-for line instead of unexplained tier labels.'],
            ['State the price honestly', 'Show currency, billing interval, setup fees, usage limits, renewal behavior, taxes, and whether checkout begins immediately.'],
            ['Choose comparison rows', 'Compare the decisions customers ask about: sites, storage, traffic, products, edits, support, security, backups, migrations, SEO, and response time.'],
            ['Use accessible markup', 'Keep plan headers and feature labels programmatically associated with their values; do not communicate availability by color alone.'],
            ['Transform for mobile', 'At tablet and phone widths, use labeled plan sections, a controlled horizontal comparison, or a plan selector rather than five compressed columns.'],
            ['Connect the action', 'Give each plan a distinct destination and preserve the selected plan through checkout or contact handoff.'],
            ['Test edge content', 'Use the longest plan name, translated labels, large prices, unavailable features, footnotes, and 360px width.'],
        ], [['Avoid fake savings', 'Only show crossed-out prices or savings when the comparison is accurate and supportable.'], ['Explain symbols', 'Use text such as Included, Not included, Up to 10, or Custom instead of unexplained icons.'], ['Keep rows aligned', 'Dynamic content and wrapped labels must not detach a value from its feature.']], $ticketUrl);
    }

    private function h4BuilderFaqGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('FAQ accordion and schema', 'Answer real questions with controls everyone can operate.', 'An FAQ accordion needs visible questions, readable answers, keyboard behavior, stable expanded state, and schema that matches exactly what visitors can read.', [['Control', 'Button disclosure'], ['Access', 'Keyboard and screen reader'], ['Schema', 'Visible answers only']], ['studio', 'seo', 'templates'], 'FAQ workflow', 'Write the answer first, then add disclosure behavior.', 'FAQ content should remove a buying or support obstacle. It should not exist only to manufacture keywords or structured data.', [
            ['Collect real questions', 'Use sales, support, onboarding, billing, migration, product, and search queries rather than invented keyword variations.'],
            ['Write direct answers', 'Lead with the answer, add necessary limits or steps, and link to a deeper guide when the full explanation is long.'],
            ['Use disclosure buttons', 'Each question trigger needs a unique accessible name, expanded state, and connection to its answer region.'],
            ['Support keyboard use', 'Tab reaches every trigger, Enter and Space toggle it, focus remains predictable, and no answer becomes a keyboard trap.'],
            ['Choose initial state', 'Keep important first answers open when useful and preserve readability when scripts fail.'],
            ['Emit matching schema', 'Generate one FAQPage graph from the visible question/answer set and avoid duplicating output from another SEO plugin.'],
            ['Test responsive content', 'Check long questions, links, lists, phone numbers, translated text, reduced motion, and 360px width.'],
        ], [['No hidden schema copy', 'Structured answers must match content a visitor can access on the page.'], ['No heading abuse', 'Use a logical page heading structure around the accordion without turning every trigger into an oversized heading.'], ['No animation dependency', 'Reduced-motion and script-failure states must preserve the content.']], $ticketUrl);
    }

    private function h4BuilderSiteChromeGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Header and footer launch', 'Finish the shared site shell before activating the blank theme.', 'Build reusable header and footer templates with the exact logo, real WordPress menu hierarchy, dependable dropdowns, mobile controls, contact routes, and legal information.', [['Header', 'Brand and navigation'], ['Footer', 'Contact and legal'], ['Conditions', 'Entire site plus exclusions']], ['theme_builder', 'studio', 'templates'], 'Site shell workflow', 'Treat shared chrome as a product, not leftover decoration.', 'The header and footer frame every normal request. A small mistake there repeats across the entire site, so assignments and responsive behavior need their own launch matrix.', [
            ['Preserve the exact logo', 'Use the approved media attachment and intrinsic proportions; do not regenerate, recolor, crop, or substitute a visually similar mark.'],
            ['Build native navigation', 'Use WordPress parent/child menu hierarchy so desktop dropdowns, keyboard focus, and the mobile menu share one source.'],
            ['Fix the pointer path', 'Keep the submenu open while a pointer moves from its parent trigger into the dropdown and close only after focus/pointer truly leaves.'],
            ['Build mobile controls', 'Provide one visible hamburger button, expanded state, close action, focus behavior, readable panel width, and no page overflow.'],
            ['Complete the footer', 'Add organization name, contact/support route, important services, privacy, terms, accessibility, social profiles, and an automatic year or year range.'],
            ['Assign conditions', 'Use entire-site defaults with explicit canvas, checkout, protected, or campaign exclusions and resolve overlaps through priority.'],
            ['Run the route matrix', 'Check home, page, post, custom post, archive, search, 404, checkout, logged-in state, desktop keyboard, touch, 390px, and 360px.'],
        ], [['No duplicate shell', 'Every request should receive one winning header and footer.'], ['No inaccessible dropdown', 'Hover, focus, keyboard, and touch users need a stable path into every submenu.'], ['No hard-coded customer brand', 'Distributed Help4 Blank starts neutral; site-specific logos and contact details belong to the site configuration.']], $ticketUrl);
    }

    private function h4BuilderSectionsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Page structure', 'Build sections, containers, and columns that stay understandable at every viewport.', 'A dependable Builder page has a simple parent tree: full-width sections define the visual bands, containers control readable content width, and columns place related elements without applying the same width twice.', [['Section', 'Full-width page band'], ['Container', 'Constrained content'], ['Columns', 'Grid or flex children']], ['studio', 'templates', 'builder_pages'], 'Structure workflow', 'Build the page skeleton before styling individual widgets.', 'Use Navigator while building so every child has the intended parent and slot, then set responsive values at the structure level before fixing individual elements.', [
            ['Add the outer section', 'Insert one Section for each meaningful page band, give it a clear Navigator name, and choose the background and vertical spacing for that band.'],
            ['Add a content container', 'Place a Container inside the section when text and controls need a readable maximum width; use full width only when the design truly reaches the viewport edge.'],
            ['Choose grid or flex', 'Use Grid for defined columns and consistent tracks. Use Flex for directional rows, wrapping groups, alignment, and content-sized items.'],
            ['Set columns and ratios', 'Choose the occupied column count, then set intentional ratios. Grid children fill their track; the track owns the width and the gap remains inside the available container.'],
            ['Place children by parent and slot', 'Select the correct parent before inserting headings, text, media, buttons, forms, or nested containers; verify the result in Navigator.'],
            ['Set breakpoint values', 'Adjust columns, direction, wrap, gap, padding, min height, width mode, and alignment independently for desktop, tablet, and mobile.'],
            ['Check the boundaries', 'Preview 1025, 1024, 768, 767, 390, and 360 pixels so a breakpoint change never squeezes content or creates horizontal overflow.'],
        ], [['One width owner', 'A grid track owns its child width; avoid percentage-squaring a child inside an already-sized track.'], ['Valid tree', 'Every nested element has one existing parent, a valid slot, and a unique ID.'], ['Content order', 'Mobile visual and accessibility order should match the reading and action sequence.']], $ticketUrl);
    }

    private function h4BuilderSiteKitsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Site kits', 'Start from a complete site system without overwriting the site you already have.', 'Help4 site kits create reviewable draft pages, draft templates, and kit-owned navigation. Applying style tokens is a separate choice, and no kit should publish content or replace the front page automatically.', [['Import', 'Draft-only objects'], ['Styles', 'Optional token layer'], ['Launch', 'Page-by-page review']], ['templates', 'theme_builder', 'studio'], 'Site kit workflow', 'Import, inspect, personalize, then publish intentionally.', 'A kit provides structure and inspiration. The site owner still controls the logo, offer, content, media, menus, assignments, metadata, forms, and launch order.', [
            ['Open Site Kits', 'In Builder Studio, open the Site Kits tab and choose a kit that matches the website job rather than choosing only by color.'],
            ['Choose the style option', 'Leave Apply style tokens off when the current global design must remain. Turn it on only when the kit palette, typography, spacing, and shape should become the new starting system.'],
            ['Import as drafts', 'Run the kit import once and wait for the completion report. Confirm the created page, template, and menu IDs before editing anything.'],
            ['Review the shared shell', 'Open the draft header, footer, 404, archive, and other templates; replace placeholder branding and confirm every condition before publication.'],
            ['Personalize each page', 'Replace sample copy, links, images, forms, proof, prices, contact routes, and dynamic sources while preserving the valid element tree.'],
            ['Set navigation deliberately', 'Review the kit-owned menu, parent and child hierarchy, mobile trigger, destinations, and any pages that should remain outside primary navigation.'],
            ['Launch in a controlled order', 'Publish the shared shell and approved pages, set the front page only after verification, then test metadata, forms, menus, 404, desktop, tablet, and mobile.'],
        ], [['No silent replacement', 'Existing pages, templates, menus, globals, and front-page settings stay unchanged unless the user explicitly applies that change.'], ['Idempotent import', 'A repeated import recognizes kit-owned objects instead of creating duplicate pages and menu items.'], ['No placeholder launch', 'Sample logos, contact details, links, prices, and images are removed before publication.']], $ticketUrl);
    }

    private function h4BuilderWidgetsGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Widget library', 'Find the right Builder element and configure it without losing the page around it.', 'The Elements tab contains native page building blocks. The Widgets tab adds task-focused modules for content, navigation, forms, commerce, SEO, media, and registered addons while keeping the same Content, Design, and Advanced editing model.', [['Search', 'Find by page job'], ['Configure', 'Content, Design, Advanced'], ['Verify', 'Preview and public output']], ['studio', 'commerce', 'forms', 'seo'], 'Widget workflow', 'Choose the smallest component that completes the job.', 'A purpose-built widget should expose its real settings, load its own assets only when used, inherit global tokens, and preserve addon extension data through save and reload.', [
            ['Search by outcome', 'Search for the job such as menu, form, product, cart, reviews, FAQ, video, gallery, or dynamic content instead of browsing every module.'],
            ['Inspect the source', 'Read the widget name and category, then confirm whether it is native Builder functionality or a registered addon module with its own data requirements.'],
            ['Insert into the correct parent', 'Select the intended section, container, or column first, then click or drag the widget and confirm its new layer in Navigator.'],
            ['Complete Content settings', 'Set the actual text, media, data source, links, product context, labels, empty state, and accessibility information before decorative styling.'],
            ['Complete Design settings', 'Set typography, colors, spacing, width, states, and independent responsive values while watching the same element in Live Preview.'],
            ['Complete Advanced settings', 'Add a useful Navigator label, stable anchor or class only when needed, visibility rules, attributes, and accessible motion behavior.'],
            ['Test the real state matrix', 'Check empty and populated data, logged-out and allowed user states, keyboard use, reduced motion, slow or failed media, 390px, 360px, and the public page after publish.'],
        ], [['Keep extension data', 'Unknown namespaced addon settings survive edit, save, export, import, and preview normalization.'], ['Avoid global asset bloat', 'A widget loads its required assets on pages that use it instead of adding every module stylesheet and script sitewide.'], ['Keep empty states intentional', 'Counts, carts, customer fields, products, and dynamic modules explain or hide empty data according to their configured behavior.']], $ticketUrl);
    }

    private function h4BuilderVideoGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Video and HLS', 'Build dependable video and background heroes with a complete fallback path.', 'Help4 video controls support an HLS stream or direct media source, browser-compatible fallbacks, a poster, a separate failure image, playback behavior, responsive focal positioning, and overlaid Builder content without raw HTML.', [['Primary', 'HLS or direct video'], ['Fallback', 'MP4, WebM, poster, image'], ['Responsive', 'Cover and focal point']], ['studio', 'templates', 'settings'], 'Video workflow', 'Plan the failure state before turning on autoplay.', 'The visitor should still understand and use the page when a stream is unsupported, slow, blocked by autoplay policy, unavailable, or intentionally reduced for accessibility.', [
            ['Choose foreground or background', 'Use a Video element for meaningful media with controls and accessible context. Use section or container background video only when headings, text, and buttons remain normal editable children above it.'],
            ['Set the primary source', 'Add the validated HLS manifest when adaptive streaming is available, or use a supported direct video URL for simple delivery.'],
            ['Add browser fallbacks', 'Provide MP4, M4V, WebM, or Ogg sources in the supported fields so playback can continue when HLS is unavailable.'],
            ['Set poster and failure image', 'Use a correctly sized poster for the first frame and loading state, then set a separate failure image that preserves contrast and the page message if every source fails.'],
            ['Configure playback', 'Autoplay requires mute; choose loop, controls, preload, and inline playback based on whether the media is decorative or user-requested.'],
            ['Compose the hero', 'Set cover or contain, overflow clipping, overlay color or gradient, opacity, and clean stacking so editable headings, text, and buttons remain above the video.'],
            ['Tune every viewport', 'Set min height and focal X/Y independently for desktop, tablet, and mobile; confirm the important subject stays visible without covering the call to action.'],
            ['Test the fallback matrix', 'Check HLS success, direct fallback, blocked autoplay, source failure, poster display, controls, keyboard use, reduced motion, 1280, 768, and 390 pixels.'],
        ], [['Decorative video stays quiet', 'Background video is muted, removed from the accessibility tree, and never blocks access to the real content.'], ['Reduced motion remains useful', 'The poster or failure image replaces ambient motion while headings and actions remain present.'], ['Preview matches public', 'Studio loads the same player runtime, sources, overlays, focal settings, and breakpoint values as the public renderer.']], $ticketUrl);
    }

    private function h4BuilderCustomCssGuide(string $ticketUrl): string
    {
        return $this->h4BuilderTutorialPage('Advanced controls', 'Use scoped custom CSS only after the native controls have done their job.', 'Page and template CSS is available for the final design requirements that cannot be expressed through Content, Design, responsive, state, or global-token controls. It is sanitized, compiled once, scoped to the Builder root, and included in preview and public output.', [['Scope', ':builder root'], ['Support', 'Media, pseudo, keyframes'], ['Recovery', 'History and public QA']], ['studio', 'settings', 'updates'], 'Advanced workflow', 'Keep custom code small, owned, and recoverable.', 'A stable class plus a narrow rule is easier to maintain than a long selector tied to generated markup. Record why the rule exists and remove it when a native control replaces the need.', [
            ['Try native controls first', 'Check Content, Design, responsive inheritance, states, globals, and element Advanced settings before adding code.'],
            ['Add a stable class', 'Give the intended element a clear class or anchor in Advanced settings rather than selecting by fragile generated order or page text.'],
            ['Open Page Settings Code', 'Use Page or Template Custom CSS for rules owned by this Builder document; use the :builder token to scope selectors to its public and preview root.'],
            ['Write the smallest rule', 'Change only the required property and state. Avoid broad element selectors, sitewide resets, external imports, hidden content, or code that changes unrelated pages.'],
            ['Add responsive or motion behavior', 'Use media queries, pseudo-elements, keyframes, and prefers-reduced-motion only where they preserve readable, operable fallback output.'],
            ['Verify sanitizer output', 'Save, reopen Code, and confirm the intended declarations remain. Then compare computed preview and public styles for the target element.'],
            ['Test and recover', 'Check desktop, tablet, 390px, 360px, keyboard, reduced motion, console, overflow, and affected interactions; restore History when the rule causes a regression.'],
        ], [['Keep secrets out', 'Custom CSS and HTML are public output. Never place credentials, private customer data, signed URLs, or internal notes in them.'], ['Avoid duplicate rules', 'Use one page or template owner for a design rule and remove temporary site-specific workarounds after the platform control ships.'], ['Preserve parity', 'The sanitized compiled rule appears once and computes the same in Studio and on the public request.']], $ticketUrl);
    }

    private function h4ProductAiImagePromptsPage(string $ticketUrl): string
    {
        return $this->h4ProductHero(
            'AI image prompts',
            'Make better website visuals without staring at a blank prompt box.',
            'Use these prompt briefs to create hero images, product scenes, service proof, tutorial visuals, social previews, and portfolio graphics that fit Help4 Builder layouts.',
            $this->h4ProductActions('https://help.openai.com/en/articles/8932459-creating-images-in-chatgpt', 'ChatGPT Image Guide', $ticketUrl, 'Ask Help4 for Images'),
            $this->h4ProductCommand(
                [
                    ['Use', 'Hero, product, tutorial, proof'],
                    ['Format', '16:9, square, portrait'],
                    ['Builder', '230 default icons'],
                    ['Check', 'Rights, alt text, mobile crop'],
                ],
                'Image workflow'
            )
        )
        . $this->h4ProductFeatureBand(
            'Prompt before you generate',
            'Good images start with page context.',
            'Tell the image tool what page the asset is for, what it must communicate, what space needs to stay clear for text, and which brand colors or mood to follow.',
            [
                ['Hero image', 'Describe the business, audience, mood, layout crop, safe text area, and what should not appear in the image.'],
                ['Product or service proof', 'Ask for a realistic scene, clear subject, clean background, and no unreadable interface text.'],
                ['Tutorial or support visual', 'Request a simple instructional graphic, numbered steps, and visual clarity at mobile size.'],
            ]
        )
        . $this->h4ProductCardGrid(
            [
                ['Hero prompt', 'Homepage hero background', 'Create a 16:9 website hero image for a [business type] serving [audience]. Keep the left third clean for headline text, use [brand colors], show [real outcome], avoid logos, avoid tiny text, and make it polished but not stock-like.', '', ''],
                ['Service prompt', 'Proof image for a service page', 'Create a realistic image showing [service outcome] for [customer type]. The image should feel trustworthy, local, and practical. Leave room for a short overlay caption. Avoid exaggerated claims or fake badges.', '', ''],
                ['Commerce prompt', 'Product or package scene', 'Create a clean product scene for [product/package]. Show the item or service context clearly, use a neutral background, leave space for price or CTA copy, and avoid brand names unless they are owned by the site.', '', ''],
                ['Tutorial prompt', 'Help article visual', 'Create a simple tutorial image explaining [task]. Use numbered visual steps, high contrast, no tiny UI text, no fake login details, and enough spacing to remain readable on mobile.', '', ''],
                ['Social prompt', 'Social preview image', 'Create a square social preview for [page/post]. Use a strong central subject, no more than three short words if text is needed, and keep the composition readable at thumbnail size.', '', ''],
                ['Portfolio prompt', 'Recent-work visual', 'Create a clean portfolio card image for a website build in [industry]. Show a browser-window style composition with no real third-party logos, clear layout structure, and space for the project name.', '', ''],
            ]
        )
        . $this->h4ProductCompare(
            ['Image job', 'Prompt details to include', 'Builder follow-up'],
            [
                ['Hero section', 'Audience, offer, mood, safe text area, aspect ratio', 'Upload, crop, add alt text, test mobile.'],
                ['Product page', 'Product type, buyer problem, background, call-to-action space', 'Pair with product gallery, comparison cards, and schema.'],
                ['Tutorial page', 'Task, numbered steps, simple visual metaphors, no private data', 'Add screenshot cards and short captions.'],
                ['Recent work', 'Industry, browser-frame look, proof angle, no unrelated logos', 'Use Website Snapshot when a real public URL is available.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Useful resources',
            'Start with the official docs, then keep the workflow practical.',
            'ChatGPT can generate and edit images from natural-language prompts. Developers can also use the OpenAI image generation API for automated image workflows when a site needs repeatable asset creation.',
            [
                ['ChatGPT images', 'OpenAI explains how to create images in ChatGPT and edit uploaded images from the ChatGPT interface.'],
                ['Image API', 'OpenAI documents image generations and edits for applications that need programmatic image workflows.'],
                ['Help4 Builder', 'Use the icon library, Website Snapshot, media picker, and responsive checks after generating the source image.'],
            ]
        )
        . '<section class="h4wp-card-grid">'
        . '<article class="h4wp-card"><p class="h4-product-eyebrow">Official guide</p><h3>Creating images in ChatGPT</h3><p>Use ChatGPT when a customer needs a quick hero, service, tutorial, or social visual from a plain-English brief.</p><p><a class="button button-primary" href="https://help.openai.com/en/articles/8932459-creating-images-in-chatgpt" target="_blank" rel="noopener">Open ChatGPT Image Guide</a></p></article>'
        . '<article class="h4wp-card"><p class="h4-product-eyebrow">Developer guide</p><h3>OpenAI image generation API</h3><p>Use the API guide when a build needs repeatable generated assets, edit flows, output sizing, or automated media workflows.</p><p><a class="button button-primary" href="https://developers.openai.com/api/docs/guides/image-generation" target="_blank" rel="noopener">Open API Guide</a></p></article>'
        . '<article class="h4wp-card"><p class="h4-product-eyebrow">Help4 workflow</p><h3>Put images into Builder</h3><p>Upload the final image, write alt text, choose the right crop, pair it with default icons, and preview at mobile before publishing.</p><p><a class="button button-primary" href="' . esc_url(home_url('/help4-builder-icons/')) . '">Open Icon Library</a></p></article>'
        . '</section>'
        . $this->h4ProductFinalCta('Need images made for a site?', 'Send Help4 the page goal and rough visual idea.', 'Include the business type, audience, brand colors, pages needed, real photos if available, and any words or logos that must stay out of generated visuals.', $ticketUrl, 'Request Image Help', home_url('/help4-builder-template-library/'), 'Template Library');
    }

    private function h4ProductThemeBuilderPage(string $ticketUrl): string
    {
        return $this->h4ProductHero(
            'Global templates',
            'Control the header, footer, reusable sections, and page rules from one place.',
            'Help4 Theme Builder is the system layer that makes a blank theme usable: global header/footer templates, condition rules, priorities, and reusable sections that keep output consistent.',
            $this->h4ProductActions(home_url('/help4-theme-builder-guide/'), 'Open Theme Guide', $ticketUrl, 'Request Template Help'),
            $this->h4ProductCommand(
                [
                    ['Header', 'Global or scoped'],
                    ['Footer', 'Global or scoped'],
                    ['Sections', 'Reusable blocks'],
                    ['Rules', 'Include, exclude, priority'],
                ],
                'Template controls'
            )
        )
        . $this->h4ProductFeatureBand(
            'What customers understand',
            'Edit the parts of the site that show everywhere.',
            'Customers do not want to rebuild a header on every page. Theme Builder turns repeated layout into assigned templates with clear scope rules.',
            [
                ['Global layout', 'Create headers and footers once, then assign them across the site.'],
                ['Page-specific exceptions', 'Use include/exclude rules and priorities when a landing page or checkout page needs a different layout.'],
                ['Builder-friendly workflow', 'Templates can be edited as reusable page parts instead of buried in theme PHP.'],
            ]
        )
        . $this->h4ProductCompare(
            ['Template job', 'Rule to use', 'Check before launch'],
            [
                ['Normal site header', 'Include the entire site, then exclude canvas or checkout pages only when needed', 'Desktop dropdowns, keyboard focus, mobile menu, logo, and primary CTA.'],
                ['Normal site footer', 'Include the entire site unless a focused funnel intentionally removes it', 'Legal links, contact route, support route, copyright year, and mobile stacking.'],
                ['Landing page shell', 'Include only the matching landing pages or assign a canvas layout', 'No duplicate header/footer, no white wrapper frame, and no horizontal clipping.'],
                ['404 page', 'Assign the 404 role once with a clear priority', 'Helpful search/navigation, contact path, and a route back to useful content.'],
                ['Reusable section', 'Insert where needed instead of assigning it as a global header/footer', 'Editing one source updates the intended placements without changing unrelated pages.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Publish with fewer surprises',
            'Template rules need the same care as page content.',
            'Review rule overlap before publishing, keep a normal page open for comparison, and test one desktop and one phone width. Clear caches after the public page proves the saved template and its conditions are correct.',
            [
                ['If a template is missing', 'Confirm publish status, role, include rules, exclusions, and the current page layout.'],
                ['If two templates appear', 'Find overlapping conditions and use the narrowest rule or an intentional priority.'],
                ['If mobile navigation fails', 'Check menu hierarchy, the toggle state, submenu spacing, focus behavior, and overflow.'],
            ]
        )
        . $this->h4ProductFinalCta('Need the theme system configured?', 'Let Help4 set up the layout rules.', 'Send the desired navigation, footer links, conversion routes, and special page exceptions.', $ticketUrl, 'Request Theme Setup', home_url('/plugins/'), 'Plugin Catalog');
    }

    private function h4ProductPaymentRouterPage(string $ticketUrl): string
    {
        return $this->h4ProductHero(
            'Help4 payment routing',
            'Route payment traffic with rules instead of hoping one processor always works.',
            'Help4 Payment Router is for stores that need smarter routing by product type, variation, subscription state, cart value, country, processor availability, failover behavior, or support workflow.',
            $this->h4ProductActions(home_url('/help4-payment-router/'), 'Open Router Guide', $ticketUrl, 'Request Commerce Help'),
            $this->h4ProductCommand(
                [
                    ['Catalog', 'Product and variation context'],
                    ['Route', 'Processor selection rules'],
                    ['Failover', 'Fallback path planning'],
                    ['Support', 'Order context for troubleshooting'],
                ],
                'Checkout routing'
            )
        )
        . $this->h4ProductFeatureBand(
            'Why stores care',
            'A broken checkout is not a normal plugin problem. It is a revenue problem.',
            'Routing rules make checkout behavior clearer for stores with subscriptions, digital goods, bookings, services, physical shipping, regional constraints, or processor resilience needs.',
            [
                ['Product-aware routing', 'Treat subscriptions, digital goods, bookings, shipped items, service products, and high-value carts differently when the store needs it.'],
                ['Processor adapters', 'Use Stripe, PayPal, Square, Braintree, Authorize.net, Wise, and custom Help4 endpoints through one routing layer.'],
                ['Fallback planning', 'Reduce the business risk of one payment route being the only route.'],
            ]
        )
        . $this->h4ProductCompare(
            ['Checkout question', 'Routing decision', 'Verification'],
            [
                ['What is being sold?', 'Use product type, variation, subscription, booking, shipping, or service context', 'Confirm the selected processor supports that exact transaction.'],
                ['Where is the customer?', 'Apply only approved country, currency, tax, and processor rules', 'Test an allowed and a blocked example without exposing private customer data.'],
                ['What if the first route fails?', 'Choose an intentional fallback or stop with a clear customer message', 'Prevent duplicate attempts and confirm support can see the route decision.'],
                ['How do renewals behave?', 'Keep subscription tokens, schedules, webhooks, and retry policy aligned', 'Test success, failure, retry, cancellation, and refund paths.'],
                ['How does support investigate?', 'Store non-secret order and route context with the transaction trail', 'A support request can explain the path without collecting processor credentials.'],
            ]
        )
        . $this->h4ProductFeatureBand(
            'Go live deliberately',
            'Processor credentials are the last step, not the first.',
            'Map the routes, test with processor test modes, validate webhooks and signatures, run the store test matrix, then switch to live credentials through a protected access path. Monitor the first real transactions and keep a rollback plan.',
            [
                ['Protect secrets', 'Never place live keys, webhook secrets, or authentication codes in page content or normal support messages.'],
                ['Test business cases', 'Cover physical, digital, subscription, booking, refund, decline, retry, and fallback behavior that the store actually uses.'],
                ['Watch the handoff', 'Confirm order status, processor result, customer message, fulfillment context, and support evidence stay connected.'],
            ]
        )
        . $this->h4ProductFinalCta('Need commerce routing scoped?', 'Choose the router path and test it before launch.', 'Tell us the store type, processors, product types, and what checkout failure would cost you.', home_url('/stripe-router-pro-vs-enterprise/'), 'Compare Stripe Plans', home_url('/stripe-router-tutorial/'), 'Open Stripe Tutorial');
    }

    private function applySalesSeoMeta(int $pageId, string $title, string $description): void
    {
        if ($pageId <= 0) {
            return;
        }

        update_post_meta($pageId, '_h4_seo_title', sanitize_text_field($title));
        update_post_meta($pageId, '_h4_seo_description', sanitize_text_field($description));
        update_post_meta($pageId, '_h4_seo_social_title', sanitize_text_field($title));
        update_post_meta($pageId, '_h4_seo_social_description', sanitize_text_field($description));
        update_post_meta($pageId, '_h4_seo_canonical', esc_url_raw((string) get_permalink($pageId)));
        update_post_meta($pageId, '_h4_seo_noindex', '0');
    }

    private function applyTutorialSeoMeta(int $pageId, string $title, string $description, string $focusKeyword): void
    {
        if ($pageId <= 0) {
            return;
        }

        $this->applySalesSeoMeta($pageId, $title, $description);
        update_post_meta($pageId, '_h4_seo_schema_type', 'article');
        update_post_meta($pageId, '_h4_seo_focus_keyword', sanitize_text_field($focusKeyword));
        update_post_meta($pageId, '_h4_seo_conversion_goal', 'learn');
        update_post_meta($pageId, '_h4_seo_primary_cta', 'Open Help4 Tutorial');
        update_post_meta($pageId, '_h4_seo_max_image_preview', 'large');
    }

    private function markLegacySalesAlias(int $legacyPageId, int $canonicalPageId): void
    {
        if ($legacyPageId <= 0 || $canonicalPageId <= 0) {
            return;
        }

        update_post_meta($legacyPageId, '_h4_seo_noindex', '1');
        update_post_meta($legacyPageId, '_h4_seo_canonical', esc_url_raw((string) get_permalink($canonicalPageId)));
    }

    /**
     * @param array<int, array{0:string, 1:string}> $rules
     */
    private function ensureSalesLegacyRedirects(array $rules): void
    {
        global $wpdb;

        $table = $wpdb->prefix . 'h4_redirects';
        $cacheGroup = 'h4bs_demos';
        $tableCacheKey = 'redirect_table_exists_' . hash('sha256', $table);
        $tableExists = wp_cache_get($tableCacheKey, $cacheGroup);
        if (! is_string($tableExists)) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Cached schema guard for optional Help4 redirects table.
            $tableExists = (string) $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $wpdb->esc_like($table)));
            wp_cache_set($tableCacheKey, $tableExists, $cacheGroup, MINUTE_IN_SECONDS * 10);
        }
        if ($tableExists !== $table) {
            return;
        }

        foreach ($rules as $rule) {
            $sourcePath = sanitize_text_field((string) ($rule[0] ?? ''));
            $targetUrl = esc_url_raw((string) ($rule[1] ?? ''));
            if ($sourcePath === '' || $targetUrl === '') {
                continue;
            }
            if (! str_starts_with($sourcePath, '/')) {
                $sourcePath = '/' . $sourcePath;
            }

            $idsCacheKey = 'redirect_ids_' . hash('sha256', $table . '|' . $sourcePath);
            $cachedIds = wp_cache_get($idsCacheKey, $cacheGroup);
            if (is_array($cachedIds)) {
                $ids = array_map('absint', $cachedIds);
            } else {
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Cached lookup against native Help4 redirects table.
                $ids = $wpdb->get_col(
                    $wpdb->prepare(
                        "SELECT id FROM %i WHERE source_path = %s AND match_type = 'exact' ORDER BY id ASC",
                        $table,
                        $sourcePath
                    )
                );
                $ids = is_array($ids) ? array_map('absint', $ids) : [];
                wp_cache_set($idsCacheKey, $ids, $cacheGroup, MINUTE_IN_SECONDS * 10);
            }

            if ($ids) {
                foreach ($ids as $id) {
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Updates native Help4 redirects table during demo redirect repair.
                    $wpdb->update(
                        $table,
                        [
                            'target_url' => $targetUrl,
                            'status' => 'active',
                            'http_code' => 301,
                        ],
                        ['id' => (int) $id],
                        ['%s', '%s', '%d'],
                        ['%d']
                    );
                }
                wp_cache_set($idsCacheKey, $ids, $cacheGroup, MINUTE_IN_SECONDS * 10);
                continue;
            }

            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Inserts native Help4 redirects table rows during demo redirect repair.
            $wpdb->insert(
                $table,
                [
                    'source_path' => $sourcePath,
                    'match_type' => 'exact',
                    'target_url' => $targetUrl,
                    'status' => 'active',
                    'http_code' => 301,
                    'hits' => 0,
                ],
                ['%s', '%s', '%s', '%s', '%d', '%d']
            );
            if (! empty($wpdb->insert_id)) {
                wp_cache_set($idsCacheKey, [(int) $wpdb->insert_id], $cacheGroup, MINUTE_IN_SECONDS * 10);
            }
        }
    }

    /**
     * @param array<int, array<string, string>> $items
     */
    private function applyFaqSchema(int $pageId, array $items): void
    {
        if ($pageId <= 0) {
            return;
        }

        $normalized = [];
        foreach ($items as $item) {
            if (! is_array($item)) {
                continue;
            }
            $question = sanitize_text_field((string) ($item['question'] ?? ''));
            $answer = sanitize_text_field((string) ($item['answer'] ?? ''));
            if ($question === '' || $answer === '') {
                continue;
            }
            $normalized[] = [
                'question' => $question,
                'answer' => $answer,
            ];
        }

        if (! $normalized) {
            delete_post_meta($pageId, '_h4_seo_faq_items');
            return;
        }

        update_post_meta($pageId, '_h4_seo_faq_items', wp_json_encode($normalized));
    }

    private function ensureSeoMetaCoverageForAllPublishedPages(): void
    {
        $pages = get_posts(
            [
                'post_type'      => 'page',
                'post_status'    => 'publish',
                'posts_per_page' => 500,
                'orderby'        => 'title',
                'order'          => 'ASC',
                'fields'         => 'ids',
            ]
        );

        if (! is_array($pages) || ! $pages) {
            return;
        }

        $curatedTitles = [
            'about' => 'About Help4 WordPress | Managed WordPress Team',
            'faq' => 'WordPress FAQ | Help4 WordPress',
            'portfolio' => 'Recent WordPress Work | Help4 WordPress',
            'self-help' => 'WordPress Self Help Resources | Help4 WordPress',
            'sos' => 'Scope Of Support | Help4 WordPress',
            'gallery' => 'WordPress Gallery & Examples | Help4 WordPress',
            'free-wordpress-builder' => 'Free WordPress Builder | Visual Editing, Templates and SEO',
            'help4-builder-download' => 'Help4 Builder Download | Free WordPress Builder',
            'help4-builder-showcase' => 'Help4 Builder Showcase | Features & Demos',
            'help4-builder-elements-gallery' => 'Help4 Builder Elements Gallery | Widget Demos',
            'help4-builder-screenshots' => 'Help4 Builder Screenshots | UI & Frontend',
        ];
        $curatedDescriptions = [
            'about' => 'Learn how Help4 WordPress delivers managed hosting, implementation support, performance optimization, and security-first operations.',
            'all-in-one-plan-details' => 'Review what is included in each all-in-one Help4 plan, from baseline managed hosting to high-touch enterprise support.',
            'cart' => 'Review selected Help4 services before secure checkout on Help4 WordPress.',
            'cookie-policy' => 'Read how Help4 WordPress uses cookies to support analytics, security, and user experience controls.',
            'disclaimer' => 'Review service and content disclaimers for Help4 WordPress managed hosting and support offerings.',
            'faq' => 'Find answers about managed WordPress hosting, support routing, migrations, billing, and platform operations.',
            'gallery' => 'Explore real website examples, layouts, and interface builds delivered by Help4 WordPress.',
            'free-wordpress-builder' => 'Download Help4 Builder Suite free for live visual WordPress editing, responsive templates, dynamic fields, sliders, forms, SEO, security, performance, and native commerce.',
            'help-4-wordpress' => 'Managed WordPress services with done-for-you execution, support, security, and speed optimization from Help4.',
            'my-account' => 'Access your Help4 customer account, services, billing records, and support resources.',
            'popular-all-in-one-plans' => 'Compare the most requested all-in-one Help4 plans for managed WordPress websites.',
            'portfolio' => 'See recent website projects, redesigns, and optimization outcomes delivered by the Help4 team.',
            'privacy-policy' => 'Read Help4 WordPress privacy practices for data collection, processing, and support workflows.',
            'self-help' => 'Use Help4 self-help resources for quick WordPress troubleshooting and maintenance guidance.',
            'sos' => 'Understand what support tasks are included by plan and how Help4 handles escalation paths.',
            'sites' => 'Browse industry-focused site examples used for onboarding and feature testing inside Help4 Builder Suite.',
            'sample-page' => 'Sample content page used for baseline WordPress rendering checks on this environment.',
        ];

        foreach ($pages as $pageId) {
            $pageId = (int) $pageId;
            if ($pageId <= 0) {
                continue;
            }

            $slug = sanitize_title((string) get_post_field('post_name', $pageId));
            $postTitle = sanitize_text_field((string) get_the_title($pageId));
            $currentTitle = sanitize_text_field((string) get_post_meta($pageId, '_h4_seo_title', true));
            if ($currentTitle === '' || (isset($curatedTitles[$slug]) && str_ends_with($currentTitle, '| Help4 WordPress'))) {
                $titleFromMap = sanitize_text_field((string) ($curatedTitles[$slug] ?? ''));
                $seoTitle = $postTitle !== ''
                    ? $postTitle . ' | Help4 WordPress'
                    : 'Help4 WordPress | Managed WordPress Services';
                if ($titleFromMap !== '') {
                    $seoTitle = $titleFromMap;
                }
                update_post_meta($pageId, '_h4_seo_title', sanitize_text_field($seoTitle));
            }

            $currentDesc = sanitize_text_field((string) get_post_meta($pageId, '_h4_seo_description', true));
            if ($currentDesc === '' || $this->isWeakSeoDescription($currentDesc)) {
                $rawContent = (string) get_post_field('post_content', $pageId);
                $plain = trim(preg_replace('/\s+/', ' ', wp_strip_all_tags(strip_shortcodes($rawContent), true)) ?? '');
                if ($plain === '') {
                    $plain = 'Managed WordPress hosting, support, and implementation by Help4 WordPress.';
                }

                if (function_exists('mb_substr')) {
                    $seoDesc = mb_substr($plain, 0, 158);
                } else {
                    $seoDesc = substr($plain, 0, 158);
                }
                $seoDesc = rtrim($seoDesc, " \t\n\r\0\x0B.,;:-");
                if ($seoDesc !== '') {
                    $seoDesc .= '.';
                }
                $mappedDesc = sanitize_text_field((string) ($curatedDescriptions[$slug] ?? ''));
                if ($mappedDesc !== '') {
                    $seoDesc = $mappedDesc;
                }
                update_post_meta($pageId, '_h4_seo_description', sanitize_text_field($seoDesc));
            }

            update_post_meta($pageId, '_h4_seo_canonical', esc_url_raw((string) get_permalink($pageId)));
            if ((string) get_post_meta($pageId, '_h4_seo_noindex', true) === '') {
                update_post_meta($pageId, '_h4_seo_noindex', '0');
            }
        }
    }

    private function isWeakSeoDescription(string $description): bool
    {
        $description = strtolower(trim($description));
        if ($description === '') {
            return true;
        }
        if (str_contains($description, 'home packages fully managed servers')) {
            return true;
        }
        if (str_contains($description, 'menu home packages')) {
            return true;
        }
        if (str_contains($description, 'account login register')) {
            return true;
        }
        if (strlen($description) < 30) {
            return true;
        }
        return false;
    }

    private function setFrontPageForDemo(): void
    {
        $preferredSources = [
            'https://help4wordpress.com',
            'https://www.help4wordpress.com',
        ];
        // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Mirror cleanup intentionally finds pages by the Help4 source marker.
        $mirroredPages = get_posts(
            [
                'post_type'      => 'page',
                'post_status'    => 'publish',
                'posts_per_page' => 100,
                'meta_key'       => '_h4_mirror_source',
                'fields'         => 'ids',
            ]
        );
        // phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_key
        if (is_array($mirroredPages) && $mirroredPages) {
            foreach ($mirroredPages as $id) {
                $source = strtolower((string) get_post_meta((int) $id, '_h4_mirror_source', true));
                $source = untrailingslashit($source);
                if ($source === '') {
                    continue;
                }
                foreach ($preferredSources as $preferredSource) {
                    if ($source === untrailingslashit(strtolower($preferredSource))) {
                        update_option('show_on_front', 'page');
                        update_option('page_on_front', (int) $id);
                        return;
                    }
                }
            }
        }

        $preferred = ['help-4-wordpress', 'help4wordpress', 'home', 'welcome', 'managed-wordpress-hosting'];
        foreach ($preferred as $slug) {
            $page = get_page_by_path($slug, OBJECT, 'page');
            if ($page && isset($page->ID)) {
                update_option('show_on_front', 'page');
                update_option('page_on_front', (int) $page->ID);
                return;
            }
        }
    }

    private function ensureMarketingHomeUsesGlobalChrome(): void
    {
        if (! $this->isHelp4WordPressMarketingSite()) {
            return;
        }

        $candidateIds = [];
        $frontPageId = absint(get_option('page_on_front'));
        if ($frontPageId > 0) {
            $candidateIds[] = $frontPageId;
        }

        $homePage = get_page_by_path('home', OBJECT, 'page');
        if ($homePage instanceof \WP_Post) {
            $candidateIds[] = (int) $homePage->ID;
        }

        $candidateIds = array_values(array_unique(array_filter(array_map('absint', $candidateIds))));
        foreach ($candidateIds as $pageId) {
            update_post_meta($pageId, '_h4_builder_page_layout', 'full_width');

            if ((string) get_post_meta($pageId, '_h4_mirror_enabled', true) !== '1') {
                continue;
            }

            $mirrorSource = strtolower(untrailingslashit((string) get_post_meta($pageId, '_h4_mirror_source', true)));
            if ($mirrorSource !== '' && ! str_contains($mirrorSource, 'help4wordpress.com')) {
                continue;
            }

            $this->clearMirrorPayload($pageId);
            if ((string) get_post_meta($pageId, '_h4_builder_enabled', true) !== '1') {
                update_post_meta($pageId, '_h4_builder_enabled', '0');
                update_post_meta($pageId, '_h4_builder_mode', 'wp');
            }
        }
    }

    private function rewriteCommerceLinks(string $content): string
    {
        $supportPageUrl = esc_url_raw(home_url('/wordpress-support/'));
        $supportTicketUrl = esc_url_raw(ContactRoutes::supportTicketUrl());
        $search = [
            'https://help4wordpress.com/store',
            'https://www.help4wordpress.com/store',
            'http://help4wordpress.com/store',
            'http://www.help4wordpress.com/store',
            'https://help4wordpress.com/cart',
            'https://www.help4wordpress.com/cart',
            'http://help4wordpress.com/cart',
            'http://www.help4wordpress.com/cart',
            'https://help4wordpress.com/checkout',
            'https://www.help4wordpress.com/checkout',
            'http://help4wordpress.com/checkout',
            'http://www.help4wordpress.com/checkout',
            'https://help4wordpress.com/product',
            'https://www.help4wordpress.com/product',
            'http://help4wordpress.com/product',
            'http://www.help4wordpress.com/product',
            'https://help4wordpress.com/products',
            'https://www.help4wordpress.com/products',
            'http://help4wordpress.com/products',
            'http://www.help4wordpress.com/products',
            'https://help4wordpress.com/contact-us',
            'https://www.help4wordpress.com/contact-us',
            'http://help4wordpress.com/contact-us',
            'http://www.help4wordpress.com/contact-us',
            'https://help4wordpress.com/contact',
            'https://www.help4wordpress.com/contact',
            'http://help4wordpress.com/contact',
            'http://www.help4wordpress.com/contact',
            'https://help4wordpress.com/contact',
            'href="/store',
            'href="/cart',
            'href="/checkout',
        ];
        $replace = [
            'https://help4network.com/store',
            'https://help4network.com/store',
            'https://help4network.com/store',
            'https://help4network.com/store',
            'https://help4network.com/cart',
            'https://help4network.com/cart',
            'https://help4network.com/cart',
            'https://help4network.com/cart',
            'https://help4network.com/cart',
            'https://help4network.com/cart',
            'https://help4network.com/cart',
            'https://help4network.com/cart',
            'https://help4network.com/product',
            'https://help4network.com/product',
            'https://help4network.com/product',
            'https://help4network.com/product',
            'https://help4network.com/products',
            'https://help4network.com/products',
            'https://help4network.com/products',
            'https://help4network.com/products',
            $supportPageUrl !== '' ? $supportPageUrl : $supportTicketUrl,
            $supportPageUrl !== '' ? $supportPageUrl : $supportTicketUrl,
            $supportPageUrl !== '' ? $supportPageUrl : $supportTicketUrl,
            $supportPageUrl !== '' ? $supportPageUrl : $supportTicketUrl,
            $supportPageUrl !== '' ? $supportPageUrl : $supportTicketUrl,
            $supportPageUrl !== '' ? $supportPageUrl : $supportTicketUrl,
            $supportPageUrl !== '' ? $supportPageUrl : $supportTicketUrl,
            $supportPageUrl !== '' ? $supportPageUrl : $supportTicketUrl,
            $supportTicketUrl !== '' ? $supportTicketUrl : ContactRoutes::SUPPORT_TICKET_DEFAULT,
            'href="https://help4network.com/store',
            'href="https://help4network.com/cart',
            'href="https://help4network.com/cart',
        ];
        $rewritten = str_replace($search, $replace, $content);
        $rewritten = str_replace('contact//', 'contact/', $rewritten);
        return $this->rewriteMainSiteLinksToLocal($rewritten);
    }

    private function rewriteMainSiteLinksToLocal(string $content): string
    {
        if ($content === '') {
            return $content;
        }

        $localBase = untrailingslashit((string) home_url('/'));
        if ($localBase === '') {
            return $content;
        }

        $localHost = strtolower((string) wp_parse_url($localBase, PHP_URL_HOST));
        if ($localHost === '') {
            return $content;
        }
        $rewriteOne = function (string $absoluteUrl) use ($localBase): string {
            $parts = wp_parse_url($absoluteUrl);
            if (! is_array($parts)) {
                return $absoluteUrl;
            }

            $path = (string) ($parts['path'] ?? '/');
            $query = (string) ($parts['query'] ?? '');
            $fragment = (string) ($parts['fragment'] ?? '');

            if (! $this->shouldRewriteMainSitePathToLocal($path)) {
                return $absoluteUrl;
            }

            $normalizedPath = $path !== '' ? $path : '/';
            $rebuilt = untrailingslashit($localBase) . $normalizedPath;
            if ($query !== '') {
                $rebuilt .= '?' . $query;
            }
            if ($fragment !== '') {
                $rebuilt .= '#' . $fragment;
            }

            return $rebuilt;
        };

        $content = (string) preg_replace_callback(
            '#https?://(?:www\.)?help4wordpress\.com(?:[^\s"\')<]+)?#i',
            static function (array $matches) use ($rewriteOne): string {
                $url = (string) ($matches[0] ?? '');
                if ($url === '') {
                    return $url;
                }
                return $rewriteOne($url);
            },
            $content
        );

        // Rewrite protocol-relative page links while preserving static assets.
        $content = (string) preg_replace_callback(
            '#//(?:www\.)?help4wordpress\.com(?:[^\s"\')<]+)?#i',
            static function (array $matches) use ($rewriteOne): string {
                $url = (string) ($matches[0] ?? '');
                if ($url === '') {
                    return $url;
                }
                $rewritten = $rewriteOne('https:' . $url);
                return preg_replace('#^https?:#i', '', $rewritten) ?? $url;
            },
            $content
        );

        return $content;
    }

    private function shouldRewriteMainSitePathToLocal(string $path): bool
    {
        $path = strtolower(trim($path));
        if ($path === '' || $path === '/') {
            return true;
        }
        // Mirror mode must remain self-contained on md/help4 domains so preview
        // and frontend stay pixel-consistent even if source host assets fail.
        return true;
    }

    private function help4GlobalActionLink(string $className, string $url, string $label, string $icon, bool $external = false): string
    {
        $target = $external ? ' target="_blank" rel="noopener"' : '';

        return '<a class="' . esc_attr($className) . '" href="' . esc_url($url) . '"' . $target . ' aria-label="' . esc_attr($label) . '" title="' . esc_attr($label) . '">' . $this->help4GlobalActionIcon($icon) . '</a>';
    }

    private function help4GlobalActionIcon(string $icon): string
    {
        $slugs = [
            'ticket' => 'support-ticket',
            'account' => 'account-rep',
            'text' => 'email-deliverability',
            'phone' => 'call-tracking',
            'chat' => 'support-escalation',
        ];
        $slug = $slugs[$icon] ?? $slugs['ticket'];
        if (! is_readable(H4BS_PATH . 'assets/icons/defaults/' . $slug . '.svg')) {
            $slug = 'support-ticket';
        }

        return '<img class="h4-global-action-svg" src="' . esc_url(H4BS_URL . 'assets/icons/defaults/' . $slug . '.svg') . '" alt="" aria-hidden="true" loading="lazy" decoding="async" />';
    }

    private function ensureGlobalThemeBuilderTemplates(): void
    {
        $salesCallUrl = esc_url(ContactRoutes::salesCallUrl());
        $salesSmsUrl = esc_url(ContactRoutes::salesSmsUrl());
        $salesWhatsAppUrl = esc_url(ContactRoutes::salesWhatsAppUrl());
        $clientAreaUrl = esc_url(ContactRoutes::supportClientAreaUrl());
        $salesPhoneDisplay = esc_html(ContactRoutes::salesPhoneDisplay());
        $supportTicketUrl = esc_url(ContactRoutes::supportTicketUrl());
        $supportRepUrl = esc_url(ContactRoutes::supportRepUrl());

        $brandHomeUrl = esc_url(home_url('/'));
        $brandLogoUrl = esc_url(H4BS_URL . 'assets/images/brand/help4-logo-main-1536x487.png');
        $brandWordmark = '<a class="h4-global-header__brand" href="' . $brandHomeUrl . '" aria-label="Help4 WordPress home"><span class="h4-global-header__brand-lockup"><img class="h4-global-header__brand-logo" src="' . $brandLogoUrl . '" alt="Help4 WordPress managed hosting, support, security, speed optimization, and website builder" loading="eager" decoding="async"></span></a>';
        $mobileToggle = '<button type="button" class="h4-global-header__menu-toggle" aria-controls="h4-global-header-menu" aria-expanded="false"><span class="h4-global-header__menu-icon" aria-hidden="true"><span></span><span></span><span></span></span><span class="h4-global-header__menu-label">Menu</span></button>';
        $servicesMenu = '<div class="h4-global-header__menu-item h4-global-header__menu-item--dropdown"><a href="' . esc_url(home_url('/help-4-wordpress/')) . '" aria-haspopup="true" aria-expanded="false">Services</a><div class="h4-global-header__dropdown" role="menu"><a role="menuitem" href="' . esc_url(home_url('/wordpress-speed-optimization/')) . '">Speed Optimization</a><a role="menuitem" href="' . esc_url(home_url('/emergency-wordpress-support/')) . '">Emergency Support</a><a role="menuitem" href="' . esc_url(home_url('/wordpress-malware-removal/')) . '">Malware Removal</a><a role="menuitem" href="' . esc_url(home_url('/wordpress-migration-service/')) . '">Migration Service</a><a role="menuitem" href="' . esc_url(home_url('/wordpress-maintenance-care-plans/')) . '">Maintenance Plans</a><a role="menuitem" href="' . esc_url(home_url('/commerce-support/')) . '">Commerce Support</a><a role="menuitem" href="' . esc_url(home_url('/design-to-wordpress/')) . '">Design to WordPress</a><a role="menuitem" href="' . esc_url(home_url('/white-label-wordpress-support/')) . '">Agency Support</a></div></div>';
        $resourcesMenu = '<div class="h4-global-header__menu-item h4-global-header__menu-item--dropdown"><a href="' . esc_url(home_url('/self-help/')) . '" aria-haspopup="true" aria-expanded="false">Resources</a><div class="h4-global-header__dropdown" role="menu"><a role="menuitem" href="' . esc_url(home_url('/wordpress-hosting-faq/')) . '">Hosting FAQ</a><a role="menuitem" href="' . esc_url(home_url('/free-wordpress-builder/')) . '">Free Builder</a><a role="menuitem" href="' . esc_url(home_url('/help4-blank-theme/')) . '">Blank Theme</a><a role="menuitem" href="' . esc_url(home_url('/help4-builder-tutorials/')) . '">Builder Tutorials</a><a role="menuitem" href="' . esc_url(home_url('/plugins/')) . '">Plugin Catalog</a><a role="menuitem" href="' . esc_url(home_url('/portfolio/')) . '">Recent Work</a><a role="menuitem" href="' . $clientAreaUrl . '" target="_blank" rel="noopener">Client Area</a></div></div>';
        $headerActions = '<div class="h4-global-header__actions">'
            . '<a class="h4-global-header__sales-call" href="' . $salesCallUrl . '">Call Sales</a>'
            . '<a class="h4-global-header__cta" href="https://help4network.com/index.php?rp=/store/help-4-wordpress/basic-hosting-4-me" target="_blank" rel="noopener">Start for $4.95</a>'
            . '</div>';
        $footerSupport = '<div class="h4-global-footer__support" aria-label="Get support">'
            . $this->help4GlobalActionLink('h4-global-footer__icon', $supportTicketUrl, 'Support Ticket', 'ticket', true)
            . $this->help4GlobalActionLink('h4-global-footer__icon', $supportRepUrl, 'Account Rep', 'account', true)
            . $this->help4GlobalActionLink('h4-global-footer__icon', $salesSmsUrl, 'Text Support', 'text')
            . $this->help4GlobalActionLink('h4-global-footer__icon', $salesCallUrl, 'Call Support', 'phone')
            . $this->help4GlobalActionLink('h4-global-footer__icon', $salesWhatsAppUrl, 'WhatsApp Support', 'chat', true)
            . '</div>';
        $headerContent = '<header class="h4-global-header"><div class="h4-global-header__inner">' . $brandWordmark . $mobileToggle . '<nav id="h4-global-header-menu" class="h4-global-header__nav" aria-label="Main navigation"><a href="' . esc_url(home_url('/packages/')) . '">Hosting</a><a href="' . esc_url(home_url('/fully-managed-wordpress-hosting/')) . '">Managed Care</a>' . $servicesMenu . '<a href="' . esc_url(home_url('/portfolio/')) . '">Recent Work</a>' . $resourcesMenu . '<a href="' . esc_url(home_url('/contact-us/')) . '">Contact</a></nav>' . $headerActions . '</div></header>';
        $footerContent = '<footer class="h4-global-footer"><div class="h4-global-footer__inner"><div class="h4-global-footer__meta"><p class="h4-global-footer__copyright">&copy; 2022-' . esc_html((string) gmdate('Y')) . ' Help4 WordPress. All rights reserved.</p></div><nav class="h4-global-footer__about" aria-label="About links"><a href="' . esc_url(home_url('/about-us/')) . '">About</a><a href="' . esc_url(home_url('/help-4-wordpress/')) . '">Services</a><a href="' . esc_url(home_url('/packages/')) . '">Subscriptions</a><a href="' . esc_url(home_url('/plugins/')) . '">Plugins</a><a href="' . esc_url(home_url('/help4-blank-theme/')) . '">Blank Theme</a><a href="' . esc_url(home_url('/wordpress-hosting-faq/')) . '">FAQ</a></nav>' . $footerSupport . '</div></footer>';

        $this->upsertGlobalTemplate('h4-global-header', 'Global Header', 'header', $headerContent, 120);
        $this->upsertGlobalTemplate('h4-global-footer', 'Global Footer', 'footer', $footerContent, 120);
    }

    private function upsertGlobalTemplate(string $slug, string $title, string $role, string $content, int $priority = 10): int
    {
        $existing = get_page_by_path($slug, OBJECT, 'h4_template');
        $postData = [
            'post_type'    => 'h4_template',
            'post_status'  => 'publish',
            'post_name'    => $slug,
            'post_title'   => $title,
            'post_content' => $content,
        ];

        if ($existing instanceof \WP_Post) {
            $postData['ID'] = (int) $existing->ID;
            $templateId = wp_update_post($postData, true);
        } else {
            $templateId = wp_insert_post($postData, true);
        }

        if (is_wp_error($templateId) || ! $templateId) {
            return 0;
        }

        $templateId = (int) $templateId;
        update_post_meta($templateId, '_h4_template_role', sanitize_key($role));
        update_post_meta($templateId, '_h4_template_scope', 'entire_site');
        update_post_meta($templateId, '_h4_template_include_ids', '');
        update_post_meta($templateId, '_h4_template_exclude_ids', '');
        update_post_meta($templateId, '_h4_template_include_types', '');
        update_post_meta($templateId, '_h4_template_exclude_types', '');
        update_post_meta($templateId, '_h4_template_user_roles', '');
        update_post_meta($templateId, '_h4_template_priority', (string) max(-100, min(999, $priority)));

        return $templateId;
    }

    private function currentRequestIsMirroredPage(): bool
    {
        if (! is_singular()) {
            return false;
        }

        $postId = get_queried_object_id();
        if (! $postId) {
            return false;
        }

        return $this->isMirroredPage((int) $postId);
    }

    private function isMirroredPage(int $postId): bool
    {
        return (string) get_post_meta($postId, '_h4_mirror_enabled', true) === '1';
    }

    /**
     * @param array<string, mixed> $payload
     */
    private function persistMirrorPayload(int $postId, array $payload): void
    {
        update_post_meta($postId, '_h4_mirror_enabled', '1');
        update_post_meta($postId, '_h4_mirror_source', esc_url_raw((string) ($payload['source_url'] ?? '')));
        update_post_meta($postId, '_h4_mirror_html', (string) ($payload['content_html'] ?? ''));
        update_post_meta($postId, '_h4_mirror_inline_css', (string) ($payload['inline_css'] ?? ''));
        update_post_meta($postId, '_h4_mirror_inline_js', '');
        update_post_meta(
            $postId,
            '_h4_mirror_styles',
            wp_json_encode(array_values(array_unique(array_filter(array_map('strval', (array) ($payload['styles'] ?? []))))))
        );
        update_post_meta(
            $postId,
            '_h4_mirror_scripts',
            wp_json_encode(array_values(array_unique(array_filter(array_map('strval', (array) ($payload['scripts'] ?? []))))))
        );
    }

    private function clearMirrorPayload(int $postId): void
    {
        delete_post_meta($postId, '_h4_mirror_enabled');
        delete_post_meta($postId, '_h4_mirror_source');
        delete_post_meta($postId, '_h4_mirror_html');
        delete_post_meta($postId, '_h4_mirror_inline_css');
        delete_post_meta($postId, '_h4_mirror_inline_js');
        delete_post_meta($postId, '_h4_mirror_styles');
        delete_post_meta($postId, '_h4_mirror_scripts');
    }

    /**
     * @return array<int, string>
     */
    private function loadMirrorAssetList(int $postId, string $metaKey): array
    {
        $raw = (string) get_post_meta($postId, $metaKey, true);
        if ($raw === '') {
            return [];
        }

        $decoded = json_decode($raw, true);
        if (! is_array($decoded)) {
            return [];
        }

        $out = [];
        foreach ($decoded as $entry) {
            $url = $this->sanitizeMirrorAssetUrl((string) $entry);
            if ($url === '') {
                continue;
            }
            $out[] = $url;
        }

        return array_values(array_unique(array_slice($out, 0, 80)));
    }

    /**
     * @return array{
     *   source_url: string,
     *   content_html: string,
     *   styles: array<int, string>,
     *   scripts: array<int, string>,
     *   inline_css: string,
     *   inline_js: string
     * }
     */
    private function fetchRenderedMirrorPayload(string $sourceUrl): array
    {
        $sourceUrl = esc_url_raw($sourceUrl);
        $payload = [
            'source_url' => $sourceUrl,
            'content_html' => '',
            'styles' => [],
            'scripts' => [],
            'inline_css' => '',
            'inline_js' => '',
        ];
        if ($sourceUrl === '') {
            return $payload;
        }

        $host = strtolower((string) wp_parse_url($sourceUrl, PHP_URL_HOST));
        if (! in_array($host, ['help4wordpress.com', 'www.help4wordpress.com'], true)) {
            return $payload;
        }

        $response = wp_remote_get(
            $sourceUrl,
            [
                'timeout' => 25,
                'redirection' => 5,
                'headers' => [
                    'Accept' => 'text/html,application/xhtml+xml',
                ],
            ]
        );
        if (is_wp_error($response)) {
            return $payload;
        }

        $statusCode = (int) wp_remote_retrieve_response_code($response);
        if ($statusCode < 200 || $statusCode >= 300) {
            return $payload;
        }

        $html = (string) wp_remote_retrieve_body($response);
        if (trim($html) === '') {
            return $payload;
        }

        return $this->extractRenderedMirrorPayload($html, $sourceUrl);
    }

    /**
     * @return array{
     *   source_url: string,
     *   content_html: string,
     *   styles: array<int, string>,
     *   scripts: array<int, string>,
     *   inline_css: string,
     *   inline_js: string
     * }
     */
    private function extractRenderedMirrorPayload(string $html, string $sourceUrl): array
    {
        $payload = [
            'source_url' => esc_url_raw($sourceUrl),
            'content_html' => '',
            'styles' => [],
            'scripts' => [],
            'inline_css' => '',
            'inline_js' => '',
        ];
        if (! class_exists(\DOMDocument::class)) {
            return $payload;
        }

        $dom = new \DOMDocument();
        $previous = libxml_use_internal_errors(true);
        $loaded = $dom->loadHTML($html);
        libxml_clear_errors();
        libxml_use_internal_errors($previous);
        if (! $loaded) {
            return $payload;
        }

        $xpath = new \DOMXPath($dom);

        $styles = [];
        $styleNodes = $xpath->query("//link[@href]");
        if ($styleNodes instanceof \DOMNodeList) {
            foreach ($styleNodes as $styleNode) {
                if (! $styleNode instanceof \DOMElement) {
                    continue;
                }
                $rel = strtolower((string) $styleNode->getAttribute('rel'));
                if (! str_contains($rel, 'stylesheet')) {
                    continue;
                }
                $styleUrl = $this->sanitizeMirrorAssetUrl(
                    $this->absolutizeRemoteUrl((string) $styleNode->getAttribute('href'), $sourceUrl)
                );
                if ($styleUrl !== '') {
                    $styles[] = $this->rewriteMainSiteLinksToLocal($styleUrl);
                }
            }
        }

        $scripts = [];
        $scriptNodes = $xpath->query("//script[@src]");
        if ($scriptNodes instanceof \DOMNodeList) {
            foreach ($scriptNodes as $scriptNode) {
                if (! $scriptNode instanceof \DOMElement) {
                    continue;
                }
                $scriptUrl = $this->sanitizeMirrorAssetUrl(
                    $this->absolutizeRemoteUrl((string) $scriptNode->getAttribute('src'), $sourceUrl)
                );
                if ($scriptUrl !== '') {
                    $scripts[] = $this->rewriteMainSiteLinksToLocal($scriptUrl);
                }
            }
        }

        $inlineCssParts = [];
        $inlineNodes = $xpath->query('//style');
        if ($inlineNodes instanceof \DOMNodeList) {
            foreach ($inlineNodes as $inlineNode) {
                $css = trim((string) $inlineNode->textContent);
                if ($css !== '') {
                    $inlineCssParts[] = $this->rewriteCssUrls($css, $sourceUrl);
                }
            }
        }

        $rootNode = $this->pickMirrorRootNode($xpath);
        if (! $rootNode instanceof \DOMElement) {
            return $payload;
        }

        $inlineJsParts = [];
        $rootScripts = $xpath->query('.//script[not(@src)]', $rootNode);
        if ($rootScripts instanceof \DOMNodeList) {
            foreach ($rootScripts as $rootScript) {
                if (! $rootScript instanceof \DOMElement) {
                    continue;
                }
                $type = strtolower(trim((string) $rootScript->getAttribute('type')));
                if ($type !== '' && ! in_array($type, ['text/javascript', 'application/javascript', 'module'], true)) {
                    continue;
                }
                $js = trim((string) $rootScript->textContent);
                if ($js !== '') {
                    $inlineJsParts[] = $js;
                }
            }
        }

        $this->normalizeNodeAssetUrls($rootNode, $sourceUrl);
        $this->removeScriptNodes($rootNode);
        $contentHtml = trim($this->nodeOuterHtml($rootNode));
        if ($contentHtml !== '') {
            $payload['content_html'] = $this->rewriteCommerceLinks($contentHtml);
        }

        $payload['styles'] = array_values(array_unique(array_slice($styles, 0, 80)));
        $payload['scripts'] = array_values(array_unique(array_slice($scripts, 0, 40)));
        $payload['inline_css'] = $this->rewriteMainSiteLinksToLocal(implode("\n", array_filter($inlineCssParts)));
        $payload['inline_js'] = '';
        return $payload;
    }

    private function pickMirrorRootNode(\DOMXPath $xpath): ?\DOMElement
    {
        $queries = [
            "//*[@id='page']",
            "//*[contains(concat(' ', normalize-space(@class), ' '), ' site ')]",
            '//main',
            '//body',
        ];

        foreach ($queries as $query) {
            $nodes = $xpath->query($query);
            if (! $nodes instanceof \DOMNodeList || $nodes->length < 1) {
                continue;
            }
            $candidate = $nodes->item(0);
            if ($candidate instanceof \DOMElement) {
                return $candidate;
            }
        }

        return null;
    }

    private function removeScriptNodes(\DOMElement $root): void
    {
        $scripts = $root->getElementsByTagName('script');
        if (! $scripts instanceof \DOMNodeList || $scripts->length < 1) {
            return;
        }

        $toRemove = [];
        foreach ($scripts as $scriptNode) {
            if ($scriptNode instanceof \DOMNode) {
                $toRemove[] = $scriptNode;
            }
        }
        foreach ($toRemove as $node) {
            if ($node->parentNode instanceof \DOMNode) {
                $node->parentNode->removeChild($node);
            }
        }
    }

    private function normalizeNodeAssetUrls(\DOMElement $root, string $sourceUrl): void
    {
        if (! $root->ownerDocument instanceof \DOMDocument) {
            return;
        }
        $xpath = new \DOMXPath($root->ownerDocument);
        $nodes = $xpath->query('.//*', $root);
        if (! $nodes instanceof \DOMNodeList) {
            return;
        }

        foreach ($nodes as $node) {
            if (! $node instanceof \DOMElement) {
                continue;
            }
            $this->normalizeElementAssetUrls($node, $sourceUrl);
        }

        $this->normalizeElementAssetUrls($root, $sourceUrl);
    }

    private function normalizeElementAssetUrls(\DOMElement $node, string $sourceUrl): void
    {
        foreach (['href', 'src', 'poster', 'data-src', 'data-lazy-src', 'action'] as $attribute) {
            if (! $node->hasAttribute($attribute)) {
                continue;
            }
            $resolved = $this->absolutizeRemoteUrl((string) $node->getAttribute($attribute), $sourceUrl);
            if ($resolved !== '') {
                $node->setAttribute($attribute, $resolved);
            }
        }

        if ($node->hasAttribute('srcset')) {
            $parts = array_filter(array_map('trim', explode(',', (string) $node->getAttribute('srcset'))));
            $resolvedParts = [];
            foreach ($parts as $part) {
                $chunks = preg_split('/\s+/', $part, 2);
                $url = isset($chunks[0]) ? $this->absolutizeRemoteUrl((string) $chunks[0], $sourceUrl) : '';
                if ($url === '') {
                    continue;
                }
                $descriptor = isset($chunks[1]) ? trim((string) $chunks[1]) : '';
                $resolvedParts[] = $descriptor !== '' ? $url . ' ' . $descriptor : $url;
            }
            if ($resolvedParts) {
                $node->setAttribute('srcset', implode(', ', $resolvedParts));
            }
        }

        if ($node->hasAttribute('style')) {
            $node->setAttribute(
                'style',
                $this->rewriteCssUrls((string) $node->getAttribute('style'), $sourceUrl)
            );
        }
    }

    private function nodeOuterHtml(\DOMElement $node): string
    {
        $tagName = strtolower((string) $node->tagName);
        if (in_array($tagName, ['html', 'body'], true)) {
            $html = '';
            foreach ($node->childNodes as $child) {
                if (! $child instanceof \DOMNode) {
                    continue;
                }
                $rendered = $node->ownerDocument instanceof \DOMDocument ? (string) $node->ownerDocument->saveHTML($child) : '';
                if ($rendered !== '') {
                    $html .= $rendered;
                }
            }
            return $html;
        }

        $tmp = new \DOMDocument();
        $tmp->formatOutput = false;
        $imported = $tmp->importNode($node, true);
        if (! $imported) {
            return '';
        }
        $tmp->appendChild($imported);
        return (string) $tmp->saveHTML($tmp->documentElement);
    }

    private function rewriteCssUrls(string $css, string $sourceUrl): string
    {
        return (string) preg_replace_callback(
            '#url\(([^)]+)\)#i',
            function (array $matches) use ($sourceUrl): string {
                $raw = trim((string) ($matches[1] ?? ''), " \t\n\r\0\x0B'\"");
                if ($raw === '' || str_starts_with($raw, 'data:') || str_starts_with($raw, '#')) {
                    return (string) ($matches[0] ?? '');
                }
                $resolved = $this->absolutizeRemoteUrl($raw, $sourceUrl);
                if ($resolved === '') {
                    return (string) ($matches[0] ?? '');
                }
                if ($this->shouldSuppressMirroredAssetUrl($resolved)) {
                    return 'url("")';
                }
                return 'url("' . esc_url_raw($resolved) . '")';
            },
            $css
        );
    }

    private function shouldSuppressMirroredAssetUrl(string $url): bool
    {
        $parts = wp_parse_url($url);
        if (! is_array($parts)) {
            return false;
        }

        $host = strtolower((string) ($parts['host'] ?? ''));
        if (! in_array($host, ['help4wordpress.com', 'www.help4wordpress.com'], true)) {
            return false;
        }

        $path = strtolower((string) ($parts['path'] ?? ''));
        if ($path === '') {
            return false;
        }

        $blockedSubpaths = [
            '/wp-content/uploads/elementor/google-fonts/fonts/',
            '/wp-content/plugins/elementor/assets/lib/eicons/fonts/',
        ];
        foreach ($blockedSubpaths as $needle) {
            if (str_contains($path, $needle)) {
                return true;
            }
        }

        return (bool) preg_match('/\.(woff2?|ttf|otf|eot)$/', $path);
    }

    private function absolutizeRemoteUrl(string $url, string $baseUrl): string
    {
        $url = trim(html_entity_decode($url, ENT_QUOTES));
        if ($url === '' || str_starts_with($url, '#')) {
            return $url;
        }
        if (str_starts_with($url, 'data:') || str_starts_with($url, 'mailto:') || str_starts_with($url, 'tel:') || str_starts_with($url, 'javascript:')) {
            return $url;
        }
        if (preg_match('#^https?://#i', $url)) {
            return esc_url_raw($this->rewriteMainSiteLinksToLocal($url));
        }

        $base = wp_parse_url($baseUrl);
        if (! is_array($base) || empty($base['host'])) {
            return '';
        }
        $scheme = (string) ($base['scheme'] ?? 'https');
        $host = (string) $base['host'];

        if (str_starts_with($url, '//')) {
            return esc_url_raw($this->rewriteMainSiteLinksToLocal($scheme . ':' . $url));
        }

        $fragment = '';
        $query = '';
        $path = $url;
        if (str_contains($path, '#')) {
            [$path, $fragment] = array_pad(explode('#', $path, 2), 2, '');
        }
        if (str_contains($path, '?')) {
            [$path, $query] = array_pad(explode('?', $path, 2), 2, '');
        }

        if ($path === '') {
            $basePath = (string) ($base['path'] ?? '/');
            $normalizedPath = $this->normalizeRemotePath($basePath);
        } elseif (str_starts_with($path, '/')) {
            $normalizedPath = $this->normalizeRemotePath($path);
        } else {
            $basePath = (string) ($base['path'] ?? '/');
            $baseDir = preg_replace('#/[^/]*$#', '/', $basePath);
            if (! is_string($baseDir) || $baseDir === '') {
                $baseDir = '/';
            }
            $normalizedPath = $this->normalizeRemotePath($baseDir . $path);
        }

        $absolute = $scheme . '://' . $host . $normalizedPath;
        if ($query !== '') {
            $absolute .= '?' . $query;
        }
        if ($fragment !== '') {
            $absolute .= '#' . $fragment;
        }

        return esc_url_raw($this->rewriteMainSiteLinksToLocal($absolute));
    }

    private function normalizeRemotePath(string $path): string
    {
        $segments = [];
        foreach (explode('/', $path) as $segment) {
            $segment = trim($segment);
            if ($segment === '' || $segment === '.') {
                continue;
            }
            if ($segment === '..') {
                array_pop($segments);
                continue;
            }
            $segments[] = $segment;
        }

        return '/' . implode('/', $segments);
    }

    private function sanitizeMirrorAssetUrl(string $url): string
    {
        $url = esc_url_raw(trim($url), ['https', 'http']);
        if ($url === '') {
            return '';
        }

        $host = strtolower((string) wp_parse_url($url, PHP_URL_HOST));
        if ($host === '') {
            return '';
        }

        $allowedHosts = [
            'help4wordpress.com',
            'www.help4wordpress.com',
        ];

        foreach ($allowedHosts as $allowedHost) {
            if ($host === $allowedHost || str_ends_with($host, '.' . $allowedHost)) {
                return $url;
            }
        }

        return '';
    }

    private function sanitizeMirrorInlineJs(string $raw): string
    {
        $js = trim($raw);
        if ($js === '') {
            return '';
        }

        // Remove wrappers if script tags were accidentally included.
        $js = (string) preg_replace('#<\s*/?\s*script\b[^>]*>#i', '', $js);
        $js = str_replace(["<?", "?>"], '', $js);
        $js = trim($js);
        if ($js === '') {
            return '';
        }

        $lines = preg_split('/\R/', $js);
        if (is_array($lines)) {
            $filtered = [];
            foreach ($lines as $line) {
                $trimmedLine = trim((string) $line);
                if (
                    str_contains($trimmedLine, 'ParticleThemesData')
                    && preg_match('/\bvar\s+localize\s*=/', $trimmedLine) === 1
                ) {
                    continue;
                }
                if (
                    str_contains($trimmedLine, 'wp-emoji-settings')
                    || str_contains($trimmedLine, 'wp-emoji-loader.min.js')
                ) {
                    continue;
                }
                $filtered[] = (string) $line;
            }
            $js = trim(implode("\n", $filtered));
        }

        if ($js === '') {
            return '';
        }

        // Keep payload bounded for performance and admin safety.
        if (strlen($js) > 400000) {
            $js = substr($js, 0, 400000);
        }

        return $js;
    }

    private function forcePageLayoutForAllPages(string $layout, bool $preserveMirroredPages = true): void
    {
        $layout = sanitize_key($layout);
        if (! in_array($layout, ['default', 'full_width', 'canvas'], true)) {
            $layout = 'full_width';
        }

        $pages = get_posts(
            [
                'post_type'      => 'page',
                'post_status'    => ['publish', 'draft', 'private', 'pending', 'future'],
                'posts_per_page' => -1,
                'fields'         => 'ids',
            ]
        );

        foreach ($pages as $pageId) {
            $id = (int) $pageId;
            if ($id <= 0) {
                continue;
            }
            if ($preserveMirroredPages && $this->isMirroredPage($id)) {
                continue;
            }
            update_post_meta($id, '_h4_builder_page_layout', $layout);
        }
    }
}
