diff --git a/Instructivo detallado para Antigravity.md b/Instructivo detallado para Antigravity.md deleted file mode 100644 index e9cbbc2..0000000 --- a/Instructivo detallado para Antigravity.md +++ /dev/null @@ -1,220 +0,0 @@ -# INSTRUCTIVO TÉCNICO Y DE DISEÑO: REFACTORIZACIÓN DEFINITIVA WEB "IDE CONSULTORES" - -Este documento contiene las especificaciones técnicas (HTML5, CSS3, JavaScript), de interfaz (UI/UX) y de redacción comercial (Copywriting) para guiar la corrección y reestructuración total del sitio web demo de **IDE Consultores**. - -El objetivo es eliminar todo aspecto genérico o sintético ("aspecto de IA") y sustituirlo por una presencia digital auténtica, minimalista, ejecutiva y orientada a la conversión, donde convivan fluidamente el storytelling sistémico y la búsqueda de soluciones técnicas directas. - ---- - -## 1. PRINCIPIOS DE DISEÑO Y DIRECTRICES TÉCNICAS GLOBALES - -1. **Estilo Visual e Identidad:** - - * **Minimalismo ejecutivo:** Espacios en blanco amplios, composiciones geométricas limpias, sin saturación de gradientes ni fondos oscuros pesados. - * **Tipografía:** Jerarquía estricta. Fuentes sans-serif modernas y legibles (`Poppins` para títulos principales / `Inter` o `Mulish` para texto de lectura y metadatos). - * **Paleta Cromática del Ecosistema: (variables en styles.css)** - * **Color Institucional / Base:** --ide-primary y --ide-accent - * **IDE Excellence:** --ide-excellence. - * **IDE Projects:** --ide-projects. - * **IDE Digital:** --ide-digital. - * **IDE Academy:** --ide-academy - - -2. **Componentes Globales Estandarizados:** - - * **Ensanchar el sitio:** Utilizar mas los anchos de la pantalla para optimizar el contenido de cada sección. - * **Buscador predictivo superior:** Agregar un botón de búsqueda (``) ubicado permanentemente en el header junto al botón principal. Debe permitir la búsqueda rápida de términos clave (*ISO 9001, Productividad, Telecomunicaciones, FTTH, PMO, Procesos, IA, Capacitación*). - * **Botón CTA Unificado:** Unificar el botón **HABLEMOS →** (`.btn-cta-unificado`). Mismo padding, border-radius (estilo píldora), color corporativo y flecha circular en todas las páginas (header, cierres de sección y footer). No utilizar textos largos como "VER CÓMO AFRONTAMOS ESTE DESAFÍO". - * **Footer Global Idéntico:** Unificar un único footer en todas las páginas con la siguiente estructura: - * Izquierda: Logotipo IDE Consultores + lema `"Convertimos la gestión en una ventaja competitiva"`. - * Centro: Navegación directa (`Inicio` | `Por dónde empezar` | `Soluciones` | `Ecosistema` | `Insights` | `Nosotros`). - * Derecha: Datos de contacto reales (`info@ideconsultores.com.ar` | Sedes: Salta y Jujuy | Teléfonos: `+54 9 388 4880536` y `+54 9 387 6132059`). - * Inferior: Enlaces legales (`Política de privacidad` y `Términos y condiciones`) + Redes sociales validadas (LinkedIn, Instagram y Facebook; verificar que el enlace de Facebook no tenga etiqueta de YouTube). - -3. **Tratamiento de Contenidos:** - - * **Insercion de imagenes de fondos:** Aplicar estilos, layers de colores, degrades y demases efectos visuales y respecto de la imagen que se insertará dejar un placeholder para que luego se escoga del repositorio cual es el archivo de imagen mas adecuado. - ---- - -## 2. ARQUITECTURA DEL SITIO Y RUTAS - -/ -├── index.html -> INICIO (Conexión sistémica, pilares, ámbitos de experiencia y Brújula) -├── desafios.html -> POR DÓNDE EMPEZAR (Identificación de problemas organizacionales) -├── soluciones.html -> SOLUCIONES (Las 6 familias de soluciones + Nivel 2 concreto) -├── ecosistema.html -> ECOSISTEMA (Infinito interactivo + Nivel 2 desplegable de unidades) -├── insights.html -> INSIGHTS (Artículos de opinión, tendencias y herramientas descargables) -└── nosotros.html -> NOSOTROS (Somos IDE: Socios reales, propósito y Trabajá con nosotros) - ---- - -## 3. TAREAS DE REFACTORIZACIÓN POR PANTALLA - -### PANTALLA 1: INICIO (`index.html`) - -1. **Header / Hero Section:** - - * **Mensaje Central:** Invertir la jerarquía. El claim rector debe ser **"CONECTAMOS EL TODO"**. - * **Pregunta de tensión:** `¿Qué pasa cuando dejamos de mirar los problemas por separado?` - * **Texto descriptivo (sintetizado):** - - > *"En IDE entendemos cómo funciona el sistema para identificar dónde intervenir, integrar las capacidades necesarias y generar valor en el conjunto."* - * **Fondo visual:** Reemplazar la animación de malla ("efecto pecera") por un fondo estático limpio con degradado hacia el texto para máxima legibilidad, acompañado de una cinta de infinito sutil con halos en los cuatro colores del ecosistema. - * **Elementos UI:** Input o botón directo con lupa para el buscador rápido + botón **HABLEMOS →**. - -2. **Sección Cuatro Pilares (Ecosistema):** - - * **Título:** `"Cuatro capacidades, un mismo propósito: generar impacto."` (en un solo renglón, sin eyebrow redundante). - * **Diseño:** Grilla 2x2 apaisada o 4 columnas limpias con tarjeta estilizada: foto real de contexto superior, ola de color distintiva, ícono vectorial y títulos en mayor escala: - * *IDE Excellence:* `PARA FORTALECER LA GESTIÓN` - * *IDE Projects:* `PARA CONVERTIR PROYECTOS EN RESULTADOS` - * *IDE Digital:* `PARA INTEGRAR TECNOLOGÍA CON PROPÓSITO` - * *IDE Academy:* `PARA DESARROLLAR CAPACIDADES` - -3. **Sección Ámbitos de Experiencia:** - - * **Estructura:** Título a la izquierda y tarjetas interactivas a la derecha. - * **Bajada:** `"Comprendemos las particularidades de cada sector para adaptar la intervención sin perder de vista el conjunto."` - * **Ajuste fotográfico:** Cambiar la foto de fondo de *Industria & Servicios* por una planta industrial/metalmecánica o línea de montaje (no alimenticia). - * **Incorporación obligatoria:** Añadir la tarjeta de **Telecomunicaciones**. - * **Comportamiento UI:** Las tarjetas solo muestran el título por defecto; el texto descriptivo aparece exclusivamente en estado `:hover`: - * *Agro & Alimentos* $\rightarrow$ `"Fortalecer operaciones y generar valor sostenible."` - * *Industria & Servicios* $\rightarrow$ `"Optimizar la gestión y potenciar la eficiencia operativa."` - * *Telecomunicaciones* $\rightarrow$ `"Impulsar conectividad eficiente mediante operaciones y proyectos integrados."` - * *Sector Salud* $\rightarrow$ `"Fortalecer la calidad, la seguridad y la experiencia del paciente."` - * *Educación & Gobierno* $\rightarrow$ `"Fortalecer la gestión y generar mejores resultados."` - -4. **Sección Incomodidad Productiva & Brújula IDE:** - - * Unificar ambas secciones en un solo bloque para optimizar la altura de la página. - * **Título:** `"¿Qué impacto tendrá esa mejora en el conjunto?"` - * **Cuerpo:** `"Una mejora puede resolver una necesidad puntual. En IDE vamos un paso más allá: ¿qué impacto tendrá esa mejora en el conjunto?"` - * **Brújula IDE:** Ubicar el componente interactivo en paralelo con una marca de agua suave de brújula. - -5. **Cierre de Conversión:** - - * Módulo limpio: `"¿Qué desafío querés transformar?"` + botón **HABLEMOS →**. - ---- - -### PANTALLA 2: POR DÓNDE EMPEZAR / DESAFÍOS (`desafios.html`) - -1. **Cabecera Asimétrica:** - - * Texto a la izquierda (en 2 líneas): `"¿Qué está pasando en tu organización?"` - * Bajada: `"A veces el desafío es evidente. Otras, aparece como una señal, una necesidad de cambio o una oportunidad. Empecemos por comprenderlo para identificar dónde intervenir."` - * Gráfico a la derecha: Cinta de infinito pausada interconectando Estrategia, Procesos, Tecnología, Personas y Resultados. - -2. **Grilla de Señales y Desafíos:** - - * Tarjetas simplificadas sin textos densos. Sustituir el botón de texto por un selector circular `+` o flecha unificada: - 1. *"La organización creció y necesitamos ordenar los procesos."* - 2. *"Necesitamos mejorar la eficiencia y los resultados."* - 3. *"Queremos desarrollar a nuestras personas y fortalecer equipos."* - 4. *"Buscamos incorporar tecnología o avanzar en la transformación digital."* - 5. *"Necesitamos fortalecer la calidad, el cumplimiento o la gestión de riesgos."* - 6. *Tarjeta de escape:* *"No sé exactamente qué necesito."* $\rightarrow$ `INICIAR BRÚJULA IDE →` - -3. **Modales de Diagnóstico:** - - * Eliminar cajas monocromáticas y etiquetas pesadas tipo "Contexto y diagnóstico". - * Estructura limpia: Preguntas disparadoras del cliente, capacidades que intervienen (etiquetas de color) y botón directo de contacto. - -4. **Cierre:** - - * `"¿Tu situación es diferente? Conversemos..."` + botón **HABLEMOS →**. - ---- - -### PANTALLA 3: ECOSISTEMA (`ecosistema.html`) - -1. **Hero del Ecosistema:** - - * **Foco Absoluto:** El infinito vectorial como protagonista sobre fondo neutro (eliminar fotos de paisajes). - * **Animación Funcional:** Ciclo de iluminación suave cada 4 segundos mostrando combinaciones reales de capacidades (e.g., *Excellence + Digital* para "sistemas de gestión con tableros en tiempo real"). - * **Acción:** Al hacer clic en un nodo o tarjeta de capacidad, desplazarse suavemente y abrir el Nivel 2 correspondiente debajo (sin abrir ventanas modales flotantes). - -2. **Arquitectura Nivel 2 (Despliegue en la misma página):** - - * Configurar anclas y URLs directas (e.g., `/ecosistema#excellence`). - * **IDE Excellence:** - * Título: `"Procesos más eficientes, organizaciones más confiables."` - * Copys revisados: Sustituir "certificación" por *"preparación y acompañamiento para certificar"* (norma ética de consultoría). - * Chips de normas: `ISO 9001` | `ISO 14001` | `ISO 45001` | `ISO 21001` | `Mejora de procesos` | `RNE / RNPA`. - * Tarjetas de soluciones con íconos vectoriales y marcas de agua suaves. - * **IDE Projects:** - * Título: `"Convertimos iniciativas en resultados concretos."` - * Ciclo de vida: `1. Planificación y diseño` $\rightarrow$ `2. Ejecución y coordinación` $\rightarrow$ `3. Control y seguimiento` $\rightarrow$ `4. Cierre y resultados`. - * Sectores clave: Incluir en primer término **Telecomunicaciones (Despliegue de redes FTTH y proyectos de conectividad)**, seguido de Industria, Construcción, Organizaciones educativas y Empresas de servicios. - * **IDE Digital:** - * Título: `"Digitalizamos procesos para generar más valor."` - * Servicios: Automatización de procesos, Integración de plataformas, Dashboards de BI, Soluciones a medida, IA aplicada y Capacitación digital. - * *Ajuste crítico:* Retirar logotipos no autorizados de terceros (SAP, WTM, TOA) salvo que exista validación documental escrita de alianzas. - * **IDE Academy:** - * Tarjeta con botón de redirección directa al sitio específico de Academy (`/academy` o página dedicada). - -3. **Preguntas Frecuentes (FAQ):** - - * Acordeón desplegable nativo (`
...`) que resuelva objeciones comerciales reales: alcance geográfico, contratación independiente de capacidades y seguimiento post-implementación. - ---- - -### PANTALLA 4: IDE ACADEMY (`academy.html`) - -1. **Estilo:** Paleta borgoña (`#C21E3A`), estética formativa moderna y académica. -2. **Diferenciales ("Aprender con IDE"):** Tarjetas conectadas por una línea guía sutil con íconos vectoriales (*Contexto Real*, *Aprender Haciendo*, *Mirada Integral*, *Intercambio que Enriquece*, *Aplicación que Continúa*). -3. **Próximas Experiencias:** Carrusel o grilla de 3 cursos destacados con metadatos clave (modalidad sincrónica/presencial, duración en horas, nivel de complejidad y fecha). -4. **Formación In-Company:** Distribución en 3 columnas: (1) Texto conceptual, (2) Bullets de formatos (Cursos, Workshops, Programas, Rutas de aprendizaje) y (3) Fotografía real de capacitación en planta/oficina. -5. **Ajuste de contenido:** **Eliminar** la sección *"Quiénes facilitan el aprendizaje"* en Academy para no duplicar los perfiles de los socios que ya se presentan en la página institucional. -6. **Campus y Recursos:** Bloque dividido al 50%: botón de acceso a *Campus IDE (LMS)* y botón a *Herramientas descargables (plantillas Excel, Business Model Canvas, etc.)*. - ---- - -### PANTALLA 5: SOLUCIONES (`soluciones.html`) - -1. **Hero:** Continuidad visual con la cabecera de Desafíos (paso de la detección a la ejecución). -2. **Las Seis Familias:** Grilla de 6 tarjetas con diseño minimalista e íconos de trazo fino: - * *Procesos y gestión* - * *Proyectos e innovación* - * *Tecnología e IA* - * *Personas y desarrollo* - * *Calidad, riesgos y cumplimiento* - * *Sostenibilidad y valor* -3. **Modales de Solución:** Ventana limpia con resumen ejecutivo, listado estructurado de normas/servicios en bullets y botón directo de contacto. -4. **Soluciones Relacionadas:** Módulo inferior que refuerza la sinergia con las cuatro unidades del Ecosistema antes del CTA final. - ---- - -### PANTALLA 6: SOMOS IDE & TRABAJÁ CON NOSOTROS (`nosotros.html`) - -1. **Apertura:** Claim institucional: `"Vemos organizaciones. Entendemos sistemas. Conectamos el todo."` junto a la foto grupal real `team4.jpg`. -2. **Filosofía de Trabajo:** Síntesis visual mediante íconos y textos breves de los Principios Guía (*Mirada Sistémica*, *Rigor con sentido práctico*, *Personas como parte del Sistema*, *Capacidades que permanecen*). -3. **Equipo Directivo (Perfiles Reales de los 4 Socios):** - * Reemplazar maquetas previas por las fotografías reales: - * **Claudia Raquel Andrés (`CRA.png`):** Socia Fundadora | Estrategia y Gestión de la Calidad. - * **José Alberto Pugliese (`JAP.png`):** Socio | Proyectos y Metodologías Ágiles. - * **Miguel Ángel Rojas (`MAR.png`):** Socio | Operaciones, Infraestructura y Mejora Continua. - * **Víctor Ulises Barrionuevo (`VUB.png`):** Socio | Telecomunicaciones y Operaciones de Red. - * **Tarjeta de Red de Especialistas:** Incluir como quinto elemento la tarjeta: *"Y una red de consultores y especialistas que nos permite llevar la mejor solución a cada desafío"*. - * **Enlaces a LinkedIn:** Ícono vectorial en tono oscuro/monocromático con enlace verificado a cada perfil: - * Claudia Raquel Andrés: `https://www.linkedin.com/in/claudia-raquel-andres/` - * José Alberto Pugliese: `https://www.linkedin.com/in/ing-josé-pugliese-706445413/` - * Miguel Ángel Rojas: `https://www.linkedin.com/in/ingenieromiguelrojas/` - * Víctor Ulises Barrionuevo: `www.linkedin.com/in/victor-ulises-barrionuevo` -4. **Eliminación:** Quitar la sección *"Estándares Globales"*. -5. **Trabajá con Nosotros:** Formulario limpio con campos: Nombre y apellido, Email, Teléfono, Ciudad/País, Área de interés, Mensaje, campo para CV/LinkedIn y casilla de consentimiento legal. Acompañar con la frase de cierre: `"El cambio también se construye en equipo."` - ---- - -## 4. CHECKLIST DE CONTROL DE CALIDAD PARA LA IA DE CÓDIGO - -- [ ] ¿El header tiene el buscador predictivo (lupa) de forma fija junto al botón de contacto? -- [ ] ¿El botón "HABLEMOS →" mantiene idéntico tamaño, padding, radio de borde y tipografía en todo el sitio? -- [ ] ¿Se eliminaron los fondos con movimiento rápido ("efecto pecera") y el grafo de 35 nodos? -- [ ] ¿La categoría "Telecomunicaciones" y los proyectos FTTH están integrados en Ámbitos de Experiencia y en IDE Projects? -- [ ] ¿Se reemplazaron todas las fotos del equipo por los archivos `CRA.png`, `JAP.png`, `MAR.png`, `VUB.png` y `team4.jpg`? -- [ ] ¿Los perfiles de los socios tienen sus enlaces de LinkedIn correctos en formato monocromático? -- [ ] ¿En IDE Excellence se corrigió la redacción a "preparación para certificar" en lugar de adjudicarse la certificación? -- [ ] ¿Se eliminó la sección duplicada de facilitadores en IDE Academy? -- [ ] ¿El footer es exactamente igual y homogéneo en todas las páginas? diff --git a/animacion2.html b/animacion2.html deleted file mode 100644 index 35d81cb..0000000 --- a/animacion2.html +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - Animación Nodos Infinito - Pulsos Aleatorios - - - - -
-
- - - - -
-
-
- - - - \ No newline at end of file diff --git a/assets/iconos/agro_color.svg b/assets/iconos/agro_color.svg deleted file mode 100644 index dd7db6d..0000000 --- a/assets/iconos/agro_color.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/assets/iconos/balanza_color.svg b/assets/iconos/balanza_color.svg deleted file mode 100644 index f1cf52c..0000000 --- a/assets/iconos/balanza_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/binocular_color.svg b/assets/iconos/binocular_color.svg deleted file mode 100644 index c8998a0..0000000 --- a/assets/iconos/binocular_color.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/book_color.svg b/assets/iconos/book_color.svg deleted file mode 100644 index b13e27c..0000000 --- a/assets/iconos/book_color.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/boss_color.svg b/assets/iconos/boss_color.svg deleted file mode 100644 index 47a1f1c..0000000 --- a/assets/iconos/boss_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/bot-2_color.svg b/assets/iconos/bot-2_color.svg deleted file mode 100644 index f09f6e8..0000000 --- a/assets/iconos/bot-2_color.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/bot_color.svg b/assets/iconos/bot_color.svg deleted file mode 100644 index 94904fc..0000000 --- a/assets/iconos/bot_color.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/brujula_color.svg b/assets/iconos/brujula_color.svg deleted file mode 100644 index a55bb9c..0000000 --- a/assets/iconos/brujula_color.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/calendar_color.svg b/assets/iconos/calendar_color.svg deleted file mode 100644 index 9cb0b91..0000000 --- a/assets/iconos/calendar_color.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/camion_color.svg b/assets/iconos/camion_color.svg deleted file mode 100644 index 0b42d1d..0000000 --- a/assets/iconos/camion_color.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/cohete_color.svg b/assets/iconos/cohete_color.svg deleted file mode 100644 index 23aca8d..0000000 --- a/assets/iconos/cohete_color.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/dart_32.svg b/assets/iconos/dart_32.svg deleted file mode 100644 index 1fcb17a..0000000 --- a/assets/iconos/dart_32.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/assets/iconos/dart_color.svg b/assets/iconos/dart_color.svg deleted file mode 100644 index 8e61173..0000000 --- a/assets/iconos/dart_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/edificio_color.svg b/assets/iconos/edificio_color.svg deleted file mode 100644 index 39e81e7..0000000 --- a/assets/iconos/edificio_color.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/engranage_color.svg b/assets/iconos/engranage_color.svg deleted file mode 100644 index d53ae6d..0000000 --- a/assets/iconos/engranage_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/engranaje_32.svg b/assets/iconos/engranaje_32.svg deleted file mode 100644 index a6e87cf..0000000 --- a/assets/iconos/engranaje_32.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/assets/iconos/escuela_color.svg b/assets/iconos/escuela_color.svg deleted file mode 100644 index 1f2ed73..0000000 --- a/assets/iconos/escuela_color.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - diff --git a/assets/iconos/fabrica_color.svg b/assets/iconos/fabrica_color.svg deleted file mode 100644 index 149ce00..0000000 --- a/assets/iconos/fabrica_color.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/assets/iconos/globo_color.svg b/assets/iconos/globo_color.svg deleted file mode 100644 index 74e69e0..0000000 --- a/assets/iconos/globo_color.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/gorro_32.svg b/assets/iconos/gorro_32.svg deleted file mode 100644 index 0a8c499..0000000 --- a/assets/iconos/gorro_32.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/assets/iconos/gorro_color.svg b/assets/iconos/gorro_color.svg deleted file mode 100644 index 8953f90..0000000 --- a/assets/iconos/gorro_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/grafico_color.svg b/assets/iconos/grafico_color.svg deleted file mode 100644 index 907ef52..0000000 --- a/assets/iconos/grafico_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/list-ok_color.svg b/assets/iconos/list-ok_color.svg deleted file mode 100644 index 2e5394b..0000000 --- a/assets/iconos/list-ok_color.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/lista_32.svg b/assets/iconos/lista_32.svg deleted file mode 100644 index 71a7194..0000000 --- a/assets/iconos/lista_32.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/assets/iconos/lista_color.svg b/assets/iconos/lista_color.svg deleted file mode 100644 index 5ad5048..0000000 --- a/assets/iconos/lista_color.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/lupa_32.svg b/assets/iconos/lupa_32.svg deleted file mode 100644 index cc9ad3a..0000000 --- a/assets/iconos/lupa_32.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/assets/iconos/lupa_color.svg b/assets/iconos/lupa_color.svg deleted file mode 100644 index c16fb5f..0000000 --- a/assets/iconos/lupa_color.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/map_color.svg b/assets/iconos/map_color.svg deleted file mode 100644 index 6a7ff13..0000000 --- a/assets/iconos/map_color.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/mundo_color.svg b/assets/iconos/mundo_color.svg deleted file mode 100644 index d59b3ba..0000000 --- a/assets/iconos/mundo_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/nurse_color.svg b/assets/iconos/nurse_color.svg deleted file mode 100644 index a0cae11..0000000 --- a/assets/iconos/nurse_color.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - diff --git a/assets/iconos/pin_color.svg b/assets/iconos/pin_color.svg deleted file mode 100644 index abcdafb..0000000 --- a/assets/iconos/pin_color.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/plan_color.svg b/assets/iconos/plan_color.svg deleted file mode 100644 index b35854a..0000000 --- a/assets/iconos/plan_color.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/portafolio_color.svg b/assets/iconos/portafolio_color.svg deleted file mode 100644 index c218ee6..0000000 --- a/assets/iconos/portafolio_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/proceso_color.svg b/assets/iconos/proceso_color.svg deleted file mode 100644 index d420a69..0000000 --- a/assets/iconos/proceso_color.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/project_color.svg b/assets/iconos/project_color.svg deleted file mode 100644 index cea1314..0000000 --- a/assets/iconos/project_color.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/seed_color.svg b/assets/iconos/seed_color.svg deleted file mode 100644 index 87f7477..0000000 --- a/assets/iconos/seed_color.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/team_color.svg b/assets/iconos/team_color.svg deleted file mode 100644 index 311c404..0000000 --- a/assets/iconos/team_color.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/telescopio_color.svg b/assets/iconos/telescopio_color.svg deleted file mode 100644 index 8f09e5f..0000000 --- a/assets/iconos/telescopio_color.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/assets/iconos/transform_color.svg b/assets/iconos/transform_color.svg deleted file mode 100644 index 8aaf365..0000000 --- a/assets/iconos/transform_color.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/img/1790382805.png b/assets/img/1790382805.png deleted file mode 100644 index d2c2455..0000000 Binary files a/assets/img/1790382805.png and /dev/null differ diff --git a/assets/img/culture.png b/assets/img/culture.png deleted file mode 100644 index 0a1a3f0..0000000 Binary files a/assets/img/culture.png and /dev/null differ diff --git a/assets/img/cursos.png b/assets/img/cursos.png deleted file mode 100644 index 59384d1..0000000 Binary files a/assets/img/cursos.png and /dev/null differ diff --git a/assets/img/equipo.png b/assets/img/equipo.png deleted file mode 100644 index 5053261..0000000 Binary files a/assets/img/equipo.png and /dev/null differ diff --git a/assets/img/fabrica3.jpg b/assets/img/fabrica3.jpg deleted file mode 100644 index 35f5192..0000000 Binary files a/assets/img/fabrica3.jpg and /dev/null differ diff --git a/assets/img/ide-insights.png b/assets/img/ide-insights.png deleted file mode 100644 index 584622d..0000000 Binary files a/assets/img/ide-insights.png and /dev/null differ diff --git a/assets/limpiar-iconos.py b/assets/limpiar-iconos.py deleted file mode 100644 index caf88a7..0000000 --- a/assets/limpiar-iconos.py +++ /dev/null @@ -1,110 +0,0 @@ -import os -import xml.etree.ElementTree as ET -from pathlib import Path -import shutil - -def convertir_a_current_color(archivo_entrada, archivo_salida=None, backup=True): - """ - Convierte todos los colores fijos en un SVG a currentColor. - Preserva las opacidades y transparencias. - """ - - if archivo_salida is None: - path = Path(archivo_entrada) - archivo_salida = path.parent / f"{path.stem}_color{path.suffix}" - - try: - # Leer el archivo - with open(archivo_entrada, 'r', encoding='utf-8') as f: - contenido = f.read() - - # Parsear XML - tree = ET.ElementTree(ET.fromstring(contenido)) - root = tree.getroot() - - # Registrar namespace - ET.register_namespace('', 'http://www.w3.org/2000/svg') - - # Procesar TODOS los elementos con fill o stroke - elementos_modificados = 0 - - for elem in root.iter(): - # Procesar fill - if 'fill' in elem.attrib: - fill = elem.get('fill') - # Si no es none, ni currentColor, ni url(), reemplazar - if fill and fill.lower() not in ['none', 'currentcolor'] and not fill.startswith('url'): - elem.set('fill', 'currentColor') - elementos_modificados += 1 - - # Procesar stroke - if 'stroke' in elem.attrib: - stroke = elem.get('stroke') - if stroke and stroke.lower() not in ['none', 'currentcolor'] and not stroke.startswith('url'): - elem.set('stroke', 'currentColor') - elementos_modificados += 1 - - # Limpiar metadata innecesaria (opcional) - for metadata in root.findall('.//metadata'): - parent = root.find('.//g') or root - if parent is not None: - parent.remove(metadata) - - # Guardar el archivo - tree.write(archivo_salida, encoding='utf-8', xml_declaration=True) - - print(f"✅ {Path(archivo_entrada).name} → {elementos_modificados} elementos convertidos") - return True - - except Exception as e: - print(f"❌ Error con {archivo_entrada}: {str(e)}") - return False - -def procesar_carpeta(carpeta): - """ - Procesa todos los SVG en una carpeta - """ - carpeta_path = Path(carpeta) - - if not carpeta_path.exists(): - print(f"❌ La carpeta {carpeta} no existe") - return - - # Buscar todos los SVG (excepto los que ya tienen _color) - archivos = [f for f in carpeta_path.glob('*.svg') if '_color' not in f.name] - - if not archivos: - print(f"⚠️ No se encontraron archivos SVG en {carpeta}") - return - - print(f"🔍 Encontrados {len(archivos)} archivos") - print("=" * 50) - - # Crear carpeta de backup - backup_dir = carpeta_path / 'backup_originales' - backup_dir.mkdir(exist_ok=True) - - for archivo in archivos: - # Hacer backup - shutil.copy2(archivo, backup_dir / archivo.name) - - # Generar nombre de salida (sobrescribir el original o crear nuevo) - # Opción 1: Sobrescribir el original (CUIDADO) - # salida = archivo - - # Opción 2: Crear nuevo archivo con sufijo _color (RECOMENDADO) - salida = archivo.parent / f"{archivo.stem}_color{archivo.suffix}" - - convertir_a_current_color(str(archivo), str(salida)) - - print("=" * 50) - print(f"💾 Backups guardados en: {backup_dir}") - print(f"📁 Archivos convertidos con sufijo '_color'") - -# ============= EJECUTAR ============= - -if __name__ == "__main__": - # Cambia esta ruta a tu carpeta de iconos - CARPETA = "./iconos" # Tu ruta - - procesar_carpeta(CARPETA) \ No newline at end of file diff --git a/assets/logos/academy_b.png b/assets/logos/academy_b.png new file mode 100644 index 0000000..6970aca Binary files /dev/null and b/assets/logos/academy_b.png differ diff --git a/assets/logos/digital_b.png b/assets/logos/digital_b.png new file mode 100644 index 0000000..5bb6c52 Binary files /dev/null and b/assets/logos/digital_b.png differ diff --git a/assets/logos/excellence_b.png b/assets/logos/excellence_b.png new file mode 100644 index 0000000..c5ff6f2 Binary files /dev/null and b/assets/logos/excellence_b.png differ diff --git a/assets/logos/ide.png b/assets/logos/ide.png new file mode 100644 index 0000000..ac2d1ee Binary files /dev/null and b/assets/logos/ide.png differ diff --git a/assets/logos/projects_b.png b/assets/logos/projects_b.png new file mode 100644 index 0000000..b11a239 Binary files /dev/null and b/assets/logos/projects_b.png differ diff --git a/css/ecosistema.css b/css/ecosistema.css new file mode 100644 index 0000000..0f73395 --- /dev/null +++ b/css/ecosistema.css @@ -0,0 +1,548 @@ +.animacion-infinito { + width: 80%; + min-width: 600px; + max-width: 1000px; + aspect-ratio: 2 / 1; + position: relative; + background-color: transparent; + } + + .capa-svg-lineas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; + /* Fuerza al navegador a usar la Tarjeta Gráfica (GPU) */ + transform: translateZ(0); + } + + .capa-html-nodos { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 10; + pointer-events: none; + } + + .nodo-circulo { + position: absolute; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0 12px 25px rgba(0, 0, 0, 0.15), inset 0 -4px 10px rgba(0,0,0,0.1); + transform: translate(-50%, -50%); + pointer-events: auto; + transition: transform 0.3s ease, box-shadow 0.3s ease; + overflow: hidden; + background-color: #fff; /* Fondo por si usas logos PNG transparentes */ + } + + .nodo-circulo:hover { + transform: translate(-50%, -55%) scale(1.05); + box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2); + cursor: pointer; + } + + /* Estilos para insertar logos como pediste */ + .nodo-contenido { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + } + + .nodo-contenido img { + width: 70%; /* Ajusta el tamaño de tu logo aquí */ + height: 70%; + object-fit: contain; + } + + /* Estilos de las líneas base SVG */ + .linea-base { + fill: none; + stroke-width: 1.5; + opacity: 0.5; + } + + /* Estilo de los Pulsos */ + .linea-pulso { + fill: none; + stroke: #ffffff; + stroke-width: 6; + stroke-linecap: round; + stroke-dasharray: 0 2000; + filter: drop-shadow(0 0 3px rgba(255, 255, 255, 1)) drop-shadow(0 0 8px rgba(255, 255, 255, 0.8)); + opacity: 1; + /* Le avisa al navegador que esto es lo único que se va a animar */ + will-change: stroke-dashoffset; + } + +/* ========================================================================== + ECOSISTEMA IDE — Sección con 4 tarjetas y paneles expandibles in-place + ========================================================================== */ + +/* ---------- Variables locales por unidad ---------- */ +.ecosistema-section { + --unit: var(--ide-primary); + --unit-dark: var(--ide-primary-dark); + --unit-soft: rgba(30, 74, 94, 0.10); +} + +.eco-panel--excellence, +.eco-card--excellence, +.eco-pill--excellence { --unit: var(--ide-excellence); --unit-dark: var(--ide-excellence-dark); --unit-soft: rgba(0, 158, 143, 0.10); } + +.eco-panel--projects, +.eco-card--projects, +.eco-pill--projects { --unit: var(--ide-projects); --unit-dark: var(--ide-projects-dark); --unit-soft: rgba(242, 140, 43, 0.10); } + +.eco-panel--digital, +.eco-card--digital, +.eco-pill--digital { --unit: var(--ide-digital); --unit-dark: var(--ide-digital-dark); --unit-soft: rgba(29, 113, 184, 0.10); } + +.eco-panel--academy, +.eco-card--academy, +.eco-pill--academy { --unit: var(--ide-academy); --unit-dark: var(--ide-academy-dark); --unit-soft: rgba(200, 16, 46, 0.10); } + +/* ---------- Header del ecosistema ---------- */ +.eco-header { + text-align: center; + max-width: 820px; + margin: 0 auto 3rem; +} + +.eco-header__lead { + margin: 1rem auto 0; + text-align: center; +} + +/* ---------- Grid de 4 tarjetas ---------- */ +.eco-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1.5rem; +} + +.eco-card { + position: relative; + border-radius: var(--radius-lg); + overflow: hidden; + background: var(--bg-surface); + border: 1px solid var(--border-color); + transition: transform .35s ease, border-color .35s ease, box-shadow .35s ease; +} + +.eco-card:hover { + transform: translateY(-6px); + border-color: var(--unit); + box-shadow: 0 18px 40px -18px color-mix(in srgb, var(--unit) 45%, transparent); +} + +.eco-card__btn { + all: unset; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: .85rem; + padding: 2rem 1.6rem 1.75rem; + width: 100%; + height: 100%; + cursor: pointer; + position: relative; + z-index: 1; +} + +.eco-card__btn:focus-visible { + outline: 2px solid var(--unit); + outline-offset: -4px; + border-radius: var(--radius-lg); +} + +/* Ícono circular */ +.eco-card__icon-wrap { + width: 64px; + height: 64px; + border-radius: 50%; + display: grid; + place-items: center; + background: var(--unit-soft); + color: var(--unit); + border: 1px solid color-mix(in srgb, var(--unit) 35%, transparent); + transition: background .35s ease, transform .35s ease; +} + +.eco-card:hover .eco-card__icon-wrap { + background: var(--unit); + color: #fff; + transform: scale(1.06); +} + +.eco-card__icon { font-size: 1.5rem; } + +.eco-card__badge { + font-family: 'Bebas Neue', sans-serif; + letter-spacing: .32em; + font-size: .85rem; + color: var(--unit); + text-transform: uppercase; +} + +.eco-card__title { + font-family: 'Barlow Semi Condensed', sans-serif; + font-size: 1.25rem; + line-height: 1.2; + color: var(--text-main); + margin: 0; +} + +.eco-card__text { + font-size: .9rem; + color: var(--text-muted); + line-height: 1.55; + margin: 0 0 auto; +} + +.eco-card__cta { + display: inline-flex; + align-items: center; + gap: .5rem; + font-family: 'Barlow Condensed', sans-serif; + font-weight: 600; + text-transform: uppercase; + letter-spacing: .06em; + font-size: .9rem; + color: var(--unit); + margin-top: .5rem; +} + +.eco-card__cta i { transition: transform .3s ease; } +.eco-card:hover .eco-card__cta i { transform: translateX(5px); } + +/* Curva decorativa inferior por tarjeta */ +.eco-card::after { + content: ""; + position: absolute; + inset: auto -20% -40% -20%; + height: 60%; + background: radial-gradient(closest-side, var(--unit-soft), transparent 70%); + pointer-events: none; + opacity: .8; + transition: opacity .35s ease; +} +.eco-card:hover::after { opacity: 1; } + +/* ========================================================================== + ESTADO UNIDAD + ========================================================================== */ + +.eco-state--unit { + position: relative; + animation: ecoFadeIn .45s ease both; +} + +@keyframes ecoFadeIn { + from { opacity: 0; transform: translateY(12px); } + to { opacity: 1; transform: translateY(0); } +} + +/* ---------- Topbar (volver + pills) ---------- */ +.eco-unit__topbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + margin-bottom: 1.5rem; + flex-wrap: wrap; +} + +.eco-unit__back { + all: unset; + display: inline-flex; + align-items: center; + gap: .55rem; + padding: .55rem 1rem; + border-radius: var(--radius-full); + border: 1px solid var(--border-color); + background: var(--bg-surface); + color: var(--text-body); + cursor: pointer; + font-family: 'Barlow Condensed', sans-serif; + font-weight: 600; + letter-spacing: .05em; + text-transform: uppercase; + font-size: .9rem; + transition: all .25s ease; +} + +.eco-unit__back:hover { + border-color: var(--unit); + color: var(--unit); + transform: translateX(-3px); +} + +.eco-unit__nav { + display: flex; + flex-wrap: wrap; + gap: .5rem; +} + +.eco-pill { + all: unset; + display: inline-flex; + align-items: center; + gap: .4rem; + padding: .45rem 1rem; + border-radius: var(--radius-full); + border: 1px solid var(--border-color); + background: var(--bg-surface); + color: var(--text-body); + font-family: 'Barlow Condensed', sans-serif; + font-weight: 600; + letter-spacing: .05em; + text-transform: uppercase; + font-size: .85rem; + cursor: pointer; + transition: all .25s ease; +} + +.eco-pill:hover, +.eco-pill.is-active { + background: var(--unit); + border-color: var(--unit); + color: #fff; +} + +/* ---------- Panel de unidad ---------- */ +.eco-panel { + position: relative; + border-radius: var(--radius-lg); + overflow: hidden; + background: var(--bg-surface); + border: 1px solid var(--border-color); + padding: clamp(2rem, 4vw, 3rem); + isolation: isolate; +} + +/* Fondo con curvas SVG teñidas por el color de la unidad */ +.eco-panel__bg { + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + color: var(--unit); + opacity: .12; +} + +.eco-panel__bg svg { + width: 100%; + height: 100%; +} + +.eco-panel__bg path { + fill: none; + stroke: currentColor; + stroke-width: 1.4; + stroke-linecap: round; +} + +.eco-panel__bg path:nth-child(1) { opacity: .9; } +.eco-panel__bg path:nth-child(2) { opacity: .5; } + +/* Grid principal del panel */ +.eco-panel__grid { + position: relative; + z-index: 1; + display: grid; + grid-template-columns: 1.1fr 1fr; + gap: 2.5rem; + align-items: start; + margin-bottom: 2.5rem; +} + +.eco-panel__brand { + display: inline-block; + font-family: 'Bebas Neue', sans-serif; + letter-spacing: .32em; + font-size: 1rem; + color: var(--unit); + margin-bottom: .75rem; +} + +.eco-panel__title { + font-family: 'Barlow Semi Condensed', sans-serif; + font-size: clamp(1.8rem, 3vw, 2.4rem); + line-height: 1.15; + color: var(--text-main); + margin-bottom: 1rem; +} + +.eco-panel__lead { + font-size: 1.02rem; + color: var(--text-body); + line-height: 1.65; + margin-bottom: 1.5rem; + max-width: 52ch; +} + +.eco-panel__cta { + background-color: var(--unit); + border-color: var(--unit); +} +.eco-panel__cta:hover { + background-color: var(--unit-dark); + border-color: var(--unit-dark); +} + +/* Lista lateral de capacidades */ +.eco-panel__side { + background: color-mix(in srgb, var(--unit) 5%, var(--bg-surface)); + border: 1px solid color-mix(in srgb, var(--unit) 22%, var(--border-color)); + border-radius: var(--radius-md); + padding: 1.5rem 1.4rem; +} + +.eco-panel__side-title { + font-family: 'Barlow Condensed', sans-serif; + font-weight: 700; + text-transform: uppercase; + letter-spacing: .08em; + font-size: .95rem; + color: var(--unit); + margin-bottom: 1rem; +} + +.eco-panel__list { + list-style: none; + display: grid; + gap: .9rem; + margin: 0; + padding: 0; +} + +.eco-panel__list li { + display: flex; + gap: .75rem; + align-items: flex-start; +} + +.eco-panel__li-icon { + flex-shrink: 0; + width: 34px; + height: 34px; + border-radius: 50%; + display: grid; + place-items: center; + background: var(--unit-soft); + color: var(--unit); + font-size: .85rem; +} + +.eco-panel__list strong { + display: block; + font-family: 'Barlow Condensed', sans-serif; + font-weight: 700; + font-size: 1rem; + color: var(--text-main); + letter-spacing: .02em; +} + +.eco-panel__list p { + font-size: .85rem; + color: var(--text-muted); + line-height: 1.45; + margin: .1rem 0 0; +} + +/* Franja inferior con minicards */ +.eco-panel__strip { + position: relative; + z-index: 1; + border-top: 1px solid color-mix(in srgb, var(--unit) 20%, var(--border-color)); + padding-top: 1.75rem; +} + +.eco-panel__strip-title { + font-family: 'Barlow Semi Condensed', sans-serif; + font-size: 1.1rem; + color: var(--text-main); + margin-bottom: 1rem; +} + +.eco-panel__strip-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1rem; +} + +.eco-mini { + display: flex; + align-items: center; + gap: .65rem; + padding: .85rem 1rem; + border-radius: var(--radius-md); + background: color-mix(in srgb, var(--unit) 6%, var(--bg-surface)); + border: 1px solid color-mix(in srgb, var(--unit) 18%, var(--border-color)); + font-family: 'Barlow Condensed', sans-serif; + font-weight: 600; + font-size: .92rem; + color: var(--text-main); + letter-spacing: .02em; + transition: transform .25s ease, border-color .25s ease; +} + +.eco-mini:hover { + transform: translateY(-3px); + border-color: var(--unit); +} + +.eco-mini i { + color: var(--unit); + font-size: 1rem; +} + +/* ========================================================================== + RESPONSIVE (desktop-first, degradación limpia) + ========================================================================== */ + +@media (max-width: 1100px) { + .eco-grid { grid-template-columns: repeat(2, 1fr); } + .eco-panel__grid { grid-template-columns: 1fr; gap: 1.75rem; } + .eco-panel__strip-grid { grid-template-columns: repeat(2, 1fr); } +} + +@media (max-width: 640px) { + .eco-grid { grid-template-columns: 1fr; } + .eco-panel { padding: 1.5rem; } + .eco-panel__strip-grid { grid-template-columns: 1fr; } + .eco-unit__topbar { flex-direction: column; align-items: stretch; } + .eco-unit__nav { justify-content: flex-start; } +} + +/* Modo oscuro: ajustes finos */ +[data-theme="dark"] .eco-card, +[data-theme="dark"] .eco-panel { + background: var(--bg-surface); +} +[data-theme="dark"] .eco-panel__side, +[data-theme="dark"] .eco-mini { + background: color-mix(in srgb, var(--unit) 10%, var(--bg-surface)); +} + +/* Accesibilidad: reduce motion */ +@media (prefers-reduced-motion: reduce) { + .eco-card, + .eco-card__icon-wrap, + .eco-card__cta i, + .eco-mini, + .eco-unit__back, + .eco-state--unit { + transition: none !important; + animation: none !important; + } +} \ No newline at end of file diff --git a/css/styles.css b/css/styles.css index 4a7aa63..c0ce2cc 100644 --- a/css/styles.css +++ b/css/styles.css @@ -138,6 +138,7 @@ html { scroll-behavior: smooth; + scroll-padding-top: 80px; font-size: 16px; } @@ -191,7 +192,7 @@ button, input, select, textarea { h1 { font-family: 'Barlow Semi Condensed', sans-serif; font-weight: 700; - font-size: clamp(2.2rem, 5vw, 4.5rem); + font-size: clamp(2.1rem, 4.5vw, 4.2rem); line-height: 1.15; color: var(--text-main); letter-spacing: -0.02em; @@ -229,6 +230,35 @@ p, li, .lead-text, .text-body, .text-muted { .bg-subtle-section{ background-color: var(--bg-subtle); } +/* 1. Gradiente corporativo profundo - Ideal para Hero sections, cabeceras o footers */ +.bgl1 { + background: linear-gradient(135deg, var(--ide-primary-dark) 0%, var(--ide-primary) 100%); + color: #ffffff; +} + +/* 2. Resplandor central (Radial) - Excelente para destacar un producto, un mockup o una métrica central */ +.bgl2 { + background: radial-gradient(circle at 80% 50%, var(--bg-surface) 0%, var(--ide-primary-dark) 100%); + color: #ffffff; +} + +/* 3. Transición de marca (Azul a Verde) - Perfecto para secciones divisorias o franjas de características */ +.bgl3 { + background: linear-gradient(135deg, var(--ide-primary) 0%, var(--ide-accent-dark) 100%); + color: #ffffff; +} + +/* 4. Vibrante y fresco (Solo acentos) - Recomendado para "Call to Actions" (llamados a la acción) o tarjetas de precios */ +.bgl4 { + background: linear-gradient(135deg, var(--ide-accent) 0%, var(--ide-accent-ligth) 100%); + color: #ffffff; /* O un color oscuro dependiendo de la tipografía */ +} + +/* 5. Gradiente angular suave a 3 tonos - Un fondo moderno y dinámico para secciones de contenido extenso */ +.bgl5 { + background: linear-gradient(109.6deg, var(--ide-primary-dark) 11.2%, var(--ide-primary) 51.2%, var(--ide-primary-light) 98.6%); + color: #ffffff; +} .lead-text { font-size: 1.15rem; color: var(--text-muted); diff --git a/ecosistema-PatriPad.html b/ecosistema-PatriPad.html deleted file mode 100644 index 51c6ad9..0000000 --- a/ecosistema-PatriPad.html +++ /dev/null @@ -1,609 +0,0 @@ - - - - - - El Ecosistema IDE | Cuatro Capacidades Conectadas - IDE Consultores - - - - - - - - - - - - - -
- - -
- -
-
- PROPUESTA DE VALOR -

