/* ========================================================================== MAPEO DE NODOS CENTRALES CON CADA MODAL ========================================================================== */ const NODE_MODAL_MAP = { p_top: "modal-ide-excellence", p_bottom: "modal-ide-digital", p_left: "modal-ide-academy", p_right: "modal-ide-projects" }; /* ========================================================================== FUNCIONES GLOBALES DE CONTROL ========================================================================== */ function openModal(modalId) { const modal = document.getElementById(modalId); if (!modal) return; modal.classList.add("is-active"); document.body.style.overflow = "hidden"; const scrollArea = modal.querySelector(".ide-modal-scroll"); if (scrollArea) scrollArea.scrollTop = 0; } function closeModal(modalOrId) { const modal = typeof modalOrId === "string" ? document.getElementById(modalOrId) : modalOrId; if (!modal) return; modal.classList.remove("is-active"); document.body.style.overflow = ""; } /* ========================================================================== EVENTO CLICK EN EL CANVAS (Abre el modal correspondiente a cada nodo) ========================================================================== */ canvas.addEventListener("click", (e) => { const { x, y } = getCanvasCoordinates(e); for (const [nodeId, modalId] of Object.entries(NODE_MODAL_MAP)) { const node = nodes.find(n => n.id === nodeId); if (node && Math.hypot(node.x - x, node.y - y) <= node.radius) { openModal(modalId); break; } } }); /* ========================================================================== INICIALIZACIÓN DE EVENTOS UNIVERSALES PARA TODOS LOS MODALES ========================================================================== */ document.addEventListener("DOMContentLoaded", () => { // 1. Cualquier botón con [data-modal-target] abre su modal asignado document.querySelectorAll("[data-modal-target]").forEach(btn => { btn.addEventListener("click", () => { const targetId = btn.getAttribute("data-modal-target"); openModal(targetId); }); }); // 2. Todos los modales gestionan cierre por botón (X) o clic fuera document.querySelectorAll(".ide-modal-backdrop").forEach(modal => { // Botón X const closeBtn = modal.querySelector(".ide-modal-close"); if (closeBtn) { closeBtn.addEventListener("click", () => closeModal(modal)); } // Clic en el fondo oscuro modal.addEventListener("click", (e) => { if (e.target === modal) closeModal(modal); }); // Control del hint de scroll individual para cada modal const scrollArea = modal.querySelector(".ide-modal-scroll"); const scrollHint = modal.querySelector(".ide-scroll-hint"); if (scrollArea && scrollHint) { scrollArea.addEventListener("scroll", () => { const isAtBottom = scrollArea.scrollHeight - scrollArea.scrollTop - scrollArea.clientHeight < 40; if (isAtBottom) { scrollHint.classList.add("is-hidden"); } else { scrollHint.classList.remove("is-hidden"); } }); } }); // 3. Tecla Escape cierra cualquier modal que esté abierto document.addEventListener("keydown", (e) => { if (e.key === "Escape") { const activeModal = document.querySelector(".ide-modal-backdrop.is-active"); if (activeModal) closeModal(activeModal); } }); });