ecosistema finish

This commit is contained in:
2026-09-10 16:25:29 -03:00
parent 8c778471d1
commit 13fdc4ab2a
16 changed files with 1291 additions and 78 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.
Binary file not shown.
+120 -1
View File
@@ -23,6 +23,7 @@
--ide-digital: #2c69ab; --ide-digital: #2c69ab;
--teal-dark: #1B5E6E; --teal-dark: #1B5E6E;
--cta-hover:#40ab8e; --cta-hover:#40ab8e;
--bg-subtle: #ecf9fd;
/* Tema Claro (Por defecto) */ /* Tema Claro (Por defecto) */
--bg-body: #F8FAFB; --bg-body: #F8FAFB;
@@ -46,6 +47,9 @@
--shadow-sm: 0 1px 3px rgba(10, 72, 94, 0.05); --shadow-sm: 0 1px 3px rgba(10, 72, 94, 0.05);
--shadow-md: 0 4px 16px rgba(10, 72, 94, 0.08); --shadow-md: 0 4px 16px rgba(10, 72, 94, 0.08);
--shadow-lg: 0 10px 30px rgba(10, 72, 94, 0.12); --shadow-lg: 0 10px 30px rgba(10, 72, 94, 0.12);
--shadow-canva: rgba(10, 72, 94, 0.05);
--ide-primary-line: rgba(9,75,99, 0.4);
--radius-sm: 6px; --radius-sm: 6px;
--radius-md: 12px; --radius-md: 12px;
@@ -63,6 +67,7 @@
--bg-surface: #18222A; --bg-surface: #18222A;
--bg-surface-elevated: #202D37; --bg-surface-elevated: #202D37;
--bg-subtle: #24333E; --bg-subtle: #24333E;
--ide-primary-dark: #1D4672;
--bg-card: #18222A; --bg-card: #18222A;
--ripple-color:#253441; --ripple-color:#253441;
--bg-card-alt: var(--bg-muted); --bg-card-alt: var(--bg-muted);
@@ -79,6 +84,7 @@
--ide-digital: #2c69ab; --ide-digital: #2c69ab;
--teal-dark: #40ab8e; --teal-dark: #40ab8e;
--cta-hover:#0d5a91; --cta-hover:#0d5a91;
--bg-subtle: #03151c;;
--text-primary:#4fb389; --text-primary:#4fb389;
@@ -87,9 +93,12 @@
--text-muted: #8E9FAA; --text-muted: #8E9FAA;
--text-inverse: #0E2833; --text-inverse: #0E2833;
--ide-primary-line: rgba(79,179,137, 0.4);
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3); --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 20px rgba(0, 0, 0, 0.4); --shadow-md: 0 4px 20px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 10px 35px rgba(0, 0, 0, 0.55); --shadow-lg: 0 10px 35px rgba(0, 0, 0, 0.55);
--shadow-canva: rgba(92, 103, 107, 0.432);
} }
/* --- 2. Reseteo y Base --- */ /* --- 2. Reseteo y Base --- */
@@ -189,7 +198,9 @@ p, li, .lead-text, .text-body, .text-muted {
font-family: 'Plus Jakarta Sans', sans-serif; font-family: 'Plus Jakarta Sans', sans-serif;
} }
.bg-subtle-section{
background-color: var(--bg-subtle);
}
.lead-text { .lead-text {
font-size: 1.15rem; font-size: 1.15rem;
color: var(--text-muted); color: var(--text-muted);
@@ -580,6 +591,20 @@ p, li, .lead-text, .text-body, .text-muted {
color: var(--ide-accent); color: var(--ide-accent);
background-color: var(--ide-accent-soft); background-color: var(--ide-accent-soft);
} }
.btn-primary-cta {
background-color: var(--ide-primary-dark);
color: #FFFFFF;
border-color: var(--ide-primary);
}
.btn-primary-cta:hover {
background-color: var(--ide-primary-dark);
border-color: var(--ide-primary-dark);
color: #FFFFFF;
box-shadow: var(--shadow-md);
transform: translateY(-1px);
}
.btn-outline-cta { .btn-outline-cta {
background-color: transparent; background-color: transparent;
color: var(--text-inverse); color: var(--text-inverse);
@@ -1437,7 +1462,101 @@ p, li, .lead-text, .text-body, .text-muted {
border-color: var(--ide-primary); border-color: var(--ide-primary);
color: #FFFFFF; color: #FFFFFF;
} }
/* --- Tarjetas de Ecosistema --- */
.card-excellence:hover {
border-color: var(--ide-excellence);
box-shadow: 0 0 30px rgba(79,179,137, 0.5);
transform: translateY(-2px);
}
.card-projects:hover {
border-color: var(--ide-projects);
box-shadow: 0 0 30px rgba(237,141,1, 0.5);
transform: translateY(-2px);
}
.card-academy:hover {
border-color: var(--ide-academy);
box-shadow: 0 0 30px rgba(168,60,65, 0.5);
transform: translateY(-2px);
}
.card-digital:hover {
border-color: var(--ide-digital);
box-shadow: 0 0 30px rgba(44,105,171, 0.5);
transform: translateY(-2px);
}
/* --- Formato NetSchema --- */
.netschema-section {
width: 100%;
padding: 40px 20px;
display: flex;
justify-content: center;
align-items: center;
background-color: var(--bg-subtle);
}
/* Envoltura con aspecto horizontal responsivo */
.netschema-wrapper {
position: relative;
width: 100%;
max-width: 1240px;
overflow: hidden;
}
.netschema-header {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
margin-bottom: 1.5rem;
}
/* El canvas se escala proporcionalmente según el ancho del contenedor */
canvas {
display: block;
width: 100%;
height: auto;
aspect-ratio: 1240 / 520;
cursor: default;
}
/* ==========================================================================
LEYENDA / TOOLTIP FLOTANTE
========================================================================== */
.network-tooltip {
position: absolute;
pointer-events: none;
background: rgba(22, 24, 38, 0.94);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
color: #ffffff;
padding: 10px 15px;
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
transform: translate(-50%, -125%);
transition: opacity 0.2s ease, transform 0.2s ease;
z-index: 20;
max-width: 240px;
text-align: center;
}
.network-tooltip.hidden {
opacity: 0;
visibility: hidden;
transform: translate(-50%, -115%);
}
.tooltip-title {
font-weight: 700;
font-size: 14px;
margin-bottom: 3px;
color: #ffffff;
letter-spacing: 0.3px;
}
.tooltip-desc {
font-size: 12px;
color: #cfd4dc;
line-height: 1.35;
}
/* --- 17. Footer --- */ /* --- 17. Footer --- */
#site-footer { #site-footer {
position: relative; position: relative;
+3 -3
View File
@@ -49,9 +49,9 @@
<!-- Contenido --> <!-- Contenido -->
<div class="container container-narrow text-center" style="position: relative; z-index: 2;"> <div class="container container-narrow text-center" style="position: relative; z-index: 2;">
<span class="eyebrow" style="color: var(--text-inverse)">PUNTO DE PARTIDA</span> <span class="eyebrow" style="color: var(--text-main)">PUNTO DE PARTIDA</span>
<h1 style="margin-bottom: 1.25rem; color:var(--text-inverse);">¿Qué está pasando en tu organización?</h1> <h1 style="margin-bottom: 1.25rem; color:var(--text-main);">¿Qué está pasando en tu organización?</h1>
<p class="lead-text" style="color:var(--text-inverse)"> <p class="lead-text" style="color:var(--text-main)">
No necesitás tener la solución definida para empezar a conversar. Si reconocés alguno de estos síntomas o metas en tu contexto, hacé clic para explorar cómo podemos abordarlo. No necesitás tener la solución definida para empezar a conversar. Si reconocés alguno de estos síntomas o metas en tu contexto, hacé clic para explorar cómo podemos abordarlo.
</p> </p>
</div> </div>
+75 -65
View File
@@ -7,7 +7,8 @@
<meta name="description" content="Conocé cómo se articulan IDE Excellence, IDE Project, IDE Academy e IDE Digital para generar valor integral y sostenible en las organizaciones."> <meta name="description" content="Conocé cómo se articulan IDE Excellence, IDE Project, IDE Academy e IDE Digital para generar valor integral y sostenible en las organizaciones.">
<meta property="og:title" content="El Ecosistema IDE | Cuatro Capacidades Conectadas"> <meta property="og:title" content="El Ecosistema IDE | Cuatro Capacidades Conectadas">
<meta property="og:description" content="No se trata de sumar soluciones. Se trata de conectar las capacidades necesarias para una transformación real."> <meta property="og:description" content="No se trata de sumar soluciones. Se trata de conectar las capacidades necesarias para una transformación real.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="icon" type="image/x-icon" href="assets/img/favicon.png">
<link rel="stylesheet" href="css/styles.css"> <link rel="stylesheet" href="css/styles.css">
</head> </head>
<body> <body>
@@ -17,66 +18,85 @@
<main> <main>
<!-- Header Ecosistema --> <!-- Header Ecosistema -->
<section class="section-padding" style="background-color: var(--bg-surface); border-bottom: 1px solid var(--border-color);"> <section class="section-padding hero-video-section" style="background-color: var(--bg-surface); border-bottom: 1px solid var(--border-color); position: relative; overflow: hidden; min-height: 400px;">
<!-- Video de fondo -->
<video autoplay muted loop playsinline style="
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0.15;
z-index: 0;
pointer-events: none;
">
<source src="/assets/video/Video header Ide3.mp4" type="video/mp4">
Tu navegador no soporta videos.
</video>
<!-- Overlay oscuro opcional para mejor contraste -->
<div style="
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(19, 167, 138, 0.5);
z-index: 1;
"></div>
<!-- Contenido -->
<div class="container container-narrow text-center" style="position: relative; z-index: 2;">
<div class="container container-narrow text-center"> <div class="container container-narrow text-center">
<span class="eyebrow">LA PROPUESTA DE VALOR</span> <span class="eyebrow" style="color: var(--text-main);">LA PROPUESTA DE VALOR</span>
<h1 style="margin-bottom: 1.25rem;">Una mirada. <br> Múltiples capacidades. <br> Un mismo propósito.</h1> <h1 style="margin-bottom: 1.25rem;color:var(--text-main);">Una mirada. <br> Múltiples capacidades. <br> Un mismo propósito.</h1>
<p class="lead-text" style="margin: 0 auto 2rem auto;"> <p class="lead-text" style="margin: 0 auto 2rem auto;color:var(--text-main);">
No se trata de sumar soluciones aisladas. Se trata de conectar las capacidades necesarias para generar una transformación real que perdure en el conjunto de la organización. No se trata de sumar soluciones aisladas. Se trata de conectar las capacidades necesarias para generar una transformación real que perdure en el conjunto de la organización.
</p> </p>
<!-- Principio Destacado en Caja --> <!-- Principio Destacado en Caja -->
<div style="background-color: var(--ide-accent-soft); border-left: 4px solid var(--ide-accent); padding: 1.25rem 1.5rem; text-align: left; border-radius: var(--radius-sm); max-width: 760px; margin: 0 auto;"> <div style="background-color: var(--ide-accent); border-left: 4px solid var(--text-main); padding: 1.25rem 1.5rem; text-align: left; border-radius: var(--radius-sm); max-width: 760px; margin: 0 auto;">
<p style="font-size: 0.98rem; color: var(--text-main); font-weight: 600; margin: 0;"> <p style="font-size: 0.98rem; color: var(--text-main); font-weight: 600; margin: 0;">
<em>“No todos los desafíos necesitan todo el Ecosistema. Pero todos pueden beneficiarse de una mirada capaz de comprender el conjunto.”</em> <em>“No todos los desafíos necesitan todo el Ecosistema. Pero todos pueden beneficiarse de una mirada capaz de comprender el conjunto.”</em>
</p> </p>
</div> </div>
</div> </div>
</div>
</section> </section>
<!-- Gráfico Visual de Conectividad del Ecosistema --> <!-- SECCIÓN WEB DEDICADA PARA EL ESQUEMA -->
<section class="section-padding-sm bg-subtle-section"> <section class="netschema-section">
<div class="container text-center"> <div class="netschema-wrapper">
<div style="max-width: 860px; margin: 0 auto; background-color: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-lg); padding: 2.5rem 1.5rem;"> <div style="text-align: center; margin-bottom: 3rem;">
<span class="eyebrow">ARQUITECTURA DE INTEGRACIÓN</span> <span class="eyebrow">ARQUITECTURA DE INTEGRACIÓN</span>
<h2 style="font-size: 1.8rem; margin-bottom: 1.5rem;">El Modelo de Red Sistémica</h2> <h2>El Modelo de Red Sistémica</h2>
</div>
<!-- Canvas de alta resolución -->
<canvas id="networkCanvas" width="1200" height="520"></canvas>
<div class="grid-4" style="margin-top: 2rem; text-align: center;"> <!-- Tooltip / Leyenda emergente en hover -->
<div style="padding: 1rem; border: 1px dashed var(--border-color); border-radius: var(--radius-md);"> <div id="tooltip" class="network-tooltip hidden">
<!-- <div style="font-size: 1.75rem; color: var(--ide-primary); margin-bottom: 0.25rem;">📊</div> --> <div id="tooltip-title" class="tooltip-title"></div>
<strong style="color: var(--ide-primary);">EXCELLENCE</strong> <div id="tooltip-desc" class="tooltip-desc"></div>
<p style="font-size: 0.8rem; color: var(--text-muted); margin-top: 0.25rem;">Procesos & Calidad</p>
</div>
<div style="padding: 1rem; border: 1px dashed var(--border-color); border-radius: var(--radius-md);">
<!-- <div style="font-size: 1.75rem; color: var(--ide-accent); margin-bottom: 0.25rem;">🎯</div> -->
<strong style="color: var(--ide-accent);">PROJECT</strong>
<p style="font-size: 0.8rem; color: var(--text-muted); margin-top: 0.25rem;">Dirección & PMO</p>
</div>
<div style="padding: 1rem; border: 1px dashed var(--border-color); border-radius: var(--radius-md);">
<!-- <div style="font-size: 1.75rem; color: #D97706; margin-bottom: 0.25rem;">🎓</div> -->
<strong style="color: #ed8d01;">ACADEMY</strong>
<p style="font-size: 0.8rem; color: var(--text-muted); margin-top: 0.25rem;">Capacidades & Personas</p>
</div>
<div style="padding: 1rem; border: 1px dashed var(--border-color); border-radius: var(--radius-md);">
<!-- <div style="font-size: 1.75rem; color: #6366F1; margin-bottom: 0.25rem;">⚡</div> -->
<strong style="color: #2c69ab;">DIGITAL</strong>
<p style="font-size: 0.8rem; color: var(--text-muted); margin-top: 0.25rem;">IA & Automatización</p>
</div>
</div>
</div> </div>
</div> </div>
</section> </section>
<!-- Profundización de las 4 Capacidades --> <!-- Profundización de las 4 Capacidades -->
<section class="section-padding"> <section class="section-padding">
<div class="container"> <div class="container">
<div style="text-align: center; margin-bottom: 3rem;">
<span class="eyebrow">MÓDULOS</span>
<h2>Conocé el detalle de Nuestro Ecosistema</h2>
</div>
<!-- 1. IDE Excellence --> <!-- 1. IDE Excellence -->
<div id="excellence" class="card" style="margin-bottom: 2.5rem; padding: 2.5rem;"> <div id="excellence" class="card card-excellence" style="margin-bottom: 2.5rem; padding: 2.5rem;">
<div class="grid-2" style="gap: 2.5rem; align-items: center;"> <div class="grid-2" style="gap: 2.5rem; align-items: center;">
<div> <div>
<span class="ecosystem-badge badge-excellence">GESTIÓN Y PROCESOS</span> <span class="ecosystem-badge badge-excellence">GESTIÓN Y PROCESOS</span>
<h2 style="color: var(--ide-primary); font-size: 2rem; margin-bottom: 1rem;">IDE Excellence</h2>
<p style="font-size: 1.05rem; color: var(--text-body); line-height: 1.65; margin-bottom: 1rem;"> <p style="font-size: 1.05rem; color: var(--text-body); line-height: 1.65; margin-bottom: 1rem;">
<strong>Para fortalecer la gestión:</strong> Diseñamos y optimizamos la arquitectura de procesos organizacionales, sistemas de gestión de calidad y cumplimiento normativo internacional. <strong>Para fortalecer la gestión:</strong> Diseñamos y optimizamos la arquitectura de procesos organizacionales, sistemas de gestión de calidad y cumplimiento normativo internacional.
</p> </p>
@@ -88,26 +108,19 @@
</ul> </ul>
</div> </div>
<div> <div>
<div class="img-placeholder" style="aspect-ratio: 4/3;"> <img src="assets/img/excellence.png" alt="IDE Excellence" style="width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-md);">
<!-- <div class="img-placeholder-icon">📋</div> -->
<div class="img-placeholder-label">Espacio Gráfico IDE Excellence</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- 2. IDE Project --> <!-- 2. IDE Project -->
<div id="project" class="card" style="margin-bottom: 2.5rem; padding: 2.5rem;"> <div id="project" class="card card-projects" style="margin-bottom: 2.5rem; padding: 2.5rem;">
<div class="grid-2" style="gap: 2.5rem; align-items: center;"> <div class="grid-2" style="gap: 2.5rem; align-items: center;">
<div> <div>
<div class="img-placeholder" style="aspect-ratio: 4/3;"> <img src="assets/img/projects.png" alt="IDE Project" style="width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-md);">
<!-- <div class="img-placeholder-icon">🎯</div> -->
<div class="img-placeholder-label">Espacio Gráfico IDE Project</div>
</div>
</div> </div>
<div> <div>
<span class="ecosystem-badge badge-project">DIRECCIÓN Y RESULTADOS</span> <span class="ecosystem-badge badge-project">DIRECCIÓN Y RESULTADOS</span>
<h2 style="color: var(--ide-accent); font-size: 2rem; margin-bottom: 1rem;">IDE Project</h2>
<p style="font-size: 1.05rem; color: var(--text-body); line-height: 1.65; margin-bottom: 1rem;"> <p style="font-size: 1.05rem; color: var(--text-body); line-height: 1.65; margin-bottom: 1rem;">
<strong>Para convertir desafíos en proyectos y proyectos en resultados:</strong> Estructuramos la metodología y el control para que las iniciativas estratégicas se cumplan en tiempo, costo y alcance. <strong>Para convertir desafíos en proyectos y proyectos en resultados:</strong> Estructuramos la metodología y el control para que las iniciativas estratégicas se cumplan en tiempo, costo y alcance.
</p> </p>
@@ -122,13 +135,12 @@
</div> </div>
<!-- 3. IDE Academy --> <!-- 3. IDE Academy -->
<div id="academy" class="card" style="margin-bottom: 2.5rem; padding: 2.5rem;"> <div id="academy" class="card card-academy" style="margin-bottom: 2.5rem; padding: 2.5rem;">
<div class="grid-2" style="gap: 2.5rem; align-items: center;"> <div class="grid-2" style="gap: 2.5rem; align-items: center;">
<div> <div>
<span class="ecosystem-badge badge-academy">DESARROLLO HUMANO</span> <span class="ecosystem-badge badge-academy">DESARROLLO HUMANO</span>
<h2 style="color: #ed8d01; font-size: 2rem; margin-bottom: 1rem;">IDE Academy</h2>
<p style="font-size: 1.05rem; color: var(--text-body); line-height: 1.65; margin-bottom: 1rem;"> <p style="font-size: 1.05rem; color: var(--text-body); line-height: 1.65; margin-bottom: 1rem;">
<strong>Para desarrollar las capacidades que hacen posible la transformación:</strong> Formación ejecutiva e In-Company diseñada para que los equipos comprendan, apliquen y sostengan los cambios. <strong>Para desarrollar las capacidades que hacen posible la transformación:</strong>Formación ejecutiva e In-Company diseñada para que los equipos comprendan, apliquen y sostengan los cambios.
</p> </p>
<ul style="list-style: none; display: flex; flex-direction: column; gap: 0.6rem; font-size: 0.92rem; color: var(--text-muted); margin-bottom: 1.25rem;"> <ul style="list-style: none; display: flex; flex-direction: column; gap: 0.6rem; font-size: 0.92rem; color: var(--text-muted); margin-bottom: 1.25rem;">
<li>• Capacitación In-Company sobre casos y procesos reales.</li> <li>• Capacitación In-Company sobre casos y procesos reales.</li>
@@ -138,26 +150,19 @@
<a href="ide-academy.html" class="btn btn-outline btn-sm">Ver Catálogo de Cursos →</a> <a href="ide-academy.html" class="btn btn-outline btn-sm">Ver Catálogo de Cursos →</a>
</div> </div>
<div> <div>
<div class="img-placeholder" style="aspect-ratio: 4/3;"> <img src="assets/img/academy.png" alt="IDE Academy" style="width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-md);">
<!-- <div class="img-placeholder-icon">🎓</div> -->
<div class="img-placeholder-label">Espacio Gráfico IDE Academy</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- 4. IDE Digital --> <!-- 4. IDE Digital -->
<div id="digital" class="card" style="padding: 2.5rem;"> <div id="digital" class="card card-digital" style="padding: 2.5rem;">
<div class="grid-2" style="gap: 2.5rem; align-items: center;"> <div class="grid-2" style="gap: 2.5rem; align-items: center;">
<div> <div>
<div class="img-placeholder" style="aspect-ratio: 4/3;"> <img src="assets/img/digital.png" alt="IDE Digital" style="width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-md);">
<!-- <div class="img-placeholder-icon">⚡</div> -->
<div class="img-placeholder-label">Espacio Gráfico IDE Digital</div>
</div>
</div> </div>
<div> <div>
<span class="ecosystem-badge badge-digital">TECNOLOGÍA CON SENTIDO</span> <span class="ecosystem-badge badge-digital">TECNOLOGÍA CON SENTIDO</span>
<h2 style="color: #2c69ab; font-size: 2rem; margin-bottom: 1rem;">IDE Digital</h2>
<p style="font-size: 1.05rem; color: var(--text-body); line-height: 1.65; margin-bottom: 1rem;"> <p style="font-size: 1.05rem; color: var(--text-body); line-height: 1.65; margin-bottom: 1rem;">
<strong>Para integrar tecnología, datos e IA con propósito:</strong> No sumamos herramientas por moda; automatizamos procesos clave y potenciamos la toma de decisiones con analítica de datos. <strong>Para integrar tecnología, datos e IA con propósito:</strong> No sumamos herramientas por moda; automatizamos procesos clave y potenciamos la toma de decisiones con analítica de datos.
</p> </p>
@@ -174,6 +179,8 @@
</div> </div>
</section> </section>
<!-- Ejemplos Concretos de Integración --> <!-- Ejemplos Concretos de Integración -->
<section class="section-padding bg-subtle-section"> <section class="section-padding bg-subtle-section">
<div class="container"> <div class="container">
@@ -213,22 +220,25 @@
</section> </section>
<!-- CTA Final --> <!-- CTA Final -->
<section class="section-padding"> <section class="section-padding" style="background-color: var(--teal-dark); border-top: 1px solid var(--border-color);">
<div class="container text-center"> <div class="container container-narrow text-center">
<h2 style="font-size: 2rem; margin-bottom: 1rem;">¿Qué combinación de capacidades necesita tu organización?</h2> <h2 style="color: var(--text-inverse); margin-bottom: 1rem;">¿Qué combinación de capacidades necesita tu organización?</h2>
<p class="lead-text" style="margin: 0 auto 2rem auto;"> <p class="lead-text-cta" style="margin-bottom: 1.5rem;">
Conversemos para diseñar una propuesta a medida de tu realidad. Conversemos para diseñar una propuesta a medida de tu realidad.
</p> </p>
<div style="display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap;"> <div style="display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap;">
<a href="contacto.html" class="btn btn-primary btn-lg">HABLEMOS</a> <a href="contacto.html" class="btn btn-primary-cta btn-sm">HABLEMOS</a>
<a href="desafios.html" class="btn btn-outline btn-lg">Explorar por Desafíos</a> <a href="desafios.html" class="btn btn-outline-cta btn-sm">Explorar por Desafíos</a>
</div> </div>
</div> </div>
</section> </section>
</main> </main>
<footer id="site-footer"></footer> <footer id="site-footer"></footer>
<script src="js/main.js"></script> <script src="js/main.js"></script>
<script src="js/netschema.js"></script>
</body> </body>
</html> </html>
+2 -1
View File
@@ -7,7 +7,8 @@
<meta name="description" content="Desarrollamos las capacidades que hacen posible la transformación organizacional. Cursos ejecutivos y formación In-Company en Calidad, Proyectos e IA."> <meta name="description" content="Desarrollamos las capacidades que hacen posible la transformación organizacional. Cursos ejecutivos y formación In-Company en Calidad, Proyectos e IA.">
<meta property="og:title" content="IDE Academy | Formación Ejecutiva e In-Company"> <meta property="og:title" content="IDE Academy | Formación Ejecutiva e In-Company">
<meta property="og:description" content="Programas aplicados de gestión de calidad ISO, PMO y metodologías ágiles, y adopción de IA en procesos."> <meta property="og:description" content="Programas aplicados de gestión de calidad ISO, PMO y metodologías ágiles, y adopción de IA en procesos.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="icon" type="image/x-icon" href="assets/img/favicon.png">
<link rel="stylesheet" href="css/styles.css"> <link rel="stylesheet" href="css/styles.css">
</head> </head>
<body> <body>
+2 -1
View File
@@ -7,7 +7,8 @@
<meta name="description" content="Artículos, análisis y perspectivas sobre pensamiento sistémico, calidad, normas ISO, gestión de proyectos y transformación digital."> <meta name="description" content="Artículos, análisis y perspectivas sobre pensamiento sistémico, calidad, normas ISO, gestión de proyectos y transformación digital.">
<meta property="og:title" content="Insights & Blog | IDE Consultores"> <meta property="og:title" content="Insights & Blog | IDE Consultores">
<meta property="og:description" content="Evidencia, metodología y reflexiones prácticas para líderes organizacionales."> <meta property="og:description" content="Evidencia, metodología y reflexiones prácticas para líderes organizacionales.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="icon" type="image/x-icon" href="assets/img/favicon.png">
<link rel="stylesheet" href="css/styles.css"> <link rel="stylesheet" href="css/styles.css">
</head> </head>
<body> <body>
+543
View File
@@ -0,0 +1,543 @@
// 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 <html> y <body>.
========================================================================== */
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 <html> (habitual en data-theme) y <body> (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);
+537
View File
@@ -0,0 +1,537 @@
// Mapa: propiedad de CONFIG -> nombre de variable CSS
const CSS_VARS = {
greenNodesColor: "--ide-primary",
greenStrokeColor: "--ide-primary-light",
linkLineColor: "--canvas-link-line-color",
linkGreenColor: "--canvas-link-green-color",
linkActiveColor: "--canvas-link-active-color",
purpleCoreLineColor: "--canvas-purple-core-line-color"
};
// Mapa: id de nodo violeta -> variable CSS
const PURPLE_NODE_VARS = {
p_top: "--canvas-purple-p-top-color",
p_bottom: "--canvas-purple-p-bottom-color",
p_left: "--canvas-purple-p-left-color",
p_right: "--canvas-purple-p-right-color"
};
// Variable CSS común para todos los amarillos
const YELLOW_NODE_VAR = "--canvas-yellow-node-color";
/* ==========================================================================
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, "#9b1717"),
greenStrokeColor: readCSSVariable(CSS_VARS.greenStrokeColor, "#630b5f"),
// 2. Estilos de líneas punteadas y dinámicas
linkLineColor: readCSSVariable(CSS_VARS.linkLineColor, "rgba(95, 110, 240, 0.40)"),
linkGreenColor: readCSSVariable(CSS_VARS.linkGreenColor, "rgba(235, 60, 60, 0.42)"),
linkActiveColor: readCSSVariable(CSS_VARS.linkActiveColor, "rgba(25, 35, 205, 0.95)"),
purpleCoreLineColor: readCSSVariable(CSS_VARS.purpleCoreLineColor, "rgba(35, 35, 35, 0.70)"),
// 3. Nodos VIOLETAS centrales (posiciones, color individual, leyenda)
purpleNodes: [
{
id: "p_top",
x: 615, y: 185,
radius: 42,
label: "Núcleo N",
color: readCSSVariable(PURPLE_NODE_VARS.p_top, "#8a00c2"),
desc: "Servidor central de control y despacho de tareas."
},
{
id: "p_bottom",
x: 615, y: 335,
radius: 42,
label: "Núcleo S",
color: readCSSVariable(PURPLE_NODE_VARS.p_bottom, "#9900d8"),
desc: "Base de datos y redundancia estructural sur."
},
{
id: "p_left",
x: 485, y: 260,
radius: 42,
label: "Núcleo O",
color: readCSSVariable(PURPLE_NODE_VARS.p_left, "#7e00b3"),
desc: "Pasarela occidental hacia submódulos de entrada."
},
{
id: "p_right",
x: 745, y: 260,
radius: 42,
label: "Núcleo E",
color: readCSSVariable(PURPLE_NODE_VARS.p_right, "#9400cf"),
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: "IZQ-1", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Módulo intermedio A-1", purpleTargets: ["p_top", "p_left"], side: "left" },
{ id: "yl_2", x: 350, y: 165, r: 24, label: "IZQ-2", color: readCSSVariable(YELLOW_NODE_VAR, "#fff01f"), desc: "Módulo intermedio A-2", purpleTargets: ["p_top", "p_left"], side: "left" },
{ id: "yl_3", x: 355, y: 245, r: 25, label: "IZQ-3", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Balanceador izquierdo", purpleTargets: ["p_left", "p_top"], side: "left" },
{ id: "yl_4", x: 335, y: 335, r: 26, label: "IZQ-4", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Filtro de tráfico A-4", purpleTargets: ["p_left", "p_bottom"], side: "left" },
{ id: "yl_5", x: 395, y: 415, r: 28, label: "IZQ-5", color: readCSSVariable(YELLOW_NODE_VAR, "#fff33b"), desc: "Procesador de paquetes", purpleTargets: ["p_bottom", "p_left"], side: "left" },
{ id: "yl_6", x: 255, y: 350, r: 25, label: "IZQ-6", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Enrutador secundario", purpleTargets: ["p_left", "p_bottom"], side: "left" },
// --- Lado Derecho ---
{ id: "yr_1", x: 800, y: 135, r: 25, label: "DER-1", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Concentrador de salida 1", purpleTargets: ["p_top", "p_right"], side: "right" },
{ id: "yr_2", x: 875, y: 155, r: 25, label: "DER-2", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Concentrador de salida 2", purpleTargets: ["p_top", "p_right"], side: "right" },
{ id: "yr_3", x: 950, y: 195, r: 25, label: "DER-3", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Distribuidor rápido 3", purpleTargets: ["p_right", "p_top"], side: "right" },
{ id: "yr_4", x: 875, y: 235, r: 25, label: "DER-4", color: readCSSVariable(YELLOW_NODE_VAR, "#fff33b"), desc: "Replicador este 4", purpleTargets: ["p_right", "p_top"], side: "right" },
{ id: "yr_5", x: 890, y: 300, r: 25, label: "DER-5", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Gestor de colas 5", purpleTargets: ["p_right", "p_bottom"], side: "right" },
{ id: "yr_6", x: 965, y: 345, r: 25, label: "DER-6", color: readCSSVariable(YELLOW_NODE_VAR, "#ffff00"), desc: "Canal asíncrono 6", purpleTargets: ["p_right", "p_bottom"], side: "right" },
{ id: "yr_7", x: 890, y: 375, r: 25, label: "DER-7", color: readCSSVariable(YELLOW_NODE_VAR, "#fff01f"), desc: "Salida perimetral 7", purpleTargets: ["p_bottom", "p_right"], side: "right" },
{ id: "yr_8", x: 830, y: 420, r: 26, label: "DER-8", color: readCSSVariable(YELLOW_NODE_VAR, "#ffee00"), desc: "Canal de descarga 8", purpleTargets: ["p_bottom", "p_right"], side: "right" }
]
};
/* ==========================================================================
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 ? "#000000" : 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 = "#210036";
ctx.lineWidth = 1.8;
} else if (node.type === "yellow") {
ctx.fillStyle = node.color;
ctx.strokeStyle = "#383500";
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 = "rgba(0, 0, 0, 0.35)";
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 = "#1e1e1e";
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 <html> y <body>.
========================================================================== */
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 <html> (habitual en data-theme) y <body> (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);
+3 -3
View File
@@ -49,9 +49,9 @@
<!-- Contenido --> <!-- Contenido -->
<div class="container container-narrow text-center" style="position: relative; z-index: 2;"> <div class="container container-narrow text-center" style="position: relative; z-index: 2;">
<span class="eyebrow" style="color: var(--text-inverse)">RESPUESTAS ESPECÍFICAS</span> <span class="eyebrow" style="color: var(--text-main)">RESPUESTAS ESPECÍFICAS</span>
<h1 style="margin-bottom: 1.25rem; color:var(--text-inverse);">Soluciones concretas a necesidades definidas</h1> <h1 style="margin-bottom: 1.25rem; color:var(--text-main);">Soluciones concretas a necesidades definidas</h1>
<p class="lead-text" style="color:var(--text-inverse)"> <p class="lead-text" style="color:var(--text-main)">
Si ya sabés exactamente qué servicio estás buscando, aquí encontrarás el detalle técnico de nuestras intervenciones, alcances y valor esperado. Si ya sabés exactamente qué servicio estás buscando, aquí encontrarás el detalle técnico de nuestras intervenciones, alcances y valor esperado.
</p> </p>
</div> </div>
+2 -1
View File
@@ -7,7 +7,8 @@
<meta name="description" content="Conocé el origen, propósito, equipo senior y metodología que sustentan el Ecosistema IDE Consultores."> <meta name="description" content="Conocé el origen, propósito, equipo senior y metodología que sustentan el Ecosistema IDE Consultores.">
<meta property="og:title" content="Somos IDE | Identidad, Propósito y Equipo"> <meta property="og:title" content="Somos IDE | Identidad, Propósito y Equipo">
<meta property="og:description" content="Un equipo multidisciplinario con sólida trayectoria en gestión de calidad, proyectos, formación y tecnología."> <meta property="og:description" content="Un equipo multidisciplinario con sólida trayectoria en gestión de calidad, proyectos, formación y tecnología.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="icon" type="image/x-icon" href="assets/img/favicon.png">
<link rel="stylesheet" href="css/styles.css"> <link rel="stylesheet" href="css/styles.css">
</head> </head>
<body> <body>
+2 -1
View File
@@ -7,7 +7,8 @@
<meta name="description" content="Buscamos profesionales apasionados por el pensamiento sistémico, la gestión de calidad, la dirección de proyectos y la tecnología."> <meta name="description" content="Buscamos profesionales apasionados por el pensamiento sistémico, la gestión de calidad, la dirección de proyectos y la tecnología.">
<meta property="og:title" content="Trabaja con Nosotros | IDE Consultores"> <meta property="og:title" content="Trabaja con Nosotros | IDE Consultores">
<meta property="og:description" content="Formá parte de un equipo multidisciplinario que impulsa la transformación organizacional real."> <meta property="og:description" content="Formá parte de un equipo multidisciplinario que impulsa la transformación organizacional real.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="icon" type="image/x-icon" href="assets/img/favicon.png">
<link rel="stylesheet" href="css/styles.css"> <link rel="stylesheet" href="css/styles.css">
</head> </head>
<body> <body>