Diferentes capacidades.
Una visión compartida del conjunto.

-

- Cada desafío activa la parte del Ecosistema que necesita.
La clave está en comprender el conjunto para saber dónde intervenir. -

-
-
-
- - -
-
- - - -
-
- - -
-
-
- 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 - Desempeño - Riesgos - Sostenibilidad -
- - CONOCER MÁS → -
-
- IDE Excellence -
-
-
- - -
-
-
- 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 - Gobernanza - Metodologías - Resultados -
- CONOCER MÁS → -
-
-
- - -
-
-
- 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 - Inteligencia Artificial - 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. -

- -
- Formación Ejecutiva - In-Company - Programas - Talleres - Rutas de aprendizaje -
- EXPLORAR 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. -

-
-
- - -
- - ¿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. -

-
-
- - -
- - ¿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. -

-
-
- -
-
-
- - -
-
-

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

-

- Conversemos para comprender tu desafío e identificar qué capacidades pueden aportar mayor valor. -

- -
-
- - - - - - - - - - - - - - -
- -
- - - - - diff --git a/ecosistema.html b/ecosistema.html index de5c8ca..170e39b 100644 --- a/ecosistema.html +++ b/ecosistema.html @@ -10,6 +10,7 @@ + @@ -18,24 +19,361 @@
- -
- -
-
- PROPUESTA DE VALOR -

