A simple 404 error page with CSS3 Animation
A Pen by Mitchel Falcon on CodePen.
<!DOCTYPE html> | |
<html lang="es" class="scroll-smooth"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Informe Interactivo: Conectividad en Baja California Sur 2030</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
<link rel="preconnect" href="https://fonts.googleapis.com"> | |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;800&display=swap" rel="stylesheet"> | |
<link rel="stylesheet" href="style.css"> | |
</head> | |
<body class="text-slate-700"> | |
<header class="bg-white/80 backdrop-blur-lg sticky top-0 z-50 shadow-sm"> | |
<nav class="container mx-auto px-4 sm:px-6 lg:px-8"> | |
<div class="flex items-center justify-between h-16"> | |
<div class="flex-shrink-0"> | |
<h1 class="text-xl font-bold text-blue-700">BCS Digital 2030</h1> </div> | |
<div class="hidden md:block"> | |
<div class="ml-10 flex items-baseline space-x-4"> | |
<a href="#diagnostico" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Diagnóstico</a> | |
<a href="#zonas" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Zonas Clave</a> | |
<a href="#impacto" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Impacto</a> | |
<a href="#propuesta" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Propuesta</a> | |
<a href="#recomendaciones" class="nav-link px-3 py-2 rounded-md text-sm font-medium text-slate-600">Recomendaciones</a> | |
</div> | |
</div> | |
</div> | |
</nav> | |
</header> | |
<main> | |
<section class="hero-section py-16 md:py-24 text-center bg-white overflow-hidden"> <div class="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10"> <h1 class="text-4xl md:text-5xl font-extrabold text-slate-800 leading-tight hero-title"> Impulsando la <span class="text-blue-600">Transformación Digital</span> </h1> | |
<p class="mt-4 max-w-3xl mx-auto text-lg text-slate-600"> | |
Un análisis interactivo de la conectividad en Baja California Sur y la estrategia para cerrar la brecha digital hacia 2030, basada en la propuesta de Nailea. | |
</p> | |
</div> | |
</section> | |
<section id="diagnostico" class="py-16 md:py-20"> | |
<div class="container mx-auto px-4 sm:px-6 lg:px-8"> | |
<div class="text-center mb-12"> | |
<h2 class="text-3xl font-bold text-slate-800">Diagnóstico General</h2> | |
<p class="mt-2 text-lg text-slate-500">BCS es líder nacional en penetración de internet, pero los promedios ocultan una profunda desigualdad.</p> | |
</div> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 items-center"> | |
<div> | |
<h3 class="text-2xl font-semibold text-slate-700 mb-4">Liderazgo a Nivel Nacional</h3> | |
<p class="mb-6 text-slate-600">Con más del 90% de su población usando internet, BCS supera significativamente el promedio nacional. Este es un cimiento sólido, pero la calidad y disponibilidad del acceso no es uniforme en todo el estado.</p> | |
<div class="space-y-4"> | |
<div class="bg-white p-4 rounded-lg shadow-md flex items-center"> | |
<span class="text-3xl mr-4">📱</span> | |
<div> | |
<p class="text-2xl font-bold text-blue-600" data-target="90.4" id="internet-users">0.0%</p> <p class="text-sm font-medium text-slate-500">Personas usuarias de internet (3er lugar nacional)</p> | |
</div> | |
</div> | |
<div class="bg-white p-4 rounded-lg shadow-md flex items-center"> | |
<span class="text-3xl mr-4">📶</span> | |
<div> | |
<p class="text-2xl font-bold text-blue-600" data-target="88.7" id="mobile-users">0.0%</p> <p class="text-sm font-medium text-slate-500">Personas usuarias de teléfono celular (2do lugar nacional)</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="bg-white p-4 sm:p-6 rounded-lg shadow-lg"> | |
<div class="chart-container h-[300px] md:h-[400px]"> | |
<canvas id="penetrationChart"></canvas> | |
</div> | |
</div> | |
</div> | |
<div class="mt-20"> | |
<h3 class="text-2xl font-semibold text-slate-700 mb-4 text-center">La Brecha Municipal: Acceso a Banda Ancha Fija</h3> | |
<p class="text-center max-w-3xl mx-auto text-slate-600 mb-8">La disparidad más clara se observa en el acceso a internet fijo de alta velocidad por hogar. Mientras Los Cabos tiene una penetración casi total, otros municipios apenas alcanzan la mitad. Este gráfico ilustra el núcleo del desafío.</p> | |
<div class="bg-white p-4 sm:p-6 rounded-lg shadow-lg"> | |
<div class="chart-container h-[400px] md:h-[500px]"> | |
<canvas id="bafChart"></canvas> | |
</div> | |
</div> | |
</div> | |
</div> | |
</section> | |
<section id="zonas" class="py-16 md:py-20 bg-white"> | |
<div class="container mx-auto px-4 sm:px-6 lg:px-8"> | |
<div class="text-center mb-12"> | |
<h2 class="text-3xl font-bold text-slate-800">Zonas Clave de Intervención</h2> | |
<p class="mt-2 text-lg text-slate-500">El informe identifica dos realidades opuestas que requieren estrategias diferenciadas.</p> | |
</div> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 text-center mb-12"> | |
<div class="bg-blue-50 p-8 rounded-lg border border-blue-200"> <h3 class="text-2xl font-bold text-blue-800">Zonas de Mayor Carencia</h3> <p class="mt-2 text-blue-700">Áreas rurales y periferias urbanas con acceso limitado o nulo. La prioridad es desplegar infraestructura básica para garantizar servicios esenciales.</p> | |
</div> | |
<div class="bg-green-50 p-8 rounded-lg border border-green-200"> <h3 class="text-2xl font-bold text-green-800">Zonas de Mayor Necesidad</h3> <p class="mt-2 text-green-700">Centros turísticos y la capital del estado. La demanda es de conectividad robusta, fiable y de alta capacidad para sostener la economía y la innovación.</p> | |
</div> | |
</div> | |
<div> | |
<h3 class="text-2xl font-semibold text-slate-700 mb-4 text-center">Explora la Cobertura Móvil por Municipio</h3> | |
<p class="text-center max-w-3xl mx-auto text-slate-600 mb-8">Selecciona un municipio para visualizar su infraestructura de red móvil (2G, 3G, 4G) y el número de operadores. Esto revela cómo la competencia y la tecnología varían drásticamente en el estado.</p> | |
<div id="municipio-selector" class="flex flex-wrap justify-center gap-2 mb-8"> | |
<button data-municipio="Los Cabos" class="municipio-btn btn-active px-4 py-2 bg-white border border-slate-300 rounded-md shadow-sm text-sm font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all">Los Cabos</button> <button data-municipio="La Paz" class="municipio-btn px-4 py-2 bg-white border border-slate-300 rounded-md shadow-sm text-sm font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all">La Paz</button> | |
<button data-municipio="Comondú" class="municipio-btn px-4 py-2 bg-white border border-slate-300 rounded-md shadow-sm text-sm font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all">Comondú</button> | |
<button data-municipio="Mulegé" class="municipio-btn px-4 py-2 bg-white border border-slate-300 rounded-md shadow-sm text-sm font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all">Mulegé</button> | |
<button data-municipio="Loreto" class="municipio-btn px-4 py-2 bg-white border border-slate-300 rounded-md shadow-sm text-sm font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all">Loreto</button> | |
</div> | |
<div class="grid grid-cols-1 lg:grid-cols-5 gap-8"> | |
<div class="lg:col-span-3 bg-white p-4 sm:p-6 rounded-lg shadow-lg"> | |
<div class="chart-container h-[400px] md:h-[450px]"> | |
<canvas id="coverageChart"></canvas> | |
</div> | |
</div> | |
<div id="municipio-details" class="lg:col-span-2 flex items-center"> | |
<div class="bg-white p-8 rounded-lg shadow-lg w-full"> | |
<h4 id="details-title" class="text-2xl font-bold text-slate-800 mb-4">Los Cabos</h4> | |
<p id="details-text" class="text-slate-600 mb-6">Con 3 operadores de 4G y una cobertura casi total, Los Cabos es el municipio mejor conectado, impulsado por su demanda turística. La infraestructura aquí es moderna y competitiva.</p> | |
<div class="border-t pt-4"> | |
<p class="text-sm text-slate-500">Operadores Banda Ancha Fija (2019): <span id="details-baf" class="font-bold text-slate-700">3</span></p> | |
<p class="text-sm text-slate-500">Operadores 4G (2018): <span id="details-4g" class="font-bold text-slate-700">3</span></p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</section> | |
<section id="impacto" class="py-16 md:py-20"> | |
<div class="container mx-auto px-4 sm:px-6 lg:px-8"> | |
<div class="text-center mb-12"> | |
<h2 class="text-3xl font-bold text-slate-800">Impacto Socioeconómico</h2> | |
<p class="mt-2 text-lg text-slate-500">La falta de conectividad no es un problema técnico, es una barrera para el desarrollo.</p> | |
</div> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-8"> | |
<div class="bg-white p-6 rounded-lg shadow-md"> | |
<h3 class="text-xl font-bold mb-2 flex items-center"><span class="text-3xl mr-3">🎓</span> Educación</h3> | |
<p class="text-slate-600">El rezago educativo se perpetúa al privar a estudiantes en zonas rurales de acceso a plataformas de aprendizaje en línea y recursos digitales.</p> | |
</div> | |
<div class="bg-white p-6 rounded-lg shadow-md"> | |
<h3 class="text-xl font-bold mb-2 flex items-center"><span class="text-3xl mr-3">❤️</span> Salud</h3> | |
<p class="text-slate-600">Restringe el acceso a atención médica especializada a través de la telemedicina, obligando a largos viajes y limitando el monitoreo de pacientes crónicos.</p> | |
</div> | |
<div class="bg-white p-6 rounded-lg shadow-md"> | |
<h3 class="text-xl font-bold mb-2 flex items-center"><span class="text-3xl mr-3">📈</span> Economía</h3> | |
<p class="text-slate-600">Limita las oportunidades de pequeños negocios rurales para acceder a mercados más amplios, ralentizando la diversificación económica y la innovación.</p> | |
</div> | |
</div> | |
<div class="mt-20"> | |
<h3 class="text-2xl font-semibold text-slate-700 mb-4 text-center">Caso de Estudio: Desigualdad en Telemedicina</h3> | |
<p class="text-center max-w-3xl mx-auto text-slate-600 mb-8">Los datos de consultas por telemedicina hasta abril de 2022 muestran una concentración abrumadora en La Paz y Los Cabos, dejando a otros municipios con un acceso casi nulo. Esta es una prueba contundente del impacto de la brecha digital en la salud.</p> | |
<div class="bg-white p-4 sm:p-6 rounded-lg shadow-lg"> | |
<div class="chart-container h-[350px] md:h-[400px]"> | |
<canvas id="telemedicinaChart"></canvas> | |
</div> | |
</div> | |
</div> | |
</div> | |
</section> | |
<section id="propuesta" class="py-16 md:py-20 bg-white"> | |
<div class="container mx-auto px-4 sm:px-6 lg:px-8"> | |
<div class="text-center mb-12"> | |
<h2 class="text-3xl font-bold text-slate-800">La Propuesta: Visualización del Impacto con QGIS</h2> | |
<p class="mt-2 text-lg text-slate-500">La estrategia se basa en un enfoque de "diplomacia de datos": usar la visualización geoespacial para comunicar el problema y la solución de forma clara y convincente.</p> | |
</div> | |
<div class="bg-slate-100 p-8 rounded-lg shadow-inner"> | |
<div class="flex justify-center mb-6"> | |
<div id="qgis-tabs" class="flex space-x-1 rounded-lg bg-blue-900/20 p-1" role="tablist" aria-orientation="horizontal"> <button id="tab-actual" class="qgis-tabbtn w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-blue-700 ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2 bg-white shadow" role="tab" type="button" aria-selected="true">Conectividad Actual</button> <button id="tab-criticos" class="qgis-tabbtn w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-white ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2" role="tab" type="button" aria-selected="false">Puntos Críticos</button> | |
<button id="tab-simulacion" class="qgis-tabbtn w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-white ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2" role="tab" type="button" aria-selected="false">Simulación 2030</button> | |
</div> | |
</div> | |
<div class="relative min-h-[200px]"> | |
<div id="content-actual" class="qgis-content transition-opacity duration-500 ease-in-out"> | |
<h4 class="text-xl font-bold text-blue-800 text-center mb-2">1. Mapeo de la Realidad Actual</h4> <p class="text-center text-slate-600 max-w-2xl mx-auto">Crear un mapa detallado de BCS que muestre la cobertura de banda ancha (2G, 3G, 4G, fibra), diferenciando con colores las zonas de mayor carencia (rojo) de las de mayor necesidad (azul). Esto proporciona una base de referencia clara y objetiva para la toma de decisiones.</p> | |
</div> | |
<div id="content-criticos" class="qgis-content absolute top-0 left-0 w-full opacity-0 transition-opacity duration-500 ease-in-out"> | |
<h4 class="text-xl font-bold text-blue-800 text-center mb-2">2. Identificación de Puntos Críticos</h4> <p class="text-center text-slate-600 max-w-2xl mx-auto">Señalar en el mapa ubicaciones clave como escuelas, centros de salud y pequeñas comunidades que hoy carecen de conectividad. Esto resalta la urgencia de la intervención y ayuda a priorizar las inversiones con mayor impacto social.</p> | |
</div> | |
<div id="content-simulacion" class="qgis-content absolute top-0 left-0 w-full opacity-0 transition-opacity duration-500 ease-in-out"> | |
<h4 class="text-xl font-bold text-blue-800 text-center mb-2">3. Simulación de Proyectos Futuros</h4> <p class="text-center text-slate-600 max-w-2xl mx-auto">Proyectar el impacto de nuevas inversiones. El mapa mostrará cómo se expandiría la cobertura y se reducirían las "zonas oscuras" (sin conectividad) hacia 2030. Esto ofrece una visión clara del progreso esperado y facilita la alineación de todos los actores.</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</section> | |
<section id="recomendaciones" class="py-16 md:py-20"> | |
<div class="container mx-auto px-4 sm:px-6 lg:px-8"> | |
<div class="text-center mb-12"> | |
<h2 class="text-3xl font-bold text-slate-800">Recomendaciones Estratégicas</h2> | |
<p class="mt-2 text-lg text-slate-500">Un plan de acción integral para maximizar el impacto de la iniciativa.</p> | |
</div> | |
<div class="max-w-4xl mx-auto space-y-6"> | |
<div class="bg-white p-5 rounded-lg shadow-md flex items-start space-x-4"> | |
<div class="flex-shrink-0 h-12 w-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xl font-bold">1</div> <div> | |
<h4 class="font-bold text-lg text-slate-800">Establecer un Observatorio de Conectividad</h4> | |
<p class="text-slate-600">Crear una plataforma pública de datos geoespaciales para monitorear la infraestructura y el progreso de la conectividad en tiempo real, fomentando la transparencia.</p> | |
</div> | |
</div> | |
<div class="bg-white p-5 rounded-lg shadow-md flex items-start space-x-4"> | |
<div class="flex-shrink-0 h-12 w-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xl font-bold">2</div> | |
<div> | |
<h4 class="font-bold text-lg text-slate-800">Priorizar Inversión en Zonas de Carencia</h4> | |
<p class="text-slate-600">Dirigir recursos de manera prioritaria a Mulegé, Comondú y las periferias urbanas, con énfasis en fibra óptica, soluciones de última milla y tecnologías satelitales.</p> | |
</div> | |
</div> | |
<div class="bg-white p-5 rounded-lg shadow-md flex items-start space-x-4"> | |
<div class="flex-shrink-0 h-12 w-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xl font-bold">3</div> | |
<div> | |
<h4 class="font-bold text-lg text-slate-800">Fomentar Habilidades Digitales</h4> | |
<p class="text-slate-600">Complementar la inversión en infraestructura con programas de alfabetización y capacitación tecnológica para asegurar la adopción y el uso significativo de las herramientas.</p> | |
</div> | |
</div> | |
<div class="bg-white p-5 rounded-lg shadow-md flex items-start space-x-4"> | |
<div class="flex-shrink-0 h-12 w-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xl font-bold">4</div> | |
<div> | |
<h4 class="font-bold text-lg text-slate-800">Digitalizar Servicios Esenciales</h4> | |
<p class="text-slate-600">Desarrollar e implementar soluciones de telemedicina y educación en línea adaptadas a las necesidades y contextos locales para expandir el acceso universal.</p> | |
</div> | |
</div> | |
<div class="bg-white p-5 rounded-lg shadow-md flex items-start space-x-4"> | |
<div class="flex-shrink-0 h-12 w-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xl font-bold">5</div> | |
<div> | |
<h4 class="font-bold text-lg text-slate-800">Promover el Comercio Digital Rural</h4> | |
<p class="text-slate-600">Crear plataformas y programas de apoyo para que pequeños negocios y productores rurales accedan a mercados más amplios, diversificando la economía local.</p> | |
</div> | |
</div> | |
<div class="bg-white p-5 rounded-lg shadow-md flex items-start space-x-4"> | |
<div class="flex-shrink-0 h-12 w-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xl font-bold">6</div> | |
<div> | |
<h4 class="font-bold text-lg text-slate-800">Fortalecer Colaboración y Marco Regulatorio</h4> | |
<p class="text-slate-600">Fomentar una coordinación robusta entre gobierno, academia y sector privado, y simplificar los marcos regulatorios para incentivar la inversión privada.</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</section> | |
</main> | |
<footer class="bg-slate-800 text-slate-400"> | |
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-4 text-center text-sm"> | |
<p>© 2024 Panel Interactivo Digital de BCS. Basado en el "Informe Estratégico: Impulsando la Conectividad y la Transformación Digital en Baja California Sur Hacia 2030".</p> | |
</div> | |
</footer> | |
<script src="script.js"></script> | |
</body> | |
</html> |
document.addEventListener('DOMContentLoaded', () => { | |
// --- Definición de la Paleta de Colores Azules --- | |
const colors = { | |
primaryBlue: '#2563eb', // blue-600 | |
primaryDarkBlue: '#1d4ed8', // blue-700 | |
lightBlue: '#bfdbfe', // blue-200 | |
lighterBlue: '#eff6ff', // blue-50 | |
accentGreen: '#10b981', // emerald-500 | |
accentYellow: '#fbbf24', // amber-400 | |
accentOrange: '#f97316', // orange-500 | |
accentRed: '#ef4444', // red-500 | |
slate600: '#475569', | |
slate900: '#0f172a', | |
slate200: '#e2e8f0', | |
slate500: '#64748b' | |
}; | |
// --- Configuración General de Chart.js --- | |
const chartJsConfig = { | |
plugins: { | |
legend: { | |
labels: { | |
color: colors.slate600, | |
font: { | |
family: "'Inter', sans-serif", | |
size: 12, | |
} | |
} | |
}, | |
tooltip: { | |
backgroundColor: colors.slate900, | |
titleFont: { size: 14, family: "'Inter', sans-serif" }, | |
bodyFont: { size: 12, family: "'Inter', sans-serif" }, | |
padding: 10, | |
cornerRadius: 4, | |
displayColors: true, | |
} | |
}, | |
scales: { | |
y: { | |
border: { display: false }, | |
grid: { color: colors.slate200 }, | |
ticks: { | |
color: colors.slate500, | |
font: { family: "'Inter', sans-serif", size: 12 } | |
} | |
}, | |
x: { | |
grid: { display: false }, | |
ticks: { | |
color: colors.slate500, | |
font: { family: "'Inter', sans-serif", size: 12 } | |
} | |
} | |
}, | |
responsive: true, | |
maintainAspectRatio: false | |
}; | |
// --- Datos de los Gráficos con Colores Azules --- | |
const chartData = { | |
penetration: { | |
labels: ['Usuarios de Internet', 'Usuarios de Teléfono Celular'], | |
datasets: [{ | |
label: 'Baja California Sur', | |
data: [90.4, 88.7], | |
backgroundColor: colors.primaryBlue, | |
borderColor: colors.primaryDarkBlue, | |
borderWidth: 1, | |
hoverBackgroundColor: colors.primaryDarkBlue, // Color al pasar el ratón | |
}, { | |
label: 'Nacional', | |
data: [83.1, 81.4], | |
backgroundColor: colors.slate500, | |
borderColor: colors.slate600, | |
borderWidth: 1, | |
hoverBackgroundColor: colors.slate600, // Color al pasar el ratón | |
}] | |
}, | |
baf: { | |
labels: ['Los Cabos', 'La Paz', 'Loreto', 'Comondú', 'Mulegé'], | |
datasets: [{ | |
label: 'Accesos BAF por 100 hogares (2019)', | |
data: [94.0, 81.0, 51.0, 49.3, 43.7], | |
backgroundColor: [colors.primaryBlue, colors.accentGreen, colors.accentYellow, colors.accentOrange, colors.accentRed], // Colores variados | |
borderWidth: 0, | |
hoverBackgroundColor: (context) => { // Función para colores de hover dinámicos | |
return context.dataset.backgroundColor[context.dataIndex].replace(')', ', 0.8)'); // Ligeramente más oscuro o con más opacidad | |
} | |
}] | |
}, | |
telemedicina: { | |
labels: ['La Paz', 'Los Cabos', 'Loreto', 'Mulegé'], | |
datasets: [{ | |
label: 'Consultas por Telemedicina (a Abril 2022)', | |
data: [33950, 16847, 667, 374], | |
backgroundColor: [colors.primaryBlue, colors.accentGreen, colors.accentOrange, colors.accentRed], // Colores variados | |
borderWidth: 0, | |
hoverBackgroundColor: (context) => { | |
return context.dataset.backgroundColor[context.dataIndex].replace(')', ', 0.8)'); | |
} | |
}] | |
}, | |
municipios: { | |
'Los Cabos': { | |
cobertura: [99, 100, 97], | |
operadoresBAF: 3, | |
operadores4G: 3, | |
texto: "Con 3 operadores de 4G y una cobertura casi total, Los Cabos es el municipio mejor conectado, impulsado por su demanda turística. La infraestructura aquí es moderna y competitiva." | |
}, | |
'La Paz': { | |
cobertura: [100, 100, 80], | |
operadoresBAF: 3, | |
operadores4G: 3, | |
texto: "Como capital del estado, La Paz tiene una conectividad robusta con múltiples operadores, aunque la cobertura 4G no es tan completa como en Los Cabos. Es un centro administrativo que depende de una buena red." | |
}, | |
'Comondú': { | |
cobertura: [94, 94, 79], | |
operadoresBAF: 2, | |
operadores4G: 1, | |
texto: "Comondú muestra una cobertura decente en tecnologías anteriores, pero una marcada falta de competencia en 4G, con un solo operador. Esto limita la calidad y las opciones para los usuarios." | |
}, | |
'Mulegé': { | |
cobertura: [76, 62, 45], | |
operadoresBAF: 1, | |
operadores4G: 1, | |
texto: "Mulegé presenta una de las mayores carencias, con cobertura 4G por debajo del 50% y un solo operador para servicios fijos y móviles. Es una zona prioritaria para la inversión en infraestructura." | |
}, | |
'Loreto': { | |
cobertura: [45, 49, 38], | |
operadoresBAF: 1, | |
operadores4G: 1, | |
texto: "Loreto es el municipio con la brecha digital más pronunciada. Con un solo operador y la cobertura más baja del estado en todas las tecnologías, su desarrollo está críticamente limitado por la falta de conectividad." | |
} | |
} | |
}; | |
// --- 1. Funciones para Gráficos de Chart.js --- | |
/** | |
* Inicializa y renderiza los gráficos de Chart.js. | |
*/ | |
function initializeCharts() { | |
new Chart(document.getElementById('penetrationChart'), { | |
type: 'bar', | |
data: chartData.penetration, | |
options: { ...chartJsConfig, indexAxis: 'y' } | |
}); | |
new Chart(document.getElementById('bafChart'), { | |
type: 'bar', | |
data: chartData.baf, | |
options: { | |
...chartJsConfig, | |
indexAxis: 'y', | |
plugins: { | |
...chartJsConfig.plugins, | |
legend: { display: false } | |
} | |
} | |
}); | |
new Chart(document.getElementById('telemedicinaChart'), { | |
type: 'bar', | |
data: chartData.telemedicina, | |
options: { | |
...chartJsConfig, | |
indexAxis: 'y', | |
plugins: { | |
...chartJsConfig.plugins, | |
legend: { display: false } | |
} | |
} | |
}); | |
const coverageCtx = document.getElementById('coverageChart').getContext('2d'); | |
window.coverageChart = new Chart(coverageCtx, { | |
type: 'bar', | |
data: { | |
labels: ['Cobertura 2G', 'Cobertura 3G', 'Cobertura 4G'], | |
datasets: [{ | |
label: 'Porcentaje de Cobertura', | |
data: chartData.municipios['Los Cabos'].cobertura, | |
backgroundColor: [colors.accentYellow, colors.accentGreen, colors.primaryBlue], // Colores variados | |
borderWidth: 0, | |
hoverBackgroundColor: (context) => { | |
return context.dataset.backgroundColor[context.dataIndex].replace(')', ', 0.8)'); | |
} | |
}] | |
}, | |
options: { | |
...chartJsConfig, | |
scales: { ...chartJsConfig.scales, y: { ...chartJsConfig.scales.y, max: 100 } }, | |
plugins: { ...chartJsConfig.plugins, legend: { display: false } } | |
} | |
}); | |
} | |
// --- 2. Funciones para Interacción de Municipios --- | |
/** | |
* Gestiona la selección de municipios y actualiza el gráfico y el texto de detalles. | |
*/ | |
function setupMunicipioSelector() { | |
const municipioSelector = document.getElementById('municipio-selector'); | |
const detailsTitle = document.getElementById('details-title'); | |
const detailsText = document.getElementById('details-text'); | |
const detailsBaf = document.getElementById('details-baf'); | |
const details4g = document.getElementById('details-4g'); | |
municipioSelector.addEventListener('click', (e) => { | |
if (e.target.tagName === 'BUTTON') { | |
const municipio = e.target.dataset.municipio; | |
document.querySelectorAll('.municipio-btn').forEach(btn => btn.classList.remove('btn-active')); | |
e.target.classList.add('btn-active'); | |
const data = chartData.municipios[municipio]; | |
window.coverageChart.data.datasets[0].data = data.cobertura; | |
window.coverageChart.update(); | |
detailsTitle.textContent = municipio; | |
detailsText.textContent = data.texto; | |
detailsBaf.textContent = data.operadoresBAF; | |
details4g.textContent = data.operadores4G; | |
} | |
}); | |
} | |
// --- 3. Funciones para Pestañas QGIS --- | |
/** | |
* Gestiona la interacción de las pestañas de la sección QGIS. | |
*/ | |
function setupQgisTabs() { | |
const qgisTabs = document.getElementById('qgis-tabs'); | |
const qgisTabButtons = document.querySelectorAll('.qgis-tabbtn'); | |
const qgisContents = document.querySelectorAll('.qgis-content'); | |
qgisTabs.addEventListener('click', (e) => { | |
if (e.target.tagName === 'BUTTON') { | |
const targetContentId = 'content-' + e.target.id.split('-')[1]; | |
qgisTabButtons.forEach(btn => { | |
btn.setAttribute('aria-selected', 'false'); | |
btn.classList.remove('bg-white', 'shadow', 'text-blue-700'); // Ajustado a blue | |
btn.classList.add('text-white'); | |
}); | |
e.target.setAttribute('aria-selected', 'true'); | |
e.target.classList.add('bg-white', 'shadow', 'text-blue-700'); // Ajustado a blue | |
e.target.classList.remove('text-white'); | |
qgisContents.forEach(content => { | |
if (content.id === targetContentId) { | |
content.classList.remove('opacity-0'); | |
} else { | |
content.classList.add('opacity-0'); | |
} | |
}); | |
} | |
}); | |
} | |
// --- 4. Función para Animación de Números (Contador) --- | |
/** | |
* Anima un número de un valor inicial a un valor objetivo. | |
* @param {HTMLElement} element - El elemento HTML donde se mostrará el número. | |
* @param {number} start - El valor inicial de la animación. | |
* @param {number} end - El valor objetivo de la animación. | |
* @param {number} duration - La duración de la animación en milisegundos. | |
* @param {string} suffix - Sufijo a añadir al número (ej. "%"). | |
*/ | |
function animateNumber(element, start, end, duration, suffix = '') { | |
let startTime = null; | |
const step = (currentTime) => { | |
if (!startTime) startTime = currentTime; | |
const progress = Math.min((currentTime - startTime) / duration, 1); | |
const currentValue = start + (end - start) * progress; | |
element.textContent = currentValue.toFixed(1) + suffix; | |
if (progress < 1) { | |
requestAnimationFrame(step); | |
} | |
}; | |
requestAnimationFrame(step); | |
} | |
// --- 5. Función para Disparar Animaciones de Números al Scroll (Intersection Observer) --- | |
/** | |
* Observa las tarjetas de estadísticas y dispara la animación de números cuando son visibles. | |
*/ | |
function setupNumberAnimationsOnScroll() { | |
const internetUsersElement = document.getElementById('internet-users'); | |
const mobileUsersElement = document.getElementById('mobile-users'); | |
let animated = { | |
internet: false, | |
mobile: false | |
}; | |
const observer = new IntersectionObserver((entries, observer) => { | |
entries.forEach(entry => { | |
if (entry.isIntersecting) { | |
if (entry.target.id === 'internet-users' && !animated.internet) { | |
const target = parseFloat(entry.target.dataset.target); | |
animateNumber(internetUsersElement, 0, target, 1500, '%'); | |
animated.internet = true; | |
} | |
if (entry.target.id === 'mobile-users' && !animated.mobile) { | |
const target = parseFloat(entry.target.dataset.target); | |
animateNumber(mobileUsersElement, 0, target, 1500, '%'); | |
animated.mobile = true; | |
} | |
} | |
}); | |
}, { threshold: 0.7 }); // Ajusta el threshold para que se active cuando el 70% del elemento sea visible | |
if (internetUsersElement) observer.observe(internetUsersElement); | |
if (mobileUsersElement) observer.observe(mobileUsersElement); | |
} | |
// --- 6. Función para Efecto Parallax en Hero Section --- | |
/** | |
* Aplica un efecto de parallax suave al título de la sección principal. | |
*/ | |
function setupHeroParallax() { | |
const heroTitle = document.querySelector('.hero-title'); | |
const heroSection = document.querySelector('.hero-section'); | |
if (!heroTitle || !heroSection) return; | |
window.addEventListener('scroll', () => { | |
const scrollPos = window.scrollY; | |
// Un desplazamiento suave basado en la posición de scroll | |
heroTitle.style.transform = `translateZ(-1px) scale(2) translateY(${scrollPos * 0.2}px)`; // Ajusta el 0.2 para la intensidad | |
}); | |
} | |
// --- Función para Resaltado de Navegación (Intersection Observer) --- | |
/** | |
* Resalta el enlace de navegación activo en la cabecera según la sección visible. | |
*/ | |
function setupNavigationHighlight() { | |
const navLinks = document.querySelectorAll('.nav-link'); | |
const sections = document.querySelectorAll('main section'); | |
const observer = new IntersectionObserver((entries) => { | |
entries.forEach(entry => { | |
if (entry.isIntersecting) { | |
navLinks.forEach(link => { | |
link.classList.remove('text-blue-600'); // Ajustado a blue | |
if (link.getAttribute('href').substring(1) === entry.target.id) { | |
link.classList.add('text-blue-600'); // Ajustado a blue | |
} | |
}); | |
} | |
}); | |
}, { rootMargin: "-50% 0px -50% 0px" }); | |
sections.forEach(section => observer.observe(section)); | |
} | |
// --- Ejecutar funciones al cargar el DOM --- | |
initializeCharts(); | |
setupMunicipioSelector(); | |
setupQgisTabs(); | |
setupNumberAnimationsOnScroll(); // Nueva función | |
setupHeroParallax(); // Nueva función | |
setupNavigationHighlight(); | |
}); |
A simple 404 error page with CSS3 Animation
A Pen by Mitchel Falcon on CodePen.
/* Variables CSS para la paleta de azules */ | |
:root { | |
--color-primary-blue: #2563eb; /* blue-600 */ | |
--color-primary-dark-blue: #1d4ed8; /* blue-700 */ | |
--color-light-blue: #eff6ff; /* blue-50 */ | |
--color-lighter-blue: #bfdbfe; /* blue-200 */ | |
--color-text-blue: #1e3a8a; /* blue-900 */ | |
--color-accent-green: #10b981; /* emerald-500 para contraste */ | |
} | |
body { | |
font-family: 'Inter', sans-serif; | |
background-color: #f8fafc; /* slate-50 */ | |
} | |
/* Ajustes de color con variables */ | |
.text-blue-600 { color: var(--color-primary-blue); } | |
.text-blue-700 { color: var(--color-primary-dark-blue); } | |
.text-blue-800 { color: var(--color-text-blue); } | |
.bg-blue-50 { background-color: var(--color-light-blue); } | |
.border-blue-200 { border-color: var(--color-lighter-blue); } | |
.bg-blue-900\/20 { background-color: rgba(30, 58, 138, 0.2); } /* blue-900 con opacidad */ | |
.ring-blue-400 { --tw-ring-color: #60a5fa; } /* blue-400 */ | |
.chart-container { | |
position: relative; | |
width: 100%; | |
max-width: 800px; | |
margin-left: auto; | |
margin-right: auto; | |
height: 350px; | |
} | |
@media (min-width: 768px) { | |
.chart-container { | |
height: 450px; | |
} | |
} | |
.nav-link { | |
transition: color 0.3s, border-color 0.3s; | |
} | |
.nav-link:hover { | |
color: var(--color-primary-blue); /* blue-600 */ | |
} | |
.btn-active { | |
background-color: var(--color-primary-blue) !important; /* blue-600 */ | |
color: white !important; | |
border-color: var(--color-primary-blue) !important; | |
} | |
/* Colores para las tarjetas de zonas, usando un color de acento para el contraste */ | |
.bg-rose-50 { background-color: var(--color-light-blue); } /* Ajustado a azul */ | |
.border-rose-200 { border-color: var(--color-lighter-blue); } /* Ajustado a azul */ | |
.text-rose-800 { color: var(--color-text-blue); } /* Ajustado a azul */ | |
.text-rose-700 { color: var(--color-primary-dark-blue); } /* Ajustado a azul */ | |
.bg-sky-50 { background-color: #ecfdf5; } /* emerald-50 (verde suave) */ | |
.border-sky-200 { border-color: #a7f3d0; } /* emerald-200 */ | |
.text-sky-800 { color: #065f46; } /* emerald-800 */ | |
.text-sky-700 { color: #047857; } /* emerald-700 */ | |
/* Efecto de Parallax suave para el título del hero section */ | |
.hero-section { | |
perspective: 1px; /* Necesario para el efecto 3D */ | |
transform-style: preserve-3d; | |
} | |
.hero-title { | |
transform: translateZ(-1px) scale(2); /* Mueve el texto hacia atrás en Z y lo escala para compensar */ | |
transition: transform 0.1s ease-out; /* Transición suave para el movimiento */ | |
/* La animación se controlará con JS mediante el scroll */ | |
} | |
/* Estilos para el hover de las barras de Chart.js (se controlará en JS) */ | |
/* No se necesitan estilos CSS específicos aquí, ya que Chart.js maneja el hover directamente. | |
Los colores de hover se definirán en la configuración de los datasets en JavaScript. */ |
<link href="https://fonts.googleapis.com/css?family=Lato:100,300" rel="stylesheet" /> |