{"id":25747,"date":"2025-08-25T15:09:42","date_gmt":"2025-08-25T15:09:42","guid":{"rendered":"https:\/\/sparoysothers.cl\/?page_id=25747"},"modified":"2026-08-13T10:20:27","modified_gmt":"2026-08-13T14:20:27","slug":"acompanamiento-de-reserva","status":"publish","type":"page","link":"https:\/\/sparoysothers.cl\/en\/acompanamiento-de-reserva\/","title":{"rendered":"Acompa\u00f1amiento de Reserva"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"25747\" class=\"elementor elementor-25747\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-68d0e49 e-con-full elementor-hidden-widescreen elementor-hidden-desktop elementor-hidden-laptop elementor-hidden-tablet elementor-hidden-mobile e-flex e-con e-parent\" data-id=\"68d0e49\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-cec4b38 e-flex e-con-boxed e-con e-child\" data-id=\"cec4b38\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1014e16 elementor-widget elementor-widget-heading\" data-id=\"1014e16\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">REQUEST YOUR RESERVATION<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-79263b4 elementor-widget elementor-widget-html\" data-id=\"79263b4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<iframe style=\"overflow: hidden; border-radius: 10px; margin-bottom: 20px;\" src=\"https:\/\/agendamiento.reservo.cl\/makereserva\/agenda\/s0074L7080V6CK6g6F10djh707u1S0\" width=\"100%\" height=\"550\" frameborder=\"0\"><\/iframe><a href=\"https:\/\/www.reservo.cl\"><\/a>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-d4a9e37 e-con-full e-flex e-con e-child\" data-id=\"d4a9e37\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-4bdee84 e-con-full paso1-selecciona-tu-servicio e-flex e-con e-parent\" data-id=\"4bdee84\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-0c70a8f e-con-full e-flex e-con e-child\" data-id=\"0c70a8f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-dfcd633 elementor-widget elementor-widget-heading\" data-id=\"dfcd633\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">SELECT YOUR SERVICE<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-8a5b4cb e-con-full e-flex e-con e-child\" data-id=\"8a5b4cb\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-1814d89 e-con-full e-flex e-con e-child\" data-id=\"1814d89\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-0a3e773 e-con-full e-flex e-con e-child\" data-id=\"0a3e773\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-5c51709 e-con-full servicio-option e-flex e-con e-child\" data-id=\"5c51709\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-87b1dda elementor-widget elementor-widget-heading\" data-id=\"87b1dda\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">\u00c1rea <\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2982a7e servicio-arrow elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"2982a7e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-chevron-left\" viewbox=\"0 0 320 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-f949faa e-con-full servicio-selected e-flex e-con e-child\" data-id=\"f949faa\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-b5d67ec elementor-absolute elementor-widget elementor-widget-html\" data-id=\"b5d67ec\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;_position&quot;:&quot;absolute&quot;}\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- HTML PERSONALIZADO - SELECTOR DE SERVICIOS CORREGIDO -->\r\n<div class=\"custom-select-container-servicios\">\r\n    <div class=\"custom-select-display-servicios\" id=\"selectDisplayServicios\">\r\n        <span id=\"selectedSpanServicios\"><\/span>\r\n    <\/div>\r\n    <select id=\"hiddenSelectServicios\" style=\"display: none;\">\r\n        <!-- Se llenar\u00e1 din\u00e1micamente -->\r\n    <\/select>\r\n    <div class=\"custom-options-servicios\" id=\"optionsListServicios\">\r\n        <!-- area fija: no requiere carga -->\r\n    <\/div>\r\n<\/div>\r\n\r\n<style>\r\n.custom-select-container-servicios {\r\n    position: relative;\r\n    width: 300px;\r\n}\r\n\r\n.custom-select-display-servicios {\r\n    cursor: pointer;\r\n    user-select: none;\r\n}\r\n\r\n.custom-options-servicios {\r\n    position: absolute;\r\n    top: 100%;\r\n    left: 0;\r\n    right: 0;\r\n    background: white;\r\n    border: 1px solid #ddd;\r\n    border-radius: 4px;\r\n    box-shadow: 0 2px 10px rgba(0,0,0,0.1);\r\n    z-index: 1000;\r\n    max-height: 200px;\r\n    overflow-y: auto;\r\n    opacity: 0;\r\n    visibility: hidden;\r\n    transform: translateY(-10px);\r\n    transition: all 0.3s ease;\r\n}\r\n\r\n.custom-options-servicios.show {\r\n    opacity: 1;\r\n    visibility: visible;\r\n    transform: translateY(0);\r\n}\r\n\r\n.custom-option-servicios {\r\n    padding: 12px 16px;\r\n    cursor: pointer;\r\n    transition: background-color 0.2s ease;\r\n    border-bottom: 1px solid #f0f0f0;\r\n}\r\n\r\n.custom-option-servicios:last-child {\r\n    border-bottom: none;\r\n}\r\n\r\n.custom-option-servicios:hover {\r\n    background-color: #f5f5f5;\r\n}\r\n\r\n.custom-option-servicios.selected {\r\n    background-color: #e3f2fd;\r\n    color: #1976d2;\r\n}\r\n\r\n.loading-message {\r\n    padding: 12px 16px;\r\n    text-align: center;\r\n    color: #666;\r\n    font-style: italic;\r\n}\r\n\r\n.error-message {\r\n    padding: 12px 16px;\r\n    text-align: center;\r\n    color: #dc2626;\r\n    background-color: #fef2f2;\r\n}\r\n\r\n\/* Clase para rotar la flecha *\/\r\n.arrow-rotated-servicios {\r\n    transform: rotate(-90deg) !important;\r\n    transition: transform 0.3s ease !important;\r\n}\r\n\r\n.arrow-normal-servicios {\r\n    transform: rotate(0deg) !important;\r\n    transition: transform 0.3s ease !important;\r\n}\r\n\r\n#selectedTextServicios{\r\n    text-align: var(--text-align);\r\n    margin-block-end: 1rem;\r\n    margin-block-start: .5rem;\r\n    box-sizing: border-box;\r\n    line-height: 1;\r\n    margin: 0;\r\n    margin-top: 5px;\r\n    padding: 0;\r\n    font-family: \"Josefin Sans\", Sans-serif;\r\n    font-size: 16px;\r\n    font-weight: 600;\r\n    color: var( --e-global-color-primary );\r\n    text-transform: uppercase;\r\n}\r\n\r\n.loading-overlay-servicios {\r\n    position: absolute;\r\n    top: 0;\r\n    left: 0;\r\n    right: 0;\r\n    bottom: 0;\r\n    background: rgba(255, 255, 255, 0.95);\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    z-index: 10000;\r\n    border-radius: 4px;\r\n}\r\n\r\n.spinner-servicios {\r\n    border: 3px solid #f3f3f3;\r\n    border-top: 3px solid #31989E;\r\n    border-radius: 50%;\r\n    width: 30px;\r\n    height: 30px;\r\n    animation: spin-servicios 0.8s linear infinite;\r\n}\r\n\r\n@keyframes spin-servicios {\r\n    0% { transform: rotate(0deg); }\r\n    100% { transform: rotate(360deg); }\r\n}\r\n\r\n.loading-text-servicios {\r\n    margin-left: 12px;\r\n    color: #31989E;\r\n    font-weight: 600;\r\n    font-size: 14px;\r\n}\r\n\r\n\/* Area fija: Day Spa visible pero no editable *\/\r\n.custom-options-servicios {\r\n    display: none !important;\r\n}\r\n.servicio-arrow,\r\n.servicio-close {\r\n    display: none !important;\r\n}\r\n.custom-select-display-servicios,\r\n.servicio-option .elementor-heading-title,\r\n.servicio-selected {\r\n    cursor: default !important;\r\n    pointer-events: none !important;\r\n}\r\n\r\n\/* \u00c1rea fija: Day Spa visible pero no editable *\/\r\n\/* Ocultamos solo el desplegable de opciones, la flecha y la X de limpiar *\/\r\n.custom-options-servicios {\r\n    display: none !important;\r\n}\r\n.servicio-arrow,\r\n.servicio-close {\r\n    display: none !important;\r\n}\r\n\/* Quitamos el cursor de \"clickeable\" para que no invite a interactuar *\/\r\n.custom-select-display-servicios,\r\n.servicio-option .elementor-heading-title,\r\n.servicio-selected {\r\n    cursor: default !important;\r\n    pointer-events: none !important;\r\n}\r\n<\/style>\r\n\r\n<script>\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    console.log('\ud83d\ude80 SELECTOR DE SERVICIOS - Versi\u00f3n Optimizada');\r\n\r\n    \/\/ ==========================================================\r\n    \/\/ AREAS HABILITADAS PARA AUTOAGENDA\r\n    \/\/ ==========================================================\r\n    \/\/ Day Spa es el area predeterminada. Med Spa se activa unicamente\r\n    \/\/ cuando el visitante llega con una evaluacion Med Spa ya guardada\r\n    \/\/ (boton de reserva directa en la ficha de producto o en el archivo\r\n    \/\/ de categoria). Nunca se elige a mano: el area sigue siendo un\r\n    \/\/ campo de solo lectura.\r\n    \/\/\r\n    \/\/ Si cambian los IDs en WooCommerce, se actualizan aqui y en\r\n    \/\/ sothers_arbol_config() de functions.php.\r\n    const AREAS = {\r\n        'day-spa': { id: 24, name: 'Day Spa', slug: 'day-spa' },\r\n        'med-spa': { id: 30, name: 'Med Spa', slug: 'med-spa' }\r\n    };\r\n\r\n    const AREA_PREDETERMINADA = 'day-spa';\r\n\r\n    \/\/ Se resuelve UNA vez, al inicializar\r\n    let AREA_FIJA = AREAS[AREA_PREDETERMINADA];\r\n\r\n    \/**\r\n     * El area la determina el producto con el que llega el visitante, no una\r\n     * eleccion suya. Si no hay producto guardado o su area no esta habilitada,\r\n     * queda Day Spa.\r\n     *\r\n     * A proposito NO se mira popupMenuSelection: el menu de navegacion sigue\r\n     * comportandose como hasta ahora.\r\n     *\/\r\n    function resolverArea() {\r\n        try {\r\n            const guardado = JSON.parse(localStorage.getItem('selectedServicio') || 'null');\r\n\r\n            if (guardado && guardado.slug && AREAS[guardado.slug]) {\r\n                return AREAS[guardado.slug];\r\n            }\r\n        } catch (e) {\r\n            console.warn('No se pudo leer selectedServicio:', e);\r\n        }\r\n\r\n        return AREAS[AREA_PREDETERMINADA];\r\n    }\r\n\r\n    let serviciosData = {};\r\n    let isInitialized = false;\r\n    \r\n    const selectDisplayServicios = document.getElementById('selectDisplayServicios');\r\n    const optionsListServicios = document.getElementById('optionsListServicios');\r\n    const hiddenSelectServicios = document.getElementById('hiddenSelectServicios');\r\n    const selectedTextServicios = document.getElementById('selectedTextServicios');\r\n    const titleElementServicios = document.querySelector('.servicio-selected .elementor-heading-title');\r\n    const arrowIconServicios = document.querySelector('.servicio-arrow .elementor-icon svg');\r\n    const closeIconServicios = document.querySelector('.servicio-close');\r\n    \r\n    let isOpenServicios = false;\r\n\r\n    \/\/ Funci\u00f3n para mostrar indicador de carga\r\n    \/\/ ANTI-PARPADEO DE LA CAPA BLANCA\r\n    \/\/ El overlay es rgba(255,255,255,0.95) con z-index 10000: tapa el widget\r\n    \/\/ por completo. Se disparaba en cada carga de pagina mientras corrian los\r\n    \/\/ dos fetch a la REST de WooCommerce, que pagan ~1300ms de arranque de\r\n    \/\/ WordPress cada uno. Eso producia dos destellos blancos seguidos.\r\n    \/\/\r\n    \/\/ Dos correcciones:\r\n    \/\/   1. En la hidratacion inicial no se muestra. El usuario acaba de entrar\r\n    \/\/      y una capa blanca sobre el widget se lee como un fallo, no como\r\n    \/\/      progreso. El desplegable esta cerrado, asi que no ve nada raro.\r\n    \/\/   2. Para acciones del usuario se muestra con retraso: si la carga\r\n    \/\/      termina antes de RETRASO_OVERLAY, la capa nunca aparece.\r\n    const RETRASO_OVERLAY = 350;\r\n    let timerOverlay = null;\r\n    let cargaInicial = true;\r\n\r\n    function cancelarOverlayPendiente() {\r\n        if (timerOverlay) {\r\n            clearTimeout(timerOverlay);\r\n            timerOverlay = null;\r\n        }\r\n    }\r\n\r\n    function mostrarCargando(mensaje = 'Cargando...') {\r\n        if (cargaInicial) {\r\n            return;\r\n        }\r\n\r\n        cancelarOverlayPendiente();\r\n\r\n        timerOverlay = setTimeout(function () {\r\n            timerOverlay = null;\r\n\r\n            const container = document.querySelector('.servicio-selected');\r\n            if (!container) return;\r\n\r\n            let overlay = container.querySelector('.loading-overlay-servicios');\r\n            if (!overlay) {\r\n                overlay = document.createElement('div');\r\n                overlay.className = 'loading-overlay-servicios';\r\n                overlay.innerHTML = `\r\n                    <div class=\"spinner-servicios\"><\/div>\r\n                    <span class=\"loading-text-servicios\">${mensaje}<\/span>\r\n                `;\r\n                container.style.position = 'relative';\r\n                container.appendChild(overlay);\r\n            }\r\n        }, RETRASO_OVERLAY);\r\n    }\r\n\r\n    function ocultarCargando() {\r\n        cancelarOverlayPendiente();\r\n\r\n        \/\/ A partir de aca cualquier carga es por accion del usuario\r\n        cargaInicial = false;\r\n\r\n        const overlay = document.querySelector('.loading-overlay-servicios');\r\n        if (overlay) {\r\n            overlay.remove();\r\n        }\r\n    }\r\n\r\n    \/\/ Carga instantanea del area fija. Sin fetch, sin espera de red.\r\n    function loadServicios() {\r\n\r\n        \/\/ El area depende del producto con el que se entra\r\n        AREA_FIJA = resolverArea();\r\n        console.log('Area resuelta: ' + AREA_FIJA.name);\r\n\r\n        \/\/ Solo se registra el area resuelta. Asi aplicarSeleccionPopup()\r\n        \/\/ sigue descartando cualquier otra, igual que antes.\r\n        serviciosData = {};\r\n        serviciosData[AREA_FIJA.slug] = {\r\n            id: AREA_FIJA.id,\r\n            name: AREA_FIJA.name,\r\n            slug: AREA_FIJA.slug\r\n        };\r\n\r\n        hiddenSelectServicios.innerHTML = '';\r\n        const optionSelect = document.createElement('option');\r\n        optionSelect.value = AREA_FIJA.slug;\r\n        optionSelect.textContent = AREA_FIJA.name;\r\n        hiddenSelectServicios.appendChild(optionSelect);\r\n\r\n        optionsListServicios.innerHTML = '';\r\n\r\n        isInitialized = true;\r\n        console.log('Area fija cargada (sin API): ' + AREA_FIJA.name);\r\n\r\n        \/\/ El dispatch se aplaza al siguiente tick A PROPOSITO.\r\n        \/\/ Los selectores de servicio y experiencia registran su listener de\r\n        \/\/ 'servicioSeleccionado' en su propio DOMContentLoaded, que corre\r\n        \/\/ DESPUES de este. Disparar de forma sincrona deja la cadena muerta.\r\n        setTimeout(function () {\r\n            selectOptionServicios(AREA_FIJA.slug, AREA_FIJA.name);\r\n        }, 0);\r\n    }\r\n\r\n    function toggleSelectServicios() {\r\n        isOpenServicios = !isOpenServicios;\r\n        \r\n        if (isOpenServicios) {\r\n            optionsListServicios.classList.add('show');\r\n            if (arrowIconServicios) {\r\n                arrowIconServicios.classList.add('arrow-rotated-servicios');\r\n                arrowIconServicios.classList.remove('arrow-normal-servicios');\r\n            }\r\n        } else {\r\n            optionsListServicios.classList.remove('show');\r\n            if (arrowIconServicios) {\r\n                arrowIconServicios.classList.add('arrow-normal-servicios');\r\n                arrowIconServicios.classList.remove('arrow-rotated-servicios');\r\n            }\r\n        }\r\n    }\r\n\r\n    function closeSelectServicios() {\r\n        isOpenServicios = false;\r\n        optionsListServicios.classList.remove('show');\r\n        if (arrowIconServicios) {\r\n            arrowIconServicios.classList.add('arrow-normal-servicios');\r\n            arrowIconServicios.classList.remove('arrow-rotated-servicios');\r\n        }\r\n    }\r\n\r\n    function selectOptionServicios(value, text) {\r\n        console.log('\ud83d\udccb Seleccionando servicio:', text);\r\n\r\n        if (selectedTextServicios) {\r\n            selectedTextServicios.textContent = text;\r\n        }\r\n        \r\n        hiddenSelectServicios.value = value;\r\n        \r\n        if (titleElementServicios && value !== '') {\r\n            titleElementServicios.textContent = text.toUpperCase();\r\n        } else if (titleElementServicios) {\r\n            titleElementServicios.textContent = '';\r\n        }\r\n        \r\n        document.querySelectorAll('.custom-option-servicios').forEach(option => {\r\n            option.classList.remove('selected');\r\n            if (option.dataset.value === value) {\r\n                option.classList.add('selected');\r\n            }\r\n        });\r\n        \r\n        closeSelectServicios();\r\n\r\n        const event = new CustomEvent('servicioSeleccionado', {\r\n            detail: {\r\n                servicioSlug: value,\r\n                servicioData: serviciosData[value]\r\n            }\r\n        });\r\n        document.dispatchEvent(event);\r\n\r\n        localStorage.setItem('selectedServicio', JSON.stringify({\r\n            slug: value,\r\n            data: serviciosData[value]\r\n        }));\r\n    }\r\n\r\n    function limpiarSeleccion() {\r\n        console.log('\ud83e\uddf9 Limpiando selecci\u00f3n');\r\n\r\n        if (selectedTextServicios) {\r\n            selectedTextServicios.textContent = '';\r\n        }\r\n        \r\n        if (titleElementServicios) {\r\n            titleElementServicios.textContent = '';\r\n        }\r\n        \r\n        hiddenSelectServicios.value = '';\r\n        \r\n        document.querySelectorAll('.custom-option-servicios').forEach(option => {\r\n            option.classList.remove('selected');\r\n        });\r\n\r\n        localStorage.removeItem('selectedServicio');\r\n        document.dispatchEvent(new CustomEvent('servicioLimpiado'));\r\n    }\r\n\r\n    function limpiarTodasLasSelecciones() {\r\n        console.log('\ud83e\uddf9 Limpiando TODAS las selecciones');\r\n\r\n        localStorage.removeItem('selectedServicio');\r\n        localStorage.removeItem('selectedCategoria');\r\n        localStorage.removeItem('selectedProducto');\r\n\r\n        if (selectedTextServicios) {\r\n            selectedTextServicios.textContent = '';\r\n        }\r\n        \r\n        if (titleElementServicios) {\r\n            titleElementServicios.textContent = '';\r\n        }\r\n        \r\n        hiddenSelectServicios.value = '';\r\n        \r\n        document.querySelectorAll('.custom-option-servicios').forEach(option => {\r\n            option.classList.remove('selected');\r\n        });\r\n\r\n        document.dispatchEvent(new CustomEvent('servicioLimpiado'));\r\n        document.dispatchEvent(new CustomEvent('limpiarTodasLasSelecciones'));\r\n    }\r\n\r\n    function verificarSeleccionPopup() {\r\n        console.log('\ud83d\udd0d Verificando popup...');\r\n        \r\n        try {\r\n            const popupSelection = localStorage.getItem('popupMenuSelection');\r\n            \r\n            if (!popupSelection) {\r\n                return null;\r\n            }\r\n\r\n            const data = JSON.parse(popupSelection);\r\n            const edad = Date.now() - data.timestamp;\r\n            \r\n            if (edad > 10000) {\r\n                console.log('\u23f0 Popup expirado');\r\n                localStorage.removeItem('popupMenuSelection');\r\n                return null;\r\n            }\r\n\r\n            console.log('\u2705 Popup encontrado:', data.data.name);\r\n            return data;\r\n\r\n        } catch (e) {\r\n            console.error('\u274c Error verificando popup:', e);\r\n            localStorage.removeItem('popupMenuSelection');\r\n            return null;\r\n        }\r\n    }\r\n\r\n    function aplicarSeleccionPopup(popupData) {\r\n        console.log('\ud83c\udfaf Aplicando popup:', popupData.data.name);\r\n\r\n        try {\r\n            \/\/ AREA FIJA: si el popup del menu trae un area que ya no existe\r\n            \/\/ en el acompanamiento (ej. Med Spa), la descartamos.\r\n            if (!serviciosData[popupData.slug]) {\r\n                console.warn('Area del popup no disponible (' + popupData.slug + '), se mantiene Day Spa');\r\n                localStorage.removeItem('popupMenuSelection');\r\n                return false;\r\n            }\r\n\r\n            \/\/ Mostrar indicador de carga\r\n            mostrarCargando('Aplicando selecci\u00f3n...');\r\n\r\n            localStorage.removeItem('selectedCategoria');\r\n            localStorage.removeItem('selectedProducto');\r\n\r\n            \/\/ Peque\u00f1o delay para mostrar el indicador\r\n            setTimeout(() => {\r\n                selectOptionServicios(popupData.slug, popupData.data.name);\r\n                localStorage.removeItem('popupMenuSelection');\r\n                \r\n                document.dispatchEvent(new CustomEvent('popupMenuAplicado', {\r\n                    detail: { fromPopup: true }\r\n                }));\r\n                \r\n                ocultarCargando();\r\n                console.log('\u2705 Popup aplicado');\r\n            }, 300);\r\n\r\n            return true;\r\n\r\n        } catch (e) {\r\n            console.error('\u274c Error aplicando popup:', e);\r\n            localStorage.removeItem('popupMenuSelection');\r\n            ocultarCargando();\r\n            return false;\r\n        }\r\n    }\r\n\r\n    function validarEstadoCompleto() {\r\n        const servicioGuardado = localStorage.getItem('selectedServicio');\r\n        const categoriaGuardada = localStorage.getItem('selectedCategoria');\r\n        const productoGuardado = localStorage.getItem('selectedProducto');\r\n\r\nconst tieneSelecciones = servicioGuardado || categoriaGuardada || productoGuardado;\r\n        const tieneTodasLasSelecciones = servicioGuardado && categoriaGuardada && productoGuardado;\r\n\r\n        \/\/ \u00c1REA FIJA: tener SOLO el servicio (Day Spa) es un estado v\u00e1lido,\r\n        \/\/ porque el \u00e1rea ya no la construye el usuario paso a paso.\r\n        \/\/ Solo es inconsistente si hay categor\u00eda o producto SIN su cadena completa.\r\n        const soloServicio = servicioGuardado && !categoriaGuardada && !productoGuardado;\r\n\r\n        if (tieneSelecciones && !tieneTodasLasSelecciones && !soloServicio) {\r\n            console.log('\u26a0\ufe0f Estado inconsistente, limpiando...');\r\n            \r\n            \/\/ Preservamos el servicio (Day Spa fijo); limpiamos solo lo dem\u00e1s\r\n            localStorage.removeItem('selectedCategoria');\r\n            localStorage.removeItem('selectedProducto');\r\n            \r\n            document.dispatchEvent(new CustomEvent('estadoInconsistente'));\r\n            document.dispatchEvent(new CustomEvent('limpiarTodasLasSelecciones'));\r\n            \r\n            return false;\r\n        }\r\n\r\n        if (!tieneSelecciones) {\r\n            return true;\r\n        }\r\n\r\n        if (tieneTodasLasSelecciones) {\r\n            try {\r\n                const servicio = JSON.parse(servicioGuardado);\r\n                const categoria = JSON.parse(categoriaGuardada);\r\n\r\n                if (categoria.data.parent !== servicio.data.id) {\r\n                    console.log('\u26a0\ufe0f Relaci\u00f3n inv\u00e1lida');\r\n                    throw new Error('Relaci\u00f3n padre-hijo inv\u00e1lida');\r\n                }\r\n\r\n                console.log('\u2705 Estado consistente');\r\n                return true;\r\n\r\n            } catch (e) {\r\n                console.log('\u26a0\ufe0f Error validando, limpiando...');\r\n                localStorage.removeItem('selectedServicio');\r\n                localStorage.removeItem('selectedCategoria');\r\n                localStorage.removeItem('selectedProducto');\r\n                document.dispatchEvent(new CustomEvent('estadoInconsistente'));\r\n                return false;\r\n            }\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    function recuperarSeleccionPrevia() {\r\n        if (!isInitialized) {\r\n            return;\r\n        }\r\n\r\n        const popupData = verificarSeleccionPopup();\r\n\r\n        if (popupData) {\r\n            setTimeout(() => {\r\n                aplicarSeleccionPopup(popupData);\r\n            }, 100);\r\n            return;\r\n        }\r\n\r\n        validarEstadoCompleto();\r\n\r\n        \/\/ AREA FIJA: aca ANTES se volvia a llamar a selectOptionServicios()\r\n        \/\/ para \"recuperar\" el area guardada. Con el area fija eso dispara\r\n        \/\/ 'servicioSeleccionado' una SEGUNDA vez, y se produce esto:\r\n        \/\/   - dos rondas de loadCategorias() y loadProductos()\r\n        \/\/   - las dos carreras se pisan y validarYRecuperar() del selector\r\n        \/\/     de experiencia no encuentra el producto en productosData\r\n        \/\/   - resultado: \"Producto a recuperar no esta en productosData,\r\n        \/\/     limpiando\" -> se borra el producto y se limpia el calendario\r\n        \/\/ Se autocorregia despues, pero dejaba el calendario reiniciado.\r\n        \/\/\r\n        \/\/ loadServicios() ya autoselecciono Day Spa y disparo el evento una\r\n        \/\/ vez. El area no puede variar, asi que no hay nada que recuperar.\r\n    }\r\n\r\n    \/\/ Event listeners\r\n    const productTitleServicios = document.querySelector('.servicio-option .elementor-heading-title');\r\n    if (productTitleServicios) {\r\n        productTitleServicios.style.cursor = 'pointer';\r\n        productTitleServicios.addEventListener('click', toggleSelectServicios);\r\n    }\r\n    \r\n    const arrowContainerServicios = document.querySelector('.servicio-arrow');\r\n    if (arrowContainerServicios) {\r\n        arrowContainerServicios.style.cursor = 'pointer';\r\n        arrowContainerServicios.addEventListener('click', toggleSelectServicios);\r\n    }\r\n    \r\n    if (selectDisplayServicios) {\r\n        selectDisplayServicios.addEventListener('click', toggleSelectServicios);\r\n    }\r\n    \r\n    if (closeIconServicios) {\r\n        closeIconServicios.style.cursor = 'pointer';\r\n        closeIconServicios.addEventListener('click', function() {\r\n            limpiarTodasLasSelecciones();\r\n        });\r\n    }\r\n    \r\n    document.addEventListener('click', function(e) {\r\n        const container = document.querySelector('.custom-select-container-servicios');\r\n        const titleElement = document.querySelector('.servicio-option');\r\n        const arrowElement = document.querySelector('.servicio-arrow');\r\n        \r\n        if (container && !container.contains(e.target) && \r\n            (!titleElement || !titleElement.contains(e.target)) && \r\n            (!arrowElement || !arrowElement.contains(e.target))) {\r\n            closeSelectServicios();\r\n        }\r\n    });\r\n\r\n    document.addEventListener('limpiarTodasLasSelecciones', limpiarTodasLasSelecciones);\r\n    document.addEventListener('validarEstadoGlobal', validarEstadoCompleto);\r\n\r\n    window.addEventListener('storage', function(e) {\r\n        if (e.key === 'selectedCategoria' || e.key === 'selectedProducto') {\r\n            console.log('\ud83d\udc41\ufe0f Cambio detectado');\r\n            setTimeout(validarEstadoCompleto, 100);\r\n        }\r\n    });\r\n    \r\n    if (arrowIconServicios) {\r\n        arrowIconServicios.classList.add('arrow-normal-servicios');\r\n    }\r\n\r\n    function inicializar() {\r\n        validarEstadoCompleto();\r\n\r\n        \/\/ Sincrono: el area se pinta en el mismo tick, sin esperar red.\r\n        loadServicios();\r\n\r\n        recuperarSeleccionPrevia();\r\n    }\r\n\r\n    inicializar();\r\n    console.log('\u2705 Selector optimizado inicializado');\r\n});\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7ea1b06 elementor-widget elementor-widget-heading\" data-id=\"7ea1b06\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">  <\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d3acc63 servicio-close elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"d3acc63\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-times\" viewbox=\"0 0 352 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-e7343e9 e-con-full e-flex e-con e-child\" data-id=\"e7343e9\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-1ed4a25 e-con-full categoria-option e-flex e-con e-child\" data-id=\"1ed4a25\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-595ea74 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"595ea74\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Select your service<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7d8c847 categoria-arrow elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"7d8c847\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-chevron-left\" viewbox=\"0 0 320 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-4121d4c e-con-full categoria-selected e-flex e-con e-child\" data-id=\"4121d4c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-b1010d1 elementor-absolute elementor-widget elementor-widget-html\" data-id=\"b1010d1\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;_position&quot;:&quot;absolute&quot;}\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- HTML PERSONALIZADO - SELECTOR DE CATEGOR\u00cdAS CORREGIDO -->\r\n<div class=\"custom-select-container-categories\">\r\n    <div class=\"custom-select-display-categories\" id=\"selectDisplayCategories\">\r\n        <span id=\"selectedSpanCategories\"><\/span>\r\n    <\/div>\r\n    <select id=\"hiddenSelectCategories\" style=\"display: none;\">\r\n        <!-- Se llenar\u00e1 din\u00e1micamente -->\r\n    <\/select>\r\n    <div class=\"custom-options-categories\" id=\"optionsListCategories\">\r\n        <div class=\"waiting-message\">Selecciona un \u00e1rea primero<\/div>\r\n    <\/div>\r\n<\/div>\r\n\r\n<style>\r\n.custom-select-container-categories {\r\n    position: relative;\r\n    width: 300px;\r\n}\r\n\r\n.custom-select-display-categories {\r\n    cursor: pointer;\r\n    user-select: none;\r\n}\r\n\r\n.custom-options-categories {\r\n    position: absolute;\r\n    top: 100%;\r\n    left: 0;\r\n    right: 0;\r\n    background: white;\r\n    border: 1px solid #ddd;\r\n    border-radius: 4px;\r\n    box-shadow: 0 2px 10px rgba(0,0,0,0.1);\r\n    z-index: 1000;\r\n    max-height: 200px;\r\n    overflow-y: auto;\r\n    opacity: 0;\r\n    visibility: hidden;\r\n    transform: translateY(-10px);\r\n    transition: all 0.3s ease;\r\n}\r\n\r\n.custom-options-categories.show {\r\n    opacity: 1;\r\n    visibility: visible;\r\n    transform: translateY(0);\r\n}\r\n\r\n.custom-option-categories {\r\n    padding: 12px 16px;\r\n    cursor: pointer;\r\n    transition: background-color 0.2s ease;\r\n    border-bottom: 1px solid #f0f0f0;\r\n}\r\n\r\n.custom-option-categories:last-child {\r\n    border-bottom: none;\r\n}\r\n\r\n.custom-option-categories:hover {\r\n    background-color: #f5f5f5;\r\n}\r\n\r\n.custom-option-categories.selected {\r\n    background-color: #e3f2fd;\r\n    color: #1976d2;\r\n}\r\n\r\n.waiting-message, .loading-message-cat {\r\n    padding: 12px 16px;\r\n    text-align: center;\r\n    color: #666;\r\n    font-style: italic;\r\n}\r\n\r\n.error-message-cat {\r\n    padding: 12px 16px;\r\n    text-align: center;\r\n    color: #dc2626;\r\n    background-color: #fef2f2;\r\n}\r\n\r\n.disabled-selector {\r\n    opacity: 0.5;\r\n    pointer-events: none;\r\n}\r\n\r\n\/* Clase para rotar la flecha *\/\r\n.arrow-rotated-categories {\r\n    transform: rotate(-90deg) !important;\r\n    transition: transform 0.3s ease !important;\r\n}\r\n\r\n.arrow-normal-categories {\r\n    transform: rotate(0deg) !important;\r\n    transition: transform 0.3s ease !important;\r\n}\r\n\r\n#selectedTextCategories{\r\n    text-align: var(--text-align);\r\n    margin-block-end: 1rem;\r\n    margin-block-start: .5rem;\r\n    box-sizing: border-box;\r\n    line-height: 1;\r\n    margin: 0;\r\n    margin-top: 5px;\r\n    padding: 0;\r\n    font-family: \"Josefin Sans\", Sans-serif;\r\n    font-size: 16px;\r\n    font-weight: 600;\r\n    color: var( --e-global-color-primary );\r\n    text-transform: uppercase;\r\n}\r\n\r\n.loading-overlay-categories {\r\n    position: absolute;\r\n    top: 0;\r\n    left: 0;\r\n    right: 0;\r\n    bottom: 0;\r\n    background: rgba(255, 255, 255, 0.95);\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    z-index: 10000;\r\n    border-radius: 4px;\r\n}\r\n\r\n.spinner-categories {\r\n    border: 3px solid #f3f3f3;\r\n    border-top: 3px solid #31989E;\r\n    border-radius: 50%;\r\n    width: 30px;\r\n    height: 30px;\r\n    animation: spin-categories 0.8s linear infinite;\r\n}\r\n\r\n@keyframes spin-categories {\r\n    0% { transform: rotate(0deg); }\r\n    100% { transform: rotate(360deg); }\r\n}\r\n.loading-text-categories {\r\n    margin-left: 12px;\r\n    color: #31989E;\r\n    font-weight: 600;\r\n    font-size: 14px;\r\n}\r\n\r\n.categoria-selected .elementor-heading-title:empty::after {\r\n    content: 'Cargando...';\r\n    color: #b9bcc0;\r\n    font-weight: 400;\r\n    font-style: italic;\r\n    text-transform: none;\r\n}\r\n\r\n\r\nhtml.sothers-categorias-listas .categoria-selected .elementor-heading-title:empty::after {\r\n    content: none;\r\n}\r\n\r\n.categoria-close {\r\n    opacity: 0;\r\n    pointer-events: none;\r\n    transition: opacity 0.2s ease;\r\n}\r\n\r\nhtml.sothers-categoria-elegida .categoria-close {\r\n    opacity: 1;\r\n    pointer-events: auto;\r\n}\r\n<\/style>\r\n\r\n<script>\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    console.log('\ud83c\udff7\ufe0f SELECTOR DE CATEGOR\u00cdAS - Versi\u00f3n Optimizada');\r\n\r\n\r\n    let categoriasData = {};\r\n    let servicioSeleccionado = null;\r\n    let fromPopupMenu = false;\r\n    \r\n    const selectDisplayCategories = document.getElementById('selectDisplayCategories');\r\n    const optionsListCategories = document.getElementById('optionsListCategories');\r\n    const hiddenSelectCategories = document.getElementById('hiddenSelectCategories');\r\n    const selectedTextCategories = document.getElementById('selectedTextCategories');\r\n    const containerCategories = document.querySelector('.custom-select-container-categories');\r\n    const titleElementCategories = document.querySelector('.categoria-selected .elementor-heading-title');\r\n    const arrowIconCategories = document.querySelector('.categoria-arrow .elementor-icon svg');\r\n    const closeIconCategories = document.querySelector('.categoria-close');\r\n    \r\n    let isOpenCategories = false;\r\n\r\n    const RETRASO_OVERLAY = 350;\r\n    let timerOverlay = null;\r\n    let cargaInicial = true;\r\n\r\n    function cancelarOverlayPendiente() {\r\n        if (timerOverlay) {\r\n            clearTimeout(timerOverlay);\r\n            timerOverlay = null;\r\n        }\r\n    }\r\n\r\n    function mostrarCargando(mensaje = 'Cargando...') {\r\n        if (cargaInicial) {\r\n            return;\r\n        }\r\n\r\n        cancelarOverlayPendiente();\r\n\r\n        timerOverlay = setTimeout(function () {\r\n            timerOverlay = null;\r\n\r\n            const container = document.querySelector('.categoria-selected');\r\n            if (!container) return;\r\n\r\n            let overlay = container.querySelector('.loading-overlay-categories');\r\n            if (!overlay) {\r\n                overlay = document.createElement('div');\r\n                overlay.className = 'loading-overlay-categories';\r\n                overlay.innerHTML = `\r\n                    <div class=\"spinner-categories\"><\/div>\r\n                    <span class=\"loading-text-categories\">${mensaje}<\/span>\r\n                `;\r\n                container.style.position = 'relative';\r\n                container.appendChild(overlay);\r\n            }\r\n        }, RETRASO_OVERLAY);\r\n    }\r\n\r\n    function ocultarCargando() {\r\n        cancelarOverlayPendiente();\r\n\r\n        \/\/ A partir de aca cualquier carga es por accion del usuario\r\n        cargaInicial = false;\r\n\r\n        const overlay = document.querySelector('.loading-overlay-categories');\r\n        if (overlay) {\r\n            overlay.remove();\r\n        }\r\n    }\r\n\r\n    let arbolPromesa = null;\r\n\r\n    function obtenerArbol() {\r\n\r\n        if (window.SOTHERS_ARBOL && Array.isArray(window.SOTHERS_ARBOL.categorias)) {\r\n            return Promise.resolve(window.SOTHERS_ARBOL);\r\n        }\r\n\r\n        if (!arbolPromesa) {\r\n\r\n            console.warn('window.SOTHERS_ARBOL ausente. Se pide por AJAX (modo respaldo).');\r\n\r\n            arbolPromesa = Promise.resolve(\r\n                jQuery.post(\r\n                    (window.popupCartData && window.popupCartData.ajaxUrl) || '\/wp-admin\/admin-ajax.php',\r\n                    { action: 'get_sothers_arbol' }\r\n                )\r\n            ).then(function (respuesta) {\r\n\r\n                if (respuesta && respuesta.success && respuesta.data &&\r\n                    Array.isArray(respuesta.data.categorias)) {\r\n                    window.SOTHERS_ARBOL = respuesta.data;\r\n                    return respuesta.data;\r\n                }\r\n\r\n                throw new Error('El respaldo del arbol no devolvio datos validos');\r\n            });\r\n        }\r\n\r\n        return arbolPromesa;\r\n    }\r\n\r\n    async function fetchWooCommerceData(endpoint, params = {}) {\r\n\r\n        const arbol = await obtenerArbol();\r\n\r\n        if (endpoint === 'products\/categories') {\r\n            const padre = parseInt(params.parent, 10);\r\n\r\n            const categorias = padre\r\n                ? arbol.categorias.filter(c => c.parent === padre)\r\n                : arbol.categorias;\r\n\r\n            console.log('Arbol: ' + categorias.length + ' categorias (sin red)');\r\n            return categorias;\r\n        }\r\n\r\n        if (endpoint === 'products') {\r\n            const productos = arbol.productos[String(params.category)] || [];\r\n            console.log('Arbol: ' + productos.length + ' productos (sin red)');\r\n            return productos;\r\n        }\r\n\r\n        throw new Error('Endpoint no contemplado en el arbol: ' + endpoint);\r\n    }\r\n\r\n    async function loadCategorias(servicioId) {\r\n        try {\r\n            \/\/ Mostrar indicador de carga\r\n            mostrarCargando('Cargando categor\u00edas...');\r\n            \r\n            optionsListCategories.innerHTML = '<div class=\"loading-message-cat\">Cargando categor\u00edas...<\/div>';\r\n            categoriasData = {};\r\n            \r\n            const subcategorias = await fetchWooCommerceData('products\/categories', {\r\n                parent: servicioId,\r\n                per_page: 100,\r\n                hide_empty: true\r\n            });\r\n\r\n            optionsListCategories.innerHTML = '';\r\n            hiddenSelectCategories.innerHTML = '';\r\n\r\n            if (!subcategorias || subcategorias.length === 0) {\r\n                optionsListCategories.innerHTML = '<div class=\"waiting-message\">No hay categor\u00edas disponibles<\/div>';\r\n                disableSelector();\r\n                ocultarCargando();\r\n                return;\r\n            }\r\n\r\n            enableSelector();\r\n\r\n            subcategorias.forEach(categoria => {\r\n                categoriasData[categoria.slug] = {\r\n                    id: categoria.id,\r\n                    name: categoria.name,\r\n                    slug: categoria.slug,\r\n                    parent: categoria.parent\r\n                };\r\n\r\n                const optionDiv = document.createElement('div');\r\n                optionDiv.className = 'custom-option-categories';\r\n                optionDiv.dataset.value = categoria.slug;\r\n                optionDiv.textContent = categoria.name;\r\n                optionDiv.addEventListener('click', () => selectOptionCategories(categoria.slug, categoria.name));\r\n                optionsListCategories.appendChild(optionDiv);\r\n\r\n                const optionSelect = document.createElement('option');\r\n                optionSelect.value = categoria.slug;\r\n                optionSelect.textContent = categoria.name;\r\n                hiddenSelectCategories.appendChild(optionSelect);\r\n            });\r\n\r\n            ocultarCargando();\r\n\r\n        } catch (error) {\r\n            console.error('Error cargando categor\u00edas:', error);\r\n            optionsListCategories.innerHTML = '<div class=\"error-message-cat\">Error al cargar categor\u00edas<\/div>';\r\n            disableSelector();\r\n            ocultarCargando();\r\n        }\r\n    }\r\n\r\n    function enableSelector() {\r\n        containerCategories.classList.remove('disabled-selector');\r\n    }\r\n\r\n    function disableSelector() {\r\n        containerCategories.classList.add('disabled-selector');\r\n        closeSelectCategories();\r\n    }\r\n\r\n    function toggleSelectCategories() {\r\n        if (containerCategories.classList.contains('disabled-selector')) return;\r\n        \r\n        isOpenCategories = !isOpenCategories;\r\n        \r\n        if (isOpenCategories) {\r\n            optionsListCategories.classList.add('show');\r\n            if (arrowIconCategories) {\r\n                arrowIconCategories.classList.add('arrow-rotated-categories');\r\n                arrowIconCategories.classList.remove('arrow-normal-categories');\r\n            }\r\n        } else {\r\n            optionsListCategories.classList.remove('show');\r\n            if (arrowIconCategories) {\r\n                arrowIconCategories.classList.add('arrow-normal-categories');\r\n                arrowIconCategories.classList.remove('arrow-rotated-categories');\r\n            }\r\n        }\r\n    }\r\n\r\n    function closeSelectCategories() {\r\n        isOpenCategories = false;\r\n        optionsListCategories.classList.remove('show');\r\n        if (arrowIconCategories) {\r\n            arrowIconCategories.classList.add('arrow-normal-categories');\r\n            arrowIconCategories.classList.remove('arrow-rotated-categories');\r\n        }\r\n    }\r\n\r\n    function selectOptionCategories(value, text) {\r\n        console.log('\ud83c\udff7\ufe0f Seleccionando categor\u00eda:', text);\r\n\r\n        if (selectedTextCategories) {\r\n            selectedTextCategories.textContent = text;\r\n        }\r\n        \r\n        hiddenSelectCategories.value = value;\r\nif (titleElementCategories && value !== '') {\r\n            titleElementCategories.textContent = text.toUpperCase();\r\n        } else if (titleElementCategories) {\r\n            titleElementCategories.textContent = '';\r\n        }\r\n\r\n        \/\/ La X solo tiene sentido si hay algo que limpiar\r\n        document.documentElement.classList.toggle('sothers-categoria-elegida', value !== '');\r\n        \r\n        document.querySelectorAll('.custom-option-categories').forEach(option => {\r\n            option.classList.remove('selected');\r\n            if (option.dataset.value === value) {\r\n                option.classList.add('selected');\r\n            }\r\n        });\r\n        \r\n        closeSelectCategories();\r\n\r\n        const event = new CustomEvent('categoriaSeleccionada', {\r\n            detail: {\r\n                categoriaSlug: value,\r\n                categoriaData: categoriasData[value]\r\n            }\r\n        });\r\n        document.dispatchEvent(event);\r\n\r\n        localStorage.setItem('selectedCategoria', JSON.stringify({\r\n            slug: value,\r\n            data: categoriasData[value]\r\n        }));\r\n    }\r\n\r\n\r\n    function clearSelector(mantenerOpciones) {\r\n        console.log('\ud83e\uddf9 Limpiando categor\u00edas' + (mantenerOpciones ? ' (conservando opciones)' : ''));\r\n\r\n        if (selectedTextCategories) {\r\n            selectedTextCategories.textContent = '';\r\n        }\r\nif (titleElementCategories) {\r\n            titleElementCategories.textContent = '';\r\n        }\r\n\r\n        \/\/ Sin seleccion no hay X, y el texto de carga tampoco debe volver\r\n        document.documentElement.classList.remove('sothers-categoria-elegida');\r\n        document.documentElement.classList.add('sothers-categorias-listas');\r\n\r\n        hiddenSelectCategories.value = '';\r\n\r\n        document.querySelectorAll('.custom-option-categories').forEach(option => {\r\n            option.classList.remove('selected');\r\n        });\r\n\r\n        const hayOpcionesCargadas = Object.keys(categoriasData).length > 0;\r\n\r\n        if (mantenerOpciones === true && hayOpcionesCargadas) {\r\n\r\n            enableSelector();\r\n            closeSelectCategories();\r\n        } else {\r\n            optionsListCategories.innerHTML = '<div class=\"waiting-message\">Selecciona un \u00e1rea primero<\/div>';\r\n            disableSelector();\r\n        }\r\n\r\n        localStorage.removeItem('selectedCategoria');\r\n\r\n        document.dispatchEvent(new CustomEvent('categoriaLimpiada'));\r\n    }\r\n\r\n    function validarYRecuperar() {\r\n        console.log('\ud83d\udd0d Validando categor\u00eda...');\r\n\r\n        if (fromPopupMenu) {\r\n            console.log('\ud83c\udfaf Popup - NO autocompletar');\r\n            return;\r\n        }\r\n\r\n        const servicioGuardado = localStorage.getItem('selectedServicio');\r\n        const categoriaGuardada = localStorage.getItem('selectedCategoria');\r\n\r\n        if (categoriaGuardada && !servicioGuardado) {\r\n            console.log('\u26a0\ufe0f Categor\u00eda sin servicio, limpiando...');\r\n            clearSelector();\r\n            return;\r\n        }\r\n\r\n        if (servicioSeleccionado && categoriaGuardada) {\r\n            try {\r\n                const parsed = JSON.parse(categoriaGuardada);\r\n                console.log('\ud83d\udd04 Recuperando categor\u00eda:', parsed.data.name);\r\n                \r\n                if (parsed.data.parent === servicioSeleccionado.id) {\r\n                    \/\/ Mostrar indicador\r\n                    mostrarCargando('Recuperando categor\u00eda...');\r\n                    \r\n                    setTimeout(() => {\r\n                        if (categoriasData[parsed.slug]) {\r\n                            selectOptionCategories(parsed.slug, parsed.data.name);\r\n                        } else {\r\n                            console.log('\u26a0\ufe0f Categor\u00eda no encontrada');\r\n                            clearSelector();\r\n                        }\r\n                        ocultarCargando();\r\n                    }, 250);\r\n                } else {\r\n                    console.log('\u26a0\ufe0f Categor\u00eda no pertenece al servicio');\r\n                    clearSelector();\r\n                }\r\n            } catch (e) {\r\n                console.error('\u274c Error recuperando categor\u00eda:', e);\r\n                clearSelector();\r\n            }\r\n        }\r\n    }\r\n\r\n    \/\/ Event listeners\r\n    document.addEventListener('servicioSeleccionado', function(e) {\r\n        console.log('\ud83d\udccb Servicio seleccionado');\r\n        servicioSeleccionado = e.detail.servicioData;\r\n        loadCategorias(servicioSeleccionado.id).then(() => {\r\n            validarYRecuperar();\r\n\r\n            document.documentElement.classList.add('sothers-categorias-listas');\r\n        });\r\n    });\r\n\r\n    document.addEventListener('servicioLimpiado', function() {\r\n        servicioSeleccionado = null;\r\n        fromPopupMenu = false;\r\n        clearSelector();\r\n    });\r\n\r\n    document.addEventListener('popupMenuAplicado', function() {\r\n        console.log('\ud83c\udfaf Popup detectado');\r\n        fromPopupMenu = true;\r\n    });\r\n\r\n    document.addEventListener('limpiarTodasLasSelecciones', function() {\r\n        servicioSeleccionado = null;\r\n        fromPopupMenu = false;\r\n        clearSelector();\r\n    });\r\n\r\n    document.addEventListener('estadoInconsistente', function() {\r\n        servicioSeleccionado = null;\r\n        fromPopupMenu = false;\r\n        clearSelector();\r\n    });\r\n    \r\n    const productTitleCategories = document.querySelector('.categoria-option .elementor-heading-title');\r\n    if (productTitleCategories) {\r\n        productTitleCategories.style.cursor = 'pointer';\r\n        productTitleCategories.addEventListener('click', toggleSelectCategories);\r\n    }\r\n    \r\n    const arrowContainerCategories = document.querySelector('.categoria-arrow');\r\n    if (arrowContainerCategories) {\r\n        arrowContainerCategories.style.cursor = 'pointer';\r\n        arrowContainerCategories.addEventListener('click', toggleSelectCategories);\r\n    }\r\n    \r\n    if (selectDisplayCategories) {\r\n        selectDisplayCategories.addEventListener('click', toggleSelectCategories);\r\n    }\r\n    \r\n    if (closeIconCategories) {\r\n        closeIconCategories.style.cursor = 'pointer';\r\n\r\n        closeIconCategories.addEventListener('click', function () {\r\n            clearSelector(true);\r\n        });\r\n    }\r\n    \r\n    document.addEventListener('click', function(e) {\r\n        const container = document.querySelector('.custom-select-container-categories');\r\n        const titleElement = document.querySelector('.categoria-option');\r\n        const arrowElement = document.querySelector('.categoria-arrow');\r\n        \r\n        if (container && !container.contains(e.target) && \r\n            (!titleElement || !titleElement.contains(e.target)) && \r\n            (!arrowElement || !arrowElement.contains(e.target))) {\r\n            closeSelectCategories();\r\n        }\r\n    });\r\n    \r\n    if (arrowIconCategories) {\r\n        arrowIconCategories.classList.add('arrow-normal-categories');\r\n    }\r\n\r\n    disableSelector();\r\n\r\n\r\n    setTimeout(function recuperarServicioDesdeStorage() {\r\n        if (servicioSeleccionado) {\r\n            return;\r\n        }\r\n\r\n        try {\r\n            const guardado = JSON.parse(localStorage.getItem('selectedServicio') || 'null');\r\n\r\n            if (guardado && guardado.data && guardado.data.id) {\r\n                console.log('Servicio recuperado de localStorage:', guardado.data.name);\r\n                servicioSeleccionado = guardado.data;\r\n                loadCategorias(servicioSeleccionado.id).then(validarYRecuperar);\r\n            }\r\n        } catch (e) {\r\n            console.warn('No se pudo recuperar el servicio guardado:', e);\r\n        }\r\n    }, 100);\r\n\r\n    console.log('\u2705 Selector de categor\u00edas optimizado');\r\n});\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-77659d0 elementor-widget elementor-widget-heading\" data-id=\"77659d0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">  <\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-45c9b10 categoria-close elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"45c9b10\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-times\" viewbox=\"0 0 352 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3d05ee1 e-con-full e-flex e-con e-child\" data-id=\"3d05ee1\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-b8da1b8 e-con-full producto-option e-flex e-con e-child\" data-id=\"b8da1b8\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9086c02 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"9086c02\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Selecciona tu experencia<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-232ef01 producto-arrow elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"232ef01\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-chevron-left\" viewbox=\"0 0 320 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-36a7070 e-con-full producto-selected e-flex e-con e-child\" data-id=\"36a7070\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-940a790 elementor-absolute elementor-widget elementor-widget-html\" data-id=\"940a790\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;_position&quot;:&quot;absolute&quot;}\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- HTML PERSONALIZADO - SELECTOR DE PRODUCTOS CORREGIDO -->\r\n<div class=\"custom-select-container-masajes\">\r\n    <div class=\"custom-select-display-masajes\" id=\"selectDisplayMasajes\">\r\n        <span id=\"selectedSpanMasajes\"><\/span>\r\n    <\/div>\r\n    <select id=\"hiddenSelectMasajes\" style=\"display: none;\">\r\n        <!-- Se llenar\u00e1 din\u00e1micamente -->\r\n    <\/select>\r\n    <div class=\"custom-options-masajes\" id=\"optionsListMasajes\">\r\n        <div class=\"waiting-message-prod\">Select a service first<\/div>\r\n    <\/div>\r\n<\/div>\r\n\r\n<style>\r\n.custom-select-container-masajes {\r\n    position: relative;\r\n    width: 300px;\r\n}\r\n\r\n.custom-select-display-masajes {\r\n    cursor: pointer;\r\n    user-select: none;\r\n}\r\n\r\n.custom-options-masajes {\r\n    position: absolute;\r\n    top: 100%;\r\n    left: 0;\r\n    right: 0;\r\n    background: white;\r\n    border: 1px solid #ddd;\r\n    border-radius: 4px;\r\n    box-shadow: 0 2px 10px rgba(0,0,0,0.1);\r\n    z-index: 1000;\r\n    max-height: 250px;\r\n    overflow-y: auto;\r\n    opacity: 0;\r\n    visibility: hidden;\r\n    transform: translateY(-10px);\r\n    transition: all 0.3s ease;\r\n}\r\n\r\n.custom-options-masajes.show {\r\n    opacity: 1;\r\n    visibility: visible;\r\n    transform: translateY(0);\r\n}\r\n\r\n.custom-option-masajes {\r\n    padding: 12px 16px;\r\n    cursor: pointer;\r\n    transition: background-color 0.2s ease;\r\n    border-bottom: 1px solid #f0f0f0;\r\n}\r\n\r\n.custom-option-masajes:last-child {\r\n    border-bottom: none;\r\n}\r\n\r\n.custom-option-masajes:hover {\r\n    background-color: #f5f5f5;\r\n}\r\n\r\n.custom-option-masajes.selected {\r\n    background-color: #e3f2fd;\r\n    color: #1976d2;\r\n}\r\n\r\n.product-option-content {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    width: 100%;\r\n}\r\n\r\n.product-name {\r\n    flex: 1;\r\n    margin-right: 10px;\r\n}\r\n\r\n.product-price {\r\n    color: #31989E;\r\n    font-weight: bold;\r\n    font-size: 0.9em;\r\n}\r\n\r\n.waiting-message-prod, .loading-message-prod {\r\n    padding: 12px 16px;\r\n    text-align: center;\r\n    color: #666;\r\n    font-style: italic;\r\n}\r\n\r\n.error-message-prod {\r\n    padding: 12px 16px;\r\n    text-align: center;\r\n    color: #dc2626;\r\n    background-color: #fef2f2;\r\n}\r\n\r\n.disabled-selector-prod {\r\n    opacity: 0.5;\r\n    pointer-events: none;\r\n}\r\n\r\n\/* Clase para rotar la flecha *\/\r\n.arrow-rotated-masajes {\r\n    transform: rotate(-90deg) !important;\r\n    transition: transform 0.3s ease !important;\r\n}\r\n\r\n.arrow-normal-masajes {\r\n    transform: rotate(0deg) !important;\r\n    transition: transform 0.3s ease !important;\r\n}\r\n\r\n#selectedTextMasajes{\r\n    text-align: var(--text-align);\r\n    margin-block-end: 1rem;\r\n    margin-block-start: .5rem;\r\n    box-sizing: border-box;\r\n    line-height: 1;\r\n    margin: 0;\r\n    margin-top: 5px;\r\n    padding: 0;\r\n    font-family: \"Josefin Sans\", Sans-serif;\r\n    font-size: 16px;\r\n    font-weight: 600;\r\n    color: var( --e-global-color-primary );\r\n    text-transform: uppercase;\r\n}\r\n\r\n.loading-overlay-productos {\r\n    position: absolute;\r\n    top: 0;\r\n    left: 0;\r\n    right: 0;\r\n    bottom: 0;\r\n    background: rgba(255, 255, 255, 0.95);\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    z-index: 10000;\r\n    border-radius: 4px;\r\n}\r\n\r\n.spinner-productos {\r\n    border: 3px solid #f3f3f3;\r\n    border-top: 3px solid #31989E;\r\n    border-radius: 50%;\r\n    width: 30px;\r\n    height: 30px;\r\n    animation: spin-productos 0.8s linear infinite;\r\n}\r\n\r\n@keyframes spin-productos {\r\n    0% { transform: rotate(0deg); }\r\n    100% { transform: rotate(360deg); }\r\n}\r\n\r\n\/* ---------- TEXTO DE CARGA ANTES DE HIDRATAR ---------- *\/\r\n.producto-selected .elementor-heading-title:empty::after {\r\n    content: 'Cargando...';\r\n    color: #b9bcc0;\r\n    font-weight: 400;\r\n    font-style: italic;\r\n    text-transform: none;\r\n}\r\n\r\nhtml.sothers-productos-listos .producto-selected .elementor-heading-title:empty::after {\r\n    content: none;\r\n}\r\n\r\n\/* ---------- X SOLO CON SELECCION ACTIVA ---------- *\/\r\n.producto-close {\r\n    opacity: 0;\r\n    pointer-events: none;\r\n    transition: opacity 0.2s ease;\r\n}\r\n\r\nhtml.sothers-producto-elegido .producto-close {\r\n    opacity: 1;\r\n    pointer-events: auto;\r\n}\r\n\r\n.loading-text-productos {\r\n    margin-left: 12px;\r\n    color: #31989E;\r\n    font-weight: 600;\r\n    font-size: 14px;\r\n}\r\n<\/style>\r\n\r\n<script>\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    console.log('SELECTOR DE experiencias');\r\n\r\n    let productosData = {};\r\n    let categoriaSeleccionada = null;\r\n    let fromPopupMenu = false;\r\n    \r\n    let servicioSeleccionado = null;\r\n    \r\n    document.addEventListener('servicioSeleccionado', function(e) {\r\n        servicioSeleccionado = {\r\n            slug: e.detail?.servicioSlug,\r\n            data: e.detail?.servicioData\r\n        };\r\n    });\r\n\r\ntry {\r\n    const saved = JSON.parse(localStorage.getItem('selectedServicio') || 'null');\r\n    if (saved?.slug) servicioSeleccionado = saved;\r\n} catch (err) {}\r\n    \r\n    const selectDisplayMasajes = document.getElementById('selectDisplayMasajes');\r\n    const optionsListMasajes = document.getElementById('optionsListMasajes');\r\n    const hiddenSelectMasajes = document.getElementById('hiddenSelectMasajes');\r\n    const selectedTextMasajes = document.getElementById('selectedTextMasajes');\r\n    const containerMasajes = document.querySelector('.custom-select-container-masajes');\r\n    const titleElementMasajes = document.querySelector('.producto-selected .elementor-heading-title');\r\n    const arrowIconMasajes = document.querySelector('.producto-arrow .elementor-icon svg');\r\n    const closeIconMasajes = document.querySelector('.producto-close');\r\n    \r\n    let isOpenMasajes = false;\r\n\r\n    const RETRASO_OVERLAY = 350;\r\n    let timerOverlay = null;\r\n    let cargaInicial = true;\r\n\r\n    function cancelarOverlayPendiente() {\r\n        if (timerOverlay) {\r\n            clearTimeout(timerOverlay);\r\n            timerOverlay = null;\r\n        }\r\n    }\r\n\r\n    function mostrarCargando(mensaje = 'Cargando...') {\r\n        if (cargaInicial) {\r\n            return;\r\n        }\r\n\r\n        cancelarOverlayPendiente();\r\n\r\n        timerOverlay = setTimeout(function () {\r\n            timerOverlay = null;\r\n\r\n            const container = document.querySelector('.producto-selected');\r\n            if (!container) return;\r\n\r\n            let overlay = container.querySelector('.loading-overlay-productos');\r\n            if (!overlay) {\r\n                overlay = document.createElement('div');\r\n                overlay.className = 'loading-overlay-productos';\r\n                overlay.innerHTML = `\r\n                    <div class=\"spinner-productos\"><\/div>\r\n                    <span class=\"loading-text-productos\">${mensaje}<\/span>\r\n                `;\r\n                container.style.position = 'relative';\r\n                container.appendChild(overlay);\r\n            }\r\n        }, RETRASO_OVERLAY);\r\n    }\r\n\r\n    function ocultarCargando() {\r\n        cancelarOverlayPendiente();\r\n\r\n        \/\/ A partir de aca cualquier carga es por accion del usuario\r\n        cargaInicial = false;\r\n\r\n        const overlay = document.querySelector('.loading-overlay-productos');\r\n        if (overlay) {\r\n            overlay.remove();\r\n        }\r\n    }\r\n\r\n    let arbolPromesa = null;\r\n\r\n    function obtenerArbol() {\r\n\r\n        if (window.SOTHERS_ARBOL && Array.isArray(window.SOTHERS_ARBOL.categorias)) {\r\n            return Promise.resolve(window.SOTHERS_ARBOL);\r\n        }\r\n\r\n        if (!arbolPromesa) {\r\n\r\n            console.warn('window.SOTHERS_ARBOL ausente. Se pide por AJAX (modo respaldo).');\r\n\r\n            arbolPromesa = Promise.resolve(\r\n                jQuery.post(\r\n                    (window.popupCartData && window.popupCartData.ajaxUrl) || '\/wp-admin\/admin-ajax.php',\r\n                    { action: 'get_sothers_arbol' }\r\n                )\r\n            ).then(function (respuesta) {\r\n\r\n                if (respuesta && respuesta.success && respuesta.data &&\r\n                    Array.isArray(respuesta.data.categorias)) {\r\n                    window.SOTHERS_ARBOL = respuesta.data;\r\n                    return respuesta.data;\r\n                }\r\n\r\n                throw new Error('El respaldo del arbol no devolvio datos validos');\r\n            });\r\n        }\r\n\r\n        return arbolPromesa;\r\n    }\r\n\r\n    async function fetchWooCommerceData(endpoint, params = {}) {\r\n\r\n        const arbol = await obtenerArbol();\r\n\r\n        if (endpoint === 'products\/categories') {\r\n            const padre = parseInt(params.parent, 10);\r\n\r\n            const categorias = padre\r\n                ? arbol.categorias.filter(c => c.parent === padre)\r\n                : arbol.categorias;\r\n\r\n            console.log('Arbol: ' + categorias.length + ' categorias (sin red)');\r\n            return categorias;\r\n        }\r\n\r\n        if (endpoint === 'products') {\r\n            const productos = arbol.productos[String(params.category)] || [];\r\n            console.log('Arbol: ' + productos.length + ' productos (sin red)');\r\n            return productos;\r\n        }\r\n\r\n        throw new Error('Endpoint no contemplado en el arbol: ' + endpoint);\r\n    }\r\n\r\n    function formatPrice(price) {\r\n        return new Intl.NumberFormat('es-CL', {\r\n            style: 'currency',\r\n            currency: 'CLP',\r\n            minimumFractionDigits: 0,\r\n            maximumFractionDigits: 0\r\n        }).format(parseFloat(price));\r\n    }\r\n    \r\n    const PRODUCTO_PERMITIDO_POR_CATEGORIA = {\r\n    'tratamientos-corporales': 'evaluacion-bodytech', \r\n    'tratamientos-faciales': 'evaluacion-facetech'\r\n};\r\n\r\nasync function loadProductos(categoriaId) {\r\n    try {\r\n        mostrarCargando('Cargando experiencias.');\r\n\r\n        optionsListMasajes.innerHTML = '<div class=\"loading-message-prod\">Cargando experiencias.<\/div>';\r\n        productosData = {};\r\n\r\n        const productos = await fetchWooCommerceData('products', {\r\n            category: categoriaId,\r\n            per_page: 100,\r\n            status: 'publish'\r\n        });\r\n\r\n        optionsListMasajes.innerHTML = '';\r\n        hiddenSelectMasajes.innerHTML = '';\r\n\r\n        if (!productos || productos.length === 0) {\r\n            optionsListMasajes.innerHTML = '<div class=\"waiting-message-prod\">No hay experiencias disponibles<\/div>';\r\n            disableSelector();\r\n            ocultarCargando();\r\n            return;\r\n        }\r\n\r\n        let productosFinal = productos;\r\n\r\n        if (servicioSeleccionado?.slug === 'med-spa') {\r\n            const categoriaSlug = categoriaSeleccionada?.slug;\r\n            const slugPermitido = categoriaSlug ? PRODUCTO_PERMITIDO_POR_CATEGORIA[categoriaSlug] : null;\r\n        \r\n            if (slugPermitido) {\r\n                productosFinal = productos.filter(p => p.slug === slugPermitido);\r\n            }\r\n        }\r\n\r\n        if (!productosFinal || productosFinal.length === 0) {\r\n            optionsListMasajes.innerHTML = '<div class=\"waiting-message-prod\">No hay experiencias disponibles<\/div>';\r\n            disableSelector();\r\n            ocultarCargando();\r\n            return;\r\n        }\r\n\r\n        enableSelector();\r\n\r\n        productosFinal.forEach(producto => {\r\n\r\n            const price = producto.sale_price || producto.regular_price || producto.price || '0';\r\n            const regularPrice = producto.regular_price || '0';\r\n            const salePrice = producto.sale_price || null;\r\n\r\n            productosData[producto.slug] = {\r\n                id: producto.id,\r\n                name: producto.name,\r\n                slug: producto.slug,\r\n                price: parseFloat(price),\r\n                regular_price: parseFloat(regularPrice),\r\n                sale_price: salePrice ? parseFloat(salePrice) : null,\r\n                description: producto.short_description || '',\r\n                images: producto.images || [],\r\n                sku: producto.sku || '',\r\n                stock_status: producto.stock_status || 'instock',\r\n                meta_data: producto.meta_data || []\r\n            };\r\n\r\n            const optionDiv = document.createElement('div');\r\n            optionDiv.className = 'custom-option-masajes';\r\n            optionDiv.dataset.value = producto.slug;\r\n\r\n            const contentDiv = document.createElement('div');\r\n            contentDiv.className = 'product-option-content';\r\n\r\n            const nameSpan = document.createElement('span');\r\n            nameSpan.className = 'product-name';\r\n            nameSpan.textContent = producto.name;\r\n\r\n            const priceSpan = document.createElement('span');\r\n            priceSpan.className = 'product-price';\r\n\r\n            if (salePrice && salePrice < parseFloat(regularPrice)) {\r\n                priceSpan.innerHTML = `\r\n                    <span style=\"text-decoration: line-through; color: #999; margin-right: 5px; font-size: 0.8em;\">\r\n                        ${formatPrice(regularPrice)}\r\n                    <\/span>\r\n                    ${formatPrice(salePrice)}\r\n                `;\r\n            } else {\r\n                priceSpan.textContent = formatPrice(price);\r\n            }\r\n\r\n            contentDiv.appendChild(nameSpan);\r\n            contentDiv.appendChild(priceSpan);\r\n            optionDiv.appendChild(contentDiv);\r\n\r\n            optionDiv.addEventListener('click', () => selectOptionMasajes(producto.slug, producto.name));\r\n            optionsListMasajes.appendChild(optionDiv);\r\n\r\n            const optionSelect = document.createElement('option');\r\n            optionSelect.value = producto.slug;\r\n            optionSelect.textContent = `${producto.name} - ${formatPrice(price)}`;\r\n            optionSelect.dataset.price = price;\r\n            optionSelect.dataset.productId = producto.id;\r\n            hiddenSelectMasajes.appendChild(optionSelect);\r\n        });\r\n\r\n        if (servicioSeleccionado?.slug === 'med-spa' && productosFinal.length === 1) {\r\n            selectOptionMasajes(productosFinal[0].slug, productosFinal[0].name);\r\n        }\r\n\r\n        ocultarCargando();\r\n\r\n    } catch (error) {\r\n        console.error('Error cargando experiencias:', error);\r\n        optionsListMasajes.innerHTML = '<div class=\"error-message-prod\">Error al cargar productos<\/div>';\r\n        disableSelector();\r\n        ocultarCargando();\r\n    }\r\n}\r\n\r\n    function enableSelector() {\r\n        containerMasajes.classList.remove('disabled-selector-prod');\r\n    }\r\n\r\n    function disableSelector() {\r\n        containerMasajes.classList.add('disabled-selector-prod');\r\n        closeSelectMasajes();\r\n    }\r\n\r\n    function toggleSelectMasajes() {\r\n        if (containerMasajes.classList.contains('disabled-selector-prod')) return;\r\n        \r\n        isOpenMasajes = !isOpenMasajes;\r\n        \r\n        if (isOpenMasajes) {\r\n            optionsListMasajes.classList.add('show');\r\n            if (arrowIconMasajes) {\r\n                arrowIconMasajes.classList.add('arrow-rotated-masajes');\r\n                arrowIconMasajes.classList.remove('arrow-normal-masajes');\r\n            }\r\n        } else {\r\n            optionsListMasajes.classList.remove('show');\r\n            if (arrowIconMasajes) {\r\n                arrowIconMasajes.classList.add('arrow-normal-masajes');\r\n                arrowIconMasajes.classList.remove('arrow-rotated-masajes');\r\n            }\r\n        }\r\n    }\r\n\r\n    function closeSelectMasajes() {\r\n        isOpenMasajes = false;\r\n        optionsListMasajes.classList.remove('show');\r\n        if (arrowIconMasajes) {\r\n            arrowIconMasajes.classList.add('arrow-normal-masajes');\r\n            arrowIconMasajes.classList.remove('arrow-rotated-masajes');\r\n        }\r\n    }\r\n\r\n    function selectOptionMasajes(value, text) {\r\n        console.log('\ud83c\udfaf Seleccionando producto:', text);\r\n\r\n        if (selectedTextMasajes) {\r\n            selectedTextMasajes.textContent = text;\r\n        }\r\n        \r\n        hiddenSelectMasajes.value = value;\r\n        \r\nif (titleElementMasajes && value !== '') {\r\n            titleElementMasajes.textContent = text.toUpperCase();\r\n        } else if (titleElementMasajes) {\r\n            titleElementMasajes.textContent = '';\r\n        }\r\n\r\n        document.documentElement.classList.toggle('sothers-producto-elegido', value !== '');\r\n        \r\n        document.querySelectorAll('.custom-option-masajes').forEach(option => {\r\n            option.classList.remove('selected');\r\n            if (option.dataset.value === value) {\r\n                option.classList.add('selected');\r\n            }\r\n        });\r\n        \r\n        closeSelectMasajes();\r\n\r\n        const event = new CustomEvent('productoSeleccionado', {\r\n            detail: {\r\n                productoSlug: value,\r\n                productoData: productosData[value],\r\n                categoriaData: categoriaSeleccionada\r\n            }\r\n        });\r\n        document.dispatchEvent(event);\r\n\r\n        localStorage.setItem('selectedProducto', JSON.stringify({\r\n            slug: value,\r\n            data: productosData[value]\r\n        }));\r\n\r\n        const cartEvent = new CustomEvent('agregarAlCarrito', {\r\n            detail: {\r\n                producto: productosData[value],\r\n                accion: 'seleccionado'\r\n            }\r\n        });\r\n        document.dispatchEvent(cartEvent);\r\n    }\r\n\r\n\r\n    function clearSelector(mantenerOpciones) {\r\n        console.log('\ud83e\uddf9 Limpiando experiencias' + (mantenerOpciones ? ' (conservando opciones)' : ''));\r\n\r\n        if (selectedTextMasajes) {\r\n            selectedTextMasajes.textContent = '';\r\n        }\r\n\r\nif (titleElementMasajes) {\r\n            titleElementMasajes.textContent = '';\r\n        }\r\n\r\n        document.documentElement.classList.remove('sothers-producto-elegido');\r\n        document.documentElement.classList.add('sothers-productos-listos');\r\n\r\n        hiddenSelectMasajes.value = '';\r\n\r\n        hiddenSelectMasajes.value = '';\r\n\r\n        document.querySelectorAll('.custom-option-masajes').forEach(option => {\r\n            option.classList.remove('selected');\r\n        });\r\n\r\n        const hayOpcionesCargadas = Object.keys(productosData).length > 0;\r\n\r\n        if (mantenerOpciones === true && hayOpcionesCargadas) {\r\n            enableSelector();\r\n            closeSelectMasajes();\r\n        } else {\r\n            optionsListMasajes.innerHTML = '<div class=\"waiting-message-prod\">Selecciona un servicio primero<\/div>';\r\n            disableSelector();\r\n        }\r\n\r\n        localStorage.removeItem('selectedProducto');\r\n\r\n        document.dispatchEvent(new CustomEvent('productoLimpiado'));\r\n    }\r\n\r\nfunction validarYRecuperar() {\r\n    console.log('\ud83d\udd0d Validando producto.');\r\n\r\n    if (fromPopupMenu) {\r\n        console.log('\ud83c\udfaf Popup - NO autocompletar');\r\n        return;\r\n    }\r\n\r\n    const servicioGuardado = localStorage.getItem('selectedServicio');\r\n    const categoriaGuardada = localStorage.getItem('selectedCategoria');\r\n    const productoGuardado = localStorage.getItem('selectedProducto');\r\n\r\n    if (productoGuardado && (!servicioGuardado || !categoriaGuardada)) {\r\n        console.log('\u26a0\ufe0f Producto sin padres, limpiando.');\r\n        clearSelector();\r\n        return;\r\n    }\r\n\r\n    if (!categoriaSeleccionada) return;\r\n\r\n\r\n    let slugARecuperar = null;\r\n    let nombreARecuperar = null;\r\n\r\n    if (servicioSeleccionado?.slug === 'med-spa') {\r\n        const categoriaSlug = categoriaSeleccionada?.slug;\r\n        const slugPermitido = categoriaSlug ? PRODUCTO_PERMITIDO_POR_CATEGORIA[categoriaSlug] : null;\r\n\r\n        if (slugPermitido) {\r\n            slugARecuperar = slugPermitido;\r\n\r\n            nombreARecuperar = productosData[slugPermitido]?.name || slugPermitido;\r\n        }\r\n    }\r\n\r\n    if (!slugARecuperar && productoGuardado) {\r\n        try {\r\n            const parsed = JSON.parse(productoGuardado);\r\n            slugARecuperar = parsed.slug;\r\n            nombreARecuperar = parsed.data?.name || parsed.slug;\r\n        } catch (e) {\r\n            console.error('\u274c Error leyendo productoGuardado:', e);\r\n            clearSelector();\r\n            return;\r\n        }\r\n    }\r\n\r\n    if (!slugARecuperar) return;\r\n\r\n    console.log('\ud83d\udd04 Recuperando producto final:', slugARecuperar);\r\n\r\n    mostrarCargando('Recuperando producto.');\r\n\r\n    setTimeout(() => {\r\n        if (productosData[slugARecuperar]) {\r\n\r\n            selectOptionMasajes(slugARecuperar, productosData[slugARecuperar].name);\r\n\r\n            localStorage.setItem('selectedProducto', JSON.stringify({\r\n                slug: slugARecuperar,\r\n                data: productosData[slugARecuperar]\r\n            }));\r\n        } else {\r\n            console.log('\u26a0\ufe0f Producto a recuperar no est\u00e1 en productosData, limpiando.');\r\n            clearSelector();\r\n        }\r\n        ocultarCargando();\r\n    }, 250);\r\n}\r\n\r\n\r\n    \/\/ Event listeners\r\ndocument.addEventListener('categoriaSeleccionada', function(e) {\r\n        console.log('\ud83c\udff7\ufe0f Categor\u00eda seleccionada');\r\n        categoriaSeleccionada = e.detail.categoriaData;\r\n        loadProductos(categoriaSeleccionada.id).then(() => {\r\n            validarYRecuperar();\r\n            document.documentElement.classList.add('sothers-productos-listos');\r\n        });\r\n    });\r\n\r\n    document.addEventListener('categoriaLimpiada', function() {\r\n        categoriaSeleccionada = null;\r\n        fromPopupMenu = false;\r\n        clearSelector();\r\n    });\r\n\r\n    document.addEventListener('servicioLimpiado', function() {\r\n        categoriaSeleccionada = null;\r\n        fromPopupMenu = false;\r\n        clearSelector();\r\n    });\r\n\r\n    document.addEventListener('popupMenuAplicado', function() {\r\n        console.log('\ud83c\udfaf Popup detectado');\r\n        fromPopupMenu = true;\r\n    });\r\n\r\n    document.addEventListener('limpiarTodasLasSelecciones', function() {\r\n        categoriaSeleccionada = null;\r\n        fromPopupMenu = false;\r\n        clearSelector();\r\n    });\r\n\r\n    document.addEventListener('estadoInconsistente', function() {\r\n        categoriaSeleccionada = null;\r\n        fromPopupMenu = false;\r\n        clearSelector();\r\n    });\r\n    \r\n    const productTitleMasajes = document.querySelector('.producto-option .elementor-heading-title');\r\n    if (productTitleMasajes) {\r\n        productTitleMasajes.style.cursor = 'pointer';\r\n        productTitleMasajes.addEventListener('click', toggleSelectMasajes);\r\n    }\r\n    \r\n    const arrowContainerMasajes = document.querySelector('.producto-arrow');\r\n    if (arrowContainerMasajes) {\r\n        arrowContainerMasajes.style.cursor = 'pointer';\r\n        arrowContainerMasajes.addEventListener('click', toggleSelectMasajes);\r\n    }\r\n    \r\n    if (selectDisplayMasajes) {\r\n        selectDisplayMasajes.addEventListener('click', toggleSelectMasajes);\r\n    }\r\n    \r\n    if (closeIconMasajes) {\r\n        closeIconMasajes.style.cursor = 'pointer';\r\n\r\n        closeIconMasajes.addEventListener('click', function () {\r\n            clearSelector(true);\r\n        });\r\n    }\r\n    \r\n    document.addEventListener('click', function(e) {\r\n        const container = document.querySelector('.custom-select-container-masajes');\r\n        const titleElement = document.querySelector('.producto-option');\r\n        const arrowElement = document.querySelector('.producto-arrow');\r\n        \r\n        if (container && !container.contains(e.target) && \r\n            (!titleElement || !titleElement.contains(e.target)) && \r\n            (!arrowElement || !arrowElement.contains(e.target))) {\r\n            closeSelectMasajes();\r\n        }\r\n    });\r\n    \r\n    if (arrowIconMasajes) {\r\n        arrowIconMasajes.classList.add('arrow-normal-masajes');\r\n    }\r\n\r\n    disableSelector();\r\n    console.log('\u2705 Selector de productos optimizado');\r\n});\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c1ba9ec elementor-widget elementor-widget-heading\" data-id=\"c1ba9ec\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\"> <\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b96794b producto-close elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"b96794b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-times\" viewbox=\"0 0 352 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b4596d9 e-con-full e-flex e-con e-child\" data-id=\"b4596d9\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-a3ba6b5 e-con-full regalar-container e-flex e-con e-child\" data-id=\"a3ba6b5\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-371cc84 e-con-full e-flex e-con e-child\" data-id=\"371cc84\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3680314 elementor-widget elementor-widget-heading\" data-id=\"3680314\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Do you want to give this experience as a gift?<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-967a932 e-con-full e-flex e-con e-child\" data-id=\"967a932\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-90bb1e6 elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"90bb1e6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"35.732\" height=\"25.523\" viewbox=\"0 0 35.732 25.523\"><path id=\"gift_card\" data-name=\"gift card\" d=\"M3,14.1A5.109,5.109,0,0,1,8.1,9H33.627a5.109,5.109,0,0,1,5.1,5.1V29.418a5.109,5.109,0,0,1-5.1,5.1H8.1a5.109,5.109,0,0,1-5.1-5.1ZM33.627,31.97a2.549,2.549,0,0,0,2.552-2.552V21.761H17.565l2.927,2.927a1.275,1.275,0,0,1-1.8,1.8l-2.927-2.927V31.97ZM20.645,19.209H36.179V14.1a2.549,2.549,0,0,0-2.552-2.552H15.761v2.773a3.725,3.725,0,0,1,1.276-.221,3.823,3.823,0,0,1,3.828,3.828A3.725,3.725,0,0,1,20.645,19.209Zm-3.607,0a1.276,1.276,0,1,0-1.276-1.276v1.276Zm-3.828-4.883V11.552H8.1A2.549,2.549,0,0,0,5.552,14.1v5.1H8.326A3.725,3.725,0,0,1,8.1,17.933,3.823,3.823,0,0,1,11.933,14.1,3.725,3.725,0,0,1,13.209,14.326Zm-1.276,4.883h1.276V17.933a1.276,1.276,0,1,0-1.276,1.276Zm-.527,2.552H5.552v7.657A2.549,2.549,0,0,0,8.1,31.97h5.1V23.565l-2.927,2.927a1.275,1.275,0,1,1-1.8-1.8Z\" transform=\"translate(-3 -9)\" fill=\"#31989e\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cce0a99 elementor-widget elementor-widget-heading\" data-id=\"cce0a99\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Gift Card<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-92b2cbd elementor-widget elementor-widget-heading\" data-id=\"92b2cbd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<p class=\"elementor-heading-title elementor-size-default\">Or if you prefer<\/p>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f47359c elementor-align-justify elementor-widget elementor-widget-button\" data-id=\"f47359c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"https:\/\/sparoysothers.cl\/en\/contacto\/\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Write us to reserve<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-90acfd9 elementor-align-justify paso1-boton-continuar elementor-widget elementor-widget-button\" data-id=\"90acfd9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"#complementa-tu-exp\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">CONTINUE<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-8347a5b e-con-full elementor-hidden-tablet elementor-hidden-mobile e-flex e-con e-child\" data-id=\"8347a5b\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-50bb3c3 e-con-full paso2-complementa-tu-experiencia e-flex e-con e-parent\" data-id=\"50bb3c3\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-d633fdb e-con-full e-flex e-con e-child\" data-id=\"d633fdb\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-77ed3fe elementor-widget elementor-widget-heading\" data-id=\"77ed3fe\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">COMPLEMENT YOUR EXPERIENCE<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-857f964 elementor-widget elementor-widget-text-editor\" data-id=\"857f964\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Choose from our exclusive massages designed to relieve tension, revitalize your skin, and provide an incomparable wellness experience.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7c666b1 e-con-full e-grid e-con e-child\" data-id=\"7c666b1\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-de4c424 e-con-full producto-relacionado-1 e-flex e-con e-child\" data-id=\"de4c424\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a84a141 imagen-relacionado-1 elementor-widget elementor-widget-image\" data-id=\"a84a141\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"520\" height=\"580\" src=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png\" class=\"attachment-large size-large wp-image-1364\" alt=\"\" srcset=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png 520w, https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x-269x300.png 269w\" sizes=\"(max-width: 520px) 100vw, 520px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-117bdcc titulo-relacionado-1 elementor-widget elementor-widget-heading\" data-id=\"117bdcc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">WATER CIRCUIT<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6f28e3a duracion-relacionado-1 elementor-widget elementor-widget-heading\" data-id=\"6f28e3a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">2 hours<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-57368e5 valor-relacionado-1 elementor-widget elementor-widget-heading\" data-id=\"57368e5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">$00.000<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-5aca60c e-con-full producto-relacionado-2 e-flex e-con e-child\" data-id=\"5aca60c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5b31a4a imagen-relacionado-2 elementor-widget elementor-widget-image\" data-id=\"5b31a4a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"520\" height=\"580\" src=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png\" class=\"attachment-large size-large wp-image-1364\" alt=\"\" srcset=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png 520w, https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x-269x300.png 269w\" sizes=\"(max-width: 520px) 100vw, 520px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-90f38d2 titulo-relacionado-2 elementor-widget elementor-widget-heading\" data-id=\"90f38d2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">WATER CIRCUIT<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d72b2a3 duracion-relacionado-2 elementor-widget elementor-widget-heading\" data-id=\"d72b2a3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">2 hours<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-25197ec valor-relacionado-2 elementor-widget elementor-widget-heading\" data-id=\"25197ec\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">$00.000<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-521d654 e-con-full producto-relacionado-3 e-flex e-con e-child\" data-id=\"521d654\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-16297ac imagen-relacionado-3 elementor-widget elementor-widget-image\" data-id=\"16297ac\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"520\" height=\"580\" src=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png\" class=\"attachment-large size-large wp-image-1364\" alt=\"\" srcset=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png 520w, https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x-269x300.png 269w\" sizes=\"(max-width: 520px) 100vw, 520px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-aa68a7d titulo-relacionado-3 elementor-widget elementor-widget-heading\" data-id=\"aa68a7d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">WATER CIRCUIT<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-94ced25 duracion-relacionado-3 elementor-widget elementor-widget-heading\" data-id=\"94ced25\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">2 hours<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-900b455 valor-relacionado-3 elementor-widget elementor-widget-heading\" data-id=\"900b455\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">$00.000<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d46991a elementor-align-justify paso2-boton-continuar elementor-widget elementor-widget-button\" data-id=\"d46991a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"#resumen-compra\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">CONTINUE<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-88b8d19 elementor-widget elementor-widget-html\" data-id=\"88b8d19\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\r\n\r\n<script>\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    \/\/ Configuraci\u00f3n de la API de WooCommerce\r\n    const WC_CONFIG = {\r\n        baseUrl: window.location.origin,\r\n        apiPath: '\/wp-json\/wc\/v3\/',\r\n        consumerKey: 'ck_6381579117ac59ad6ecbd38e618553eaa9856765',\r\n        consumerSecret: 'cs_e12f13e79017efdf5799f55fd22ad42c458dcb22',\r\n    };\r\n\r\n    \/\/ Variables globales\r\n    let productoPrincipal = null;\r\n    let productosRelacionados = [];\r\n    let productosSeleccionados = new Set();\r\n\r\n    \/\/ Elementos del DOM de Elementor con verificaci\u00f3n adicional\r\n    const containers = [\r\n        {\r\n            container: document.querySelector('.producto-relacionado-1, .elementor-element-428fbef'),\r\n            imagen: document.querySelector('.imagen-relacionado-1 img'),\r\n            titulo: document.querySelector('.titulo-relacionado-1 .elementor-heading-title'),\r\n            duracion: document.querySelector('.duracion-relacionado-1 .elementor-heading-title'), \r\n            valor: document.querySelector('.valor-relacionado-1 .elementor-heading-title')\r\n        },\r\n        {\r\n            container: document.querySelector('.producto-relacionado-2, .elementor-element-9e6bd04'),\r\n            imagen: document.querySelector('.imagen-relacionado-2 img'),\r\n            titulo: document.querySelector('.titulo-relacionado-2 .elementor-heading-title'),\r\n            duracion: document.querySelector('.duracion-relacionado-2 .elementor-heading-title'),\r\n            valor: document.querySelector('.valor-relacionado-2 .elementor-heading-title')\r\n        },\r\n        {\r\n            container: document.querySelector('.producto-relacionado-3, .elementor-element-0a368f9'),\r\n            imagen: document.querySelector('.imagen-relacionado-3 img'),\r\n            titulo: document.querySelector('.titulo-relacionado-3 .elementor-heading-title'),\r\n            duracion: document.querySelector('.duracion-relacionado-3 .elementor-heading-title'),\r\n            valor: document.querySelector('.valor-relacionado-3 .elementor-heading-title')\r\n        }\r\n    ];\r\n\r\n\r\n    \/\/ Funci\u00f3n para hacer llamadas a la API de WooCommerce\r\n    async function fetchWooCommerceData(endpoint, params = {}) {\r\n        try {\r\n            const url = new URL(WC_CONFIG.baseUrl + WC_CONFIG.apiPath + endpoint);\r\n            \r\n            Object.keys(params).forEach(key => {\r\n                url.searchParams.append(key, params[key]);\r\n            });\r\n\r\n            if (WC_CONFIG.consumerKey && WC_CONFIG.consumerSecret) {\r\n                url.searchParams.append('consumer_key', WC_CONFIG.consumerKey);\r\n                url.searchParams.append('consumer_secret', WC_CONFIG.consumerSecret);\r\n            }\r\n\r\n            const response = await fetch(url, {\r\n                method: 'GET',\r\n                headers: {\r\n                    'Content-Type': 'application\/json',\r\n                },\r\n            });\r\n            \r\n            if (!response.ok) {\r\n                throw new Error(`Error HTTP: ${response.status} - ${response.statusText}`);\r\n            }\r\n            \r\n            return await response.json();\r\n        } catch (error) {\r\n            console.error('\u274c Error al cargar datos de WooCommerce:', error);\r\n            throw error;\r\n        }\r\n    }\r\n\r\n    \/\/ Funci\u00f3n para obtener la mejor imagen del producto\r\n    function obtenerMejorImagen(producto) {\r\n        \r\n        \/\/ Verificar si hay im\u00e1genes\r\n        if (!producto.images || !Array.isArray(producto.images) || producto.images.length === 0) {\r\n            console.log('  \u274c No hay im\u00e1genes disponibles');\r\n            return 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png';\r\n        }\r\n        \r\n        \r\n        \/\/ Intentar obtener la imagen principal (featured)\r\n        const imagenPrincipal = producto.images.find(img => img.position === 0);\r\n        if (imagenPrincipal && imagenPrincipal.src) {\r\n            return imagenPrincipal.src;\r\n        }\r\n        \r\n        \/\/ Si no hay imagen principal, usar la primera disponible\r\n        const primeraImagen = producto.images[0];\r\n        if (primeraImagen && primeraImagen.src) {\r\n            return primeraImagen.src;\r\n        }\r\n        \r\n        return 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png';\r\n    }\r\n\r\n    \/\/ Cargar productos relacionados\r\n    async function cargarProductosRelacionados(productoId) {\r\n        try {\r\n            \r\n            \/\/ Mostrar loading\r\n            containers.forEach(container => {\r\n                if (container.titulo) container.titulo.textContent = 'Cargando...';\r\n                if (container.duracion) container.duracion.textContent = '';\r\n                if (container.valor) container.valor.textContent = '';\r\n            });\r\n            \r\n            \/\/ Obtener producto principal\r\n            const producto = await fetchWooCommerceData(`products\/${productoId}`);\r\n            \r\n            let productosEncontrados = [];\r\n            let estrategiaUsada = '';\r\n\r\n            \/\/ PRIORIDAD: Cross-sell primero (donde est\u00e1n los productos correctos)\r\n            if (producto.cross_sell_ids && Array.isArray(producto.cross_sell_ids) && producto.cross_sell_ids.length > 0) {\r\n                estrategiaUsada = 'cross_sell_ids';\r\n                \r\n                const idsLimitados = producto.cross_sell_ids.slice(0, 3);\r\n                const promesas = idsLimitados.map(async (id) => {\r\n                    try {\r\n                        const prod = await fetchWooCommerceData(`products\/${id}`);\r\n                        \r\n                        \/\/ Log de im\u00e1genes para debugging\r\n                        if (prod.images && prod.images.length > 0) {\r\n                            prod.images.forEach((img, idx) => {\r\n                            });\r\n                        }\r\n                        \r\n                        return prod;\r\n                    } catch (error) {\r\n                        console.error(`\u274c Error cargando cross-sell ${id}:`, error);\r\n                        return null;\r\n                    }\r\n                });\r\n                \r\n                const resultados = await Promise.all(promesas);\r\n                productosEncontrados = resultados.filter(p => p !== null);\r\n            }\r\n            \r\n            \/\/ Fallback: upsell_ids\r\n            if (productosEncontrados.length < 3 && producto.upsell_ids && Array.isArray(producto.upsell_ids) && producto.upsell_ids.length > 0) {\r\n                estrategiaUsada += ' + upsell_ids';\r\n                \r\n                const idsYaIncluidos = productosEncontrados.map(p => p.id);\r\n                const idsUpsellNuevos = producto.upsell_ids.filter(id => !idsYaIncluidos.includes(id));\r\n                const idsNecesarios = idsUpsellNuevos.slice(0, 3 - productosEncontrados.length);\r\n                \r\n                if (idsNecesarios.length > 0) {\r\n                    const promesasUpsell = idsNecesarios.map(async (id) => {\r\n                        try {\r\n                            const prod = await fetchWooCommerceData(`products\/${id}`);\r\n                            return prod;\r\n                        } catch (error) {\r\n                            console.error(`\u274c Error cargando upsell ${id}:`, error);\r\n                            return null;\r\n                        }\r\n                    });\r\n                    \r\n                    const resultadosUpsell = await Promise.all(promesasUpsell);\r\n                    productosEncontrados.push(...resultadosUpsell.filter(p => p !== null));\r\n                }\r\n            }\r\n            \r\n            \/\/ Fallback: related_ids\r\n            if (productosEncontrados.length < 3 && producto.related_ids && Array.isArray(producto.related_ids) && producto.related_ids.length > 0) {\r\n                estrategiaUsada += ' + related_ids';\r\n                \r\n                const idsYaIncluidos = productosEncontrados.map(p => p.id);\r\n                const idsRelatedNuevos = producto.related_ids.filter(id => !idsYaIncluidos.includes(id));\r\n                const idsNecesarios = idsRelatedNuevos.slice(0, 3 - productosEncontrados.length);\r\n                \r\n                if (idsNecesarios.length > 0) {\r\n                    const promesasRelated = idsNecesarios.map(async (id) => {\r\n                        try {\r\n                            const prod = await fetchWooCommerceData(`products\/${id}`);\r\n                            return prod;\r\n                        } catch (error) {\r\n                            console.error(`\u274c Error cargando related ${id}:`, error);\r\n                            return null;\r\n                        }\r\n                    });\r\n                    \r\n                    const resultadosRelated = await Promise.all(promesasRelated);\r\n                    productosEncontrados.push(...resultadosRelated.filter(p => p !== null));\r\n                }\r\n            }\r\n            \r\n            \/\/ \u00daltimo fallback: categor\u00eda\r\n            if (productosEncontrados.length === 0) {\r\n                estrategiaUsada = 'categoria_fallback';\r\n                \r\n                if (producto.categories && producto.categories.length > 0) {\r\n                    const categoriaId = producto.categories[0].id;\r\n                    const productosMismaCategoria = await fetchWooCommerceData('products', {\r\n                        category: categoriaId,\r\n                        per_page: 6,\r\n                        exclude: productoId,\r\n                        status: 'publish'\r\n                    });\r\n                    \r\n                    productosEncontrados = productosMismaCategoria.slice(0, 3);\r\n                }\r\n            }\r\n\r\n            \/\/ Limitar a m\u00e1ximo 3 productos\r\n            productosEncontrados = productosEncontrados.slice(0, 3);\r\n\r\n            productosRelacionados = productosEncontrados;\r\n            mostrarProductosRelacionados();\r\n\r\n        } catch (error) {\r\n            console.error('\u274c ERROR GENERAL:', error);\r\n            containers.forEach(container => {\r\n                if (container.titulo) container.titulo.textContent = 'Error al cargar';\r\n                if (container.duracion) container.duracion.textContent = '';\r\n                if (container.valor) container.valor.textContent = '';\r\n            });\r\n        }\r\n    }\r\n\r\n    \/\/ Formatear precio en CLP\r\n    function formatPrice(price) {\r\n        return new Intl.NumberFormat('es-CL', {\r\n            style: 'currency',\r\n            currency: 'CLP',\r\n            minimumFractionDigits: 0,\r\n            maximumFractionDigits: 0\r\n        }).format(parseFloat(price));\r\n    }\r\n\r\n    \/\/ Extraer duraci\u00f3n del producto\r\n    function extraerDuracion(producto) {\r\n        if (producto.short_description) {\r\n            const match = producto.short_description.match(\/(\\d+)\\s*(hora|horas|minuto|minutos|min)\/i);\r\n            if (match) return match[0];\r\n        }\r\n        \r\n        if (producto.description) {\r\n            const match = producto.description.match(\/(\\d+)\\s*(hora|horas|minuto|minutos|min)\/i);\r\n            if (match) return match[0];\r\n        }\r\n        \r\n        if (producto.meta_data && Array.isArray(producto.meta_data)) {\r\n            for (const meta of producto.meta_data) {\r\n                if (meta.key && (meta.key.includes('duracion') || meta.key.includes('duration')) && meta.value) {\r\n                    return meta.value;\r\n                }\r\n            }\r\n        }\r\n        \r\n        return '2 horas';\r\n    }\r\n\r\n    \/\/ Mostrar productos relacionados en las tarjetas\r\n    function mostrarProductosRelacionados() {\r\n\r\n        \/\/ Limpiar todas las tarjetas\r\n        containers.forEach(container => {\r\n            if (container.container) {\r\n                container.container.style.display = 'none';\r\n                container.container.onclick = null;\r\n                container.container.classList.remove('producto-seleccionado', 'producto-disponible');\r\n                container.container.style.transform = '';\r\n                container.container.style.boxShadow = '';\r\n                container.container.style.border = '';\r\n                container.container.style.borderRadius = '';\r\n            }\r\n        });\r\n\r\n        productosRelacionados.forEach((producto, index) => {\r\n            if (index >= containers.length) return;\r\n            \r\n            const container = containers[index];\r\n            const precioVenta = producto.sale_price;\r\n            const precioRegular = producto.regular_price || producto.price;\r\n            const precio = precioVenta || precioRegular || '0';\r\n            const tieneOferta = precioVenta && parseFloat(precioVenta) < parseFloat(precioRegular);\r\n            \r\n            \/\/ Obtener la mejor imagen disponible\r\n            const imagen = obtenerMejorImagen(producto);\r\n            const duracion = extraerDuracion(producto);\r\n\r\n\r\n            \/\/ Actualizar imagen con verificaci\u00f3n y forzado\r\n            if (container.imagen) {\r\n                \r\n                \/\/ Forzar actualizaci\u00f3n de imagen\r\n                container.imagen.onerror = function() {\r\n\r\n                    this.src = 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png';\r\n                    this.removeAttribute('srcset'); \/\/ Remover srcset en caso de error\r\n                };\r\n                \r\n                \r\n                \/\/ CR\u00cdTICO: Remover srcset que est\u00e1 interfiriendo\r\n                container.imagen.removeAttribute('srcset');\r\n                container.imagen.removeAttribute('sizes');\r\n                \r\n                \/\/ Forzar la actualizaci\u00f3n removiendo y reasignando src\r\n                container.imagen.removeAttribute('src');\r\n                \r\n                setTimeout(() => {\r\n                    container.imagen.src = imagen;\r\n                    container.imagen.alt = producto.name;\r\n                    \r\n                    \/\/ Verificar que realmente cambi\u00f3\r\n                    setTimeout(() => {\r\n\r\n                        \r\n                        if (container.imagen.src !== imagen) {\r\n                            container.imagen.removeAttribute('srcset');\r\n                            container.imagen.removeAttribute('sizes');\r\n                            container.imagen.src = imagen + '?v=' + Date.now(); \/\/ Agregar timestamp para evitar cach\u00e9\r\n                        }\r\n                    }, 100);\r\n                }, 50);\r\n            }\r\n            \r\n            \/\/ Actualizar t\u00edtulo\r\n            if (container.titulo) {\r\n                container.titulo.textContent = producto.name.toUpperCase();\r\n            }\r\n            \r\n            \/\/ Actualizar duraci\u00f3n\r\n            if (container.duracion) {\r\n                container.duracion.textContent = duracion;\r\n            }\r\n            \r\n            \/\/ Actualizar precio con soporte para ofertas\r\n            if (container.valor) {\r\n                if (tieneOferta) {\r\n                    container.valor.innerHTML = `\r\n                        <span style=\"text-decoration: line-through; color: #999; margin-right: 5px; font-size: 0.8em;\">\r\n                            ${formatPrice(precioRegular)}\r\n                        <\/span>\r\n                        ${formatPrice(precioVenta)}\r\n                    `;\r\n                } else {\r\n                    container.valor.textContent = formatPrice(precio);\r\n                }\r\n            }\r\n\r\n            \/\/ Configurar container para interactividad\r\n            if (container.container) {\r\n                container.container.style.display = 'flex';\r\n                container.container.classList.add('producto-disponible');\r\n                \r\n                \/\/ Almacenar datos del producto\r\n                container.container.dataset.productoId = producto.id;\r\n                container.container.dataset.productoNombre = producto.name;\r\n                container.container.dataset.productoPrecio = precio;\r\n                container.container.dataset.productoSku = producto.sku || '';\r\n                \r\n                \/\/ Configurar estilos de interactividad\r\n                container.container.style.cursor = 'pointer';\r\n                container.container.style.transition = 'transform 0.3s ease, box-shadow 0.3s ease';\r\n                \r\n                \/\/ Event listener para selecci\u00f3n con feedback visual mejorado\r\n                container.container.onclick = function(e) {\r\n                    e.preventDefault();\r\n                    e.stopPropagation();\r\n\r\n                    toggleSeleccionProducto(container.container, producto, index);\r\n                };\r\n                \r\n                \/\/ Efectos hover mejorados\r\n                container.container.onmouseenter = function() {\r\n                    if (!this.classList.contains('producto-seleccionado')) {\r\n                        this.style.transform = 'translateY(-2px)';\r\n                        this.style.boxShadow = '0 3px 15px rgba(0,0,0,0.1)';\r\n                    }\r\n                };\r\n                \r\n                container.container.onmouseleave = function() {\r\n                    if (!this.classList.contains('producto-seleccionado')) {\r\n                        this.style.transform = '';\r\n                        this.style.boxShadow = '';\r\n                    }\r\n                };\r\n            }\r\n        });\r\n\r\n        \/\/ Ocultar tarjetas vac\u00edas\r\n        for (let i = productosRelacionados.length; i < containers.length; i++) {\r\n            if (containers[i].container) {\r\n                containers[i].container.style.display = 'none';\r\n            }\r\n        }\r\n\r\n    }\r\n\r\n    \/\/ Toggle selecci\u00f3n de producto complementario con feedback visual mejorado\r\n    function toggleSeleccionProducto(containerElement, producto, index) {\r\n        const productoId = producto.id.toString();\r\n        \r\n        if (productosSeleccionados.has(productoId)) {\r\n            \/\/ Deseleccionar\r\n            productosSeleccionados.delete(productoId);\r\n            containerElement.classList.remove('producto-seleccionado');\r\n            \r\n            \/\/ Restaurar estilos normales\r\n            containerElement.style.transform = '';\r\n            containerElement.style.boxShadow = '';\r\n            containerElement.style.border = '';\r\n            containerElement.style.borderRadius = '';\r\n\r\n            \r\n        } else {\r\n            \/\/ Seleccionar\r\n            productosSeleccionados.add(productoId);\r\n            containerElement.classList.add('producto-seleccionado');\r\n            \r\n            \/\/ Aplicar estilos de selecci\u00f3n\r\n            containerElement.style.transform = 'translateY(-5px)';\r\n            containerElement.style.boxShadow = '0 8px 25px rgba(49, 152, 158, 0.4)';\r\n            containerElement.style.border = '3px solid #31989E';\r\n            containerElement.style.borderRadius = '12px';\r\n            \r\n        }\r\n        \r\n        \/\/ Actualizar bot\u00f3n continuar\r\n        actualizarBotonContinuar();\r\n        \r\n        \r\n        \/\/ Disparar evento personalizado para comunicaci\u00f3n con otras secciones\r\n\/\/ Preparar datos de productos seleccionados con formato completo\r\nconst productosComplementarios = Array.from(productosSeleccionados).map(id => {\r\n    const producto = productosRelacionados.find(p => p.id.toString() === id);\r\n    if (producto) {\r\n        return {\r\n            slug: producto.slug || `producto-${producto.id}`,\r\n            data: producto\r\n        };\r\n    }\r\n    return null;\r\n}).filter(Boolean);\r\n\r\n\/\/ GUARDAR EN LOCALSTORAGE\r\nlocalStorage.setItem('selectedComplementos', JSON.stringify(productosComplementarios));\r\nconsole.log('\ud83d\udce6 Complementos guardados en localStorage:', productosComplementarios);\r\n\r\n\/\/ Disparar evento personalizado para comunicaci\u00f3n con otras secciones\r\ndocument.dispatchEvent(new CustomEvent('complementosActualizados', {\r\n    detail: {\r\n        productosSeleccionados: Array.from(productosSeleccionados),\r\n        cantidad: productosSeleccionados.size,\r\n        productos: productosComplementarios.map(p => p.data)\r\n    }\r\n}));\r\n        \r\n        \/\/ Feedback visual adicional\r\n        containerElement.style.animation = 'pulse 0.3s ease-in-out';\r\n        setTimeout(() => {\r\n            containerElement.style.animation = '';\r\n        }, 300);\r\n    }\r\n\r\n    \/\/ Actualizar estado del bot\u00f3n continuar\r\n    function actualizarBotonContinuar() {\r\n        const btnContinuar = document.querySelector('.elementor-element-6faea10 .elementor-button');\r\n        if (btnContinuar) {\r\n            const tieneSelecciones = productosSeleccionados.size > 0 || productoPrincipal;\r\n            \r\n            if (tieneSelecciones) {\r\n                btnContinuar.style.opacity = '1';\r\n                btnContinuar.style.pointerEvents = 'auto';\r\n                btnContinuar.style.background = '#31989E';\r\n                btnContinuar.style.transform = 'scale(1)';\r\n            } else {\r\n                btnContinuar.style.opacity = '0.5';\r\n                btnContinuar.style.pointerEvents = 'none';\r\n                btnContinuar.style.background = '#ccc';\r\n            }\r\n            \r\n            const spanText = btnContinuar.querySelector('.elementor-button-text');\r\n            if (spanText) {\r\n                const complementos = productosSeleccionados.size;\r\n                if (complementos > 0) {\r\n                    spanText.textContent = `CONTINUAR (${complementos} complemento${complementos > 1 ? 's' : ''})`;\r\n                    btnContinuar.style.animation = 'pulse 0.5s ease-in-out';\r\n                    setTimeout(() => btnContinuar.style.animation = '', 500);\r\n                } else {\r\n                    spanText.textContent = 'CONTINUAR';\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    \/\/ Limpiar selecciones\r\n    function limpiarSelecciones() {\r\n        \r\n        productosSeleccionados.clear();\r\n         localStorage.removeItem('selectedComplementos');\r\n        \r\n        productosRelacionados = [];\r\n        \r\n        containers.forEach(container => {\r\n            if (container.container) {\r\n                container.container.classList.remove('producto-seleccionado', 'producto-disponible');\r\n                container.container.style.transform = '';\r\n                container.container.style.boxShadow = '';\r\n                container.container.style.border = '';\r\n                container.container.style.borderRadius = '';\r\n                container.container.style.display = 'flex';\r\n                container.container.onclick = null;\r\n                container.container.onmouseenter = null;\r\n                container.container.onmouseleave = null;\r\n            }\r\n            \r\n            \/\/ Restaurar contenido original\r\n            if (container.titulo) container.titulo.textContent = 'CIRCUITO DE AGUAS';\r\n            if (container.duracion) container.duracion.textContent = '2 horas';\r\n            if (container.valor) container.valor.textContent = '$00.000';\r\n            if (container.imagen) {\r\n                \r\n                \/\/ Remover atributos que pueden interferir\r\n                container.imagen.removeAttribute('srcset');\r\n                container.imagen.removeAttribute('sizes');\r\n                container.imagen.removeAttribute('src');\r\n                \r\n                setTimeout(() => {\r\n                    container.imagen.src = 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png';\r\n                    container.imagen.alt = 'Imagen por defecto';\r\n                }, 50);\r\n                \r\n                container.imagen.onerror = null;\r\n                container.imagen.onload = null;\r\n            }\r\n        });\r\n        \r\n        actualizarBotonContinuar();\r\n    }\r\n\r\n    \/\/ Event listeners principales\r\n    document.addEventListener('productoSeleccionado', function(e) {\r\n        productoPrincipal = e.detail.productoData;\r\n        limpiarSelecciones();\r\n        \r\n        if (productoPrincipal && productoPrincipal.id) {\r\n            cargarProductosRelacionados(productoPrincipal.id);\r\n        }\r\n    });\r\n\r\n    document.addEventListener('productoLimpiado', function() {\r\n        productoPrincipal = null;\r\n        limpiarSelecciones();\r\n    });\r\n\r\n    document.addEventListener('servicioLimpiado', function() {\r\n        productoPrincipal = null;\r\n        limpiarSelecciones();\r\n    });\r\n\r\n    document.addEventListener('categoriaLimpiada', function() {\r\n        productoPrincipal = null;\r\n        limpiarSelecciones();\r\n    });\r\n\r\n    actualizarBotonContinuar();\r\n});\r\n<\/script>\r\n\r\n<style>\r\n\/* Estilos mejorados para productos relacionados *\/\r\n.producto-disponible {\r\n    transition: all 0.3s ease !important;\r\n    cursor: pointer !important;\r\n    position: relative !important;\r\n}\r\n\r\n.producto-disponible:hover {\r\n    transform: translateY(-2px) !important;\r\n    box-shadow: 0 3px 15px rgba(0,0,0,0.1) !important;\r\n}\r\n\r\n.producto-seleccionado {\r\n    position: relative !important;\r\n}\r\n\r\n.producto-seleccionado::before {\r\n\r\n    z-index: 10 !important;\r\n    box-shadow: 0 3px 10px rgba(49, 152, 158, 0.5) !important;\r\n    border: 2px solid white !important;\r\n}\r\n\r\n\/* Animaci\u00f3n de pulso para feedback *\/\r\n@keyframes pulse {\r\n    0% { transform: scale(1); }\r\n    50% { transform: scale(1.05); }\r\n    100% { transform: scale(1); }\r\n}\r\n\r\n\/* Mejorar el estado hover del bot\u00f3n continuar *\/\r\n.elementor-button {\r\n    transition: all 0.3s ease !important;\r\n}\r\n\r\n\/* Efecto de carga para im\u00e1genes *\/\r\n.producto-relacionado-1 img,\r\n.producto-relacionado-2 img,\r\n.producto-relacionado-3 img {\r\n    transition: opacity 0.3s ease !important;\r\n}\r\n\r\n.producto-relacionado-1 img[src*=\"exp1@2x.png\"],\r\n.producto-relacionado-2 img[src*=\"exp1@2x.png\"],\r\n.producto-relacionado-3 img[src*=\"exp1@2x.png\"] {\r\n    opacity: 0.7 !important;\r\n    filter: grayscale(20%) !important;\r\n}\r\n\r\n\/* Estados de selecci\u00f3n mejorados *\/\r\n.producto-seleccionado .producto-imagen {\r\n    filter: brightness(110%) saturate(110%) !important;\r\n}\r\n\r\n\/* Responsive *\/\r\n@media (max-width: 768px) {\r\n    .producto-seleccionado::before {\r\n        top: 10px !important;\r\n        right: 10px !important;\r\n        width: 25px !important;\r\n        height: 25px !important;\r\n        font-size: 14px !important;\r\n    }\r\n}\r\n\r\n\/* Indicador visual adicional para productos seleccionables *\/\r\n.producto-disponible::after {\r\n    content: '';\r\n    position: absolute !important;\r\n    top: 10px !important;\r\n    left: 10px !important;\r\n    width: 8px !important;\r\n    height: 8px !important;\r\n    background: #31989E !important;\r\n    border-radius: 50% !important;\r\n    opacity: 0.6 !important;\r\n    transition: all 0.3s ease !important;\r\n}\r\n\r\n.producto-disponible:hover::after {\r\n    opacity: 1 !important;\r\n    transform: scale(1.5) !important;\r\n}\r\n\r\n.producto-seleccionado::after {\r\n    opacity: 0 !important;\r\n}\r\n<\/style>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-f7d80b5 e-con-full elementor-hidden-tablet elementor-hidden-mobile e-flex e-con e-child\" data-id=\"f7d80b5\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-cd841e6 e-con-full paso3-tus-experiencias e-flex e-con e-parent\" data-id=\"cd841e6\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-728da96 e-con-full e-flex e-con e-child\" data-id=\"728da96\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a923062 elementor-widget elementor-widget-heading\" data-id=\"a923062\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">YOUR EXPERIENCES<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-deefc00 e-grid e-con-full e-con e-child\" data-id=\"deefc00\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-6e99943 e-con-full producto-seleccionado-1 e-flex e-con e-child\" data-id=\"6e99943\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-53a993c foto-producto-seleccionado-1 elementor-widget elementor-widget-image\" data-id=\"53a993c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"420\" height=\"342\" src=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/foto-prod1@2x.png\" class=\"attachment-large size-large wp-image-1366\" alt=\"\" srcset=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/foto-prod1@2x.png 420w, https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/foto-prod1@2x-300x244.png 300w\" sizes=\"(max-width: 420px) 100vw, 420px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-8e93036 e-con-full e-flex e-con e-child\" data-id=\"8e93036\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-c0c61c3 e-con-full e-flex e-con e-child\" data-id=\"c0c61c3\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-711e127 titulo-producto-seleccionado-1 elementor-widget elementor-widget-heading\" data-id=\"711e127\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">---<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6276f1a duracion-producto-seleccionado-1 elementor-widget elementor-widget-heading\" data-id=\"6276f1a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<p class=\"elementor-heading-title elementor-size-default\">-- minutos<\/p>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0292642 valor-producto-seleccionado-1 elementor-widget elementor-widget-heading\" data-id=\"0292642\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">$00.000<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b076bda elementor-absolute aliminar-producto-seleccionado-1 elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"b076bda\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;_position&quot;:&quot;absolute&quot;}\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-far-trash-alt\" viewbox=\"0 0 448 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M268 416h24a12 12 0 0 0 12-12V188a12 12 0 0 0-12-12h-24a12 12 0 0 0-12 12v216a12 12 0 0 0 12 12zM432 80h-82.41l-34-56.7A48 48 0 0 0 274.41 0H173.59a48 48 0 0 0-41.16 23.3L98.41 80H16A16 16 0 0 0 0 96v16a16 16 0 0 0 16 16h16v336a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V128h16a16 16 0 0 0 16-16V96a16 16 0 0 0-16-16zM171.84 50.91A6 6 0 0 1 177 48h94a6 6 0 0 1 5.15 2.91L293.61 80H154.39zM368 464H80V128h288zm-212-48h24a12 12 0 0 0 12-12V188a12 12 0 0 0-12-12h-24a12 12 0 0 0-12 12v216a12 12 0 0 0 12 12z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-97fb764 elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"97fb764\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-26ee9a0 e-grid e-con-full e-con e-child\" data-id=\"26ee9a0\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-49dea1f e-con-full e-flex e-con e-child\" data-id=\"49dea1f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f0fe113 elementor-widget elementor-widget-heading\" data-id=\"f0fe113\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">PURCHASE TOTALS<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-edd5bea elementor-widget elementor-widget-heading\" data-id=\"edd5bea\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Subtotal<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b73b175 e-con-full e-flex e-con e-child\" data-id=\"b73b175\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c7496b3 total-de-la-compra elementor-widget elementor-widget-heading\" data-id=\"c7496b3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">$000.000<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fbafe91 elementor-align-justify paso3-boton-continuar elementor-widget elementor-widget-button\" data-id=\"fbafe91\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"#selecciona-fecha\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">CONTINUE TO RESERVATION<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c10afbf elementor-widget elementor-widget-html\" data-id=\"c10afbf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\r\n    document.addEventListener('DOMContentLoaded', function() {\r\n\r\n    \/\/ Variables globales para tracking\r\n    let productoPrincipal = null;\r\n    let productosComplementarios = [];\r\n    let experienciasActuales = [];\r\n\r\n    \/\/ Configuraci\u00f3n de la API\r\n    const WC_CONFIG = {\r\n        baseUrl: window.location.origin,\r\n        apiPath: '\/wp-json\/wc\/v3\/',\r\n        consumerKey: 'ck_6381579117ac59ad6ecbd38e618553eaa9856765',\r\n        consumerSecret: 'cs_e12f13e79017efdf5799f55fd22ad42c458dcb22',\r\n    };\r\n\r\n    \/\/ Elementos del DOM principales\r\n    const elementosDOM = {\r\n        \/\/ Producto principal (tarjeta 1)\r\n        principal: {\r\n            container: document.querySelector('.producto-seleccionado-1'),\r\n            imagen: document.querySelector('.foto-producto-seleccionado-1 img'),\r\n            titulo: document.querySelector('.titulo-producto-seleccionado-1 .elementor-heading-title'),\r\n            duracion: document.querySelector('.duracion-producto-seleccionado-1 .elementor-heading-title'),\r\n            valor: document.querySelector('.valor-producto-seleccionado-1 .elementor-heading-title'),\r\n            eliminar: document.querySelector('.aliminar-producto-seleccionado-1')\r\n        },\r\n        \/\/ Totales\r\n        subtotal: document.querySelector('.elementor-element-6994135 .elementor-heading-title'),\r\n        total: document.querySelector('.total-de-la-compra .elementor-heading-title'),\r\n        botonReserva: document.querySelector('.elementor-element-24fe3b1 .elementor-button')\r\n    };\r\n\r\n    \/\/ Contenedor donde se agregar\u00e1n las tarjetas de complementos\r\n    const containerComplementos = document.querySelector('.elementor-element-2f17863');\r\n\r\n    \/\/ Funci\u00f3n para hacer llamadas a la API\r\n    async function fetchWooCommerceData(endpoint, params = {}) {\r\n        try {\r\n            const url = new URL(WC_CONFIG.baseUrl + WC_CONFIG.apiPath + endpoint);\r\n            \r\n            Object.keys(params).forEach(key => {\r\n                url.searchParams.append(key, params[key]);\r\n            });\r\n\r\n            if (WC_CONFIG.consumerKey && WC_CONFIG.consumerSecret) {\r\n                url.searchParams.append('consumer_key', WC_CONFIG.consumerKey);\r\n                url.searchParams.append('consumer_secret', WC_CONFIG.consumerSecret);\r\n            }\r\n\r\n            const response = await fetch(url, {\r\n                method: 'GET',\r\n                headers: {\r\n                    'Content-Type': 'application\/json',\r\n                },\r\n            });\r\n            \r\n            if (!response.ok) {\r\n                throw new Error(`Error HTTP: ${response.status}`);\r\n            }\r\n            \r\n            return await response.json();\r\n        } catch (error) {\r\n            console.error('\u274c Error API:', error);\r\n            throw error;\r\n        }\r\n    }\r\n\r\n    \/\/ Formatear precio\r\n    function formatPrice(price) {\r\n        return new Intl.NumberFormat('es-CL', {\r\n            style: 'currency',\r\n            currency: 'CLP',\r\n            minimumFractionDigits: 0,\r\n            maximumFractionDigits: 0\r\n        }).format(parseFloat(price));\r\n    }\r\n\r\n\/\/ Extraer duraci\u00f3n del producto (Actualizado para ACF)\r\nfunction extraerDuracion(producto) {\r\n    \/\/ IMPORTANTE: Cambia 'duracion' por el \"Nombre del campo\" (Field Name) exacto que configuraste en ACF\r\n    const nombreCampoACF = 'duracion'; \r\n\r\n    \/\/ 1. Buscar si viene nativamente en el objeto \"acf\" (Si usas el plugin ACF to REST API)\r\n    if (producto.acf && producto.acf[nombreCampoACF]) {\r\n        return `Duraci\u00f3n: ${producto.acf[nombreCampoACF]}`;\r\n    }\r\n\r\n    \/\/ 2. Buscar en el array de meta_data est\u00e1ndar de WooCommerce\r\n    if (producto.meta_data && Array.isArray(producto.meta_data)) {\r\n        const metaDuracion = producto.meta_data.find(meta => meta.key === nombreCampoACF);\r\n        \r\n        if (metaDuracion && metaDuracion.value) {\r\n            return `Duraci\u00f3n: ${metaDuracion.value}`;\r\n        }\r\n    }\r\n\r\n    \/\/ 3. Plan C: Buscar en la descripci\u00f3n por si alg\u00fan producto no tiene el campo ACF lleno\r\n    const regex = \/(\\d+)\\s*(hora|horas|hrs|h|minuto|minutos|min)\\b\/i;\r\n    \r\n    if (producto.short_description) {\r\n        const textoLimpio = producto.short_description.replace(\/<[^>]*>?\/gm, '');\r\n        const match = textoLimpio.match(regex);\r\n        if (match) return `Duraci\u00f3n: ${match[0]}`;\r\n    }\r\n\r\n    \/\/ 4. Fallback final\r\n    return 'Duraci\u00f3n: -- minutos';\r\n}\r\n\r\n    \/\/ Obtener mejor imagen del producto\r\n    function obtenerMejorImagen(producto) {\r\n        if (!producto.images || !Array.isArray(producto.images) || producto.images.length === 0) {\r\n            return 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/foto-prod1@2x.png';\r\n        }\r\n        \r\n        const imagenPrincipal = producto.images.find(img => img.position === 0);\r\n        if (imagenPrincipal && imagenPrincipal.src) {\r\n            return imagenPrincipal.src;\r\n        }\r\n        \r\n        const primeraImagen = producto.images[0];\r\n        if (primeraImagen && primeraImagen.src) {\r\n            return primeraImagen.src;\r\n        }\r\n        \r\n        return 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/foto-prod1@2x.png';\r\n    }\r\n\r\n    \/\/ Crear tarjeta de complemento din\u00e1micamente\r\n    function crearTarjetaComplemento(producto, indice) {\r\n        const tarjetaHTML = `\r\n            <div class=\"elementor-element producto-complemento-${indice} e-con-full e-flex e-con e-child\" \r\n                 data-producto-id=\"${producto.id}\" \r\n                 data-indice=\"${indice}\"\r\n                 style=\"border: none; border-radius: 5px; margin-bottom: 15px; padding: 0px; display: flex; flex-direction: row; box-shadow: 0px 3px 8px #0000001D; width: 70%;\">\r\n                \r\n                <div class=\"elementor-element foto-complemento-${indice} elementor-widget elementor-widget-image\">\r\n                    <div class=\"elementor-widget-container\">\r\n                        <img decoding=\"async\" \r\n                             src=\"${obtenerMejorImagen(producto)}\" \r\n                             alt=\"${producto.name}\"\r\n                             style=\"height: 200px;\r\n    object-fit: cover;\r\n    object-position: center center; border-radius: 6px; width: 236px;\">\r\n                    <\/div>\r\n                <\/div>\r\n                \r\n                <div class=\"elementor-element e-con-full e-flex e-con e-child\" style=\"flex: 1; padding: 20px 0; justify-content: space-between;\">\r\n                    <div class=\"elementor-element e-con-full e-flex e-con e-child\" style=\"padding: 0; gap: 5px;\">\r\n                        <div class=\"elementor-element titulo-complemento-${indice} elementor-widget elementor-widget-heading\">\r\n                            <div class=\"elementor-widget-container\">\r\n                                <h3 class=\"elementor-heading-title elementor-size-default\" \r\n                                    style=\"font-family: 'Josefin Sans', Sans-serif; font-size: 18px; font-weight: 600; color: #31989E; text-transform: uppercase; margin: 0 0 5px 0;\">\r\n                                    ${producto.name.toUpperCase()}\r\n                                <\/h3>\r\n                            <\/div>\r\n                        <\/div>\r\n                        <div class=\"elementor-element duracion-complemento-${indice} elementor-widget elementor-widget-heading\">\r\n                            <div class=\"elementor-widget-container\">\r\n                                <p class=\"elementor-heading-title elementor-size-default\" \r\n                                   style=\"font-family: 'EB Garamond', Sans-serif; font-size: 18px; color: #4F4F4F; margin: 0;\">\r\n                                    ${extraerDuracion(producto)}\r\n                                <\/p>\r\n                            <\/div>\r\n                        <\/div>\r\n                    <\/div>\r\n                    \r\n                    <div class=\"elementor-element valor-complemento-${indice} elementor-widget elementor-widget-heading\" \r\n                         style=\"margin-right: auto;\">\r\n                        <div class=\"elementor-widget-container\">\r\n                            <h3 class=\"elementor-heading-title elementor-size-default\" \r\n                                style=\"font-family: 'Josefin Sans', Sans-serif; font-size: 18px; font-weight: 400; color: #4F4F4F; margin: 0;\">\r\n                                ${formatPrice(producto.sale_price || producto.regular_price || producto.price || '0')}\r\n                            <\/h3>\r\n                        <\/div>\r\n                    <\/div>\r\n                    \r\n                    <div class=\"elementor-element eliminar-complemento-${indice} elementor-absolute elementor-view-default elementor-widget elementor-widget-icon\" \r\n                         style=\"position: absolute; bottom: 10px; right: 10px; cursor: pointer; padding: 5px; transition: all 0.3s ease;\"\r\n                         \r\n                        >\r\n                        <div class=\"elementor-widget-container\">\r\n                            <div class=\"elementor-icon-wrapper\">\r\n                                <div class=\"elementor-icon\">\r\n                                    <svg aria-hidden=\"true\" class=\"e-font-icon-svg e-far-trash-alt\" viewBox=\"0 0 448 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"fill: #ACADAD; width: 18px; height: 18px;\">\r\n                                        <path d=\"M268 416h24a12 12 0 0 0 12-12V188a12 12 0 0 0-12-12h-24a12 12 0 0 0-12 12v216a12 12 0 0 0 12 12zM432 80h-82.41l-34-56.7A48 48 0 0 0 274.41 0H173.59a48 48 0 0 0-41.16 23.3L98.41 80H16A16 16 0 0 0 0 96v16a16 16 0 0 0 16 16h16v336a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V128h16a16 16 0 0 0 16-16V96a16 16 0 0 0-16-16zM171.84 50.91A6 6 0 0 1 177 48h94a6 6 0 0 1 5.15 2.91L293.61 80H154.39zM368 464H80V128h288zm-212-48h24a12 12 0 0 0 12-12V188a12 12 0 0 0-12-12h-24a12 12 0 0 0-12 12v216a12 12 0 0 0 12 12z\"><\/path>\r\n                                    <\/svg>\r\n                                <\/div>\r\n                            <\/div>\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n        `;\r\n        \r\n        return tarjetaHTML;\r\n    }\r\n\r\n    \/\/ Actualizar producto principal\r\nasync function actualizarProductoPrincipal(producto) {\r\n    \r\n    try {\r\n        \/\/ Obtener datos completos del producto si es necesario\r\n        let productoCompleto = producto;\r\n        if (!producto.images || !producto.description) {\r\n            productoCompleto = await fetchWooCommerceData(`products\/${producto.id}`);\r\n        }\r\n        \r\n        \/\/ Actualizar imagen\r\n        if (elementosDOM.principal.imagen) {\r\n            const imagen = obtenerMejorImagen(productoCompleto);\r\n            elementosDOM.principal.imagen.removeAttribute('srcset');\r\n            elementosDOM.principal.imagen.removeAttribute('sizes');\r\n            elementosDOM.principal.imagen.src = imagen;\r\n            elementosDOM.principal.imagen.alt = productoCompleto.name;\r\n        }\r\n        \r\n        \/\/ Actualizar t\u00edtulo\r\n        if (elementosDOM.principal.titulo) {\r\n            elementosDOM.principal.titulo.textContent = productoCompleto.name.toUpperCase();\r\n        }\r\n        \r\n        \/\/ Actualizar duraci\u00f3n\r\n        if (elementosDOM.principal.duracion) {\r\n            elementosDOM.principal.duracion.textContent = extraerDuracion(productoCompleto);\r\n        }\r\n        \r\n        \/\/ Actualizar precio\r\n        if (elementosDOM.principal.valor) {\r\n            const precio = productoCompleto.sale_price || productoCompleto.regular_price || productoCompleto.price || '0';\r\n            elementosDOM.principal.valor.textContent = formatPrice(precio);\r\n        }\r\n        \r\n        \/\/ Mostrar tarjeta principal\r\n        if (elementosDOM.principal.container) {\r\n            elementosDOM.principal.container.style.display = 'flex';\r\n        }\r\n        \r\n        productoPrincipal = productoCompleto;\r\n        \r\n        \/\/ AGREGAR ESTA L\u00cdNEA PARA ACTUALIZAR TOTALES\r\n        actualizarTotales();\r\n        \r\n    } catch (error) {\r\n        console.error('\u274c Error actualizando producto principal:', error);\r\n    }\r\n}\r\n\r\n    \/\/ Agregar producto complementario\r\nfunction agregarProductoComplementario(producto) {\r\n    console.log('\u2795 Intentando agregar complementario:', producto.name);\r\n    \r\n    const yaExiste = productosComplementarios.find(p => p.id === producto.id);\r\n    if (yaExiste) return;\r\n    \r\n    productosComplementarios.push(producto);\r\n    \r\n    const indice = productosComplementarios.length + 1;\r\n    const tarjetaHTML = crearTarjetaComplemento(producto, indice);\r\n    \r\n    \/\/ PUNTOS DE INSERCI\u00d3N CORREGIDOS (basados en tu HTML real)\r\n    let puntoInsercion = null;\r\n    let metodoInsercion = '';\r\n    \r\n    \/\/ Opci\u00f3n 1: Antes del divider que S\u00cd existe\r\n    const divider = document.querySelector('.elementor-element-97fb764');\r\n    if (divider) {\r\n        puntoInsercion = divider;\r\n        metodoInsercion = 'beforebegin';\r\n    }\r\n    \r\n    \/\/ Opci\u00f3n 2: Despu\u00e9s del producto principal\r\n    if (!puntoInsercion) {\r\n        const productoPrincipal = document.querySelector('.elementor-element-6e99943');\r\n        if (productoPrincipal) {\r\n            puntoInsercion = productoPrincipal;\r\n            metodoInsercion = 'afterend';\r\n        }\r\n    }\r\n    \r\n    \/\/ Opci\u00f3n 3: Dentro del contenedor grid\r\n    if (!puntoInsercion) {\r\n        const containerGrid = document.querySelector('.elementor-element-deefc00');\r\n        if (containerGrid) {\r\n            puntoInsercion = containerGrid;\r\n            metodoInsercion = 'beforeend';\r\n        }\r\n    }\r\n    \r\n    if (puntoInsercion) {\r\n        puntoInsercion.insertAdjacentHTML(metodoInsercion, tarjetaHTML);\r\n        console.log('\u2705 Tarjeta complementaria insertada:', producto.name);\r\n        \r\n        \/\/ Agregar event listener despu\u00e9s de un breve delay\r\n        setTimeout(() => {\r\n            const botonEliminar = document.querySelector(`.eliminar-complemento-${indice}`);\r\n            if (botonEliminar) {\r\n                botonEliminar.addEventListener('click', function() {\r\n                    eliminarProductoComplementario(producto.id, indice);\r\n                });\r\n            }\r\n        }, 100);\r\n    } else {\r\n        console.error('\u274c No se encontr\u00f3 punto de inserci\u00f3n para:', producto.name);\r\n    }\r\n    \r\n    actualizarTotales();\r\n}\r\n\r\n    \/\/ Eliminar producto complementario\r\n    function eliminarProductoComplementario(productoId, indice) {\r\n        \r\n        \/\/ Remover del array\r\n        productosComplementarios = productosComplementarios.filter(p => p.id !== productoId);\r\n        \r\n        \/\/ Remover tarjeta del DOM\r\n        const tarjeta = document.querySelector(`.producto-complemento-${indice}`);\r\n        if (tarjeta) {\r\n            tarjeta.remove();\r\n        }\r\n        \r\n        \/\/ Actualizar totales\r\n        actualizarTotales();\r\n        \r\n        \/\/ Disparar evento para notificar a otros sistemas\r\n        document.dispatchEvent(new CustomEvent('complementoEliminado', {\r\n            detail: { productoId, productosActuales: productosComplementarios }\r\n        }));\r\n    }\r\n\r\n    \/\/ Limpiar producto principal\r\n    function limpiarProductoPrincipal() {\r\n        \r\n        if (elementosDOM.principal.titulo) {\r\n            elementosDOM.principal.titulo.textContent = '';\r\n        }\r\n        if (elementosDOM.principal.duracion) {\r\n            elementosDOM.principal.duracion.textContent = '';\r\n        }\r\n        if (elementosDOM.principal.valor) {\r\n            elementosDOM.principal.valor.textContent = '$00.000';\r\n        }\r\n        if (elementosDOM.principal.imagen) {\r\n            elementosDOM.principal.imagen.src = 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/foto-prod1@2x.png';\r\n            elementosDOM.principal.imagen.alt = '';\r\n        }\r\n        \r\n        \/\/ Ocultar tarjeta si no hay contenido\r\n        if (elementosDOM.principal.container) {\r\n            elementosDOM.principal.container.style.display = 'none';\r\n        }\r\n        \r\n        productoPrincipal = null;\r\n        limpiarComplementarios();\r\n    }\r\n\r\n    \/\/ Limpiar productos complementarios\r\n    function limpiarComplementarios() {\r\n        \r\n        \/\/ Remover todas las tarjetas de complementos\r\n        const tarjetasComplementos = document.querySelectorAll('[class*=\"producto-complemento-\"]');\r\n        tarjetasComplementos.forEach(tarjeta => tarjeta.remove());\r\n        \r\n        productosComplementarios = [];\r\n        actualizarTotales();\r\n    }\r\n\r\n    \/\/ Actualizar totales\r\n    function actualizarTotales() {\r\n        let total = 0;\r\n        let cantidadProductos = 0;\r\n        \r\n        \/\/ Agregar producto principal\r\n        if (productoPrincipal) {\r\n            const precioPrincipal = parseFloat(productoPrincipal.sale_price || productoPrincipal.regular_price || productoPrincipal.price || '0');\r\n            total += precioPrincipal;\r\n            cantidadProductos++;\r\n        }\r\n        \r\n        \/\/ Agregar complementarios\r\n        productosComplementarios.forEach(producto => {\r\n            const precio = parseFloat(producto.sale_price || producto.regular_price || producto.price || '0');\r\n            total += precio;\r\n            cantidadProductos++;\r\n        });\r\n        \r\n        \/\/ Actualizar DOM\r\n        if (elementosDOM.subtotal) {\r\n            elementosDOM.subtotal.textContent = cantidadProductos > 1 ? 'SUBTOTAL' : 'TOTAL';\r\n        }\r\n        \r\n        if (elementosDOM.total) {\r\n            elementosDOM.total.textContent = formatPrice(total);\r\n        }\r\n        \r\n        \/\/ Actualizar bot\u00f3n de reserva\r\n        if (elementosDOM.botonReserva) {\r\n            const spanText = elementosDOM.botonReserva.querySelector('.elementor-button-text');\r\n            if (spanText) {\r\n                if (cantidadProductos > 0) {\r\n                    spanText.textContent = `CONTINUAR A RESERVA (${cantidadProductos} experiencia${cantidadProductos > 1 ? 's' : ''})`;\r\n                    elementosDOM.botonReserva.style.opacity = '1';\r\n                    elementosDOM.botonReserva.style.pointerEvents = 'auto';\r\n                } else {\r\n                    spanText.textContent = 'CONTINUAR A RESERVA';\r\n                    elementosDOM.botonReserva.style.opacity = '0.5';\r\n                    elementosDOM.botonReserva.style.pointerEvents = 'none';\r\n                }\r\n            }\r\n        }\r\n\r\n    }\r\n\r\n    \/\/ Event listeners principales\r\n    document.addEventListener('productoSeleccionado', function(e) {\r\n        actualizarProductoPrincipal(e.detail.productoData);\r\n        actualizarTotales();\r\n    });\r\n\r\n    document.addEventListener('productoLimpiado', function() {\r\n        limpiarProductoPrincipal();\r\n    });\r\n\r\n    document.addEventListener('servicioLimpiado', function() {\r\n        limpiarProductoPrincipal();\r\n    });\r\n\r\n    document.addEventListener('categoriaLimpiada', function() {\r\n        limpiarProductoPrincipal();\r\n    });\r\n\r\n    document.addEventListener('complementosActualizados', function(e) {\r\n        \r\n        const productosSeleccionados = e.detail.productos || [];\r\n        \r\n        \/\/ Remover complementos que ya no est\u00e1n seleccionados\r\n        const idsActuales = productosSeleccionados.map(p => p.id);\r\n        const complementosAEliminar = productosComplementarios.filter(p => !idsActuales.includes(p.id));\r\n        \r\n        complementosAEliminar.forEach(producto => {\r\n            const indice = productosComplementarios.findIndex(p => p.id === producto.id) + 2; \/\/ +2 porque principal es 1\r\n            eliminarProductoComplementario(producto.id, indice);\r\n        });\r\n        \r\n        \/\/ Agregar nuevos complementos\r\n        productosSeleccionados.forEach(producto => {\r\n            const yaExiste = productosComplementarios.find(p => p.id === producto.id);\r\n            if (!yaExiste) {\r\n                agregarProductoComplementario(producto);\r\n            }\r\n        });\r\n    });\r\n\r\n    \/\/ Event listener para eliminar producto principal\r\n    if (elementosDOM.principal.eliminar) {\r\n        elementosDOM.principal.eliminar.addEventListener('click', function() {\r\n            limpiarProductoPrincipal();\r\n            \r\n            \/\/ Disparar evento para limpiar selecciones en otros componentes\r\n            document.dispatchEvent(new CustomEvent('limpiarTodasLasSelecciones'));\r\n        });\r\n    }\r\n\r\n    \r\n    \/\/ Ocultar producto principal inicialmente si no hay contenido\r\n    if (elementosDOM.principal.container && \r\n        (!elementosDOM.principal.titulo || !elementosDOM.principal.titulo.textContent.trim())) {\r\n        elementosDOM.principal.container.style.display = 'none';\r\n    }\r\n    \r\n    actualizarTotales();\r\n});\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-e3c079b e-con-full elementor-hidden-tablet elementor-hidden-mobile e-flex e-con e-child\" data-id=\"e3c079b\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3acab2e e-con-full paso4-selecciona-tu-fecha-y-hora e-flex e-con e-parent\" data-id=\"3acab2e\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-56ec69b e-con-full e-flex e-con e-child\" data-id=\"56ec69b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-cf679b4 elementor-widget elementor-widget-heading\" data-id=\"cf679b4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">SELECT YOUR DATE AND TIME<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-feeb8cc elementor-widget elementor-widget-html\" data-id=\"feeb8cc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"es\">\r\n<head>\r\n    <meta charset=\"UTF-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n    <title>Calendario de Reservas Mensual<\/title>\r\n<\/head>\r\n<body>\r\n\r\n<!-- CALENDARIO DE RESERVAS MENSUAL -->\r\n<div class=\"calendario-reservas-container\">\r\n    <div class=\"calendario-header\">\r\n        <p class=\"calendario-subtitulo\">Choose the perfect time for your wellness experience<\/p>\r\n    <\/div>\r\n    \r\n    <!-- Producto seleccionado (resumen) -->\r\n    <div class=\"producto-reserva-resumen\" id=\"productoResumen\" style=\"display: none;\">\r\n        <div class=\"producto-info\">\r\n            <img decoding=\"async\" id=\"productoImagen\" src=\"\" alt=\"\" class=\"producto-imagen-small\">\r\n            <div class=\"producto-detalles\">\r\n                <h3 id=\"productoNombre\" class=\"producto-nombre-small\"><\/h3>\r\n                <p id=\"productoDuracion\" class=\"producto-duracion-small\"><\/p>\r\n            <\/div>\r\n        <\/div>\r\n        <div class=\"producto-precio\">\r\n            <span id=\"productoPrecio\" class=\"precio-text\"><\/span>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <!-- Navegaci\u00f3n del calendario -->\r\n    <div class=\"calendario-navegacion\">\r\n        <button class=\"nav-btn nav-prev\" id=\"btnPrevMonth\">\r\n            <svg viewbox=\"0 0 24 24\" width=\"20\" height=\"20\">\r\n                <path d=\"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"\/>\r\n            <\/svg>\r\n        <\/button>\r\n        <div class=\"mes-actual\">\r\n            <span id=\"mesTexto\">August 2025<\/span>\r\n        <\/div>\r\n        <button class=\"nav-btn nav-next\" id=\"btnNextMonth\">\r\n            <svg viewbox=\"0 0 24 24\" width=\"20\" height=\"20\">\r\n                <path d=\"M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z\"\/>\r\n            <\/svg>\r\n        <\/button>\r\n    <\/div>\r\n\r\n    <!-- Grid del calendario mensual -->\r\n    <div class=\"calendario-mensual\">\r\n        <!-- Headers de d\u00edas de la semana -->\r\n        <div class=\"dias-semana\">\r\n            <div class=\"dia-semana\">Mon<\/div>\r\n            <div class=\"dia-semana\">Sea<\/div>\r\n            <div class=\"dia-semana\">Wed<\/div>\r\n            <div class=\"dia-semana\">Thu<\/div>\r\n            <div class=\"dia-semana\">Fri<\/div>\r\n            <div class=\"dia-semana\">Sat<\/div>\r\n            <div class=\"dia-semana\">Sun<\/div>\r\n        <\/div>\r\n        \r\n        <!-- Grid de d\u00edas del mes -->\r\n        <div class=\"dias-grid\" id=\"diasGrid\">\r\n            <!-- Los d\u00edas se generar\u00e1n din\u00e1micamente -->\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <!-- Panel de horarios -->\r\n    <div class=\"horarios-panel\" id=\"horariosPanel\" style=\"display: none;\">\r\n        <div class=\"horarios-header\">\r\n            <h3 id=\"fechaSeleccionada\">Available times<\/h3>\r\n            <button class=\"btn-cerrar-horarios\" id=\"btnCerrarHorarios\">\u00d7<\/button>\r\n        <\/div>\r\n        <div class=\"horarios-contenido\" id=\"horariosContenido\">\r\n            <!-- Los horarios se cargar\u00e1n aqu\u00ed -->\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <!-- Loading state -->\r\n    <div class=\"calendario-loading\" id=\"calendarioLoading\">\r\n        <div class=\"loading-spinner\"><\/div>\r\n        <p>Loading available schedules...<\/p>\r\n    <\/div>\r\n\r\n    <!-- Botones de acci\u00f3n -->\r\n    <div class=\"calendario-acciones\">\r\n        <button class=\"btn-secundario\" id=\"btnVolver\">Return to Products<\/button>\r\n        <button class=\"btn-primario paso4-boton-continuar\" id=\"btnConfirmarReserva\" disabled>Confirm Reservation<\/button>\r\n    <\/div>\r\n<\/div>\r\n\r\n<style>\r\n.calendario-reservas-container {\r\n    max-width: 1000px;\r\n    margin: 0 auto;\r\n    padding: 20px;\r\n    font-family: 'Josefin Sans', sans-serif;\r\n}\r\n\r\n.calendario-header {\r\n    text-align: center;\r\n    margin-bottom: 30px;\r\n}\r\n\r\n.calendario-titulo {\r\n    font-size: 28px;\r\n    font-weight: 700;\r\n    color: #31989E;\r\n    text-transform: uppercase;\r\n    margin: 0 0 10px 0;\r\n    letter-spacing: 1px;\r\n}\r\n\r\n.calendario-subtitulo {\r\n    font-size: 16px;\r\n    color: #666;\r\n    margin: 0;\r\n}\r\n\r\n\/* Resumen del producto *\/\r\n.producto-reserva-resumen {\r\n    background: linear-gradient(135deg, #f8fafc 0%, #e2f5f7 100%);\r\n    border: 2px solid rgba(49, 152, 158, 0.2);\r\n    border-radius: 5px;\r\n    padding: 10px;\r\n    margin-bottom: 30px;\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    box-shadow: 0 4px 15px rgba(49, 152, 158, 0.1);\r\n}\r\n\r\n.producto-info {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 15px;\r\n}\r\n\r\n.producto-imagen-small {\r\n    width: 60px;\r\n    height: 60px;\r\n    border-radius: 8px;\r\n    object-fit: cover;\r\n    border: 2px solid rgba(49, 152, 158, 0.3);\r\n}\r\n\r\n.producto-nombre-small {\r\n    font-size: 18px;\r\n    font-weight: 600;\r\n    color: #31989E;\r\n    margin: 0 0 5px 0;\r\n    text-transform: uppercase;\r\n}\r\n\r\n@media only screen and (max-width: 600px) {\r\n    .producto-nombre-small {\r\n    font-size: 14px;\r\n    font-weight: 600;\r\n    color: #31989E;\r\n    margin: 0 0 5px 0;\r\n    text-transform: uppercase;\r\n}\r\n}\r\n\r\n.producto-duracion-small {\r\n    font-size: 14px;\r\n    color: #666;\r\n    margin: 0;\r\n}\r\n\r\n.precio-text {\r\n    font-size: 24px;\r\n    font-weight: 400;\r\n    color: #31989E;\r\n}\r\n\r\n\/* Navegaci\u00f3n *\/\r\n.calendario-navegacion {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    margin-bottom: 20px;\r\n    padding: 0 10px;\r\n}\r\n\r\n.nav-btn {\r\n    background: #31989E;\r\n    border: none;\r\n    border-radius: 5px;\r\n    width: 45px;\r\n    height: 45px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    cursor: pointer;\r\n    transition: all 0.3s ease;\r\n    box-shadow: 0 2px 8px rgba(49, 152, 158, 0.3);\r\n}\r\n\r\n.nav-btn:hover {\r\n    background: #2a8187;\r\n    transform: translateY(-2px);\r\n    box-shadow: 0 4px 12px rgba(49, 152, 158, 0.4);\r\n}\r\n\r\n.nav-btn:disabled {\r\n    background: #ccc;\r\n    cursor: not-allowed;\r\n    transform: none;\r\n    box-shadow: none;\r\n}\r\n\r\n.nav-btn svg {\r\n    fill: white;\r\n}\r\n\r\n.mes-actual {\r\n    font-size: 20px;\r\n    font-weight: 600;\r\n    color: #31989E;\r\n    text-align: center;\r\n}\r\n\r\n\/* Calendario mensual *\/\r\n.calendario-mensual {\r\n    background: white;\r\n    border-radius: 5px;\r\n    box-shadow: 0 4px 15px rgba(0,0,0,0.1);\r\n    overflow: hidden;\r\n    margin-bottom: 30px;\r\n}\r\n\r\n.dias-semana {\r\n    display: grid;\r\n    grid-template-columns: repeat(7, 1fr);\r\n    background: #31989E;\r\n    color: white;\r\n}\r\n\r\n.dia-semana {\r\n    padding: 15px 10px;\r\n    text-align: center;\r\n    font-weight: 600;\r\n    font-size: 14px;\r\n    text-transform: uppercase;\r\n}\r\n\r\n.dias-grid {\r\n    display: grid;\r\n    grid-template-columns: repeat(7, 1fr);\r\n    border: 1px solid #e0e0e0;\r\n}\r\n\r\n.dia-celda {\r\n    min-height: 80px;\r\n    border: 1px solid #f0f0f0;\r\n    padding: 8px;\r\n    cursor: pointer;\r\n    transition: all 0.3s ease;\r\n    position: relative;\r\n    display: flex;\r\n    flex-direction: column;\r\n}\r\n\r\n.dia-celda:hover {\r\n    background: rgba(49, 152, 158, 0.05);\r\n}\r\n\r\n.dia-celda.otro-mes {\r\n    color: #ccc;\r\n    background: #f8f9fa;\r\n    cursor: not-allowed;\r\n}\r\n\r\n.dia-celda.hoy {\r\n    background: rgba(220, 38, 38, 0.1);\r\n    color: #dc2626;\r\n    font-weight: 600;\r\n}\r\n\r\n.dia-celda.seleccionado {\r\n    background: #31989E;\r\n    border: solid 1px #2a8187;\r\n}\r\n\r\n.dia-celda.con-horarios {\r\n    background: rgba(49, 152, 158, 0.1);\r\n}\r\n\r\n.dia-celda.con-horarios::after {\r\n    content: '';\r\n    position: absolute;\r\n    bottom: 5px;\r\n    right: 5px;\r\n    width: 8px;\r\n    height: 8px;\r\n    background: #31989E;\r\n    border-radius: 50%;\r\n}\r\n\r\n.numero-dia {\r\n    font-size: 16px;\r\n    font-weight: 500;\r\n    margin-bottom: 5px;\r\n}\r\n\r\n.indicador-horarios {\r\n    font-size: 10px;\r\n    color: #31989E;\r\n    text-align: center;\r\n}\r\n\r\n\/* ---------- ESTADOS DE CARGA PROGRESIVA ---------- *\/\r\n\r\n\/* Dia sin resolver. Neutro a proposito: no se muestra como disponible\r\n   (seria mentir) ni como agotado (tambien seria mentir). *\/\r\n.dia-celda.cargando {\r\n    background: linear-gradient(90deg, #fafafa 25%, #f0f0f0 50%, #fafafa 75%);\r\n    background-size: 200% 100%;\r\n    animation: dia-shimmer 1.4s ease-in-out infinite;\r\n}\r\n.dia-celda.cargando .numero-dia { color: #9aa0a6; }\r\n\r\n@keyframes dia-shimmer {\r\n    0%   { background-position: 200% 0; }\r\n    100% { background-position: -200% 0; }\r\n}\r\n\r\n.dia-celda.sin-horarios { background: #fbfbfb; cursor: default; }\r\n.dia-celda.sin-horarios .numero-dia,\r\n.dia-celda.sin-horarios .indicador-horarios { color: #b9bcc0; }\r\n.dia-celda.sin-horarios:hover { background: #fbfbfb; }\r\n\r\n.dia-celda.reintentar .indicador-horarios { color: #d97706; }\r\n\r\n.aviso-carga-horarios {\r\n    display: flex; align-items: center; gap: 8px;\r\n    padding: 8px 12px; font-size: 12px; color: #6b7280;\r\n    font-family: 'Josefin Sans', sans-serif;\r\n}\r\n.aviso-carga-horarios .punto-carga {\r\n    width: 8px; height: 8px; border-radius: 50%;\r\n    background: #31989E; animation: dia-pulso 1s ease-in-out infinite;\r\n}\r\n@keyframes dia-pulso { 0%,100% { opacity: .3; } 50% { opacity: 1; } }\r\n\r\n\/* Panel de horarios *\/\r\n.horarios-panel {\r\n    background: white;\r\n    border: 2px solid rgba(49, 152, 158, 0.2);\r\n    border-radius: 12px;\r\n    margin-bottom: 20px;\r\n    box-shadow: 0 4px 15px rgba(0,0,0,0.1);\r\n    animation: slideDown 0.3s ease-out;\r\n}\r\n\r\n@keyframes slideDown {\r\n    from {\r\n        opacity: 0;\r\n        transform: translateY(-20px);\r\n    }\r\n    to {\r\n        opacity: 1;\r\n        transform: translateY(0);\r\n    }\r\n}\r\n\r\n.horarios-header {\r\n    background: linear-gradient(135deg, #31989E 0%, #2a8187 100%);\r\n    color: white;\r\n    padding: 15px 20px;\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n}\r\n\r\n.horarios-header h3 {\r\n    margin: 0;\r\n    font-size: 18px;\r\n    font-weight: 600;\r\n}\r\n\r\n.btn-cerrar-horarios {\r\n    background: none;\r\n    border: none;\r\n    color: white;\r\n    font-size: 24px;\r\n    cursor: pointer;\r\n    padding: 0;\r\n    width: 30px;\r\n    height: 30px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    border-radius: 4px;\r\n    transition: background 0.3s ease;\r\n}\r\n\r\n.btn-cerrar-horarios:hover {\r\n    background: rgba(255, 255, 255, 0.2);\r\n}\r\n\r\n.horarios-contenido {\r\n    padding: 20px;\r\n}\r\n\r\n.profesional-grupo {\r\n    margin-bottom: 20px;\r\n}\r\n\r\n.profesional-grupo:last-child {\r\n    margin-bottom: 0;\r\n}\r\n\r\n.profesional-nombre {\r\n    font-size: 16px;\r\n    font-weight: 600;\r\n    color: #31989E;\r\n    margin-bottom: 10px;\r\n    padding-bottom: 5px;\r\n    border-bottom: 1px solid rgba(49, 152, 158, 0.2);\r\n}\r\n\r\n.horarios-lista {\r\n    display: grid;\r\n    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\r\n    gap: 10px;\r\n}\r\n\r\n.horario-btn {\r\n    background: #f8fafc;\r\n    border: 2px solid rgba(49, 152, 158, 0.2);\r\n    border-radius: 8px;\r\n    padding: 12px 16px;\r\n    font-size: 14px;\r\n    font-weight: 500;\r\n    color: #31989E;\r\n    cursor: pointer;\r\n    transition: all 0.3s ease;\r\n    text-align: center;\r\n}\r\n\r\n.horario-btn:hover {\r\n    background: rgba(49, 152, 158, 0.1);\r\n    border-color: #31989E;\r\n    color: #31989E;\r\n    transform: translateY(-1px);\r\n}\r\n\r\n.horario-btn.seleccionado {\r\n    background: #31989E;\r\n    border-color: #31989E;\r\n    color: white;\r\n    box-shadow: 0 2px 8px rgba(49, 152, 158, 0.4);\r\n}\r\n\r\n.horario-btn.seleccionado:hover{\r\n    color: white;\r\n}\r\n\r\n\/* Loading *\/\r\n.calendario-loading {\r\n    display: flex;\r\n    flex-direction: column;\r\n    align-items: center;\r\n    justify-content: center;\r\n    padding: 60px 20px;\r\n    color: #666;\r\n}\r\n\r\n.loading-spinner {\r\n    width: 40px;\r\n    height: 40px;\r\n    border: 4px solid #f0f0f0;\r\n    border-top: 4px solid #31989E;\r\n    border-radius: 50%;\r\n    animation: spin 1s linear infinite;\r\n    margin-bottom: 20px;\r\n}\r\n\r\n@keyframes spin {\r\n    0% { transform: rotate(0deg); }\r\n    100% { transform: rotate(360deg); }\r\n}\r\n\r\n\/* Botones de acci\u00f3n *\/\r\n.calendario-acciones {\r\n    display: flex;\r\n    gap: 15px;\r\n    justify-content: center;\r\n    margin-top: 30px;\r\n}\r\n\r\n.btn-secundario, .btn-primario {\r\n    padding: 10px 30px;\r\n    border: none;\r\n    border-radius: 5px;\r\n    font-size: 16px;\r\n    font-weight: 600;\r\n    cursor: pointer;\r\n    transition: all 0.3s ease;\r\n    letter-spacing: 0.5px;\r\n}\r\n\r\n.btn-secundario {\r\n    background: #f8f9fa;\r\n    color: #666;\r\n    border: 2px solid #e0e0e0;\r\n}\r\n\r\n.btn-secundario:hover {\r\n    background: #e9ecef;\r\n    border-color: #ccc;\r\n    color: #666;\r\n}\r\n\r\n.btn-secundario:focus {\r\n    background: #e9ecef;\r\n    border-color: #ccc;\r\n    color: #666;\r\n}\r\n\r\n.btn-primario {\r\n    background: #31989E;\r\n    color: white;\r\n    box-shadow: 0 4px 15px rgba(49, 152, 158, 0.3);\r\n}\r\n\r\n.btn-primario:hover:not(:disabled) {\r\n    background: #2a8187;\r\n    transform: translateY(-2px);\r\n    box-shadow: 0 6px 20px rgba(49, 152, 158, 0.4);\r\n}\r\n\r\n.btn-primario:disabled {\r\n    background: #ccc;\r\n    cursor: not-allowed;\r\n    transform: none;\r\n    box-shadow: none;\r\n}\r\n\r\n.btn-primario:focus{\r\n    background: #31989E;\r\n    color: white;\r\n}\r\n\r\n\/* Responsive *\/\r\n@media (max-width: 768px) {\r\n    .calendario-reservas-container {\r\n        padding: 15px;\r\n    }\r\n    \r\n    .producto-reserva-resumen {\r\n        flex-direction: column;\r\n        gap: 15px;\r\n        text-align: center;\r\n    }\r\n    \r\n    .calendario-acciones {\r\n        flex-direction: column;\r\n    }\r\n    \r\n    .btn-secundario, .btn-primario {\r\n        width: 100%;\r\n    }\r\n    \r\n    .horarios-lista {\r\n        grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));\r\n        gap: 8px;\r\n    }\r\n    \r\n    .dia-celda {\r\n        min-height: 60px;\r\n        padding: 4px;\r\n    }\r\n    \r\n    .numero-dia {\r\n        font-size: 14px;\r\n    }\r\n}\r\n<\/style>\r\n\r\n<script>\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    console.log('SISTEMA DE CALENDARIO MENSUAL INICIADO');\r\n\r\n    \/\/ Configuraci\u00f3n de la API\r\n    \/\/ El token se elimino: nunca se usaba en el frontend, la autenticacion\r\n    \/\/ con Reservo la hace el proxy del servidor.\r\n    const API_CONFIG = {\r\n        uuidAgenda: 's0074L7080V6CK6g6F10djh707u1S0'\r\n    };\r\n\r\n    \/\/ Dias que se resuelven en el primer tramo, antes de pintar disponibilidad.\r\n    \/\/ La mayoria elige fecha dentro de las proximas dos semanas.\r\n    const DIAS_PRIORITARIOS = 31;\r\n\r\n    \/\/ Cache en memoria para ir y venir entre meses en la misma visita\r\n    const CACHE_CLIENTE_TTL = 5 * 60 * 1000;\r\n\r\n    \/\/ Variables globales\r\n    let mesActual = new Date();\r\n    let productoSeleccionado = null;\r\n    let horariosDelMes = new Map();   \/\/ fecha -> datos (o null)\r\n    let estadoDias = new Map();       \/\/ fecha -> 'pendiente' | 'listo' | 'error'\r\n    let cacheCliente = new Map();     \/\/ 'uuid|fecha' -> { valor, ts }\r\n    let uuidTratamientoActual = null;\r\n    let generacionCarga = 0;          \/\/ descarta respuestas de un mes abandonado\r\n    let rangoDisponible = true;       \/\/ se apaga si falta el endpoint del servidor\r\n    let fechaSeleccionada = null;\r\n    let reservaSeleccionada = null;\r\n    let productosComplementarios = [];\r\n\r\n    \/\/ ==========================================================\r\n    \/\/ ERROR DIFERIDO\r\n    \/\/ ==========================================================\r\n    \/\/ Al entrar DIRECTO al calendario, el paso 1 sigue inicializandose y\r\n    \/\/ suele re-disparar 'productoSeleccionado' unos cientos de ms despues con\r\n    \/\/ el meta_data completo. El primer intento puede fallar y el segundo\r\n    \/\/ funcionar. Mostrar el error al instante hacia parpadear una pantalla de\r\n    \/\/ fallo justo antes de la carga correcta.\r\n    const DEMORA_ERROR = 3000;\r\n    let errorPendiente = null;\r\n\r\n    function programarError(mensaje) {\r\n        cancelarError();\r\n        errorPendiente = setTimeout(function () {\r\n            errorPendiente = null;\r\n            console.warn('El error persistio, se muestra al usuario:', mensaje);\r\n            mostrarLoading(false);\r\n            mostrarError(mensaje);\r\n        }, DEMORA_ERROR);\r\n        console.log('Error diferido ' + DEMORA_ERROR + 'ms (se cancela si llega otro intento)');\r\n    }\r\n\r\n    function cancelarError() {\r\n        if (errorPendiente) {\r\n            clearTimeout(errorPendiente);\r\n            errorPendiente = null;\r\n            console.log('Error pendiente cancelado');\r\n        }\r\n    } \r\n\r\n    \/\/ Elementos del DOM\r\n    const elementos = {\r\n        diasGrid: document.getElementById('diasGrid'),\r\n        loading: document.getElementById('calendarioLoading'),\r\n        mesTexto: document.getElementById('mesTexto'),\r\n        btnPrevMonth: document.getElementById('btnPrevMonth'),\r\n        btnNextMonth: document.getElementById('btnNextMonth'),\r\n        btnVolver: document.getElementById('btnVolver'),\r\n        btnConfirmar: document.getElementById('btnConfirmarReserva'),\r\n        productoResumen: document.getElementById('productoResumen'),\r\n        productoImagen: document.getElementById('productoImagen'),\r\n        productoNombre: document.getElementById('productoNombre'),\r\n        productoDuracion: document.getElementById('productoDuracion'),\r\n        productoPrecio: document.getElementById('productoPrecio'),\r\n        horariosPanel: document.getElementById('horariosPanel'),\r\n        fechaSeleccionada: document.getElementById('fechaSeleccionada'),\r\n        horariosContenido: document.getElementById('horariosContenido'),\r\n        btnCerrarHorarios: document.getElementById('btnCerrarHorarios')\r\n    };\r\n\r\n    \/\/ Inicializar\r\n    init();\r\n\r\n    function init() {\r\n        console.log('Inicializando calendario mensual');\r\n        \r\n        \/\/ Configurar mes inicial\r\n        mesActual = new Date();\r\n        mesActual.setDate(1); \/\/ Primer d\u00eda del mes\r\n        \r\n        \/\/ Event listeners\r\n        elementos.btnPrevMonth.addEventListener('click', () => cambiarMes(-1));\r\n        elementos.btnNextMonth.addEventListener('click', () => cambiarMes(1));\r\n        elementos.btnVolver.addEventListener('click', volverAProductos);\r\n        elementos.btnConfirmar.addEventListener('click', confirmarReserva);\r\n        elementos.btnCerrarHorarios.addEventListener('click', cerrarPanelHorarios);\r\n        \r\n        \/\/ Escuchar selecci\u00f3n de producto principal\r\n        document.addEventListener('productoSeleccionado', manejarProductoSeleccionado);\r\n        document.addEventListener('productoLimpiado', limpiarCalendario);\r\n        \r\n        \/\/ Cargar producto actual si existe\r\n        cargarProductoActual();\r\n    }\r\n\r\nasync function cargarProductoActual() {\r\n    \/\/ Cargar producto principal\r\n    const productoGuardado = localStorage.getItem('selectedProducto');\r\n    if (productoGuardado) {\r\n        try {\r\n            const parsed = JSON.parse(productoGuardado);\r\n            if (parsed.data) {\r\n                productoSeleccionado = parsed.data;\r\n                console.log('\ud83d\udce6 Producto principal cargado:', productoSeleccionado.name);\r\n            }\r\n        } catch (e) {\r\n            console.error('Error cargando producto guardado:', e);\r\n        }\r\n    }\r\n    \r\n    \/\/ NUEVO: Cargar productos complementarios\r\n    const complementosGuardados = localStorage.getItem('selectedComplementos');\r\n    if (complementosGuardados) {\r\n        try {\r\n            const complementarios = JSON.parse(complementosGuardados);\r\n            if (Array.isArray(complementarios) && complementarios.length > 0) {\r\n                productosComplementarios = complementarios.map(c => c.data);\r\n                console.log('\u2795 Complementarios cargados:', productosComplementarios.length);\r\n            }\r\n        } catch (e) {\r\n            console.error('Error cargando complementarios:', e);\r\n            productosComplementarios = [];\r\n        }\r\n    } else {\r\n        productosComplementarios = [];\r\n    }\r\n    \r\n    \/\/ Mostrar resumen completo\r\n    if (productoSeleccionado) {\r\n        mostrarResumenCompleto(); \/\/ CAMBIAR DE mostrarResumenProducto()\r\n        cargarHorariosDelMes();\r\n        return;\r\n    }\r\n    \r\n    mostrarMensajeSinProducto();\r\n}\r\n\r\nasync function manejarProductoSeleccionado(event) {\r\n    console.log('Producto seleccionado para reserva:', event.detail.productoData.name);\r\n\r\n    \/\/ Llega un producto con datos frescos: descarta un error programado por un\r\n    \/\/ intento anterior incompleto.\r\n    cancelarError();\r\n\r\n    productoSeleccionado = event.detail.productoData;\r\n    \r\n    \/\/ Tambi\u00e9n cargar complementarios cuando cambie el producto principal\r\n    const complementosGuardados = localStorage.getItem('selectedComplementos');\r\n    if (complementosGuardados) {\r\n        try {\r\n            const complementarios = JSON.parse(complementosGuardados);\r\n            productosComplementarios = complementarios.map(c => c.data);\r\n        } catch (e) {\r\n            productosComplementarios = [];\r\n        }\r\n    } else {\r\n        productosComplementarios = [];\r\n    }\r\n    \r\n    mostrarResumenCompleto(); \/\/ CAMBIAR DE mostrarResumenProducto()\r\n    cargarHorariosDelMes();\r\n}\r\n\r\n\/\/ NUEVOS event listeners\r\ndocument.addEventListener('complementosActualizados', function(e) {\r\n    console.log('\u2795 Complementarios actualizados en paso 4:', e.detail);\r\n    \r\n    const productosSeleccionados = e.detail.productos || [];\r\n    productosComplementarios = productosSeleccionados;\r\n    \r\n    \/\/ Re-mostrar el resumen completo\r\n    if (productoSeleccionado) {\r\n        mostrarResumenCompleto();\r\n    }\r\n});\r\n\r\ndocument.addEventListener('complementoEliminado', function(e) {\r\n    console.log('\u2796 Complementario eliminado, actualizando paso 4...');\r\n    \r\n    \/\/ Recargar complementarios desde localStorage\r\n    const complementosGuardados = localStorage.getItem('selectedComplementos');\r\n    if (complementosGuardados) {\r\n        try {\r\n            const complementarios = JSON.parse(complementosGuardados);\r\n            productosComplementarios = complementarios.map(c => c.data);\r\n        } catch (e) {\r\n            productosComplementarios = [];\r\n        }\r\n    } else {\r\n        productosComplementarios = [];\r\n    }\r\n    \r\n    \/\/ Re-mostrar el resumen\r\n    if (productoSeleccionado) {\r\n        mostrarResumenCompleto();\r\n    }\r\n});\r\n\r\nasync function mostrarResumenCompleto() {\r\n    if (!productoSeleccionado) return;\r\n    \r\n    console.log('\ud83d\udccb Mostrando resumen completo...');\r\n    console.log('  - Producto principal:', productoSeleccionado.name);\r\n    console.log('  - Complementarios:', productosComplementarios.length);\r\n    \r\n    \/\/ Calcular precio total\r\n    const precioPrincipal = parseFloat(productoSeleccionado.sale_price || \r\n                                     productoSeleccionado.regular_price || \r\n                                     productoSeleccionado.price || '0');\r\n    \r\n    let precioComplementarios = 0;\r\n    productosComplementarios.forEach(comp => {\r\n        const precio = parseFloat(comp.sale_price || comp.regular_price || comp.price || '0');\r\n        precioComplementarios += precio;\r\n    });\r\n    \r\n    const precioTotal = precioPrincipal + precioComplementarios;\r\n    \r\n    \/\/ Nombre completo con indicaci\u00f3n de complementarios\r\n    let nombreCompleto = productoSeleccionado.name.toUpperCase();\r\n    if (productosComplementarios.length > 0) {\r\n        nombreCompleto += ` + ${productosComplementarios.length} complemento${productosComplementarios.length > 1 ? 's' : ''}`;\r\n    }\r\n    \r\n    \/\/ Mostrar imagen por defecto primero\r\n    elementos.productoImagen.src = 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/foto-prod1@2x.png';\r\n    elementos.productoImagen.alt = productoSeleccionado.name;\r\n    \r\n    elementos.productoNombre.textContent = nombreCompleto;\r\n    elementos.productoDuracion.textContent = calcularDuracionTotal();\r\n    elementos.productoPrecio.textContent = formatPrice(precioTotal);\r\n    \r\n    \/\/ Agregar tooltip con desglose\r\n let tooltipText = `Producto principal: ${formatPrice(precioPrincipal)}`;\r\n    if (productosComplementarios.length > 0) {\r\n        productosComplementarios.forEach(comp => {\r\n            const precio = parseFloat(comp.sale_price || comp.regular_price || comp.price || '0');\r\n            tooltipText += `\\n${comp.name}: ${formatPrice(precio)}`;\r\n        });\r\n        tooltipText += `\\nTotal: ${formatPrice(precioTotal)}`;\r\n    }\r\n    elementos.productoPrecio.title = tooltipText;\r\n    \r\n    elementos.productoResumen.style.display = 'flex';\r\n    \r\n    \/\/ Cargar imagen correcta de forma as\u00edncrona\r\n    try {\r\n        const imagen = await obtenerImagenProducto(productoSeleccionado);\r\n        elementos.productoImagen.removeAttribute('srcset');\r\n        elementos.productoImagen.removeAttribute('sizes');\r\n        \/\/ Sin ?v=Date.now(): ese parametro forzaba descargar la imagen de nuevo\r\n        \/\/ en cada render, anulando el cache del navegador.\r\n        elementos.productoImagen.src = imagen;\r\n    } catch (error) {\r\n        console.error('\u274c Error actualizando imagen:', error);\r\n    }\r\n}\r\n\r\nasync function obtenerImagenProducto(producto) {\r\n    console.log('\ud83d\uddbc\ufe0f Obteniendo imagen para:', producto.name);\r\n    \r\n    try {\r\n        \/\/ Si el producto no tiene im\u00e1genes completas, cargar desde WooCommerce\r\n        if (!producto.images || !Array.isArray(producto.images) || producto.images.length === 0) {\r\n            console.log('  \ud83d\udd04 Cargando datos completos del producto desde WooCommerce...');\r\n            \r\n            \/\/ ANTES: wp-json\/wc\/v3\/products\/{id} con las credenciales en el JS.\r\n            \/\/ Traia el producto ENTERO para sacar una URL de imagen.\r\n            const respuestaImg = await jQuery.post(\r\n                (window.popupCartData && window.popupCartData.ajaxUrl) || '\/wp-admin\/admin-ajax.php',\r\n                { action: 'get_product_popup_data', product_id: producto.id, nonce: window.productPopupNonce || '' }\r\n            );\r\n\r\n            if (respuestaImg && respuestaImg.success && respuestaImg.data) {\r\n                const productoCompleto = respuestaImg.data;\r\n\r\n                if (productoCompleto.featured_image) {\r\n                    return productoCompleto.featured_image;\r\n                }\r\n\r\n                if (productoCompleto.images && productoCompleto.images.length > 0) {\r\n                    console.log(`  \ud83d\udcf8 ${productoCompleto.images.length} imagen(es) encontrada(s)`);\r\n                    \r\n                    \/\/ Intentar obtener la imagen principal\r\n                    const imagenPrincipal = productoCompleto.images.find(img => img.position === 0);\r\n                    if (imagenPrincipal && imagenPrincipal.src) {\r\n                        console.log(`  \u2705 Imagen principal: ${imagenPrincipal.src}`);\r\n                        return imagenPrincipal.src;\r\n                    }\r\n                    \r\n                    \/\/ Si no hay imagen principal, usar la primera disponible\r\n                    const primeraImagen = productoCompleto.images[0];\r\n                    if (primeraImagen && primeraImagen.src) {\r\n                        console.log(`  \u2705 Primera imagen: ${primeraImagen.src}`);\r\n                        return primeraImagen.src;\r\n                    }\r\n                }\r\n            } else {\r\n                console.error('  \u274c No se pudo obtener la imagen del producto');\r\n            }\r\n        } else {\r\n            console.log(`  \ud83d\udcf8 ${producto.images.length} imagen(es) ya disponible(s)`);\r\n            \r\n            \/\/ Intentar obtener la imagen principal\r\n            const imagenPrincipal = producto.images.find(img => img.position === 0);\r\n            if (imagenPrincipal && imagenPrincipal.src) {\r\n                console.log(`  \u2705 Imagen principal: ${imagenPrincipal.src}`);\r\n                return imagenPrincipal.src;\r\n            }\r\n            \r\n            \/\/ Si no hay imagen principal, usar la primera disponible\r\n            const primeraImagen = producto.images[0];\r\n            if (primeraImagen && primeraImagen.src) {\r\n                console.log(`  \u2705 Primera imagen: ${primeraImagen.src}`);\r\n                return primeraImagen.src;\r\n            }\r\n        }\r\n        \r\n    } catch (error) {\r\n        console.error('  \u274c Error obteniendo imagen:', error);\r\n    }\r\n    \r\n    console.log('  \u26a0\ufe0f Usando imagen por defecto');\r\n    return 'https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/foto-prod1@2x.png';\r\n}\r\n\r\n    function extraerDuracion(producto) {\r\n        if (producto.short_description) {\r\n            const match = producto.short_description.match(\/(\\d+)\\s*(hora|horas|minuto|minutos|min)\/i);\r\n            if (match) return `Duraci\u00f3n: ${match[0]}`;\r\n        }\r\n        return 'Duraci\u00f3n: 50 minutos';\r\n    }\r\n    \r\n    function calcularDuracionTotal() {\r\n    let duracionTotal = extraerDuracionNumerica(productoSeleccionado);\r\n    \r\n    productosComplementarios.forEach(complementario => {\r\n        duracionTotal += extraerDuracionNumerica(complementario);\r\n    });\r\n    \r\n    return `Duraci\u00f3n: ${duracionTotal} minutos`;\r\n}\r\n\r\nfunction extraerDuracionNumerica(producto) {\r\n    if (producto.short_description) {\r\n        const match = producto.short_description.match(\/(\\d+)\\s*(minuto|minutos|min)\/i);\r\n        if (match) return parseInt(match[1]);\r\n        \r\n        const matchHora = producto.short_description.match(\/(\\d+)\\s*(hora|horas)\/i);\r\n        if (matchHora) return parseInt(matchHora[1]) * 60;\r\n    }\r\n    \r\n    if (producto.description) {\r\n        const match = producto.description.match(\/(\\d+)\\s*(minuto|minutos|min)\/i);\r\n        if (match) return parseInt(match[1]);\r\n        \r\n        const matchHora = producto.description.match(\/(\\d+)\\s*(hora|horas)\/i);\r\n        if (matchHora) return parseInt(matchHora[1]) * 60;\r\n    }\r\n    \r\n    return 50; \/\/ Default 50 minutos\r\n}\r\n\r\n    function formatPrice(price) {\r\n        return new Intl.NumberFormat('es-CL', {\r\n            style: 'currency',\r\n            currency: 'CLP',\r\n            minimumFractionDigits: 0,\r\n            maximumFractionDigits: 0\r\n        }).format(parseFloat(price));\r\n    }\r\n\r\n    function mostrarMensajeSinProducto() {\r\n        elementos.productoResumen.style.display = 'none';\r\n        elementos.diasGrid.innerHTML = `\r\n            <div style=\"grid-column: 1 \/ -1; text-align: center; padding: 60px 20px; color: #666;\">\r\n                <div style=\"font-size: 64px; margin-bottom: 20px;\">\ud83d\udecd\ufe0f<\/div>\r\n                <h3 style=\"color: #31989E; margin: 0 0 10px 0;\">Selecciona un producto primero<\/h3>\r\n                <p style=\"margin: 0;\">Debes elegir un tratamiento antes de poder reservar tu cita.<\/p>\r\n            <\/div>\r\n        `;\r\n    }\r\n\r\n    \/\/ =====================================================================\r\n    \/\/ CARGA PROGRESIVA\r\n    \/\/ =====================================================================\r\n    \/\/ ANTES: 31 requests (incluidos los dias ya pasados), en lotes de 6 con\r\n    \/\/ 1000ms de espera hardcodeada entre lotes = 5s de espera artificial pura,\r\n    \/\/ y nada se pintaba hasta que resolvian todos.\r\n    \/\/\r\n    \/\/ AHORA:\r\n    \/\/   1. La grilla se pinta de inmediato, sin red.\r\n    \/\/   2. Los primeros DIAS_PRIORITARIOS dias se resuelven en 1 request.\r\n    \/\/   3. El resto se completa de fondo.\r\n    \/\/   4. Nunca se piden fechas pasadas.\r\n    \/\/ =====================================================================\r\n\r\n    async function cargarHorariosDelMes() {\r\n\r\n        if (!productoSeleccionado) {\r\n            mostrarMensajeSinProducto();\r\n            return;\r\n        }\r\n\r\n        cancelarError();\r\n\r\n        const generacion = ++generacionCarga;\r\n\r\n        let uuidTratamiento;\r\n\r\n        try {\r\n            uuidTratamiento = await obtenerUuidTratamiento(productoSeleccionado);\r\n        } catch (error) {\r\n            console.error('Error obteniendo UUID del tratamiento:', error);\r\n            programarError(error.message);\r\n            return;\r\n        }\r\n\r\n        if (generacion !== generacionCarga) return;\r\n\r\n        if (!uuidTratamiento) {\r\n            programarError('No se encontro el tratamiento asociado a este producto');\r\n            return;\r\n        }\r\n\r\n        uuidTratamientoActual = uuidTratamiento;\r\n\r\n        const fechas = fechasConsultablesDelMes();\r\n\r\n        horariosDelMes.clear();\r\n        estadoDias.clear();\r\n        fechas.forEach(f => estadoDias.set(formatFecha(f), 'pendiente'));\r\n\r\n        \/\/ PASO 1: grilla visible ya. Calculo local, no espera red.\r\n        mostrarLoading(false);\r\n        renderizarCalendarioMensual();\r\n\r\n        if (!fechas.length) return;   \/\/ mes enteramente pasado\r\n\r\n        const prioritarias = fechas.slice(0, DIAS_PRIORITARIOS);\r\n        const resto = fechas.slice(DIAS_PRIORITARIOS);\r\n\r\n        \/\/ PASO 2: tramo cercano\r\n        await cargarRangoDeFechas(uuidTratamiento, prioritarias);\r\n\r\n        if (generacion !== generacionCarga) return;\r\n\r\n        cancelarError();   \/\/ si algo cargo bien, el error programado ya no aplica\r\n        renderizarCalendarioMensual();\r\n\r\n        \/\/ PASO 3: el resto sin bloquear\r\n        if (resto.length) {\r\n            cargarRangoDeFechas(uuidTratamiento, resto).then(() => {\r\n                if (generacion !== generacionCarga) return;\r\n                renderizarCalendarioMensual();\r\n                prefetchMesSiguiente(uuidTratamiento);\r\n            });\r\n        } else {\r\n            prefetchMesSiguiente(uuidTratamiento);\r\n        }\r\n    }\r\n\r\n    \/** Fechas del mes visible desde hoy en adelante. *\/\r\n    function fechasConsultablesDelMes() {\r\n\r\n        const hoy = new Date();\r\n        hoy.setHours(0, 0, 0, 0);\r\n\r\n        const primerDia = new Date(mesActual.getFullYear(), mesActual.getMonth(), 1);\r\n        const ultimoDia = new Date(mesActual.getFullYear(), mesActual.getMonth() + 1, 0);\r\n\r\n        const fechas = [];\r\n\r\n        for (let f = new Date(primerDia); f <= ultimoDia; f.setDate(f.getDate() + 1)) {\r\n            if (f >= hoy) fechas.push(new Date(f));\r\n        }\r\n\r\n        return fechas;\r\n    }\r\n\r\n    async function cargarRangoDeFechas(uuidTratamiento, fechas, soloCache) {\r\n\r\n        const pendientes = [];\r\n\r\n        fechas.forEach(fecha => {\r\n            const fechaStr = typeof fecha === 'string' ? fecha : formatFecha(fecha);\r\n            const cacheado = leerCacheCliente(uuidTratamiento, fechaStr);\r\n\r\n            if (cacheado !== undefined) {\r\n                if (!soloCache) registrarResultado(fechaStr, cacheado);\r\n                return;\r\n            }\r\n\r\n            pendientes.push(fechaStr);\r\n        });\r\n\r\n        if (!pendientes.length) return;\r\n\r\n        \/\/ Camino rapido: 1 request, el fan-out ocurre en el servidor\r\n        if (rangoDisponible) {\r\n            const ok = await intentarRango(uuidTratamiento, pendientes, soloCache);\r\n            if (ok) return;\r\n        }\r\n\r\n        \/\/ Respaldo: por dia, en paralelo, SIN la espera de 1000ms.\r\n        \/\/ Funciona sin tocar functions.php, pero es modo degradado.\r\n        await cargarPorDiaEnParalelo(uuidTratamiento, pendientes, soloCache);\r\n    }\r\n\r\n    async function intentarRango(uuidTratamiento, pendientes, soloCache) {\r\n\r\n        const url = `${window.location.origin}\/wp-json\/sothers\/v1\/reservo-proxy\/horarios-rango`;\r\n        \r\n        \/*\r\n        const params = new URLSearchParams({\r\n            fechas: pendientes.join(','),\r\n            uuid_tratamiento: uuidTratamiento,\r\n            uuid_agenda: API_CONFIG.uuidAgenda\r\n        });\r\n        *\/\r\n        \r\n                const ordenadas = pendientes.slice().sort();\r\n\r\n        const params = new URLSearchParams({\r\n            desde: ordenadas[0],\r\n            hasta: ordenadas[ordenadas.length - 1],\r\n            uuid_tratamiento: uuidTratamiento,\r\n            uuid_agenda: API_CONFIG.uuidAgenda\r\n        });\r\n        \/\/ Hasta aqui el cmabio\r\n\r\n        try {\r\n            const response = await fetch(`${url}?${params}`, {\r\n                method: 'GET',\r\n                headers: { 'Accept': 'application\/json' }\r\n            });\r\n\r\n            \/\/ 404 = el bloque PHP del endpoint de rango no esta instalado\r\n            if (response.status === 404) {\r\n                rangoDisponible = false;\r\n                console.warn('El endpoint \/reservo-proxy\/horarios-rango no existe. ' +\r\n                             'Falta pegar calendario_rango_backend.php en functions.php. ' +\r\n                             'Se usa el modo por dia en paralelo (mas lento).');\r\n                return false;\r\n            }\r\n\r\n            if (!response.ok) throw new Error('HTTP ' + response.status);\r\n\r\n            const data = await response.json();\r\n            const horarios = (data && data.horarios) ? data.horarios : {};\r\n\r\n\/*\r\n            pendientes.forEach(fechaStr => {\r\n                const valor = Object.prototype.hasOwnProperty.call(horarios, fechaStr)\r\n                    ? horarios[fechaStr]\r\n                    : null;\r\n\r\n                guardarCacheCliente(uuidTratamiento, fechaStr, valor);\r\n                if (!soloCache) registrarResultado(fechaStr, valor);\r\n            });\r\n            *\/\r\n            \r\n             pendientes.forEach(fechaStr => {\r\n                if (!Object.prototype.hasOwnProperty.call(horarios, fechaStr)) {\r\n                    return;\r\n                }\r\n\r\n                const valor = horarios[fechaStr];\r\n\r\n                guardarCacheCliente(uuidTratamiento, fechaStr, valor);\r\n                if (!soloCache) registrarResultado(fechaStr, valor);\r\n            });\r\n\r\n            console.log(`Rango ${ordenadas[0]} a ${ordenadas[ordenadas.length - 1]}: ` +\r\n                `${Object.keys(horarios).length} dias resueltos en ${data.saltos} peticion(es)` +\r\n                (data.desde_cache ? `, ${data.desde_cache} desde cache` : ''));\r\n            \r\n            \/\/ Hasta aqui el cambio\r\n\/*\r\n\r\n            console.log(`Rango resuelto: ${pendientes.length} dias` +\r\n                (typeof data.desde_cache === 'number' ? ` (${data.desde_cache} desde cache del servidor)` : ''));\r\n*\/\r\n            return true;\r\n\r\n        } catch (error) {\r\n            console.error('Error en el endpoint de rango:', error);\r\n            return false;\r\n        }\r\n    }\r\n\r\n    async function cargarPorDiaEnParalelo(uuidTratamiento, fechas, soloCache) {\r\n\r\n        const TANDA = 6;\r\n\r\n        for (let i = 0; i < fechas.length; i += TANDA) {\r\n\r\n            const tanda = fechas.slice(i, i + TANDA);\r\n            const resultados = await Promise.all(\r\n                tanda.map(fechaStr => cargarHorariosFecha(uuidTratamiento, fechaStr))\r\n            );\r\n\r\n            tanda.forEach((fechaStr, idx) => {\r\n                if (!soloCache) registrarResultado(fechaStr, resultados[idx]);\r\n            });\r\n\r\n            \/\/ Sin espera artificial entre tandas. Los 1000ms del codigo viejo\r\n            \/\/ buscaban evitar el 429 de Reservo; 6 en paralelo esta por debajo\r\n            \/\/ del limite que ya usa el proxy del servidor.\r\n            if (!soloCache) renderizarCalendarioMensual();\r\n        }\r\n    }\r\n\r\n    function prefetchMesSiguiente(uuidTratamiento) {\r\n\r\n        const inicio = new Date(mesActual.getFullYear(), mesActual.getMonth() + 1, 1);\r\n        const fin = new Date(mesActual.getFullYear(), mesActual.getMonth() + 2, 0);\r\n\r\n        const hoy = new Date();\r\n        hoy.setHours(0, 0, 0, 0);\r\n\r\n        const fechas = [];\r\n\r\n        for (let f = new Date(inicio); f <= fin; f.setDate(f.getDate() + 1)) {\r\n            if (f >= hoy) fechas.push(formatFecha(f));\r\n        }\r\n\r\n        if (!fechas.length) return;\r\n\r\n        cargarRangoDeFechas(uuidTratamiento, fechas, true);\r\n    }\r\n\r\n    function registrarResultado(fechaStr, valor) {\r\n        horariosDelMes.set(fechaStr, valor);\r\n        estadoDias.set(fechaStr, 'listo');\r\n    }\r\n\r\n    \/**\r\n     * Un dia puede traer datos pero sin ningun cupo real. Antes se marcaba\r\n     * como \"Disponible\" y al abrirlo el panel salia vacio.\r\n     *\/\r\n    function tieneHorariosReales(data) {\r\n\r\n        if (!data || !Array.isArray(data.sucursales)) return false;\r\n\r\n        return data.sucursales.some(suc =>\r\n            Array.isArray(suc.profesionales) &&\r\n            suc.profesionales.some(p =>\r\n                Array.isArray(p.horas_disponibles) && p.horas_disponibles.length > 0\r\n            )\r\n        );\r\n    }\r\n\r\n    function claveCacheCliente(uuid, fechaStr) { return uuid + '|' + fechaStr; }\r\n\r\n    function leerCacheCliente(uuid, fechaStr) {\r\n        const entrada = cacheCliente.get(claveCacheCliente(uuid, fechaStr));\r\n        if (!entrada) return undefined;\r\n\r\n        if ((Date.now() - entrada.ts) > CACHE_CLIENTE_TTL) {\r\n            cacheCliente.delete(claveCacheCliente(uuid, fechaStr));\r\n            return undefined;\r\n        }\r\n\r\n        return entrada.valor;\r\n    }\r\n\r\n    function guardarCacheCliente(uuid, fechaStr, valor) {\r\n        cacheCliente.set(claveCacheCliente(uuid, fechaStr), { valor: valor, ts: Date.now() });\r\n    }\r\n\r\n    const uuidsMemo = new Map();\r\n\r\n    async function obtenerUuidTratamiento(producto) {\r\n\r\n        if (uuidsMemo.has(producto.id)) return uuidsMemo.get(producto.id);\r\n\r\n        const CLAVES = ['reservo_uuid', '_reservo_uuid', 'field_689b4c787beba', '_field_689b4c787beba'];\r\n\r\n        if (Array.isArray(producto.meta_data)) {\r\n            const meta = producto.meta_data.find(m => CLAVES.indexOf(m.key) !== -1);\r\n            if (meta && meta.value) {\r\n                uuidsMemo.set(producto.id, meta.value);\r\n                return meta.value;\r\n            }\r\n        }\r\n\r\n        if (producto.reservo_uuid) {\r\n            uuidsMemo.set(producto.id, producto.reservo_uuid);\r\n            return producto.reservo_uuid;\r\n        }\r\n\r\n        \/\/ Respaldo por AJAX. ANTES pedia el producto COMPLETO a\r\n        \/\/ wp-json\/wc\/v3\/products\/{id} con consumer_key y consumer_secret en el\r\n        \/\/ JS: peticion pesada y credenciales expuestas.\r\n        try {\r\n            const respuesta = await jQuery.post(\r\n                (window.popupCartData && window.popupCartData.ajaxUrl) || '\/wp-admin\/admin-ajax.php',\r\n                { action: 'get_reservo_uuid', product_id: producto.id, nonce: window.productPopupNonce || '' }\r\n            );\r\n\r\n            if (respuesta && respuesta.success && respuesta.data && respuesta.data.uuid) {\r\n                uuidsMemo.set(producto.id, respuesta.data.uuid);\r\n                return respuesta.data.uuid;\r\n            }\r\n        } catch (e) {\r\n            console.error('Error consultando el UUID del tratamiento:', e);\r\n        }\r\n\r\n        console.error('Falta el campo ACF \"reservo_uuid\" en el producto id=' + producto.id);\r\n        throw new Error('Este servicio todav\u00eda no est\u00e1 habilitado para reserva en l\u00ednea. Cont\u00e1ctanos para agendarlo.');\r\n    }\r\n\r\n    \/** Consulta de UN dia. Se usa para el click prioritario y como respaldo. *\/\r\n    async function cargarHorariosFecha(uuidTratamiento, fecha) {\r\n\r\n        const fechaStr = typeof fecha === 'string' ? fecha : formatFecha(fecha);\r\n\r\n        const cacheado = leerCacheCliente(uuidTratamiento, fechaStr);\r\n        if (cacheado !== undefined) return cacheado;\r\n\r\n        const url = `${window.location.origin}\/wp-json\/sothers\/v1\/reservo-proxy\/horarios`;\r\n        const params = new URLSearchParams({\r\n            fecha: fechaStr,\r\n            uuid_tratamiento: uuidTratamiento,\r\n            uuid_agenda: API_CONFIG.uuidAgenda\r\n        });\r\n\r\n        try {\r\n            const response = await fetch(`${url}?${params}`, {\r\n                method: 'GET',\r\n                headers: { 'Accept': 'application\/json' }\r\n            });\r\n\r\n            if (!response.ok) {\r\n                console.error(`Error HTTP ${response.status} para ${fechaStr}`);\r\n                return null;\r\n            }\r\n\r\n            const data = await response.json();\r\n            const valor = (Array.isArray(data) && data.length > 0) ? data[0] : null;\r\n\r\n            guardarCacheCliente(uuidTratamiento, fechaStr, valor);\r\n            return valor;\r\n\r\n        } catch (error) {\r\n            console.error(`Error cargando horarios para ${fechaStr}:`, error.message);\r\n            return null;\r\n        }\r\n    }\r\n\r\n    function formatFecha(fecha) {\r\n        return fecha.getFullYear() + '-' + \r\n               String(fecha.getMonth() + 1).padStart(2, '0') + '-' + \r\n               String(fecha.getDate()).padStart(2, '0');\r\n    }\r\n\r\n    function renderizarCalendarioMensual() {\r\n\r\n        actualizarMesTexto();\r\n\r\n        \/\/ Ya NO se corta con \"No hay horarios disponibles\" cuando el mapa esta\r\n        \/\/ vacio: al inicio siempre lo esta, y la grilla debe pintarse igual.\r\n        elementos.diasGrid.innerHTML = '';\r\n\r\n        const primerDia = new Date(mesActual.getFullYear(), mesActual.getMonth(), 1);\r\n        const diaSemana = primerDia.getDay();\r\n        const diasAntes = diaSemana === 0 ? 6 : diaSemana - 1;\r\n\r\n        const ultimoDia = new Date(mesActual.getFullYear(), mesActual.getMonth() + 1, 0);\r\n        const totalDiasMes = ultimoDia.getDate();\r\n\r\n        const hoy = new Date();\r\n        hoy.setHours(0, 0, 0, 0);\r\n\r\n        for (let i = diasAntes; i > 0; i--) {\r\n            const fecha = new Date(mesActual.getFullYear(), mesActual.getMonth(), -i + 1);\r\n            elementos.diasGrid.appendChild(crearDiaCalendario(fecha, { esOtroMes: true }));\r\n        }\r\n\r\n        for (let dia = 1; dia <= totalDiasMes; dia++) {\r\n            const fecha = new Date(mesActual.getFullYear(), mesActual.getMonth(), dia);\r\n            elementos.diasGrid.appendChild(crearDiaCalendario(fecha, {\r\n                esOtroMes: false,\r\n                esHoy: fecha.getTime() === hoy.getTime(),\r\n                esPasado: fecha < hoy,\r\n                estado: estadoDias.get(formatFecha(fecha)) || 'pendiente'\r\n            }));\r\n        }\r\n\r\n        const celdasTotales = elementos.diasGrid.children.length;\r\n        const celdasNecesarias = Math.ceil(celdasTotales \/ 7) * 7;\r\n\r\n        for (let i = 1; celdasTotales + i - 1 < celdasNecesarias; i++) {\r\n            const fecha = new Date(mesActual.getFullYear(), mesActual.getMonth() + 1, i);\r\n            elementos.diasGrid.appendChild(crearDiaCalendario(fecha, { esOtroMes: true }));\r\n        }\r\n\r\n        if (fechaSeleccionada) marcarDiaSeleccionado(formatFecha(fechaSeleccionada));\r\n\r\n        actualizarAvisoCarga();\r\n    }\r\n\r\n    function crearDiaCalendario(fecha, opciones) {\r\n\r\n        const cfg = opciones || {};\r\n        const fechaStr = formatFecha(fecha);\r\n        const diaDiv = document.createElement('div');\r\n        const clases = ['dia-celda'];\r\n\r\n        diaDiv.dataset.fecha = fechaStr;\r\n\r\n        const numeroDia = document.createElement('div');\r\n        numeroDia.className = 'numero-dia';\r\n        numeroDia.textContent = fecha.getDate();\r\n\r\n        if (cfg.esOtroMes || cfg.esPasado) {\r\n            clases.push('otro-mes');\r\n            diaDiv.className = clases.join(' ');\r\n            diaDiv.appendChild(numeroDia);\r\n            return diaDiv;\r\n        }\r\n\r\n        if (cfg.esHoy) clases.push('hoy');\r\n\r\n        let etiqueta = null;\r\n        let clickeable = false;\r\n\r\n        if (cfg.estado === 'listo') {\r\n            if (tieneHorariosReales(horariosDelMes.get(fechaStr))) {\r\n                clases.push('con-horarios');\r\n                etiqueta = 'Disponible';\r\n                clickeable = true;\r\n            } else {\r\n                clases.push('sin-horarios');\r\n                etiqueta = 'Sin horarios';\r\n            }\r\n        } else if (cfg.estado === 'error') {\r\n            clases.push('reintentar');\r\n            etiqueta = 'Reintentar';\r\n            clickeable = true;\r\n        } else {\r\n            \/\/ Pendiente: neutro. No decimos \"disponible\" ni \"agotado\" porque\r\n            \/\/ todavia no lo sabemos. Clickeable: se resuelve con prioridad.\r\n            clases.push('cargando');\r\n            clickeable = true;\r\n        }\r\n\r\n        diaDiv.className = clases.join(' ');\r\n        diaDiv.appendChild(numeroDia);\r\n\r\n        if (etiqueta) {\r\n            const ind = document.createElement('div');\r\n            ind.className = 'indicador-horarios';\r\n            ind.textContent = etiqueta;\r\n            diaDiv.appendChild(ind);\r\n        }\r\n\r\n        if (clickeable) {\r\n            diaDiv.style.cursor = 'pointer';\r\n            diaDiv.addEventListener('click', () => seleccionarFecha(fecha, diaDiv));\r\n        }\r\n\r\n        return diaDiv;\r\n    }\r\n\r\n    function marcarDiaSeleccionado(fechaStr) {\r\n\r\n        document.querySelectorAll('.dia-celda.seleccionado').forEach(d => d.classList.remove('seleccionado'));\r\n\r\n        const celda = elementos.diasGrid.querySelector(`.dia-celda[data-fecha=\"${fechaStr}\"]:not(.otro-mes)`);\r\n        if (celda) celda.classList.add('seleccionado');\r\n    }\r\n\r\n    \/** Aviso discreto mientras se completa el mes de fondo. *\/\r\n    function actualizarAvisoCarga() {\r\n\r\n        const contenedor = document.querySelector('.calendario-mensual') || elementos.diasGrid.parentNode;\r\n        if (!contenedor) return;\r\n\r\n        let aviso = contenedor.querySelector('.aviso-carga-horarios');\r\n        let pendientes = 0;\r\n\r\n        estadoDias.forEach(e => { if (e === 'pendiente') pendientes++; });\r\n\r\n        if (pendientes === 0) {\r\n            if (aviso) aviso.remove();\r\n            return;\r\n        }\r\n\r\n        if (!aviso) {\r\n            aviso = document.createElement('div');\r\n            aviso.className = 'aviso-carga-horarios';\r\n            aviso.innerHTML = '<span class=\"punto-carga\"><\/span><span class=\"texto-carga\"><\/span>';\r\n            contenedor.appendChild(aviso);\r\n        }\r\n\r\n        aviso.querySelector('.texto-carga').textContent =\r\n            `Completando disponibilidad (${pendientes} ${pendientes === 1 ? 'd\u00eda' : 'd\u00edas'} por confirmar)`;\r\n    }\r\n\r\n    async function seleccionarFecha(fecha, celda) {\r\n\r\n        const fechaStr = formatFecha(fecha);\r\n\r\n        fechaSeleccionada = fecha;\r\n\r\n        document.querySelectorAll('.dia-celda.seleccionado').forEach(d => d.classList.remove('seleccionado'));\r\n        if (celda) celda.classList.add('seleccionado');\r\n\r\n        \/\/ Si el dia no resolvio todavia, se resuelve ahora con prioridad\r\n        if (estadoDias.get(fechaStr) !== 'listo') {\r\n\r\n            mostrarPanelCargandoHorarios(fecha);\r\n\r\n            const valor = await cargarHorariosFecha(uuidTratamientoActual, fechaStr);\r\n\r\n            registrarResultado(fechaStr, valor);\r\n            renderizarCalendarioMensual();\r\n            marcarDiaSeleccionado(fechaStr);\r\n        }\r\n\r\n        const horariosData = horariosDelMes.get(fechaStr);\r\n\r\n        if (!tieneHorariosReales(horariosData)) {\r\n            mostrarPanelSinHorarios(fecha);\r\n            return;\r\n        }\r\n\r\n        mostrarPanelHorarios(fecha, horariosData);\r\n    }\r\n\r\n    function textoFechaLarga(fecha) {\r\n        return fecha.toLocaleDateString('es-ES', {\r\n            weekday: 'long', day: 'numeric', month: 'long', year: 'numeric'\r\n        });\r\n    }\r\n\r\n    function mostrarPanelCargandoHorarios(fecha) {\r\n\r\n        elementos.fechaSeleccionada.textContent = `Horarios para ${textoFechaLarga(fecha)}`;\r\n        elementos.horariosContenido.innerHTML = `\r\n            <div style=\"text-align:center; padding:40px; color:#666;\">\r\n                <div style=\"width:32px; height:32px; margin:0 auto 15px; border:3px solid #f0f0f0; border-top:3px solid #31989E; border-radius:50%; animation:spin-horarios .8s linear infinite;\"><\/div>\r\n                <p style=\"margin:0;\">Consultando disponibilidad...<\/p>\r\n            <\/div>\r\n            <style>@keyframes spin-horarios { 0%{transform:rotate(0)} 100%{transform:rotate(360deg)} }<\/style>\r\n        `;\r\n        elementos.horariosPanel.style.display = 'block';\r\n    }\r\n\r\n    function mostrarPanelSinHorarios(fecha) {\r\n\r\n        elementos.fechaSeleccionada.textContent = `Horarios para ${textoFechaLarga(fecha)}`;\r\n        elementos.horariosContenido.innerHTML = `\r\n            <div style=\"text-align:center; padding:40px; color:#666;\">\r\n                <p style=\"margin:0 0 6px 0; font-weight:600;\">No hay horarios disponibles para esta fecha.<\/p>\r\n                <p style=\"margin:0; font-size:14px;\">Prob\u00e1 con otro d\u00eda del calendario.<\/p>\r\n            <\/div>\r\n        `;\r\n        elementos.horariosPanel.style.display = 'block';\r\n    }\r\n\r\n    function mostrarPanelHorarios(fecha, horariosData) {\r\n        const fechaFormateada = fecha.toLocaleDateString('es-ES', {\r\n            weekday: 'long',\r\n            day: 'numeric',\r\n            month: 'long',\r\n            year: 'numeric'\r\n        });\r\n        \r\n        elementos.fechaSeleccionada.textContent = `Horarios para ${fechaFormateada}`;\r\n        elementos.horariosContenido.innerHTML = '';\r\n        \r\n        if (!horariosData.sucursales || horariosData.sucursales.length === 0) {\r\n            elementos.horariosContenido.innerHTML = `\r\n                <div style=\"text-align: center; padding: 40px; color: #666;\">\r\n                    <p>No hay horarios disponibles para esta fecha.<\/p>\r\n                <\/div>\r\n            `;\r\n        } else {\r\n            const sucursal = horariosData.sucursales[0];\r\n            \r\n            if (sucursal.profesionales && sucursal.profesionales.length > 0) {\r\n                sucursal.profesionales.forEach(profesional => {\r\n                    if (profesional.horas_disponibles && profesional.horas_disponibles.length > 0) {\r\n                        const profesionalDiv = document.createElement('div');\r\n                        profesionalDiv.className = 'profesional-grupo';\r\n                        \r\n                        profesionalDiv.innerHTML = `\r\n                            <div class=\"profesional-nombre\">${profesional.nombre}<\/div>\r\n                            <div class=\"horarios-lista\">\r\n                                ${profesional.horas_disponibles.map(hora => {\r\n                                    const horaFormateada = formatearHora(hora);\r\n                                    return `\r\n                                        <button class=\"horario-btn\" \r\n                                                data-fecha=\"${horariosData.fecha}\"\r\n                                                data-hora=\"${hora}\"\r\n                                                data-profesional=\"${profesional.nombre}\"\r\n                                                data-agenda=\"${profesional.agenda}\"\r\n                                                onclick=\"seleccionarHorario(this)\">\r\n                                            ${horaFormateada}\r\n                                        <\/button>\r\n                                    `;\r\n                                }).join('')}\r\n                            <\/div>\r\n                        `;\r\n                        \r\n                        elementos.horariosContenido.appendChild(profesionalDiv);\r\n                    }\r\n                });\r\n            }\r\n        }\r\n        \r\n        elementos.horariosPanel.style.display = 'block';\r\n        \r\n        \/\/ Scroll suave al panel\r\n        elementos.horariosPanel.scrollIntoView({ \r\n            behavior: 'smooth', \r\n            block: 'nearest' \r\n        });\r\n    }\r\n\r\n    function formatearHora(horaISO) {\r\n        const fecha = new Date(horaISO);\r\n        return fecha.toLocaleTimeString('es-ES', { \r\n            hour: '2-digit', \r\n            minute: '2-digit',\r\n            hour12: false \r\n        });\r\n    }\r\n\r\n    function cerrarPanelHorarios() {\r\n        elementos.horariosPanel.style.display = 'none';\r\n        \r\n        \/\/ Limpiar selecci\u00f3n de d\u00eda\r\n        document.querySelectorAll('.dia-celda.seleccionado').forEach(dia => {\r\n            dia.classList.remove('seleccionado');\r\n        });\r\n        \r\n        fechaSeleccionada = null;\r\n        limpiarSeleccionHorario();\r\n    }\r\n\r\n    function limpiarSeleccionHorario() {\r\n        reservaSeleccionada = null;\r\n        elementos.btnConfirmar.disabled = true;\r\n        elementos.btnConfirmar.textContent = 'Confirmar Reserva';\r\n        \r\n        document.querySelectorAll('.horario-btn.seleccionado').forEach(btn => {\r\n            btn.classList.remove('seleccionado');\r\n        });\r\n    }\r\n\r\n    \/\/ Funci\u00f3n global para seleccionar horario\r\n    window.seleccionarHorario = function(boton) {\r\n        \/\/ Limpiar selecci\u00f3n anterior\r\n        document.querySelectorAll('.horario-btn.seleccionado').forEach(btn => {\r\n            btn.classList.remove('seleccionado');\r\n        });\r\n        \r\n        \/\/ Seleccionar nuevo horario\r\n        boton.classList.add('seleccionado');\r\n        \r\n        \/\/ Guardar datos de la reserva\r\n        reservaSeleccionada = {\r\n            fecha: boton.dataset.fecha,\r\n            hora: boton.dataset.hora,\r\n            profesional: boton.dataset.profesional,\r\n            agenda: boton.dataset.agenda,\r\n            producto: productoSeleccionado\r\n        };\r\n        \r\n        console.log('\u2705 Horario seleccionado:', reservaSeleccionada);\r\n        \r\n        \/\/ Habilitar bot\u00f3n de confirmar\r\n        elementos.btnConfirmar.disabled = false;\r\n        \r\n        const fechaFormateada = formatearFechaCorta(reservaSeleccionada.fecha);\r\n        const horaFormateada = formatearHora(reservaSeleccionada.hora);\r\n        elementos.btnConfirmar.textContent = `Confirmar - ${fechaFormateada} ${horaFormateada}`;\r\n        \r\n        \/\/ Scroll suave hacia los botones\r\n        elementos.btnConfirmar.scrollIntoView({ \r\n            behavior: 'smooth', \r\n            block: 'nearest' \r\n        });\r\n        \r\n        document.dispatchEvent(new CustomEvent('horarioSeleccionado', {\r\n        detail: {\r\n            fecha: reservaSeleccionada.fecha,\r\n            hora: reservaSeleccionada.hora,\r\n            profesional: reservaSeleccionada.profesional,\r\n            agenda: reservaSeleccionada.agenda,\r\n            sucursal: 'Spa & Wellness Dr Roy Sothers'\r\n        }\r\n    }));\r\n    };\r\n\r\n    function formatearFechaCorta(fechaStr) {\r\n        const fecha = new Date(fechaStr + 'T00:00:00');\r\n        return fecha.toLocaleDateString('es-ES', { \r\n            day: 'numeric', \r\n            month: 'short' \r\n        });\r\n    }\r\n\r\n    function cambiarMes(direccion) {\r\n        console.log(`\ud83d\udcc5 Cambiando mes: ${direccion > 0 ? 'siguiente' : 'anterior'}`);\r\n        \r\n        mesActual.setMonth(mesActual.getMonth() + direccion);\r\n        limpiarSelecciones();\r\n        cargarHorariosDelMes();\r\n    }\r\n\r\n    function limpiarSelecciones() {\r\n        fechaSeleccionada = null;\r\n        reservaSeleccionada = null;\r\n        elementos.horariosPanel.style.display = 'none';\r\n        elementos.btnConfirmar.disabled = true;\r\n        elementos.btnConfirmar.textContent = 'Confirmar Reserva';\r\n        \r\n        document.querySelectorAll('.dia-celda.seleccionado').forEach(dia => {\r\n            dia.classList.remove('seleccionado');\r\n        });\r\n        \r\n        document.querySelectorAll('.horario-btn.seleccionado').forEach(btn => {\r\n            btn.classList.remove('seleccionado');\r\n        });\r\n    }\r\n\r\n    function actualizarMesTexto() {\r\n        const nombreMes = mesActual.toLocaleDateString('es-ES', { \r\n            month: 'long', \r\n            year: 'numeric' \r\n        });\r\n        elementos.mesTexto.textContent = nombreMes.charAt(0).toUpperCase() + nombreMes.slice(1);\r\n        \r\n        \/\/ Deshabilitar bot\u00f3n anterior si es el mes actual o anterior\r\n        const hoy = new Date();\r\n        const mesHoy = new Date(hoy.getFullYear(), hoy.getMonth(), 1);\r\n        elementos.btnPrevMonth.disabled = mesActual <= mesHoy;\r\n    }\r\n\r\n    function mostrarLoading(mostrar) {\r\n\r\n        \/\/ ANTES esta funcion ocultaba .calendario-mensual por completo, asi que\r\n        \/\/ durante toda la carga el usuario veia solo un spinner. Era LA razon\r\n        \/\/ de la pantalla en blanco: no importa cuanto optimices la red si lo\r\n        \/\/ primero que hace el codigo es esconder el calendario.\r\n        if (elementos.loading) {\r\n            elementos.loading.style.display = mostrar ? 'flex' : 'none';\r\n        }\r\n\r\n        const calendario = document.querySelector('.calendario-mensual');\r\n        if (calendario) calendario.style.display = 'block';\r\n    }\r\n\r\n    function mostrarError(mensaje) {\r\n        elementos.diasGrid.innerHTML = `\r\n            <div style=\"grid-column: 1 \/ -1; text-align: center; padding: 60px 20px; color: #dc2626;\">\r\n                <div style=\"font-size: 64px; margin-bottom: 20px;\">\u26a0\ufe0f<\/div>\r\n                <h3 style=\"color: #dc2626; margin: 0 0 10px 0;\">Error al cargar horarios<\/h3>\r\n                <p style=\"margin: 0 0 20px 0;\">${mensaje}<\/p>\r\n                <button onclick=\"location.reload()\" style=\"background: #31989E; color: white; border: none; padding: 10px 20px; border-radius: 6px; cursor: pointer;\">\r\n                    Intentar de nuevo\r\n                <\/button>\r\n            <\/div>\r\n        `;\r\n    }\r\n\r\n    function volverAProductos() {\r\n        console.log('\ud83d\udd19 Volviendo a selecci\u00f3n de productos');\r\n        \r\n        const selectoresContainer = document.querySelector('.elementor-element-717f167') || \r\n                                   document.querySelector('[data-id=\"717f167\"]') ||\r\n                                   document.body;\r\n        \r\n        selectoresContainer.scrollIntoView({ \r\n            behavior: 'smooth', \r\n            block: 'start' \r\n        });\r\n    }\r\n\r\n    async function confirmarReserva() {\r\n        if (!reservaSeleccionada) {\r\n            alert('Por favor selecciona un horario primero');\r\n            return;\r\n        }\r\n\r\n        console.log('\u2705 Confirmando reserva:', reservaSeleccionada);\r\n        \r\n        elementos.btnConfirmar.disabled = true;\r\n        elementos.btnConfirmar.textContent = 'Procesando...';\r\n        \r\n        try {\r\n            await simularCrearReserva(reservaSeleccionada);\r\n            mostrarConfirmacionReserva(reservaSeleccionada);\r\n            \r\n        } catch (error) {\r\n            console.error('\u274c Error confirmando reserva:', error);\r\n            alert('Error al confirmar la reserva. Por favor intenta de nuevo.');\r\n            \r\n            elementos.btnConfirmar.disabled = false;\r\n            const fechaFormateada = formatearFechaCorta(reservaSeleccionada.fecha);\r\n            const horaFormateada = formatearHora(reservaSeleccionada.hora);\r\n            elementos.btnConfirmar.textContent = `Confirmar - ${fechaFormateada} ${horaFormateada}`;\r\n        }\r\n    }\r\n\r\n    async function simularCrearReserva(reserva) {\r\n        return new Promise((resolve) => {\r\n            setTimeout(() => {\r\n                console.log('\ud83c\udf89 Reserva creada exitosamente:', reserva);\r\n                resolve();\r\n            }, 2000);\r\n        });\r\n    }\r\n\r\n    function mostrarConfirmacionReserva(reserva) {\r\n        const fechaFormateada = new Date(reserva.hora).toLocaleDateString('es-ES', {\r\n            weekday: 'long',\r\n            year: 'numeric',\r\n            month: 'long',\r\n            day: 'numeric'\r\n        });\r\n        \r\n        const horaFormateada = formatearHora(reserva.hora);\r\n        \r\n        elementos.diasGrid.innerHTML = `\r\n            <div style=\"grid-column: 1 \/ -1; text-align: center; padding: 60px 20px; background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%); border-radius: 12px; border: 2px solid #22c55e;\">\r\n                <div style=\"font-size: 64px; margin-bottom: 20px;\">\ud83c\udf89<\/div>\r\n                <h2 style=\"color: #16a34a; margin: 0 0 20px 0; font-size: 28px;\">\u00a1Reserva Confirmada!<\/h2>\r\n                \r\n                <div style=\"background: white; border-radius: 8px; padding: 30px; margin: 20px auto; max-width: 500px; box-shadow: 0 4px 15px rgba(0,0,0,0.1);\">\r\n                    <h3 style=\"color: #31989E; margin: 0 0 15px 0;\">${reserva.producto.name.toUpperCase()}<\/h3>\r\n                    <p style=\"margin: 5px 0; color: #666;\"><strong>Fecha:<\/strong> ${fechaFormateada}<\/p>\r\n                    <p style=\"margin: 5px 0; color: #666;\"><strong>Hora:<\/strong> ${horaFormateada}<\/p>\r\n                    <p style=\"margin: 5px 0; color: #666;\"><strong>Profesional:<\/strong> ${reserva.profesional}<\/p>\r\n                    <p style=\"margin: 15px 0 5px 0; color: #31989E; font-size: 18px; font-weight: 600;\">\r\n                        Total: ${formatPrice(reserva.producto.sale_price || reserva.producto.regular_price || reserva.producto.price || '0')}\r\n                    <\/p>\r\n                <\/div>\r\n                \r\n                <p style=\"color: #666; margin: 20px 0;\">Te hemos enviado un email de confirmaci\u00f3n con todos los detalles de tu reserva.<\/p>\r\n                \r\n                <div style=\"margin-top: 30px; display: flex; gap: 15px; justify-content: center;\">\r\n                    <button onclick=\"location.reload()\" style=\"background: #31989E;  border: none; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: 600;\">\r\n                        Nueva Reserva\r\n                    <\/button>\r\n                    <button onclick=\"window.print()\" style=\"background: #f8f9fa; color: #666; border: 2px solid #e0e0e0; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: 600;\">\r\n                        Imprimir\r\n                    <\/button>\r\n                <\/div>\r\n            <\/div>\r\n        `;\r\n        \r\n        elementos.horariosPanel.style.display = 'none';\r\n        elementos.btnConfirmar.style.display = 'none';\r\n        elementos.btnVolver.style.display = 'none';\r\n        \r\n        localStorage.setItem('ultimaReserva', JSON.stringify({\r\n            ...reserva,\r\n            fechaCreacion: new Date().toISOString()\r\n        }));\r\n        \r\n        elementos.diasGrid.scrollIntoView({ \r\n            behavior: 'smooth', \r\n            block: 'center' \r\n        });\r\n    }\r\n\r\n    function limpiarCalendario() {\r\n        console.log('\ud83e\uddf9 Limpiando calendario');\r\n\r\n        cancelarError();\r\n\r\n        productoSeleccionado = null;\r\n        uuidTratamientoActual = null;\r\n\r\n        \/\/ Invalida cualquier carga en vuelo: sus respuestas se descartan\r\n        generacionCarga++;\r\n\r\n        horariosDelMes.clear();\r\n        estadoDias.clear();\r\n\r\n        const aviso = document.querySelector('.aviso-carga-horarios');\r\n        if (aviso) aviso.remove();\r\n\r\n        limpiarSelecciones();\r\n        elementos.productoResumen.style.display = 'none';\r\n        mostrarMensajeSinProducto();\r\n    }\r\n\r\n    \/\/ Event listeners adicionales\r\n    document.addEventListener('servicioLimpiado', limpiarCalendario);\r\n    document.addEventListener('categoriaLimpiada', limpiarCalendario);\r\n    document.addEventListener('limpiarTodasLasSelecciones', limpiarCalendario);\r\n\r\n    console.log('\u2705 Sistema de calendario mensual inicializado correctamente');\r\n});\r\n<\/script>\r\n\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1565a64 elementor-widget elementor-widget-html\" data-id=\"1565a64\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\n    \/\/ Script para modificar el comportamiento del bot\u00f3n \"Confirmar Reserva\"\ndocument.addEventListener('DOMContentLoaded', function() {\n    console.log('\ud83d\udd04 MODIFICANDO COMPORTAMIENTO DEL BOT\u00d3N CONFIRMAR RESERVA');\n\n    \/\/ Funci\u00f3n para modificar el bot\u00f3n confirmar\n    function modificarBotonConfirmar() {\n        const btnConfirmar = document.getElementById('btnConfirmarReserva');\n        \n        if (btnConfirmar) {\n            console.log('\u2705 Bot\u00f3n confirmar encontrado, modificando comportamiento...');\n            \n            \/\/ Remover todos los event listeners existentes clonando el elemento\n            const nuevoBoton = btnConfirmar.cloneNode(true);\n            btnConfirmar.parentNode.replaceChild(nuevoBoton, btnConfirmar);\n            \n            \/\/ Agregar nuevo event listener que redirija a #datos-usuario\n            nuevoBoton.addEventListener('click', function(e) {\n                e.preventDefault();\n                e.stopPropagation();\n                \n                console.log('\ud83c\udfaf Redirigiendo a secci\u00f3n de datos de usuario...');\n                \n                \/\/ Validar que hay una reserva seleccionada\n                if (!validarReservaSeleccionada()) {\n                    alert('Por favor selecciona una fecha y horario primero');\n                    return;\n                }\n                \n                \/\/ Scroll suave a la secci\u00f3n de datos\n                \n                redirigirADatosUsuario();\n                \n            });\n            \n            console.log('\u2705 Comportamiento del bot\u00f3n modificado exitosamente');\n        } else {\n            console.log('\u26a0\ufe0f Bot\u00f3n confirmar no encontrado, reintentando...');\n            \/\/ Reintentar despu\u00e9s de un momento\n            setTimeout(modificarBotonConfirmar, 1000);\n        }\n    }\n\n    \/\/ Funci\u00f3n para validar que hay una reserva seleccionada\n    function validarReservaSeleccionada() {\n        \/\/ Verificar datos en datosReservaCompleta\n        if (window.datosReservaCompleta) {\n            const tieneReserva = window.datosReservaCompleta.fecha && \n                               window.datosReservaCompleta.hora && \n                               window.datosReservaCompleta.profesional &&\n                               window.datosReservaCompleta.agenda;\n            \n            if (tieneReserva) {\n                console.log('\u2705 Reserva v\u00e1lida encontrada:', {\n                    fecha: window.datosReservaCompleta.fecha,\n                    hora: window.datosReservaCompleta.hora,\n                    profesional: window.datosReservaCompleta.profesional\n                });\n                return true;\n            }\n        }\n\n        \/\/ Verificar si hay un horario seleccionado visualmente\n        const horarioSeleccionado = document.querySelector('.horario-btn.seleccionado');\n        if (horarioSeleccionado) {\n            console.log('\u2705 Horario seleccionado encontrado en DOM');\n            return true;\n        }\n\n        \/\/ Verificar variables globales alternativas\n        if (window.reservaSeleccionada && window.reservaSeleccionada.fecha) {\n            console.log('\u2705 Reserva encontrada en reservaSeleccionada');\n            return true;\n        }\n\n        console.log('\u274c No se encontr\u00f3 una reserva seleccionada');\n        return false;\n    }\n\n    \/\/ Funci\u00f3n para redirigir con scroll suave\n    \n    function redirigirADatosUsuario() {\n        \/\/ Buscar la secci\u00f3n de datos de usuario\n        \/*\n        const seccionDatos = document.querySelector('#datos-usuario') || \n                            document.querySelector('[id*=\"datos\"]') ||\n                            document.querySelector('.datos-usuario') ||\n                            document.querySelector('[class*=\"formulario\"]') ||\n                            document.querySelector('form.elementor-form');\n\n        if (seccionDatos) {\n            console.log('\u2705 Secci\u00f3n de datos encontrada, haciendo scroll...');\n            \n            \/\/ Scroll suave a la secci\u00f3n\n            seccionDatos.scrollIntoView({ \n                behavior: 'smooth', \n                block: 'start',\n                inline: 'nearest'\n            });\n\n            \/\/ Opcional: agregar efecto visual a la secci\u00f3n\n            destacarSeccionDatos(seccionDatos);\n\n            \/\/ Opcional: actualizar URL con anchor\n            if (seccionDatos.id) {\n                window.history.pushState(null, null, '#' + seccionDatos.id);\n            } else {\n                window.history.pushState(null, null, '#datos-usuario');\n            }\n\n        } else {\n            console.log('\u26a0\ufe0f Secci\u00f3n de datos no encontrada, haciendo scroll hacia abajo...');\n            \n            \/\/ Fallback: scroll hacia abajo para buscar el formulario\n            window.scrollBy({\n                top: window.innerHeight * 0.8,\n                behavior: 'smooth'\n            });\n        }\n*\/\n        siguientePaso();\n        \/\/ Mostrar mensaje de confirmaci\u00f3n\n        mostrarMensajeConfirmacion();\n    }\n\n    \/\/ Funci\u00f3n para destacar visualmente la secci\u00f3n de datos\n    function destacarSeccionDatos(seccion) {\n        \/\/ Agregar una clase temporal para highlighting\n        seccion.style.transition = 'all 0.3s ease';\n        seccion.style.boxShadow = '0 0 20px rgba(49, 152, 158, 0.3)';\n        seccion.style.border = '2px solid rgba(49, 152, 158, 0.5)';\n        seccion.style.borderRadius = '8px';\n\n        \/\/ Remover el highlighting despu\u00e9s de 3 segundos\n        setTimeout(() => {\n            seccion.style.boxShadow = '';\n            seccion.style.border = '';\n            seccion.style.borderRadius = '';\n        }, 3000);\n    }\n\n    \/\/ Funci\u00f3n para mostrar mensaje de confirmaci\u00f3n\n    function mostrarMensajeConfirmacion() {\n        \/\/ Crear toast\/notificaci\u00f3n\n        const mensaje = document.createElement('div');\n        mensaje.style.cssText = `\n            position: fixed;\n            bottom: 20px;\n            right: 20px;\n            background: #31989E;\n            color: white;\n            padding: 15px 25px;\n            border-radius: 8px;\n            box-shadow: 0 4px 15px rgba(49, 152, 158, 0.3);\n            z-index: 10000;\n            font-family: 'Josefin Sans', sans-serif;\n            font-weight: 600;\n            animation: slideIn 0.3s ease-out;\n        `;\n        \n        \/\/ Obtener datos de la reserva para el mensaje\n        let infoReserva = '';\n        if (window.datosReservaCompleta && window.datosReservaCompleta.fecha) {\n            const fecha = new Date(window.datosReservaCompleta.fecha + 'T00:00:00');\n            const fechaFormateada = fecha.toLocaleDateString('es-ES', { \n                weekday: 'long', \n                day: 'numeric', \n                month: 'long' \n            });\n            \n            let hora = '';\n            if (window.datosReservaCompleta.hora) {\n                const horaObj = new Date(window.datosReservaCompleta.hora);\n                hora = horaObj.toLocaleTimeString('es-ES', { \n                    hour: '2-digit', \n                    minute: '2-digit' \n                });\n            }\n\n            infoReserva = `<br><small style=\"opacity: 0.9;\">${fechaFormateada} ${hora}<\/small>`;\n        }\n\n        mensaje.innerHTML = `\n            <div style=\"display: flex; align-items: center; gap: 10px;\">\n                <div>\n                    <strong>Horario seleccionado<\/strong>\n                    ${infoReserva}\n                    <br><small style=\"opacity: 0.8;\">Completa tus datos para continuar<\/small>\n                <\/div>\n            <\/div>\n        `;\n\n        \/\/ Agregar animaci\u00f3n CSS\n        const style = document.createElement('style');\n        style.textContent = `\n            @keyframes slideIn {\n                from {\n                    transform: translateX(100%);\n                    opacity: 0;\n                }\n                to {\n                    transform: translateX(0);\n                    opacity: 1;\n                }\n            }\n        `;\n        document.head.appendChild(style);\n\n        document.body.appendChild(mensaje);\n\n        \/\/ Auto-remover despu\u00e9s de 5 segundos\n        setTimeout(() => {\n            mensaje.style.animation = 'slideIn 0.3s ease-out reverse';\n            setTimeout(() => {\n                if (mensaje.parentNode) {\n                    mensaje.parentNode.removeChild(mensaje);\n                }\n            }, 300);\n        }, 5000);\n    }\n\n    \/\/ Funci\u00f3n para intercertar cuando se selecciona un horario y actualizar el bot\u00f3n\n    function interceptarSeleccionHorario() {\n        \/\/ Observar cambios en horarios seleccionados\n        const observer = new MutationObserver(function(mutations) {\n            mutations.forEach(function(mutation) {\n                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {\n                    const target = mutation.target;\n                    if (target.classList.contains('horario-btn') && target.classList.contains('seleccionado')) {\n                        actualizarTextoBotonConfirmar();\n                    }\n                }\n            });\n        });\n\n        \/\/ Observar el panel de horarios\n        const panelHorarios = document.getElementById('horariosPanel');\n        if (panelHorarios) {\n            observer.observe(panelHorarios, {\n                attributes: true,\n                subtree: true,\n                attributeFilter: ['class']\n            });\n        }\n\n        \/\/ Tambi\u00e9n escuchar eventos personalizados\n        document.addEventListener('horarioSeleccionado', actualizarTextoBotonConfirmar);\n    }\n\n    \/\/ Funci\u00f3n para actualizar el texto del bot\u00f3n seg\u00fan la selecci\u00f3n\n    function actualizarTextoBotonConfirmar() {\n        const btnConfirmar = document.getElementById('btnConfirmarReserva');\n        \n        if (btnConfirmar && validarReservaSeleccionada()) {\n            let textoBoton = 'Continuar con Reserva';\n            \n            \/\/ Intentar obtener informaci\u00f3n espec\u00edfica de la reserva\n            if (window.datosReservaCompleta) {\n                const fecha = window.datosReservaCompleta.fecha;\n                const hora = window.datosReservaCompleta.hora;\n                \n                if (fecha && hora) {\n                    const fechaObj = new Date(fecha + 'T00:00:00');\n                    const horaObj = new Date(hora);\n                    \n                    const fechaCorta = fechaObj.toLocaleDateString('es-ES', { \n                        day: 'numeric', \n                        month: 'short' \n                    });\n                    const horaCorta = horaObj.toLocaleTimeString('es-ES', { \n                        hour: '2-digit', \n                        minute: '2-digit' \n                    });\n                    \n                    textoBoton = `Continuar - ${fechaCorta} ${horaCorta}`;\n                }\n            }\n            \n            btnConfirmar.textContent = textoBoton;\n            btnConfirmar.disabled = false;\n            \n            console.log('\u2705 Texto del bot\u00f3n actualizado:', textoBoton);\n        }\n    }\n\n    \/\/ Event listeners para intercertar eventos del sistema de calendario\n    document.addEventListener('productoSeleccionado', function() {\n        \/\/ Cuando se selecciona un producto, reinicializar el bot\u00f3n\n        setTimeout(modificarBotonConfirmar, 500);\n    });\n\n    \/\/ Escuchar cuando se actualiza datosReservaCompleta\n    let lastReservaState = null;\n    setInterval(() => {\n        if (window.datosReservaCompleta) {\n            const currentState = JSON.stringify({\n                fecha: window.datosReservaCompleta.fecha,\n                hora: window.datosReservaCompleta.hora,\n                profesional: window.datosReservaCompleta.profesional\n            });\n            \n            if (currentState !== lastReservaState) {\n                lastReservaState = currentState;\n                actualizarTextoBotonConfirmar();\n            }\n        }\n    }, 1000);\n\n    \/\/ Funci\u00f3n global para testing\n    \n    window.testRedireccionDatos = function() {\n        console.log('\ud83e\uddea Testeando redirecci\u00f3n a datos de usuario...');\n        redirigirADatosUsuario();\n    };\n\n    \/\/ Funci\u00f3n global para forzar modificaci\u00f3n del bot\u00f3n\n    window.modificarBotonConfirmarManual = function() {\n        console.log('\ud83d\udd27 Modificando bot\u00f3n manualmente...');\n        modificarBotonConfirmar();\n    };\n\n    \/\/ Inicializar\n    modificarBotonConfirmar();\n    interceptarSeleccionHorario();\n\n    console.log('\u2705 Sistema de redirecci\u00f3n de confirmar reserva inicializado');\n    console.log('\ud83d\udca1 Funciones de testing disponibles:');\n    console.log('  - window.testRedireccionDatos() - Probar redirecci\u00f3n');\n    console.log('  - window.modificarBotonConfirmarManual() - Forzar modificaci\u00f3n del bot\u00f3n');\n});\n\n\n\n\n\n\/\/ Script para transferir funcionalidad de botones HTML a botones de Elementor\ndocument.addEventListener('DOMContentLoaded', function() {\n    console.log('\ud83d\udd04 SINCRONIZANDO BOTONES DE ELEMENTOR CON CALENDARIO');\n\n    \/\/ Funci\u00f3n para sincronizar los botones\n    function sincronizarBotones() {\n        \/\/ 1. Bot\u00f3n \"Volver a Productos\" - Elementor\n        const btnVolverElementor = document.querySelector('.elementor-element-cbddb52 .elementor-button');\n        \/\/ Bot\u00f3n original del HTML personalizado\n        const btnVolverOriginal = document.getElementById('btnVolver');\n\n        if (btnVolverElementor && btnVolverOriginal) {\n            console.log('\u2705 Sincronizando bot\u00f3n \"Volver\" de Elementor...');\n            \n            \/\/ Copiar funcionalidad del bot\u00f3n original\n            btnVolverElementor.addEventListener('click', function(e) {\n                e.preventDefault();\n                e.stopPropagation();\n                \n                console.log('\ud83d\udd19 Ejecutando funci\u00f3n \"Volver a Productos\" desde bot\u00f3n Elementor');\n                \n                \/\/ Ejecutar la misma funci\u00f3n que el bot\u00f3n original\n                const selectoresContainer = document.querySelector('.elementor-element-717f167') || \n                                           document.querySelector('[data-id=\"717f167\"]') ||\n                                           document.body;\n                \n                selectoresContainer.scrollIntoView({ \n                    behavior: 'smooth', \n                    block: 'start' \n                });\n            });\n            \n            \/\/ Ocultar el bot\u00f3n original del HTML\n            if (btnVolverOriginal.parentElement) {\n                btnVolverOriginal.parentElement.style.display = 'none';\n            }\n        }\n\n        \/\/ 2. Bot\u00f3n \"Confirmar Reserva\" - Elementor\n        const btnConfirmarElementor = document.querySelector('.elementor-element-38a75ab .elementor-button');\n        const btnConfirmarOriginal = document.getElementById('btnConfirmarReserva');\n\n        if (btnConfirmarElementor && btnConfirmarOriginal) {\n            console.log('\u2705 Sincronizando bot\u00f3n \"Confirmar\" de Elementor...');\n            \n            \/\/ Funci\u00f3n para sincronizar estado del bot\u00f3n\n            function sincronizarEstadoBoton() {\n                \/\/ Copiar texto del bot\u00f3n original\n                const textoOriginal = btnConfirmarOriginal.textContent;\n                const spanTexto = btnConfirmarElementor.querySelector('.elementor-button-text');\n                if (spanTexto) {\n                    spanTexto.textContent = textoOriginal;\n                }\n\n                \/\/ Copiar estado disabled\n                if (btnConfirmarOriginal.disabled) {\n                    btnConfirmarElementor.style.opacity = '0.6';\n                    btnConfirmarElementor.style.cursor = 'not-allowed';\n                    btnConfirmarElementor.setAttribute('data-disabled', 'true');\n                } else {\n                    btnConfirmarElementor.style.opacity = '';\n                    btnConfirmarElementor.style.cursor = '';\n                    btnConfirmarElementor.removeAttribute('data-disabled');\n                }\n            }\n\n            \/\/ Sincronizar estado inicial\n            sincronizarEstadoBoton();\n\n            \/\/ Observar cambios en el bot\u00f3n original\n            const observer = new MutationObserver(function(mutations) {\n                mutations.forEach(function(mutation) {\n                    if (mutation.type === 'attributes' || mutation.type === 'childList') {\n                        sincronizarEstadoBoton();\n                    }\n                });\n            });\n\n            observer.observe(btnConfirmarOriginal, {\n                attributes: true,\n                childList: true,\n                subtree: true,\n                attributeFilter: ['disabled']\n            });\n\n            \/\/ Agregar funcionalidad al bot\u00f3n de Elementor\n            btnConfirmarElementor.addEventListener('click', function(e) {\n                e.preventDefault();\n                e.stopPropagation();\n                \n                \/\/ Verificar si el bot\u00f3n est\u00e1 deshabilitado\n                if (btnConfirmarElementor.getAttribute('data-disabled') === 'true') {\n                    console.log('\u26a0\ufe0f Bot\u00f3n deshabilitado, no se puede continuar');\n                    return;\n                }\n\n                console.log('\ud83c\udfaf Ejecutando confirmaci\u00f3n desde bot\u00f3n Elementor...');\n                \n                \/\/ Validar que hay una reserva seleccionada\n                if (!validarReservaSeleccionada()) {\n                    alert('Por favor selecciona una fecha y horario primero');\n                    return;\n                }\n                \n                \/\/ Redirigir a secci\u00f3n de datos de usuario\n                \n                redirigirADatosUsuario();\n                \n            });\n            \n            \/\/ Ocultar el bot\u00f3n original del HTML\n            if (btnConfirmarOriginal.parentElement) {\n                btnConfirmarOriginal.parentElement.style.display = 'none';\n            }\n        }\n    }\n\n    \/\/ Funciones auxiliares (copiadas del script original)\n    function validarReservaSeleccionada() {\n        \/\/ Verificar datos en datosReservaCompleta\n        if (window.datosReservaCompleta) {\n            const tieneReserva = window.datosReservaCompleta.fecha && \n                               window.datosReservaCompleta.hora && \n                               window.datosReservaCompleta.profesional &&\n                               window.datosReservaCompleta.agenda;\n            \n            if (tieneReserva) {\n                console.log('\u2705 Reserva v\u00e1lida encontrada:', {\n                    fecha: window.datosReservaCompleta.fecha,\n                    hora: window.datosReservaCompleta.hora,\n                    profesional: window.datosReservaCompleta.profesional\n                });\n                return true;\n            }\n        }\n\n        \/\/ Verificar si hay un horario seleccionado visualmente\n        const horarioSeleccionado = document.querySelector('.horario-btn.seleccionado');\n        if (horarioSeleccionado) {\n            console.log('\u2705 Horario seleccionado encontrado en DOM');\n            return true;\n        }\n\n        \/\/ Verificar variables globales alternativas\n        if (window.reservaSeleccionada && window.reservaSeleccionada.fecha) {\n            console.log('\u2705 Reserva encontrada en reservaSeleccionada');\n            return true;\n        }\n\n        console.log('\u274c No se encontr\u00f3 una reserva seleccionada');\n        return false;\n    }\n\n    function redirigirADatosUsuario() {\n        \/\/ Buscar la secci\u00f3n de datos de usuario\n        \/*\n        const seccionDatos = document.querySelector('#datos-usuario') || \n                            document.querySelector('[id*=\"datos\"]') ||\n                            document.querySelector('.datos-usuario') ||\n                            document.querySelector('[class*=\"formulario\"]') ||\n                            document.querySelector('form.elementor-form');\n\n        if (seccionDatos) {\n            console.log('\u2705 Secci\u00f3n de datos encontrada, haciendo scroll...');\n            \n            \/\/ Scroll suave a la secci\u00f3n\n            seccionDatos.scrollIntoView({ \n                behavior: 'smooth', \n                block: 'start',\n                inline: 'nearest'\n            });\n\n            destacarSeccionDatos(seccionDatos);\n\n            \/\/ Actualizar URL con anchor\n            if (seccionDatos.id) {\n                window.history.pushState(null, null, '#' + seccionDatos.id);\n            } else {\n                window.history.pushState(null, null, '#datos-usuario');\n            }\n\n        } else {\n            console.log('\u26a0\ufe0f Secci\u00f3n de datos no encontrada, haciendo scroll hacia abajo...');\n            \n            \/\/ Fallback: scroll hacia abajo\n            window.scrollBy({\n                top: window.innerHeight * 0.8,\n                behavior: 'smooth'\n            });\n        }\n*\/\n        siguientePaso();\n        mostrarMensajeConfirmacion();\n    }\n\n    function destacarSeccionDatos(seccion) {\n        seccion.style.transition = 'all 0.3s ease';\n        seccion.style.boxShadow = '0 0 20px rgba(49, 152, 158, 0.3)';\n        seccion.style.border = '2px solid rgba(49, 152, 158, 0.5)';\n        seccion.style.borderRadius = '8px';\n\n        setTimeout(() => {\n            seccion.style.boxShadow = '';\n            seccion.style.border = '';\n            seccion.style.borderRadius = '';\n        }, 3000);\n    }\n\n    function mostrarMensajeConfirmacion() {\n        const mensaje = document.createElement('div');\n        mensaje.style.cssText = `\n            position: fixed;\n            bottom: 20px;\n            right: 20px;\n            background: #31989E;\n            color: white;\n            padding: 15px 25px;\n            border-radius: 8px;\n            box-shadow: 0 4px 15px rgba(49, 152, 158, 0.3);\n            z-index: 10000;\n            font-family: 'Josefin Sans', sans-serif;\n            font-weight: 600;\n            animation: slideIn 0.3s ease-out;\n        `;\n        \n        let infoReserva = '';\n        if (window.datosReservaCompleta && window.datosReservaCompleta.fecha) {\n            const fecha = new Date(window.datosReservaCompleta.fecha + 'T00:00:00');\n            const fechaFormateada = fecha.toLocaleDateString('es-ES', { \n                weekday: 'long', \n                day: 'numeric', \n                month: 'long' \n            });\n            \n            let hora = '';\n            if (window.datosReservaCompleta.hora) {\n                const horaObj = new Date(window.datosReservaCompleta.hora);\n                hora = horaObj.toLocaleTimeString('es-ES', { \n                    hour: '2-digit', \n                    minute: '2-digit' \n                });\n            }\n\n            infoReserva = `<br><small style=\"opacity: 0.9;\">${fechaFormateada} ${hora}<\/small>`;\n        }\n\n        mensaje.innerHTML = `\n            <div style=\"display: flex; align-items: center; gap: 10px;\">\n                <div>\n                    <strong>Horario seleccionado<\/strong>\n                    ${infoReserva}\n                    <br><small style=\"opacity: 0.8;\">Completa tus datos para continuar<\/small>\n                <\/div>\n            <\/div>\n        `;\n\n        \/\/ Agregar animaci\u00f3n CSS si no existe\n        if (!document.querySelector('#slideInAnimation')) {\n            const style = document.createElement('style');\n            style.id = 'slideInAnimation';\n            style.textContent = `\n                @keyframes slideIn {\n                    from {\n                        transform: translateX(100%);\n                        opacity: 0;\n                    }\n                    to {\n                        transform: translateX(0);\n                        opacity: 1;\n                    }\n                }\n            `;\n            document.head.appendChild(style);\n        }\n\n        document.body.appendChild(mensaje);\n\n        setTimeout(() => {\n            mensaje.style.animation = 'slideIn 0.3s ease-out reverse';\n            setTimeout(() => {\n                if (mensaje.parentNode) {\n                    mensaje.parentNode.removeChild(mensaje);\n                }\n            }, 300);\n        }, 5000);\n    }\n\n    \/\/ Funci\u00f3n para reinicializar cuando se carga nuevo contenido\n    function reinicializarCuandoSeaReady() {\n        const checkInterval = setInterval(() => {\n            const btnVolverElementor = document.querySelector('.elementor-element-cbddb52 .elementor-button');\n            const btnConfirmarElementor = document.querySelector('.elementor-element-38a75ab .elementor-button');\n            const btnVolverOriginal = document.getElementById('btnVolver');\n            const btnConfirmarOriginal = document.getElementById('btnConfirmarReserva');\n\n            if (btnVolverElementor && btnConfirmarElementor && btnVolverOriginal && btnConfirmarOriginal) {\n                clearInterval(checkInterval);\n                sincronizarBotones();\n                console.log('\u2705 Botones de Elementor sincronizados con funcionalidad del calendario');\n            }\n        }, 500);\n\n        \/\/ Timeout de seguridad\n        setTimeout(() => {\n            clearInterval(checkInterval);\n        }, 10000);\n    }\n\n    \/\/ Event listeners para reininicializar cuando cambie el contenido\n    document.addEventListener('productoSeleccionado', () => {\n        setTimeout(reinicializarCuandoSeaReady, 1000);\n    });\n\n    document.addEventListener('horarioSeleccionado', () => {\n        setTimeout(() => {\n            \/\/ Re-sincronizar solo el estado del bot\u00f3n confirmar\n            const btnConfirmarElementor = document.querySelector('.elementor-element-38a75ab .elementor-button');\n            const btnConfirmarOriginal = document.getElementById('btnConfirmarReserva');\n            \n            if (btnConfirmarElementor && btnConfirmarOriginal) {\n                const textoOriginal = btnConfirmarOriginal.textContent;\n                const spanTexto = btnConfirmarElementor.querySelector('.elementor-button-text');\n                if (spanTexto) {\n                    spanTexto.textContent = textoOriginal;\n                }\n            }\n        }, 100);\n    });\n\n    \/\/ Funci\u00f3n global para testing\n    window.testSincronizacionBotones = function() {\n        console.log('\ud83e\uddea Testeando sincronizaci\u00f3n de botones...');\n        sincronizarBotones();\n    };\n\n    \/\/ Inicializar\n    reinicializarCuandoSeaReady();\n\n    console.log('\u2705 Sistema de sincronizaci\u00f3n de botones Elementor inicializado');\n    console.log('\ud83d\udca1 Funci\u00f3n de testing disponible: window.testSincronizacionBotones()');\n});\n\n\n\n\n\n\n\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-5dd184c e-con-full e-flex e-con e-child\" data-id=\"5dd184c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-cbddb52 elementor-widget elementor-widget-button\" data-id=\"cbddb52\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"#\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Volver<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-38a75ab paso4-boton-continuar elementor-widget elementor-widget-button\" data-id=\"38a75ab\" data-element_type=\"widget\" data-e-type=\"widget\" id=\"btnConfirmarReserva\" data-widget_type=\"button.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-button-wrapper\">\n\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"#\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Confirm Reservation<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7a6e612 e-con-full elementor-hidden-tablet elementor-hidden-mobile e-flex e-con e-child\" data-id=\"7a6e612\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-822d28f e-con-full paso5-ingresa-tus-datos e-flex e-con e-parent\" data-id=\"822d28f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-a761c34 e-con-full e-flex e-con e-child\" data-id=\"a761c34\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1ca4d27 elementor-widget elementor-widget-heading\" data-id=\"1ca4d27\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">ENTER YOUR DATA<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-607ef7b e-con-full e-flex e-con e-child\" data-id=\"607ef7b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-fbe0f90 elementor-button-align-stretch elementor-widget elementor-widget-form\" data-id=\"fbe0f90\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;step_next_label&quot;:&quot;Siguiente&quot;,&quot;step_previous_label&quot;:&quot;Anterior&quot;,&quot;button_width&quot;:&quot;100&quot;,&quot;step_type&quot;:&quot;number_text&quot;,&quot;step_icon_shape&quot;:&quot;circle&quot;}\" data-widget_type=\"form.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<form class=\"elementor-form\" method=\"post\" name=\"Nuevo formulario\" aria-label=\"Nuevo formulario\" action=\"\">\n\t\t\t<input type=\"hidden\" name=\"post_id\" value=\"25747\"\/>\n\t\t\t<input type=\"hidden\" name=\"form_id\" value=\"fbe0f90\"\/>\n\t\t\t<input type=\"hidden\" name=\"referer_title\" value=\"Acompa\u00f1amiento de Reserva\" \/>\n\n\t\t\t\t\t\t\t<input type=\"hidden\" name=\"queried_id\" value=\"25747\"\/>\n\t\t\t\n\t\t\t<div class=\"elementor-form-fields-wrapper elementor-labels-above\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-text elementor-field-group elementor-column elementor-field-group-name elementor-col-50 elementor-field-required elementor-mark-required\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-name\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tRUT\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"text\" name=\"form_fields[name]\" id=\"form-field-name\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" placeholder=\"12.345.678-9\" required=\"required\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-text elementor-field-group elementor-column elementor-field-group-field_49f8b85 elementor-col-50 elementor-field-required elementor-mark-required\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-field_49f8b85\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tName\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"text\" name=\"form_fields[field_49f8b85]\" id=\"form-field-field_49f8b85\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" placeholder=\"Name\" required=\"required\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-text elementor-field-group elementor-column elementor-field-group-field_99b781e elementor-col-50 elementor-field-required elementor-mark-required\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-field_99b781e\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tPaternal Surname\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"text\" name=\"form_fields[field_99b781e]\" id=\"form-field-field_99b781e\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" placeholder=\"Paternal Surname\" required=\"required\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-text elementor-field-group elementor-column elementor-field-group-field_0b35636 elementor-col-50 elementor-field-required elementor-mark-required\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-field_0b35636\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tMother&#039;s Surname\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"text\" name=\"form_fields[field_0b35636]\" id=\"form-field-field_0b35636\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" placeholder=\"Mother&#039;s Surname\" required=\"required\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-email elementor-field-group elementor-column elementor-field-group-email elementor-col-50 elementor-field-required elementor-mark-required\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-email\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tE-mail\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"email\" name=\"form_fields[email]\" id=\"form-field-email\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" placeholder=\"example@email.com\" required=\"required\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-tel elementor-field-group elementor-column elementor-field-group-field_1b3c851 elementor-col-50 elementor-field-required elementor-mark-required\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-field_1b3c851\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tPhone\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t<input size=\"1\" type=\"tel\" name=\"form_fields[field_1b3c851]\" id=\"form-field-field_1b3c851\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" placeholder=\"912345678\" required=\"required\" pattern=\"[0-9()#&amp;+*-=.]+\" title=\"Only numbers and telephone characters (#, -, *, etc.) are accepted.\">\n\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-radio elementor-field-group elementor-column elementor-field-group-field_c93ad9b elementor-col-100 elementor-field-required elementor-mark-required\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-field_c93ad9b\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tSex assigned at birth\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t<div class=\"elementor-field-subgroup\"><span class=\"elementor-field-option\"><input type=\"radio\" value=\"0\" id=\"form-field-field_c93ad9b-0\" name=\"form_fields[field_c93ad9b]\" required=\"required\"> <label for=\"form-field-field_c93ad9b-0\">Not specified<\/label><\/span><span class=\"elementor-field-option\"><input type=\"radio\" value=\"1\" id=\"form-field-field_c93ad9b-1\" name=\"form_fields[field_c93ad9b]\" required=\"required\"> <label for=\"form-field-field_c93ad9b-1\">Male<\/label><\/span><span class=\"elementor-field-option\"><input type=\"radio\" value=\"2\" id=\"form-field-field_c93ad9b-2\" name=\"form_fields[field_c93ad9b]\" required=\"required\"> <label for=\"form-field-field_c93ad9b-2\">Female<\/label><\/span><\/div>\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-hidden elementor-field-group elementor-column elementor-field-group-reserva_fecha elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"hidden\" name=\"form_fields[reserva_fecha]\" id=\"form-field-reserva_fecha\" class=\"elementor-field elementor-size-sm  elementor-field-textual\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-hidden elementor-field-group elementor-column elementor-field-group-reserva_inicio elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"hidden\" name=\"form_fields[reserva_inicio]\" id=\"form-field-reserva_inicio\" class=\"elementor-field elementor-size-sm  elementor-field-textual\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-hidden elementor-field-group elementor-column elementor-field-group-reserva_fin elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"hidden\" name=\"form_fields[reserva_fin]\" id=\"form-field-reserva_fin\" class=\"elementor-field elementor-size-sm  elementor-field-textual\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-hidden elementor-field-group elementor-column elementor-field-group-reserva_comentario elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"hidden\" name=\"form_fields[reserva_comentario]\" id=\"form-field-reserva_comentario\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" value=\"Reserva Online\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-hidden elementor-field-group elementor-column elementor-field-group-reserva_profesional elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"hidden\" name=\"form_fields[reserva_profesional]\" id=\"form-field-reserva_profesional\" class=\"elementor-field elementor-size-sm  elementor-field-textual\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-hidden elementor-field-group elementor-column elementor-field-group-reserva_local elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"hidden\" name=\"form_fields[reserva_local]\" id=\"form-field-reserva_local\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" value=\"Spa &amp; Wellness Dr Roy Sothers\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-hidden elementor-field-group elementor-column elementor-field-group-reserva_servicio elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"hidden\" name=\"form_fields[reserva_servicio]\" id=\"form-field-reserva_servicio\" class=\"elementor-field elementor-size-sm  elementor-field-textual\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-hidden elementor-field-group elementor-column elementor-field-group-reserva_origen elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input size=\"1\" type=\"hidden\" name=\"form_fields[reserva_origen]\" id=\"form-field-reserva_origen\" class=\"elementor-field elementor-size-sm  elementor-field-textual\" value=\"Agenda Online\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-group elementor-column elementor-field-type-submit elementor-col-100 e-form__buttons\">\n\t\t\t\t\t<button class=\"elementor-button elementor-size-sm\" type=\"submit\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Send<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/button>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<input type=\"hidden\" name=\"trp-form-language\" value=\"en\"\/><\/form>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5a9bd78 elementor-widget elementor-widget-html\" data-id=\"5a9bd78\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\n    \/\/ Sistema de autocompletado de formulario de reserva\ndocument.addEventListener('DOMContentLoaded', function() {\n    console.log('\ud83c\udfaf SISTEMA DE AUTOCOMPLETADO DE FORMULARIO INICIADO');\n\n    \/\/ Variables globales para almacenar selecciones\n    let datosReserva = {\n        servicio: null,\n        categoria: null,\n        producto: null,\n        productosComplementarios: [],\n        fechaSeleccionada: null,\n        horaSeleccionada: null,\n        profesionalSeleccionado: null,\n        agendaSeleccionada: null,\n        sucursal: null\n    };\n\n    \/\/ Elementos del formulario - campos ocultos\n    const camposOcultos = {\n        fecha: document.getElementById('form-field-reserva_fecha'),\n        inicio: document.getElementById('form-field-reserva_inicio'),\n        fin: document.getElementById('form-field-reserva_fin'),\n        comentario: document.getElementById('form-field-reserva_comentario'),\n        profesional: document.getElementById('form-field-reserva_profesional'),\n        local: document.getElementById('form-field-reserva_local'),\n        servicio: document.getElementById('form-field-reserva_servicio'),\n        origen: document.getElementById('form-field-reserva_origen')\n    };\n\n    \/\/ Verificar que los campos existen\n    console.log('\ud83d\udd0d Campos ocultos encontrados:', {\n        fecha: !!camposOcultos.fecha,\n        inicio: !!camposOcultos.inicio,\n        fin: !!camposOcultos.fin,\n        comentario: !!camposOcultos.comentario,\n        profesional: !!camposOcultos.profesional,\n        local: !!camposOcultos.local,\n        servicio: !!camposOcultos.servicio,\n        origen: !!camposOcultos.origen\n    });\n\n    \/\/ Event listeners para capturar selecciones del usuario\n    \n    \/\/ 1. Servicio seleccionado (Day Spa, Med Spa)\n    document.addEventListener('servicioSeleccionado', function(e) {\n        console.log('\ud83d\udccb Servicio seleccionado:', e.detail.servicioData.name);\n        datosReserva.servicio = e.detail.servicioData;\n        actualizarCamposFormulario();\n    });\n\n    \/\/ 2. Categor\u00eda seleccionada (Masajes, Cosmetolog\u00eda, etc.)\n    document.addEventListener('categoriaSeleccionada', function(e) {\n        console.log('\ud83c\udff7\ufe0f Categor\u00eda seleccionada:', e.detail.categoriaData.name);\n        datosReserva.categoria = e.detail.categoriaData;\n        actualizarCamposFormulario();\n    });\n\n    \/\/ 3. Producto principal seleccionado\n    document.addEventListener('productoSeleccionado', function(e) {\n        console.log('\ud83c\udfaf Producto principal seleccionado:', e.detail.productoData.name);\n        datosReserva.producto = e.detail.productoData;\n        actualizarCamposFormulario();\n    });\n\n    \/\/ 4. Productos complementarios actualizados\n    document.addEventListener('complementosActualizados', function(e) {\n        console.log('\u2795 Complementos actualizados:', e.detail.productos.length, 'productos');\n        datosReserva.productosComplementarios = e.detail.productos || [];\n        actualizarCamposFormulario();\n    });\n\n    \/\/ 5. Horario seleccionado en el calendario\n    document.addEventListener('horarioSeleccionado', function(e) {\n        console.log('\u23f0 Horario seleccionado desde calendario:', e.detail);\n        datosReserva.fechaSeleccionada = e.detail.fecha;\n        datosReserva.horaSeleccionada = e.detail.hora;\n        datosReserva.profesionalSeleccionado = e.detail.profesional;\n        datosReserva.agendaSeleccionada = e.detail.agenda;\n        datosReserva.sucursal = e.detail.sucursal || 'Spa & Wellness Dr Roy Sothers';\n        actualizarCamposFormulario();\n    });\n\n    \/\/ 5b. Funci\u00f3n global para capturar selecci\u00f3n de horario desde cualquier sistema\n    window.actualizarHorarioReserva = function(datosHorario) {\n        console.log('\u23f0 Actualizando horario manualmente:', datosHorario);\n        \n        if (datosHorario.fecha) datosReserva.fechaSeleccionada = datosHorario.fecha;\n        if (datosHorario.hora) datosReserva.horaSeleccionada = datosHorario.hora;\n        if (datosHorario.profesional) datosReserva.profesionalSeleccionado = datosHorario.profesional;\n        if (datosHorario.agenda) datosReserva.agendaSeleccionada = datosHorario.agenda;\n        if (datosHorario.sucursal) datosReserva.sucursal = datosHorario.sucursal;\n        \n        actualizarCamposFormulario();\n        return datosReserva;\n    };\n\n    \/\/ 6. Event listeners para limpiezas\n    document.addEventListener('servicioLimpiado', limpiarDatosReserva);\n    document.addEventListener('categoriaLimpiada', limpiarDatosReserva);\n    document.addEventListener('productoLimpiado', limpiarDatosReserva);\n    document.addEventListener('limpiarTodasLasSelecciones', limpiarDatosReserva);\n\n    \/\/ Funci\u00f3n principal para actualizar los campos del formulario\n    function actualizarCamposFormulario() {\n        console.log('\ud83d\udd04 Actualizando campos del formulario...');\n        \n        try {\n            \/\/ 1. Fecha de la reserva (formato YYYY-MM-DD)\n            if (datosReserva.fechaSeleccionada && camposOcultos.fecha) {\n                camposOcultos.fecha.value = datosReserva.fechaSeleccionada;\n                console.log('\ud83d\udcc5 Fecha establecida:', datosReserva.fechaSeleccionada);\n            }\n\n            \/\/ 2. Hora de inicio (formato ISO completo)\n            if (datosReserva.horaSeleccionada && camposOcultos.inicio) {\n                camposOcultos.inicio.value = datosReserva.horaSeleccionada;\n                console.log('\u23f0 Hora inicio establecida:', datosReserva.horaSeleccionada);\n            }\n\n            \/\/ 3. Hora de fin (calculada seg\u00fan duraci\u00f3n del producto)\n            if (datosReserva.horaSeleccionada && datosReserva.producto && camposOcultos.fin) {\n                const horaFin = calcularHoraFin(datosReserva.horaSeleccionada, datosReserva.producto);\n                camposOcultos.fin.value = horaFin;\n                console.log('\u23f0 Hora fin calculada:', horaFin);\n            }\n\n            \/\/ 4. Comentario (incluir detalles de los productos)\n            if (camposOcultos.comentario) {\n                const comentario = generarComentarioReserva();\n                camposOcultos.comentario.value = comentario;\n                console.log('\ud83d\udcac Comentario generado:', comentario);\n            }\n\n            \/\/ 5. Profesional seleccionado\n            if (datosReserva.profesionalSeleccionado && camposOcultos.profesional) {\n                camposOcultos.profesional.value = datosReserva.profesionalSeleccionado;\n                console.log('\ud83d\udc64 Profesional establecido:', datosReserva.profesionalSeleccionado);\n            }\n\n            \/\/ 6. Local\/Sucursal\n            if (datosReserva.sucursal && camposOcultos.local) {\n                camposOcultos.local.value = datosReserva.sucursal;\n                console.log('\ud83c\udfe2 Local establecido:', datosReserva.sucursal);\n            } else if (camposOcultos.local && !camposOcultos.local.value) {\n                \/\/ Valor por defecto si no se especifica\n                camposOcultos.local.value = 'Spa & Wellness Dr Roy Sothers';\n            }\n\n            \/\/ 7. Servicio completo (producto principal + complementarios)\n            if (camposOcultos.servicio) {\n                const servicioCompleto = generarDescripcionServicio();\n                camposOcultos.servicio.value = servicioCompleto;\n                console.log('\ud83d\udecd\ufe0f Servicio establecido:', servicioCompleto);\n            }\n\n            \/\/ 8. Origen (siempre \"Agenda Online\")\n            if (camposOcultos.origen && !camposOcultos.origen.value) {\n                camposOcultos.origen.value = 'Agenda Online';\n            }\n\n            \/\/ Mostrar estado actual\n            mostrarEstadoFormulario();\n\n        } catch (error) {\n            console.error('\u274c Error actualizando campos del formulario:', error);\n        }\n    }\n\n    \/\/ Calcular hora de fin basada en la duraci\u00f3n del producto\n    function calcularHoraFin(horaInicio, producto) {\n        try {\n            const fechaInicio = new Date(horaInicio);\n            \n            \/\/ Extraer duraci\u00f3n del producto (en minutos)\n            let duracionMinutos = extraerDuracionEnMinutos(producto);\n            \n            \/\/ Agregar duraci\u00f3n de productos complementarios\n            if (datosReserva.productosComplementarios && datosReserva.productosComplementarios.length > 0) {\n                datosReserva.productosComplementarios.forEach(complemento => {\n                    duracionMinutos += extraerDuracionEnMinutos(complemento);\n                });\n            }\n            \n            \/\/ Calcular hora de fin\n            const fechaFin = new Date(fechaInicio.getTime() + (duracionMinutos * 60000));\n            \n            return fechaFin.toISOString();\n            \n        } catch (error) {\n            console.error('\u274c Error calculando hora de fin:', error);\n            \n            \/\/ Fallback: agregar 60 minutos por defecto\n            const fechaInicio = new Date(horaInicio);\n            const fechaFin = new Date(fechaInicio.getTime() + (60 * 60000));\n            return fechaFin.toISOString();\n        }\n    }\n\n    \/\/ Extraer duraci\u00f3n en minutos de un producto\n    function extraerDuracionEnMinutos(producto) {\n        let duracion = 60; \/\/ Default: 60 minutos\n        \n        try {\n            \/\/ Buscar en descripci\u00f3n corta\n            if (producto.short_description) {\n                const match = producto.short_description.match(\/(\\d+)\\s*(hora|horas|minuto|minutos|min)\/i);\n                if (match) {\n                    const numero = parseInt(match[1]);\n                    const unidad = match[2].toLowerCase();\n                    \n                    if (unidad.includes('hora')) {\n                        duracion = numero * 60;\n                    } else {\n                        duracion = numero;\n                    }\n                }\n            }\n            \n            \/\/ Buscar en descripci\u00f3n completa si no se encontr\u00f3 en la corta\n            if (duracion === 60 && producto.description) {\n                const match = producto.description.match(\/(\\d+)\\s*(hora|horas|minuto|minutos|min)\/i);\n                if (match) {\n                    const numero = parseInt(match[1]);\n                    const unidad = match[2].toLowerCase();\n                    \n                    if (unidad.includes('hora')) {\n                        duracion = numero * 60;\n                    } else {\n                        duracion = numero;\n                    }\n                }\n            }\n            \n            \/\/ Buscar en meta_data\n            if (duracion === 60 && producto.meta_data && Array.isArray(producto.meta_data)) {\n                const metaDuracion = producto.meta_data.find(meta => \n                    meta.key.includes('duracion') || \n                    meta.key.includes('duration') ||\n                    meta.key.includes('tiempo')\n                );\n                \n                if (metaDuracion && metaDuracion.value) {\n                    const numero = parseInt(metaDuracion.value);\n                    if (!isNaN(numero)) {\n                        duracion = numero;\n                    }\n                }\n            }\n            \n        } catch (error) {\n            console.error('\u274c Error extrayendo duraci\u00f3n:', error);\n        }\n        \n        console.log(`\u23f1\ufe0f Duraci\u00f3n extra\u00edda para ${producto.name}: ${duracion} minutos`);\n        return duracion;\n    }\n\n    \/\/ Generar comentario detallado de la reserva\n    function generarComentarioReserva() {\n        let comentario = 'Reserva Online';\n        \n        try {\n            const detalles = [];\n            \n            \/\/ Producto principal\n            if (datosReserva.producto) {\n                detalles.push(`Tratamiento Principal: ${datosReserva.producto.name}`);\n                \n                \/\/ Precio del producto principal\n                const precio = datosReserva.producto.sale_price || \n                             datosReserva.producto.regular_price || \n                             datosReserva.producto.price;\n                if (precio) {\n                    detalles.push(`Precio: ${formatPrice(precio)}`);\n                }\n            }\n            \n            \/\/ Productos complementarios\n            if (datosReserva.productosComplementarios && datosReserva.productosComplementarios.length > 0) {\n                detalles.push('--- Tratamientos Complementarios ---');\n                \n                datosReserva.productosComplementarios.forEach((complemento, index) => {\n                    detalles.push(`${index + 1}. ${complemento.name}`);\n                    \n                    const precioComplemento = complemento.sale_price || \n                                            complemento.regular_price || \n                                            complemento.price;\n                    if (precioComplemento) {\n                        detalles.push(`   Precio: ${formatPrice(precioComplemento)}`);\n                    }\n                });\n            }\n            \n            \/\/ Categor\u00eda y servicio\n            if (datosReserva.categoria) {\n                detalles.push(`Categor\u00eda: ${datosReserva.categoria.name}`);\n            }\n            \n            if (datosReserva.servicio) {\n                detalles.push(`Tipo de Servicio: ${datosReserva.servicio.name}`);\n            }\n            \n            \/\/ Calcular total\n            let total = 0;\n            if (datosReserva.producto) {\n                const precioP = parseFloat(datosReserva.producto.sale_price || \n                                         datosReserva.producto.regular_price || \n                                         datosReserva.producto.price || '0');\n                total += precioP;\n            }\n            \n            if (datosReserva.productosComplementarios) {\n                datosReserva.productosComplementarios.forEach(comp => {\n                    const precioC = parseFloat(comp.sale_price || \n                                             comp.regular_price || \n                                             comp.price || '0');\n                    total += precioC;\n                });\n            }\n            \n            if (total > 0) {\n                detalles.push(`--- TOTAL: ${formatPrice(total)} ---`);\n            }\n            \n            if (detalles.length > 0) {\n                comentario = 'Reserva Online - ' + detalles.join(' | ');\n            }\n            \n        } catch (error) {\n            console.error('\u274c Error generando comentario:', error);\n        }\n        \n        return comentario;\n    }\n\n    \/\/ Generar descripci\u00f3n completa del servicio\n    function generarDescripcionServicio() {\n        const servicios = [];\n        \n        if (datosReserva.producto) {\n            servicios.push(datosReserva.producto.name);\n        }\n        \n        if (datosReserva.productosComplementarios && datosReserva.productosComplementarios.length > 0) {\n            datosReserva.productosComplementarios.forEach(complemento => {\n                servicios.push(complemento.name);\n            });\n        }\n        \n        return servicios.length > 0 ? servicios.join(' + ') : '';\n    }\n\n    \/\/ Formatear precio\n    function formatPrice(price) {\n        return new Intl.NumberFormat('es-CL', {\n            style: 'currency',\n            currency: 'CLP',\n            minimumFractionDigits: 0,\n            maximumFractionDigits: 0\n        }).format(parseFloat(price));\n    }\n\n    \/\/ Limpiar todos los datos de reserva\n    function limpiarDatosReserva() {\n        \n        datosReserva = {\n            servicio: null,\n            categoria: null,\n            producto: null,\n            productosComplementarios: [],\n            fechaSeleccionada: null,\n            horaSeleccionada: null,\n            profesionalSeleccionado: null,\n            agendaSeleccionada: null,\n            sucursal: null\n        };\n        \n        \/\/ Limpiar campos del formulario (excepto los que tienen valores por defecto)\n        Object.keys(camposOcultos).forEach(key => {\n            if (camposOcultos[key] && key !== 'local' && key !== 'origen') {\n                camposOcultos[key].value = '';\n            }\n        });\n        \n        console.log('\u2705 Datos de reserva limpiados');\n    }\n\n    \/\/ Mostrar estado actual del formulario (para debugging)\n    function mostrarEstadoFormulario() {\n        console.log('\ud83d\udccb ESTADO ACTUAL DEL FORMULARIO:');\n        console.log('  \ud83c\udfaf Producto principal:', datosReserva.producto?.name || 'No seleccionado');\n        console.log('  \u2795 Complementarios:', datosReserva.productosComplementarios.length, 'productos');\n        console.log('  \ud83d\udcc5 Fecha:', datosReserva.fechaSeleccionada || 'No seleccionada');\n        console.log('  \u23f0 Hora:', datosReserva.horaSeleccionada || 'No seleccionada');\n        console.log('  \ud83d\udc64 Profesional:', datosReserva.profesionalSeleccionado || 'No seleccionado');\n        \n        console.log('\ud83d\udcdd VALORES EN CAMPOS OCULTOS:');\n        Object.keys(camposOcultos).forEach(key => {\n            if (camposOcultos[key]) {\n                console.log(`  ${key}:`, camposOcultos[key].value || '(vac\u00edo)');\n            }\n        });\n    }\n\n    \/\/ Funci\u00f3n para validar que todos los campos necesarios est\u00e9n completos\n    function validarDatosCompletos() {\n        const errores = [];\n        \n        if (!datosReserva.producto) {\n            errores.push('Debe seleccionar un producto principal');\n        }\n        \n        if (!datosReserva.fechaSeleccionada) {\n            errores.push('Debe seleccionar una fecha');\n        }\n        \n        if (!datosReserva.horaSeleccionada) {\n            errores.push('Debe seleccionar un horario');\n        }\n        \n        if (!datosReserva.profesionalSeleccionado) {\n            errores.push('Debe seleccionar un profesional');\n        }\n        \n        return {\n            valido: errores.length === 0,\n            errores: errores\n        };\n    }\n\n    \/\/ Event listener para validar antes del env\u00edo del formulario\n    const formulario = document.querySelector('.elementor-form');\n    if (formulario) {\n        formulario.addEventListener('submit', function(e) {\n            console.log('\ud83d\udce4 Intentando enviar formulario...');\n            \n            const validacion = validarDatosCompletos();\n            \n            if (!validacion.valido) {\n                e.preventDefault();\n                console.error('\u274c Formulario incompleto:', validacion.errores);\n                \n                alert('Por favor complete su reserva:\\n\\n' + validacion.errores.join('\\n'));\n                return false;\n            }\n            \n            console.log('\u2705 Formulario v\u00e1lido, enviando...');\n            mostrarEstadoFormulario();\n        });\n    }\n\n    \/\/ Funci\u00f3n global para recuperar datos desde localStorage al cargar la p\u00e1gina\n    function recuperarDatosGuardados() {\n        console.log('\ud83d\udd04 Recuperando datos guardados...');\n        \n        try {\n            \/\/ Recuperar producto principal\n            const productoGuardado = localStorage.getItem('selectedProducto');\n            if (productoGuardado) {\n                const parsed = JSON.parse(productoGuardado);\n                datosReserva.producto = parsed.data;\n            }\n            \n            \/\/ Recuperar categor\u00eda\n            const categoriaGuardada = localStorage.getItem('selectedCategoria');\n            if (categoriaGuardada) {\n                const parsed = JSON.parse(categoriaGuardada);\n                datosReserva.categoria = parsed.data;\n            }\n            \n            \/\/ Recuperar servicio\n            const servicioGuardado = localStorage.getItem('selectedServicio');\n            if (servicioGuardado) {\n                const parsed = JSON.parse(servicioGuardado);\n                datosReserva.servicio = parsed.data;\n            }\n            \n            \/\/ Recuperar \u00faltima reserva si existe\n            const ultimaReserva = localStorage.getItem('ultimaReserva');\n            if (ultimaReserva) {\n                const parsed = JSON.parse(ultimaReserva);\n                if (parsed.fecha && parsed.hora && parsed.profesional) {\n                    datosReserva.fechaSeleccionada = parsed.fecha;\n                    datosReserva.horaSeleccionada = parsed.hora;\n                    datosReserva.profesionalSeleccionado = parsed.profesional;\n                    datosReserva.agendaSeleccionada = parsed.agenda;\n                }\n            }\n            \n            \/\/ Actualizar formulario con datos recuperados\n            if (datosReserva.producto || datosReserva.fechaSeleccionada) {\n                actualizarCamposFormulario();\n            }\n            \n        } catch (error) {\n            console.error('\u274c Error recuperando datos guardados:', error);\n        }\n    }\n\n    \/\/ Ejecutar recuperaci\u00f3n de datos al inicializar\n    recuperarDatosGuardados();\n\n    \/\/ Funci\u00f3n global para debugging (disponible en consola)\n    window.mostrarDatosReserva = function() {\n        console.log('\ud83d\udd0d DATOS ACTUALES DE RESERVA:', datosReserva);\n        mostrarEstadoFormulario();\n        return datosReserva;\n    };\n\n    \/\/ Funci\u00f3n global para actualizar datos manualmente (\u00fatil para testing)\n    window.actualizarReservaManual = function(datos) {\n        console.log('\ud83d\udd27 Actualizando datos manualmente:', datos);\n        \n        if (datos.fecha) datosReserva.fechaSeleccionada = datos.fecha;\n        if (datos.hora) datosReserva.horaSeleccionada = datos.hora;\n        if (datos.profesional) datosReserva.profesionalSeleccionado = datos.profesional;\n        if (datos.agenda) datosReserva.agendaSeleccionada = datos.agenda;\n        if (datos.sucursal) datosReserva.sucursal = datos.sucursal;\n        \n        actualizarCamposFormulario();\n        mostrarEstadoFormulario();\n        return datosReserva;\n    };\n\n    console.log('\u2705 Sistema de autocompletado de formulario inicializado');\n    console.log('\ud83d\udca1 Usa mostrarDatosReserva() en consola para ver el estado actual');\n});\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1c817b7 elementor-widget elementor-widget-html\" data-id=\"1c817b7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    console.log('\ud83d\ude80 SISTEMA DE ENV\u00cdO A RESERVO INICIADO');\r\n\r\n    \/\/ =========================\r\n    \/\/ HELPERS GLOBALES (scope)\r\n    \/\/ =========================\r\n\r\n    \/\/ Lee UUIDs de complementos desde localStorage\r\n    function obtenerUuidsComplementos() {\r\n        try {\r\n            const complementos = localStorage.getItem('selectedComplementos');\r\n            if (complementos) {\r\n                const arr = JSON.parse(complementos) || [];\r\n                const uuids = [];\r\n                arr.forEach(c => {\r\n                    const meta = c?.data?.meta_data || [];\r\n                    const m = meta.find(x =>\r\n                        x.key === 'reservo_uuid' ||\r\n                        x.key === 'field_689b4c787beba' ||\r\n                        x.key === '_reservo_uuid'\r\n                    );\r\n                    if (m?.value) uuids.push(String(m.value));\r\n                });\r\n                console.log('\ud83d\udd0d UUIDs de complementos encontrados:', uuids);\r\n                return uuids;\r\n            }\r\n        } catch (e) {\r\n            console.error('\u274c Error obteniendo UUIDs de complementos:', e);\r\n        }\r\n        return [];\r\n    }\r\n\r\n    \/\/ Une principal + complementos \u2192 array plano filtrado y sin duplicados\r\n    function construirTratamientosUuid(uuidPrincipal) {\r\n        const comp = obtenerUuidsComplementos(); \/\/ retorna [] si no hay\r\n        const base = [];\r\n\r\n        if (uuidPrincipal && typeof uuidPrincipal === 'string' && uuidPrincipal.trim()) {\r\n            base.push(uuidPrincipal.trim());\r\n        }\r\n        if (Array.isArray(comp)) {\r\n            for (const v of comp) {\r\n                if (typeof v === 'string' && v.trim()) base.push(v.trim());\r\n            }\r\n        }\r\n        return Array.from(new Set(base));\r\n    }\r\n\r\n    \/\/ =========================\r\n    \/\/ FORM \/ ESTADO\r\n    \/\/ =========================\r\n    const formulario = document.querySelector('.elementor-form');\r\n    const botonEnvio = formulario?.querySelector('button[type=\"submit\"]');\r\n\r\n    if (!formulario) {\r\n        console.error('\u274c No se encontr\u00f3 el formulario');\r\n        return;\r\n    }\r\n\r\n    let enviandoFormulario = false;\r\n    let datosReservaActuales = null;\r\n\r\n    console.log('\u2705 Formulario encontrado:', formulario);\r\n\r\n    \/\/ Interceptar env\u00edo nativo del form\r\n    formulario.addEventListener('submit', async function(e) {\r\n        e.preventDefault();\r\n        e.stopPropagation();\r\n\r\n        if (enviandoFormulario) {\r\n            console.log('\u23f3 Ya se est\u00e1 procesando una reserva...');\r\n            return;\r\n        }\r\n\r\n        console.log('\ud83d\udce4 Interceptando env\u00edo del formulario...');\r\n        try {\r\n            enviandoFormulario = true;\r\n            await procesarEnvioReserva();\r\n        } catch (error) {\r\n            console.error('\u274c Error procesando reserva:', error);\r\n            mostrarError('Error al procesar la reserva. Por favor intenta de nuevo.');\r\n        } finally {\r\n            enviandoFormulario = false;\r\n        }\r\n    });\r\n\r\n    \/\/ =========================\r\n    \/\/ ENV\u00cdO A API\r\n    \/\/ =========================\r\n    async function procesarEnvioReserva() {\r\n        \/\/ 1) Estado bot\u00f3n\r\n        actualizarEstadoBoton('Procesando reserva...', true);\r\n\r\n        \/\/ 2) Datos del formulario\r\n        const datosFormulario = recopilarDatosFormulario();\r\n\r\n        \/\/ 3) Datos de la reserva (versi\u00f3n mejorada)\r\n        const datosReserva = recopilarDatosReservaMejorada();\r\n\r\n        console.log('\ud83d\udccb Datos del formulario:', datosFormulario);\r\n        console.log('\ud83d\udcc5 Datos de la reserva:', datosReserva);\r\n\r\n        \/\/ 4) Validaci\u00f3n (con normalizaci\u00f3n previa)\r\n        const validacion = validarDatosCompletos(datosFormulario, datosReserva);\r\n        if (!validacion.valido) {\r\n            mostrarError('Datos incompletos:\\n\\n' + validacion.errores.join('\\n'));\r\n            actualizarEstadoBoton('Enviar', false);\r\n            return;\r\n        }\r\n        \r\n\/\/ Obtener lista de tratamientos normalizada UNA SOLA VEZ\r\nconst uuidsTratamientos = Array.isArray(datosReserva.tratamientos_uuid)\r\n  ? datosReserva.tratamientos_uuid\r\n  : construirTratamientosUuid(datosReserva.tratamiento_uuid);\r\n\r\n\/\/ Validar que tengamos al menos un UUID\r\nif (uuidsTratamientos.length === 0) {\r\n    mostrarError('Debe seleccionar al menos un tratamiento');\r\n    actualizarEstadoBoton('Enviar', false);\r\n    return;\r\n}\r\n\r\n\r\n\/\/ Enviar TODOS los tratamientos como array\r\nconst payload = {\r\n  cliente: {\r\n    rut: datosFormulario.rut,\r\n    nombre: datosFormulario.nombre,\r\n    apellido_paterno: datosFormulario.apellido_paterno,\r\n    apellido_materno: datosFormulario.apellido_materno,\r\n    email: datosFormulario.email,\r\n    telefono: datosFormulario.telefono || '',\r\n    sexo: datosFormulario.sexo || 'No especifica'\r\n  },\r\n  reserva: {\r\n    fecha: datosReserva.fecha,\r\n    hora: datosReserva.hora,\r\n    agenda_uuid: datosReserva.agenda_uuid,\r\n    tratamientos_uuid: uuidsTratamientos, \/\/ Array con todos los UUIDs\r\n    comentario: datosReserva.comentario || 'Reserva Online'\r\n  }\r\n};\r\n\r\nconsole.log('\ud83d\udce6 Tratamientos a enviar (total ' + uuidsTratamientos.length + '):', payload.reserva.tratamientos_uuid);\r\nconsole.log('  \ud83c\udfaf Principal:', uuidsTratamientos[0]);\r\n\r\n\r\n\r\nif (uuidsTratamientos.length > 1) {\r\n    console.log('  \u2795 Complementarios:', uuidsTratamientos.slice(1));\r\n}\r\n        \/\/ 6) Llamada endpoint\r\n        try {\r\n            actualizarEstadoBoton('Creando reserva...', true);\r\n\r\nconst response = await fetch('\/wp-json\/sothers\/v1\/crear-reserva', {\r\n    method: 'POST',\r\n    headers: {\r\n        'Content-Type': 'application\/json'\r\n\r\n    },\r\n    body: JSON.stringify(payload)\r\n});\r\n\r\n            const resultado = await response.json();\r\n            console.log('\ud83d\udce5 Respuesta del servidor:', resultado);\r\n\r\n            if (!response.ok || !resultado.success) {\r\n                throw new Error(resultado.message || 'Error del servidor');\r\n            }\r\n\r\n            \/\/ 7) OK\r\n            await procesarRespuestaExitosa(resultado.data, datosFormulario, datosReserva);\r\n\r\n        } catch (error) {\r\n            console.error('\u274c Error en llamada al servidor:', error);\r\n            let mensaje = 'Error al crear la reserva. ';\r\n            if (error.message.includes('fetch')) {\r\n                mensaje += 'Verifica tu conexi\u00f3n a internet.';\r\n            } else {\r\n                mensaje += error.message;\r\n            }\r\n            mostrarError(mensaje);\r\n            actualizarEstadoBoton('Enviar', false);\r\n        }\r\n    }\r\n\r\n    \/\/ =========================\r\n    \/\/ RECOLECCI\u00d3N DE DATOS\r\n    \/\/ =========================\r\n    function recopilarDatosFormulario() {\r\n        const formData = new FormData(formulario);\r\n        return {\r\n            rut: formData.get('form_fields[name]') || '',\r\n            nombre: formData.get('form_fields[field_49f8b85]') || '',\r\n            apellido_paterno: formData.get('form_fields[field_99b781e]') || '',\r\n            apellido_materno: formData.get('form_fields[field_0b35636]') || '',\r\n            email: formData.get('form_fields[email]') || '',\r\n            telefono: formData.get('form_fields[field_1b3c851]') || '',\r\n            sexo: formData.get('form_fields[field_c93ad9b]') || 'No especifica'\r\n        };\r\n    }\r\n\r\n    \/\/ \u26a0\ufe0f Versi\u00f3n legada (se mantiene para debugging), CORREGIDA\r\n    function recopilarDatosReserva() {\r\n        const campos = {\r\n            fecha: document.getElementById('form-field-reserva_fecha')?.value || '',\r\n            hora: document.getElementById('form-field-reserva_inicio')?.value || '',\r\n            comentario: document.getElementById('form-field-reserva_comentario')?.value || '',\r\n            profesional: document.getElementById('form-field-reserva_profesional')?.value || '',\r\n            servicio: document.getElementById('form-field-reserva_servicio')?.value || ''\r\n        };\r\n\r\n        let agendaUuid = '';\r\n        let tratamientoUuid = '';\r\n\r\n        try {\r\n            if (window.reservaSeleccionada?.agenda) {\r\n                agendaUuid = window.reservaSeleccionada.agenda;\r\n            }\r\n\r\n            const productoGuardado = localStorage.getItem('selectedProducto');\r\n            if (productoGuardado) {\r\n                const producto = JSON.parse(productoGuardado);\r\n                const metaUuid = producto?.data?.meta_data?.find(meta =>\r\n                    meta.key === 'reservo_uuid' ||\r\n                    meta.key === 'field_689b4c787beba' ||\r\n                    meta.key === '_reservo_uuid'\r\n                );\r\n                if (metaUuid?.value) tratamientoUuid = metaUuid.value;\r\n            }\r\n\r\n            if (window.datosReserva) {\r\n                agendaUuid = agendaUuid || window.datosReserva.agendaSeleccionada || '';\r\n                const metaUuid2 = window.datosReserva?.producto?.meta_data?.find(meta =>\r\n                    meta.key === 'reservo_uuid' ||\r\n                    meta.key === 'field_689b4c787beba' ||\r\n                    meta.key === '_reservo_uuid'\r\n                );\r\n                if (metaUuid2?.value) tratamientoUuid = metaUuid2.value;\r\n            }\r\n        } catch (error) {\r\n            console.error('\u274c Error obteniendo UUIDs:', error);\r\n        }\r\n\r\n        return {\r\n            fecha: campos.fecha,\r\n            hora: campos.hora,\r\n            agenda_uuid: agendaUuid,\r\n            \/\/ \u2705 corregido: siempre usamos el helper y la clave plural\r\n            tratamientos_uuid: construirTratamientosUuid(tratamientoUuid),\r\n            comentario: campos.comentario,\r\n            profesional: campos.profesional,\r\n            servicio: campos.servicio\r\n        };\r\n    }\r\n\r\n    \/\/ Versi\u00f3n MEJORADA y normalizada (la que usa el env\u00edo)\r\nfunction recopilarDatosReservaMejorada() {\r\n    console.log('\ud83d\udd04 Recopilando datos de reserva...');\r\n\r\n    \/\/ Prioridad 1: Integraci\u00f3n simplificada\r\n    if (window.obtenerDatosReservaParaFormulario) {\r\n        const datosIntegracion = window.obtenerDatosReservaParaFormulario();\r\n\r\n        \/\/ Normalizamos SIEMPRE, sin importar si la validaci\u00f3n es v\u00e1lida\r\n        const normalizado = {\r\n            ...datosIntegracion,\r\n            tratamientos_uuid: Array.isArray(datosIntegracion.tratamientos_uuid)\r\n                ? datosIntegracion.tratamientos_uuid\r\n                : construirTratamientosUuid(datosIntegracion.tratamiento_uuid)\r\n        };\r\n        return normalizado;\r\n    }\r\n\r\n    \/\/ Prioridad 2: datosReservaCompleta\r\n    if (window.datosReservaCompleta) {\r\n        console.log('\ud83d\udd04 Usando datosReservaCompleta directamente...');\r\n        return {\r\n            fecha: window.datosReservaCompleta.fecha,\r\n            hora: window.datosReservaCompleta.hora,\r\n            agenda_uuid: window.datosReservaCompleta.agenda,\r\n            tratamientos_uuid: construirTratamientosUuid(\r\n                window.datosReservaCompleta.tratamiento_uuid\r\n            ),\r\n            profesional: window.datosReservaCompleta.profesional,\r\n            comentario: 'Reserva Online',\r\n            servicio: window.datosReservaCompleta.producto?.name || ''\r\n        };\r\n    }\r\n\r\n    \/\/ Prioridad 3: Fallback a campos del formulario\r\n    console.log('\ud83d\udd04 Fallback a campos del formulario...');\r\n    const campos = {\r\n        fecha: document.getElementById('form-field-reserva_fecha')?.value || '',\r\n        hora: document.getElementById('form-field-reserva_inicio')?.value || '',\r\n        comentario: document.getElementById('form-field-reserva_comentario')?.value || 'Reserva Online',\r\n        profesional: document.getElementById('form-field-reserva_profesional')?.value || '',\r\n        servicio: document.getElementById('form-field-reserva_servicio')?.value || ''\r\n    };\r\n\r\n    const agendaUuid = document.getElementById('form-field-reserva_agenda')?.value || '';\r\n    const tratamientoUuid = document.getElementById('form-field-reserva_tratamiento')?.value || '';\r\n\r\n    return {\r\n        fecha: campos.fecha,\r\n        hora: campos.hora,\r\n        agenda_uuid: agendaUuid,\r\n        tratamientos_uuid: construirTratamientosUuid(tratamientoUuid),\r\n        comentario: campos.comentario,\r\n        profesional: campos.profesional,\r\n        servicio: campos.servicio\r\n    };\r\n}\r\n\r\n    \/\/ Hacemos que cualquier llamada a la legada use la mejorada por defecto\r\n    recopilarDatosReserva = recopilarDatosReservaMejorada;\r\n\r\n    \/\/ =========================\r\n    \/\/ VALIDACI\u00d3N\r\n    \/\/ =========================\r\nfunction validarDatosCompletos(datosFormulario, datosReserva) {\r\n    const errores = [];\r\n\r\n    \/\/ Cliente\r\n    if (!datosFormulario.rut || !datosFormulario.rut.trim()) errores.push('RUT es requerido');\r\n    if (!datosFormulario.nombre || !datosFormulario.nombre.trim()) errores.push('Nombre es requerido');\r\n    if (!datosFormulario.apellido_paterno || !datosFormulario.apellido_paterno.trim()) errores.push('Apellido paterno es requerido');\r\n    if (!datosFormulario.email || !datosFormulario.email.trim()) errores.push('Email es requerido');\r\n\r\n    const emailRegex = \/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/;\r\n    if (datosFormulario.email && !emailRegex.test(datosFormulario.email)) {\r\n        errores.push('Email tiene formato inv\u00e1lido');\r\n    }\r\n\r\n    \/\/ Normalizar tratamientos_uuid ANTES de validar\r\n    let lista = [];\r\n    if (Array.isArray(datosReserva.tratamientos_uuid)) {\r\n        lista = datosReserva.tratamientos_uuid;\r\n    } else if (Array.isArray(datosReserva.tratamiento_uuid)) {\r\n        lista = datosReserva.tratamiento_uuid;\r\n    } else {\r\n        lista = construirTratamientosUuid(datosReserva.tratamiento_uuid);\r\n    }\r\n    datosReserva.tratamientos_uuid = lista;\r\n\r\n    \/\/ Validar que exista al menos 1 uuid v\u00e1lido\r\n    const validos = (lista || []).filter(v => typeof v === 'string' && v.trim());\r\n    if (validos.length === 0) {\r\n        errores.push('Debe seleccionar al menos un tratamiento');\r\n    }\r\n\r\n    \/\/ Reserva\r\n    if (!datosReserva.fecha || !datosReserva.fecha.trim()) errores.push('Debe seleccionar una fecha');\r\n    if (!datosReserva.hora || !datosReserva.hora.trim()) errores.push('Debe seleccionar un horario');\r\n    if (!datosReserva.agenda_uuid || !datosReserva.agenda_uuid.trim()) errores.push('Debe seleccionar un profesional');\r\n\r\n    return { valido: errores.length === 0, errores };\r\n}\r\n\r\n    \/\/ =========================\r\n    \/\/ UI \/ UTILIDADES\r\n    \/\/ =========================\r\n    async function procesarRespuestaExitosa(data, datosFormulario, datosReserva) {\r\n        console.log('\ud83c\udf89 Reserva creada exitosamente:', data);\r\n\r\n        const reservaCompleta = {\r\n            ...data,\r\n            cliente: datosFormulario,\r\n            reserva_datos: datosReserva,\r\n            fecha_creacion: new Date().toISOString()\r\n        };\r\n        localStorage.setItem('ultimaReservaCreadaCompleta', JSON.stringify(reservaCompleta));\r\n\r\n        actualizarEstadoBoton('\u2705 Reserva creada - Redirigiendo...', true);\r\n        mostrarConfirmacionReserva(data);\r\n\r\n        await new Promise(resolve => setTimeout(resolve, 2000));\r\n\r\n        if (data.link_pago) {\r\n            console.log('\ud83d\udd04 Redirigiendo a pago:', data.link_pago);\r\n            window.location.href = data.link_pago;\r\n        } else {\r\n            console.error('\u274c No se recibi\u00f3 link de pago');\r\n            mostrarError('Reserva creada pero no se encontr\u00f3 el link de pago. Contacta con soporte.');\r\n            actualizarEstadoBoton('Enviar', false);\r\n        }\r\n    }\r\n\r\n    function mostrarConfirmacionReserva(data) {\r\n        const modal = document.createElement('div');\r\n        modal.style.cssText = `\r\n            position: fixed; top: 0; left: 0; width: 100%; height: 100%;\r\n            background: rgba(0,0,0,0.8); display: flex; align-items: center; justify-content: center;\r\n            z-index: 10000; font-family: 'Josefin Sans', sans-serif;\r\n        `;\r\n        const contenido = document.createElement('div');\r\n        contenido.style.cssText = `\r\n            background: white; border-radius: 12px; padding: 40px; max-width: 500px; margin: 20px;\r\n            text-align: center; box-shadow: 0 10px 40px rgba(0,0,0,0.3);\r\n        `;\r\n\r\n        const cita = data.citas && data.citas[0];\r\n        const fechaFormateada = cita ? new Date(cita.inicio).toLocaleDateString('es-ES', {\r\n            weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'\r\n        }) : '';\r\n        const horaFormateada = cita ? new Date(cita.inicio).toLocaleTimeString('es-ES', {\r\n            hour: '2-digit', minute: '2-digit'\r\n        }) : '';\r\n\r\n        contenido.innerHTML = `\r\n            <div style=\"font-size: 64px; margin-bottom: 20px;\">\ud83c\udf89<\/div>\r\n            <h2 style=\"color: #31989E; margin: 0 0 20px 0;\">\u00a1Reserva Creada!<\/h2>\r\n            <p style=\"color: #666; margin-bottom: 20px;\">Tu cita ha sido agendada exitosamente.<\/p>\r\n            <div style=\"background: #f8f9fa; border-radius: 8px; padding: 20px; margin: 20px 0; text-align: left;\">\r\n                <h3 style=\"color: #31989E; margin: 0 0 15px 0; text-align: center;\">Detalles de tu reserva<\/h3>\r\n                ${cita ? `\r\n                    <p><strong>Fecha:<\/strong> ${fechaFormateada}<\/p>\r\n                    <p><strong>Hora:<\/strong> ${horaFormateada}<\/p>\r\n                    <p><strong>Profesional:<\/strong> ${cita.profesional?.nombre || 'No especificado'}<\/p>\r\n                    <p><strong>Tratamiento:<\/strong> ${cita.tratamientos?.[0]?.nombre || 'No especificado'}<\/p>\r\n                ` : ''}\r\n                ${data.valor_pago ? `<p><strong>Valor:<\/strong> $${data.valor_pago}<\/p>` : ''}\r\n                ${data.countdown ? `<p style=\"color: #dc2626;\"><strong>Tiempo l\u00edmite:<\/strong> ${data.countdown}<\/p>` : ''}\r\n            <\/div>\r\n            <p style=\"color: #666; font-size: 14px; margin-bottom: 20px;\">\r\n                Ser\u00e1s redirigido al sistema de pago en unos segundos...\r\n            <\/p>\r\n            <div class=\"loading-dots\" style=\"display: flex; justify-content: center; gap: 4px;\">\r\n                <div style=\"width: 8px; height: 8px; border-radius: 50%; background: #31989E; animation: bounce 1.4s ease-in-out infinite both;\"><\/div>\r\n                <div style=\"width: 8px; height: 8px; border-radius: 50%; background: #31989E; animation: bounce 1.4s ease-in-out infinite both; animation-delay: -0.32s;\"><\/div>\r\n                <div style=\"width: 8px; height: 8px; border-radius: 50%; background: #31989E; animation: bounce 1.4s ease-in-out infinite both; animation-delay: -0.16s;\"><\/div>\r\n            <\/div>\r\n        `;\r\n\r\n        const style = document.createElement('style');\r\n        style.textContent = `\r\n            @keyframes bounce { 0%,80%,100%{transform:scale(0);} 40%{transform:scale(1);} }\r\n        `;\r\n        document.head.appendChild(style);\r\n\r\n        modal.appendChild(contenido);\r\n        document.body.appendChild(modal);\r\n\r\n        setTimeout(() => { modal.parentNode && modal.parentNode.removeChild(modal); }, 5000);\r\n    }\r\n\r\n    function actualizarEstadoBoton(texto, deshabilitado) {\r\n        if (botonEnvio) {\r\n            const spanTexto = botonEnvio.querySelector('.elementor-button-text');\r\n            if (spanTexto) spanTexto.textContent = texto;\r\n\r\n            botonEnvio.disabled = deshabilitado;\r\n            botonEnvio.style.opacity = deshabilitado ? '0.6' : '1';\r\n            botonEnvio.style.cursor = deshabilitado ? 'not-allowed' : 'pointer';\r\n            botonEnvio.style.pointerEvents = deshabilitado ? 'none' : 'auto';\r\n        }\r\n    }\r\n\r\n    function mostrarError(mensaje) {\r\n        console.error('\u274c Error:', mensaje);\r\n        const notificacion = document.createElement('div');\r\n        notificacion.style.cssText = `\r\n            position: fixed; top: 20px; right: 20px; background: #dc2626; color: white;\r\n            padding: 20px; border-radius: 8px; box-shadow: 0 4px 15px rgba(220, 38, 38, 0.3);\r\n            z-index: 10001; max-width: 400px; font-family: 'Josefin Sans', sans-serif; font-size: 14px; line-height: 1.4;\r\n        `;\r\n        notificacion.innerHTML = `\r\n            <div style=\"display:flex; align-items:flex-start; gap:10px;\">\r\n                <div style=\"font-size:20px;\">\u26a0\ufe0f<\/div>\r\n                <div><strong>Error al procesar reserva<\/strong><br>${mensaje}<\/div>\r\n                <button onclick=\"this.parentElement.parentElement.remove()\" \r\n                        style=\"background:none; border:none; color:white; font-size:18px; cursor:pointer; margin-left:auto;\">\u00d7<\/button>\r\n            <\/div>\r\n        `;\r\n        document.body.appendChild(notificacion);\r\n        setTimeout(() => { notificacion.parentNode && notificacion.parentNode.removeChild(notificacion); }, 8000);\r\n        alert(mensaje);\r\n    }\r\n\r\n    function obtenerNonce() {\r\n        return '';\r\n    }\r\n\r\n    \/\/ =========================\r\n    \/\/ INTEGRACIONES \/ EVENTOS\r\n    \/\/ =========================\r\n    window.testEnvioReserva = function() {\r\n        console.log('\ud83e\uddea Iniciando test de env\u00edo de reserva...');\r\n        procesarEnvioReserva();\r\n    };\r\n\r\n    window.obtenerDatosActuales = function() {\r\n        const datosFormulario = recopilarDatosFormulario();\r\n        \/\/ \ud83d\udc49 usar SIEMPRE la versi\u00f3n mejorada\r\n        const datosReserva = recopilarDatosReservaMejorada();\r\n\r\n        console.log('\ud83d\udccb Datos actuales del formulario:', datosFormulario);\r\n        console.log('\ud83d\udcc5 Datos actuales de reserva:', datosReserva);\r\n\r\n        const validacion = validarDatosCompletos(datosFormulario, datosReserva);\r\n        console.log('\u2705 Validaci\u00f3n:', validacion);\r\n\r\n        return { formulario: datosFormulario, reserva: datosReserva, validacion };\r\n    };\r\n\r\n    document.addEventListener('reservaConfirmada', function(e) {\r\n        console.log('\ud83d\udcc5 Reserva confirmada desde calendario:', e.detail);\r\n        datosReservaActuales = e.detail;\r\n    });\r\n\r\n    window.actualizarDatosReservaFormulario = function(datos) {\r\n        console.log('\ud83d\udd04 Actualizando datos de reserva desde calendario:', datos);\r\n        datosReservaActuales = datos;\r\n\r\n        if (datos.fecha && document.getElementById('form-field-reserva_fecha')) {\r\n            document.getElementById('form-field-reserva_fecha').value = datos.fecha;\r\n        }\r\n        if (datos.hora && document.getElementById('form-field-reserva_inicio')) {\r\n            document.getElementById('form-field-reserva_inicio').value = datos.hora;\r\n        }\r\n        if (datos.profesional && document.getElementById('form-field-reserva_profesional')) {\r\n            document.getElementById('form-field-reserva_profesional').value = datos.profesional;\r\n        }\r\n        if (datos.agenda && document.getElementById('form-field-reserva_agenda')) {\r\n            document.getElementById('form-field-reserva_agenda').value = datos.agenda;\r\n        }\r\n        return datosReservaActuales;\r\n    };\r\n\r\n    if (window.seleccionarHorario) {\r\n        const originalSeleccionarHorario = window.seleccionarHorario;\r\n        window.seleccionarHorario = function(boton) {\r\n            const resultado = originalSeleccionarHorario(boton);\r\n            const datosHorario = {\r\n                fecha: boton.dataset.fecha,\r\n                hora: boton.dataset.hora,\r\n                profesional: boton.dataset.profesional,\r\n                agenda: boton.dataset.agenda\r\n            };\r\n            window.actualizarDatosReservaFormulario(datosHorario);\r\n            return resultado;\r\n        };\r\n    }\r\n    \r\n    window.procesarEnvioReserva = procesarEnvioReserva;\r\nwindow.recopilarDatosFormulario = recopilarDatosFormulario;\r\nwindow.recopilarDatosReservaMejorada = recopilarDatosReservaMejorada;\r\nwindow.validarDatosCompletos = validarDatosCompletos;\r\n\r\nwindow.debugTratamientosCompletos = function() {\r\n    console.log('\ud83d\udd0d DEBUG TRATAMIENTOS M\u00daLTIPLES:');\r\n    \r\n    const principal = localStorage.getItem('selectedProducto');\r\n    const complementos = localStorage.getItem('selectedComplementos');\r\n    \r\n    if (principal) {\r\n        const p = JSON.parse(principal);\r\n        console.log('\ud83c\udfaf Producto principal:', p.data?.name);\r\n        const uuidP = obtenerUuidDeProducto(p.data);\r\n        console.log('\ud83d\udd11 UUID principal:', uuidP);\r\n    }\r\n    \r\n    if (complementos) {\r\n        const c = JSON.parse(complementos);\r\n        console.log('\u2795 Productos complementarios:', c.length);\r\n        c.forEach((comp, i) => {\r\n            console.log(`  ${i+1}. ${comp.data?.name}`);\r\n            const uuidC = obtenerUuidDeProducto(comp.data);\r\n            console.log(`     UUID: ${uuidC}`);\r\n        });\r\n    }\r\n    \r\n    const uuidsCompletos = construirTratamientosUuid(\r\n        principal ? obtenerUuidDeProducto(JSON.parse(principal).data) : null\r\n    );\r\n    console.log('\ud83d\udccb UUIDs que se enviar\u00edan:', uuidsCompletos);\r\n    \r\n    return uuidsCompletos;\r\n};\r\n\r\nfunction obtenerUuidDeProducto(producto) {\r\n    if (!producto?.meta_data) return null;\r\n    \r\n    const meta = producto.meta_data.find(m => \r\n        m.key === 'reservo_uuid' || \r\n        m.key === 'field_689b4c787beba' || \r\n        m.key === '_reservo_uuid'\r\n    );\r\n    \r\n    return meta?.value || null;\r\n}\r\n\r\n    console.log('\u2705 Sistema de env\u00edo a Reservo inicializado correctamente');\r\n    console.log('\ud83d\udca1 Funciones disponibles para debugging:');\r\n    console.log('  - window.testEnvioReserva() - Probar env\u00edo');\r\n    console.log('  - window.obtenerDatosActuales() - Ver datos actuales');\r\n    console.log('  - window.actualizarDatosReservaFormulario(datos) - Actualizar datos manualmente');\r\n});\r\n\r\n\r\n<\/script>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b0588de elementor-widget elementor-widget-html\" data-id=\"b0588de\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\n    \/\/ Script de integraci\u00f3n calendario-formulario SIMPLIFICADO Y FUNCIONAL\ndocument.addEventListener('DOMContentLoaded', function() {\n    console.log('\ud83d\udd17 INTEGRACI\u00d3N CALENDARIO-FORMULARIO INICIADA (VERSI\u00d3N SIMPLIFICADA)');\n\n    \/\/ Variables globales para tracking - INICIALIZAR INMEDIATAMENTE\n    if (!window.datosReservaCompleta) {\n        window.datosReservaCompleta = {\n            producto: null,\n            categoria: null,\n            servicio: null,\n            fecha: null,\n            hora: null,\n            profesional: null,\n            agenda: null,\n            sucursal: null,\n            tratamiento_uuid: null\n        };\n    }\n\n    console.log('\u2705 datosReservaCompleta inicializado:', window.datosReservaCompleta);\n\n    \/\/ Funci\u00f3n S\u00cdNCRONA para extraer UUID del tratamiento\n    function extraerUuidTratamientoSync(producto) {\n        console.log('\ud83d\udd0d Extrayendo UUID del tratamiento (sync) para:', producto?.name);\n        \n        if (!producto) {\n            console.warn('\u26a0\ufe0f No se proporcion\u00f3 producto');\n            return null;\n        }\n\n        if (producto.meta_data && Array.isArray(producto.meta_data)) {\n            console.log(`\ud83d\udccb Buscando en ${producto.meta_data.length} meta_data entries...`);\n            \n            const posiblesClaves = [\n                'reservo_uuid',\n                'field_689b4c787beba',\n                '_field_689b4c787beba',\n                '_reservo_uuid',\n                'acf_reservo_uuid',\n                'uuid_tratamiento'\n            ];\n\n            for (const clave of posiblesClaves) {\n                const meta = producto.meta_data.find(item => item.key === clave);\n                if (meta && meta.value && meta.value.trim()) {\n                    const uuid = meta.value.trim();\n                    console.log(`\u2705 UUID encontrado en ${clave}:`, uuid);\n                    return uuid;\n                }\n            }\n        }\n\n        console.warn('\u26a0\ufe0f UUID no encontrado en meta_data');\n        return null;\n    }\n\n    \/\/ Escuchar eventos del sistema de selecci\u00f3n de productos\n    document.addEventListener('productoSeleccionado', function(e) {\n        console.log('\ud83c\udfaf Producto seleccionado para reserva:', e.detail.productoData?.name);\n        \n        window.datosReservaCompleta.producto = e.detail.productoData;\n        \n        \/\/ Intentar extraer UUID inmediatamente\n        const uuid = extraerUuidTratamientoSync(e.detail.productoData);\n        if (uuid) {\n            window.datosReservaCompleta.tratamiento_uuid = uuid;\n            console.log('\ud83c\udd94 UUID de tratamiento obtenido:', uuid);\n        } else {\n            console.warn('\u26a0\ufe0f No se pudo obtener UUID del tratamiento');\n            window.datosReservaCompleta.tratamiento_uuid = null;\n        }\n\n        actualizarCamposFormulario();\n    });\n\n    \/\/ Interceptar selecci\u00f3n de horario\n    document.addEventListener('click', function(e) {\n        const botonHorario = e.target.closest('.horario-btn');\n        if (botonHorario && botonHorario.dataset.fecha) {\n            console.log('\ud83d\udd50 Horario seleccionado:', {\n                fecha: botonHorario.dataset.fecha,\n                hora: botonHorario.dataset.hora,\n                profesional: botonHorario.dataset.profesional,\n                agenda: botonHorario.dataset.agenda\n            });\n\n            window.datosReservaCompleta.fecha = botonHorario.dataset.fecha;\n            window.datosReservaCompleta.hora = botonHorario.dataset.hora;\n            window.datosReservaCompleta.profesional = botonHorario.dataset.profesional;\n            window.datosReservaCompleta.agenda = botonHorario.dataset.agenda;\n\n            setTimeout(actualizarCamposFormulario, 100);\n        }\n    });\n\n    \/\/ Funci\u00f3n para actualizar campos del formulario\n    function actualizarCamposFormulario() {\n        console.log('\ud83d\udd04 Actualizando campos del formulario...');\n        console.log('\ud83d\udccb Datos actuales:', window.datosReservaCompleta);\n\n        try {\n            \/\/ Crear campos ocultos si no existen\n            crearCamposOcultosUUID();\n\n            \/\/ Actualizar campos existentes\n            actualizarCampo('form-field-reserva_fecha', window.datosReservaCompleta.fecha);\n            actualizarCampo('form-field-reserva_inicio', window.datosReservaCompleta.hora);\n            actualizarCampo('form-field-reserva_profesional', window.datosReservaCompleta.profesional);\n            \n            \/\/ Actualizar UUIDs en campos ocultos\n            actualizarCampo('form-field-reserva_agenda', window.datosReservaCompleta.agenda);\n            actualizarCampo('form-field-reserva_tratamiento', window.datosReservaCompleta.tratamiento_uuid);\n\n            \/\/ Actualizar servicio\n            if (window.datosReservaCompleta.producto) {\n                actualizarCampo('form-field-reserva_servicio', window.datosReservaCompleta.producto.name);\n            }\n\n            \/\/ Actualizar comentario\n            const comentario = generarComentario();\n            actualizarCampo('form-field-reserva_comentario', comentario);\n\n            mostrarEstadoActual();\n\n        } catch (error) {\n            console.error('\u274c Error actualizando campos:', error);\n        }\n    }\n\n    \/\/ Funci\u00f3n auxiliar para actualizar un campo\n    function actualizarCampo(id, valor) {\n        const campo = document.getElementById(id);\n        if (campo && valor) {\n            campo.value = valor;\n            console.log(`\u2705 ${id} actualizado:`, valor);\n        }\n    }\n\n    \/\/ Funci\u00f3n para crear campos ocultos UUID si no existen\n    function crearCamposOcultosUUID() {\n        const formulario = document.querySelector('.elementor-form');\n        if (!formulario) return;\n\n        \/\/ Campo agenda UUID\n        if (!document.getElementById('form-field-reserva_agenda')) {\n            const campoAgenda = document.createElement('input');\n            campoAgenda.type = 'hidden';\n            campoAgenda.id = 'form-field-reserva_agenda';\n            campoAgenda.name = 'form_fields[reserva_agenda]';\n            formulario.appendChild(campoAgenda);\n            console.log('\u2705 Campo agenda UUID creado');\n        }\n\n        \/\/ Campo tratamiento UUID\n        if (!document.getElementById('form-field-reserva_tratamiento')) {\n            const campoTratamiento = document.createElement('input');\n            campoTratamiento.type = 'hidden';\n            campoTratamiento.id = 'form-field-reserva_tratamiento';\n            campoTratamiento.name = 'form_fields[reserva_tratamiento]';\n            formulario.appendChild(campoTratamiento);\n            console.log('\u2705 Campo tratamiento UUID creado');\n        }\n    }\n\n    \/\/ Funci\u00f3n para generar comentario\n    function generarComentario() {\n        const detalles = ['Reserva Online'];\n\n        if (window.datosReservaCompleta.producto) {\n            detalles.push(`Tratamiento: ${window.datosReservaCompleta.producto.name}`);\n        }\n\n        return detalles.join(' | ');\n    }\n\n    \/\/ Funci\u00f3n para mostrar estado actual\n    function mostrarEstadoActual() {\n        console.log('\ud83d\udccb ESTADO ACTUAL:');\n        console.log('  \ud83c\udfaf Producto:', window.datosReservaCompleta.producto?.name || 'No seleccionado');\n        console.log('  \ud83d\udcc5 Fecha:', window.datosReservaCompleta.fecha || 'No seleccionada');\n        console.log('  \u23f0 Hora:', window.datosReservaCompleta.hora || 'No seleccionada');\n        console.log('  \ud83d\udc64 Profesional:', window.datosReservaCompleta.profesional || 'No seleccionado');\n        console.log('  \ud83c\udd94 Agenda UUID:', window.datosReservaCompleta.agenda || 'No disponible');\n        console.log('  \ud83d\udd11 Tratamiento UUID:', window.datosReservaCompleta.tratamiento_uuid || 'No disponible');\n    }\n\n    \/\/ Funci\u00f3n global simplificada para obtener datos de reserva\n    window.obtenerDatosReservaParaFormulario = function() {\n        console.log('\ud83d\udccb Obteniendo datos de reserva para formulario...');\n        \n        const datos = {\n            fecha: window.datosReservaCompleta.fecha,\n            hora: window.datosReservaCompleta.hora,\n            agenda_uuid: window.datosReservaCompleta.agenda,\n            tratamiento_uuid: window.datosReservaCompleta.tratamiento_uuid,\n            profesional: window.datosReservaCompleta.profesional,\n            comentario: generarComentario(),\n            validacion: {\n                valido: !!(window.datosReservaCompleta.fecha && \n                          window.datosReservaCompleta.hora && \n                          window.datosReservaCompleta.agenda && \n                          window.datosReservaCompleta.tratamiento_uuid),\n                errores: []\n            }\n        };\n        \n        \/\/ Validar datos\n        if (!datos.fecha) datos.validacion.errores.push('Fecha no seleccionada');\n        if (!datos.hora) datos.validacion.errores.push('Hora no seleccionada');\n        if (!datos.agenda_uuid) datos.validacion.errores.push('Agenda UUID no disponible');\n        if (!datos.tratamiento_uuid) datos.validacion.errores.push('Tratamiento UUID no disponible');\n\n        console.log('\ud83d\udcca Datos para formulario:', datos);\n        return datos;\n    };\n\n    \/\/ Funci\u00f3n global para debugging\n    window.mostrarEstadoReserva = function() {\n        mostrarEstadoActual();\n        return window.datosReservaCompleta;\n    };\n\n    \/\/ Funci\u00f3n para forzar actualizaci\u00f3n del UUID\n    window.forzarActualizacionUuidSimple = function() {\n        console.log('\ud83d\udd27 Forzando actualizaci\u00f3n de UUID...');\n        \n        if (!window.datosReservaCompleta.producto) {\n            console.error('\u274c No hay producto');\n            return null;\n        }\n\n        const uuid = extraerUuidTratamientoSync(window.datosReservaCompleta.producto);\n        if (uuid) {\n            window.datosReservaCompleta.tratamiento_uuid = uuid;\n            console.log('\u2705 UUID actualizado:', uuid);\n            actualizarCamposFormulario();\n            return uuid;\n        } else {\n            console.error('\u274c No se pudo obtener UUID');\n            return null;\n        }\n    };\n\n    \/\/ Intentar recuperar datos de localStorage al inicializar\n    function inicializarDatosGuardados() {\n        console.log('\ud83d\udd04 Verificando datos guardados...');\n        \n        try {\n            const productoGuardado = localStorage.getItem('selectedProducto');\n            if (productoGuardado) {\n                const producto = JSON.parse(productoGuardado);\n                if (producto.data) {\n                    window.datosReservaCompleta.producto = producto.data;\n                    console.log('\ud83d\udce6 Producto recuperado:', producto.data.name);\n                    \n                    const uuid = extraerUuidTratamientoSync(producto.data);\n                    if (uuid) {\n                        window.datosReservaCompleta.tratamiento_uuid = uuid;\n                        console.log('\ud83c\udd94 UUID recuperado:', uuid);\n                    }\n                    \n                    actualizarCamposFormulario();\n                }\n            }\n        } catch (error) {\n            console.error('\u274c Error recuperando datos:', error);\n        }\n    }\n\n    \/\/ Event listeners para limpiar datos\n    function limpiarDatos() {\n        window.datosReservaCompleta = {\n            producto: null,\n            categoria: null,\n            servicio: null,\n            fecha: null,\n            hora: null,\n            profesional: null,\n            agenda: null,\n            sucursal: null,\n            tratamiento_uuid: null\n        };\n    }\n\n    document.addEventListener('servicioLimpiado', limpiarDatos);\n    document.addEventListener('categoriaLimpiada', limpiarDatos);\n    document.addEventListener('productoLimpiado', limpiarDatos);\n\n    \/\/ Inicializar\n    inicializarDatosGuardados();\n\n    console.log('\u2705 Sistema de integraci\u00f3n simplificado inicializado');\n    console.log('\ud83d\udca1 Funciones disponibles:');\n    console.log('  - window.obtenerDatosReservaParaFormulario() - Obtener datos para env\u00edo');\n    console.log('  - window.mostrarEstadoReserva() - Ver estado actual');\n    console.log('  - window.forzarActualizacionUuidSimple() - Forzar actualizaci\u00f3n UUID');\n    console.log('  - window.datosReservaCompleta - Datos globales');\n});\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4ec5c3c elementor-widget elementor-widget-html\" data-id=\"4ec5c3c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\n    \/\/ Script de diagn\u00f3stico para investigar el problema del UUID\nconsole.log('\ud83d\udd0d DIAGN\u00d3STICO DE UUID DEL TRATAMIENTO');\n\n\/\/ 1. Verificar producto en localStorage\nconsole.log('\\n\ud83d\udce6 PRODUCTO EN LOCALSTORAGE:');\nconst productoGuardado = localStorage.getItem('selectedProducto');\nif (productoGuardado) {\n    try {\n        const producto = JSON.parse(productoGuardado);\n        console.log('\u2705 Producto encontrado:', producto.data?.name);\n        console.log('\ud83d\udccb Meta data disponible:', producto.data?.meta_data);\n        \n        if (producto.data?.meta_data && Array.isArray(producto.data.meta_data)) {\n            console.log(`\ud83d\udcca Total meta_data entries: ${producto.data.meta_data.length}`);\n            \n            \/\/ Mostrar todas las claves disponibles\n            console.log('\ud83d\udd11 Claves disponibles en meta_data:');\n            producto.data.meta_data.forEach((meta, index) => {\n                console.log(`  ${index}: ${meta.key} = ${meta.value}`);\n            });\n            \n            \/\/ Buscar espec\u00edficamente el UUID\n            const posiblesClaves = [\n                'reservo_uuid',\n                'field_689b4c787beba',\n                '_field_689b4c787beba',\n                '_reservo_uuid',\n                'acf_reservo_uuid',\n                'uuid_tratamiento'\n            ];\n            \n            console.log('\\n\ud83c\udfaf B\u00daSQUEDA DE UUID:');\n            posiblesClaves.forEach(clave => {\n                const meta = producto.data.meta_data.find(item => item.key === clave);\n                if (meta) {\n                    console.log(`\u2705 Encontrado en ${clave}:`, meta.value);\n                } else {\n                    console.log(`\u274c No encontrado: ${clave}`);\n                }\n            });\n            \n        } else {\n            console.warn('\u26a0\ufe0f meta_data no est\u00e1 disponible o no es un array');\n        }\n    } catch (e) {\n        console.error('\u274c Error parseando producto:', e);\n    }\n} else {\n    console.warn('\u26a0\ufe0f No hay producto guardado en localStorage');\n}\n\n\/\/ 2. Verificar variables globales\nconsole.log('\\n\ud83c\udf10 VARIABLES GLOBALES:');\nconsole.log('productoPrincipal:', window.productoPrincipal);\nconsole.log('datosReservaCompleta:', window.datosReservaCompleta);\nconsole.log('reservaSeleccionada:', window.reservaSeleccionada);\n\n\/\/ 3. Verificar si el UUID se us\u00f3 para cargar horarios\nconsole.log('\\n\ud83d\udcc5 SISTEMA DE CALENDARIO:');\nif (window.productoPrincipal) {\n    console.log('Producto principal disponible:', window.productoPrincipal.name);\n    console.log('Meta data:', window.productoPrincipal.meta_data);\n}\n\n\/\/ 4. Intentar cargar el producto completo desde WooCommerce\nasync function cargarProductoCompleto() {\n    console.log('\\n\ud83d\udd04 CARGANDO PRODUCTO COMPLETO DESDE WOOCOMMERCE:');\n    \n    const productoGuardado = localStorage.getItem('selectedProducto');\n    if (!productoGuardado) {\n        console.error('\u274c No hay producto para cargar');\n        return;\n    }\n    \n    try {\n        const producto = JSON.parse(productoGuardado);\n        const productoId = producto.data?.id;\n        \n        if (!productoId) {\n            console.error('\u274c No se encontr\u00f3 ID del producto');\n            return;\n        }\n        \n        console.log(`\ud83d\udd04 Cargando producto ID: ${productoId}`);\n        \n        const response = await fetch(`${window.location.origin}\/wp-json\/wc\/v3\/products\/${productoId}?consumer_key=ck_6381579117ac59ad6ecbd38e618553eaa9856765&consumer_secret=cs_e12f13e79017efdf5799f55fd22ad42c458dcb22`);\n        \n        if (response.ok) {\n            const productoCompleto = await response.json();\n            console.log('\u2705 Producto completo cargado:', productoCompleto.name);\n            console.log('\ud83d\udccb Meta data completa:', productoCompleto.meta_data);\n            \n            if (productoCompleto.meta_data && Array.isArray(productoCompleto.meta_data)) {\n                console.log(`\ud83d\udcca Total meta_data en producto completo: ${productoCompleto.meta_data.length}`);\n                \n                \/\/ Buscar UUID en producto completo\n                const posiblesClaves = [\n                    'reservo_uuid',\n                    'field_689b4c787beba',\n                    '_field_689b4c787beba',\n                    '_reservo_uuid',\n                    'acf_reservo_uuid',\n                    'uuid_tratamiento'\n                ];\n                \n                console.log('\\n\ud83c\udfaf B\u00daSQUEDA DE UUID EN PRODUCTO COMPLETO:');\n                let uuidEncontrado = null;\n                \n                posiblesClaves.forEach(clave => {\n                    const meta = productoCompleto.meta_data.find(item => item.key === clave);\n                    if (meta) {\n                        console.log(`\u2705 Encontrado en ${clave}:`, meta.value);\n                        if (!uuidEncontrado) uuidEncontrado = meta.value;\n                    } else {\n                        console.log(`\u274c No encontrado: ${clave}`);\n                    }\n                });\n                \n                if (uuidEncontrado) {\n                    console.log(`\ud83c\udf89 UUID ENCONTRADO: ${uuidEncontrado}`);\n                    \n                    \/\/ Actualizar localStorage con el producto completo\n                    const productoActualizado = {\n                        slug: producto.slug,\n                        data: productoCompleto\n                    };\n                    localStorage.setItem('selectedProducto', JSON.stringify(productoActualizado));\n                    console.log('\u2705 Producto actualizado en localStorage');\n                    \n                    \/\/ Actualizar variables globales\n                    if (window.datosReservaCompleta) {\n                        window.datosReservaCompleta.producto = productoCompleto;\n                        window.datosReservaCompleta.tratamiento_uuid = uuidEncontrado;\n                        console.log('\u2705 Variables globales actualizadas');\n                    }\n                    \n                    return uuidEncontrado;\n                } else {\n                    console.error('\u274c No se encontr\u00f3 UUID en el producto completo');\n                    \n                    \/\/ Mostrar todos los campos disponibles para debugging\n                    console.log('\ud83d\udccb TODOS LOS CAMPOS META DISPONIBLES:');\n                    productoCompleto.meta_data.forEach((meta, index) => {\n                        console.log(`  ${index}: \"${meta.key}\" = \"${meta.value}\"`);\n                    });\n                }\n            }\n        } else {\n            console.error('\u274c Error cargando producto completo:', response.status);\n        }\n    } catch (error) {\n        console.error('\u274c Error:', error);\n    }\n}\n\n\/\/ 5. Verificar campos ACF directamente\nasync function verificarCamposACF() {\n    console.log('\\n\ud83d\udd27 VERIFICANDO CAMPOS ACF:');\n    \n    const productoGuardado = localStorage.getItem('selectedProducto');\n    if (!productoGuardado) return;\n    \n    try {\n        const producto = JSON.parse(productoGuardado);\n        const productoId = producto.data?.id;\n        \n        if (!productoId) return;\n        \n        \/\/ Intentar acceder a campos ACF directamente\n        const response = await fetch(`${window.location.origin}\/wp-json\/wp\/v2\/product\/${productoId}?_fields=acf,meta`);\n        \n        if (response.ok) {\n            const data = await response.json();\n            console.log('\ud83d\udccb Datos ACF:', data.acf);\n            console.log('\ud83d\udccb Meta fields:', data.meta);\n        }\n    } catch (error) {\n        console.error('\u274c Error verificando ACF:', error);\n    }\n}\n\n\/\/ Ejecutar diagn\u00f3sticos\nconsole.log('\\n\ud83d\ude80 EJECUTANDO DIAGN\u00d3STICOS...');\ncargarProductoCompleto().then(uuid => {\n    if (uuid) {\n        console.log('\\n\u2705 PROBLEMA RESUELTO - UUID encontrado:', uuid);\n        console.log('\ud83d\udd04 Intenta enviar el formulario nuevamente');\n    } else {\n        console.log('\\n\u274c PROBLEMA PERSISTE - Ejecutando verificaci\u00f3n ACF...');\n        verificarCamposACF();\n    }\n});\n\n\/\/ Funci\u00f3n para forzar actualizaci\u00f3n del UUID\nwindow.forzarActualizacionUUID = async function() {\n    console.log('\ud83d\udd27 FORZANDO ACTUALIZACI\u00d3N DE UUID...');\n    return await cargarProductoCompleto();\n};\n\n\/\/ Funci\u00f3n para mostrar configuraci\u00f3n actual de ACF\nwindow.mostrarConfiguracionACF = function() {\n    console.log('\u2699\ufe0f CONFIGURACI\u00d3N ACTUAL:');\n    console.log('1. Ve a WordPress Admin > Campos Personalizados');\n    console.log('2. Busca el grupo de campos para productos');\n    console.log('3. Verifica que existe un campo llamado \"reservo_uuid\"');\n    console.log('4. La clave del campo debe ser: field_689b4c787beba');\n    console.log('5. El campo debe estar asignado a productos');\n    console.log('6. Edita el producto y agrega el UUID del tratamiento');\n};\n\nconsole.log('\\n\ud83d\udca1 FUNCIONES DISPONIBLES:');\nconsole.log('- window.forzarActualizacionUUID() - Recargar producto con UUID');\nconsole.log('- window.mostrarConfiguracionACF() - Ver configuraci\u00f3n necesaria');\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4cfc356 elementor-widget elementor-widget-html\" data-id=\"4cfc356\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\n    \/\/ Script de correcci\u00f3n de timing para capturar UUID - VERSI\u00d3N DEFINITIVA\ndocument.addEventListener('DOMContentLoaded', function() {\n    console.log('\ud83c\udfaf CORRECCI\u00d3N DE TIMING UUID INICIADA');\n\n    \/\/ Asegurar que datosReservaCompleta existe\n    if (!window.datosReservaCompleta) {\n        window.datosReservaCompleta = {\n            producto: null,\n            categoria: null,\n            servicio: null,\n            fecha: null,\n            hora: null,\n            profesional: null,\n            agenda: null,\n            sucursal: null,\n            tratamiento_uuid: null\n        };\n    }\n\n    \/\/ INTERCEPTAR LA CONSOLA PARA CAPTURAR EL UUID CUANDO SE ENCUENTRA\n    const originalConsoleLog = console.log;\n    console.log = function(...args) {\n        \/\/ Buscar el mensaje espec\u00edfico donde se encuentra el UUID\n        const mensaje = args.join(' ');\n        \n        if (mensaje.includes('\u2705 UUID encontrado en producto completo:')) {\n            \/\/ Extraer el UUID del mensaje\n            const uuidMatch = mensaje.match(\/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})\/i);\n            \n            if (uuidMatch && uuidMatch[1]) {\n                const uuid = uuidMatch[1];\n                console.log('\ud83c\udf89 UUID INTERCEPTADO DESDE CONSOLA:', uuid);\n                \n                \/\/ Guardar inmediatamente en datosReservaCompleta\n                window.datosReservaCompleta.tratamiento_uuid = uuid;\n                \n                \/\/ Actualizar campo del formulario inmediatamente\n                actualizarCampoUuidEnFormulario(uuid);\n                \n                \/\/ Tambi\u00e9n intentar actualizar el producto\n                setTimeout(() => {\n                    actualizarProductoConUuid(uuid);\n                }, 100);\n            }\n        }\n        \n        \/\/ Llamar al console.log original\n        originalConsoleLog.apply(console, args);\n    };\n\n    function actualizarCampoUuidEnFormulario(uuid) {\n        console.log('\ud83d\udd27 Actualizando campo UUID en formulario:', uuid);\n        \n        \/\/ Crear campo si no existe\n        let campoTratamiento = document.getElementById('form-field-reserva_tratamiento');\n        if (!campoTratamiento) {\n            const formulario = document.querySelector('.elementor-form');\n            if (formulario) {\n                campoTratamiento = document.createElement('input');\n                campoTratamiento.type = 'hidden';\n                campoTratamiento.id = 'form-field-reserva_tratamiento';\n                campoTratamiento.name = 'form_fields[reserva_tratamiento]';\n                formulario.appendChild(campoTratamiento);\n                console.log('\u2705 Campo tratamiento UUID creado');\n            }\n        }\n        \n        \/\/ Actualizar valor\n        if (campoTratamiento) {\n            campoTratamiento.value = uuid;\n            console.log('\u2705 UUID establecido en formulario:', uuid);\n        }\n    }\n\n    function actualizarProductoConUuid(uuid) {\n        console.log('\ud83d\udd04 Actualizando producto con UUID:', uuid);\n        \n        try {\n            const productoGuardado = localStorage.getItem('selectedProducto');\n            if (productoGuardado) {\n                const producto = JSON.parse(productoGuardado);\n                if (producto.data) {\n                    window.datosReservaCompleta.producto = producto.data;\n                    window.datosReservaCompleta.tratamiento_uuid = uuid;\n                    \n                    console.log('\u2705 Producto y UUID actualizados en datosReservaCompleta');\n                    mostrarEstadoCompleto();\n                }\n            }\n        } catch (e) {\n            console.error('\u274c Error actualizando producto:', e);\n        }\n    }\n\n    function mostrarEstadoCompleto() {\n        console.log('\ud83d\udcca ESTADO COMPLETO ACTUALIZADO:');\n        console.log('  \ud83c\udfaf Producto:', window.datosReservaCompleta.producto?.name || 'No disponible');\n        console.log('  \ud83d\udd11 UUID Tratamiento:', window.datosReservaCompleta.tratamiento_uuid || 'No disponible');\n        console.log('  \ud83d\udcc5 Fecha:', window.datosReservaCompleta.fecha || 'No seleccionada');\n        console.log('  \u23f0 Hora:', window.datosReservaCompleta.hora || 'No seleccionada');\n        console.log('  \ud83d\udc64 Profesional:', window.datosReservaCompleta.profesional || 'No seleccionado');\n        console.log('  \ud83c\udd94 Agenda UUID:', window.datosReservaCompleta.agenda || 'No disponible');\n    }\n\n    \/\/ M\u00c9TODO ALTERNATIVO: Observar cambios en el localStorage\n    let storageCheckInterval;\n    \n    function iniciarMonitoreoLocalStorage() {\n        let ultimoProducto = null;\n        \n        storageCheckInterval = setInterval(() => {\n            const productoActual = localStorage.getItem('selectedProducto');\n            \n            if (productoActual && productoActual !== ultimoProducto) {\n                ultimoProducto = productoActual;\n                \n                try {\n                    const producto = JSON.parse(productoActual);\n                    if (producto.data && producto.data.meta_data) {\n                        const uuid = extraerUuidDelProducto(producto.data);\n                        \n                        if (uuid && uuid !== window.datosReservaCompleta.tratamiento_uuid) {\n                            console.log('\ud83d\udd0d UUID detectado por monitoreo:', uuid);\n                            \n                            window.datosReservaCompleta.producto = producto.data;\n                            window.datosReservaCompleta.tratamiento_uuid = uuid;\n                            \n                            actualizarCampoUuidEnFormulario(uuid);\n                            mostrarEstadoCompleto();\n                        }\n                    }\n                } catch (e) {\n                    \/\/ Ignorar errores de parsing\n                }\n            }\n        }, 500); \/\/ Verificar cada 500ms\n    }\n\n    function extraerUuidDelProducto(producto) {\n        if (!producto || !producto.meta_data) return null;\n\n        const posiblesClaves = [\n            'reservo_uuid',\n            'field_689b4c787beba',\n            '_field_689b4c787beba',\n            '_reservo_uuid',\n            'acf_reservo_uuid',\n            'uuid_tratamiento'\n        ];\n\n        for (const clave of posiblesClaves) {\n            const meta = producto.meta_data.find(item => item.key === clave);\n            if (meta && meta.value && meta.value.trim()) {\n                return meta.value.trim();\n            }\n        }\n\n        return null;\n    }\n\n    \/\/ SOBRESCRIBIR LA FUNCI\u00d3N obtenerDatosReservaParaFormulario ORIGINAL\n    window.obtenerDatosReservaParaFormulario = function() {\n        console.log('\ud83d\udccb [CORREGIDO] Obteniendo datos completos de reserva...');\n        \n        \/\/ Verificar que tenemos el UUID antes de continuar\n        if (!window.datosReservaCompleta.tratamiento_uuid) {\n            console.warn('\u26a0\ufe0f Intentando obtener UUID desde localStorage...');\n            \n            const productoGuardado = localStorage.getItem('selectedProducto');\n            if (productoGuardado) {\n                try {\n                    const producto = JSON.parse(productoGuardado);\n                    const uuid = extraerUuidDelProducto(producto.data);\n                    \n                    if (uuid) {\n                        console.log('\u2705 UUID recuperado desde localStorage:', uuid);\n                        window.datosReservaCompleta.tratamiento_uuid = uuid;\n                        window.datosReservaCompleta.producto = producto.data;\n                        actualizarCampoUuidEnFormulario(uuid);\n                    }\n                } catch (e) {\n                    console.error('\u274c Error recuperando UUID:', e);\n                }\n            }\n        }\n        \n        const datos = {\n            fecha: window.datosReservaCompleta.fecha,\n            hora: window.datosReservaCompleta.hora,\n            agenda_uuid: window.datosReservaCompleta.agenda,\n            tratamiento_uuid: window.datosReservaCompleta.tratamiento_uuid,\n            profesional: window.datosReservaCompleta.profesional,\n            comentario: `Reserva Online | Tratamiento: ${window.datosReservaCompleta.producto?.name || 'No especificado'}`,\n            validacion: {\n                valido: false,\n                errores: []\n            }\n        };\n        \n        \/\/ Validar datos\n        if (!datos.fecha) datos.validacion.errores.push('Fecha no seleccionada');\n        if (!datos.hora) datos.validacion.errores.push('Hora no seleccionada');\n        if (!datos.agenda_uuid) datos.validacion.errores.push('Agenda UUID no disponible');\n        if (!datos.tratamiento_uuid) datos.validacion.errores.push('Tratamiento UUID no disponible');\n        if (!datos.profesional) datos.validacion.errores.push('Profesional no seleccionado');\n\n        datos.validacion.valido = datos.validacion.errores.length === 0;\n\n        console.log('\ud83d\udcca [CORREGIDO] Datos finales:', datos);\n        return datos;\n    };\n\n    \/\/ FUNCI\u00d3N PARA FORZAR SINCRONIZACI\u00d3N MANUAL\n    window.forzarSincronizacionUuid = function() {\n        console.log('\ud83d\udd27 FORZANDO SINCRONIZACI\u00d3N DE UUID...');\n        \n        const productoGuardado = localStorage.getItem('selectedProducto');\n        if (!productoGuardado) {\n            console.error('\u274c No hay producto guardado');\n            return false;\n        }\n        \n        try {\n            const producto = JSON.parse(productoGuardado);\n            const uuid = extraerUuidDelProducto(producto.data);\n            \n            if (uuid) {\n                console.log('\u2705 UUID encontrado:', uuid);\n                \n                \/\/ Actualizar datosReservaCompleta\n                window.datosReservaCompleta.producto = producto.data;\n                window.datosReservaCompleta.tratamiento_uuid = uuid;\n                \n                \/\/ Actualizar campo del formulario\n                actualizarCampoUuidEnFormulario(uuid);\n                \n                \/\/ Mostrar estado\n                mostrarEstadoCompleto();\n                \n                \/\/ Verificar que los datos est\u00e9n listos para env\u00edo\n                const datosParaEnvio = window.obtenerDatosReservaParaFormulario();\n                console.log('\ud83d\udd0d Validaci\u00f3n de datos:', datosParaEnvio.validacion);\n                \n                return true;\n            } else {\n                console.error('\u274c UUID no encontrado en producto');\n                console.log('\ud83d\udccb Meta data disponible:', producto.data?.meta_data);\n                return false;\n            }\n        } catch (e) {\n            console.error('\u274c Error:', e);\n            return false;\n        }\n    };\n\n    \/\/ FUNCI\u00d3N DE DEBUG MEJORADA\n    window.debugReservaCompleta = function() {\n        console.log('\ud83d\udd0d DEBUG COMPLETO [VERSI\u00d3N CORREGIDA]:');\n        console.log('1. datosReservaCompleta:', window.datosReservaCompleta);\n        \n        const productoLS = localStorage.getItem('selectedProducto');\n        if (productoLS) {\n            const producto = JSON.parse(productoLS);\n            console.log('2. Producto en localStorage:', producto.data?.name);\n            console.log('3. Meta data:', producto.data?.meta_data);\n            \n            const uuid = extraerUuidDelProducto(producto.data);\n            console.log('4. UUID extra\u00eddo:', uuid);\n        }\n        \n        \/\/ Verificar campos del formulario\n        console.log('5. Campos del formulario:');\n        console.log('   - Fecha:', document.getElementById('form-field-reserva_fecha')?.value);\n        console.log('   - Hora:', document.getElementById('form-field-reserva_inicio')?.value);\n        console.log('   - Profesional:', document.getElementById('form-field-reserva_profesional')?.value);\n        console.log('   - Agenda UUID:', document.getElementById('form-field-reserva_agenda')?.value);\n        console.log('   - Tratamiento UUID:', document.getElementById('form-field-reserva_tratamiento')?.value);\n        \n        \/\/ Verificar validaci\u00f3n\n        const datosValidacion = window.obtenerDatosReservaParaFormulario();\n        console.log('6. Estado de validaci\u00f3n:', datosValidacion.validacion);\n        \n        return {\n            datosReserva: window.datosReservaCompleta,\n            validacion: datosValidacion.validacion,\n            listo: datosValidacion.validacion.valido\n        };\n    };\n\n    \/\/ Iniciar monitoreo\n    iniciarMonitoreoLocalStorage();\n\n    \/\/ Limpiar monitoreo al cambiar p\u00e1gina\n    window.addEventListener('beforeunload', () => {\n        if (storageCheckInterval) {\n            clearInterval(storageCheckInterval);\n        }\n    });\n\n    \/\/ Intentar sincronizaci\u00f3n inicial despu\u00e9s de un momento\n    setTimeout(() => {\n        console.log('\ud83d\udd04 Intentando sincronizaci\u00f3n inicial...');\n        window.forzarSincronizacionUuid();\n    }, 2000);\n\n    console.log('\u2705 Sistema de correcci\u00f3n de timing UUID inicializado');\n    console.log('\ud83d\udca1 Funciones disponibles:');\n    console.log('  - window.forzarSincronizacionUuid() - Sincronizar UUID manualmente');\n    console.log('  - window.debugReservaCompleta() - Debug completo con validaci\u00f3n');\n    console.log('  - window.obtenerDatosReservaParaFormulario() - Datos corregidos para env\u00edo');\n});\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-e544bdc e-con-full elementor-hidden-tablet elementor-hidden-mobile e-flex e-con e-child\" data-id=\"e544bdc\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-8a6fd64 e-flex e-con-boxed e-con e-parent\" data-id=\"8a6fd64\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ecfae90 elementor-widget elementor-widget-html\" data-id=\"ecfae90\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"es\">\r\n<head>\r\n    <meta charset=\"UTF-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n    <title>Sistema Multi-Paso para Formulario Sothers<\/title>\r\n    <style>\r\n        \/* CSS para el sistema de pasos m\u00faltiples *\/\r\n        \r\n        \/* Indicador de progreso *\/\r\n        .sothers-progress-bar {\r\n            position: fixed;\r\n            top: 0;\r\n            left: 0;\r\n            width: 100%;\r\n            height: 4px;\r\n            background: rgba(49, 152, 158, 0.2);\r\n            z-index: 9999;\r\n            transition: all 0.3s ease;\r\n        }\r\n        \r\n        .sothers-progress-fill {\r\n            height: 100%;\r\n            background: linear-gradient(90deg, #31989E 0%, #2a8187 100%);\r\n            width: 0%;\r\n            transition: width 0.5s ease;\r\n            box-shadow: 0 0 10px rgba(49, 152, 158, 0.5);\r\n        }\r\n        \r\n        \/* Indicador de pasos *\/\r\n        .sothers-steps-indicator {\r\n            position: fixed;\r\n            top: 120px;\r\n            right: 20px;\r\n            background: white;\r\n            border-radius: 12px;\r\n            padding: 15px 20px;\r\n            box-shadow: 0 4px 20px rgba(0,0,0,0.1);\r\n            z-index: 9998;\r\n            font-family: 'Josefin Sans', sans-serif;\r\n            border: 2px solid rgba(49, 152, 158, 0.1);\r\n        }\r\n        \r\n        .step-indicator {\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 10px;\r\n            margin-bottom: 8px;\r\n            font-size: 14px;\r\n            transition: all 0.3s ease;\r\n        }\r\n        \r\n        .step-indicator:last-child {\r\n            margin-bottom: 0;\r\n        }\r\n        \r\n        .step-number {\r\n            width: 24px;\r\n            height: 24px;\r\n            border-radius: 50%;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n            font-size: 12px;\r\n            font-weight: 600;\r\n            transition: all 0.3s ease;\r\n        }\r\n        \r\n        .step-indicator.completed .step-number {\r\n            background: #31989E;\r\n            color: white;\r\n        }\r\n        \r\n        .step-indicator.active .step-number {\r\n            background: #31989E;\r\n            color: white;\r\n            box-shadow: 0 0 0 3px rgba(49, 152, 158, 0.3);\r\n        }\r\n        \r\n        .step-indicator.pending .step-number {\r\n            background: #f0f0f0;\r\n            color: #999;\r\n        }\r\n        \r\n        .step-text {\r\n            color: #666;\r\n            font-weight: 500;\r\n        }\r\n        \r\n        .step-indicator.active .step-text {\r\n            color: #31989E;\r\n            font-weight: 600;\r\n        }\r\n        \r\n        .step-indicator.completed .step-text {\r\n            color: #31989E;\r\n        }\r\n        \r\n        \/* ANTI-PARPADEO\r\n           Elementor renderiza los tres pasos VISIBLES en el HTML. El CSS que\r\n           los oculta depende de .sothers-step, clase que agrega el JavaScript\r\n           en DOMContentLoaded. Resultado: el navegador pinta las tres\r\n           secciones (calendario y formulario incluidos), despues el JS las\r\n           colapsa, y recien entonces aparece el paso 1. Eso es el parpadeo.\r\n\r\n           Estas reglas ocultan los pasos 2 y 3 desde el primer pintado, sin\r\n           esperar al JS. El paso 1 queda visible porque es el punto de\r\n           entrada normal, asi no hay hueco en blanco.\r\n\r\n           No interfiere con el sistema: mostrarPaso() escribe\r\n           el.style.display en linea, y el estilo en linea gana sobre esto. *\/\r\n        .paso4-selecciona-tu-fecha-y-hora,\r\n        .paso5-ingresa-tus-datos {\r\n            display: none;\r\n        }\r\n\r\n        \/* Ocultar secciones por defecto *\/\r\n        .sothers-step {\r\n            display: none;\r\n            opacity: 0;\r\n            transform: translateY(20px);\r\n            transition: all 0.5s ease;\r\n        }\r\n        \r\n        .sothers-step.active {\r\n            display: flex;\r\n            opacity: 1;\r\n            transform: translateY(0);\r\n        }\r\n        \r\n        \/* Animaciones de transici\u00f3n *\/\r\n        .sothers-step.entering {\r\n            animation: slideInUp 0.5s ease-out forwards;\r\n        }\r\n        \r\n        .sothers-step.exiting {\r\n            animation: slideOutDown 0.3s ease-in forwards;\r\n        }\r\n        \r\n        @keyframes slideInUp {\r\n            from {\r\n                opacity: 0;\r\n                transform: translateY(30px);\r\n            }\r\n            to {\r\n                opacity: 1;\r\n                transform: translateY(0);\r\n            }\r\n        }\r\n        \r\n        @keyframes slideOutDown {\r\n            from {\r\n                opacity: 1;\r\n                transform: translateY(0);\r\n            }\r\n            to {\r\n                opacity: 0;\r\n                transform: translateY(-20px);\r\n            }\r\n        }\r\n        \r\n        \/* Botones de navegaci\u00f3n mejorados *\/\r\n        .sothers-step-navigation {\r\n            display: flex;\r\n            justify-content: center;\r\n            gap: 20px;\r\n            margin: 40px 0;\r\n            padding: 20px;\r\n        }\r\n        \r\n        .sothers-nav-btn {\r\n            padding: 12px 30px;\r\n            border: none;\r\n            border-radius: 8px;\r\n            font-size: 16px;\r\n            font-weight: 600;\r\n            cursor: pointer;\r\n            transition: all 0.3s ease;\r\n            font-family: 'Josefin Sans', sans-serif;\r\n            text-transform: uppercase;\r\n            letter-spacing: 0.5px;\r\n        }\r\n        \r\n        .sothers-btn-back {\r\n            background: #f8f9fa;\r\n            color: #666;\r\n            border: 2px solid #e0e0e0;\r\n        }\r\n        \r\n        .sothers-btn-back:hover {\r\n            background: #e9ecef;\r\n            border-color: #ccc;\r\n        }\r\n        \r\n        .sothers-btn-next {\r\n            background: #31989E;\r\n            color: white;\r\n            box-shadow: 0 4px 15px rgba(49, 152, 158, 0.3);\r\n        }\r\n        \r\n        .sothers-btn-next:hover:not(:disabled) {\r\n            background: #2a8187;\r\n            transform: translateY(-2px);\r\n            box-shadow: 0 6px 20px rgba(49, 152, 158, 0.4);\r\n        }\r\n        \r\n        .sothers-btn-next:disabled {\r\n            background: #ccc;\r\n            cursor: not-allowed;\r\n            transform: none;\r\n            box-shadow: none;\r\n        }\r\n        \r\n        \/* Mensaje de validaci\u00f3n *\/\r\n        .sothers-validation-message {\r\n            position: fixed;\r\n            bottom: 20px;\r\n            right: 20px;\r\n            background: #dc2626;\r\n            color: white;\r\n            padding: 15px 20px;\r\n            border-radius: 8px;\r\n            box-shadow: 0 4px 15px rgba(220, 38, 38, 0.3);\r\n            z-index: 10000;\r\n            font-family: 'Josefin Sans', sans-serif;\r\n            font-weight: 600;\r\n            transform: translateX(100%);\r\n            transition: transform 0.3s ease;\r\n        }\r\n        \r\n        .sothers-validation-message.show {\r\n            transform: translateX(0);\r\n        }\r\n        \r\n        \/* Responsive *\/\r\n        @media (max-width: 768px) {\r\n            .sothers-steps-indicator {\r\n                position: relative;\r\n                top: auto;\r\n                right: auto;\r\n                margin: 20px;\r\n                padding: 15px;\r\n            }\r\n            \r\n            .sothers-step-navigation {\r\n                flex-direction: column;\r\n                gap: 15px;\r\n            }\r\n            \r\n            .sothers-nav-btn {\r\n                width: 100%;\r\n                padding: 15px;\r\n            }\r\n        }\r\n        \r\n        \/* Overlay de carga entre pasos *\/\r\n        .sothers-loading-overlay {\r\n            position: fixed;\r\n            top: 0;\r\n            left: 0;\r\n            width: 100%;\r\n            height: 100%;\r\n            background: rgba(255, 255, 255, 0.9);\r\n            display: none;\r\n            align-items: center;\r\n            justify-content: center;\r\n            z-index: 10001;\r\n        }\r\n        \r\n        .sothers-loading-spinner {\r\n            width: 50px;\r\n            height: 50px;\r\n            border: 4px solid #f0f0f0;\r\n            border-top: 4px solid #31989E;\r\n            border-radius: 50%;\r\n            animation: spin 1s linear infinite;\r\n        }\r\n        \r\n        @keyframes spin {\r\n            0% { transform: rotate(0deg); }\r\n            100% { transform: rotate(360deg); }\r\n        }\r\n\r\n        \/* PASO \"TUS EXPERIENCIAS\" ELIMINADO DEL FLUJO. *\/\r\n        .paso3-tus-experiencias {\r\n            display: none !important;\r\n        }\r\n    <\/style>\r\n<\/head>\r\n<body>\r\n\r\n    <div class=\"sothers-progress-bar\">\r\n        <div class=\"sothers-progress-fill\"><\/div>\r\n    <\/div>\r\n    \r\n\r\n    <div class=\"sothers-steps-indicator\">\r\n        <div class=\"step-indicator active\" data-step=\"1\">\r\n            <div class=\"step-number\">1<\/div>\r\n            <div class=\"step-text\">Select Service<\/div>\r\n        <\/div>\r\n        <div class=\"step-indicator pending\" data-step=\"2\">\r\n            <div class=\"step-number\">2<\/div>\r\n            <div class=\"step-text\">Select Date<\/div>\r\n        <\/div>\r\n        <div class=\"step-indicator pending\" data-step=\"3\">\r\n            <div class=\"step-number\">3<\/div>\r\n            <div class=\"step-text\">Enter Data<\/div>\r\n        <\/div>\r\n    <\/div>\r\n    \r\n    <div class=\"sothers-loading-overlay\">\r\n        <div class=\"sothers-loading-spinner\"><\/div>\r\n    <\/div>\r\n\r\n    <script>\r\n\/\/ Sistema de formulario multi-paso para Sothers Spa\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    console.log('\ud83c\udfaf SISTEMA MULTI-PASO SOTHERS INICIADO');\r\n\r\n    \/\/ Configuraci\u00f3n de los pasos\r\n    const pasos = [\r\n        {\r\n            id: 1,\r\n            nombre: 'Seleccionar Servicio',\r\n            selector: '.paso1-selecciona-tu-servicio',\r\n            botonContinuar: '.paso1-boton-continuar',\r\n            validacion: () => validarSeleccionProducto(),\r\n            onEnter: () => console.log('\ud83d\udccb Entrando al paso 1: Seleccionar Servicio'),\r\n            onExit: () => console.log('\u2705 Saliendo del paso 1')\r\n        },\r\n        {\r\n            id: 2,\r\n            nombre: 'Seleccionar Fecha',\r\n            selector: '.paso4-selecciona-tu-fecha-y-hora',\r\n            botonContinuar: '.paso4-boton-continuar',\r\n            validacion: () => validarFechaHora(),\r\n            onEnter: () => console.log('\ud83d\udcc5 Entrando al paso 2: Seleccionar Fecha'),\r\n            onExit: () => console.log('\u2705 Saliendo del paso 2')\r\n        },\r\n        {\r\n            id: 3,\r\n            nombre: 'Ingresar Datos',\r\n            selector: '.paso5-ingresa-tus-datos',\r\n            botonContinuar: '.elementor-form button[type=\"submit\"]',\r\n            validacion: () => validarDatosPersonales(),\r\n            onEnter: () => console.log('\ud83d\udc64 Entrando al paso 3: Ingresar Datos'),\r\n            onExit: () => console.log('\u2705 Completando formulario')\r\n        }\r\n    ];\r\n\r\n    \/\/ Numero del paso del calendario dentro del flujo actual.\r\n    const PASO_CALENDARIO = 2;\r\n\r\n    \/\/ Botones \"Volver a Productos\" del paso del calendario.\r\n    \/\/ Hay dos: el del HTML personalizado (#btnVolver, que el script de\r\n    \/\/ sincronizacion OCULTA) y el widget de Elementor, que es el visible.\r\n    \/\/ Si algun dia cambia el ID del widget en Elementor, se ajusta aca.\r\n    const SELECTOR_BOTON_VOLVER = '#btnVolver, .elementor-element-cbddb52 .elementor-button';\r\n\r\n    \/\/ Estado del sistema\r\n    let pasoActual = 1;\r\n    let elementosPaso = new Map();\r\n    \r\n    \/\/ Elementos de la UI\r\n    const progressBar = document.querySelector('.sothers-progress-fill');\r\n    const stepsIndicator = document.querySelector('.sothers-steps-indicator');\r\n    const loadingOverlay = document.querySelector('.sothers-loading-overlay');\r\n    \r\n    \r\n\r\n\r\n    \/\/ Inicializar el sistema\r\n    init();\r\n\r\n    function init() {\r\n        console.log('\ud83d\udd04 Inicializando sistema multi-paso...');\r\n\r\n        mapearElementosPaso();\r\n\r\n        \/\/ El paso \"Tus Experiencias\" ya no forma parte del flujo\r\n        ocultarPasoExperiencias();\r\n\r\n        \/\/ Sin paso de experiencias no hay forma de elegir complementos\r\n        limpiarComplementosObsoletos();\r\n\r\n        configurarEventos();\r\n\r\n        \/\/ El \"Volver\" del calendario necesita interceptarse antes que el\r\n        \/\/ handler del script de confirmacion, que apunta a un contenedor\r\n        \/\/ inexistente.\r\n        conectarBotonVolver();\r\n\r\n        \/\/ Puede venir un salto directo al calendario\r\n        const pasoInicial = resolverPasoInicial();\r\n        mostrarPaso(pasoInicial, false);\r\n\r\n        actualizarIndicadores();\r\n\r\n        if (pasoInicial === PASO_CALENDARIO) {\r\n            vigilarProductoEnCalendario();\r\n        }\r\n\r\n        console.log('\u2705 Sistema multi-paso inicializado (paso inicial: ' + pasoInicial + ')');\r\n    }\r\n\r\n    \/\/ Oculta de forma definitiva el contenedor del paso eliminado.\r\n    \/\/ Sin esto quedaria visible, porque ya no lo gestiona mostrarPaso().\r\n    function ocultarPasoExperiencias() {\r\n        document.querySelectorAll('.paso3-tus-experiencias').forEach(el => {\r\n            el.classList.remove('active', 'entering', 'exiting');\r\n            el.style.display = 'none';\r\n        });\r\n    }\r\n\r\n    \/**\r\n     * Reconecta \"Volver a Productos\" al paso 1.\r\n     *\r\n     * POR QUE UN LISTENER EN document CON CAPTURE\r\n     * El script de confirmacion de reserva ya tiene su propio handler en ese\r\n     * boton, que hace scrollIntoView() hacia '.elementor-element-717f167'.\r\n     * Ese contenedor NO EXISTE en la pagina (es un ID sobrante de un layout\r\n     * anterior), asi que cae al fallback document.body y no hace nada visible.\r\n     * Ademas el paso 1 esta en display:none, con lo cual ningun scroll sirve.\r\n     *\r\n     * No alcanza con agregar otro listener al boton: los listeners del mismo\r\n     * elemento se ejecutan en orden de registro, sin importar el flag capture.\r\n     * En cambio un listener de CAPTURA en document corre antes de llegar al\r\n     * boton, y stopPropagation() evita que el handler viejo se ejecute.\r\n     *\/\r\n    function conectarBotonVolver() {\r\n        document.addEventListener('click', function (ev) {\r\n            if (!ev.target || typeof ev.target.closest !== 'function') {\r\n                return;\r\n            }\r\n\r\n            const boton = ev.target.closest(SELECTOR_BOTON_VOLVER);\r\n\r\n            if (!boton) {\r\n                return;\r\n            }\r\n\r\n            ev.preventDefault();\r\n            ev.stopPropagation();\r\n\r\n            console.log('\ud83d\udd19 Volver a Productos -> paso 1');\r\n            mostrarPaso(1);\r\n        }, true);\r\n\r\n        console.log('\u2705 Bot\u00f3n \"Volver a Productos\" conectado al paso 1');\r\n    }\r\n\r\n    function limpiarComplementosObsoletos() {\r\n        try {\r\n            if (localStorage.getItem('selectedComplementos')) {\r\n                localStorage.removeItem('selectedComplementos');\r\n                console.log('\ud83e\uddf9 selectedComplementos residual eliminado');\r\n            }\r\n        } catch (e) {\r\n            console.warn('No se pudo limpiar selectedComplementos:', e);\r\n        }\r\n    }\r\n\r\n    \/\/ ===== SALTO DIRECTO AL CALENDARIO =====\r\n    \/\/ Se activa con sessionStorage.sothersIrAPaso = 'calendario'\r\n    \/\/ o con el parametro de URL ?paso=calendario\r\n    function resolverPasoInicial() {\r\n        let solicitado = null;\r\n\r\n        try {\r\n            solicitado = sessionStorage.getItem('sothersIrAPaso');\r\n            if (solicitado) {\r\n                sessionStorage.removeItem('sothersIrAPaso');\r\n            }\r\n        } catch (e) {\r\n            console.warn('sessionStorage no disponible:', e);\r\n        }\r\n\r\n        if (!solicitado) {\r\n            try {\r\n                solicitado = new URLSearchParams(window.location.search).get('paso');\r\n            } catch (e) {}\r\n        }\r\n\r\n        if (solicitado !== 'calendario') {\r\n            return 1;\r\n        }\r\n\r\n        if (!validarSeleccionProducto()) {\r\n            console.warn('\u26a0\ufe0f Salto al calendario pedido pero no hay producto. Se abre el paso 1.');\r\n            return 1;\r\n        }\r\n\r\n        const elementosCalendario = elementosPaso.get(PASO_CALENDARIO) || [];\r\n        if (!elementosCalendario.length) {\r\n            console.warn('\u26a0\ufe0f Contenedor del calendario no encontrado. Se abre el paso 1.');\r\n            return 1;\r\n        }\r\n\r\n        console.log('\u23e9 Salto directo al calendario');\r\n        return PASO_CALENDARIO;\r\n    }\r\n\r\n    \/\/ Red de seguridad: si algun selector del paso 1 borra el producto\r\n    \/\/ durante su inicializacion, devolvemos al usuario al paso 1.\r\n    function vigilarProductoEnCalendario() {\r\n        let intentos = 0;\r\n\r\n        const vigilante = setInterval(() => {\r\n            intentos++;\r\n\r\n            if (!validarSeleccionProducto()) {\r\n                clearInterval(vigilante);\r\n                console.warn('\u26a0\ufe0f El producto se perdio tras el salto al calendario. Volviendo al paso 1.');\r\n                mostrarPaso(1);\r\n                mostrarMensajeValidacion('Vuelve a seleccionar tu experiencia para continuar');\r\n                return;\r\n            }\r\n\r\n            if (intentos >= 6) {\r\n                clearInterval(vigilante);\r\n            }\r\n        }, 500);\r\n    }\r\n\r\n    function mapearElementosPaso() {\r\n        console.log('\ud83d\uddfa\ufe0f Mapeando elementos de cada paso...');\r\n        \r\n        pasos.forEach(paso => {\r\n            const elementos = document.querySelectorAll(paso.selector);\r\n            \r\n            if (elementos.length > 0) {\r\n                console.log(`\u2705 Paso ${paso.id} encontrado:`, elementos.length, 'elemento(s)');\r\n                elementosPaso.set(paso.id, Array.from(elementos));\r\n            } else {\r\n                console.warn(`\u26a0\ufe0f Paso ${paso.id} no encontrado con selector:`, paso.selector);\r\n                elementosPaso.set(paso.id, []);\r\n            }\r\n        });\r\n\r\n        \/\/ Agregar clase identificadora a cada elemento\r\n        elementosPaso.forEach((elementos, pasoId) => {\r\n            elementos.forEach(el => {\r\n                el.classList.add('sothers-step', `sothers-step-${pasoId}`);\r\n            });\r\n        });\r\n    }\r\n\r\n    function configurarEventos() {\r\n        console.log('\u2699\ufe0f Configurando eventos...');\r\n\r\n        \/\/ Interceptar botones de continuar existentes\r\n        pasos.forEach(paso => {\r\n            const botones = document.querySelectorAll(paso.botonContinuar);\r\n            \r\n            botones.forEach(boton => {\r\n                if (boton) {\r\n                    console.log(`\ud83d\udd18 Configurando bot\u00f3n para paso ${paso.id}:`, boton);\r\n                    \r\n                    \/\/ Clonar el bot\u00f3n para remover event listeners existentes\r\n                    const nuevoBoton = boton.cloneNode(true);\r\n                    boton.parentNode?.replaceChild(nuevoBoton, boton);\r\n                    \r\n                    \/\/ CORRECCI\u00d3N ESPEC\u00cdFICA PARA EL PASO DEL CALENDARIO\r\n                    if (paso.id === PASO_CALENDARIO) {\r\n                        nuevoBoton.addEventListener('click', function(e) {\r\n                            e.preventDefault();\r\n                            e.stopPropagation();\r\n                            console.log(`\ud83d\udd04 Click en bot\u00f3n continuar del paso ${paso.id}`);\r\n                            \r\n                            \/\/ Validar antes de avanzar\r\n                            if (!validarFechaHora()) {\r\n                                mostrarMensajeValidacion('Por favor selecciona fecha y hora antes de continuar');\r\n                                return;\r\n                            }\r\n                            \r\n                            \/\/ Validar que hay una reserva seleccionada\r\n                            if (!validarReservaSeleccionada()) {\r\n                                mostrarMensajeValidacion('Por favor selecciona una fecha y horario primero');\r\n                                return;\r\n                            }\r\n                            \r\n                            \/\/ Actualizar campos del formulario con los datos de la reserva\r\n                            actualizarCamposFormularioDesdeReserva();\r\n                            \r\n                            console.log('\u2705 Validaci\u00f3n exitosa, avanzando al paso de datos...');\r\n\r\n                            \/\/ Ejecutar onExit del paso del calendario\r\n                            if (paso.onExit) {\r\n                                paso.onExit();\r\n                            }\r\n\r\n                            \/\/ AVANZAR AL PASO DE DATOS PERSONALES\r\n                            mostrarPaso(PASO_CALENDARIO + 1);\r\n                        });\r\n                        \r\n                        \/\/ Ocultar el bot\u00f3n \"Confirmar Reserva\" del HTML personalizado\r\n                        setTimeout(() => {\r\n                            const btnConfirmarReserva = document.getElementById('btnConfirmarReserva');\r\n                            if (btnConfirmarReserva) {\r\n                                btnConfirmarReserva.style.display = 'none';\r\n                                console.log('\u2705 Bot\u00f3n Confirmar Reserva oculto');\r\n                            }\r\n\r\n                        }, 500);\r\n                        \r\n                    } else {\r\n                        \/\/ Para otros pasos, usar l\u00f3gica normal\r\n                        nuevoBoton.addEventListener('click', function(e) {\r\n                            e.preventDefault();\r\n                            e.stopPropagation();\r\n                            console.log(`\ud83d\udd04 Click en bot\u00f3n continuar del paso ${paso.id}`);\r\n                            siguientePaso();\r\n                        });\r\n                    }\r\n                }\r\n            });\r\n        });\r\n\r\n        \/\/ Crear botones de navegaci\u00f3n adicionales si es necesario\r\n        crearBotonesNavegacion();\r\n\r\n        \/\/ Event listeners para eventos del sistema existente\r\n        document.addEventListener('productoSeleccionado', () => {\r\n            console.log('\ud83c\udfaf Producto seleccionado, actualizando validaci\u00f3n...');\r\n            actualizarValidacionPaso(1);\r\n        });\r\n\r\n        \/\/ El listener de 'complementosActualizados' se elimino junto con el\r\n        \/\/ paso de experiencias: ya no hay complementos que validar.\r\n\r\n        document.addEventListener('horarioSeleccionado', () => {\r\n            console.log('\ud83d\udcc5 Horario seleccionado, actualizando validaci\u00f3n...');\r\n            actualizarValidacionPaso(PASO_CALENDARIO);\r\n        });\r\n    \r\n\r\n        \/\/ Teclas de navegaci\u00f3n\r\n        document.addEventListener('keydown', function(e) {\r\n            if (e.ctrlKey || e.metaKey) {\r\n                if (e.key === 'ArrowRight') {\r\n                    e.preventDefault();\r\n                    siguientePaso();\r\n                } else if (e.key === 'ArrowLeft') {\r\n                    e.preventDefault();\r\n                    pasoAnterior();\r\n                }\r\n            }\r\n        });\r\n    }\r\n    \r\n\r\n\r\n    function crearBotonesNavegacion() {\r\n        \/\/ Por ahora, usar los botones existentes del sistema\r\n        \/\/ En el futuro se puede implementar botones adicionales si es necesario\r\n    }\r\n\r\n    function mostrarPaso(numeroPaso, conAnimacion = true) {\r\n        console.log(`\ud83d\udd04 Mostrando paso ${numeroPaso}...`);\r\n\r\n        if (conAnimacion) {\r\n            mostrarLoading();\r\n        }\r\n\r\n        \/\/ Ocultar todos los pasos\r\n        elementosPaso.forEach((elementos, pasoId) => {\r\n            elementos.forEach(el => {\r\n                if (pasoId !== numeroPaso) {\r\n                    el.classList.remove('active', 'entering');\r\n\r\n                    if (conAnimacion) {\r\n                        el.classList.add('exiting');\r\n                        setTimeout(() => {\r\n                            el.style.display = 'none';\r\n                            el.classList.remove('exiting');\r\n                        }, 300);\r\n                    } else {\r\n                        \/\/ Sin animacion: ocultar en el acto. Diferirlo dejaba\r\n                        \/\/ los otros pasos visibles unos frames mas.\r\n                        el.style.display = 'none';\r\n                    }\r\n                }\r\n            });\r\n        });\r\n\r\n        \/\/ Mostrar paso actual\r\n        const mostrarPasoActual = () => {\r\n            const elementosActuales = elementosPaso.get(numeroPaso) || [];\r\n\r\n            elementosActuales.forEach(el => {\r\n                el.style.display = 'flex';\r\n                el.classList.add('active');\r\n\r\n                \/\/ La animacion de entrada solo cuando hay una transicion real.\r\n                \/\/ En la carga inicial producia un fade de 500ms que se percibia\r\n                \/\/ como parpadeo, aun llamando a mostrarPaso(1, false).\r\n                if (conAnimacion) {\r\n                    el.classList.add('entering');\r\n                    setTimeout(() => {\r\n                        el.classList.remove('entering');\r\n                    }, 500);\r\n                }\r\n            });\r\n\r\n            \/\/ Ejecutar callback onEnter del paso\r\n            const paso = pasos.find(p => p.id === numeroPaso);\r\n            if (paso && paso.onEnter) {\r\n                paso.onEnter();\r\n            }\r\n\r\n            \/* Scroll suave al inicio del paso\r\n            if (elementosActuales.length > 0) {\r\n                elementosActuales[0].scrollIntoView({ \r\n                    behavior: 'smooth', \r\n                    block: 'start' \r\n                });\r\n            }\r\n*\/\r\n            pasoActual = numeroPaso;\r\n            actualizarIndicadores();\r\n\r\n            if (conAnimacion) {\r\n                setTimeout(() => ocultarLoading(), 500);\r\n            }\r\n        };\r\n\r\n        if (conAnimacion) {\r\n            setTimeout(mostrarPasoActual, 400);\r\n        } else {\r\n            \/\/ Mismo tick que el ocultado: el navegador nunca pinta el estado\r\n            \/\/ intermedio en el que ningun paso esta visible.\r\n            mostrarPasoActual();\r\n        }\r\n    }\r\n\r\n    function siguientePaso() {\r\n        const paso = pasos.find(p => p.id === pasoActual);\r\n        \r\n        if (!paso) {\r\n            console.error('\u274c Paso actual no encontrado');\r\n            return;\r\n        }\r\n\r\n        console.log(`\ud83d\udd04 Intentando avanzar desde paso ${pasoActual}...`);\r\n\r\n        \/\/ Validar paso actual\r\n        if (paso.validacion && !paso.validacion()) {\r\n            console.log(`\u274c Validaci\u00f3n fallida para paso ${pasoActual}`);\r\n            mostrarMensajeValidacion(`Por favor completa todos los campos del paso: ${paso.nombre}`);\r\n            return;\r\n        }\r\n\r\n        \/\/ Ejecutar callback onExit\r\n        if (paso.onExit) {\r\n            paso.onExit();\r\n        }\r\n\r\n        \/\/ Avanzar al siguiente paso\r\n        if (pasoActual < pasos.length) {\r\n            mostrarPaso(pasoActual + 1);\r\n        } else {\r\n            console.log('\ud83c\udf89 Formulario completado');\r\n            completarFormulario();\r\n        }\r\n    }\r\n\r\n    function pasoAnterior() {\r\n        if (pasoActual > 1) {\r\n            console.log(`\ud83d\udd19 Retrocediendo al paso ${pasoActual - 1}...`);\r\n            mostrarPaso(pasoActual - 1);\r\n        } else {\r\n            console.log('\u2139\ufe0f Ya est\u00e1s en el primer paso');\r\n        }\r\n    }\r\n\r\n    function actualizarIndicadores() {\r\n        \/\/ Actualizar barra de progreso\r\n        const progreso = (pasoActual \/ pasos.length) * 100;\r\n        if (progressBar) {\r\n            progressBar.style.width = progreso + '%';\r\n        }\r\n\r\n        \/\/ Actualizar indicador de pasos\r\n        document.querySelectorAll('.step-indicator').forEach((indicator, index) => {\r\n            const stepNumber = index + 1;\r\n            \r\n            indicator.classList.remove('active', 'completed', 'pending');\r\n            \r\n            if (stepNumber < pasoActual) {\r\n                indicator.classList.add('completed');\r\n            } else if (stepNumber === pasoActual) {\r\n                indicator.classList.add('active');\r\n            } else {\r\n                indicator.classList.add('pending');\r\n            }\r\n        });\r\n\r\n        console.log(`\ud83d\udcca Indicadores actualizados - Paso ${pasoActual}\/${pasos.length} (${progreso.toFixed(0)}%)`);\r\n    }\r\n\r\n    function actualizarValidacionPaso(numeroPaso) {\r\n        if (numeroPaso === pasoActual) {\r\n            const paso = pasos.find(p => p.id === numeroPaso);\r\n            if (paso && paso.validacion) {\r\n                const esValido = paso.validacion();\r\n                console.log(`\ud83d\udd0d Validaci\u00f3n paso ${numeroPaso}:`, esValido ? '\u2705 V\u00e1lido' : '\u274c Inv\u00e1lido');\r\n            }\r\n        }\r\n    }\r\n\r\n    \/\/ Funciones de validaci\u00f3n\r\n    function validarSeleccionProducto() {\r\n        \/\/ Verificar que hay un producto seleccionado\r\n        const productoGuardado = localStorage.getItem('selectedProducto');\r\n        const tieneProducto = productoGuardado && JSON.parse(productoGuardado)?.data?.name;\r\n        \r\n        console.log('\ud83d\udd0d Validando selecci\u00f3n de producto:', tieneProducto ? '\u2705' : '\u274c');\r\n        return !!tieneProducto;\r\n    }\r\n\r\n    function validarComplementos() {\r\n        \/\/ Los complementos son opcionales, siempre es v\u00e1lido\r\n        console.log('\ud83d\udd0d Validando complementos: \u2705 (opcional)');\r\n        return true;\r\n    }\r\n\r\n    function validarResumen() {\r\n        \/\/ Verificar que hay al menos un producto en el resumen\r\n        const tieneProducto = validarSeleccionProducto();\r\n        console.log('\ud83d\udd0d Validando resumen:', tieneProducto ? '\u2705' : '\u274c');\r\n        return tieneProducto;\r\n    }\r\n\r\n    function validarFechaHora() {\r\n        \/\/ Verificar que hay fecha, hora y profesional seleccionado\r\n        let esValido = false;\r\n\r\n        \/\/ Verificar desde datosReservaCompleta global\r\n        if (window.datosReservaCompleta) {\r\n            esValido = !!(\r\n                window.datosReservaCompleta.fecha &&\r\n                window.datosReservaCompleta.hora &&\r\n                window.datosReservaCompleta.profesional\r\n            );\r\n        }\r\n\r\n        \/\/ Verificar desde campos del formulario como fallback\r\n        if (!esValido) {\r\n            const fecha = document.getElementById('form-field-reserva_fecha')?.value;\r\n            const hora = document.getElementById('form-field-reserva_inicio')?.value;\r\n            const profesional = document.getElementById('form-field-reserva_profesional')?.value;\r\n            \r\n            esValido = !!(fecha && hora && profesional);\r\n        }\r\n\r\n        \/\/ Verificar horario seleccionado visualmente\r\n        if (!esValido) {\r\n            const horarioSeleccionado = document.querySelector('.horario-btn.seleccionado');\r\n            esValido = !!horarioSeleccionado;\r\n        }\r\n\r\n        console.log('\ud83d\udd0d Validando fecha y hora:', esValido ? '\u2705' : '\u274c');\r\n        return esValido;\r\n    }\r\n\r\n    function validarDatosPersonales() {\r\n        \/\/ Verificar campos requeridos del formulario\r\n        const camposRequeridos = [\r\n            'form-field-name', \/\/ RUT\r\n            'form-field-field_49f8b85', \/\/ Nombre\r\n            'form-field-field_99b781e', \/\/ Apellido Paterno\r\n            'form-field-email' \/\/ Email\r\n        ];\r\n\r\n        let todosCompletos = true;\r\n\r\n        camposRequeridos.forEach(id => {\r\n            const campo = document.getElementById(id);\r\n            if (!campo || !campo.value.trim()) {\r\n                todosCompletos = false;\r\n            }\r\n        });\r\n\r\n        \/\/ Verificar sexo seleccionado\r\n        const sexoSeleccionado = document.querySelector('input[name=\"form_fields[field_c93ad9b]\"]:checked');\r\n        if (!sexoSeleccionado) {\r\n            todosCompletos = false;\r\n        }\r\n\r\n        console.log('\ud83d\udd0d Validando datos personales:', todosCompletos ? '\u2705' : '\u274c');\r\n        return todosCompletos;\r\n    }\r\n\r\n    function mostrarMensajeValidacion(mensaje) {\r\n        \/\/ Remover mensaje anterior si existe\r\n        const mensajeAnterior = document.querySelector('.sothers-validation-message');\r\n        if (mensajeAnterior) {\r\n            mensajeAnterior.remove();\r\n        }\r\n\r\n        \/\/ Crear nuevo mensaje\r\n        const mensajeDiv = document.createElement('div');\r\n        mensajeDiv.className = 'sothers-validation-message';\r\n        mensajeDiv.innerHTML = `\r\n            <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n                <span style=\"font-size: 20px;\">\u26a0\ufe0f<\/span>\r\n                <span>${mensaje}<\/span>\r\n                <button onclick=\"this.parentElement.parentElement.remove()\" \r\n                        style=\"background: none; border: none; color: white; font-size: 18px; cursor: pointer; margin-left: auto;\">\r\n                    \u00d7\r\n                <\/button>\r\n            <\/div>\r\n        `;\r\n\r\n        document.body.appendChild(mensajeDiv);\r\n\r\n        \/\/ Mostrar con animaci\u00f3n\r\n        setTimeout(() => mensajeDiv.classList.add('show'), 100);\r\n\r\n        \/\/ Auto-remover despu\u00e9s de 5 segundos\r\n        setTimeout(() => {\r\n            mensajeDiv.classList.remove('show');\r\n            setTimeout(() => mensajeDiv.remove(), 300);\r\n        }, 5000);\r\n    }\r\n\r\n    function mostrarLoading() {\r\n        if (loadingOverlay) {\r\n            loadingOverlay.style.display = 'flex';\r\n        }\r\n    }\r\n\r\n    function ocultarLoading() {\r\n        if (loadingOverlay) {\r\n            loadingOverlay.style.display = 'none';\r\n        }\r\n    }\r\n\r\nfunction completarFormulario() {\r\n    console.log('\ud83c\udf89 Formulario multi-paso completado');\r\n    \r\n    \/\/ Esperar un poco por si la funci\u00f3n se est\u00e1 cargando\r\n    setTimeout(() => {\r\n        if (typeof window.procesarEnvioReserva === 'function') {\r\n            console.log('\u2705 Llamando a procesarEnvioReserva...');\r\n            window.procesarEnvioReserva();\r\n        } else {\r\n            console.error('\u274c procesarEnvioReserva no est\u00e1 disponible, intentando fallback...');\r\n            \r\n            \/\/ Verificar si al menos tenemos el formulario y los datos\r\n            const formulario = document.querySelector('.elementor-form');\r\n            if (formulario) {\r\n                console.log('\ud83d\udd04 Disparando evento submit del formulario...');\r\n                formulario.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));\r\n            } else {\r\n                console.error('\u274c No se encontr\u00f3 el formulario para fallback');\r\n                \/\/ ANTES llamaba a mostrarError(), que no existe en este script.\r\n                \/\/ Solo se alcanzaba si faltaba el formulario, asi que el\r\n                \/\/ ReferenceError quedaba oculto. mostrarMensajeValidacion() si existe.\r\n                mostrarMensajeValidacion('Error interno: No se puede procesar la reserva. Recarga la p\u00e1gina e intenta de nuevo.');\r\n            }\r\n        }\r\n    }, 100); \/\/ Peque\u00f1o delay para permitir carga de scripts\r\n}\r\n\r\n    \/\/ FUNCIONES ADICIONALES PARA EL PASO 4\r\n    function validarReservaSeleccionada() {\r\n        \/\/ Verificar datos en datosReservaCompleta\r\n        if (window.datosReservaCompleta) {\r\n            const tieneReserva = window.datosReservaCompleta.fecha && \r\n                               window.datosReservaCompleta.hora && \r\n                               window.datosReservaCompleta.profesional &&\r\n                               window.datosReservaCompleta.agenda;\r\n            \r\n            if (tieneReserva) {\r\n                console.log('\u2705 Reserva v\u00e1lida encontrada:', {\r\n                    fecha: window.datosReservaCompleta.fecha,\r\n                    hora: window.datosReservaCompleta.hora,\r\n                    profesional: window.datosReservaCompleta.profesional\r\n                });\r\n                return true;\r\n            }\r\n        }\r\n\r\n        \/\/ Verificar si hay un horario seleccionado visualmente\r\n        const horarioSeleccionado = document.querySelector('.horario-btn.seleccionado');\r\n        if (horarioSeleccionado) {\r\n            console.log('\u2705 Horario seleccionado encontrado en DOM');\r\n            return true;\r\n        }\r\n\r\n        \/\/ Verificar variables globales alternativas\r\n        if (window.reservaSeleccionada && window.reservaSeleccionada.fecha) {\r\n            console.log('\u2705 Reserva encontrada en reservaSeleccionada');\r\n            return true;\r\n        }\r\n\r\n        console.log('\u274c No se encontr\u00f3 una reserva seleccionada');\r\n        return false;\r\n    }\r\n\r\n    function actualizarCamposFormularioDesdeReserva() {\r\n        console.log('\ud83d\udd04 Actualizando campos del formulario desde reserva...');\r\n        \r\n        \/\/ Usar datos de datosReservaCompleta si est\u00e1n disponibles\r\n        if (window.datosReservaCompleta) {\r\n            const datos = window.datosReservaCompleta;\r\n            \r\n            \/\/ Actualizar campos ocultos del formulario\r\n            const campos = {\r\n                'form-field-reserva_fecha': datos.fecha,\r\n                'form-field-reserva_inicio': datos.hora,\r\n                'form-field-reserva_profesional': datos.profesional,\r\n                'form-field-reserva_agenda': datos.agenda,\r\n                'form-field-reserva_tratamiento': datos.uuidTratamiento,\r\n                'form-field-reserva_servicio': datos.producto?.name || datos.servicio\r\n            };\r\n\r\n            Object.entries(campos).forEach(([id, valor]) => {\r\n                const campo = document.getElementById(id);\r\n                if (campo && valor) {\r\n                    campo.value = valor;\r\n                    console.log(`\u2705 ${id} actualizado: ${valor}`);\r\n                }\r\n            });\r\n        }\r\n        \r\n        console.log('\u2705 Campos del formulario actualizados desde reserva');\r\n    }\r\n\r\n    \/\/ Funciones globales para control manual\r\n    window.sothersMultiStep = {\r\n        siguientePaso: siguientePaso,\r\n        pasoAnterior: pasoAnterior,\r\n        irAPaso: (numero) => mostrarPaso(numero),\r\n        pasoActual: () => pasoActual,\r\n        validarPasoActual: () => {\r\n            const paso = pasos.find(p => p.id === pasoActual);\r\n            return paso?.validacion ? paso.validacion() : true;\r\n        },\r\n        debug: () => {\r\n            console.log('\ud83d\udd0d Estado del sistema multi-paso:');\r\n            console.log('  Paso actual:', pasoActual);\r\n            console.log('  Total pasos:', pasos.length);\r\n            console.log('  Elementos mapeados:', Object.fromEntries(elementosPaso));\r\n            return { pasoActual, totalPasos: pasos.length, elementos: elementosPaso };\r\n        }\r\n    };\r\n\r\n    \/\/ ===== HACER FUNCIONES GLOBALMENTE ACCESIBLES =====\r\n    window.validarSeleccionProducto = validarSeleccionProducto;\r\n    window.validarComplementos = validarComplementos;\r\n    window.validarResumen = validarResumen;\r\n    window.validarFechaHora = validarFechaHora;\r\n    window.validarDatosPersonales = validarDatosPersonales;\r\n    window.validarReservaSeleccionada = validarReservaSeleccionada;\r\n    window.actualizarCamposFormularioDesdeReserva = actualizarCamposFormularioDesdeReserva;\r\n\twindow.pasoActual = pasoActual\r\n\twindow.siguientePaso = siguientePaso\r\n    \r\n    console.log('\u2705 Sistema multi-paso Sothers configurado');\r\n    console.log('\ud83d\udca1 Controles disponibles en window.sothersMultiStep');\r\n    console.log('\u2328\ufe0f Usa Ctrl+\u2192 y Ctrl+\u2190 para navegar entre pasos');\r\n    console.log('\u2705 Funciones de validaci\u00f3n expuestas globalmente');\r\n});\r\n\r\n\r\n \r\n    <\/script>\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fff38d9 elementor-widget elementor-widget-html\" data-id=\"fff38d9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"es\">\r\n<head>\r\n    <meta charset=\"UTF-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n    <title>Sistema Gift Card - Sothers Spa<\/title>\r\n    <style>\r\n        \/* Estilos para el estado seleccionado del Gift Card *\/\r\n        .regalar-container {\r\n            transition: all 0.3s ease;\r\n            cursor: pointer;\r\n            border-radius: 3px;\r\n        }\r\n        \r\n        .regalar-container:hover {\r\n            background-color: rgba(49, 152, 158, 0.05);\r\n        }\r\n        \r\n        .regalar-container.selected {\r\n            background-color: rgba(49, 152, 158, 0.1);\r\n            border: 2px solid #31989E;\r\n            box-shadow: 0 4px 15px rgba(49, 152, 158, 0.2);\r\n        }\r\n        \r\n        .regalar-container.selected .elementor-heading-title {\r\n            color: #31989E !important;\r\n            font-weight: bold;\r\n        }\r\n        \r\n        .regalar-container.selected .elementor-icon {\r\n            color: #31989E;\r\n            transform: scale(1.1);\r\n        }\r\n        \r\n        \/* Indicador visual de selecci\u00f3n *\/\r\n        .gift-card-indicator {\r\n            position: absolute;\r\n            top: 10px;\r\n            right: 10px;\r\n            background: #31989E;\r\n            color: white;\r\n            border-radius: 50%;\r\n            width: 24px;\r\n            height: 24px;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n            font-size: 14px;\r\n            font-weight: bold;\r\n            opacity: 0;\r\n            transition: opacity 0.3s ease;\r\n            pointer-events: none;\r\n        }\r\n        \r\n        .regalar-container.selected .gift-card-indicator {\r\n            opacity: 1;\r\n        }\r\n        \r\n        \/* Animaci\u00f3n de pulso para el contenedor seleccionado *\/\r\n        .regalar-container.selected {\r\n            animation: giftCardPulse 2s infinite;\r\n        }\r\n        \r\n        @keyframes giftCardPulse {\r\n            0% { box-shadow: 0 4px 15px rgba(49, 152, 158, 0.2); }\r\n            50% { box-shadow: 0 4px 20px rgba(49, 152, 158, 0.4); }\r\n            100% { box-shadow: 0 4px 15px rgba(49, 152, 158, 0.2); }\r\n        }\r\n        \r\n        \/* Estilos para el toast de notificaci\u00f3n *\/\r\n        .gift-card-toast {\r\n            position: fixed;\r\n            bottom: 20px;\r\n            right: 20px;\r\n            background: #31989E;\r\n            color: white;\r\n            padding: 15px 20px;\r\n            border-radius: 8px;\r\n            box-shadow: 0 4px 15px rgba(49, 152, 158, 0.3);\r\n            z-index: 10000;\r\n            font-family: 'Josefin Sans', sans-serif;\r\n            font-weight: 400;\r\n            transform: translateX(100%);\r\n            transition: transform 0.3s ease;\r\n            max-width: 300px;\r\n        }\r\n        \r\n        .gift-card-toast.show {\r\n            transform: translateX(0);\r\n        }\r\n        \r\n        .gift-card-toast .close-toast {\r\n            background: none;\r\n            border: none;\r\n            color: white;\r\n            font-size: 18px;\r\n            cursor: pointer;\r\n            float: right;\r\n            margin-left: 10px;\r\n            padding: 0;\r\n            line-height: 1;\r\n        }\r\n    <\/style>\r\n<\/head>\r\n<body>\r\n    <script>\r\n\/\/ Sistema de Gift Card para Sothers Spa\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    console.log('SISTEMA GIFT CARD INICIADO');\r\n    \r\n    \/\/ Variables de estado\r\n    let giftCardSeleccionado = false;\r\n    let productoActualSeleccionado = null;\r\n    \r\n    \/\/ Elementos del DOM\r\n    const regalarContainer = document.querySelector('.regalar-container');\r\n    const botonContinuar = document.querySelector('.paso1-boton-continuar .elementor-button');\r\n    \r\n    \/\/ Verificar que los elementos existan\r\n    if (!regalarContainer) {\r\n        console.error('\u274c No se encontr\u00f3 el contenedor de Gift Card');\r\n        return;\r\n    }\r\n    \r\n    if (!botonContinuar) {\r\n        console.error('\u274c No se encontr\u00f3 el bot\u00f3n continuar');\r\n        return;\r\n    }\r\n    \r\n    \/\/ Inicializar sistema\r\n    inicializarSistemaGiftCard();\r\n    \r\n    function inicializarSistemaGiftCard() {\r\n        console.log('\ud83d\ude80 Inicializando sistema Gift Card...');\r\n        \r\n        \/\/ Hacer el contenedor clickeable\r\n        configurarContenedorGiftCard();\r\n        \r\n        \/\/ Configurar el bot\u00f3n continuar\r\n        configurarBotonContinuar();\r\n        \r\n        \/\/ Escuchar eventos de selecci\u00f3n de productos\r\n        escucharEventosProductos();\r\n        \r\n        \/\/ Agregar indicador visual\r\n        agregarIndicadorVisual();\r\n        \r\n        console.log('\u2705 Sistema Gift Card inicializado');\r\n    }\r\n    \r\n    function configurarContenedorGiftCard() {\r\n        \/\/ Agregar cursor pointer\r\n        regalarContainer.style.cursor = 'pointer';\r\n        regalarContainer.style.position = 'relative';\r\n        \r\n        \/\/ Event listener para click\r\n        regalarContainer.addEventListener('click', function(e) {\r\n            \/\/ Evitar que el click se propague si viene de un elemento interno\r\n            e.stopPropagation();\r\n            \r\n            toggleGiftCardSelection();\r\n        });\r\n        \r\n        console.log('\ud83d\uddb1\ufe0f Contenedor Gift Card configurado como clickeable');\r\n    }\r\n    \r\n    function toggleGiftCardSelection() {\r\n        giftCardSeleccionado = !giftCardSeleccionado;\r\n        \r\n        if (giftCardSeleccionado) {\r\n            activarGiftCard();\r\n        } else {\r\n            desactivarGiftCard();\r\n        }\r\n        \r\n        \/\/ Actualizar el comportamiento del bot\u00f3n continuar\r\n        actualizarBotonContinuar();\r\n        \r\n        \/\/ Guardar estado en localStorage\r\n        localStorage.setItem('giftCardSeleccionado', JSON.stringify(giftCardSeleccionado));\r\n        \r\n        console.log('\ud83c\udf81 Gift Card', giftCardSeleccionado ? 'activado' : 'desactivado');\r\n    }\r\n    \r\n    function activarGiftCard() {\r\n        regalarContainer.classList.add('selected');\r\n        \r\n        \/\/ Mostrar notificaci\u00f3n\r\n        mostrarToast('Al continuar ser\u00e1s redirigido para configurar la tarjeta de regalo.');\r\n        \r\n        console.log('\u2705 Gift Card activado');\r\n    }\r\n    \r\n    function desactivarGiftCard() {\r\n        regalarContainer.classList.remove('selected');\r\n        \r\n        \/\/ Mostrar notificaci\u00f3n\r\n        mostrarToast('Continuar\u00e1s con el proceso normal de reserva.');\r\n        \r\n        console.log('\u274c Gift Card desactivado');\r\n    }\r\n    \r\n    function configurarBotonContinuar() {\r\n        \/\/ Clonar el bot\u00f3n para remover event listeners existentes\r\n        const nuevoBoton = botonContinuar.cloneNode(true);\r\n        botonContinuar.parentNode.replaceChild(nuevoBoton, botonContinuar);\r\n        \r\n        \/\/ Agregar nuevo event listener\r\n        nuevoBoton.addEventListener('click', function(e) {\r\n            e.preventDefault();\r\n            e.stopPropagation();\r\n            \r\n            manejarClickContinuar();\r\n        });\r\n        \r\n        console.log('\ud83d\udd18 Bot\u00f3n continuar reconfigurado');\r\n    }\r\n    \r\n    function manejarClickContinuar() {\r\n        console.log('\ud83d\udd04 Click en bot\u00f3n continuar...');\r\n        \r\n        if (giftCardSeleccionado) {\r\n            \/\/ Modo Gift Card: redirigir a producto con popup de gift card\r\n            redirigirAGiftCard();\r\n        } else {\r\n            \/\/ Modo normal: continuar con el flujo multi-paso\r\n            continuarFlujoNormal();\r\n        }\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ NUEVA FUNCIONALIDAD - REDIRECCI\u00d3N A GIFT CARD\r\n    \/\/ ====================================\r\n    \r\n    function redirigirAGiftCard() {\r\n        console.log('\ud83c\udf81 Sistema Gift Card - Preparando redirecci\u00f3n...');\r\n        \r\n        \/\/ Verificar que hay un producto seleccionado\r\n        if (!productoActualSeleccionado) {\r\n            mostrarError('Por favor selecciona un producto antes de continuar');\r\n            return;\r\n        }\r\n        \r\n        console.log('\ud83d\udce6 Producto seleccionado para Gift Card:', productoActualSeleccionado);\r\n        \r\n        \/\/ Construir la URL del producto\r\n        const productId = productoActualSeleccionado.id;\r\n        const productSlug = productoActualSeleccionado.slug;\r\n        \r\n        let giftUrl;\r\n        \r\n        if (productSlug) {\r\n            \/\/ Usar el slug del producto (m\u00e1s limpio)\r\n            giftUrl = `\/producto\/${productSlug}\/`;\r\n        } else {\r\n            \/\/ Fallback usando el ID\r\n            giftUrl = `\/?p=${productId}`;\r\n        }\r\n        \r\n        console.log('\ud83c\udf81 Sistema Gift Card - Redirigiendo a:', giftUrl);\r\n        \r\n        \/\/ Guardar en sessionStorage que queremos abrir el popup de gift card\r\n        try {\r\n            sessionStorage.setItem('openGiftCardPopup', 'true');\r\n            sessionStorage.setItem('giftCardProductId', productId);\r\n        } catch (e) {\r\n            console.warn('Sistema Gift Card - No se pudo guardar en sessionStorage:', e);\r\n        }\r\n        \r\n        \/\/ Mostrar loading antes de redirigir\r\n        mostrarLoadingGiftCard();\r\n        \r\n        \/\/ Redirigir despu\u00e9s de un breve delay para que se vea el loading\r\n        setTimeout(() => {\r\n            window.location.href = giftUrl;\r\n        }, 1500);\r\n    }\r\n    \r\n    function mostrarLoadingGiftCard() {\r\n        const loading = document.createElement('div');\r\n        loading.id = 'gift-card-loading';\r\n        loading.style.cssText = `\r\n            position: fixed;\r\n            top: 0;\r\n            left: 0;\r\n            width: 100%;\r\n            height: 100%;\r\n            background: rgba(255, 255, 255, 0.95);\r\n            display: flex;\r\n            flex-direction: column;\r\n            align-items: center;\r\n            justify-content: center;\r\n            z-index: 10001;\r\n            font-family: 'Josefin Sans', sans-serif;\r\n        `;\r\n        \r\n        loading.innerHTML = `\r\n            <div style=\"\r\n                width: 50px;\r\n                height: 50px;\r\n                border: 4px solid #f0f0f0;\r\n                border-top: 4px solid #31989E;\r\n                border-radius: 50%;\r\n                animation: spin 1s linear infinite;\r\n                margin-bottom: 20px;\r\n            \"><\/div>\r\n            <h3 style=\"color: #31989E; margin: 0; font-weight: 600;\">\r\n                Preparando Gift Card...\r\n            <\/h3>\r\n            <p style=\"color: #666; margin: 10px 0 0 0;\">\r\n                Redirigiendo al formulario de tarjeta de regalo\r\n            <\/p>\r\n            <p style=\"color: #888; margin: 5px 0 0 0; font-size: 14px;\">\r\n                <strong>${productoActualSeleccionado ? productoActualSeleccionado.name : 'Producto'}<\/strong>\r\n            <\/p>\r\n        `;\r\n        \r\n        \/\/ Agregar keyframes para la animaci\u00f3n si no existen\r\n        if (!document.getElementById('spin-animation')) {\r\n            const style = document.createElement('style');\r\n            style.id = 'spin-animation';\r\n            style.textContent = `\r\n                @keyframes spin {\r\n                    0% { transform: rotate(0deg); }\r\n                    100% { transform: rotate(360deg); }\r\n                }\r\n            `;\r\n            document.head.appendChild(style);\r\n        }\r\n        \r\n        document.body.appendChild(loading);\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ FIN NUEVA FUNCIONALIDAD\r\n    \/\/ ====================================\r\n    \r\n    function continuarFlujoNormal() {\r\n        console.log('\u27a1\ufe0f Continuando con flujo normal...');\r\n        \r\n        \/\/ Verificar que hay un producto seleccionado\r\n        if (!window.validarSeleccionProducto || !window.validarSeleccionProducto()) {\r\n            mostrarError('Por favor selecciona un producto antes de continuar');\r\n            return;\r\n        }\r\n        \r\n        \/\/ Continuar con el siguiente paso del sistema multi-paso\r\n        if (window.siguientePaso) {\r\n            window.siguientePaso();\r\n        } else {\r\n            console.error('\u274c Sistema multi-paso no disponible');\r\n            mostrarError('Error interno: No se puede continuar. Recarga la p\u00e1gina e intenta de nuevo.');\r\n        }\r\n    }\r\n    \r\n    function escucharEventosProductos() {\r\n        \/\/ Escuchar cuando se selecciona un producto\r\n        document.addEventListener('productoSeleccionado', function(e) {\r\n            console.log('\ud83d\udccb Producto seleccionado para Gift Card:', e.detail.productoData.name);\r\n            productoActualSeleccionado = e.detail.productoData;\r\n            actualizarBotonContinuar();\r\n        });\r\n        \r\n        \/\/ Escuchar cuando se limpia la selecci\u00f3n de producto\r\n        document.addEventListener('productoLimpiado', function() {\r\n            console.log('\ud83e\uddf9 Producto limpiado en Gift Card');\r\n            productoActualSeleccionado = null;\r\n            actualizarBotonContinuar();\r\n        });\r\n        \r\n        \/\/ Escuchar limpiezas globales\r\n        document.addEventListener('limpiarTodasLasSelecciones', function() {\r\n            console.log('\ud83e\uddf9 Limpieza global - reseteando Gift Card');\r\n            giftCardSeleccionado = false;\r\n            productoActualSeleccionado = null;\r\n            desactivarGiftCard();\r\n            actualizarBotonContinuar();\r\n            localStorage.removeItem('giftCardSeleccionado');\r\n        });\r\n    }\r\n    \r\n    function actualizarBotonContinuar() {\r\n        const boton = document.querySelector('.paso1-boton-continuar .elementor-button');\r\n        if (!boton) return;\r\n        \r\n        const span = boton.querySelector('.elementor-button-text');\r\n        if (!span) return;\r\n        \r\n        if (giftCardSeleccionado) {\r\n            \/\/ Modo Gift Card - Redirigir\r\n            span.textContent = 'CONFIGURAR GIFT CARD';\r\n            boton.style.background = '#31989E';\r\n            boton.style.boxShadow = '0 4px 15px rgba(49, 152, 158, 0.3)';\r\n            \r\n            \/\/ Deshabilitar si no hay producto seleccionado\r\n            if (!productoActualSeleccionado) {\r\n                boton.style.opacity = '0.5';\r\n                boton.style.cursor = 'not-allowed';\r\n            } else {\r\n                boton.style.opacity = '1';\r\n                boton.style.cursor = 'pointer';\r\n            }\r\n        } else {\r\n            \/\/ Modo normal\r\n            span.textContent = 'CONTINUAR';\r\n            boton.style.background = '';\r\n            boton.style.boxShadow = '';\r\n            boton.style.opacity = '';\r\n            boton.style.cursor = '';\r\n        }\r\n    }\r\n    \r\n    function agregarIndicadorVisual() {\r\n        \/\/ Crear indicador de selecci\u00f3n\r\n        const indicador = document.createElement('div');\r\n        indicador.className = 'gift-card-indicator';\r\n        indicador.innerHTML = '\u2713';\r\n        \r\n        regalarContainer.appendChild(indicador);\r\n        \r\n        console.log('\ud83d\udc41\ufe0f Indicador visual agregado');\r\n    }\r\n    \r\n    function mostrarToast(mensaje) {\r\n        \/\/ Remover toast anterior si existe\r\n        const toastAnterior = document.querySelector('.gift-card-toast');\r\n        if (toastAnterior) {\r\n            toastAnterior.remove();\r\n        }\r\n        \r\n        \/\/ Crear nuevo toast\r\n        const toast = document.createElement('div');\r\n        toast.className = 'gift-card-toast';\r\n        toast.innerHTML = `\r\n            <button class=\"close-toast\" onclick=\"this.parentElement.remove()\">\u00d7<\/button>\r\n            ${mensaje}\r\n        `;\r\n        \r\n        document.body.appendChild(toast);\r\n        \r\n        \/\/ Mostrar con animaci\u00f3n\r\n        setTimeout(() => toast.classList.add('show'), 100);\r\n        \r\n        \/\/ Auto-remover despu\u00e9s de 5 segundos\r\n        setTimeout(() => {\r\n            if (toast.parentElement) {\r\n                toast.classList.remove('show');\r\n                setTimeout(() => toast.remove(), 300);\r\n            }\r\n        }, 5000);\r\n    }\r\n    \r\n    function mostrarError(mensaje) {\r\n        console.error('\u274c', mensaje);\r\n        mostrarToast(`\u274c ${mensaje}`);\r\n    }\r\n    \r\n    \/\/ Funci\u00f3n para recuperar estado previo\r\n    function recuperarEstadoPrevio() {\r\n        const estadoGuardado = localStorage.getItem('giftCardSeleccionado');\r\n        if (estadoGuardado) {\r\n            try {\r\n                const estado = JSON.parse(estadoGuardado);\r\n                if (estado) {\r\n                    giftCardSeleccionado = true;\r\n                    activarGiftCard();\r\n                    actualizarBotonContinuar();\r\n                }\r\n            } catch (e) {\r\n                console.log('\u26a0\ufe0f Error recuperando estado Gift Card:', e);\r\n            }\r\n        }\r\n    }\r\n    \r\n    \/\/ Recuperar estado previo al cargar\r\n    setTimeout(recuperarEstadoPrevio, 500);\r\n    \r\n    \/\/ Funciones globales para control externo\r\n    window.giftCardSystem = {\r\n        activar: () => {\r\n            giftCardSeleccionado = true;\r\n            activarGiftCard();\r\n            actualizarBotonContinuar();\r\n        },\r\n        desactivar: () => {\r\n            giftCardSeleccionado = false;\r\n            desactivarGiftCard();\r\n            actualizarBotonContinuar();\r\n        },\r\n        toggle: toggleGiftCardSelection,\r\n        isActivo: () => giftCardSeleccionado,\r\n        getProductoSeleccionado: () => productoActualSeleccionado\r\n    };\r\n    \r\n    console.log('\u2705 Sistema Gift Card configurado con redirecci\u00f3n');\r\n    console.log('\ud83d\udca1 Controles disponibles en window.giftCardSystem');\r\n});\r\n<\/script>\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bc8756a elementor-widget elementor-widget-html\" data-id=\"bc8756a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\r\n\/\/ ====================================\r\n\/\/ GA4 - BEGIN_CHECKOUT EVENT\r\n\/\/ ====================================\r\n\r\n(function() {\r\n    'use strict';\r\n    \r\n    console.log('\ud83d\ude80 Iniciando GA4 begin_checkout (versi\u00f3n simplificada)...');\r\n    \r\n    let eventoYaEnviado = false;\r\n    \r\n    \/\/ ====================================\r\n    \/\/ VALIDAR QUE ESTAMOS EN PASO 5\r\n    \/\/ ====================================\r\n    \r\n    function validarPaso5Visible() {\r\n        const paso5 = document.querySelector('.paso5-ingresa-tus-datos');\r\n        \r\n        if (!paso5) {\r\n            return false;\r\n        }\r\n        \r\n        \/\/ El paso 5 debe estar visible\r\n        const paso5Visible = (\r\n            paso5.style.display !== 'none' &&\r\n            paso5.offsetParent !== null &&\r\n            paso5.offsetHeight > 0\r\n        );\r\n        \r\n        if (!paso5Visible) {\r\n            return false;\r\n        }\r\n        \r\n        \/\/ El paso 4 debe estar OCULTO\r\n        const paso4 = document.querySelector('.paso4-selecciona-tu-fecha-y-hora');\r\n        if (paso4) {\r\n            const paso4Visible = (\r\n                paso4.style.display !== 'none' &&\r\n                paso4.offsetParent !== null &&\r\n                paso4.offsetHeight > 0\r\n            );\r\n            \r\n            if (paso4Visible) {\r\n                console.log('\u23ed\ufe0f Paso 4 todav\u00eda visible, esperando...');\r\n                return false;\r\n            }\r\n        }\r\n        \r\n        \/\/ Verificar que existe el formulario en paso 5\r\n        const formulario = paso5.querySelector('.elementor-form');\r\n        if (!formulario) {\r\n            console.log('\u26a0\ufe0f No se encontr\u00f3 formulario en paso 5');\r\n            return false;\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ OBTENER PRODUCTOS\r\n    \/\/ ====================================\r\n    \r\n    function obtenerProductosParaCheckout() {\r\n        const productos = [];\r\n        \r\n        \/\/ Producto principal\r\n        const productoGuardado = localStorage.getItem('selectedProducto');\r\n        if (productoGuardado) {\r\n            try {\r\n                const productoData = JSON.parse(productoGuardado);\r\n                const producto = productoData.data;\r\n                \r\n                if (producto && producto.id) {\r\n                    let precio = 0;\r\n                    if (producto.sale_price) {\r\n                        precio = parseFloat(producto.sale_price);\r\n                    } else if (producto.regular_price) {\r\n                        precio = parseFloat(producto.regular_price);\r\n                    } else if (producto.price) {\r\n                        precio = parseFloat(producto.price);\r\n                    }\r\n                    \r\n                    productos.push({\r\n                        item_id: String(producto.id),\r\n                        item_name: producto.name || 'Producto sin nombre',\r\n                        price: precio,\r\n                        currency: 'CLP',\r\n                        quantity: 1,\r\n                        system: 'Reservo',\r\n                        item_category: producto.category || '',\r\n                        item_list_name: 'Producto Principal'\r\n                    });\r\n                }\r\n            } catch (e) {\r\n                console.error('\u274c Error parseando producto principal:', e);\r\n            }\r\n        }\r\n        \r\n        \/\/ Complementarios\r\n        const complementosGuardados = localStorage.getItem('selectedComplementos');\r\n        if (complementosGuardados) {\r\n            try {\r\n                const complementos = JSON.parse(complementosGuardados);\r\n                \r\n                if (Array.isArray(complementos) && complementos.length > 0) {\r\n                    complementos.forEach((complementoData) => {\r\n                        const complemento = complementoData.data;\r\n                        \r\n                        if (complemento && complemento.id) {\r\n                            let precio = 0;\r\n                            if (complemento.sale_price) {\r\n                                precio = parseFloat(complemento.sale_price);\r\n                            } else if (complemento.regular_price) {\r\n                                precio = parseFloat(complemento.regular_price);\r\n                            } else if (complemento.price) {\r\n                                precio = parseFloat(complemento.price);\r\n                            }\r\n                            \r\n                            productos.push({\r\n                                item_id: String(complemento.id),\r\n                                item_name: complemento.name || 'Complemento sin nombre',\r\n                                price: precio,\r\n                                currency: 'CLP',\r\n                                quantity: 1,\r\n                                system: 'Reservo',\r\n                                item_category: complemento.category || '',\r\n                                item_list_name: 'Producto Complementario'\r\n                            });\r\n                        }\r\n                    });\r\n                }\r\n            } catch (e) {\r\n                console.error('\u274c Error parseando complementarios:', e);\r\n            }\r\n        }\r\n        \r\n        return productos;\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ ENVIAR EVENTO\r\n    \/\/ ====================================\r\n    \r\n    function sendGA4BeginCheckoutEvent() {\r\n        console.log('\ud83d\udce4 [BEGIN_CHECKOUT] Intentando enviar evento...');\r\n        \r\n        \/\/ Validar paso 5\r\n        if (!validarPaso5Visible()) {\r\n            console.log('\u26d4 [BEGIN_CHECKOUT] Paso 5 no est\u00e1 visible correctamente');\r\n            return;\r\n        }\r\n        \r\n        \/\/ Evitar duplicados\r\n        if (eventoYaEnviado) {\r\n            console.log('\u26a0\ufe0f [BEGIN_CHECKOUT] Evento ya enviado');\r\n            return;\r\n        }\r\n        \r\n        \/\/ Validar dataLayer\r\n        if (typeof window.dataLayer === 'undefined') {\r\n            console.warn('\u26a0\ufe0f [BEGIN_CHECKOUT] dataLayer no disponible');\r\n            return;\r\n        }\r\n        \r\n        \/\/ Obtener productos\r\n        const productos = obtenerProductosParaCheckout();\r\n        \r\n        if (productos.length === 0) {\r\n            console.warn('\u26a0\ufe0f [BEGIN_CHECKOUT] No hay productos');\r\n            return;\r\n        }\r\n        \r\n        \/\/ Calcular total\r\n        const valorTotal = productos.reduce((sum, p) => sum + p.price, 0);\r\n        \r\n        \/\/ Limpiar y enviar\r\n        window.dataLayer.push({ ecommerce: null });\r\n        \r\n        const eventData = {\r\n            event: 'begin_checkout',\r\n            ecommerce: {\r\n                currency: 'CLP',\r\n                value: valorTotal,\r\n                items: productos\r\n            }\r\n        };\r\n        \r\n        window.dataLayer.push(eventData);\r\n        \r\n        eventoYaEnviado = true;\r\n        \r\n        console.log('\u2705\u2705\u2705 [BEGIN_CHECKOUT] EVENTO ENVIADO:', {\r\n            productos: productos.length,\r\n            total: valorTotal,\r\n            items: productos.map(p => p.item_name)\r\n        });\r\n        \r\n        console.log('\ud83d\udce6 [BEGIN_CHECKOUT] DataLayer:', eventData);\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ OBSERVER SIMPLIFICADO\r\n    \/\/ ====================================\r\n    \r\n    function inicializarObserver() {\r\n        console.log('\ud83d\udd0d [BEGIN_CHECKOUT] Buscando paso 5...');\r\n        \r\n        \/\/ Buscar el paso 5\r\n        const paso5 = document.querySelector('.paso5-ingresa-tus-datos');\r\n        \r\n        if (!paso5) {\r\n            console.log('\u26a0\ufe0f [BEGIN_CHECKOUT] Paso 5 no encontrado, reintentando en 1s...');\r\n            setTimeout(inicializarObserver, 1000);\r\n            return;\r\n        }\r\n        \r\n        console.log('\u2705 [BEGIN_CHECKOUT] Paso 5 encontrado');\r\n        \r\n        \/\/ Observer en paso 5\r\n        const observer = new MutationObserver(() => {\r\n            const esVisible = validarPaso5Visible();\r\n            \r\n            if (esVisible && !eventoYaEnviado) {\r\n                console.log('\ud83c\udfaf [BEGIN_CHECKOUT] Paso 5 ahora visible');\r\n                \r\n                \/\/ Peque\u00f1o delay para asegurar que todo est\u00e1 listo\r\n                setTimeout(() => {\r\n                    sendGA4BeginCheckoutEvent();\r\n                }, 500);\r\n            }\r\n        });\r\n        \r\n        \/\/ Observar cambios en style\r\n        observer.observe(paso5, {\r\n            attributes: true,\r\n            attributeFilter: ['style'],\r\n            childList: false,\r\n            subtree: false\r\n        });\r\n        \r\n        console.log('\u2705 [BEGIN_CHECKOUT] Observer configurado');\r\n        \r\n        \/\/ Verificaci\u00f3n inmediata por si ya est\u00e1 visible\r\n        if (validarPaso5Visible()) {\r\n            console.log('\u26a1 [BEGIN_CHECKOUT] Paso 5 ya visible al iniciar');\r\n            setTimeout(() => {\r\n                sendGA4BeginCheckoutEvent();\r\n            }, 500);\r\n        }\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ POLLING DE RESPALDO\r\n    \/\/ ====================================\r\n    \r\n    function inicializarPolling() {\r\n        let ultimoEstado = false;\r\n        \r\n        setInterval(() => {\r\n            const esVisible = validarPaso5Visible();\r\n            \r\n            \/\/ Si cambi\u00f3 a visible\r\n            if (esVisible && !ultimoEstado && !eventoYaEnviado) {\r\n                console.log('\ud83c\udfaf [BEGIN_CHECKOUT] Polling detect\u00f3 paso 5 visible');\r\n                \r\n                setTimeout(() => {\r\n                    sendGA4BeginCheckoutEvent();\r\n                }, 500);\r\n            }\r\n            \r\n            ultimoEstado = esVisible;\r\n        }, 1000); \/\/ Cada 1 segundo\r\n        \r\n        console.log('\u2705 [BEGIN_CHECKOUT] Polling configurado (cada 1s)');\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ FUNCIONES DE DEBUG\r\n    \/\/ ====================================\r\n    \r\n    window.testGA4BeginCheckout = function() {\r\n        console.log('\ud83e\uddea [TEST] Probando begin_checkout...');\r\n        eventoYaEnviado = false;\r\n        \r\n        console.log('Estado del paso 5:', validarPaso5Visible());\r\n        \r\n        const productos = obtenerProductosParaCheckout();\r\n        console.log('Productos:', productos.length);\r\n        \r\n        if (productos.length > 0) {\r\n            sendGA4BeginCheckoutEvent();\r\n        }\r\n    };\r\n    \r\n    window.debugPaso5 = function() {\r\n        console.log('\ud83d\udd0d [DEBUG] Estado del paso 5');\r\n        console.log('\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550');\r\n        \r\n        const paso4 = document.querySelector('.paso4-selecciona-tu-fecha-y-hora');\r\n        const paso5 = document.querySelector('.paso5-ingresa-tus-datos');\r\n        \r\n        if (paso4) {\r\n            console.log('Paso 4:');\r\n            console.log('  display:', paso4.style.display);\r\n            console.log('  offsetParent:', paso4.offsetParent !== null);\r\n            console.log('  offsetHeight:', paso4.offsetHeight);\r\n            console.log('  VISIBLE:', paso4.style.display !== 'none' && paso4.offsetParent !== null);\r\n        }\r\n        \r\n        if (paso5) {\r\n            console.log('\\nPaso 5:');\r\n            console.log('  display:', paso5.style.display);\r\n            console.log('  offsetParent:', paso5.offsetParent !== null);\r\n            console.log('  offsetHeight:', paso5.offsetHeight);\r\n            console.log('  VISIBLE:', paso5.style.display !== 'none' && paso5.offsetParent !== null);\r\n            \r\n            const formulario = paso5.querySelector('.elementor-form');\r\n            console.log('  formulario:', formulario ? 'Existe' : 'NO EXISTE');\r\n        }\r\n        \r\n        console.log('\\nValidaci\u00f3n paso 5:', validarPaso5Visible());\r\n        console.log('Evento enviado:', eventoYaEnviado);\r\n        console.log('window.pasoActual:', window.pasoActual);\r\n        \r\n        const productos = obtenerProductosParaCheckout();\r\n        console.log('\\nProductos:', productos.length);\r\n        productos.forEach((p, i) => {\r\n            console.log(`  ${i + 1}. ${p.item_name} - $${p.price}`);\r\n        });\r\n    };\r\n    \r\n    window.resetBeginCheckout = function() {\r\n        console.log('\ud83d\udd04 [RESET] Reseteando begin_checkout...');\r\n        eventoYaEnviado = false;\r\n        console.log('\u2705 Listo para enviar de nuevo');\r\n    };\r\n    \r\n    window.forzarEnvioBeginCheckout = function() {\r\n        console.log('\u26a1 [FORZAR] Enviando begin_checkout...');\r\n        eventoYaEnviado = false;\r\n        sendGA4BeginCheckoutEvent();\r\n    };\r\n    \r\n    \/\/ ====================================\r\n    \/\/ INICIALIZACI\u00d3N\r\n    \/\/ ====================================\r\n    \r\n    function inicializar() {\r\n        console.log('\ud83d\udd27 [BEGIN_CHECKOUT] Inicializando...');\r\n        \r\n        setTimeout(() => {\r\n            inicializarObserver();\r\n            inicializarPolling();\r\n            \r\n            console.log('\u2705 [BEGIN_CHECKOUT] Sistema listo');\r\n            console.log('\ud83d\udca1 Comandos disponibles:');\r\n            console.log('   - debugPaso5()');\r\n            console.log('   - testGA4BeginCheckout()');\r\n            console.log('   - forzarEnvioBeginCheckout()');\r\n            console.log('   - resetBeginCheckout()');\r\n        }, 1000);\r\n    }\r\n    \r\n    if (document.readyState === 'loading') {\r\n        document.addEventListener('DOMContentLoaded', inicializar);\r\n    } else {\r\n        inicializar();\r\n    }\r\n    \r\n    console.log('\u2705 [BEGIN_CHECKOUT] Script cargado');\r\n    \r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e04f522 elementor-widget elementor-widget-html\" data-id=\"e04f522\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\r\n\/\/ ====================================\r\n\/\/ GA4 - GUARDAR DATOS PARA PURCHASE\r\n\/\/ ====================================\r\n\r\n\r\n(function() {\r\n    'use strict';\r\n    \r\n    console.log('\ud83d\udcbe Inicializando sistema de guardado para purchase...');\r\n    \r\n    \/\/ ====================================\r\n    \/\/ FUNCI\u00d3N PARA OBTENER PRODUCTOS\r\n    \/\/ ====================================\r\n    \r\n    function obtenerProductosActuales() {\r\n        const productos = [];\r\n        \r\n        \/\/ Producto principal\r\n        const productoGuardado = localStorage.getItem('selectedProducto');\r\n        if (productoGuardado) {\r\n            try {\r\n                const productoData = JSON.parse(productoGuardado);\r\n                const producto = productoData.data;\r\n                \r\n                if (producto && producto.id) {\r\n                    let precio = 0;\r\n                    if (producto.sale_price) {\r\n                        precio = parseFloat(producto.sale_price);\r\n                    } else if (producto.regular_price) {\r\n                        precio = parseFloat(producto.regular_price);\r\n                    } else if (producto.price) {\r\n                        precio = parseFloat(producto.price);\r\n                    }\r\n                    \r\n                    productos.push({\r\n                        item_id: String(producto.id),\r\n                        item_name: producto.name || 'Producto sin nombre',\r\n                        price: precio,\r\n                        currency: 'CLP',\r\n                        quantity: 1,\r\n                        system: 'Reservo',\r\n                        item_category: producto.category || '',\r\n                        item_list_name: 'Producto Principal'\r\n                    });\r\n                }\r\n            } catch (e) {\r\n                console.error('\u274c Error parseando producto principal:', e);\r\n            }\r\n        }\r\n        \r\n        \/\/ Complementarios\r\n        const complementosGuardados = localStorage.getItem('selectedComplementos');\r\n        if (complementosGuardados) {\r\n            try {\r\n                const complementos = JSON.parse(complementosGuardados);\r\n                \r\n                if (Array.isArray(complementos) && complementos.length > 0) {\r\n                    complementos.forEach((complementoData) => {\r\n                        const complemento = complementoData.data;\r\n                        \r\n                        if (complemento && complemento.id) {\r\n                            let precio = 0;\r\n                            if (complemento.sale_price) {\r\n                                precio = parseFloat(complemento.sale_price);\r\n                            } else if (complemento.regular_price) {\r\n                                precio = parseFloat(complemento.regular_price);\r\n                            } else if (complemento.price) {\r\n                                precio = parseFloat(complemento.price);\r\n                            }\r\n                            \r\n                            productos.push({\r\n                                item_id: String(complemento.id),\r\n                                item_name: complemento.name || 'Complemento sin nombre',\r\n                                price: precio,\r\n                                currency: 'CLP',\r\n                                quantity: 1,\r\n                                system: 'Reservo',\r\n                                item_category: complemento.category || '',\r\n                                item_list_name: 'Producto Complementario'\r\n                            });\r\n                        }\r\n                    });\r\n                }\r\n            } catch (e) {\r\n                console.error('\u274c Error parseando complementarios:', e);\r\n            }\r\n        }\r\n        \r\n        return productos;\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ FUNCI\u00d3N PARA GUARDAR DATOS DEL PURCHASE\r\n    \/\/ ====================================\r\n    \r\n    function guardarDatosPurchase() {\r\n        console.log('\ud83d\udcbe [PURCHASE] Guardando datos para purchase...');\r\n        \r\n        const productos = obtenerProductosActuales();\r\n        \r\n        if (productos.length === 0) {\r\n            console.warn('\u26a0\ufe0f [PURCHASE] No hay productos para guardar');\r\n            return false;\r\n        }\r\n        \r\n        \/\/ Calcular valor total\r\n        const valorTotal = productos.reduce((sum, p) => sum + p.price, 0);\r\n        \r\n        \/\/ Generar ID de transacci\u00f3n \u00fanico\r\n        const transactionId = 'TXN_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);\r\n        \r\n        \/\/ Datos completos del purchase\r\n        const datosPurchase = {\r\n            transaction_id: transactionId,\r\n            currency: 'CLP',\r\n            value: valorTotal,\r\n            items: productos,\r\n            timestamp: new Date().toISOString(),\r\n            affiliation: 'Reservo Online'\r\n        };\r\n        \r\n        \/\/ Guardar en localStorage\r\n        try {\r\n            localStorage.setItem('ga4_purchase_data', JSON.stringify(datosPurchase));\r\n            console.log('\u2705 [PURCHASE] Datos guardados:', {\r\n                transaction_id: transactionId,\r\n                productos: productos.length,\r\n                valor_total: valorTotal\r\n            });\r\n            return true;\r\n        } catch (e) {\r\n            console.error('\u274c [PURCHASE] Error guardando datos:', e);\r\n            return false;\r\n        }\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ DETECTAR ENV\u00cdO DEL FORMULARIO\r\n    \/\/ ====================================\r\n    \r\n    function interceptarEnvioFormulario() {\r\n        const paso5 = document.querySelector('.paso5-ingresa-tus-datos');\r\n        \r\n        if (!paso5) {\r\n            console.log('\u26a0\ufe0f [PURCHASE] Paso 5 no encontrado, reintentando...');\r\n            setTimeout(interceptarEnvioFormulario, 1000);\r\n            return;\r\n        }\r\n        \r\n        const formulario = paso5.querySelector('.elementor-form');\r\n        \r\n        if (!formulario) {\r\n            console.log('\u26a0\ufe0f [PURCHASE] Formulario no encontrado, reintentando...');\r\n            setTimeout(interceptarEnvioFormulario, 1000);\r\n            return;\r\n        }\r\n        \r\n        console.log('\u2705 [PURCHASE] Formulario encontrado, interceptando env\u00edo...');\r\n        \r\n        \/\/ Interceptar submit del formulario\r\n        formulario.addEventListener('submit', function(e) {\r\n            console.log('\ud83d\udce4 [PURCHASE] Formulario enviado, guardando datos...');\r\n            guardarDatosPurchase();\r\n        });\r\n        \r\n        \/\/ Tambi\u00e9n interceptar clicks en el bot\u00f3n de env\u00edo\r\n        const botonSubmit = formulario.querySelector('button[type=\"submit\"]');\r\n        if (botonSubmit) {\r\n            botonSubmit.addEventListener('click', function(e) {\r\n                console.log('\ud83d\uddb1\ufe0f [PURCHASE] Click en bot\u00f3n submit, guardando datos...');\r\n                \/\/ Peque\u00f1o delay para asegurar que se guarda antes de salir\r\n                setTimeout(() => {\r\n                    guardarDatosPurchase();\r\n                }, 100);\r\n            });\r\n        }\r\n        \r\n        console.log('\u2705 [PURCHASE] Interceptor configurado');\r\n    }\r\n    \r\n    \/\/ ====================================\r\n    \/\/ FUNCIONES DE TESTING\r\n    \/\/ ====================================\r\n    \r\n    window.testGuardarPurchase = function() {\r\n        console.log('\ud83e\uddea [TEST] Guardando datos de purchase...');\r\n        const resultado = guardarDatosPurchase();\r\n        \r\n        if (resultado) {\r\n            const datos = JSON.parse(localStorage.getItem('ga4_purchase_data'));\r\n            console.log('\ud83d\udce6 Datos guardados:', datos);\r\n        }\r\n    };\r\n    \r\n    window.verDatosPurchaseGuardados = function() {\r\n        const datos = localStorage.getItem('ga4_purchase_data');\r\n        \r\n        if (datos) {\r\n            console.log('\ud83d\udce6 [PURCHASE] Datos guardados en localStorage:');\r\n            console.log(JSON.parse(datos));\r\n        } else {\r\n            console.log('\u26a0\ufe0f [PURCHASE] No hay datos guardados');\r\n        }\r\n    };\r\n    \r\n    window.limpiarDatosPurchase = function() {\r\n        localStorage.removeItem('ga4_purchase_data');\r\n        console.log('\ud83d\uddd1\ufe0f [PURCHASE] Datos eliminados');\r\n    };\r\n    \r\n    \/\/ ====================================\r\n    \/\/ INICIALIZACI\u00d3N\r\n    \/\/ ====================================\r\n    \r\n    function inicializar() {\r\n        console.log('\ud83d\udd27 [PURCHASE] Inicializando guardado de datos...');\r\n        \r\n        setTimeout(() => {\r\n            interceptarEnvioFormulario();\r\n            \r\n            console.log('\u2705 [PURCHASE] Sistema de guardado listo');\r\n            console.log('\ud83d\udca1 Comandos disponibles:');\r\n            console.log('   - testGuardarPurchase()');\r\n            console.log('   - verDatosPurchaseGuardados()');\r\n            console.log('   - limpiarDatosPurchase()');\r\n        }, 1000);\r\n    }\r\n    \r\n    if (document.readyState === 'loading') {\r\n        document.addEventListener('DOMContentLoaded', inicializar);\r\n    } else {\r\n        inicializar();\r\n    }\r\n    \r\n    console.log('\u2705 [PURCHASE] Script de guardado cargado');\r\n    \r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>SOLICITA TU RESERVA SELECCIONA TU SERVICIO \u00c1rea Selecciona tu servicio Selecciona un \u00e1rea primero Selecciona tu experencia Selecciona un servicio primero \u00bfQuieres regalar esta experiencia? Regalar como Gift Card O si lo prefieres Escr\u00edbenos para Reservar CONTINUAR COMPLEMENTA TU EXPERIENCIA Elige entre nuestros exclusivos masajes dise\u00f1ados para aliviar tensiones, revitalizar tu piel y brindarte una [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-25747","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Acompa\u00f1amiento de Reserva<\/title>\n<meta name=\"description\" content=\"Selecciona los servicios que deseas reservar, nuestro Acompa\u00f1amiento de Reserva te ayudara a personalizar y agilizar tu experiencia.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/sparoysothers.cl\/en\/acompanamiento-de-reserva\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Acompa\u00f1amiento de Reserva\" \/>\n<meta property=\"og:description\" content=\"Selecciona los servicios que deseas reservar, nuestro Acompa\u00f1amiento de Reserva te ayudara a personalizar y agilizar tu experiencia.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/sparoysothers.cl\/en\/acompanamiento-de-reserva\/\" \/>\n<meta property=\"og:site_name\" content=\"SPA &amp; WELLNESS Roy Sothers\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/sparoysothers\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-13T14:20:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png\" \/>\n\t<meta property=\"og:image:width\" content=\"520\" \/>\n\t<meta property=\"og:image:height\" content=\"580\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/\",\"url\":\"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/\",\"name\":\"Acompa\u00f1amiento de Reserva\",\"isPartOf\":{\"@id\":\"https:\/\/sparoysothers.cl\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png\",\"datePublished\":\"2025-08-25T15:09:42+00:00\",\"dateModified\":\"2026-08-13T14:20:27+00:00\",\"description\":\"Selecciona los servicios que deseas reservar, nuestro Acompa\u00f1amiento de Reserva te ayudara a personalizar y agilizar tu experiencia.\",\"breadcrumb\":{\"@id\":\"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#primaryimage\",\"url\":\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png\",\"contentUrl\":\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\/\/sparoysothers.cl\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Acompa\u00f1amiento de Reserva\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/sparoysothers.cl\/#website\",\"url\":\"https:\/\/sparoysothers.cl\/\",\"name\":\"Spa & Wellness Roy Sothers\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/sparoysothers.cl\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/sparoysothers.cl\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/sparoysothers.cl\/#organization\",\"name\":\"Spa & Wellness Roy Sothers\",\"url\":\"https:\/\/sparoysothers.cl\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/sparoysothers.cl\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/06\/Logo-Sothers-Color@2x.png\",\"contentUrl\":\"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/06\/Logo-Sothers-Color@2x.png\",\"width\":796,\"height\":216,\"caption\":\"Spa & Wellness Roy Sothers\"},\"image\":{\"@id\":\"https:\/\/sparoysothers.cl\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/sparoysothers\",\"https:\/\/www.instagram.com\/sparoysothers\/#\",\"https:\/\/www.youtube.com\/@sparoysothers12425\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Acompa\u00f1amiento de Reserva","description":"Selecciona los servicios que deseas reservar, nuestro Acompa\u00f1amiento de Reserva te ayudara a personalizar y agilizar tu experiencia.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/sparoysothers.cl\/en\/acompanamiento-de-reserva\/","og_locale":"en_US","og_type":"article","og_title":"Acompa\u00f1amiento de Reserva","og_description":"Selecciona los servicios que deseas reservar, nuestro Acompa\u00f1amiento de Reserva te ayudara a personalizar y agilizar tu experiencia.","og_url":"https:\/\/sparoysothers.cl\/en\/acompanamiento-de-reserva\/","og_site_name":"SPA &amp; WELLNESS Roy Sothers","article_publisher":"https:\/\/www.facebook.com\/sparoysothers","article_modified_time":"2026-08-13T14:20:27+00:00","og_image":[{"width":520,"height":580,"url":"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/","url":"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/","name":"Acompa\u00f1amiento de Reserva","isPartOf":{"@id":"https:\/\/sparoysothers.cl\/#website"},"primaryImageOfPage":{"@id":"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#primaryimage"},"image":{"@id":"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#primaryimage"},"thumbnailUrl":"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png","datePublished":"2025-08-25T15:09:42+00:00","dateModified":"2026-08-13T14:20:27+00:00","description":"Selecciona los servicios que deseas reservar, nuestro Acompa\u00f1amiento de Reserva te ayudara a personalizar y agilizar tu experiencia.","breadcrumb":{"@id":"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#primaryimage","url":"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png","contentUrl":"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/07\/exp1@2x.png"},{"@type":"BreadcrumbList","@id":"https:\/\/sparoysothers.cl\/acompanamiento-de-reserva\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/sparoysothers.cl\/"},{"@type":"ListItem","position":2,"name":"Acompa\u00f1amiento de Reserva"}]},{"@type":"WebSite","@id":"https:\/\/sparoysothers.cl\/#website","url":"https:\/\/sparoysothers.cl\/","name":"Spa & Wellness Roy Sothers","description":"","publisher":{"@id":"https:\/\/sparoysothers.cl\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/sparoysothers.cl\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/sparoysothers.cl\/#organization","name":"Spa & Wellness Roy Sothers","url":"https:\/\/sparoysothers.cl\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sparoysothers.cl\/#\/schema\/logo\/image\/","url":"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/06\/Logo-Sothers-Color@2x.png","contentUrl":"https:\/\/sparoysothers.cl\/wp-content\/uploads\/2025\/06\/Logo-Sothers-Color@2x.png","width":796,"height":216,"caption":"Spa & Wellness Roy Sothers"},"image":{"@id":"https:\/\/sparoysothers.cl\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/sparoysothers","https:\/\/www.instagram.com\/sparoysothers\/#","https:\/\/www.youtube.com\/@sparoysothers12425"]}]}},"_links":{"self":[{"href":"https:\/\/sparoysothers.cl\/en\/wp-json\/wp\/v2\/pages\/25747","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sparoysothers.cl\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sparoysothers.cl\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sparoysothers.cl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sparoysothers.cl\/en\/wp-json\/wp\/v2\/comments?post=25747"}],"version-history":[{"count":84,"href":"https:\/\/sparoysothers.cl\/en\/wp-json\/wp\/v2\/pages\/25747\/revisions"}],"predecessor-version":[{"id":32961,"href":"https:\/\/sparoysothers.cl\/en\/wp-json\/wp\/v2\/pages\/25747\/revisions\/32961"}],"wp:attachment":[{"href":"https:\/\/sparoysothers.cl\/en\/wp-json\/wp\/v2\/media?parent=25747"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}