Diferentes capacidades.
Una visión compartida del conjunto.

-

- Cada desafío activa la parte del Ecosistema que necesita.
La clave está en comprender el conjunto para saber dónde intervenir. -

+ +
+
+
+
+ LA PROPUESTA DE VALOR +

+ Capacidades diferentes. 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. +

+ + + +
+ +
+
+ + + + +
+
+
+
+ +
+
+ +
+
+ ECOSISTEMA IDE +

Cuatro unidades, una misma forma de trabajar.

+

+ Integramos capacidades de gestión, proyectos, tecnología y formación para acompañar a las organizaciones en cada etapa de su mejora. +

+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + +
+
+ + + + +
+
-
+
CAPACIDADES @@ -261,5 +599,7 @@
+ + diff --git a/js/ecosistema.js b/js/ecosistema.js new file mode 100644 index 0000000..e146b28 --- /dev/null +++ b/js/ecosistema.js @@ -0,0 +1,130 @@ +/* ========================================================================== + ECOSISTEMA IDE — Cambio in-place entre tarjetas y paneles de unidad + ========================================================================== */ +(function () { + 'use strict'; + + const section = document.getElementById('ecosistema-ide'); + if (!section) return; + + const stateEcosystem = section.querySelector('[data-eco-state="ecosystem"]'); + const stateUnit = section.querySelector('[data-eco-state="unit"]'); + const panels = Array.from(section.querySelectorAll('[data-eco-panel]')); + const triggers = Array.from(section.querySelectorAll('[data-eco-open]')); + const backBtn = section.querySelector('[data-eco-close]'); + const pills = Array.from(section.querySelectorAll('.eco-pill')); + + let lastFocusedTrigger = null; + + /* --- Mostrar panel de una unidad --- */ + function openUnit(id) { + const panel = panels.find(p => p.dataset.ecoPanel === id); + if (!panel) return; + + // Guardamos el trigger que originó el cambio (para devolver foco) + const origin = triggers.find(t => t.dataset.ecoOpen === id); + if (origin) lastFocusedTrigger = origin; + + // Ocultar ecosistema, mostrar estado unidad + stateEcosystem.hidden = true; + stateUnit.hidden = false; + + // Alternar paneles + panels.forEach(p => { + const isActive = p.dataset.ecoPanel === id; + p.hidden = !isActive; + if (isActive) { + // Re-trigger de la animación de entrada + p.style.animation = 'none'; + // Forzar reflow + void p.offsetWidth; + p.style.animation = ''; + } + }); + + // Aria expandido en tarjetas + triggers.forEach(t => { + const isThis = t.dataset.ecoOpen === id; + t.setAttribute('aria-expanded', isThis ? 'true' : 'false'); + }); + + // Pills activas + pills.forEach(pill => { + pill.classList.toggle('is-active', pill.dataset.ecoOpen === id); + }); + + // Foco accesible al título del panel + const title = panel.querySelector('.eco-panel__title'); + if (title) { + title.setAttribute('tabindex', '-1'); + // Pequeño timeout para asegurar visibilidad tras el cambio de estado + requestAnimationFrame(() => title.focus({ preventScroll: false })); + } + + // Scroll suave al inicio de la sección (solo si quedó fuera de vista) + const rect = section.getBoundingClientRect(); + if (rect.top < -80) { + section.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + } + + /* --- Volver al estado ecosistema --- */ + function closeUnit() { + stateUnit.hidden = true; + stateEcosystem.hidden = false; + + triggers.forEach(t => t.setAttribute('aria-expanded', 'false')); + pills.forEach(p => p.classList.remove('is-active')); + + // Devolver foco a la tarjeta origen + if (lastFocusedTrigger && typeof lastFocusedTrigger.focus === 'function') { + lastFocusedTrigger.focus({ preventScroll: false }); + } else { + // Fallback: primer botón del grid + const first = triggers[0]; + if (first) first.focus({ preventScroll: false }); + } + } + + /* --- Listeners --- */ + triggers.forEach(trigger => { + trigger.addEventListener('click', (e) => { + const id = trigger.dataset.ecoOpen; + if (!id) return; + // Si es un real (academy), dejamos que navegue + if (trigger.tagName === 'A' && trigger.getAttribute('href')) return; + e.preventDefault(); + openUnit(id); + }); + + // Soporte teclado para tarjetas no-button (por si acaso) + trigger.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { + const id = trigger.dataset.ecoOpen; + if (!id) return; + if (trigger.tagName === 'A') return; + e.preventDefault(); + openUnit(id); + } + }); + }); + + if (backBtn) backBtn.addEventListener('click', closeUnit); + + // Escape cierra el panel expandido + section.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && !stateUnit.hidden) { + closeUnit(); + } + }); + + /* --- Deep link opcional por hash (#eco-projects) sin recargar --- */ + function readHash() { + const hash = window.location.hash.replace('#eco-', ''); + if (['excellence', 'projects', 'digital'].includes(hash)) { + openUnit(hash); + } + } + window.addEventListener('hashchange', readHash); + readHash(); +})(); \ No newline at end of file diff --git a/js/netschema.js b/js/netschema.js index 1b5d05b..5728009 100644 --- a/js/netschema.js +++ b/js/netschema.js @@ -1,543 +1,172 @@ -// Mapa: propiedad de CONFIG -> nombre de variable CSS -const CSS_VARS = { - greenNodesColor: "--ide-primary", - greenStrokeColor: "--ide-primary-light", - linkLineColor: "--ide-primary-line", - linkGreenColor: "--ide-primary-line", - linkActiveColor: "--ide-primary-light", - purpleCoreLineColor: "--ide-primary-line", - shadowCanva: "--shadow-canva", - textMain: "--text-main", - textInverse: "--text-inverse" -}; - -// Mapa: id de nodo violeta -> variable CSS -const PURPLE_NODE_VARS = { - p_top: "--ide-excellence", - p_bottom: "--ide-digital", - p_left: "--ide-academy", - p_right: "--ide-projects" -}; - -// Variable CSS común para todos los amarillos -const YELLOW_NODE_VAR = "--ide-primary-dark"; - -/* ========================================================================== - UTILIDAD: LEER VARIABLES CSS - ========================================================================== */ - -function readCSSVariable(variableName, fallback = "") { - const value = getComputedStyle(document.documentElement) - .getPropertyValue(variableName) - .trim(); - return value || fallback; -} - -/* ========================================================================== - CONFIGURACIÓN GENERAL - ========================================================================== */ - -const CONFIG = { - // 1. Color global configurable para TODOS los nodos verdes - greenNodesColor: readCSSVariable(CSS_VARS.greenNodesColor), - greenStrokeColor: readCSSVariable(CSS_VARS.greenStrokeColor), - - // 2. Estilos de líneas punteadas y dinámicas - linkLineColor: readCSSVariable(CSS_VARS.linkLineColor), - linkGreenColor: readCSSVariable(CSS_VARS.linkGreenColor), - 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) - purpleNodes: [ - { - id: "p_top", - x: 615, y: 185, - radius: 42, - 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: "Digital", - 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: "Academy", - 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: "Projects", - color: readCSSVariable(PURPLE_NODE_VARS.p_right), - desc: "Concentrador oriental hacia subredes de distribución." - } - ], - - // 4. Nodos AMARILLOS: Cada uno conectado a 2 VIOLETAS - yellowNodes: [ - // --- Lado Izquierdo --- - { 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: "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" } - ] -}; - -/* ========================================================================== - MOTOR INTERACTIVO Y RENDERIZADO - ========================================================================== */ - -const canvas = document.getElementById("networkCanvas"); -const ctx = canvas.getContext("2d"); -const tooltip = document.getElementById("tooltip"); -const tooltipTitle = document.getElementById("tooltip-title"); -const tooltipDesc = document.getElementById("tooltip-desc"); - -let nodes = []; -let links = []; -let hoveredNode = null; -let dashOffset = 0; - -// Construcción de la estructura -function initNetwork() { - nodes = []; - links = []; - const linkSet = new Set(); // Previene enlaces duplicados entre mismos nodos - - function addLink(fromId, toId, type, curved = false, curvature = 0) { - const keyA = `${fromId}->${toId}`; - const keyB = `${toId}->${fromId}`; - if (linkSet.has(keyA) || linkSet.has(keyB)) return; - linkSet.add(keyA); - links.push({ from: fromId, to: toId, type, curved, curvature }); - } - - // 1. Agregar Nodos Violetas - CONFIG.purpleNodes.forEach(p => { - nodes.push({ - ...p, - type: "purple", - baseX: p.x, - baseY: p.y, - speedOffset: Math.random() * 10 - }); - }); - - // Conectar los violetas entre sí (malla central) - const purples = nodes.filter(n => n.type === "purple"); - for (let i = 0; i < purples.length; i++) { - for (let j = i + 1; j < purples.length; j++) { - addLink(purples[i].id, purples[j].id, "purple-purple", false); - } - } - - // 2. Agregar Nodos Amarillos y crear DOBLE conexión curva hacia los violetas - CONFIG.yellowNodes.forEach((y) => { - nodes.push({ - id: y.id, - x: y.x, - y: y.y, - baseX: y.x, - baseY: y.y, - radius: y.r, - label: y.label, - color: y.color, - desc: y.desc, - side: y.side, - type: "yellow", - speedOffset: Math.random() * 10 - }); - - if (Array.isArray(y.purpleTargets)) { - y.purpleTargets.forEach((targetPurpleId, index) => { - addLink( - targetPurpleId, - y.id, - "purple-yellow", - true, - index === 0 ? 0.16 : -0.16 - ); - }); - } - }); - - // 3. Crear Nodos Verdes Terciarios - const greenPositions = [ - // Lado Izquierdo - { id: "gl_1", x: 190, y: 95, side: "left" }, - { id: "gl_2", x: 260, y: 120, side: "left" }, - { id: "gl_3", x: 140, y: 155, side: "left" }, - { id: "gl_4", x: 75, y: 150, side: "left" }, - { id: "gl_5", x: 130, y: 225, side: "left" }, - { id: "gl_6", x: 65, y: 230, side: "left" }, - { id: "gl_7", x: 195, y: 235, side: "left" }, - { id: "gl_8", x: 60, y: 290, side: "left" }, - { id: "gl_9", x: 165, y: 305, side: "left" }, - { id: "gl_10", x: 75, y: 375, side: "left" }, - { id: "gl_11", x: 140, y: 380, side: "left" }, - { id: "gl_12", x: 145, y: 440, side: "left" }, - { id: "gl_13", x: 235, y: 425, side: "left" }, - - // Lado Derecho - { id: "gr_1", x: 1040, 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" }, - { id: "gr_5", x: 1160, y: 150, side: "right" }, - { id: "gr_6", x: 1030, y: 220, side: "right" }, - { id: "gr_7", x: 1105, y: 215, side: "right" }, - { id: "gr_8", x: 1170, y: 225, side: "right" }, - { id: "gr_9", x: 1060, y: 285, side: "right" }, - { id: "gr_10", x: 1120, y: 305, side: "right" }, - { id: "gr_11", x: 1175, y: 290, side: "right" }, - { id: "gr_12", x: 1025, y: 335, side: "right" }, - { id: "gr_13", x: 1095, y: 350, side: "right" }, - { id: "gr_14", x: 1035, y: 400, side: "right" }, - { id: "gr_15", x: 1085, y: 435, side: "right" }, - { id: "gr_16", x: 1165, y: 385, side: "right" }, - { id: "gr_17", x: 970, y: 425, side: "right" } - ]; - - greenPositions.forEach(g => { - nodes.push({ - id: g.id, - x: g.x, - y: g.y, - baseX: g.x, - baseY: g.y, - radius: 14, - type: "green", - side: g.side, - speedOffset: Math.random() * 10 - }); - }); - - // 4. CONEXIÓN AMARILLOS <-> VERDES (cobertura total en ambas direcciones) - 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); - return distA - distB; - }); - - if (candidateGreens.length > 0) { - addLink( - yNode.id, - candidateGreens[0].id, - "yellow-green", - true, - idx % 2 === 0 ? 0.20 : -0.20 - ); - } - }); - - // PASO B: cada verde con al menos 1 amarillo - greens.forEach((gNode, idx) => { - const alreadyConnected = links.some( - l => l.type === "yellow-green" && (l.from === gNode.id || l.to === gNode.id) - ); - - const candidateYellows = yellows.filter(y => y.side === gNode.side); - 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 (!alreadyConnected && candidateYellows.length > 0) { - addLink( - candidateYellows[0].id, - gNode.id, - "yellow-green", - true, - idx % 2 === 0 ? -0.22 : 0.22 - ); - } else if (candidateYellows.length > 1 && idx % 3 === 0) { - addLink( - candidateYellows[1].id, - gNode.id, - "yellow-green", - true, - idx % 2 === 0 ? 0.26 : -0.26 - ); - } - }); -} - -// Bucle de actualización (flotación en zona segura) -function update(time) { - const maxOffset = 4.5; - - nodes.forEach(node => { - if (hoveredNode && hoveredNode.id === node.id) { - node.x = node.baseX; - node.y = node.baseY; - return; - } - - const t = (time * 0.0016) + node.speedOffset; - node.x = node.baseX + Math.sin(t) * maxOffset; - node.y = node.baseY + Math.cos(t * 0.85) * (maxOffset * 0.75); - }); - - dashOffset -= 0.35; -} - -// Renderizado de líneas curvadas -function drawConnection(source, target, link, isHighlight) { - ctx.save(); - ctx.beginPath(); - ctx.moveTo(source.x, source.y); - - if (link.curved) { - const midX = (source.x + target.x) / 2; - const midY = (source.y + target.y) / 2; - const dx = target.x - source.x; - const dy = target.y - source.y; - const dist = Math.hypot(dx, dy); - - const nx = -dy / dist; - const ny = dx / dist; - - const arcHeight = dist * link.curvature; - const cpX = midX + nx * arcHeight; - const cpY = midY + ny * arcHeight; - - ctx.quadraticCurveTo(cpX, cpY, target.x, target.y); - } else { - ctx.lineTo(target.x, target.y); - } - - if (link.type === "purple-purple") { - ctx.setLineDash([4, 4]); - ctx.lineDashOffset = dashOffset * 0.5; - 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 { - ctx.setLineDash([3, 4]); - ctx.lineDashOffset = dashOffset; - ctx.strokeStyle = isHighlight ? CONFIG.linkActiveColor : CONFIG.linkLineColor; - ctx.lineWidth = isHighlight ? 2.0 : 1.05; - } - - ctx.stroke(); - 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 - 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); - drawConnection(s, t, link, isHighlight); - }); - - // 2. Dibujar nodos - nodes.forEach(node => { - ctx.save(); - ctx.beginPath(); - ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2); - - if (node.type === "purple") { - ctx.fillStyle = node.color; - ctx.strokeStyle = node.color; - ctx.lineWidth = 1.8; - } else if (node.type === "yellow") { - ctx.fillStyle = node.color; - ctx.strokeStyle = node.color; - ctx.lineWidth = 1.3; - } else { - ctx.fillStyle = CONFIG.greenNodesColor; - ctx.strokeStyle = CONFIG.greenStrokeColor; - ctx.lineWidth = 1.1; - } - - if (hoveredNode && hoveredNode.id === node.id) { - ctx.shadowColor = CONFIG.shadowCanva; - ctx.shadowBlur = 14; - } - - ctx.fill(); - ctx.stroke(); - ctx.restore(); - - // 3. Texto en nodos violetas y amarillos - if (node.label) { - ctx.save(); - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - - if (node.type === "purple") { - ctx.fillStyle = "#ffffff"; - ctx.font = "bold 12.5px system-ui, sans-serif"; - } else if (node.type === "yellow") { - ctx.fillStyle = "#ffffff"; - ctx.font = "600 10.5px system-ui, sans-serif"; - } - - ctx.fillText(node.label, node.x, node.y); - ctx.restore(); - } - }); -} - -// Loop 60 FPS -function animate(time) { - update(time); - draw(); - requestAnimationFrame(animate); -} - -// Coordenadas con soporte responsivo -function getCanvasCoordinates(e) { - const rect = canvas.getBoundingClientRect(); - const scaleX = canvas.width / rect.width; - const scaleY = canvas.height / rect.height; - - return { - x: (e.clientX - rect.left) * scaleX, - y: (e.clientY - rect.top) * scaleY, - cssX: e.clientX - rect.left, - cssY: e.clientY - rect.top - }; -} - -// Eventos de Mouse -canvas.addEventListener("mousemove", (e) => { - const { x, y, cssX, cssY } = getCanvasCoordinates(e); - - const targets = nodes.filter(n => n.type === "purple" || n.type === "yellow"); - let found = null; - - for (let node of targets) { - if (Math.hypot(node.x - x, node.y - y) <= node.radius) { - found = node; - break; - } - } - - hoveredNode = found; - - if (hoveredNode) { - canvas.style.cursor = "pointer"; - tooltipTitle.textContent = hoveredNode.label; - tooltipDesc.textContent = hoveredNode.desc; - - tooltip.style.left = `${cssX}px`; - tooltip.style.top = `${cssY - (hoveredNode.radius * (canvas.getBoundingClientRect().height / canvas.height))}px`; - tooltip.classList.remove("hidden"); - } else { - canvas.style.cursor = "default"; - tooltip.classList.add("hidden"); - } -}); - -canvas.addEventListener("mouseleave", () => { - hoveredNode = null; - tooltip.classList.add("hidden"); -}); - -/* ========================================================================== - 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); - - // 2. Colores de violetas en CONFIG - CONFIG.purpleNodes.forEach(p => { - const cssVar = PURPLE_NODE_VARS[p.id]; - if (cssVar) p.color = readCSSVariable(cssVar, p.color); - }); - - // 3. Colores de amarillos en CONFIG - CONFIG.yellowNodes.forEach(y => { - y.color = readCSSVariable(YELLOW_NODE_VAR, y.color); - }); - - // 4. Propagar a los nodos ya instanciados - nodes.forEach(node => { - if (node.type === "purple" && PURPLE_NODE_VARS[node.id]) { - node.color = readCSSVariable(PURPLE_NODE_VARS[node.id], node.color); - } 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 - }); -} - -function watchThemeChanges() { - const observer = new MutationObserver(() => { - refreshColorsFromCSS(); - }); - - // Observa (habitual en data-theme) y (por si acaso) - observer.observe(document.documentElement, { - attributes: true, - attributeFilter: ["data-theme", "class"] - }); - - if (document.body) { - observer.observe(document.body, { - attributes: true, - attributeFilter: ["data-theme", "class"] - }); - } -} - -// Inicialización -initNetwork(); -watchThemeChanges(); -requestAnimationFrame(animate); \ No newline at end of file +const nodosData = [ + // Reemplaza el src con la ruta real de tus logos + { id: 'tl', x0: 220, y0: 140, r: 52, color: '#16a085', html: 'EXCELLENCE' }, + { id: 'bl', x0: 200, y0: 420, r: 52, color: '#f39200', html: 'PROJECTS' }, + { id: 'tr', x0: 780, y0: 110, r: 52, color: '#c41230', html: 'ACADEMY' }, + { id: 'br', x0: 750, y0: 400, r: 52, color: '#0061a0', html: 'DIGITAL' }, + { id: 'c', x0: 500, y0: 280, r: 70, color: '#ffffff', html: 'EL TODO' } + ]; + + const conexiones = [ + { id: 'arcL', from: 'tl', to: 'bl', type: 'vertical', curveOut: -180 }, + { id: 'c1', from: 'tl', to: 'c', type: 'horizontal', curveOut: 0 }, + { id: 'c2', from: 'bl', to: 'c', type: 'horizontal', curveOut: 0 }, + { id: 'arcR', from: 'tr', to: 'br', type: 'vertical', curveOut: 180 }, + { id: 'c3', from: 'tr', to: 'c', type: 'horizontal', curveOut: 0 }, + { id: 'c4', from: 'br', to: 'c', type: 'horizontal', curveOut: 0 } + ]; + + const contenedorNodos = document.getElementById('grupo-nodos'); + const grupoLineas = document.getElementById('grupo-lineas'); + const svgDefs = document.getElementById('svg-defs'); + const nodosMap = {}; + + // 1. Renderizado de Nodos HTML (AHORA FIJOS) + nodosData.forEach(nodo => { + nodosMap[nodo.id] = nodo; + + const el = document.createElement('div'); + el.className = 'nodo-circulo'; + el.id = `node-${nodo.id}`; + el.style.backgroundColor = nodo.color; // Lo comento para que el fondo sea blanco y se vea bien tu logo, descomenta si prefieres el fondo de color + //el.style.border = `4px solid ${nodo.color}`; // Agrego un borde con el color corporativo + el.style.width = `${(nodo.r * 2 / 1000) * 100}%`; + el.style.height = `${(nodo.r * 2 / 500) * 100}%`; + + // Asignamos la posición una única vez + nodo.x = nodo.x0; + nodo.y = nodo.y0; + el.style.left = `${(nodo.x / 1000) * 100}%`; + el.style.top = `${(nodo.y / 500) * 100}%`; + + const content = document.createElement('div'); + content.className = 'nodo-contenido'; + content.innerHTML = nodo.html; + + el.appendChild(content); + contenedorNodos.appendChild(el); + nodo.el = el; + }); + + const offsetsLineas = [-12, -6, 0, 6, 12]; + + // 2. Pre-calcular rutas y gradientes (UNA SOLA VEZ) + conexiones.forEach(conn => { + const n1 = nodosMap[conn.from]; + const n2 = nodosMap[conn.to]; + const isHoriz = conn.type === 'horizontal'; + + conn.rutasCache = {}; // Diccionario para guardar las rutas + + // Crear y fijar Gradiente + const gradId = `grad-${conn.from}-${conn.to}`; + const grad = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient'); + grad.setAttribute('id', gradId); + grad.setAttribute('gradientUnits', 'userSpaceOnUse'); + grad.setAttribute('x1', n1.x); + grad.setAttribute('y1', n1.y); + grad.setAttribute('x2', n2.x); + grad.setAttribute('y2', n2.y); + + const stop1 = document.createElementNS('http://www.w3.org/2000/svg', 'stop'); + stop1.setAttribute('offset', '0%'); + stop1.setAttribute('stop-color', n1.color); + + const stop2 = document.createElementNS('http://www.w3.org/2000/svg', 'stop'); + stop2.setAttribute('offset', '100%'); + const colorTarget = n2.id === 'c' ? '#0e626e' : n2.color; + stop2.setAttribute('stop-color', colorTarget); + + grad.appendChild(stop1); + grad.appendChild(stop2); + svgDefs.appendChild(grad); + + // Función matemática + const calcularRuta = (offsetX, offsetY) => { + let cp1x, cp1y, cp2x, cp2y; + if (isHoriz) { + const distanciaX = n2.x - n1.x; + cp1x = n1.x + distanciaX * 0.5; + cp1y = n1.y; + cp2x = n2.x - distanciaX * 0.5; + cp2y = n2.y; + } else { + cp1x = n1.x + conn.curveOut; + cp1y = n1.y; + cp2x = n2.x + conn.curveOut; + cp2y = n2.y; + } + return `M ${n1.x + offsetX} ${n1.y + offsetY} C ${cp1x + offsetX} ${cp1y + offsetY}, ${cp2x + offsetX} ${cp2y + offsetY}, ${n2.x + offsetX} ${n2.y + offsetY}`; + }; + + // Dibujar y Cachear las 5 líneas base + conn.pathsBase = []; + offsetsLineas.forEach(offset => { + const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + path.classList.add('linea-base'); + path.setAttribute('stroke', `url(#${gradId})`); + + const rutaCalculada = calcularRuta(isHoriz ? 0 : offset, isHoriz ? offset : 0); + path.setAttribute('d', rutaCalculada); + conn.rutasCache[offset] = rutaCalculada; // Guardado en caché + + grupoLineas.appendChild(path); + conn.pathsBase.push({ el: path, offset: offset }); + }); + + // Crear pulsos + conn.pulsos = []; + const cantPulsos = 10; + + for (let i = 0; i < cantPulsos; i++) { + const pathPulso = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + pathPulso.classList.add('linea-pulso'); + + const carrilInicial = offsetsLineas[Math.floor(Math.random() * offsetsLineas.length)]; + pathPulso.setAttribute('d', conn.rutasCache[carrilInicial]); // Le asignamos su ruta desde la caché + + grupoLineas.appendChild(pathPulso); + + conn.pulsos.push({ + el: pathPulso, + currentOffset: carrilInicial, + needsPathUpdate: false, // Bandera de optimización + dash: (1200 / cantPulsos) * i + Math.random() * 50, + speed: 2.0 + Math.random() * 1.5 + }); + } + }); + + // 3. Lógica de salto entre carriles + setInterval(() => { + conexiones.forEach(conn => { + conn.pulsos.forEach(p => { + if (Math.random() > 0.8) { + p.currentOffset = offsetsLineas[Math.floor(Math.random() * offsetsLineas.length)]; + p.needsPathUpdate = true; // Avisamos que en el próximo frame debe cambiar de ruta + } + }); + }); + }, 1200); + + // 4. Motor de Animación Ultraligero + function animarFrame() { + conexiones.forEach(conn => { + conn.pulsos.forEach(p => { + p.dash -= p.speed; + + // OPTIMIZACIÓN EXTREMA: Solo interactuamos con el DOM si el pulso saltó de carril + if (p.needsPathUpdate) { + p.el.setAttribute('d', conn.rutasCache[p.currentOffset]); + p.needsPathUpdate = false; + } + + // Lo único que se actualiza contínuamente es el desplazamiento + p.el.style.strokeDashoffset = p.dash; + }); + }); + + requestAnimationFrame(animarFrame); + } + + animarFrame(); \ No newline at end of file diff --git a/js/netschema2.js b/js/netschema2.js deleted file mode 100644 index 52c7b4f..0000000 --- a/js/netschema2.js +++ /dev/null @@ -1,727 +0,0 @@ -// Mapa: propiedad de CONFIG -> nombre de variable CSS -const CSS_VARS = { - 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: "--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 = "--ide-primary-dark"; - -/* ========================================================================== - UTILIDAD: LEER VARIABLES CSS - ========================================================================== */ - -function readCSSVariable(variableName, fallback = "") { - const value = getComputedStyle(document.documentElement) - .getPropertyValue(variableName) - .trim(); - return value || fallback; -} - -/* ========================================================================== - CONFIGURACIÓN GENERAL - ========================================================================== */ - -const CONFIG = { - // 1. Color global configurable para TODOS los nodos verdes - greenNodesColor: readCSSVariable(CSS_VARS.greenNodesColor), - greenStrokeColor: readCSSVariable(CSS_VARS.greenStrokeColor), - - // 2. Estilos de líneas punteadas y dinámicas - 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. 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: "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: "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: "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: "Digital", - color: readCSSVariable(PURPLE_NODE_VARS.p_right), - desc: "Concentrador oriental hacia subredes de distribución." - } - ], - - // 5. Nodos AMARILLOS: Cada uno conectado a 2 VIOLETAS - yellowNodes: [ - // --- Lado Izquierdo --- - { 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: "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" } - ] -}; - -/* ========================================================================== - MOTOR INTERACTIVO Y RENDERIZADO - ========================================================================== */ - -const canvas = document.getElementById("networkCanvas"); -const ctx = canvas.getContext("2d"); -const tooltip = document.getElementById("tooltip"); -const tooltipTitle = document.getElementById("tooltip-title"); -const tooltipDesc = document.getElementById("tooltip-desc"); - -let nodes = []; -let links = []; -let hoveredNode = null; -let dashOffset = 0; - -// Construcción de la estructura -function initNetwork() { - nodes = []; - links = []; - const linkSet = new Set(); // Previene enlaces duplicados entre mismos nodos - - function addLink(fromId, toId, type, curved = false, curvature = 0) { - const keyA = `${fromId}->${toId}`; - const keyB = `${toId}->${fromId}`; - if (linkSet.has(keyA) || linkSet.has(keyB)) return; - linkSet.add(keyA); - links.push({ from: fromId, to: toId, type, curved, curvature }); - } - - // 1. Agregar Nodos Violetas - CONFIG.purpleNodes.forEach(p => { - nodes.push({ - ...p, - type: "purple", - baseX: p.x, - baseY: p.y, - speedOffset: Math.random() * 10 - }); - }); - - // Conectar los violetas entre sí (malla central) - const purples = nodes.filter(n => n.type === "purple"); - for (let i = 0; i < purples.length; i++) { - for (let j = i + 1; j < purples.length; j++) { - addLink(purples[i].id, purples[j].id, "purple-purple", false); - } - } - - // 2. Agregar Nodos Amarillos y crear DOBLE conexión curva hacia los violetas - CONFIG.yellowNodes.forEach((y) => { - nodes.push({ - id: y.id, - x: y.x, - y: y.y, - baseX: y.x, - baseY: y.y, - radius: y.r, - label: y.label, - color: y.color, - desc: y.desc, - side: y.side, - type: "yellow", - speedOffset: Math.random() * 10 - }); - - if (Array.isArray(y.purpleTargets)) { - y.purpleTargets.forEach((targetPurpleId, index) => { - addLink( - targetPurpleId, - y.id, - "purple-yellow", - true, - index === 0 ? 0.16 : -0.16 - ); - }); - } - }); - - // 3. Crear Nodos Verdes Terciarios - const greenPositions = [ - // Lado Izquierdo - { id: "gl_1", x: 190, y: 95, side: "left" }, - { id: "gl_2", x: 260, y: 120, side: "left" }, - { id: "gl_3", x: 140, y: 155, side: "left" }, - { id: "gl_4", x: 75, y: 150, side: "left" }, - { id: "gl_5", x: 130, y: 225, side: "left" }, - { id: "gl_6", x: 65, y: 230, side: "left" }, - { id: "gl_7", x: 195, y: 235, side: "left" }, - { id: "gl_8", x: 60, y: 290, side: "left" }, - { id: "gl_9", x: 165, y: 305, side: "left" }, - { id: "gl_10", x: 75, y: 375, side: "left" }, - { id: "gl_11", x: 140, y: 380, side: "left" }, - { id: "gl_12", x: 145, y: 440, side: "left" }, - { id: "gl_13", x: 235, y: 425, side: "left" }, - - // Lado Derecho - { 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" }, - { id: "gr_5", x: 1160, y: 150, side: "right" }, - { id: "gr_6", x: 1030, y: 220, side: "right" }, - { id: "gr_7", x: 1105, y: 215, side: "right" }, - { id: "gr_8", x: 1170, y: 225, side: "right" }, - { id: "gr_9", x: 1060, y: 285, side: "right" }, - { id: "gr_10", x: 1120, y: 305, side: "right" }, - { id: "gr_11", x: 1175, y: 290, side: "right" }, - { id: "gr_12", x: 1025, y: 335, side: "right" }, - { id: "gr_13", x: 1095, y: 350, side: "right" }, - { id: "gr_14", x: 1035, y: 400, side: "right" }, - { id: "gr_15", x: 1085, y: 435, side: "right" }, - { id: "gr_16", x: 1165, y: 385, side: "right" }, - { id: "gr_17", x: 970, y: 425, side: "right" } - ]; - - greenPositions.forEach(g => { - nodes.push({ - id: g.id, - x: g.x, - y: g.y, - baseX: g.x, - baseY: g.y, - radius: 14, - type: "green", - side: g.side, - speedOffset: Math.random() * 10 - }); - }); - - // 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"); - - // 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; - }); - - // 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, - gNode.id, - "yellow-green", - true, - 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); - } - } - }); - - // PASO B: cada verde con al menos 1 amarillo - greens.forEach((gNode, idx) => { - const alreadyConnected = links.some( - l => l.type === "yellow-green" && (l.from === gNode.id || l.to === gNode.id) - ); - - const candidateYellows = yellows.filter(y => y.side === gNode.side); - 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 (!alreadyConnected && candidateYellows.length > 0) { - addLink( - candidateYellows[0].id, - gNode.id, - "yellow-green", - true, - idx % 2 === 0 ? -0.22 : 0.22 - ); - } else if (candidateYellows.length > 1 && idx % 3 === 0) { - addLink( - candidateYellows[1].id, - gNode.id, - "yellow-green", - true, - idx % 2 === 0 ? 0.26 : -0.26 - ); - } - }); - - // 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) -function update(time) { - const maxOffset = 4.5; - - nodes.forEach(node => { - if (hoveredNode && hoveredNode.id === node.id) { - node.x = node.baseX; - node.y = node.baseY; - return; - } - - const t = (time * 0.0016) + node.speedOffset; - node.x = node.baseX + Math.sin(t) * maxOffset; - 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 y rectas -function drawConnection(source, target, link, isHighlight) { - ctx.save(); - ctx.beginPath(); - ctx.moveTo(source.x, source.y); - - if (link.curved) { - const midX = (source.x + target.x) / 2; - const midY = (source.y + target.y) / 2; - const dx = target.x - source.x; - const dy = target.y - source.y; - const dist = Math.hypot(dx, dy); - - const nx = -dy / dist; - const ny = dx / dist; - - const arcHeight = dist * link.curvature; - const cpX = midX + nx * arcHeight; - const cpY = midY + ny * arcHeight; - - ctx.quadraticCurveTo(cpX, cpY, target.x, target.y); - } else { - ctx.lineTo(target.x, target.y); - } - - if (link.type === "purple-purple") { - ctx.setLineDash([4, 4]); - ctx.lineDashOffset = dashOffset * 0.5; - 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; - ctx.strokeStyle = isHighlight ? CONFIG.linkActiveColor : CONFIG.linkLineColor; - ctx.lineWidth = isHighlight ? 2.0 : 1.05; - } - - ctx.stroke(); - 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; - - // 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 recuadro central "EL TODO" (situado en el plano intermedio para enmascarar cruces) - drawCenterBox(); - - // 3. Dibujar nodos - nodes.forEach(node => { - ctx.save(); - ctx.beginPath(); - ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2); - - if (node.type === "purple") { - ctx.fillStyle = node.color; - ctx.strokeStyle = node.color; - ctx.lineWidth = 1.8; - } else if (node.type === "yellow") { - ctx.fillStyle = node.color; - ctx.strokeStyle = node.color; - ctx.lineWidth = 1.3; - } else { - ctx.fillStyle = CONFIG.greenNodesColor; - ctx.strokeStyle = CONFIG.greenStrokeColor; - ctx.lineWidth = 1.1; - } - - if (hoveredNode && hoveredNode.id === node.id) { - ctx.shadowColor = CONFIG.shadowCanva; - ctx.shadowBlur = 14; - } - - ctx.fill(); - ctx.stroke(); - ctx.restore(); - - // 4. Texto en nodos violetas y amarillos - if (node.label) { - ctx.save(); - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - - if (node.type === "purple") { - ctx.fillStyle = "#ffffff"; - ctx.font = "bold 12.5px system-ui, sans-serif"; - } else if (node.type === "yellow") { - ctx.fillStyle = "#ffffff"; - ctx.font = "600 10.5px system-ui, sans-serif"; - } - - ctx.fillText(node.label, node.x, node.y); - ctx.restore(); - } - }); -} - -// Loop 60 FPS -function animate(time) { - update(time); - draw(); - requestAnimationFrame(animate); -} - -// Coordenadas con soporte responsivo -function getCanvasCoordinates(e) { - const rect = canvas.getBoundingClientRect(); - const scaleX = canvas.width / rect.width; - const scaleY = canvas.height / rect.height; - - return { - x: (e.clientX - rect.left) * scaleX, - y: (e.clientY - rect.top) * scaleY, - cssX: e.clientX - rect.left, - cssY: e.clientY - rect.top - }; -} - -// Eventos de Mouse -canvas.addEventListener("mousemove", (e) => { - const { x, y, cssX, cssY } = getCanvasCoordinates(e); - - const targets = nodes.filter(n => n.type === "purple" || n.type === "yellow"); - let found = null; - - for (let node of targets) { - if (Math.hypot(node.x - x, node.y - y) <= node.radius) { - found = node; - break; - } - } - - // 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 || ""; - - tooltip.style.left = `${cssX}px`; - tooltip.style.top = `${cssY - (hoveredNode.radius * (canvas.getBoundingClientRect().height / canvas.height))}px`; - tooltip.classList.remove("hidden"); - } else { - canvas.style.cursor = "default"; - tooltip.classList.add("hidden"); - } -}); - -canvas.addEventListener("mouseleave", () => { - hoveredNode = null; - tooltip.classList.add("hidden"); -}); - -/* ========================================================================== - SOPORTE DE TEMA CLARO / OSCURO - ========================================================================== */ - -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.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 => { - const cssVar = PURPLE_NODE_VARS[p.id]; - if (cssVar) p.color = readCSSVariable(cssVar, p.color); - }); - - // 3. Colores de amarillos en CONFIG - CONFIG.yellowNodes.forEach(y => { - y.color = readCSSVariable(YELLOW_NODE_VAR, y.color); - }); - - // 4. Propagar a los nodos ya instanciados - nodes.forEach(node => { - if (node.type === "purple" && PURPLE_NODE_VARS[node.id]) { - node.color = readCSSVariable(PURPLE_NODE_VARS[node.id], node.color); - } else if (node.type === "yellow") { - node.color = readCSSVariable(YELLOW_NODE_VAR, node.color); - } - }); -} - -function watchThemeChanges() { - const observer = new MutationObserver(() => { - refreshColorsFromCSS(); - }); - - observer.observe(document.documentElement, { - attributes: true, - attributeFilter: ["data-theme", "class"] - }); - - if (document.body) { - observer.observe(document.body, { - attributes: true, - attributeFilter: ["data-theme", "class"] - }); - } -} - -// Inicialización -initNetwork(); -watchThemeChanges(); -requestAnimationFrame(animate); \ No newline at end of file diff --git a/prueba-animacion.html b/prueba-animacion.html deleted file mode 100644 index 937047d..0000000 --- a/prueba-animacion.html +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - Animación Nodos Infinito - - - - -
- - -
- - - - - - - - - - -
- -
- -
- -
- - - - \ No newline at end of file diff --git a/soluciones-PatriPad.html b/soluciones-PatriPad.html deleted file mode 100644 index 65656ae..0000000 --- a/soluciones-PatriPad.html +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - Soluciones Concretas | IDE Consultores - - - - - - - - - - - -
- - -
- - - - - -
- - -
- IDENTIFIQUEMOS SOLUCIONES -

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.

-
-
- - -
-
- - - - -
- - - - - -
-
-

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.

-
-
- -
-
- Formamos a tus Project Managers internos mediante los programas de IDE Academy. -
- - Explorar soluciones → - -
-
- - -
-
-

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.

-
-
- -
-
- Integramos tableros de control digital de incidentes a través de IDE Digital. -
- - Explorar soluciones → - -
-
- - -
-
-

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.

-
-
- -
-
- Complementamos con diseño instruccional y campus virtual vía IDE Academy. -
- - Explorar soluciones → - -
-
- - -
-
-

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 → - -
-
- - -
-
-

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. -
- - Explorar soluciones → - -
-
- -
-
-

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.

-
-
-
-
- Alineamos la tecnología con la estructura de procesos definida por IDE Excellence. -
- - Explorar soluciones → - -
-
-
-
-
- - -
-
-

Una única solución no siempre encaja para todos los desafíos.

-

- Integramos las capacidades necesarias para diseñar una respuesta que tenga sentido para tu organización y su contexto. -

- HABLEMOS → -
-
- - - - - - - - - - - - - -
- -
- - -