diff --git a/assets/img/FOTO TEAM.jpg b/assets/img/FOTO TEAM.jpg new file mode 100644 index 0000000..3c6c4ca Binary files /dev/null and b/assets/img/FOTO TEAM.jpg differ diff --git a/assets/img/ide-insights.png b/assets/img/ide-insights.png new file mode 100644 index 0000000..584622d Binary files /dev/null and b/assets/img/ide-insights.png differ diff --git a/assets/img/ide-insights2.png b/assets/img/ide-insights2.png new file mode 100644 index 0000000..de5c284 Binary files /dev/null and b/assets/img/ide-insights2.png differ diff --git a/css/faq.css b/css/faq.css new file mode 100644 index 0000000..9ba5814 --- /dev/null +++ b/css/faq.css @@ -0,0 +1,129 @@ +/* ========================================================================== + ACORDEÓN DE PREGUNTAS FRECUENTES (FAQ) + ========================================================================== */ + +/* Contenedor centralizado para lectura óptima */ +.faq-accordion-container { + max-width: 820px; + margin: 0 auto; + display: flex; + flex-direction: column; + gap: 0.85rem; +} + +/* Tarjeta de cada pregunta */ +.faq-item { + background: rgba(255, 255, 255, 0.025); + border: 1px solid var(--ide-primary-line); + border-radius: 12px; + overflow: hidden; + transition: border-color 0.25s ease, background-color 0.25s ease; +} + +.faq-item:hover { + background: var(--ide-accent-bg); + border-color: rgba(255, 255, 255, 0.16); +} + +.faq-item[open] { + background: rgba(255, 255, 255, 0.04); + border-color: var(--ide-primary-light); +} + +/* Cabecera / Trigger */ +.faq-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1.25rem; + padding: 1.25rem 1.5rem; + cursor: pointer; + user-select: none; + list-style: none; /* Elimina la flecha estándar del navegador */ +} + +/* Ocultar el marcador nativo en navegadores WebKit */ +.faq-header::-webkit-details-marker { + display: none; +} + +/* Texto de la pregunta */ +.faq-question { + font-size: 1.05rem; + font-weight: 600; + color: var(--text-body); + line-height: 1.4; + transition: color 0.2s ease; +} + +.faq-item[open] .faq-question { + color: var(--ide-primary-light); +} + +/* Icono / Flecha */ +.faq-icon { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.05); + color: var(--text-main); + transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), background-color 0.2s ease, color 0.2s ease; +} + +.faq-item:hover .faq-icon { + background: rgba(255, 255, 255, 0.1); + color: var(--text-inverse); +} + +/* Rotación de la flecha al abrir */ +.faq-item[open] .faq-icon { + transform: rotate(180deg); + background: var(--ide-primary-light); + color: #0b1118; +} + +/* Contenido de la respuesta */ +.faq-content { + padding: 0 1.5rem 1.35rem 1.5rem; + animation: faq-fade-in 0.25s ease-out; +} + +.faq-content p { + margin: 0; + font-size: 0.92rem; + line-height: 1.65; + color: var(--text-muted, var(--text-main)); +} + +.faq-content strong { + color: var(--text-muted); +} + +/* Animación de apertura */ +@keyframes faq-fade-in { + from { + opacity: 0; + transform: translateY(-6px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Ajustes en pantallas móviles */ +@media (max-width: 640px) { + .faq-header { + padding: 1.1rem 1.2rem; + } + .faq-question { + font-size: 0.95rem; + } + .faq-content { + padding: 0 1.2rem 1.15rem 1.2rem; + } +} \ No newline at end of file diff --git a/css/modal.css b/css/modal.css new file mode 100644 index 0000000..9ab0211 --- /dev/null +++ b/css/modal.css @@ -0,0 +1,423 @@ +/* ========================================================================== + MODAL: CONTENEDOR & BACKDROP + ========================================================================== */ +.ide-modal-backdrop { + position: fixed; + inset: 0; + z-index: 99999; + display: flex; + align-items: center; + justify-content: center; + padding: 1.25rem; + background-color: var(--ide-accent-soft); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + opacity: 0; + visibility: hidden; + pointer-events: none; + transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1), + visibility 0.3s cubic-bezier(0.16, 1, 0.3, 1); +} + +.ide-modal-backdrop.is-active { + opacity: 1; + visibility: visible; + pointer-events: auto; +} + +.ide-modal-container { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + max-width: 780px; + max-height: 88vh; + background-color: var(--bg-card-alt); + border: 1px solid var(--ide-primary-line); + border-radius: 16px; + box-shadow: var(--shadow-lg); + color: var(--text-main); + overflow: hidden; + transform: translateY(20px) scale(0.98); + transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); +} + +.ide-modal-backdrop.is-active .ide-modal-container { + transform: translateY(0) scale(1); +} + +.ide-modal-close { + position: absolute; + top: 1.25rem; + right: 1.25rem; + z-index: 10; + display: flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + background: rgba(255, 255, 255, 0.06); + border: 1px solid var(--ide-primary-line); + border-radius: 50%; + color: var(--text-main); + cursor: pointer; + transition: all 0.2s ease; +} + +.ide-modal-close:hover { + background: rgba(255, 255, 255, 0.15); + color: #ffffff; + transform: rotate(90deg); +} + +/* ========================================================================== + SCROLLBAR LIMPIO (SIN BOTONES / FLECHAS) + ========================================================================== */ +.ide-modal-body-wrapper { + position: relative; + flex: 1 1 auto; + overflow: hidden; +} + +.ide-modal-scroll { + padding: 2.5rem 2.25rem 1.5rem 2.25rem; + max-height: calc(88vh - 75px); + overflow-y: auto; + overscroll-behavior: contain; + scrollbar-width: thin; + scrollbar-color: var(--ide-accent-soft) transparent; +} + +.ide-modal-scroll::-webkit-scrollbar-button { + display: none !important; + width: 0 !important; + height: 0 !important; +} + +.ide-modal-scroll::-webkit-scrollbar { + width: 6px; +} + +.ide-modal-scroll::-webkit-scrollbar-track { + background: transparent; + margin: 6px 0; +} + +.ide-modal-scroll::-webkit-scrollbar-thumb { + background-color: rgba(255, 255, 255, 0.18); + border-radius: 999px; + transition: background-color 0.2s ease; +} + +.ide-modal-scroll:hover::-webkit-scrollbar-thumb { + background-color: var(--ide-primary); +} + +/* ========================================================================== + ESTRUCTURA Y TIPOGRAFÍA DEL CONTENIDO + ========================================================================== */ +.ide-modal-header { + margin-bottom: 1.5rem; +} + +.ide-modal-pill { + display: inline-block; + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: #ffffff; + padding: 0.35rem 0.85rem; + border-radius: 20px; + margin-bottom: 0.75rem; +} +.project .ide-modal-pill { + background-color: var(--ide-projects); +} +.excellence .ide-modal-pill { + background-color: var(--ide-excellence); +} +.digital .ide-modal-pill { + background-color: var(--ide-digital); +} +.ide-modal-title { + font-size: 1.85rem; + font-weight: 800; + color: var(--text-main); + margin: 0 0 0.4rem 0; + line-height: 1.2; +} + +.ide-modal-tagline { + font-size: 1.15rem; + font-weight: 500; + color: var(--ide-primary-light); + margin: 0; +} + +.ide-modal-lead { + font-size: 0.96rem; + line-height: 1.65; + color: var(--text-main); + padding-bottom: 1.5rem; + margin-bottom: 1rem; +} + +.ide-modal-lead p { + margin: 0 0 0.85rem 0; +} + +.ide-modal-lead p:last-child { + margin-bottom: 0; +} + +.ide-modal-section { + margin-bottom: 2.25rem; +} + +.ide-section-title { + font-size: 1.05rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--text-main); + margin: 0 0 1.25rem 0; + display: flex; + align-items: center; + gap: 0.6rem; +} + +.ide-section-title::after { + content: ""; + flex: 1; + height: 1px; + background-color: var(--ide-primary-line); +} + +.ide-grid-cards { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; +} + +.ide-feature-card { + background: var(--bg-card); + border: 1px solid var(--ide-primary-line); + border-radius: 10px; + padding: 1.15rem; + transition: transform 0.2s ease, border-color 0.2s ease; +} + +.projects .ide-feature-card:hover { + transform: translateY(-2px); + border-color: var(--ide-projects); +} +.excellence .ide-feature-card:hover { + transform: translateY(-2px); + border-color: var(--ide-excellence); +} +.digital .ide-feature-card:hover { + transform: translateY(-2px); + border-color: var(--ide-digital); +} + +.ide-feature-card.ide-card-full { + grid-column: span 2; +} + +.ide-feature-card h4 { + color: var(--text-body); + font-size: 0.95rem; + font-weight: 700; + margin: 0 0 0.45rem 0; +} + +.ide-feature-card p { + font-size: 0.85rem; + line-height: 1.5; + margin: 0; +} + +.ide-tags-wrapper { + display: flex; + align-items: center; + gap: 0.6rem; + margin-bottom: 0.85rem; +} + +.ide-method-tag { + font-size: 0.85rem; + font-weight: 700; + color: var(--text-body); + background: rgba(255, 255, 255, 0.06); + padding: 0.25rem 0.75rem; + border-radius: 6px; + border: 1px solid var(--ide-primary-line); +} + +.projects .ide-dot { + color: var(--ide-projects);font-weight: bold; +} +.excellence .ide-dot { + color: var(--ide-excellence);font-weight: bold; +} +.digital .ide-dot { + color: var(--ide-digital);font-weight: bold; +} +.ide-text-block { + font-size: 0.9rem; + line-height: 1.6; + margin: 0; +} + +.ide-modal-callout { + background: var(--bg-surface-elevated); + border-radius: 0 10px 10px 0; + padding: 1.25rem 1.5rem; + margin-bottom: 2rem; +} +.project .ide-modal-callout{ + border-left: 3px solid var(--ide-projects); +} +.excellence .ide-modal-callout{ + border-left: 3px solid var(--ide-excellence); +} +.digital .ide-modal-callout{ + border-left: 3px solid var(--ide-digital); +} + +.ide-quote-highlight { + font-size: 1.05rem; + font-weight: 600; + font-style: italic; + color: var(--text-body); + margin: 0 0 0.65rem 0; +} + +.ide-modal-callout p { + font-size: 0.88rem; + line-height: 1.55; + margin: 0; +} + +.ide-modal-synergy { + background: rgba(0, 0, 0, 0.05); + border: 1px dashed var(--ide-primary-line); + border-radius: 10px; + padding: 1.25rem; + margin-bottom: 1.5rem; +} + +.ide-modal-synergy h4 { + font-size: 0.9rem; + font-weight: 700; + color: var(--text-main); + text-transform: uppercase; + letter-spacing: 0.05em; + margin: 0 0 0.45rem 0; +} + +.ide-modal-synergy p { + font-size: 0.86rem; + line-height: 1.55; + margin: 0; +} + +.ide-modal-synergy strong { + color: var(--text-primary); +} + +/* ========================================================================== + FOOTER FIJO Y BOTÓN CTA + ========================================================================== */ +.ide-modal-footer-fixed { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 2.25rem; + background: var(--ide-accent-soft); + border-top: 1px solid var(--ide-accent-soft); + z-index: 5; +} + +.ide-scroll-hint { + display: inline-flex; + align-items: center; + gap: 0.45rem; + font-size: 0.78rem; + color: var(--text-main); + opacity: 0.85; + transition: opacity 0.3s ease; +} + +.ide-scroll-hint svg { + animation: pulse-down 1.6s ease-in-out infinite; +} + +@keyframes pulse-down { + 0%, 100% { transform: translateY(0); opacity: 0.5; } + 50% { transform: translateY(3px); opacity: 1; } +} + +.ide-scroll-hint.is-hidden { + opacity: 0; + pointer-events: none; +} + +.ide-btn-cta { + display: inline-flex; + align-items: center; + gap: 0.6rem; + color: #ffffff; + font-size: 0.85rem; + font-weight: 700; + letter-spacing: 0.08em; + text-decoration: none; + padding: 0.8rem 1.75rem; + border-radius: 8px; + transition: transform 0.2s ease, filter 0.2s ease; +} +.projects .ide-btn-cta{ + background-color: var(--ide-projects); +} +.excellence .ide-btn-cta{ + background-color: var(--ide-excellence); +} +.digital .ide-btn-cta{ + background-color: var(--ide-digital); +} +.ide-btn-cta:hover { + transform: translateY(-2px); + filter: brightness(1.15); +} + +.ide-btn-arrow { + font-size: 1.1rem; + transition: transform 0.2s ease; +} + +.ide-btn-cta:hover .ide-btn-arrow { + transform: translateX(4px); +} + +@media (max-width: 640px) { + .ide-modal-scroll { + padding: 2rem 1.25rem; + } + .ide-grid-cards { + grid-template-columns: 1fr; + } + .ide-feature-card.ide-card-full { + grid-column: span 1; + } + .ide-modal-footer-fixed { + padding: 0.85rem 1.25rem; + } + .ide-scroll-hint { + display: none; + } + .ide-btn-cta { + width: 100%; + justify-content: center; + } +} \ No newline at end of file diff --git a/css/styles.css b/css/styles.css index 381e19e..b137518 100644 --- a/css/styles.css +++ b/css/styles.css @@ -253,7 +253,7 @@ p, li, .lead-text, .text-body, .text-muted { } .container-narrow { - max-width: 860px; + max-width: 1200px; } .container-wide { @@ -266,9 +266,12 @@ p, li, .lead-text, .text-body, .text-muted { } .section-padding-sm { - padding-top: clamp(2rem, 4vw, 3.5rem); + padding-top: clamp(1rem, 2vw, 3.5rem); padding-bottom: clamp(2rem, 4vw, 3.5rem); } +.section-padding-npb { + padding-top: clamp(1rem, 2vw, 3.5rem); +} /* --- 5. Componentes: Header & Navbar --- */ #site-header { @@ -874,7 +877,7 @@ p, li, .lead-text, .text-body, .text-muted { } /* tarjeta nosotros*/ .card-somos { - background-image: url('../assets/img/equipo.png'); + background-image: url('../assets/img/FOTO TEAM.jpg'); background-size: cover; background-position: center; background-repeat: no-repeat; @@ -1402,6 +1405,7 @@ p, li, .lead-text, .text-body, .text-muted { background-color: var(--ide-excellence); -webkit-mask-image: url('../assets/vectores/iso.svg'); mask-image: url('../assets/vectores/iso.svg'); + } .card-project .ecosystem-bg-vector { opacity: 0.1; @@ -1584,6 +1588,30 @@ p, li, .lead-text, .text-body, .text-muted { font-family: 'Barlow Semi Condensed', sans-serif; font-weight: 700; } +/* ---- Soluciones Modal -----*/ +.modal-window-sol { + background: radial-gradient(circle at top right, var(--card-overlay), var(--bg-subtle)); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + width: 100%; + max-width: 820px; + max-height: 90vh; + overflow-y: auto; + box-shadow: var(--shadow-lg); + position: relative; + padding: clamp(1.75rem, 4vw, 2.5rem); + transform: scale(0.95); + transition: transform 0.25s ease; +} + +.modal-backdrop.is-active .modal-window-sol { + transform: scale(1); +} + +.modal-window-sol h3 { + font-family: 'Barlow Semi Condensed', sans-serif; + font-weight: 700; +} /* --- 14. Espacio de Imágenes Genéricas / Placeholders --- */ .img-placeholder { @@ -1678,14 +1706,38 @@ p, li, .lead-text, .text-body, .text-muted { /* --- 16. Filtros de Soluciones --- */ .solution-card { + background: linear-gradient(0deg, var(--bg-surface) 0%, var(--ide-accent-soft) 100%); display: flex; flex-direction: column; justify-content: space-between; } - .solution-card.hidden { display: none; } +.solution-card h3{ + font-size: 1.2rem; + margin-bottom: 0.25rem; +} +.solution-card p{ + font-size: 0.92rem; + color: var(--text-body); + line-height: 1.6; + margin-bottom: 1rem; +} + +.solution-body{ + background-color: var(--bg-subtle); + padding: 1rem; + border-radius: var(--radius-sm); + font-size: 0.85rem; + margin-bottom: 0.5rem; +} + +.solution-ligth{ + font-size: 0.8rem; color: var(--text-muted); + border-top: 1px solid var(--border-color); + padding-top: 0.75rem; margin-bottom: 1rem; +} .filters-bar { display: flex; @@ -1716,7 +1768,10 @@ p, li, .lead-text, .text-body, .text-muted { color: #FFFFFF; } /* --- Tarjetas de Ecosistema --- */ - +.card-ecosistema{ + margin-bottom: 2.5rem; + padding: 2.5rem; +} .card-excellence:hover { border-color: var(--ide-excellence); box-shadow: 0 0 30px rgba(79,179,137, 0.5); @@ -1737,14 +1792,38 @@ p, li, .lead-text, .text-body, .text-muted { box-shadow: 0 0 30px rgba(44,105,171, 0.5); transform: translateY(-2px); } + +.eco{ + gap: 2.5rem; align-items: center; +} + +.eco p{ + font-size: 1.05rem; color:var(--text-body); line-height: 1.65; margin-bottom: 1rem; +} +.eco ul{ + list-style: none; + display: flex; + flex-direction: + column; gap: 0.6rem; + font-size: 0.92rem; + color: var(--text-muted); + margin-bottom: 1rem; +} +.eco img{ + width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-md); +} /* --- Formato NetSchema --- */ +.hero-solucion{ + background: linear-gradient(0deg, var(--bg-surface) 0%, var(--ide-accent-soft) 100%); + +} .netschema-section { width: 100%; - padding: 40px 20px; + padding: 0px 20px; display: flex; justify-content: center; align-items: center; - background-color: var(--bg-subtle); + background: linear-gradient(180deg, var(--bg-surface) 0%, var(--ide-accent-soft) 100%); } /* Envoltura con aspecto horizontal responsivo */ @@ -1771,6 +1850,14 @@ canvas { cursor: default; } +.seccion-servicios-tarjetas{ + text-align: center; + margin-bottom: 3rem; +} + +/*modales ecosistemas*/ + + /* ========================================================================== LEYENDA / TOOLTIP FLOTANTE ========================================================================== */ diff --git a/ecosistema.html b/ecosistema.html index 7384a33..c54a577 100644 --- a/ecosistema.html +++ b/ecosistema.html @@ -10,6 +10,8 @@ + + @@ -18,91 +20,50 @@
-
- - - - - -
- +
-
-
- PROPUESTA DE VALOR -

Diferentes capacidades.
Una visión compartida del conjunto.

-

- No todos los desafíos necesitan activar todo el Ecosistema.
La clave está en comprender el conjunto para saber dónde intervenir. -

- - -
-

- “No todos los desafíos necesitan todo el Ecosistema. Pero todos pueden beneficiarse de una mirada capaz de comprender el conjunto.” +

+
+ PROPUESTA DE VALOR +

Diferentes capacidades.
Una visión compartida del conjunto.

+

+ No todos los desafíos necesitan activar todo el Ecosistema.
La clave está en comprender el conjunto para saber dónde intervenir.

-
-
- ARQUITECTURA DE INTEGRACIÓN -

El Modelo de Red Sistémica

-
- - -
+
-
+
-
+
CAPACIDADES

Conocé Nuestro Ecosistema en detalle

-
-
+
+
Operational Excellence & Sustainability -

+

Para fortalecer la gestión y mejorar el desempeño: Integramos procesos, sistemas de gestión, mejora continua y sostenibilidad para ayudar a las organizaciones a gestionar mejor, optimizar su desempeño y generar valor sostenible.

-
    +
    • • Procesos
    • • Sistemas de gestión
    • • Mejora continua
    • @@ -110,26 +71,27 @@
    • • Riesgos
    • • Sostenibilidad
    + CONOCER MÁS →
- IDE Excellence + IDE Excellence
-
-
+
+
- IDE Project + IDE Project
PMO & Project Services -

+

Para convertir iniciativas en resultados: Fortalecemos la capacidad de las organizaciones para seleccionar, priorizar y gestionar proyectos, conectando estrategia, recursos y ejecución para transformar iniciativas en resultados.

-
    +
    • • Proyectos
    • • PMO
    • • Portafolios
    • @@ -137,22 +99,20 @@
    • • Metodologías
    • • Resultados
    + CONOCER MÁS →
- -
-
-
- IDE Digital -
+ +
+
Business Digital Solutions -

+

Tecnología con sentido: Conectamos gestión, procesos, datos e inteligencia artificial para identificar dónde la tecnología puede simplificar, automatizar y potenciar la forma en que las organizaciones trabajan y toman decisiones.

-
    +
    • • Digitalización
    • • Automatización
    • • Datos.
    • @@ -160,19 +120,26 @@
    • • Integración
    • • Decisiones
    + CONOCER MÁS → +
+
+ IDE Digital
-
-
+
+
+
+ IDE Academy +
Executive Learning & Capability Development -

+

Para desarrollar capacidades: Diseñamos experiencias de aprendizaje que conectan conocimiento, práctica y contexto para fortalecer las capacidades que profesionales, equipos y organizaciones necesitan para gestionar, liderar y transformar.

-
-
- IDE Academy -
+
- +
+
PREGUNTAS FRECUENTES

¿Cómo funciona el Ecosistema IDE en la práctica?

-
+ +
-
-

¿Necesito contratar las cuatro capacidades del Ecosistema?

-

- No. Cada intervención se diseña a partir del desafío y del contexto de la organización. Podemos trabajar desde una única capacidad o integrar varias cuando su combinación permite generar mayor valor. -

+ +
+ + ¿Necesito contratar las cuatro capacidades del Ecosistema? + + +
+

+ No. Cada intervención se diseña a partir del desafío y del contexto de la organización. Podemos trabajar desde una única capacidad o integrar varias cuando su combinación permite generar mayor valor. +

+
+
-
-

¿IDE trabaja con soluciones prediseñadas o desarrolla propuestas a medida?

-

- Ambas posibilidades pueden convivir. Contamos con soluciones y metodologías que sirven como punto de partida, pero definimos el alcance de cada intervención según los objetivos, necesidades y contexto de la organización. -

-
+ +
+ + ¿IDE trabaja con soluciones prediseñadas o desarrolla propuestas a medida? + + +
+

+ Ambas posibilidades pueden convivir. Contamos con soluciones y metodologías que sirven como punto de partida, pero definimos el alcance de cada intervención según los objetivos, necesidades y contexto de la organización. +

+
+
-
-

¿Qué pasa si no sé qué capacidad necesito?

-

- No hace falta definirlo de antemano. Empezamos por comprender qué está pasando, identificar dónde puede estar el punto de intervención y, a partir de allí, determinar qué capacidades pueden aportar valor. -

-
+ +
+ + ¿Qué pasa si no sé qué capacidad necesito? + + +
+

+ No hace falta definirlo de antemano. Empezamos por comprender qué está pasando, identificar dónde puede estar el punto de intervención y, a partir de allí, determinar qué capacidades pueden aportar valor. +

+
+
-
-

¿Puedo trabajar con IDE para una necesidad puntual?

-

- Si. La mirada sistémica no implica intervenir en toda la organización. Podemos abordar una necesidad específica manteniendo en perspectiva sus relaciones e impactos sobre el conjunto. + +

+ + ¿Puedo trabajar con IDE para una necesidad puntual? + + +
+

+ Sí. La mirada sistémica no implica intervenir en toda la organización. Podemos abordar una necesidad específica manteniendo en perspectiva sus relaciones e impactos sobre el conjunto. +

+
+
- -

-
- -
-

¿Cómo sé por dónde empezar?

-

- Si ya identificaste qué necesitás, podés explorar nuestras soluciones. Si todavía estás tratando de comprender el desafío, la Brújula IDE puede ayudarte a encontrar un primer punto de orientación. -

-
+ +
+ + ¿Cómo sé por dónde empezar? + + +
+

+ Si ya identificaste qué necesitás, podés explorar nuestras soluciones. Si todavía estás tratando de comprender el desafío, la Brújula IDE puede ayudarte a encontrar un primer punto de orientación. +

+
+
@@ -241,7 +257,7 @@
-
+

¿Dónde podemos generar mayor impacto en tu organización?

Conversemos para comprender tu desafío e identificar qué capacidades pueden aportar mayor valor. @@ -253,12 +269,339 @@

+ + + + + + + + + + +
- + + diff --git a/index.html b/index.html index c6b3fdc..e8d0814 100644 --- a/index.html +++ b/index.html @@ -31,7 +31,7 @@
CONECTAMOS EL TODO -

+

¿Qué pasa cuando dejamos de mirar los problemas por separado?

@@ -59,7 +59,7 @@

-
+
LA INCOMODIDAD PRODUCTIVA

@@ -686,7 +686,7 @@

-
+
CONVERSACIÓN INICIAL diff --git a/js/modal.js b/js/modal.js new file mode 100644 index 0000000..1bb90e3 --- /dev/null +++ b/js/modal.js @@ -0,0 +1,95 @@ +/* ========================================================================== + 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); + } + }); +}); \ No newline at end of file diff --git a/js/netschema2.js b/js/netschema2.js index f2958ef..52c7b4f 100644 --- a/js/netschema2.js +++ b/js/netschema2.js @@ -1,23 +1,30 @@ // Mapa: propiedad de CONFIG -> nombre de variable CSS const CSS_VARS = { - greenNodesColor: "--ide-primary", - greenStrokeColor: "--ide-primary-light", - linkLineColor: "--canvas-link-line-color", - linkGreenColor: "--canvas-link-green-color", - linkActiveColor: "--canvas-link-active-color", - purpleCoreLineColor: "--canvas-purple-core-line-color" + greenNodesColor: "--ide-primary", + greenStrokeColor: "--ide-primary-light", + linkLineColor: "--ide-primary-line", + linkGreenColor: "--ide-primary-line", + linkGreenToGreenColor: "--ide-primary-light2", // Color para líneas entre nodos verdes + linkActiveColor: "--ide-primary-light", + purpleCoreLineColor: "--ide-primary-line", + shadowCanva: "--shadow-canva", + textMain: "--text-main", + textInverse: "--text-inverse", + centerBoxBg: "--ide-center-bg", // Fondo del recuadro central + centerBoxBorder: "--ide-center-border", // Borde del recuadro central + centerBoxText: "--ide-center-text" // Texto del recuadro central }; // Mapa: id de nodo violeta -> variable CSS const PURPLE_NODE_VARS = { - p_top: "--canvas-purple-p-top-color", - p_bottom: "--canvas-purple-p-bottom-color", - p_left: "--canvas-purple-p-left-color", - p_right: "--canvas-purple-p-right-color" + p_top: "--ide-excellence", + p_bottom: "--ide-academy", + p_left: "--ide-projects", + p_right: "--ide-digital" }; // Variable CSS común para todos los amarillos -const YELLOW_NODE_VAR = "--canvas-yellow-node-color"; +const YELLOW_NODE_VAR = "--ide-primary-dark"; /* ========================================================================== UTILIDAD: LEER VARIABLES CSS @@ -36,70 +43,94 @@ function readCSSVariable(variableName, fallback = "") { const CONFIG = { // 1. Color global configurable para TODOS los nodos verdes - greenNodesColor: readCSSVariable(CSS_VARS.greenNodesColor, "#9b1717"), - greenStrokeColor: readCSSVariable(CSS_VARS.greenStrokeColor, "#630b5f"), + greenNodesColor: readCSSVariable(CSS_VARS.greenNodesColor), + greenStrokeColor: readCSSVariable(CSS_VARS.greenStrokeColor), // 2. Estilos de líneas punteadas y dinámicas - linkLineColor: readCSSVariable(CSS_VARS.linkLineColor, "rgba(95, 110, 240, 0.40)"), - linkGreenColor: readCSSVariable(CSS_VARS.linkGreenColor, "rgba(235, 60, 60, 0.42)"), - linkActiveColor: readCSSVariable(CSS_VARS.linkActiveColor, "rgba(25, 35, 205, 0.95)"), - purpleCoreLineColor: readCSSVariable(CSS_VARS.purpleCoreLineColor, "rgba(35, 35, 35, 0.70)"), + linkLineColor: readCSSVariable(CSS_VARS.linkLineColor), + linkGreenColor: readCSSVariable(CSS_VARS.linkGreenColor), + linkGreenToGreenColor: readCSSVariable(CSS_VARS.linkGreenToGreenColor, readCSSVariable(CSS_VARS.linkGreenColor, "#24333E")), + linkActiveColor: readCSSVariable(CSS_VARS.linkActiveColor), + purpleCoreLineColor: readCSSVariable(CSS_VARS.purpleCoreLineColor), + shadowCanva: readCSSVariable(CSS_VARS.shadowCanva), + textMain: readCSSVariable(CSS_VARS.textMain), + textInverse: readCSSVariable(CSS_VARS.textInverse), - // 3. Nodos VIOLETAS centrales (posiciones, color individual, leyenda) + // 3. Estilos del recuadro central "EL TODO" + centerBoxBg: readCSSVariable(CSS_VARS.centerBoxBg, readCSSVariable(YELLOW_NODE_VAR, "#1b2631")), + centerBoxBorder: readCSSVariable(CSS_VARS.centerBoxBorder, readCSSVariable(CSS_VARS.purpleCoreLineColor, "#3a5160")), + centerBoxText: readCSSVariable(CSS_VARS.centerBoxText, readCSSVariable(CSS_VARS.textInverse, "#ffffff")), + + // Datos del componente central + centerBox: { + id: "center_box", + label: "EL TODO", + desc: "Núcleo integrador central del sistema.", + x: 615, + y: 260, + baseX: 615, + baseY: 260, + width: 104, + height: 36, + borderRadius: 8, + speedOffset: Math.random() * 10 + }, + + // 4. Nodos VIOLETAS centrales (posiciones, color individual, leyenda) purpleNodes: [ { id: "p_top", x: 615, y: 185, radius: 42, - label: "Núcleo N", - color: readCSSVariable(PURPLE_NODE_VARS.p_top, "#8a00c2"), + label: "Excellence", + color: readCSSVariable(PURPLE_NODE_VARS.p_top), desc: "Servidor central de control y despacho de tareas." }, { id: "p_bottom", x: 615, y: 335, radius: 42, - label: "Núcleo S", - color: readCSSVariable(PURPLE_NODE_VARS.p_bottom, "#9900d8"), + label: "Academy", + color: readCSSVariable(PURPLE_NODE_VARS.p_bottom), desc: "Base de datos y redundancia estructural sur." }, { id: "p_left", x: 485, y: 260, radius: 42, - label: "Núcleo O", - color: readCSSVariable(PURPLE_NODE_VARS.p_left, "#7e00b3"), + label: "Project", + color: readCSSVariable(PURPLE_NODE_VARS.p_left), desc: "Pasarela occidental hacia submódulos de entrada." }, { id: "p_right", x: 745, y: 260, radius: 42, - label: "Núcleo E", - color: readCSSVariable(PURPLE_NODE_VARS.p_right, "#9400cf"), + label: "Digital", + color: readCSSVariable(PURPLE_NODE_VARS.p_right), desc: "Concentrador oriental hacia subredes de distribución." } ], - // 4. Nodos AMARILLOS: Cada uno conectado a 2 VIOLETAS + // 5. Nodos AMARILLOS: Cada uno conectado a 2 VIOLETAS yellowNodes: [ // --- Lado Izquierdo --- - { id: "yl_1", x: 420, y: 130, r: 26, label: "IZQ-1", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Módulo intermedio A-1", purpleTargets: ["p_top", "p_left"], side: "left" }, - { id: "yl_2", x: 350, y: 165, r: 24, label: "IZQ-2", color: readCSSVariable(YELLOW_NODE_VAR, "#fff01f"), desc: "Módulo intermedio A-2", purpleTargets: ["p_top", "p_left"], side: "left" }, - { id: "yl_3", x: 355, y: 245, r: 25, label: "IZQ-3", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Balanceador izquierdo", purpleTargets: ["p_left", "p_top"], side: "left" }, - { id: "yl_4", x: 335, y: 335, r: 26, label: "IZQ-4", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Filtro de tráfico A-4", purpleTargets: ["p_left", "p_bottom"], side: "left" }, - { id: "yl_5", x: 395, y: 415, r: 28, label: "IZQ-5", color: readCSSVariable(YELLOW_NODE_VAR, "#fff33b"), desc: "Procesador de paquetes", purpleTargets: ["p_bottom", "p_left"], side: "left" }, - { id: "yl_6", x: 255, y: 350, r: 25, label: "IZQ-6", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Enrutador secundario", purpleTargets: ["p_left", "p_bottom"], side: "left" }, + { id: "yl_1", x: 420, y: 130, r: 26, label: "5S", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Capacitación e Impmentación", purpleTargets: ["p_top", "p_left"], side: "left" }, + { id: "yl_2", x: 350, y: 165, r: 24, label: "ISO 9001", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Certificación", purpleTargets: ["p_top", "p_left"], side: "left" }, + { id: "yl_3", x: 355, y: 245, r: 25, label: "KAIZEN", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Modificación de Procesos", purpleTargets: ["p_left", "p_top"], side: "left" }, + { id: "yl_4", x: 335, y: 335, r: 26, label: "BPM", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Automatización de Procesos de Venta", purpleTargets: ["p_left", "p_bottom"], side: "left" }, + { id: "yl_5", x: 395, y: 415, r: 28, label: "KPI", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Implementación y Monitoreo", purpleTargets: ["p_bottom", "p_left"], side: "left" }, + { id: "yl_6", x: 255, y: 350, r: 25, label: "PDCA", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Capacitación y Mejora de Taller", purpleTargets: ["p_left", "p_bottom"], side: "left" }, // --- Lado Derecho --- - { id: "yr_1", x: 800, y: 135, r: 25, label: "DER-1", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Concentrador de salida 1", purpleTargets: ["p_top", "p_right"], side: "right" }, - { id: "yr_2", x: 875, y: 155, r: 25, label: "DER-2", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Concentrador de salida 2", purpleTargets: ["p_top", "p_right"], side: "right" }, - { id: "yr_3", x: 950, y: 195, r: 25, label: "DER-3", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Distribuidor rápido 3", purpleTargets: ["p_right", "p_top"], side: "right" }, - { id: "yr_4", x: 875, y: 235, r: 25, label: "DER-4", color: readCSSVariable(YELLOW_NODE_VAR, "#fff33b"), desc: "Replicador este 4", purpleTargets: ["p_right", "p_top"], side: "right" }, - { id: "yr_5", x: 890, y: 300, r: 25, label: "DER-5", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Gestor de colas 5", purpleTargets: ["p_right", "p_bottom"], side: "right" }, - { id: "yr_6", x: 965, y: 345, r: 25, label: "DER-6", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Canal asíncrono 6", purpleTargets: ["p_right", "p_bottom"], side: "right" }, - { id: "yr_7", x: 890, y: 375, r: 25, label: "DER-7", color: readCSSVariable(YELLOW_NODE_VAR, "#fff01f"), desc: "Salida perimetral 7", purpleTargets: ["p_bottom", "p_right"], side: "right" }, - { id: "yr_8", x: 830, y: 420, r: 26, label: "DER-8", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Canal de descarga 8", purpleTargets: ["p_bottom", "p_right"], side: "right" } + { id: "yr_1", x: 800, y: 135, r: 25, label: "BPR", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Capacitación e Impmentación", purpleTargets: ["p_top", "p_right"], side: "right" }, + { id: "yr_2", x: 875, y: 155, r: 25, label: "ISO45001", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Certificación", purpleTargets: ["p_top", "p_right"], side: "right" }, + { id: "yr_3", x: 950, y: 195, r: 25, label: "LEAN", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Modificación de Procesos", purpleTargets: ["p_right", "p_top"], side: "right" }, + { id: "yr_4", x: 875, y: 235, r: 25, label: "ISO14001", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Automatización de Procesos de Venta", purpleTargets: ["p_right", "p_top"], side: "right" }, + { id: "yr_5", x: 890, y: 300, r: 25, label: "PMO", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Mejoras en procedimientos de Atención de situaciones críticas", purpleTargets: ["p_right", "p_bottom"], side: "right" }, + { id: "yr_6", x: 965, y: 345, r: 25, label: "SIGMA", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Capacitación y Mejora de Taller", purpleTargets: ["p_right", "p_bottom"], side: "right" }, + { id: "yr_7", x: 890, y: 375, r: 25, label: "IA", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Automatización de Toma de Decisiones", purpleTargets: ["p_bottom", "p_right"], side: "right" }, + { id: "yr_8", x: 830, y: 420, r: 26, label: "RPA", color: readCSSVariable(YELLOW_NODE_VAR, "#24333E"), desc: "Implementación y Monitoreo", purpleTargets: ["p_bottom", "p_right"], side: "right" } ] }; @@ -199,7 +230,7 @@ function initNetwork() { { id: "gl_13", x: 235, y: 425, side: "left" }, // Lado Derecho - { id: "gr_1", x: 1040, y: 90, side: "right" }, + { id: "gr_1", x: 1060, y: 90, side: "right" }, { id: "gr_2", x: 960, y: 110, side: "right" }, { id: "gr_3", x: 1025, y: 150, side: "right" }, { id: "gr_4", x: 1095, y: 155, side: "right" }, @@ -232,27 +263,61 @@ function initNetwork() { }); }); - // 4. CONEXIÓN AMARILLOS <-> VERDES (cobertura total en ambas direcciones) + // 4. CONEXIÓN AMARILLOS <-> VERDES (Múltiples conexiones por verde) const yellows = nodes.filter(n => n.type === "yellow"); const greens = nodes.filter(n => n.type === "green"); - // PASO A: cada amarillo con al menos 1 verde - yellows.forEach((yNode, idx) => { - const candidateGreens = greens.filter(g => g.side === yNode.side); - candidateGreens.sort((a, b) => { - const distA = Math.hypot(a.baseX - yNode.baseX, a.baseY - yNode.baseY); - const distB = Math.hypot(b.baseX - yNode.baseX, b.baseY - yNode.baseY); + // Configura cuántos amarillos conectar a cada verde (recomendado: 2 o 3) + const YELLOWS_PER_GREEN = 2; + + greens.forEach((gNode, gIdx) => { + // 1. Filtrar amarillos que pertenezcan al mismo sector (left/right) + const candidateYellows = yellows.filter(y => y.side === gNode.side); + + // 2. Ordenar de menor a mayor distancia al nodo verde + candidateYellows.sort((a, b) => { + const distA = Math.hypot(a.baseX - gNode.baseX, a.baseY - gNode.baseY); + const distB = Math.hypot(b.baseX - gNode.baseX, b.baseY - gNode.baseY); return distA - distB; }); - if (candidateGreens.length > 0) { + // 3. Tomar los N amarillos más cercanos + const targets = candidateYellows.slice(0, YELLOWS_PER_GREEN); + + targets.forEach((yNode, targetRank) => { + // Alternar arco: el primero arquea hacia un lado y el segundo hacia el opuesto + // Esto previene que las líneas coincidan o se solapen + const direction = (gIdx + targetRank) % 2 === 0 ? 1 : -1; + const baseCurvature = 0.16 + (targetRank * 0.07); + const curvature = baseCurvature * direction; + addLink( yNode.id, - candidateGreens[0].id, + gNode.id, "yellow-green", true, - idx % 2 === 0 ? 0.20 : -0.20 + curvature ); + }); + }); + + // PASO DE SEGURIDAD: asegurar que ningún amarillo quede sin al menos un verde + yellows.forEach(yNode => { + const hasConnection = links.some( + l => l.type === "yellow-green" && (l.from === yNode.id || l.to === yNode.id) + ); + + if (!hasConnection) { + const candidateGreens = greens.filter(g => g.side === yNode.side); + candidateGreens.sort((a, b) => { + const distA = Math.hypot(a.baseX - yNode.baseX, a.baseY - yNode.baseY); + const distB = Math.hypot(b.baseX - yNode.baseX, b.baseY - yNode.baseY); + return distA - distB; + }); + + if (candidateGreens.length > 0) { + addLink(yNode.id, candidateGreens[0].id, "yellow-green", true, 0.20); + } } }); @@ -287,6 +352,27 @@ function initNetwork() { ); } }); + + // 5. CONEXIÓN VERDES <-> VERDES (mismo sector, líneas rectas) + ["left", "right"].forEach(side => { + const sectorGreens = greens.filter(g => g.side === side); + sectorGreens.forEach(gNode => { + const neighbors = sectorGreens + .filter(other => other.id !== gNode.id) + .map(other => ({ + id: other.id, + dist: Math.hypot(other.baseX - gNode.baseX, other.baseY - gNode.baseY) + })) + .sort((a, b) => a.dist - b.dist); + + // Conecta con los 4 vecinos más cercanos del mismo sector para formar la malla limpia + neighbors.slice(0, 5).forEach(neighbor => { + if (neighbor.dist <= 130) { + addLink(gNode.id, neighbor.id, "green-green", false); + } + }); + }); + }); } // Bucle de actualización (flotación en zona segura) @@ -305,10 +391,29 @@ function update(time) { node.y = node.baseY + Math.cos(t * 0.85) * (maxOffset * 0.75); }); + // Movimiento coordinado de "EL TODO" según el centroide de los nodos principales + const purples = nodes.filter(n => n.type === "purple"); + if (purples.length > 0 && CONFIG.centerBox) { + const avgX = purples.reduce((sum, p) => sum + p.x, 0) / purples.length; + const avgY = purples.reduce((sum, p) => sum + p.y, 0) / purples.length; + + if (hoveredNode && hoveredNode.id === CONFIG.centerBox.id) { + CONFIG.centerBox.x = 615; + CONFIG.centerBox.y = 260; + } else { + const t = (time * 0.0016) + CONFIG.centerBox.speedOffset; + CONFIG.centerBox.x = avgX + Math.sin(t) * (maxOffset * 0.45); + CONFIG.centerBox.y = avgY + Math.cos(t * 0.85) * (maxOffset * 0.35); + } + } + //aceleracion de la red + const isCenterActive = hoveredNode && CONFIG.centerBox && hoveredNode.id === CONFIG.centerBox.id; + dashOffset -= isCenterActive ? 0.95 : 0.35; + dashOffset -= 0.35; } -// Renderizado de líneas curvadas +// Renderizado de líneas curvadas y rectas function drawConnection(source, target, link, isHighlight) { ctx.save(); ctx.beginPath(); @@ -336,13 +441,18 @@ function drawConnection(source, target, link, isHighlight) { if (link.type === "purple-purple") { ctx.setLineDash([4, 4]); ctx.lineDashOffset = dashOffset * 0.5; - ctx.strokeStyle = isHighlight ? "#000000" : CONFIG.purpleCoreLineColor; + ctx.strokeStyle = isHighlight ? CONFIG.linkActiveColor : CONFIG.purpleCoreLineColor; ctx.lineWidth = isHighlight ? 2.6 : 1.8; } else if (link.type === "yellow-green") { ctx.setLineDash([3, 4]); ctx.lineDashOffset = dashOffset; ctx.strokeStyle = isHighlight ? CONFIG.linkActiveColor : CONFIG.linkGreenColor; ctx.lineWidth = isHighlight ? 2.0 : 0.95; + } else if (link.type === "green-green") { + ctx.setLineDash([3, 4]); + ctx.lineDashOffset = dashOffset * 0.8; + ctx.strokeStyle = isHighlight ? CONFIG.linkActiveColor : CONFIG.linkGreenToGreenColor; + ctx.lineWidth = isHighlight ? 1.8 : 0.9; } else { ctx.setLineDash([3, 4]); ctx.lineDashOffset = dashOffset; @@ -354,22 +464,86 @@ function drawConnection(source, target, link, isHighlight) { ctx.restore(); } +// Dibujo del recuadro central "EL TODO" +function drawCenterBox() { + const box = CONFIG.centerBox; + if (!box) return; + + const w = box.width; + const h = box.height; + const r = box.borderRadius; + const x = box.x - w / 2; + const y = box.y - h / 2; + + const isBoxHovered = hoveredNode && hoveredNode.id === box.id; + + ctx.save(); + ctx.beginPath(); + if (ctx.roundRect) { + ctx.roundRect(x, y, w, h, r); + } else { + // Compatibilidad en navegadores antiguos + ctx.moveTo(x + r, y); + ctx.lineTo(x + w - r, y); + ctx.quadraticCurveTo(x + w, y, x + w, y + r); + ctx.lineTo(x + w, y + h - r); + ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h); + ctx.lineTo(x + r, y + h); + ctx.quadraticCurveTo(x, y + h, x, y + h - r); + ctx.lineTo(x, y + r); + ctx.quadraticCurveTo(x, y, x + r, y); + ctx.closePath(); + } + + if (isBoxHovered) { + ctx.shadowColor = CONFIG.shadowCanva; + ctx.shadowBlur = 14; + } else { + ctx.shadowColor = "rgba(0, 0, 0, 0.25)"; + ctx.shadowBlur = 6; + } + + ctx.fillStyle = CONFIG.centerBoxBg; + ctx.fill(); + + ctx.strokeStyle = isBoxHovered ? CONFIG.linkActiveColor : CONFIG.centerBoxBorder; + ctx.lineWidth = isBoxHovered ? 2.0 : 1.4; + ctx.stroke(); + ctx.restore(); + + // Texto "EL TODO" + ctx.save(); + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillStyle = CONFIG.centerBoxText; + ctx.font = "bold 11.5px system-ui, sans-serif"; + ctx.fillText(box.label, box.x, box.y); + ctx.restore(); +} + // Renderizado del Canvas function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); const nodeMap = new Map(nodes.map(n => [n.id, n])); // 1. Dibujar líneas + const isCenterBoxHovered = hoveredNode && CONFIG.centerBox && hoveredNode.id === CONFIG.centerBox.id; + links.forEach(link => { const s = nodeMap.get(link.from); const t = nodeMap.get(link.to); if (!s || !t) return; - const isHighlight = hoveredNode && (hoveredNode.id === s.id || hoveredNode.id === t.id); + // Se ilumina si estás sobre un nodo conectado O si estás sobre "EL TODO" + const isHighlight = isCenterBoxHovered || (hoveredNode && (hoveredNode.id === s.id || hoveredNode.id === t.id)); + drawConnection(s, t, link, isHighlight); - }); + });; - // 2. Dibujar nodos + // 2. Dibujar recuadro central "EL TODO" (situado en el plano intermedio para enmascarar cruces) + drawCenterBox(); + + // 3. Dibujar nodos nodes.forEach(node => { ctx.save(); ctx.beginPath(); @@ -377,11 +551,11 @@ function draw() { if (node.type === "purple") { ctx.fillStyle = node.color; - ctx.strokeStyle = "#210036"; + ctx.strokeStyle = node.color; ctx.lineWidth = 1.8; } else if (node.type === "yellow") { ctx.fillStyle = node.color; - ctx.strokeStyle = "#383500"; + ctx.strokeStyle = node.color; ctx.lineWidth = 1.3; } else { ctx.fillStyle = CONFIG.greenNodesColor; @@ -390,7 +564,7 @@ function draw() { } if (hoveredNode && hoveredNode.id === node.id) { - ctx.shadowColor = "rgba(0, 0, 0, 0.35)"; + ctx.shadowColor = CONFIG.shadowCanva; ctx.shadowBlur = 14; } @@ -398,7 +572,7 @@ function draw() { ctx.stroke(); ctx.restore(); - // 3. Texto en nodos violetas y amarillos + // 4. Texto en nodos violetas y amarillos if (node.label) { ctx.save(); ctx.textAlign = "center"; @@ -408,7 +582,7 @@ function draw() { ctx.fillStyle = "#ffffff"; ctx.font = "bold 12.5px system-ui, sans-serif"; } else if (node.type === "yellow") { - ctx.fillStyle = "#1e1e1e"; + ctx.fillStyle = "#ffffff"; ctx.font = "600 10.5px system-ui, sans-serif"; } @@ -453,12 +627,29 @@ canvas.addEventListener("mousemove", (e) => { } } + // Detección sobre el recuadro central "EL TODO" + if (!found && CONFIG.centerBox) { + const box = CONFIG.centerBox; + const halfW = box.width / 2; + const halfH = box.height / 2; + if (x >= box.x - halfW && x <= box.x + halfW && y >= box.y - halfH && y <= box.y + halfH) { + found = { + id: box.id, + label: box.label, + desc: box.desc, + radius: halfH, + x: box.x, + y: box.y + }; + } + } + hoveredNode = found; if (hoveredNode) { canvas.style.cursor = "pointer"; tooltipTitle.textContent = hoveredNode.label; - tooltipDesc.textContent = hoveredNode.desc; + tooltipDesc.textContent = hoveredNode.desc || ""; tooltip.style.left = `${cssX}px`; tooltip.style.top = `${cssY - (hoveredNode.radius * (canvas.getBoundingClientRect().height / canvas.height))}px`; @@ -476,19 +667,20 @@ canvas.addEventListener("mouseleave", () => { /* ========================================================================== SOPORTE DE TEMA CLARO / OSCURO - -------------------------------------------------------------------------- - - Re-lee las variables CSS y actualiza CONFIG + nodos vivos. - - Observa cambios de `data-theme` o `class` en y . ========================================================================== */ function refreshColorsFromCSS() { // 1. Colores globales - CONFIG.greenNodesColor = readCSSVariable(CSS_VARS.greenNodesColor, CONFIG.greenNodesColor); - CONFIG.greenStrokeColor = readCSSVariable(CSS_VARS.greenStrokeColor, CONFIG.greenStrokeColor); - CONFIG.linkLineColor = readCSSVariable(CSS_VARS.linkLineColor, CONFIG.linkLineColor); - CONFIG.linkGreenColor = readCSSVariable(CSS_VARS.linkGreenColor, CONFIG.linkGreenColor); - CONFIG.linkActiveColor = readCSSVariable(CSS_VARS.linkActiveColor, CONFIG.linkActiveColor); - CONFIG.purpleCoreLineColor = readCSSVariable(CSS_VARS.purpleCoreLineColor, CONFIG.purpleCoreLineColor); + CONFIG.greenNodesColor = readCSSVariable(CSS_VARS.greenNodesColor, CONFIG.greenNodesColor); + CONFIG.greenStrokeColor = readCSSVariable(CSS_VARS.greenStrokeColor, CONFIG.greenStrokeColor); + CONFIG.linkLineColor = readCSSVariable(CSS_VARS.linkLineColor, CONFIG.linkLineColor); + CONFIG.linkGreenColor = readCSSVariable(CSS_VARS.linkGreenColor, CONFIG.linkGreenColor); + CONFIG.linkGreenToGreenColor = readCSSVariable(CSS_VARS.linkGreenToGreenColor, CONFIG.linkGreenToGreenColor); + CONFIG.linkActiveColor = readCSSVariable(CSS_VARS.linkActiveColor, CONFIG.linkActiveColor); + CONFIG.purpleCoreLineColor = readCSSVariable(CSS_VARS.purpleCoreLineColor, CONFIG.purpleCoreLineColor); + CONFIG.centerBoxBg = readCSSVariable(CSS_VARS.centerBoxBg, CONFIG.centerBoxBg); + CONFIG.centerBoxBorder = readCSSVariable(CSS_VARS.centerBoxBorder, CONFIG.centerBoxBorder); + CONFIG.centerBoxText = readCSSVariable(CSS_VARS.centerBoxText, CONFIG.centerBoxText); // 2. Colores de violetas en CONFIG CONFIG.purpleNodes.forEach(p => { @@ -508,7 +700,6 @@ function refreshColorsFromCSS() { } else if (node.type === "yellow") { node.color = readCSSVariable(YELLOW_NODE_VAR, node.color); } - // Los verdes leen CONFIG.greenNodesColor directo en draw(), no requieren update propio }); } @@ -517,7 +708,6 @@ function watchThemeChanges() { refreshColorsFromCSS(); }); - // Observa (habitual en data-theme) y (por si acaso) observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme", "class"] diff --git a/modal-test.html b/modal-test.html new file mode 100644 index 0000000..2b39e78 --- /dev/null +++ b/modal-test.html @@ -0,0 +1,142 @@ + + + + + + Diagrama de Red y Modal + + + + + +
+ +
+ + +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..248a0b9 --- /dev/null +++ b/script.js @@ -0,0 +1,73 @@ +/* ========================================================================== + CONTROLADOR DEL MODAL + ========================================================================== */ +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(modalId) { + const modal = document.getElementById(modalId); + if (!modal) return; + modal.classList.remove("is-active"); + document.body.style.overflow = ""; +} + +// Inicialización de eventos del modal una vez cargado el DOM +document.addEventListener("DOMContentLoaded", () => { + // 1. Botón externo HTML + const btnTrigger = document.getElementById("btnOpenProjectsModal"); + if (btnTrigger) { + btnTrigger.addEventListener("click", () => { + openModal("modal-ide-projects"); + }); + } + + // 2. Botón Cerrar (X) + const btnClose = document.getElementById("btnCloseModal"); + if (btnClose) { + btnClose.addEventListener("click", () => { + closeModal("modal-ide-projects"); + }); + } + + // 3. Cerrar al hacer clic en el backdrop oscuro + const modal = document.getElementById("modal-ide-projects"); + if (modal) { + modal.addEventListener("click", (e) => { + if (e.target === modal) { + closeModal("modal-ide-projects"); + } + }); + } + + // 4. Cerrar con tecla Escape + document.addEventListener("keydown", (e) => { + if (e.key === "Escape") { + closeModal("modal-ide-projects"); + } + }); + + // 5. Ocultar indicador "Desliza para leer más" al scrollear + const scrollArea = document.getElementById("modalScrollArea"); + const scrollHint = document.getElementById("scrollHint"); + 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"); + } + }); + } +}); + +// Inicialización del motor Canvas +//initNetwork(); +//requestAnimationFrame(animate); \ No newline at end of file diff --git a/soluciones.html b/soluciones.html index 489de29..98bd33c 100644 --- a/soluciones.html +++ b/soluciones.html @@ -50,7 +50,7 @@
IDENTIFIQUEMOS SOLUCIONES -

Soluciones Concretas: Respuestas Específicas

+

Soluciones Concretas:
Respuestas Específicas

Si ya identificaste qué necesitás, explorá nuestras soluciones, su alcance y el valor que pueden aportar a tu organización.

@@ -60,120 +60,93 @@
- +
-
+
-
- IDE Excellence - NORMA INTERNACIONAL -
-

SISTEMAS DE GESTIÓN Y CERTIFICACIONES

-

- Para convertir requisitos en herramientas de gestión. -

-
-

Diseñamos, implementamos e integramos sistemas de gestión que permiten ordenar procesos, gestionar riesgos, mejorar el desempeño y responder a requisitos normativos sin sumar burocracia innecesaria.

+

SISTEMAS DE GESTIÓN Y CERTIFICACIONES

+

Para convertir requisitos en herramientas de gestión.

+
+

Diseñamos, implementamos e integramos sistemas de gestión que permiten ordenar procesos, gestionar riesgos, mejorar el desempeño y responder a requisitos normativos sin sumar burocracia innecesaria.

-
+
¿Sabías que un SGC requiere capacitar a los líderes? Conocé cómo IDE Academy complementa esta implementación.
- + Explorar soluciones →
-
+
-
- IDE Excellence - SISTEMAS INTEGRADOS -
-

PROCESOS Y MEJORA ORGANIZACIONAL

-

- Para transformar la forma en que la organización funciona. -

-
-

Analizamos procesos, información, roles e indicadores para identificar oportunidades de mejora, reducir ineficiencias y fortalecer la capacidad de gestión y toma de decisiones.

-

+

DESARROLLO DE CAPACIDADES

+

Para transformar conocimiento en capacidad de acción.

+
+

Diseñamos experiencias de aprendizaje que conectan conocimiento, práctica y contexto para desarrollar las capacidades que personas y equipos necesitan para gestionar, liderar y transformar.

-
- Integramos tableros de control digital de incidentes a través de IDE Digital. +
+ Formamos a tus Project Managers internos mediante los programas de IDE Academy.
- + Explorar soluciones →
-
+
-
- IDE Excellence - EDUCACIÓN -
-

PROYECTOS Y PMO

-

- Para convertir iniciativas en resultados. -

-
-

Diseñamos y fortalecemos la gestión de proyectos, programas y portafolios para mejorar la priorización, coordinación, gobernanza y ejecución de iniciativas estratégicas.

-

+

PROCESOS Y MEJORA ORGANIZACIONAL

+

Para transformar la forma en que la organización funciona.

+
+

Analizamos procesos, información, roles e indicadores para identificar oportunidades de mejora, reducir ineficiencias y fortalecer la capacidad de gestión y toma de decisiones.

-
- Complementamos con diseño instruccional y campus virtual vía IDE Academy. +
+ Integramos tableros de control digital de incidentes a través de IDE Digital.
- + Explorar soluciones →
-
+
-
- IDE Project - DIRECCIÓN ESTRATÉGICA -
-

DESARROLLO DE CAPACIDADES

-

- Para transformar conocimiento en capacidad de acción. -

-
-

Diseñamos experiencias de aprendizaje que conectan conocimiento, práctica y contexto para desarrollar las capacidades que personas y equipos necesitan para gestionar, liderar y transformar.

-

+

PROYECTOS Y PMO

+

Para convertir iniciativas en resultados.

+
+

Diseñamos y fortalecemos la gestión de proyectos, programas y portafolios para mejorar la priorización, coordinación, gobernanza y ejecución de iniciativas estratégicas.

-
- Formamos a tus Project Managers internos mediante los programas de IDE Academy. +
+ Complementamos con diseño instruccional y campus virtual vía IDE Academy.
- + Explorar soluciones →
@@ -182,24 +155,18 @@
-
- IDE Academy - DESARROLLO DE TALENTO -
-

TRANSFORMACIÓN DIGITAL E INTELIGENCIA ARTIFICIAL

-

- Para poner la tecnología al servicio de la gestión. -

-

Identificamos dónde la digitalización, la automatización y la inteligencia artificial pueden simplificar procesos, mejorar decisiones y generar valor real para la organización.

-

+

TRANSFORMACIÓN DIGITAL E INTELIGENCIA ARTIFICIAL

+

Para poner la tecnología al servicio de la gestión.

+
+

Identificamos dónde la digitalización, la automatización y la inteligencia artificial pueden simplificar procesos, mejorar decisiones y generar valor real para la organización.

-
+
Conocé los programas abiertos y temarios en nuestra página de IDE Academy.
- + Explorar soluciones →
@@ -208,58 +175,40 @@
-
- IDE Digital - AUTOMATIZACIÓN -
-

EDUCACIÓN & GOBIERNO

-

- Para transformar conocimiento, procesos y capacidades en mejores servicios y resultados. -

-
-

Integramos sistemas de gestión, procesos, proyectos, gestión del conocimiento, indicadores, desarrollo de capacidades y tecnología para fortalecer organizaciones educativas, organismos públicos e instituciones que brindan servicios de formación.

-

+

SOLUCIONES SECTORIALES

+

Para responder a desafíos que requieren conocimiento del contexto.

+
+

Integramos gestión, procesos, proyectos, sistemas, capacidades y tecnología para abordar requisitos y desafíos específicos de cada actividad.

-
-
- Alineamos la tecnología con la estructura de procesos definida por IDE Excellence. +
+ Alineamos la tecnología con la estructura de procesos definida por IDE Excellence.
- + Explorar soluciones →
- - +
-
- IDE Digital - AUTOMATIZACIÓN +

EDUCACIÓN & GOBIERNO

+

Para transformar conocimiento, procesos y capacidades en mejores servicios y resultados.

+
+

Integramos sistemas de gestión, procesos, proyectos, gestión del conocimiento, indicadores, desarrollo de capacidades y tecnología para fortalecer organizaciones educativas, organismos públicos e instituciones que brindan servicios de formación.

-

SOLUCIONES SECTORIALES

-

- Para responder a desafíos que requieren conocimiento del contexto. -

-
-

Integramos gestión, procesos, proyectos, sistemas, capacidades y tecnología para abordar requisitos y desafíos específicos de cada actividad.

-

-
-
- Alineamos la tecnología con la estructura de procesos definida por IDE Excellence. +
+ Alineamos la tecnología con la estructura de procesos definida por IDE Excellence.
- + Explorar soluciones →
-
- +
-
@@ -273,6 +222,294 @@ HABLEMOS →
+ + + + + + + + + + + + + +