/* 
Theme Name: Hello Elementor Child
Theme URI: https://github.com/elementor/hello-theme-child/
Description: Hello Elementor Child is a child theme of Hello Elementor, created by Elementor team
Author: Elementor Team
Author URI: https://elementor.com/
Template: hello-elementor
Version: 2.0.0
Text Domain: hello-elementor-child
License: GNU General Public License v3 or later.
License URI: https://www.gnu.org/licenses/gpl-3.0.html
Tags: flexible-header, custom-colors, custom-menu, custom-logo, editor-style, featured-images, rtl-language-support, threaded-comments, translation-ready
*/

/* Add your custom styles here */

<?php
/**
 * Tema Hijo de Hello Elementor
 * Funciones de optimización: diferir JS y cargar CSS de forma no bloqueante.
 */

// Si no hay un archivo style.css en la carpeta del tema hijo, carga el del padre.
if ( ! defined( 'ELEMENTOR_CHILD_THEME_STYLE_INCLUDE' ) ) {
    define( 'ELEMENTOR_CHILD_THEME_STYLE_INCLUDE', true );
}

/**
 * 1. DEFER Y ASYNC SCRIPTS
 *
 * Mueve todos los scripts, excepto jQuery, a la parte inferior de la página.
 * Los scripts que ya tengan 'async' o 'defer' no se modifican.
 * Esto mejora el tiempo de carga percibido por el usuario.
 */
function optimus_defer_scripts( $tag, $handle, $src ) {
    // Evitar scripts en el panel de administración o peticiones AJAX
    if ( is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
        return $tag;
    }

    // No aplicar 'defer' a jQuery y sus dependencias para evitar errores
    if ( strpos( $src, 'jquery.min.js' ) !== false || strpos( $src, 'jquery-migrate.min.js' ) !== false ) {
        return $tag;
    }

    // Si el script ya tiene defer o async, no lo modificamos
    if ( stripos( $tag, ' defer' ) !== false || stripos( $tag, ' async' ) !== false ) {
        return $tag;
    }

    // Aplica 'defer' a todos los demás scripts
    return preg_replace( '/<script\b([^>]*)>/i', '<script$1 defer>', $tag, 1 );
}
add_filter( 'script_loader_tag', 'optimus_defer_scripts', 20, 3 );


// ---

### 2. CARGA DE CSS NO BLOQUEANTE

/**
 * Convierte selectivamente las hojas de estilo en carga no bloqueante.
 * Usa 'preload' con un fallback de 'noscript'. Esto permite que la página
 * renderice el contenido antes de que los estilos se carguen completamente.
 */
function optimus_preload_css( $html, $handle, $href, $media ) {
    // Excluye el panel de administración y usuarios logueados para evitar problemas
    if ( is_admin() || is_user_logged_in() ) {
        return $html;
    }

    // Fragmentos de URL que quieres que se carguen de forma no bloqueante
    // Puedes editar esta lista según los archivos CSS de tu sitio.
    $css_match = array(
        'hello-elementor/style.min.css',
        'hello-elementor/theme.min.css',
        'hello-elementor/header-footer.min.css',
        'hello-theme-child-master/style.css',
        'frontend-lite.min.css', // Archivo común de Elementor
        'frontend.min.css', // Archivo de Elementor Pro
        'post-\d+\.css', // Regla general para los CSS de Elementor generados por ID
        'jet-timeline.css',
        'widget-nav-menu.min.css',
        'widget-carousel-module-base.min.css',
        'widget-social-icons.min.css',
        'widget-divider.min.css',
        'widget-heading.min.css',
        'widget-image.min.css',
        'widget-media-carousel.min.css',
        'widget-nested-accordion.min.css',
        'widget-icon-list.min.css',
        'swiper.min.css',
        'slick.min.css',
        'public.css',
        'base-desktop.css',
        'frontend.css',
        'reset.css',
        'theme.css',
        'header-footer.css',
        'build/select.css',
        'build/radio.css',
        'build/checkbox.css',
        'build/switcher.css',
        'build/main.css',
        'build/wysiwyg.css',
        'jet-elements.css',
        'anton.css',
        'roboto.css',
        'robotoslab.css',
        'sgr.css',
        'motion-fx.min.css',
        'sticky.min.css',
        'e-swiper.min.css',
        'shapes.min.css',
        'flash.min.css',
        'apple-webkit.min.css',
        'hide-admin-bar-based-on-user-roles-public.css',
    );

    foreach ( $css_match as $needle ) {
        if ( preg_match( '/' . preg_quote( $needle, '/' ) . '/', $href ) ) {
            $preload = "<link rel='preload' href='{$href}' as='style' onload=\"this.onload=null;this.rel='stylesheet'\">";
            $fallback = "<noscript>{$html}</noscript>";
            return $preload . $fallback;
        }
    }

    // Devuelve el HTML original si no hay coincidencia
    return $html;
}
add_filter( 'style_loader_tag', 'optimus_preload_css', 10, 4 );


// ---

### 3. RETRASO DE SCRIPTS AL INTERACTUAR

/**
 * Retrasa la carga de scripts no críticos hasta que el usuario interactúe
 * con la página. Esto mejora las métricas de carga inicial de la página.
 */
function optimus_delay_scripts_on_interaction() {
    // Omitir en el área de administración
    if ( is_admin() ) {
        return;
    }
    ?>
    <script>
    (function() {
        const scriptsToDelay = [
            'jet-menu-public-scripts.js',
            'frontend.min.js',
            'hello-frontend.js',
            'frontend.js',
            'jet-elements.min.js',
            'swiper.min.js',
            'webpack-pro.runtime.min.js',
            'slick.min.js',
            'widgets-scripts.js',
            'email-decode.min.js',
            'sgr.js',
            'sticky.min.js',
            'jquery.smartmenus.min.js',
            'webpack.runtime.min.js',
            'elements-handlers.min.js',
            'hooks.min.js',
            'i18n.min.js',
            'vue.min.js',
            'jquery.inputmask.min.js',
            'hide-admin-bar-based-on-user-roles-public.js',
            'jquery-migrate.min.js', // No siempre es bueno, pero si es un problema, podemos probar
            'frontend-modules.min.js',
            'core.min.js',
            'index.js'
        ];
        let scriptsLoaded = false;
        function loadScripts() {
            if (scriptsLoaded) return;
            scriptsLoaded = true;
            scriptsToDelay.forEach(pattern => {
                const scripts = document.querySelectorAll(`script[src*="${pattern}"]`);
                scripts.forEach(oldScript => {
                    const newScript = document.createElement('script');
                    newScript.src = oldScript.src;
                    newScript.async = true;
                    if (oldScript.parentNode) {
                        oldScript.parentNode.replaceChild(newScript, oldScript);
                    }
                });
            });
        }
        ['scroll', 'mousemove', 'touchstart', 'keydown'].forEach(event => {
            window.addEventListener(event, loadScripts, { once: true, passive: true });
        });
    })();
    </script>
    <?php
}
add_action('wp_footer', 'optimus_delay_scripts_on_interaction', 25);