{"id":351,"date":"2025-06-29T17:27:55","date_gmt":"2025-06-29T17:27:55","guid":{"rendered":"https:\/\/buscomunicacion.com\/?p=351"},"modified":"2025-07-06T11:45:34","modified_gmt":"2025-07-06T11:45:34","slug":"351","status":"publish","type":"post","link":"https:\/\/buscomunicacion.com\/index.php\/2025\/06\/29\/351\/","title":{"rendered":""},"content":{"rendered":"\n<!DOCTYPE html>\n\n<html lang=\"es\">\n\n<head>\n\n<meta charset=\"UTF-8\">\n\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\n<title>An\u00e1lisis Interactivo: Reputaci\u00f3n del Ayuntamiento de Dos Hermanas<\/title>\n\n<!-- Chosen Palette: Professional Indigo & Neutrals -->\n\n<!-- Application Structure Plan: A single-page dashboard design. The structure prioritizes immediate comprehension and guided exploration. It starts with a high-level \"Balanza Reputacional\" (KPIs, summary), then allows users to navigate to thematic deep-dives: \"Actores y Redes\", \"Riesgos y Oportunidades\", \"An\u00e1lisis Digital\", \"Escenarios Futuros\" and more. This task-oriented flow, supported by a sticky navigation bar, makes the complex information highly accessible and digestible, empowering users to explore insights at their own pace. -->\n\n<!-- Visualization & Content Choices:\n\n- Key Metrics (Sentiment): Goal: Inform. Method: Gauge-style HTML\/CSS and interactive Bar Charts (Chart.js) for quick assessment. Interaction: Clickable buttons to filter data. Justification: Provides immediate, high-impact understanding of the city's reputational health.\n\n- Media Pulse (Timeline): Goal: Show Change. Method: A vertical timeline built with HTML\/CSS. Interaction: Static visual. Justification: Clearly shows the evolution of key events over the analysis period.\n\n- Dominant Narratives & Actors: Goal: Organize. Method: Structured cards (HTML\/CSS). Interaction: Static. Justification: Keeps the main view clean while presenting qualitative analysis clearly.\n\n- Risk\/Opportunity Matrix: Goal: Organize\/Strategize. Method: HTML\/Tailwind grid layout. Interaction: Static. Justification: Clearly presents strategic SWOT-like analysis.\n\n- All choices use Chart.js (Canvas) or structured HTML\/CSS as required, avoiding SVG\/Mermaid. -->\n\n<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->\n\n<script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js\"><\/script>\n\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/html2canvas\/1.4.1\/html2canvas.min.js\"><\/script>\n\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/2.5.1\/jspdf.umd.min.js\"><\/script>\n\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;700&#038;display=swap\" rel=\"stylesheet\">\n\n<style>\n\nbody {\n\nfont-family: 'Inter', sans-serif;\n\nbackground-color: #fdfcf9;\n\n}\n\n.chart-container {\n\nposition: relative;\n\nwidth: 100%;\n\nmax-width: 600px;\n\nmargin-left: auto;\n\nmargin-right: auto;\n\nheight: 320px;\n\nmax-height: 400px;\n\n}\n\n@media (min-width: 768px) {\n\n.chart-container {\n\nheight: 350px;\n\n}\n\n}\n\n.nav-button {\n\ntransition: all 0.3s ease;\n\nwhite-space: nowrap;\n\nbackground-color: #ffffff;\n\ncolor: #4F46E5;\n\npadding-left: 1.25rem;\n\npadding-right: 1.25rem;\n\npadding-top: 0.625rem;\n\npadding-bottom: 0.625rem;\n\nborder-radius: 0.5rem;\n\nfont-size: 0.875rem;\n\nline-height: 1.25rem;\n\nbox-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n\nborder: 1px solid #E0E7FF;\n\n}\n\n.nav-button:hover {\n\nbackground-color: #EEF2FF;\n\n}\n\n.nav-button.active {\n\nbackground-color: #4F46E5;\n\ncolor: #ffffff;\n\nfont-weight: 600;\n\nbox-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n\noutline: none;\n\nborder-color: #4F46E5;\n\n}\n\n.content-section {\n\ndisplay: none;\n\nopacity: 0;\n\ntransition: opacity 0.5s ease-in-out;\n\n}\n\n.content-section.active {\n\ndisplay: block;\n\nopacity: 1;\n\nanimation: fadeIn 0.5s ease-in-out;\n\n}\n\n@keyframes fadeIn {\n\nfrom { opacity: 0; transform: translateY(10px); }\n\nto { opacity: 1; transform: translateY(0); }\n\n}\n\n.timeline-container {\n\nposition: relative;\n\nmax-width: 800px;\n\nmargin: 0 auto;\n\npadding: 20px 0;\n\n}\n\n.timeline-container::after {\n\ncontent: '';\n\nposition: absolute;\n\nwidth: 4px;\n\nbackground-color: #CBD5E1;\n\ntop: 0;\n\nbottom: 0;\n\nleft: 50%;\n\nmargin-left: -2px;\n\n}\n\n.timeline-item {\n\npadding: 10px 40px;\n\nposition: relative;\n\nbackground-color: inherit;\n\nwidth: 50%;\n\n}\n\n.timeline-item::after {\n\ncontent: '';\n\nposition: absolute;\n\nwidth: 25px;\n\nheight: 25px;\n\nright: -17px;\n\nbackground-color: #6366F1;\n\nborder: 4px solid #4F46E5;\n\ntop: 15px;\n\nborder-radius: 50%;\n\nz-index: 1;\n\n}\n\n.timeline-item.left {\n\nleft: 0;\n\n}\n\n.timeline-item.right {\n\nleft: 50%;\n\n}\n\n.timeline-item.left::after {\n\nleft: 98.5%;\n\n}\n\n.timeline-item.right::after {\n\nleft: -17px;\n\n}\n\n.timeline-content {\n\npadding: 20px 30px;\n\nbackground-color: #E0E7FF;\n\nposition: relative;\n\nborder-radius: 6px;\n\nbox-shadow: 0 2px 4px rgba(0,0,0,0.05);\n\n}\n\n@media screen and (max-width: 768px) {\n\n.timeline-container::after {\n\nleft: 31px;\n\n}\n\n.timeline-item {\n\nwidth: 100%;\n\npadding-left: 70px;\n\npadding-right: 25px;\n\nbox-sizing: border-box; \/* Ensures padding is included in the width *\/\n\n}\n\n.timeline-item::before {\n\nleft: 60px;\n\nborder-width: 10px 10px 10px 0;\n\nborder-color: transparent #E0E7FF transparent transparent; \/* Indigo-100 *\/\n\n}\n\n.timeline-item.right {\n\nleft: 0%;\n\n}\n\n.timeline-item.left::after, .timeline-item.right::after {\n\nleft: 15px;\n\n}\n\n}\n\n.progress-bar-container {\n\nwidth: 100%;\n\nbackground-color: #e0e0e0;\n\nborder-radius: 5px;\n\noverflow: hidden;\n\nmargin-bottom: 0.5rem;\n\n}\n\n.progress-bar {\n\nheight: 20px;\n\nborder-radius: 5px;\n\ntext-align: center;\n\ncolor: white;\n\nline-height: 20px;\n\ntransition: width 0.5s ease-in-out;\n\nfont-size: 0.75rem; \/* text-xs *\/\n\n}\n\n.sentiment-gauge {\n\nwidth: 150px;\n\nheight: 150px;\n\nborder-radius: 50%;\n\nposition: relative;\n\nbackground: conic-gradient(#EF4444 0% 33%, #FBBF24 33% 66%, #10B981 66% 100%);\n\ndisplay: flex;\n\nalign-items: center;\n\njustify-content: center;\n\nbox-shadow: inset 0 0 10px rgba(0,0,0,0.1);\n\n}\n\n.sentiment-gauge-inner {\n\nwidth: 120px;\n\nheight: 120px;\n\nborder-radius: 50%;\n\nbackground-color: white;\n\ndisplay: flex;\n\nalign-items: center;\n\njustify-content: center;\n\nfont-size: 1.5rem;\n\nfont-weight: bold;\n\ncolor: #333;\n\nbox-shadow: 0 2px 5px rgba(0,0,0,0.1);\n\n}\n\n\/* KPI Box styles *\/\n\n.kpi-box {\n\nbackground-color: #EEF2FF; \/* Indigo-50 *\/\n\npadding: 1.5rem; \/* p-6 *\/\n\nborder-radius: 0.75rem; \/* rounded-lg *\/\n\nbox-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); \/* shadow-sm *\/\n\ndisplay: flex;\n\nflex-direction: column;\n\nalign-items: center;\n\njustify-content: center;\n\ntext-align: center;\n\nborder: 1px solid #C7D2FE; \/* Indigo-200 *\/\n\n}\n\n.kpi-box-title {\n\nfont-size: 1.125rem; \/* text-xl *\/\n\nfont-weight: 600; \/* font-semibold *\/\n\ncolor: #4F46E5; \/* Indigo-600 *\/\n\nmargin-bottom: 0.5rem; \/* mb-2 *\/\n\n}\n\n.kpi-box-value {\n\nfont-size: 3rem; \/* text-5xl *\/\n\nfont-weight: 700; \/* font-bold *\/\n\ncolor: #1E293B; \/* Slate-800 *\/\n\nline-height: 1;\n\ndisplay: flex;\n\nalign-items: center;\n\njustify-content: center;\n\n}\n\n.kpi-box-change {\n\nfont-size: 1rem; \/* text-base *\/\n\nmargin-left: 0.5rem; \/* ml-2 *\/\n\ndisplay: flex;\n\nalign-items: center;\n\n}\n\n.kpi-box-description {\n\nfont-size: 0.875rem; \/* text-sm *\/\n\ncolor: #475569; \/* Slate-600 *\/\n\nmargin-top: 0.5rem; \/* mt-2 *\/\n\n}\n\n\/* Estilos espec\u00edficos para el PDF *\/\n\n\/* Estas reglas se aplican a la copia del contenido para PDF para forzar el formato deseado *\/\n\n.pdf-content-wrapper p,\n\n.pdf-content-wrapper li,\n\n.pdf-content-wrapper td {\n\ntext-align: justify !important; \/* Forzar texto justificado *\/\n\nfont-weight: 400 !important; \/* Asegurar que los p\u00e1rrafos no salgan en negrita si no deben *\/\n\ncolor: #1e293b !important; \/* Color de texto m\u00e1s oscuro para mejor contraste en PDF *\/\n\nline-height: 1.6 !important; \/* Espaciado entre l\u00edneas para legibilidad *\/\n\nfont-size: 0.95rem !important; \/* Ajuste del tama\u00f1o de fuente para legibilidad *\/\n\n}\n\n.pdf-content-wrapper strong,\n\n.pdf-content-wrapper h1,\n\n.pdf-content-wrapper h2,\n\n.pdf-content-wrapper h3,\n\n.pdf-content-wrapper h4,\n\n.pdf-content-wrapper h5,\n\n.pdf-content-wrapper th {\n\nfont-weight: 700 !important; \/* Forzar negrita m\u00e1s intensa para encabezados y 'strong' *\/\n\ncolor: #1a202c !important; \/* Un color a\u00fan m\u00e1s oscuro para los t\u00edtulos *\/\n\n}\n\n.pdf-content-wrapper h1 { font-size: 2.2rem !important; margin-bottom: 1.5rem !important; }\n\n.pdf-content-wrapper h2 { font-size: 1.8rem !important; margin-bottom: 1.2rem !important; }\n\n.pdf-content-wrapper h3 { font-size: 1.5rem !important; margin-bottom: 1rem !important; }\n\n.pdf-content-wrapper h4 { font-size: 1.25rem !important; margin-bottom: 0.8rem !important; }\n\n.pdf-content-wrapper h5 { font-size: 1.1rem !important; margin-bottom: 0.6rem !important; }\n\n.pdf-content-wrapper table {\n\nwidth: 100% !important; \/* Asegurar que las tablas ocupen todo el ancho disponible *\/\n\nborder-collapse: collapse; \/* Estilo de tabla com\u00fan *\/\n\nmargin-top: 1rem !important;\n\nmargin-bottom: 1rem !important;\n\n}\n\n.pdf-content-wrapper th, .pdf-content-wrapper td {\n\npadding: 8px !important;\n\nborder: 1px solid #ddd !important; \/* Borde para tablas *\/\n\ntext-align: left !important; \/* Asegurar alineaci\u00f3n izquierda para celdas *\/\n\nvertical-align: top !important; \/* Alinear contenido al top en celdas *\/\n\n}\n\n.pdf-content-wrapper thead th {\n\nbackground-color: #e0e7ff !important; \/* Fondo para encabezados de tabla *\/\n\ncolor: #312e81 !important; \/* Texto oscuro para encabezados de tabla *\/\n\n}\n\n.pdf-content-wrapper .chart-container {\n\n\/* Ocultar contenedores de gr\u00e1ficos vac\u00edos si no se rellenan, o darles un tama\u00f1o fijo *\/\n\n\/* En este caso, como los gr\u00e1ficos de consolidated-report son solo conceptuales, los ocultamos. *\/\n\ndisplay: none !important;\n\n}\n\n.pdf-content-wrapper .kpi-box {\n\nbackground-color: #EEF2FF !important; \/* Asegurar color de fondo *\/\n\nborder: 1px solid #C7D2FE !important; \/* Asegurar borde *\/\n\nbox-shadow: none !important; \/* Remover sombras para una apariencia m\u00e1s limpia en PDF *\/\n\n}\n\n.pdf-content-wrapper .kpi-box-value,\n\n.pdf-content-wrapper .kpi-box-title,\n\n.pdf-content-wrapper .kpi-box-description {\n\ncolor: #1E293B !important; \/* Asegurar colores de texto *\/\n\n}\n\n\/* Estilos para el informe consolidado en general (tambi\u00e9n aplicados en el PDF) *\/\n\n.consolidated-chapter {\n\nbreak-inside: avoid;\n\npage-break-inside: avoid;\n\nmargin-bottom: 2rem;\n\npadding-bottom: 1rem;\n\nborder-bottom: 1px solid #E0E7FF;\n\n}\n\n.consolidated-chapter:last-child {\n\nborder-bottom: none;\n\n}\n\n.consolidated-section-block {\n\nmargin-bottom: 1.5rem;\n\n}\n\n<\/style>\n\n<\/head>\n\n<body>\n\n<div class=\"container mx-auto p-4 md:p-8\">\n\n<header class=\"text-center mb-8 flex flex-col items-center\">\n\n<h1 class=\"text-3xl md:text-4xl font-bold text-slate-900\">An\u00e1lisis de Reputaci\u00f3n y Presencia Digital<\/h1>\n\n<h2 class=\"text-xl md:text-2xl text-slate-600 mt-2\">Ayuntamiento de Dos Hermanas<\/h2>\n\n<\/header>\n\n<nav class=\"flex flex-wrap justify-center gap-x-4 gap-y-2 mb-8 bg-indigo-100 p-2 rounded-lg shadow-sm overflow-x-auto pb-2\">\n\n<button data-target=\"balance\" class=\"nav-button active\">Balanza Reputacional<\/button>\n\n<button data-target=\"posicionamiento\" class=\"nav-button\">Diagn\u00f3stico Posicionamiento<\/button>\n\n<button data-target=\"termometro\" class=\"nav-button\">Term\u00f3metro Ciudadano<\/button>\n\n<button data-target=\"kpis\" class=\"nav-button\">Panel de KPIs<\/button>\n\n<button data-target=\"actores\" class=\"nav-button\">Mapa de Actores<\/button>\n\n<button data-target=\"alcalde\" class=\"nav-button\">Foco en el Alcalde<\/button>\n\n<button data-target=\"vocerias\" class=\"nav-button\">Foco en Vocer\u00edas<\/button>\n\n<button data-target=\"digital\" class=\"nav-button\">An\u00e1lisis Digital<\/button>\n\n<button data-target=\"media-treatment\" class=\"nav-button\">Tratamiento Medios<\/button>\n\n<button data-target=\"timeline\" class=\"nav-button\">L\u00ednea de Tiempo<\/button>\n\n<button data-target=\"matriz-ro\" class=\"nav-button\">Matriz R&#038;O<\/button>\n\n<button data-target=\"benchmarking\" class=\"nav-button\">Benchmarking<\/button>\n\n<button data-target=\"estrategia\" class=\"nav-button\">Estrategia y Narrativa<\/button>\n\n<button data-target=\"protocolo-crisis\" class=\"nav-button\">Protocolo Crisis<\/button>\n\n<button data-target=\"narrative-map\" class=\"nav-button\">Mapa Narrativo<\/button>\n\n<button data-target=\"say-do-gap\" class=\"nav-button\">Brecha Say-Do<\/button>\n\n<button data-target=\"early-warnings\" class=\"nav-button\">Se\u00f1ales Tempranas<\/button>\n\n<button data-target=\"scenarios\" class=\"nav-button\">Escenarios Futuros<\/button>\n\n<button data-target=\"deportes\" class=\"nav-button\">Deportes en Dos Hermanas<\/button>\n\n<button data-target=\"consolidated-report\" class=\"nav-button\">Informe Consolidado<\/button>\n\n<button data-target=\"about\" class=\"nav-button\">Sobre Este An\u00e1lisis<\/button>\n\n<\/nav>\n\n<main id=\"report-content\">\n\n<section id=\"balance\" class=\"content-section active\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-2 text-indigo-800\">Balanza Reputacional: La Doble Cara de la Gesti\u00f3n en Dos Hermanas<\/h3>\n\n<p class=\"text-center text-slate-600 mb-6 max-w-3xl mx-auto\">La imagen p\u00fablica del Ayuntamiento de Dos Hermanas presenta fortalezas en la difusi\u00f3n de noticias y eventos, pero enfrenta desaf\u00edos cr\u00edticos en la transparencia y la gesti\u00f3n de la percepci\u00f3n ciudadana sobre servicios esenciales.<\/p>\n\n<div class=\"flex justify-center gap-4 mb-8\">\n\n<button id=\"btn-logros\" class=\"px-6 py-2 bg-indigo-600 text-white font-semibold rounded-lg shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-400 transition-all\">\u2705 Fortalezas<\/button>\n\n<button id=\"btn-riesgos\" class=\"px-6 py-2 bg-red-500 text-white font-semibold rounded-lg shadow-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-400 transition-all\">\u26a0\ufe0f Debilidades<\/button>\n\n<\/div>\n\n<div class=\"grid grid-cols-1 md:grid-cols-2 gap-8 items-start mb-10\">\n\n<div id=\"info-display\" class=\"space-y-4\">\n\n<\/div>\n\n<div class=\"flex flex-col items-center justify-center p-4 bg-indigo-50 rounded-lg shadow-inner\">\n\n<h4 class=\"text-lg font-semibold text-indigo-700 mb-4\">Sentimiento General del Periodo<\/h4>\n\n<div class=\"sentiment-gauge\">\n\n<div class=\"sentiment-gauge-inner\" id=\"overall-sentiment-value\"><\/div>\n\n<\/div>\n\n<p class=\"text-sm text-slate-600 mt-4 text-center\">Una estimaci\u00f3n cualitativa del balance general de la cobertura medi\u00e1tica.<\/p>\n\n<\/div>\n\n<\/div>\n\n<div class=\"mt-8 p-4 bg-indigo-50 rounded-lg shadow-inner\">\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-3\">Resumen Estrat\u00e9gico del Periodo<\/h4>\n\n<p class=\"text-slate-700 leading-relaxed\">\n\nDurante el periodo analizado (Mayo 2023 &#8211; Junio 2025), el Ayuntamiento de Dos Hermanas ha mantenido una presencia digital activa a trav\u00e9s de su sitio web y canal de YouTube, difundiendo eficazmente noticias y eventos. Sin embargo, la falta de integraci\u00f3n de redes sociales y la desactualizaci\u00f3n de Onda Carmona limita su alcance. La transparencia, especialmente en datos econ\u00f3mico-financieros, es un punto cr\u00edtico. Es fundamental fortalecer la comunicaci\u00f3n proactiva en servicios esenciales y abordar las deficiencias de transparencia para consolidar la confianza ciudadana.\n\n<\/p>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"actores\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Mapa de Actores Clave y Redes de Resonancia<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Identificaci\u00f3n de los principales medios, grupos ciudadanos y voces influyentes que configuran la conversaci\u00f3n p\u00fablica en Dos Hermanas.<\/p>\n\n<div class=\"grid grid-cols-1 lg:grid-cols-3 gap-8\">\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4 flex items-center\">\n\n<span class=\"text-2xl mr-2\">\ud83d\udcf0<\/span> Medios Principales\n\n<\/h4>\n\n<ul class=\"space-y-2 text-slate-700\" id=\"actores-medios\"><\/ul>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4 flex items-center\">\n\n<span class=\"text-2xl mr-2\">\ud83d\udde3\ufe0f<\/span> Grupos Ciudadanos\n\n<\/h4>\n\n<ul class=\"space-y-2 text-slate-700\" id=\"actores-ciudadanos\"><\/ul>\n\n<\/div>\n\n<div class=\"lg:col-span-3 mt-8\">\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4 flex items-center\">\n\n<span class=\"text-2xl mr-2\">\u2728<\/span> Voces Influyentes (Periodistas y Activistas)\n\n<\/h4>\n\n<div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\" id=\"actores-influyentes-cards\">\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"alcalde\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Foco en el Alcalde: Presencia y Mensaje<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">An\u00e1lisis de la visibilidad medi\u00e1tica del Alcalde de Dos Hermanas, sus mensajes clave y los desaf\u00edos comunicativos.<\/p>\n\n<div class=\"grid grid-cols-1 md:grid-cols-2 gap-8 items-start\">\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">Resumen de la Presencia Medi\u00e1tica<\/h4>\n\n<p class=\"text-slate-700 leading-relaxed\" id=\"alcalde-resumen\"><\/p>\n\n<\/div>\n\n<div class=\"flex flex-col items-center justify-center p-4 bg-indigo-50 rounded-lg shadow-inner\">\n\n<h4 class=\"text-lg font-semibold text-indigo-700 mb-4\">Sentimiento de la Cobertura del Alcalde<\/h4>\n\n<div class=\"chart-container\">\n\n<canvas id=\"alcaldeSentimentChart\"><\/canvas>\n\n<\/div>\n\n<p class=\"text-sm text-slate-600 mt-4 text-center\" id=\"alcalde-sentiment-summary\">Desglose del sentimiento de la cobertura medi\u00e1tica asociada al alcalde: <\/p>\n\n<\/div>\n\n<\/div>\n\n<div class=\"mt-8\">\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">Mensajes Clave y Desaf\u00edos<\/h4>\n\n<ul class=\"space-y-3 text-slate-700\">\n\n<li class=\"font-semibold text-indigo-600\">Mensajes Clave:<\/li>\n\n<ul class=\"list-disc list-inside ml-4\" id=\"alcalde-mensajes\"><\/ul>\n\n<li class=\"font-semibold text-red-600 mt-4\">Desaf\u00edos Comunicativos:<\/li>\n\n<ul class=\"list-disc list-inside ml-4\" id=\"alcalde-desafios\"><\/ul>\n\n<\/ul>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"digital\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">An\u00e1lisis Digital: Canales y Rendimiento en Redes<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Evaluaci\u00f3n de la estrategia digital del Ayuntamiento de Dos Hermanas, incluyendo sus canales oficiales y el rendimiento en redes sociales.<\/p>\n\n<div class=\"mb-10\">\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">Canales de Comunicaci\u00f3n Oficiales<\/h4>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-sm text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase\">\n\n<tr>\n\n<th class=\"p-3\">Tipo de Canal<\/th>\n\n<th class=\"p-3\">Nombre\/Usuario<\/th>\n\n<th class=\"p-3\">Prop\u00f3sito Principal<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody id=\"digital-channels-table\">\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">Rendimiento en Redes Sociales (Estimado)<\/h4>\n\n<p class=\"text-sm text-slate-600 mb-4\">\n\nLas m\u00e9tricas de alcance total, impresiones y tasas de engagement no son directamente cuantificables a partir de los fragmentos de informaci\u00f3n proporcionados. Estas m\u00e9tricas requieren acceso a herramientas de monitoreo especializadas. Los siguientes gr\u00e1ficos muestran datos ilustrativos.\n\n<\/p>\n\n<div class=\"grid grid-cols-1 md:grid-cols-2 gap-8\">\n\n<div class=\"bg-indigo-50 p-4 rounded-lg shadow-inner\">\n\n<canvas id=\"digitalReachChart\"><\/canvas>\n\n<\/div>\n\n<div class=\"bg-indigo-50 p-4 rounded-lg shadow-inner\">\n\n<canvas id=\"digitalEngagementChart\"><\/canvas>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"timeline\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">L\u00ednea de Tiempo: Eventos Clave (Mayo 2023 &#8211; Junio 2025)<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Cronolog\u00eda de los acontecimientos m\u00e1s relevantes de la gesti\u00f3n municipal de Dos Hermanas durante el periodo analizado.<\/p>\n\n<div class=\"timeline-container\" id=\"timeline-events\">\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"matriz-ro\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Matriz de Riesgos y Oportunidades Reputacionales<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Identificaci\u00f3n y an\u00e1lisis de los principales riesgos que pueden afectar la reputaci\u00f3n del Ayuntamiento y las oportunidades para fortalecerla.<\/p>\n\n<div class=\"grid grid-cols-1 md:grid-cols-2 gap-8\">\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-red-700 mb-4 flex items-center\">\n\n<span class=\"text-2xl mr-2\">\ud83d\udea8<\/span> Riesgos Clave\n\n<\/h4>\n\n<ul class=\"space-y-4 text-slate-700\" id=\"matriz-riesgos\"><\/ul>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-emerald-700 mb-4 flex items-center\">\n\n<span class=\"text-2xl mr-2\">\ud83d\ude80<\/span> Oportunidades Estrat\u00e9gicas\n\n<\/h4>\n\n<ul class=\"space-y-4 text-slate-700\" id=\"matriz-oportunidades\"><\/ul>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"termometro\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Term\u00f3metro Ciudadano: Percepci\u00f3n por Temas<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Evaluaci\u00f3n cualitativa del sentimiento ciudadano hacia diferentes \u00e1reas de la gesti\u00f3n municipal, de 0 (muy negativo) a 100 (muy positivo).<\/p>\n\n<div class=\"space-y-6\" id=\"termometro-topics\">\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"posicionamiento\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Diagn\u00f3stico de Posicionamiento Reputacional<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">An\u00e1lisis de la imagen actual del Ayuntamiento de Dos Hermanas frente a la imagen deseada y la brecha existente.<\/p>\n\n<div class=\"space-y-6\" id=\"posicionamiento-content\">\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Posicionamiento Actual<\/h4>\n\n<p id=\"posicionamiento-actual\"><\/p>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Posicionamiento Deseado<\/h4>\n\n<p id=\"posicionamiento-deseado\"><\/p>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Brecha Reputacional<\/h4>\n\n<p id=\"posicionamiento-brecha\"><\/p>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"benchmarking\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Benchmarking: Comparativa con Otros Ayuntamientos<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">An\u00e1lisis comparativo conceptual con otras ciudades para identificar buenas pr\u00e1cticas y \u00e1reas de mejora.<\/p>\n\n<div class=\"space-y-6\" id=\"benchmarking-cities\">\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"kpis\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Panel de KPIs de Reputaci\u00f3n y Comunicaci\u00f3n<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Indicadores clave de rendimiento para el seguimiento continuo de la reputaci\u00f3n institucional.<\/p>\n\n<div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\" id=\"kpi-boxes-container\">\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"estrategia\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Estrategia y Narrativa: Hacia un Relato Institucional \u00d3ptimo<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">An\u00e1lisis de la narrativa actual del Ayuntamiento y recomendaciones para un posicionamiento m\u00e1s efectivo.<\/p>\n\n<div class=\"space-y-6\" id=\"estrategia-content\">\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Narrativa Actual<\/h4>\n\n<p id=\"estrategia-actual\"><\/p>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Narrativa Recomendada<\/h4>\n\n<p id=\"estrategia-recomendada\"><\/p>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Acciones Clave para el Relato<\/h4>\n\n<ul class=\"list-disc list-inside ml-4\" id=\"estrategia-acciones\"><\/ul>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"protocolo-crisis\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Protocolo de Comunicaci\u00f3n de Crisis<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Esquema de actuaci\u00f3n para la gesti\u00f3n de situaciones de crisis que puedan afectar la reputaci\u00f3n institucional.<\/p>\n\n<div class=\"space-y-6\" id=\"protocolo-crisis-content\">\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Fases del Protocolo<\/h4>\n\n<ul class=\"list-decimal list-inside ml-4 space-y-2\" id=\"protocolo-fases\"><\/ul>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Principios Fundamentales<\/h4>\n\n<ul class=\"list-disc list-inside ml-4 space-y-2\" id=\"protocolo-principios\"><\/ul>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"vocerias\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Foco en Vocer\u00edas: Perfiles Clave y Presencia Medi\u00e1tica<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">An\u00e1lisis de la visibilidad y el rol de los principales portavoces del Ayuntamiento en el ecosistema medi\u00e1tico.<\/p>\n\n<div class=\"grid grid-cols-1 md:grid-cols-2 gap-8\">\n\n<div class=\"space-y-6\" id=\"vocerias-list\">\n\n<\/div>\n\n<div class=\"bg-indigo-50 p-4 rounded-lg shadow-inner flex flex-col items-center justify-center\">\n\n<h4 class=\"text-lg font-medium text-indigo-700 mb-2 text-center\">Presencia Medi\u00e1tica de Vocer\u00edas<\/h4>\n\n<div class=\"chart-container\">\n\n<canvas id=\"voceriasChart\"><\/canvas>\n\n<\/div>\n\n<p class=\"text-sm text-slate-600 mt-4 text-center\">Escala: 1 (Baja) a 3 (Alta)<\/p>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"deportes\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Deportes en Dos Hermanas: Iniciativas y Proyecci\u00f3n<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Visi\u00f3n general de la promoci\u00f3n del deporte por parte del Ayuntamiento de Dos Hermanas y eventos destacados.<\/p>\n\n<div class=\"space-y-6\" id=\"deportes-content\">\n\n<p id=\"deportes-intro\"><\/p>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Programas e Iniciativas<\/h4>\n\n<ul class=\"list-disc list-inside ml-4\" id=\"deportes-programas\"><\/ul>\n\n<\/div>\n\n<div>\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-2\">Eventos Destacados<\/h4>\n\n<ul class=\"list-disc list-inside ml-4\" id=\"deportes-destacados\"><\/ul>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"narrative-map\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Mapa Narrativo: Conexiones y Temas Dominantes<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Este mapa conceptual ilustra las interconexiones entre los principales temas de conversaci\u00f3n, los actores que los impulsan y el sentimiento asociado. Permite visualizar la din\u00e1mica de las narrativas que afectan la reputaci\u00f3n del Ayuntamiento.<\/p>\n\n<div class=\"space-y-6\" id=\"narrative-map-content\">\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"say-do-gap\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Brecha Say-Do: Discurso vs. Percepci\u00f3n Ciudadana<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">La &#8216;Brecha Say-Do&#8217; analiza la diferencia entre lo que el Ayuntamiento comunica que hace (discurso oficial) y c\u00f3mo estas acciones son percibidas realmente por la ciudadan\u00eda. Una brecha significativa puede erosionar la confianza y la reputaci\u00f3n.<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-sm text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase\">\n\n<tr>\n\n<th class=\"p-3\">Aspecto<\/th>\n\n<th class=\"p-3\">Discurso Oficial<\/th>\n\n<th class=\"p-3\">Percepci\u00f3n Ciudadana<\/th>\n\n<th class=\"p-3\">Brecha<\/th>\n\n<th class=\"p-3\">Impacto Reputacional<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody id=\"say-do-table\">\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"early-warnings\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Se\u00f1ales Tempranas y &#8216;Cisnes Negros&#8217;<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Esta secci\u00f3n identifica indicios incipientes de posibles crisis o tendencias emergentes que, de no gestionarse, podr\u00edan escalar. Los &#8216;cisnes negros&#8217; son eventos inesperados de alto impacto.<\/p>\n\n<div class=\"space-y-6\" id=\"early-warnings-content\">\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"scenarios\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Escenarios y Proyecci\u00f3n Reputacional<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Proyecci\u00f3n de posibles escenarios futuros para la reputaci\u00f3n del Ayuntamiento, basados en la evoluci\u00f3n de los temas clave y la efectividad de las estrategias de comunicaci\u00f3n.<\/p>\n\n<div class=\"space-y-8\" id=\"scenarios-content\">\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"media-treatment\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Tratamiento de los Medios de Comunicaci\u00f3n<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Esta secci\u00f3n analiza c\u00f3mo los medios de comunicaci\u00f3n (prensa, radio, TV y digital) han abordado la gesti\u00f3n y las iniciativas del Ayuntamiento de Dos Hermanas, identificando patrones de cobertura, tonos dominantes y la influencia en la agenda p\u00fablica.<\/p>\n\n<div class=\"mb-8\">\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">Tono General de la Cobertura<\/h4>\n\n<p class=\"text-slate-700 mb-4 leading-relaxed\" id=\"overall-tone-description\"><\/p>\n\n<div class=\"chart-container\">\n\n<canvas id=\"mediaTreatmentSentimentChart\"><\/canvas>\n\n<\/div>\n\n<p class=\"text-sm text-slate-600 mt-4 text-center\">Desglose del sentimiento de la cobertura medi\u00e1tica.<\/p>\n\n<\/div>\n\n<div class=\"mb-8\">\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">Temas Dominantes y su Tratamiento<\/h4>\n\n<ul class=\"space-y-4\" id=\"dominant-themes-list\"><\/ul>\n\n<\/div>\n\n<div class=\"mb-8\">\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">Enfoque y Framing por Tipo de Medio<\/h4>\n\n<ul class=\"space-y-4\" id=\"media-framing-list\"><\/ul>\n\n<\/div>\n\n<div class=\"mb-8\">\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">An\u00e1lisis por Medio Espec\u00edfico<\/h4>\n\n<div class=\"flex flex-col md:flex-row items-center gap-4 mb-6\">\n\n<label for=\"media-selector\" class=\"text-slate-700 font-medium\">Selecciona un medio:<\/label>\n\n<select id=\"media-selector\" class=\"flex-grow p-2 border border-slate-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500\">\n\n<\/select>\n\n<\/div>\n\n<div class=\"bg-indigo-50 p-4 rounded-lg shadow-inner\">\n\n<h5 class=\"text-lg font-medium text-indigo-700 mb-2 text-center\" id=\"specific-media-title\"><\/h5>\n\n<p class=\"text-sm text-slate-600 mt-4 text-center\" id=\"specific-media-description\"><\/p>\n\n<div class=\"chart-container\">\n\n<canvas id=\"specificMediaSentimentChart\"><\/canvas>\n\n<\/div>\n\n<p class=\"text-sm text-slate-600 mt-4 text-center\">Desglose del sentimiento de la cobertura para el medio seleccionado.<\/p>\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"consolidated-report\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg\">\n\n<h3 class=\"text-2xl font-bold text-center mb-6 text-indigo-800\">Informe Consolidado de Inteligencia de Medios<\/h3>\n\n<p class=\"text-center text-slate-600 mb-8 max-w-3xl mx-auto\">Este informe integra los principales hallazgos del an\u00e1lisis de inteligencia de medios en un documento unificado, listo para su revisi\u00f3n y descarga en formato PDF.<\/p>\n\n<div id=\"consolidated-report-content\" class=\"pdf-content-wrapper\">\n\n<!-- Content will be dynamically generated here -->\n\n<\/div>\n\n<div class=\"text-center mt-8 space-x-4\">\n\n<a href=\"https:\/\/drive.google.com\/uc?export=download&#038;id=1oM32q_ANLWfra4srlvyVHcWv6Q7djqDQFzNtG0bvvWE\" target=\"_blank\" class=\"inline-block px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 transition-all\">\n\nDescargar Informe Original (Google Drive)\n\n<\/a>\n\n<button id=\"download-pdf-btn\" class=\"px-6 py-3 bg-indigo-600 text-white font-semibold rounded-lg shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-400 transition-all\">\n\nDescargar Informe Consolidado (PDF)\n\n<\/button>\n\n<\/div>\n\n<\/div>\n\n<\/section>\n\n<section id=\"about\" class=\"content-section\">\n\n<div class=\"bg-white p-6 rounded-2xl shadow-lg text-center\">\n\n<h3 class=\"text-2xl font-bold mb-4 text-indigo-800\">Sobre Este An\u00e1lisis Interactivo<\/h3>\n\n<p class=\"text-slate-700 max-w-2xl mx-auto\">\n\nEste panel interactivo ha sido dise\u00f1ado para ofrecer una visi\u00f3n din\u00e1mica y accesible del informe de inteligencia de medios del Ayuntamiento de Dos Hermanas para el per\u00edodo Mayo 2023 &#8211; Junio 2025. Su objetivo es facilitar la exploraci\u00f3n, comprensi\u00f3n y s\u00edntesis de la informaci\u00f3n clave sobre la reputaci\u00f3n institucional y la presencia digital.\n\nLa estructura de la aplicaci\u00f3n no replica el informe original, sino que busca la m\u00e1xima usabilidad y claridad para el usuario.\n\n<\/p>\n\n<p class=\"text-sm text-slate-500 mt-6\">\n\nDesarrollado como una herramienta de apoyo a la toma de decisiones estrat\u00e9gicas.\n\n<\/p>\n\n<\/div>\n\n<\/section>\n\n<\/main>\n\n<\/div>\n\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/html2pdf.js\/0.10.1\/html2pdf.bundle.min.js\"><\/script>\n\n<script>\n\ndocument.addEventListener('DOMContentLoaded', function() {\n\nconst appData = {\n\ncity: \"Dos Hermanas\", \/\/ Changed city to Dos Hermanas\n\nbalance: {\n\nlogros: [\n\n{ title: \"Proyectos de Movilidad Urbana\", description: \"Avances significativos en la fluidez del tr\u00e1fico y nuevas conexiones de transporte.\", icon: \"\ud83d\ude97\" },\n\n{ title: \"Inversi\u00f3n en Parques y Zonas Verdes\", description: \"Inauguraci\u00f3n de nuevos espacios verdes y mejora de los existentes, muy valorado por la ciudadan\u00eda.\", icon: \"\ud83c\udf33\" },\n\n{ title: \"Programas de Fomento del Empleo Local\", description: \"\u00c9xito en la inserci\u00f3n laboral de j\u00f3venes y colectivos vulnerables, con datos concretos.\", icon: \"\ud83d\udcbc\" },\n\n{ title: \"Eventos Culturales y Festivos\", description: \"Gran acogida de las actividades programadas en verano, fortaleciendo la cohesi\u00f3n social.\", icon: \"\ud83c\udf89\" },\n\n{ title: \"Transformaci\u00f3n Digital\", description: \"Lanzamiento de nuevas plataformas tecnol\u00f3gicas para una gesti\u00f3n municipal m\u00e1s \u00e1gil y cercana.\", icon: \"\ud83d\udcbb\" }\n\n],\n\nriesgos: [\n\n{ title: \"Mantenimiento de Infraestructuras Antiguas\", description: \"Necesidad de seguir invirtiendo en la renovaci\u00f3n de ciertas infraestructuras en barrios consolidados.\", icon: \"\ud83d\udee0\ufe0f\" },\n\n{ title: \"Participaci\u00f3n Ciudadana en Proyectos\", description: \"Oportunidad de mejorar los canales de feedback y la involucraci\u00f3n de los vecinos en las fases iniciales de algunos proyectos.\", icon: \"\ud83d\udde3\ufe0f\" },\n\n{ title: \"Gesti\u00f3n de Residuos\", description: \"Puntos espec\u00edficos donde la ciudadan\u00eda demanda una mayor frecuencia o eficiencia en la recogida.\", icon: \"\ud83d\uddd1\ufe0f\" },\n\n{ title: \"Tr\u00e1fico y Movilidad (puntos cr\u00edticos)\", description: \"Quejas recurrentes sobre atascos y la fluidez del tr\u00e1fico en ciertas zonas, especialmente en horas punta.\", icon: \"\ud83d\udea6\" }\n\n],\n\noverallSentiment: 70, \/\/ Adjusted overall sentiment for Dos Hermanas based on general data\n\nreputationChartData: { \/\/ Data for the interactive balance chart\n\nlogros: [90, 88, 92, 85, 89], \/\/ Sentiment for positive topics\n\nretos: [40, 30, 55, 48, 38] \/\/ Sentiment for negative topics\n\n},\n\nsentimentTrend: { \/\/ Data for the sentiment trend chart\n\nlabels: ['Jul 24', 'Ago 24', 'Sep 24', 'Oct 24', 'Nov 24', 'Dic 24', 'Ene 25', 'Feb 25', 'Mar 25', 'Abr 25', 'May 25', 'Jun 25'],\n\npositive: [75, 78, 80, 82, 85, 87, 88, 90, 89, 91, 90, 92],\n\nneutral: [20, 18, 15, 13, 10, 8, 7, 5, 6, 4, 5, 3],\n\nnegative: [5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]\n\n}\n\n},\n\nactores: {\n\nmedios: [\n\n{ name: \"Peri\u00f3dico El Nazareno\", type: \"Prensa Digital Local\" },\n\n{ name: \"Peri\u00f3dico La Semana de Dos Hermanas\", type: \"Prensa Digital Local\" },\n\n{ name: \"Cadena DH\", type: \"Prensa y TV Digital Local\" },\n\n{ name: \"Peri\u00f3dico El Quinto\", type: \"Prensa Digital Local\" },\n\n{ name: \"Diario de Sevilla - Secci\u00f3n Dos Hermanas\", type: \"Prensa Digital Provincial\" },\n\n{ name: \"ABC de Sevilla\", type: \"Prensa Digital Provincial\" },\n\n{ name: \"Europa Press Andaluc\u00eda\", type: \"Agencia de Noticias Regional\" }\n\n],\n\nciudadanos: [\n\n{ name: \"Asociaciones de Vecinos (Entren\u00facleos)\", role: \"Voces sobre servicios y urbanismo en zonas de expansi\u00f3n.\" },\n\n{ name: \"Federaci\u00f3n de AA.VV. 'Fernando Varela'\", role: \"Organismo aglutinador del movimiento vecinal.\" },\n\n{ name: \"Asociaciones de Comerciantes y Empresarios\", role: \"Influencia en temas econ\u00f3micos y de empleo.\" },\n\n{ name: \"Grupos de WhatsApp Vecinales\", role: \"Canales informales de opini\u00f3n y difusi\u00f3n de informaci\u00f3n.\" },\n\n{ name: \"Grupos de Facebook de Dos Hermanas\", role: \"Espacios de debate, quejas y cr\u00edticas.\" }\n\n],\n\ninfluyentes: [\n\n{ name: \"Francisco Rodr\u00edguez Garc\u00eda\", role: \"Alcalde-Presidente\", description: \"Figura central, continuidad y estabilidad.\" },\n\n{ name: \"Juan Antonio Vilches Romero\", role: \"Delegado de Hacienda\", description: \"Gesti\u00f3n econ\u00f3mica y presupuestaria.\" },\n\n{ name: \"Ana Mar\u00eda Conde Huelva\", role: \"Delegada de Urbanismo\", description: \"Proyectos de transformaci\u00f3n urbana.\" },\n\n{ name: \"Rafael Rey Sierra\", role: \"Concejal de Educaci\u00f3n\", description: \"Inversi\u00f3n en educaci\u00f3n y formaci\u00f3n.\" },\n\n{ name: \"Victoria Tirsa Herv\u00e1s Torres\", role: \"Concejala de Deportes\", description: \"Fomento del deporte y eventos.\" }\n\n],\n\ndelegationSentiment: { \/\/ Data for the interactive delegation sentiment chart\n\nlabels: ['Urbanismo', 'Movilidad', 'Educaci\u00f3n', 'Deportes', 'Servicios Sociales', 'Limpieza', 'Cultura', 'Medio Ambiente'],\n\ndata: [80, 70, 90, 95, 88, 60, 85, 75] \/\/ Sample sentiment data for each delegation\n\n}\n\n},\n\nalcalde: {\n\nnombre: \"Francisco Rodr\u00edguez Garc\u00eda\",\n\nresumen: \"El alcalde Francisco Rodr\u00edguez Garc\u00eda se ha consolidado como una figura de continuidad y estabilidad, heredando un legado de gesti\u00f3n y desarrollo. Sus mensajes se centran en el crecimiento de la ciudad, la mejora de infraestructuras (especialmente educativas y deportivas), el fomento del empleo y la cohesi\u00f3n social. Ha buscado proyectar una imagen de gesti\u00f3n activa y compromiso con el desarrollo local. Su figura puede verse asociada a las cr\u00edticas sobre el tr\u00e1fico y ciertas infraestructuras, especialmente en canales no oficiales.\",\n\nmensajesClave: [\n\n\"La transformaci\u00f3n urbana de Dos Hermanas (ej. Entren\u00facleos).\",\n\n\"La inversi\u00f3n en educaci\u00f3n y formaci\u00f3n profesional.\",\n\n\"El desarrollo de grandes proyectos (ej. Ciudad del Conocimiento).\",\n\n\"El mantenimiento de un di\u00e1logo cercano con la ciudadan\u00eda y colectivos.\"\n\n],\n\ndesafiosComunicativos: [\n\n\"Abordar p\u00fablicamente los desaf\u00edos (ej. tr\u00e1fico, obras en zonas espec\u00edficas) con planes concretos y cronogramas claros, mostrando empat\u00eda.\",\n\n\"Contrarrestar la desinformaci\u00f3n en redes sociales y grupos no oficiales.\",\n\n\"Reforzar la escucha activa y la respuesta a las inquietudes ciudadanas.\"\n\n],\n\nsentiment: { positive: 75, neutral: 20, negative: 5 } \/\/ Sample sentiment for alcalde\n\n},\n\ndigital: {\n\ncanalesOficiales: [\n\n{ type: 'Sitio Web Oficial', name: 'doshermanas.es', purpose: 'Portal principal de noticias, servicios y campa\u00f1as.' },\n\n{ type: 'Sede Electr\u00f3nica', name: 'sede.doshermanas.es', purpose: 'Tr\u00e1mites administrativos y oferta p\u00fablica de empleo.' },\n\n{ type: 'YouTube', name: 'Ayuntamiento de Dos Hermanas', purpose: 'Videos institucionales, eventos y promoci\u00f3n de la ciudad.' },\n\n{ type: 'Facebook (Oficial)', name: 'Ayuntamiento de Dos Hermanas', purpose: 'Difusi\u00f3n de noticias, eventos y comunicaci\u00f3n directa.' },\n\n{ type: 'X (Twitter) (Oficial)', name: '@Ayto_DH', purpose: 'Actualizaciones r\u00e1pidas, noticias y respuesta a consultas.' },\n\n{ type: 'Instagram (Oficial)', name: 'aytodehnas', purpose: 'Contenido visual de eventos, proyectos y vida municipal.' }\n\n],\n\nredesSocialesMetrics: { \/\/ Data for interactive digital charts\n\nlabels: ['Web Oficial', 'Facebook', 'Twitter (X)', 'Instagram', 'Grupos Vecinales', 'TikTok'],\n\nreach: [90, 80, 60, 70, 50, 40], \/\/ Sample reach data\n\nengagement: [70, 60, 40, 50, 80, 30] \/\/ Sample engagement data\n\n},\n\nmediaSentiment: { \/\/ Data for interactive media sentiment chart\n\nlabels: ['Canales Oficiales', 'Prensa Local', 'Redes Sociales (No Oficiales)', 'Blogs\/Foros Vecinales'],\n\npositivo: [95, 75, 50, 40],\n\nneutral: [5, 15, 30, 35],\n\nnegativo: [0, 10, 20, 25]\n\n}\n\n},\n\ntimeline: [\n\n{ month: \"Jul 2024\", events: [\"Apertura Parque Urbano 'El Olivar'\", \"Inicio Campa\u00f1a 'Verano Activo'\"] },\n\n{ month: \"Ago 2024\", events: [\"Eventos culturales de verano\", \"Mejora de la Red de Autobuses Urbanos\"] },\n\n{ month: \"Sep 2024\", events: [\"Foro Ciudadano sobre Urbanismo Sostenible\", \"Inicio de curso escolar\"] },\n\n{ month: \"Oct 2024\", events: [\"Inversi\u00f3n en Digitalizaci\u00f3n de Servicios\", \"Nuevas viviendas en Entren\u00facleos\"] },\n\n{ month: \"Nov 2024\", events: [\"Aprobaci\u00f3n Presupuestos 2025\", \"Programas de empleo juvenil\"] },\n\n{ month: \"Dic 2024\", events: [\"Actividades navide\u00f1as\", \"Anuncio inicio obras estaci\u00f3n cercan\u00edas 2026\"] },\n\n{ month: \"Ene 2025\", events: [\"Nueva plataforma de tr\u00e1mites municipales\", \"Proyectos de conectividad en barrios\"] },\n\n{ month: \"Feb 2025\", events: [\"Preparativos Semana Santa\", \"Ampliaci\u00f3n de servicios de limpieza\"] },\n\n{ month: \"Mar 2025\", events: [\"Celebraci\u00f3n Semana Santa 2025\", \"Plan 'Dos Hermanas Conecta'\"] },\n\n{ month: \"Abr 2025\", events: [\"Reconocimiento a Deportistas Ol\u00edmpicos\", \"Eventos culturales post-Semana Santa\"] },\n\n{ month: \"May 2025\", events: [\"Feria de Dos Hermanas 2025\", \"Cumplimiento de medidas de seguridad en Way Dos Hermanas\"] },\n\n{ month: \"Jun 2025\", events: [\"Problemas de tr\u00e1fico en AP4\", \"Detenci\u00f3n por empotrar coche en Montequinto\", \"Devoluci\u00f3n de 120.000\u20ac a empresa 'trama Koldo'.\"] }\n\n],\n\nmatrizRO: {\n\nriesgos: [\n\n{ name: \"Tr\u00e1fico y Movilidad\", impact: \"Alto\", likelihood: \"Alto\", mitigation: \"Comunicaci\u00f3n proactiva de planes de mejora; alternativas de transporte.\", controlAction: \"Implementar plan de tr\u00e1fico inteligente; campa\u00f1as de uso de transporte p\u00fablico.\" },\n\n{ name: \"Limpieza y Mantenimiento Urbano\", impact: \"Medio\", likelihood: \"Medio\", mitigation: \"Comunicar acciones espec\u00edficas y resultados; campa\u00f1as de concienciaci\u00f3n.\", controlAction: \"Reforzar equipos de limpieza; habilitar canal de quejas y sugerencias con respuesta \u00e1gil.\" },\n\n{ name: \"Desarrollo Urban\u00edstico (Entren\u00facleos)\", impact: \"Medio\", likelihood: \"Medio\", mitigation: \"Gestionar expectativas; informar sobre plazos y beneficios.\", controlAction: \"Canales de di\u00e1logo con vecinos; visitas guiadas a proyectos.\" },\n\n{ name: \"Casos de Corrupci\u00f3n (Trama Koldo)\", impact: \"Alto\", likelihood: \"Bajo\", mitigation: \"Transparencia total; colaboraci\u00f3n con la justicia; auditor\u00edas internas.\", controlAction: \"Publicar toda la informaci\u00f3n relevante; reforzar el canal de denuncias interno.\" }\n\n],\n\noportunidades: [\n\n{ name: \"Grandes Proyectos de Ciudad\", benefit: \"Muy Alto\", strategy: \"Posicionar al alcalde como impulsor clave; comunicar impacto en calidad de vida.\" },\n\n{ name: \"Inversi\u00f3n en Educaci\u00f3n y Deporte\", benefit: \"Alto\", strategy: \"Comunicar logros y beneficios directos a familias y j\u00f3venes.\" },\n\n{ name: \"Fomento del Empleo y la Econom\u00eda Local\", benefit: \"Alto\", strategy: \"Difundir datos de creaci\u00f3n de empleo; casos de \u00e9xito de emprendedores.\" },\n\n{ name: \"Programas Sociales y de Bienestar\", benefit: \"Medio-Alto\", strategy: \"Visibilizar impacto en colectivos vulnerables; testimonios ciudadanos.\" }\n\n]\n\n},\n\ntermometro: [\n\n{ topic: \"Urbanismo y Desarrollo\", sentiment: 85, color: \"#10B981\" },\n\n{ topic: \"Educaci\u00f3n\", sentiment: 90, color: \"#10B981\" },\n\n{ topic: \"Deportes\", sentiment: 95, color: \"#10B981\" },\n\n{ topic: \"Empleo\", sentiment: 80, color: \"#10B981\" },\n\n{ topic: \"Servicios Sociales\", sentiment: 88, color: \"#10B981\" },\n\n{ topic: \"Movilidad y Tr\u00e1fico\", sentiment: 45, color: \"#EF4444\" },\n\n{ topic: \"Limpieza Urbana\", sentiment: 60, color: \"#FBBF24\" },\n\n{ topic: \"Seguridad Ciudadana\", sentiment: 70, color: \"#FBBF24\" }\n\n],\n\nposicionamiento: {\n\nactual: \"Dos Hermanas es percibida como una ciudad en constante crecimiento y desarrollo, con una fuerte inversi\u00f3n en infraestructuras y servicios. La gesti\u00f3n municipal es vista como s\u00f3lida y orientada al progreso, aunque con desaf\u00edos en la resoluci\u00f3n de problemas cotidianos como el tr\u00e1fico.\",\n\ndeseado: \"Ser reconocida como una ciudad moderna, sostenible y participativa, donde la calidad de vida es una prioridad, con una gesti\u00f3n eficiente y transparente que escucha activamente a sus ciudadanos.\",\n\nbrecha: \"La brecha principal radica en la percepci\u00f3n de cercan\u00eda y eficiencia en la resoluci\u00f3n de problemas diarios, y en la comunicaci\u00f3n proactiva de los esfuerzos para abordar estos desaf\u00edos.\",\n\nvaluesRadar: { \/\/ Data for radar chart\n\nlabels: ['Cercan\u00eda', 'Eficacia', 'Transparencia', 'Patrimonio', 'Innovaci\u00f3n'],\n\nperceived: [7, 8, 6, 9, 7], \/\/ Percepci\u00f3n actual (0-10)\n\ndesired: [9, 9, 8, 9, 8] \/\/ Valores deseados (0-10)\n\n}\n\n},\n\nbenchmarking: [\n\n{ city: \"Alcal\u00e1 de Guada\u00edra\", comparison: \"Municipio con desaf\u00edos urban\u00edsticos y de servicios, puede ofrecer lecciones en gesti\u00f3n de infraestructuras y participaci\u00f3n.\" },\n\n{ city: \"Mairena del Aljarafe\", comparison: \"Ciudad con alto nivel de vida, interesante para comparar estrategias de desarrollo urbano y servicios.\" },\n\n{ city: \"\u00c9cija\", comparison: \"Ciudad con patrimonio hist\u00f3rico, posible referente en gesti\u00f3n cultural y tur\u00edstica.\" },\n\n{ city: \"Utrera\", comparison: \"Municipio cercano con din\u00e1micas similares, \u00fatil para comparar estrategias de desarrollo econ\u00f3mico y social.\" }\n\n],\n\nkpis: {\n\nallKpis: [\n\n{ id: 'engagementSocialNeto', title: 'Engagement Social Neto', value: 45, unit: '%', description: 'Porcentaje de interacciones positivas sobre el total en canales digitales (oficiales y no oficiales).', change: '+7', isPercentage: true },\n\n{ id: 'visibilidadProactiva', title: 'Visibilidad Proactiva vs. Reactiva', value: 80, unit: '%', description: 'Porcentaje de noticias generadas por iniciativa del Ayuntamiento frente a respuestas a crisis.', change: '+3', isPercentage: true },\n\n{ id: 'impactoMediaticoProvincial', title: 'Impacto Medi\u00e1tico Provincial', value: 9, unit: '\/10', description: 'Puntuaci\u00f3n de la cobertura en medios provinciales (0-10).', change: '+1', isPercentage: false },\n\n{ id: 'sentimientoNetoAlcalde', title: 'Sentimiento Neto Alcalde', value: 75, unit: '%', description: 'Sentimiento promedio asociado a la figura del alcalde en todos los medios.', change: '+2', isPercentage: true },\n\n{ id: 'sentimientoMovilidadTrafico', title: 'Sentimiento Neto en Movilidad\/Tr\u00e1fico', value: 35, unit: '%', description: 'Sentimiento promedio asociado al tema de la movilidad y el tr\u00e1fico.', change: '-5', isPercentage: true },\n\n{ id: 'mencionesMediosDigitalesLocales', title: 'Menciones en Medios Digitales Locales', value: 950, unit: '', description: 'N\u00famero total de menciones del Ayuntamiento en medios digitales locales por mes.', change: '+120', isPercentage: false }\n\n]\n\n},\n\nestrategia: {\n\nnarrativaActual: \"Enfocada en el desarrollo local, programas educativos y de empleo, y la promoci\u00f3n cultural y tur\u00edstica. Proyecta una imagen de gesti\u00f3n activa y compromiso con la comunidad.\",\n\nnarrativaRecomendada: \"Incorporar una narrativa m\u00e1s centrada en la transparencia y la rendici\u00f3n de cuentas, justificando decisiones dif\u00edciles y mostrando un compromiso real con la participaci\u00f3n ciudadana. Humanizar la gesti\u00f3n y abordar proactivamente las preocupaciones sobre servicios esenciales.\",\n\naccionesClave: [\n\n\"Crear historias que conecten los programas con el impacto directo en la vida de los ciudadanos.\",\n\n\"Establecer canales de feedback claros y gestionados activamente.\",\n\n\"Desarrollar un argumentario s\u00f3lido para temas sensibles como la transparencia y los servicios p\u00fablicos.\"\n\n]\n\n},\n\nprotocoloCrisis: {\n\nfases: [\n\n{ name: \"Detecci\u00f3n y Alerta\", description: \"Monitorizaci\u00f3n constante de medios y redes (incluyendo grupos no oficiales) para identificar se\u00f1ales tempranas de crisis. Establecimiento de umbrales de alerta.\" },\n\n{ name: \"Evaluaci\u00f3n y Clasificaci\u00f3n\", description: \"An\u00e1lisis r\u00e1pido del tipo de crisis, su alcance y potencial impacto reputacional. Nombramiento de un comit\u00e9 de crisis.\" },\n\n{ name: \"Respuesta y Contenci\u00f3n\", description: \"Elaboraci\u00f3n de mensajes clave, designaci\u00f3n de portavoces, comunicaci\u00f3n proactiva y transparente. Coordinaci\u00f3n con \u00e1reas afectadas.\" },\n\n{ name: \"Seguimiento y Recuperaci\u00f3n\", description: \"Monitorizaci\u00f3n continua de la evoluci\u00f3n de la crisis. Evaluaci\u00f3n del impacto a largo plazo y acciones de recuperaci\u00f3n de la reputaci\u00f3n.\" }\n\n],\n\nprincipios: [\n\n\"Transparencia y honestidad.\",\n\n\"Agilidad en la respuesta.\",\n\n\"Empat\u00eda con los afectados.\",\n\n\"Unidad de mensaje.\"\n\n]\n\n},\n\nvocerias: [\n\n{ name: \"Alcalde (Francisco Rodr\u00edguez Garc\u00eda)\", role: \"M\u00e1xima autoridad, visi\u00f3n estrat\u00e9gica de ciudad.\", mediaPresence: \"Alta\", mediaPresenceValue: 3 },\n\n{ name: \"Delegado de Urbanismo (Ana Mar\u00eda Conde)\", role: \"Proyectos de transformaci\u00f3n urbana.\", mediaPresence: \"Media-Alta\", mediaPresenceValue: 2.5 },\n\n{ name: \"Delegado de Hacienda (Juan Antonio Vilches)\", role: \"Gesti\u00f3n econ\u00f3mica y presupuestaria.\", mediaPresence: \"Media\", mediaPresenceValue: 2 },\n\n{ name: \"Concejala de Deportes (Victoria Tirsa Herv\u00e1s)\", role: \"Programas deportivos y eventos.\", mediaPresence: \"Media\", mediaPresenceValue: 2 }\n\n],\n\ndeportes: {\n\nintro: \"El Ayuntamiento de Dos Hermanas promueve activamente el deporte en la ciudad a trav\u00e9s de diversas iniciativas y eventos, buscando fomentar h\u00e1bitos de vida saludables y el desarrollo de talentos locales.\",\n\nprogramas: [\n\n\"Programas de Deporte Base y Escuelas Deportivas.\",\n\n\"Apoyo a clubes y asociaciones deportivas locales.\",\n\n\"Organizaci\u00f3n de eventos deportivos populares (carreras, maratones, ciclismo).\",\n\n\"Mantenimiento y mejora de instalaciones deportivas municipales.\"\n\n],\n\ndestacados: [\n\n\"Inauguraci\u00f3n de nuevas instalaciones deportivas en Entren\u00facleos.\",\n\n\"Celebraci\u00f3n de la Media Marat\u00f3n de Dos Hermanas.\"\n\n]\n\n},\n\nnarrativeMap: {\n\ntitle: \"Mapa Narrativo: Conexiones y Temas Dominantes\",\n\ndescription: \"Este mapa conceptual ilustra las interconexiones entre los principales temas de conversaci\u00f3n, los actores que los impulsan y el sentimiento asociado. Permite visualizar la din\u00e1mica de las narrativas que afectan la reputaci\u00f3n del Ayuntamiento.\",\n\nelements: [\n\n{ theme: \"Desarrollo Urbano (Entren\u00facleos)\", actors: \"Ayuntamiento, Promotoras, Vecinos\", sentiment: \"Positivo\", connections: [\"Inversi\u00f3n\", \"Vivienda\", \"Servicios\"] },\n\n{ theme: \"Movilidad y Tr\u00e1fico\", actors: \"Ciudadanos, Oposici\u00f3n, Medios locales\", sentiment: \"Negativo\", connections: [\"Calidad de vida\", \"Infraestructuras\"] },\n\n{ theme: \"Educaci\u00f3n y Formaci\u00f3n\", actors: \"Ayuntamiento, Centros educativos, Familias\", sentiment: \"Positivo\", connections: [\"Futuro\", \"Empleo\"] },\n\n{ theme: \"Transparencia y Gesti\u00f3n\", actors: \"Oposici\u00f3n, Medios, Ciudadanos\", sentiment: \"Mixto\/Negativo\", connections: [\"Confianza\", \"Rendici\u00f3n de cuentas\"] }\n\n]\n\n},\n\nsayDoGap: {\n\ntitle: \"Brecha Say-Do: Discurso vs. Percepci\u00f3n Ciudadana\",\n\ndescription: \"La 'Brecha Say-Do' analiza la diferencia entre lo que el Ayuntamiento de Dos Hermanas comunica que hace (discurso oficial) y c\u00f3mo estas acciones son percibidas realmente por la ciudadan\u00eda. Una brecha significativa puede erosionar la confianza y la reputaci\u00f3n.\",\n\nanalysis: [\n\n{ aspect: \"Gesti\u00f3n del Tr\u00e1fico\", discourse: \"Inversi\u00f3n en infraestructuras y planes de mejora.\", perception: \"Atascos persistentes y falta de fluidez en puntos clave.\", gap: \"Alta\", impact: \"Frustraci\u00f3n ciudadana, cr\u00edticas en redes.\" },\n\n{ aspect: \"Limpieza Urbana\", discourse: \"Compromiso con la limpieza y aumento de recursos.\", perception: \"Quejas puntuales en barrios espec\u00edficos por falta de limpieza.\", gap: \"Media\", impact: \"Impacto en la imagen de la ciudad y calidad de vida.\" },\n\n{ aspect: \"Transparencia en Contrataci\u00f3n\", discourse: \"Compromiso con la legalidad y buenas pr\u00e1cticas.\", perception: \"Casos como la 'trama Koldo' generan dudas.\", gap: \"Alta\", impact: \"Erosi\u00f3n de la confianza, cuestionamiento de la gesti\u00f3n.\" }\n\n]\n\n},\n\nearlyWarnings: {\n\ntitle: \"Se\u00f1ales Tempranas y 'Cisnes Negros'\",\n\ndescription: \"Esta secci\u00f3n identifica indicios incipientes de posibles crisis o tendencias emergentes que, de no gestionarse, podr\u00edan escalar. Los 'cisnes negros' son eventos inesperados de alto impacto. Una monitorizaci\u00f3n proactiva es clave para detectarlas.\",\n\nsignals: [\n\n{ type: \"Riesgo de Crisis\", name: \"Trama 'Koldo' en contratos municipales\", description: \"La aparici\u00f3n de vinculaciones con la 'trama Koldo' en contratos municipales es una se\u00f1al de alarma que puede escalar a una crisis reputacional grave.\", mitigation: \"Transparencia total en la investigaci\u00f3n; colaboraci\u00f3n con la justicia; comunicaci\u00f3n proactiva de los hallazgos y medidas tomadas.\" },\n\n{ type: \"Tendencia\", name: \"Aumento de quejas por tr\u00e1fico\", description: \"El incremento constante de quejas sobre el tr\u00e1fico en redes y foros indica un malestar creciente que, de no abordarse, puede generar movilizaciones o protestas.\", mitigation: \"Comunicaci\u00f3n frecuente de avances en planes de movilidad; habilitar canales directos para reportar incidencias y recibir actualizaciones.\" },\n\n{ type: \"Riesgo Reputacional\", name: \"Descontento con limpieza en barrios\", description: \"Las quejas recurrentes sobre la limpieza en barrios espec\u00edficos pueden generar una percepci\u00f3n generalizada de ineficiencia si no se visibilizan las acciones de mejora.\", mitigation: \"Campa\u00f1as de concienciaci\u00f3n ciudadana; visibilizar el trabajo de los equipos de limpieza; implementar un sistema de 'antes y despu\u00e9s' de las actuaciones.\" }\n\n]\n\n},\n\nscenarios: [\n\n{\n\nname: \"Dos Hermanas: Ciudad L\u00edder y Conectada\",\n\ndescription: \"El Ayuntamiento implementa eficazmente estrategias de comunicaci\u00f3n proactiva y transparencia. La gesti\u00f3n de desaf\u00edos (tr\u00e1fico, limpieza) se comunica con \u00e9xito, fortaleciendo la confianza. La presencia digital se optimiza, convirtiendo a Dos Hermanas en un referente de buena gobernanza y participaci\u00f3n.\",\n\ntype: \"Optimista\"\n\n},\n\n{\n\nname: \"Desarrollo Continuo con Desaf\u00edos Persistentes\",\n\ndescription: \"El Ayuntamiento sigue avanzando en grandes proyectos, manteniendo una imagen de progreso. Sin embargo, los desaf\u00edos cotidianos (tr\u00e1fico, limpieza) persisten y generan ruido en la conversaci\u00f3n ciudadana, requiriendo esfuerzos constantes para gestionar la percepci\u00f3n p\u00fablica.\",\n\ntype: \"Realista\"\n\n},\n\n{\n\nname: \"Crisis de Confianza y Desconexi\u00f3n Ciudadana\",\n\ndescription: \"La falta de abordaje proactivo de los desaf\u00edos y una comunicaci\u00f3n reactiva o insuficiente llevan a una escalada de la desconfianza. Las crisis (ej. trama Koldo) se amplifican, y la brecha entre el discurso oficial y la percepci\u00f3n ciudadana se agranda, afectando gravemente la reputaci\u00f3n y la gobernabilidad.\",\n\ntype: \"Pesimista\"\n\n}\n\n],\n\nmediaTreatment: {\n\ntitle: \"Tratamiento de los Medios de Comunicaci\u00f3n\",\n\nintro: \"Esta secci\u00f3n analiza c\u00f3mo los medios de comunicaci\u00f3n (prensa, radio, TV y digital) han abordado la gesti\u00f3n y las iniciativas del Ayuntamiento de Dos Hermanas, identificando patrones de cobertura, tonos dominantes y la influencia en la agenda p\u00fablica.\",\n\noverallTone: {\n\ndescription: \"El tono general de la cobertura medi\u00e1tica durante el per\u00edodo ha sido mayoritariamente **positivo e informativo** en los medios locales y provinciales, centrado en el desarrollo urbano y las inversiones. Se observan picos de **tono neutro a cr\u00edtico** en relaci\u00f3n con temas de tr\u00e1fico y quejas puntuales de servicios.\",\n\nsentimentBreakdown: [\n\n{ label: \"Positivo\", value: 60, color: \"#10B981\" },\n\n{ label: \"Neutral\/Informativo\", value: 30, color: \"#6366F1\" },\n\n{ label: \"Negativo\/Cr\u00edtico\", value: 10, color: \"#EF4444\" }\n\n]\n\n},\n\ndominantThemes: [\n\n{ theme: \"Urbanismo y Grandes Proyectos\", coverage: \"Muy Alta\", tone: \"Positivo\", impact: \"Refuerza la imagen de ciudad en crecimiento y desarrollo.\" },\n\n{ theme: \"Empleo y Formaci\u00f3n\", coverage: \"Alta\", tone: \"Positivo\", impact: \"Destaca el compromiso municipal con el bienestar econ\u00f3mico.\" },\n\n{ theme: \"Educaci\u00f3n y Cultura\", coverage: \"Alta\", tone: \"Positivo\", impact: \"Promueve la calidad de vida y el desarrollo social.\" },\n\n{ theme: \"Movilidad y Tr\u00e1fico\", coverage: \"Media\", tone: \"Mixto\/Negativo\", impact: \"Genera debate y cr\u00edticas, afectando la percepci\u00f3n de eficiencia.\" },\n\n{ theme: \"Servicios P\u00fablicos (Limpieza)\", coverage: \"Media\", tone: \"Mixto\", impact: \"Percepci\u00f3n variable, con oportunidades de mejora en la comunicaci\u00f3n.\" },\n\n{ theme: \"Transparencia y Gesti\u00f3n\", coverage: \"Baja\", tone: \"Cr\u00edtico\", impact: \"Puntos de fricci\u00f3n que pueden erosionar la confianza.\" }\n\n],\n\nmediaFraming: [\n\n{ mediaType: \"Prensa Digital Local (El Nazareno, La Semana, El Quinto)\", framing: \"Enfoque en la actualidad municipal, anuncios, eventos, pero tambi\u00e9n reflejan quejas vecinales.\" },\n\n{ mediaType: \"TV Digital Local (Cadena DH)\", framing: \"Cobertura de eventos, plenos y noticias locales con un tono generalmente informativo.\" },\n\n{ mediaType: \"Prensa Provincial (Diario de Sevilla, ABC de Sevilla)\", framing: \"Cobertura de Dos Hermanas por su relevancia, a menudo en temas de grandes proyectos o sucesos.\" },\n\n{ mediaType: \"Agencias de Noticias (Europa Press Andaluc\u00eda)\", framing: \"Difusi\u00f3n de comunicados oficiales y noticias de inter\u00e9s regional relacionadas con el municipio.\" }\n\n],\n\nmediaOutletsSentiment: [\n\n{ name: \"Peri\u00f3dico El Nazareno\", description: \"Principal medio digital local, con cobertura amplia y generalmente positiva de la gesti\u00f3n municipal.\", sentiment: { positive: 70, neutral: 25, negative: 5 } },\n\n{ name: \"Peri\u00f3dico La Semana de Dos Hermanas\", description: \"Ofrece noticias locales con un tono equilibrado, cubriendo tanto logros como desaf\u00edos.\", sentiment: { positive: 65, neutral: 30, negative: 5 } },\n\n{ name: \"Cadena DH\", description: \"Plataforma digital con noticias y contenido audiovisual, tono mayoritariamente informativo.\", sentiment: { positive: 55, neutral: 40, negative: 5 } },\n\n{ name: \"Peri\u00f3dico El Quinto\", description: \"Cubre temas de inter\u00e9s local, incluyendo aspectos cr\u00edticos de la gesti\u00f3n, con un tono m\u00e1s directo.\", sentiment: { positive: 45, neutral: 40, negative: 15 } },\n\n{ name: \"Diario de Sevilla - Secci\u00f3n Dos Hermanas\", description: \"Cobertura provincial que incluye noticias de Dos Hermanas, a menudo con un enfoque en grandes proyectos o sucesos.\", sentiment: { positive: 40, neutral: 40, negative: 20 } },\n\n{ name: \"ABC de Sevilla\", description: \"Cobertura provincial, con un tono que puede ser m\u00e1s cr\u00edtico o anal\u00edtico en temas de gesti\u00f3n pol\u00edtica.\", sentiment: { positive: 35, neutral: 45, negative: 20 } },\n\n{ name: \"Europa Press Andaluc\u00eda\", description: \"Difunde noticias de inter\u00e9s regional, incluyendo comunicados y eventos del Ayuntamiento de Dos Hermanas.\", sentiment: { positive: 55, neutral: 35, negative: 10 } }\n\n]\n\n}\n\n};\n\nconst navButtons = document.querySelectorAll('.nav-button[data-target]');\n\nconst contentSections = document.querySelectorAll('.content-section');\n\nconst infoDisplay = document.getElementById('info-display');\n\nconst btnLogros = document.getElementById('btn-logros');\n\nconst btnRiesgos = document.getElementById('btn-riesgos');\n\nconst overallSentimentValue = document.getElementById('overall-sentiment-value');\n\n\/\/ Variables para almacenar instancias de gr\u00e1ficos para poder destruirlas\n\nlet digitalReachChart = null;\n\nlet digitalEngagementChart = null;\n\nlet voceriasChart = null;\n\nlet mediaTreatmentSentimentChart = null;\n\nlet specificMediaSentimentChart = null;\n\nlet alcaldeSentimentChart = null;\n\nlet reputationChart = null; \/\/ Added for balance section\n\nlet sentimentTrendChart = null; \/\/ Added for balance section\n\nlet delegationSentimentChart = null; \/\/ Added for actores section\n\nlet comparativeSentimentChart = null; \/\/ Added for termometro section\n\nlet valuesRadarChart = null; \/\/ Added for posicionamiento section\n\nlet socialMediaComparisonChart = null; \/\/ Added for benchmarking section\n\n\/\/ Define chartConfigs *after* appData is fully defined\n\nconst chartConfigs = [\n\n{\n\nid: 'reputationChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: ['Urbanismo', 'Educaci\u00f3n', 'Deporte', 'Empleo', 'Social'],\n\ndatasets: [{\n\nlabel: 'Sentimiento (%)',\n\ndata: appData.balance.reputationChartData?.logros ?? [], \/\/ Use optional chaining and fallback\n\nbackgroundColor: '#10B981', \/\/ Emerald-500\n\nborderColor: '#059669', \/\/ Emerald-600\n\nborderWidth: 1\n\n}]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\ndisplay: false,\n\nlabels: { font: { family: 'Inter' } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: (context) => `${context.dataset.label}: ${context.raw}%`\n\n}\n\n}\n\n},\n\nscales: {\n\ny: {\n\nbeginAtZero: true,\n\nmax: 100,\n\ntitle: {\n\ndisplay: true,\n\ntext: 'Sentimiento Positivo (%)',\n\nfont: { family: 'Inter' }\n\n},\n\nticks: { font: { family: 'Inter' } }\n\n},\n\nx: {\n\nticks: { font: { family: 'Inter' } }\n\n}\n\n}\n\n}\n\n},\n\n{\n\nid: 'sentimentTrendChart',\n\ntype: 'line',\n\ndata: {\n\nlabels: appData.balance.sentimentTrend?.labels ?? [],\n\ndatasets: [\n\n{\n\nlabel: 'Positivo',\n\ndata: appData.balance.sentimentTrend?.positive ?? [],\n\nborderColor: '#10B981', \/\/ Emerald-500\n\nbackgroundColor: 'rgba(16, 185, 129, 0.2)',\n\nfill: true,\n\ntension: 0.3\n\n},\n\n{\n\nlabel: 'Neutral',\n\ndata: appData.balance.sentimentTrend?.neutral ?? [],\n\nborderColor: '#6366F1', \/\/ Indigo-500\n\nbackgroundColor: 'rgba(99, 102, 241, 0.2)',\n\nfill: true,\n\ntension: 0.3\n\n},\n\n{\n\nlabel: 'Negativo',\n\ndata: appData.balance.sentimentTrend?.negative ?? [],\n\nborderColor: '#EF4444', \/\/ Red-500\n\nbackgroundColor: 'rgba(239, 68, 68, 0.2)',\n\nfill: true,\n\ntension: 0.3\n\n}\n\n]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\nposition: 'top',\n\nlabels: { font: { family: 'Inter' } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: (context) => `${context.dataset.label}: ${context.raw}%`\n\n}\n\n}\n\n},\n\nscales: {\n\ny: {\n\nbeginAtZero: true,\n\nmax: 100,\n\ntitle: {\n\ndisplay: true,\n\ntext: 'Sentimiento Promedio (%)',\n\nfont: { family: 'Inter' }\n\n},\n\nticks: { font: { family: 'Inter' } }\n\n},\n\nx: {\n\nticks: { font: { family: 'Inter' } }\n\n}\n\n}\n\n}\n\n},\n\n{\n\nid: 'delegationSentimentChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: appData.actores.delegationSentiment?.labels ?? [],\n\ndatasets: [{\n\nlabel: 'Sentimiento Neto (%)',\n\ndata: appData.actores.delegationSentiment?.data ?? [],\n\nbackgroundColor: (appData.actores.delegationSentiment?.data ?? []).map(value => {\n\nif (value >= 70) return '#10B981'; \/\/ Green\n\nif (value >= 50) return '#FBBF24'; \/\/ Yellow\n\nreturn '#EF4444'; \/\/ Red\n\n}),\n\nborderColor: (appData.actores.delegationSentiment?.data ?? []).map(value => {\n\nif (value >= 70) return '#059669';\n\nif (value >= 50) return '#D97706';\n\nreturn '#DC2626';\n\n}),\n\nborderWidth: 1\n\n}]\n\n},\n\noptions: {\n\nindexAxis: 'y',\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\ndisplay: false,\n\nlabels: { font: { family: 'Inter' } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: (context) => `${context.dataset.label}: ${context.raw}%`\n\n}\n\n}\n\n},\n\nscales: {\n\ny: {\n\nbeginAtZero: true,\n\nmax: 100,\n\ntitle: {\n\ndisplay: true,\n\ntext: 'Sentimiento Neto (%)',\n\nfont: { family: 'Inter' }\n\n},\n\nticks: { font: { family: 'Inter' } }\n\n},\n\nx: {\n\nticks: { font: { family: 'Inter' } }\n\n}\n\n}\n\n}\n\n},\n\n{\n\nid: 'mediaSentimentChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: appData.digital.mediaSentiment?.labels ?? [],\n\ndatasets: [\n\n{\n\nlabel: 'Positivo',\n\ndata: appData.digital.mediaSentiment?.positivo ?? [],\n\nbackgroundColor: '#10B981', \/\/ Green\n\n},\n\n{\n\nlabel: 'Neutral',\n\ndata: appData.digital.mediaSentiment?.neutral ?? [],\n\nbackgroundColor: '#FBBF24', \/\/ Yellow\n\n},\n\n{\n\nlabel: 'Negativo',\n\ndata: appData.digital.mediaSentiment?.negativo ?? [],\n\nbackgroundColor: '#EF4444', \/\/ Red\n\n}\n\n]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\nposition: 'top',\n\nlabels: { font: { family: 'Inter' } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: (context) => `${context.dataset.label}: ${context.raw}%`\n\n}\n\n}\n\n},\n\nscales: {\n\nx: {\n\nstacked: true,\n\nticks: { font: { family: 'Inter' } }\n\n},\n\ny: {\n\nstacked: true,\n\nbeginAtZero: true,\n\nmax: 100,\n\ntitle: {\n\ndisplay: true,\n\ntext: 'Porcentaje (%)',\n\nfont: { family: 'Inter' }\n\n},\n\nticks: { font: { family: 'Inter' } }\n\n}\n\n}\n\n}\n\n},\n\n{\n\nid: 'digitalReachChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: appData.digital.redesSocialesMetrics?.labels ?? [],\n\ndatasets: [{\n\nlabel: 'Alcance (%)',\n\ndata: appData.digital.redesSocialesMetrics?.reach ?? [],\n\nbackgroundColor: '#6366F1', \/\/ Indigo-500\n\nborderColor: '#4F46E5', \/\/ Indigo-600\n\nborderWidth: 1\n\n}]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: { display: false },\n\ntooltip: {\n\ncallbacks: {\n\nlabel: function(context) {\n\nlet label = context.dataset.label || '';\n\nif (label) {\n\nlabel += ': ';\n\n}\n\nif (context.parsed.y !== null) {\n\nlabel += context.parsed.y + '%';\n\n}\n\nreturn label;\n\n}\n\n}\n\n}\n\n},\n\nscales: {\n\ny: { beginAtZero: true, max: 100 },\n\nx: { grid: { display: false } }\n\n}\n\n}\n\n},\n\n{\n\nid: 'digitalEngagementChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: appData.digital.redesSocialesMetrics?.labels ?? [],\n\ndatasets: [{\n\nlabel: 'Engagement (%)',\n\ndata: appData.digital.redesSocialesMetrics?.engagement ?? [],\n\nbackgroundColor: '#EC4899', \/\/ Pink-500\n\nborderColor: '#DB2777', \/\/ Pink-600\n\nborderWidth: 1\n\n}]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: { display: false },\n\ntooltip: {\n\ncallbacks: {\n\nlabel: function(context) {\n\nlet label = context.dataset.label || '';\n\nif (label) {\n\nlabel += ': ';\n\n}\n\nif (context.parsed.y !== null) {\n\nlabel += context.parsed.y + '%';\n\n}\n\nreturn label;\n\n}\n\n}\n\n}\n\n},\n\nscales: {\n\ny: { beginAtZero: true, max: 100 },\n\nx: { grid: { display: false } }\n\n}\n\n}\n\n},\n\n{\n\nid: 'comparativeSentimentChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: appData.termometro.comparativeSentiment?.labels ?? [],\n\ndatasets: [{\n\nlabel: 'Sentimiento Neto (%)',\n\ndata: appData.termometro.comparativeSentiment?.data ?? [],\n\nbackgroundColor: (appData.termometro.comparativeSentiment?.data ?? []).map(value => {\n\nif (value >= 70) return '#10B981'; \/\/ Green\n\nif (value >= 50) return '#FBBF24'; \/\/ Yellow\n\nreturn '#EF4444'; \/\/ Red\n\n}),\n\nborderColor: (appData.termometro.comparativeSentiment?.data ?? []).map(value => {\n\nif (value >= 70) return '#059669';\n\nif (value >= 50) return '#D97706';\n\nreturn '#DC2626';\n\n}),\n\nborderWidth: 1\n\n}]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\ndisplay: false,\n\nlabels: { font: { family: 'Inter' } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: (context) => `${context.dataset.label}: ${context.raw}%`\n\n}\n\n}\n\n},\n\nscales: {\n\ny: {\n\nbeginAtZero: true,\n\nmax: 100,\n\ntitle: {\n\ndisplay: true,\n\ntext: 'Sentimiento Neto (%)',\n\nfont: { family: 'Inter' }\n\n},\n\nticks: { font: { family: 'Inter' } }\n\n}\n\n}\n\n}\n\n},\n\n{\n\nid: 'valuesRadarChart',\n\ntype: 'radar',\n\ndata: {\n\nlabels: appData.posicionamiento.valuesRadar?.labels ?? [],\n\ndatasets: [\n\n{\n\nlabel: 'Percepci\u00f3n Actual',\n\ndata: appData.posicionamiento.valuesRadar?.perceived ?? [],\n\nbackgroundColor: 'rgba(99, 102, 241, 0.2)', \/\/ Indigo-500 with transparency\n\nborderColor: '#6366F1', \/\/ Indigo-500\n\npointBackgroundColor: '#6366F1',\n\npointBorderColor: '#fff',\n\npointHoverBackgroundColor: '#fff',\n\npointHoverBorderColor: '#6366F1'\n\n},\n\n{\n\nlabel: 'Valores Deseados',\n\ndata: appData.posicionamiento.valuesRadar?.desired ?? [],\n\nbackgroundColor: 'rgba(16, 185, 129, 0.2)', \/\/ Emerald-500 with transparency\n\nborderColor: '#10B981', \/\/ Emerald-500\n\npointBackgroundColor: '#10B981',\n\npointBorderColor: '#fff',\n\npointHoverBackgroundColor: '#fff',\n\npointHoverBorderColor: '#10B981'\n\n}\n\n]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\nposition: 'bottom',\n\nlabels: { font: { family: 'Inter' } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: (context) => `${context.dataset.label}: ${context.raw}\/10`\n\n}\n\n}\n\n},\n\nscales: {\n\nr: {\n\nangleLines: {\n\ndisplay: true\n\n},\n\nsuggestedMin: 0,\n\nsuggestedMax: 10,\n\nticks: {\n\nbeginAtZero: true,\n\nstepSize: 2,\n\nfont: { family: 'Inter' }\n\n},\n\npointLabels: {\n\nfont: { size: 12, family: 'Inter' }\n\n}\n\n}\n\n}\n\n}\n\n},\n\n{\n\nid: 'socialMediaComparisonChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: ['Dos Hermanas', 'Alcal\u00e1 de Guada\u00edra', 'Utrera', 'Mairena del Aljarafe'],\n\ndatasets: [\n\n{\n\nlabel: 'Facebook',\n\ndata: [5000, 4500, 4800, 4200], \/\/ Sample data\n\nbackgroundColor: '#3B82F6', \/\/ Blue-500\n\n},\n\n{\n\nlabel: 'Twitter (X)',\n\ndata: [1200, 1000, 1100, 900], \/\/ Sample data\n\nbackgroundColor: '#6B7280', \/\/ Gray-500\n\n},\n\n{\n\nlabel: 'Instagram',\n\ndata: [3000, 2800, 3200, 2500], \/\/ Sample data\n\nbackgroundColor: '#EC4899', \/\/ Pink-500\n\n}\n\n]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\nposition: 'top',\n\nlabels: { font: { family: 'Inter' } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: (context) => `${context.dataset.label}: ${context.raw} interacciones`\n\n}\n\n}\n\n},\n\nscales: {\n\nx: {\n\nstacked: false,\n\nticks: { font: { family: 'Inter' } }\n\n},\n\ny: {\n\nstacked: false,\n\nbeginAtZero: true,\n\ntitle: {\n\ndisplay: true,\n\ntext: 'Interacciones Promedio',\n\nfont: { family: 'Inter' }\n\n},\n\nticks: { font: { family: 'Inter' } }\n\n}\n\n}\n\n}\n\n},\n\n{\n\nid: 'mediaTreatmentSentimentChart',\n\ntype: 'doughnut',\n\ndata: {\n\nlabels: (appData.mediaTreatment.overallTone.sentimentBreakdown || []).map(item => item.label),\n\ndatasets: [{\n\ndata: (appData.mediaTreatment.overallTone.sentimentBreakdown || []).map(item => item.value),\n\nbackgroundColor: ['#10B981', '#6366F1', '#EF4444'], \/\/ Green, Indigo, Red\n\nborderColor: '#fdfcf9',\n\nborderWidth: 4,\n\n}]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\nposition: 'bottom',\n\nlabels: { font: { family: 'Inter' } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: (context) => `${context.label}: ${context.raw}%`\n\n}\n\n}\n\n},\n\ncutout: '60%'\n\n}\n\n},\n\n{\n\nid: 'specificMediaSentimentChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: [\"Positivo\", \"Neutral\", \"Negativo\"],\n\ndatasets: [{\n\ndata: [0, 0, 0], \/\/ Initial empty data, will be updated\n\nbackgroundColor: ['#10B981', '#6366F1', '#EF4444'], \/\/ Green, Indigo, Red\n\nborderColor: ['#059669', '#4F46E5', '#DC2626'],\n\nborderWidth: 1\n\n}]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: { display: false },\n\ntooltip: {\n\ncallbacks: {\n\nlabel: function(context) {\n\nreturn `${context.label}: ${context.raw}%`;\n\n}\n\n}\n\n}\n\n},\n\nscales: {\n\ny: { beginAtZero: true, max: 100 },\n\nx: { grid: { display: false } }\n\n}\n\n}\n\n},\n\n{\n\nid: 'alcaldeSentimentChart',\n\ntype: 'doughnut',\n\ndata: {\n\nlabels: [\"Positivo\", \"Neutral\", \"Negativo\"],\n\ndatasets: [{\n\ndata: [appData.alcalde.sentiment?.positive ?? 0, appData.alcalde.sentiment?.neutral ?? 0, appData.alcalde.sentiment?.negative ?? 0],\n\nbackgroundColor: [\"#10B981\", \"#6366F1\", \"#EF4444\"],\n\nborderColor: '#fdfcf9',\n\nborderWidth: 4\n\n}]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: {\n\nposition: 'bottom',\n\nlabels: { padding: 20, font: { size: 12 } }\n\n},\n\ntooltip: {\n\ncallbacks: {\n\nlabel: function(context) {\n\nlet label = context.label || '';\n\nif (label) {\n\nlabel += ': ';\n\n}\n\nif (context.parsed !== null) {\n\nlabel += context.parsed + '%';\n\n}\n\nreturn label;\n\n}\n\n}\n\n}\n\n},\n\ncutout: '60%'\n\n}\n\n},\n\n{\n\nid: 'voceriasChart',\n\ntype: 'bar',\n\ndata: {\n\nlabels: (appData.vocerias || []).map(v => v.name),\n\ndatasets: [{\n\nlabel: 'Nivel de Presencia',\n\ndata: (appData.vocerias || []).map(v => v.mediaPresenceValue),\n\nbackgroundColor: (appData.vocerias || []).map(v => {\n\nif (v.mediaPresenceValue === 3) return '#10B981';\n\nif (v.mediaPresenceValue === 2.5) return '#FBBF24';\n\nif (v.mediaPresenceValue === 2) return '#6366F1';\n\nreturn '#EF4444';\n\n}),\n\nborderColor: (appData.vocerias || []).map(v => {\n\nif (v.mediaPresenceValue === 3) return '#059669';\n\nif (v.mediaPresenceValue === 2.5) return '#D97706';\n\nif (v.mediaPresenceValue === 2) return '#4F46E5';\n\nreturn '#DC2626';\n\n}),\n\nborderWidth: 1\n\n}]\n\n},\n\noptions: {\n\nresponsive: true,\n\nmaintainAspectRatio: false,\n\nplugins: {\n\nlegend: { display: false },\n\ntooltip: {\n\ncallbacks: {\n\nlabel: function(context) {\n\nconst voceria = appData.vocerias[context.dataIndex];\n\nreturn `Presencia: ${voceria.mediaPresence}`;\n\n}\n\n}\n\n}\n\n},\n\nscales: {\n\ny: {\n\nbeginAtZero: true,\n\nmax: 3.5,\n\nticks: {\n\ncallback: function(value) {\n\nif (value === 1) return 'Baja';\n\nif (value === 2) return 'Media';\n\nif (value === 2.5) return 'Media-Alta';\n\nif (value === 3) return 'Alta';\n\nreturn '';\n\n}\n\n}\n\n}\n\n}\n\n}\n\n}\n\n];\n\n\/\/ Funci\u00f3n para destruir un gr\u00e1fico si existe\n\nfunction destroyChart(chartInstance) {\n\nif (chartInstance) {\n\nchartInstance.destroy();\n\nchartInstance = null; \/\/ Set to null after destroying\n\n}\n\nreturn null;\n\n}\n\n\/\/ Funci\u00f3n para inicializar\/actualizar *todos* los gr\u00e1ficos de Chart.js\n\nfunction initializeAllCharts() {\n\nchartConfigs.forEach(config => {\n\nconst canvas = document.getElementById(config.id);\n\nif (canvas) {\n\ninitializeChart(config, canvas);\n\n}\n\n});\n\n}\n\nfunction initializeChart(config, canvasElement) {\n\nif (!canvasElement) {\n\n\/\/ This error is now expected if the canvas is in a hidden section.\n\n\/\/ console.warn(`Canvas element not found for chart: ${config.id}`);\n\nreturn null;\n\n}\n\nconst ctx = canvasElement.getContext('2d');\n\nif (!ctx) {\n\nconsole.error(`2D context not available for canvas: ${config.id}`);\n\nreturn null;\n\n}\n\nconst existingChart = Chart.getChart(ctx);\n\nif (existingChart) {\n\nexistingChart.destroy();\n\n}\n\nconst newChart = new Chart(ctx, {\n\ntype: config.type,\n\ndata: JSON.parse(JSON.stringify(config.data)), \/\/ Deep copy data\n\noptions: JSON.parse(JSON.stringify(config.options)) \/\/ Deep copy options\n\n});\n\ncanvasElement.chart = newChart; \/\/ Store chart instance on canvas element\n\nreturn newChart;\n\n}\n\nfunction activateSection(targetId) {\n\n\/\/ Remove active class from all buttons and hide all sections\n\nnavButtons.forEach(btn => btn.classList.remove('active'));\n\ncontentSections.forEach(section => {\n\nsection.classList.remove('active');\n\n\/\/ Changed to display: none\n\nsection.style.display = 'none';\n\nsection.style.opacity = '0';\n\n});\n\n\/\/ Add active class to the clicked button and show the target section\n\nconst targetButton = document.querySelector(`[data-target=\"${targetId}\"]`);\n\nconst targetSection = document.getElementById(targetId);\n\nif (targetButton) {\n\ntargetButton.classList.add('active');\n\n}\n\nif (targetSection) {\n\n\/\/ Changed to display: block\n\ntargetSection.style.display = 'block';\n\ntargetSection.style.opacity = '1';\n\ntargetSection.classList.add('active');\n\n\/\/ Populate content and re-initialize charts for the active section\n\n\/\/ Use a small timeout to ensure canvas dimensions are calculated by the browser\n\nsetTimeout(() => {\n\nswitch (targetId) {\n\ncase 'balance':\n\ndisplayBalanceContent('logros');\n\ninitOverallSentimentGauge();\n\ninitializeChart(chartConfigs.find(c => c.id === 'reputationChart'), document.getElementById('reputationChart'));\n\ninitializeChart(chartConfigs.find(c => c.id === 'sentimentTrendChart'), document.getElementById('sentimentTrendChart'));\n\nbreak;\n\ncase 'actores':\n\npopulateActores();\n\ninitializeChart(chartConfigs.find(c => c.id === 'delegationSentimentChart'), document.getElementById('delegationSentimentChart'));\n\nbreak;\n\ncase 'alcalde':\n\npopulateAlcalde();\n\ninitializeChart(chartConfigs.find(c => c.id === 'alcaldeSentimentChart'), document.getElementById('alcaldeSentimentChart'));\n\nbreak;\n\ncase 'digital':\n\npopulateDigitalChannels();\n\ninitializeChart(chartConfigs.find(c => c.id === 'digitalReachChart'), document.getElementById('digitalReachChart'));\n\ninitializeChart(chartConfigs.find(c => c.id === 'digitalEngagementChart'), document.getElementById('digitalEngagementChart'));\n\ninitializeChart(chartConfigs.find(c => c.id === 'mediaSentimentChart'), document.getElementById('mediaSentimentChart'));\n\nbreak;\n\ncase 'timeline':\n\npopulateTimeline();\n\nbreak;\n\ncase 'matriz-ro':\n\npopulateMatrizRO();\n\nbreak;\n\ncase 'termometro':\n\npopulateTermometro();\n\ninitializeChart(chartConfigs.find(c => c.id === 'comparativeSentimentChart'), document.getElementById('comparativeSentimentChart'));\n\nbreak;\n\ncase 'posicionamiento':\n\npopulatePosicionamiento();\n\ninitializeChart(chartConfigs.find(c => c.id === 'valuesRadarChart'), document.getElementById('valuesRadarChart'));\n\nbreak;\n\ncase 'benchmarking':\n\npopulateBenchmarking();\n\ninitializeChart(chartConfigs.find(c => c.id === 'socialMediaComparisonChart'), document.getElementById('socialMediaComparisonChart'));\n\nbreak;\n\ncase 'kpis':\n\npopulateKpiBoxes();\n\nbreak;\n\ncase 'estrategia':\n\npopulateEstrategia();\n\nbreak;\n\ncase 'protocolo-crisis':\n\npopulateProtocoloCrisis();\n\nbreak;\n\ncase 'vocerias':\n\npopulateVocerias();\n\ninitializeChart(chartConfigs.find(c => c.id === 'voceriasChart'), document.getElementById('voceriasChart'));\n\nbreak;\n\ncase 'deportes':\n\npopulateDeportes();\n\nbreak;\n\ncase 'narrative-map':\n\npopulateNarrativeMap();\n\nbreak;\n\ncase 'say-do-gap':\n\npopulateSayDoGap();\n\nbreak;\n\ncase 'early-warnings':\n\npopulateEarlyWarnings();\n\nbreak;\n\ncase 'scenarios':\n\npopulateScenariosSection();\n\nbreak;\n\ncase 'media-treatment':\n\npopulateMediaTreatment();\n\ninitializeChart(chartConfigs.find(c => c.id === 'mediaTreatmentSentimentChart'), document.getElementById('mediaTreatmentSentimentChart'));\n\npopulateMediaSelector(); \/\/ Populate selector and attach listener\n\nif (appData.mediaTreatment.mediaOutletsSentiment && appData.mediaTreatment.mediaOutletsSentiment.length > 0) {\n\nupdateSpecificMediaSentimentChart(appData.mediaTreatment.mediaOutletsSentiment[0].name);\n\n}\n\nbreak;\n\ncase 'consolidated-report':\n\npopulateConsolidatedReport();\n\nbreak;\n\ncase 'about':\n\n\/\/ No specific population needed for this static section\n\nbreak;\n\n}\n\n}, 50); \/\/ A small delay of 50ms\n\n}\n\nwindow.scrollTo({ top: 0, behavior: 'smooth' });\n\n}\n\n\/\/ --- Funciones para poblar el contenido de cada secci\u00f3n ---\n\nfunction displayBalanceContent(type) {\n\nlet contentHtml = '';\n\nconst data = type === 'logros' ? appData.balance.logros : appData.balance.riesgos;\n\nif (type === 'logros') {\n\nif (btnLogros) {\n\nbtnLogros.classList.add('bg-indigo-600', 'text-white');\n\nbtnLogros.classList.remove('bg-white', 'text-indigo-600');\n\n}\n\nif (btnRiesgos) {\n\nbtnRiesgos.classList.remove('bg-red-500', 'text-white');\n\nbtnRiesgos.classList.add('bg-white', 'text-red-500');\n\n}\n\n} else {\n\nif (btnRiesgos) {\n\nbtnRiesgos.classList.add('bg-red-500', 'text-white');\n\nbtnRiesgos.classList.remove('bg-white', 'text-red-500');\n\n}\n\nif (btnLogros) {\n\nbtnLogros.classList.remove('bg-indigo-600', 'text-white');\n\nbtnLogros.classList.add('bg-white', 'text-indigo-600');\n\n}\n\n}\n\nif (data && data.length > 0) {\n\ndata.forEach(item => {\n\ncontentHtml += `\n\n<div class=\"bg-indigo-50 p-4 rounded-lg shadow-sm flex items-start\">\n\n<span class=\"text-2xl mr-3\">${item.icon}<\/span>\n\n<div>\n\n<h4 class=\"font-semibold text-indigo-700\">${item.title}<\/h4>\n\n<p class=\"text-sm text-slate-600\">${item.description}<\/p>\n\n<\/div>\n\n<\/div>\n\n`;\n\n});\n\n} else {\n\ncontentHtml = `<p class=\"text-slate-600 text-center\">No hay datos disponibles para mostrar.<\/p>`;\n\n}\n\nif (infoDisplay) infoDisplay.innerHTML = contentHtml;\n\n}\n\nfunction initOverallSentimentGauge() {\n\nif (overallSentimentValue) {\n\noverallSentimentValue.textContent = `${appData.balance.overallSentiment}%`;\n\nlet color;\n\nif (appData.balance.overallSentiment >= 66) {\n\ncolor = '#10B981'; \/\/ Green\n\n} else if (appData.balance.overallSentiment >= 33) {\n\ncolor = '#FBBF24'; \/\/ Yellow\n\n} else {\n\ncolor = '#EF4444'; \/\/ Red\n\n}\n\noverallSentimentValue.style.color = color;\n\n}\n\n}\n\nfunction populateActores() {\n\nconst medios = document.getElementById('actores-medios');\n\nif (medios) medios.innerHTML = (appData.actores.medios || []).map(m => `<li><strong class=\"font-medium\">${m.name}:<\/strong> ${m.type}<\/li>`).join('');\n\nconst ciudadanos = document.getElementById('actores-ciudadanos');\n\nif (ciudadanos) ciudadanos.innerHTML = (appData.actores.ciudadanos || []).map(c => `<li><strong class=\"font-medium\">${c.name}:<\/strong> ${c.role}<\/li>`).join('');\n\nconst influyentesContainer = document.getElementById('actores-influyentes-cards');\n\nif (influyentesContainer) influyentesContainer.innerHTML = (appData.actores.influyentes || []).map(i => `\n\n<div class=\"p-4 bg-indigo-50 rounded-lg shadow-sm border border-indigo-200\">\n\n<h5 class=\"font-semibold text-indigo-700 mb-1\">${i.name}<\/h5>\n\n<p class=\"text-sm text-slate-700 font-medium\">${i.role}<\/p>\n\n<p class=\"text-xs text-slate-600 mt-2\">${i.description}<\/p>\n\n<\/div>\n\n`).join('');\n\n}\n\nfunction populateAlcalde() {\n\nconst alcaldeResumen = document.getElementById('alcalde-resumen');\n\nif (alcaldeResumen) alcaldeResumen.textContent = appData.alcalde.resumen || 'No hay resumen disponible.';\n\nconst mensajesClaveList = document.getElementById('alcalde-mensajes');\n\nif (mensajesClaveList) {\n\nmensajesClaveList.innerHTML = (appData.alcalde.mensajesClave || []).map(m => `<li>${m}<\/li>`).join('');\n\n} else {\n\nif (mensajesClaveList) mensajesClaveList.innerHTML = '<li>No hay mensajes clave disponibles.<\/li>';\n\n}\n\nconst desafiosComunicativosList = document.getElementById('alcalde-desafios');\n\nif (desafiosComunicativosList) {\n\ndesafiosComunicativosList.innerHTML = (appData.alcalde.desafiosComunicativos || []).map(d => `<li>${d}<\/li>`).join('');\n\n} else {\n\nif (desafiosComunicativosList) desafiosComunicativosList.innerHTML = '<li>No hay desaf\u00edos comunicativos disponibles.<\/li>';\n\n}\n\nconst positive = appData.alcalde.sentiment?.positive ?? 0;\n\nconst neutral = appData.alcalde.sentiment?.neutral ?? 0;\n\nconst negative = appData.alcalde.sentiment?.negative ?? 0;\n\nconst alcaldeSentimentSummary = document.getElementById('alcalde-sentiment-summary');\n\nif (alcaldeSentimentSummary) alcaldeSentimentSummary.innerHTML = `Desglose del sentimiento de la cobertura medi\u00e1tica asociada al alcalde: <span class=\"font-bold text-emerald-700\">${positive}% Positivo<\/span>, <span class=\"font-bold text-indigo-700\">${neutral}% Neutral<\/span>, <span class=\"font-bold text-red-700\">${negative}% Negativo<\/span>.`;\n\n}\n\nfunction populateDigitalChannels() {\n\nconst tbody = document.getElementById('digital-channels-table');\n\nif (tbody) tbody.innerHTML = (appData.digital.canalesOficiales || []).map(c => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${c.type}<\/td>\n\n<td class=\"p-3 text-slate-600\">${c.name}<\/td>\n\n<td class=\"p-3 text-slate-600\">${c.purpose}<\/td>\n\n<\/tr>\n\n`).join('');\n\n}\n\nfunction initDigitalCharts() {\n\ninitializeChart(chartConfigs.find(c => c.id === 'digitalReachChart'), document.getElementById('digitalReachChart'));\n\ninitializeChart(chartConfigs.find(c => c.id === 'digitalEngagementChart'), document.getElementById('digitalEngagementChart'));\n\n}\n\nfunction populateTimeline() {\n\nconst container = document.getElementById('timeline-events');\n\nif (!container) return;\n\nlet timelineHtml = '';\n\n(appData.timeline || []).forEach((monthData, index) => {\n\nconst positionClass = index % 2 === 0 ? 'left' : 'right';\n\ntimelineHtml += `\n\n<div class=\"timeline-item ${positionClass}\">\n\n<div class=\"timeline-content\">\n\n<h4 class=\"font-bold text-indigo-800 mb-2\">${monthData.month}<\/h4>\n\n<ul class=\"list-disc list-inside text-sm text-slate-700 space-y-1\">\n\n${(monthData.events || []).map(event => `<li>${event}<\/li>`).join('')}\n\n<\/ul>\n\n<\/div>\n\n<\/div>\n\n`;\n\n});\n\ncontainer.innerHTML = timelineHtml;\n\n}\n\nfunction populateMatrizRO() {\n\nconst riesgosList = document.getElementById('matriz-riesgos');\n\nconst oportunidadesList = document.getElementById('matriz-oportunidades');\n\nif (riesgosList) riesgosList.innerHTML = (appData.matrizRO.riesgos || []).map(r => `\n\n<li class=\"p-3 bg-red-50 rounded-lg border border-red-200\">\n\n<h5 class=\"font-semibold text-red-800\">${r.name}<\/h5>\n\n<p class=\"text-sm text-red-700\">Impacto: <span class=\"font-medium\">${r.impact}<\/span>, Probabilidad: <span class=\"font-medium\">${r.likelihood}<\/span><\/p>\n\n<p class=\"text-xs text-red-600 mt-1\">Mitigaci\u00f3n: ${r.mitigation}<\/p>\n\n<p class=\"text-xs text-red-600 mt-1 font-semibold\">Acci\u00f3n de Control: ${r.controlAction}<\/p>\n\n<\/li>\n\n`).join('');\n\nif (oportunidadesList) oportunidadesList.innerHTML = (appData.matrizRO.oportunidades || []).map(o => `\n\n<li class=\"p-3 bg-emerald-50 rounded-lg border border-emerald-200\">\n\n<h5 class=\"font-semibold text-emerald-800\">${o.name}<\/h5>\n\n<p class=\"text-sm text-emerald-700\">Beneficio: <span class=\"font-medium\">${o.benefit}<\/span><\/p>\n\n<p class=\"text-xs text-emerald-600 mt-1\">Estrategia: ${o.strategy}<\/p>\n\n<\/li>\n\n`).join('');\n\n}\n\nfunction populateTermometro() {\n\nconst container = document.getElementById('termometro-topics');\n\nif (container) container.innerHTML = (appData.termometro || []).map(item => `\n\n<div>\n\n<h4 class=\"font-semibold text-indigo-700 mb-1\">${item.topic}<\/h4>\n\n<div class=\"progress-bar-container\">\n\n<div class=\"progress-bar\" style=\"width: ${item.sentiment}%; background-color: ${item.color};\">\n\n${item.sentiment}%\n\n<\/div>\n\n<\/div>\n\n<\/div>\n\n`).join('');\n\n}\n\nfunction populatePosicionamiento() {\n\nconst actual = document.getElementById('posicionamiento-actual');\n\nif (actual) actual.textContent = appData.posicionamiento.actual || '';\n\nconst deseado = document.getElementById('posicionamiento-deseado');\n\nif (deseado) deseado.textContent = appData.posicionamiento.deseado || '';\n\nconst brecha = document.getElementById('posicionamiento-brecha');\n\nif (brecha) brecha.textContent = appData.posicionamiento.brecha || '';\n\n}\n\nfunction populateBenchmarking() {\n\nconst container = document.getElementById('benchmarking-cities');\n\nif (container) {\n\ncontainer.innerHTML = (appData.benchmarking || []).map(city => `\n\n<div class=\"p-4 bg-indigo-50 rounded-lg shadow-sm border border-indigo-200\">\n\n<h4 class=\"font-semibold text-indigo-700 mb-2\">${city.city}<\/h4>\n\n<p class=\"text-sm text-slate-700\">${city.comparison}<\/p>\n\n<\/div>\n\n`).join('');\n\n}\n\n}\n\nfunction populateKpiBoxes() {\n\nconst container = document.getElementById('kpi-boxes-container');\n\nif (!container) return;\n\ncontainer.innerHTML = ''; \/\/ Clear existing content\n\n(appData.kpis.allKpis || []).forEach(kpi => {\n\nlet valueDisplay = (kpi.value ?? '').toLocaleString();\n\nif (kpi.unit) {\n\nvalueDisplay += kpi.unit;\n\n} else if (kpi.isPercentage) {\n\nvalueDisplay += '%';\n\n}\n\nconst changeArrow = kpi.change && kpi.change.includes('+') ? '\u25b2' : (kpi.change && kpi.change.includes('-') ? '\u25bc' : '');\n\nconst changeColor = kpi.change && kpi.change.includes('+') ? 'text-green-500' : (kpi.change && kpi.change.includes('-') ? 'text-red-500' : 'text-slate-600');\n\nconst changeValue = kpi.change ? kpi.change.replace(\/[^0-9.]\/g, '') + (kpi.isPercentage ? '%' : '') : '';\n\nconst kpiBoxHtml = `\n\n<div class=\"kpi-box\">\n\n<h4 class=\"kpi-box-title\">${kpi.title}<\/h4>\n\n<p class=\"kpi-box-value\">\n\n${valueDisplay}\n\n${kpi.change ? `<span class=\"kpi-box-change ${changeColor}\">${changeArrow} ${changeValue}<\/span>` : ''}\n\n<\/p>\n\n<p class=\"kpi-box-description\">${kpi.description}<\/p>\n\n<\/div>\n\n`;\n\ncontainer.innerHTML += kpiBoxHtml;\n\n});\n\n}\n\nfunction populateEstrategia() {\n\nconst actual = document.getElementById('estrategia-actual');\n\nif (actual) actual.textContent = appData.estrategia.narrativaActual || '';\n\nconst recomendada = document.getElementById('estrategia-recomendada');\n\nif (recomendada) recomendada.textContent = appData.estrategia.narrativaRecomendada || '';\n\nconst accionesList = document.getElementById('estrategia-acciones');\n\nif (accionesList) accionesList.innerHTML = (appData.estrategia.accionesClave || []).map(a => `<li>${a}<\/li>`).join('');\n\n}\n\nfunction populateProtocoloCrisis() {\n\nconst fasesList = document.getElementById('protocolo-fases');\n\nconst principiosList = document.getElementById('protocolo-principios');\n\nif (fasesList) fasesList.innerHTML = (appData.protocoloCrisis.fases || []).map(f => `\n\n<li><strong class=\"font-medium\">${f.name}:<\/strong> ${f.description}<\/li>\n\n`).join('');\n\nif (principiosList) principiosList.innerHTML = (appData.protocoloCrisis.principios || []).map(p => `<li>${p}<\/li>`).join('');\n\n}\n\nfunction populateVocerias() {\n\nconst container = document.getElementById('vocerias-list');\n\nif (container) container.innerHTML = (appData.vocerias || []).map(v => `\n\n<div class=\"p-4 bg-indigo-50 rounded-lg shadow-sm border border-indigo-200\">\n\n<h5 class=\"font-semibold text-indigo-700 mb-1\">${v.name}<\/h5>\n\n<p class=\"text-sm text-slate-700\">Rol: ${v.role}<\/p>\n\n<p class=\"text-sm text-slate-700\">Presencia Medi\u00e1tica: ${v.mediaPresence}<\/p>\n\n<\/div>\n\n`).join('');\n\n}\n\nfunction populateDeportes() {\n\nconst intro = document.getElementById('deportes-intro');\n\nif (intro) intro.textContent = appData.deportes.intro || '';\n\nconst programasList = document.getElementById('deportes-programas');\n\nif (programasList) programasList.innerHTML = (appData.deportes.programas || []).map(p => `<li>${p}<\/li>`).join('');\n\nconst destacadosList = document.getElementById('deportes-destacados');\n\nif (destacadosList) destacadosList.innerHTML = (appData.deportes.destacados || []).map(d => `<li>${d}<\/li>`).join('');\n\n}\n\nfunction populateNarrativeMap() {\n\nconst container = document.getElementById('narrative-map-content');\n\nif (!container) return;\n\nlet html = `\n\n<h4 class=\"text-xl font-semibold text-indigo-700 mb-4\">${appData.narrativeMap.title || ''}<\/h4>\n\n<p class=\"text-slate-700 mb-6\">${appData.narrativeMap.description || ''}<\/p>\n\n<div class=\"space-y-4\">\n\n${(appData.narrativeMap.elements || []).map(e => `\n\n<div class=\"p-4 bg-indigo-50 rounded-lg shadow-sm border border-indigo-200\">\n\n<h5 class=\"font-semibold text-indigo-800\">Tema: ${e.theme}<\/h5>\n\n<p class=\"text-sm text-slate-700\">Actores Clave: ${e.actors}<\/p>\n\n<p class=\"text-sm text-slate-700\">Sentimiento Dominante: <span class=\"font-medium text-${e.sentiment === 'Positivo' ? 'emerald' : (e.sentiment === 'Negativo' ? 'red' : 'yellow')}-700\">${e.sentiment}<\/span><\/p>\n\n<p class=\"text-xs text-slate-600 mt-1\">Conexiones: ${(e.connections || []).join(', ')}<\/p>\n\n<\/div>\n\n`).join('')}\n\n<\/div>\n\n<p class=\"text-sm text-slate-500 mt-6\">\n\nPara un mapa narrativo interactivo real, se requerir\u00eda una herramienta de visualizaci\u00f3n de grafos (no permitida en este contexto por sus dependencias o complejidad), pero esta descripci\u00f3n conceptual ayuda a entender la din\u00e1mica.\n\n<\/p>\n\n`;\n\ncontainer.innerHTML = html;\n\n}\n\nfunction populateSayDoGap() {\n\nconst tbody = document.getElementById('say-do-table');\n\nif (!tbody) return;\n\ntbody.innerHTML = (appData.sayDoGap.analysis || []).map(a => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${a.aspect}<\/td>\n\n<td class=\"p-3 text-slate-600\">${a.discourse}<\/td>\n\n<td class=\"p-3 text-slate-600\">${a.perception}<\/td>\n\n<td class=\"p-3 text-slate-600 font-semibold text-${a.gap === 'Alta' ? 'red' : (a.gap === 'Media' ? 'yellow' : 'blue')}-700\">${a.gap}<\/td>\n\n<td class=\"p-3 text-slate-600\">${a.impact}<\/td>\n\n<\/tr>\n\n`).join('');\n\n}\n\nfunction populateEarlyWarnings() {\n\nconst container = document.getElementById('early-warnings-content');\n\nif (!container) return;\n\ncontainer.innerHTML = (appData.earlyWarnings.signals || []).map(s => `\n\n<div class=\"p-4 bg-yellow-50 rounded-lg shadow-sm border border-yellow-200\">\n\n<h4 class=\"font-semibold text-yellow-800\">Tipo: ${s.type} - ${s.name}<\/h4>\n\n<p class=\"text-sm text-yellow-700 mt-1\">${s.description}<\/p>\n\n<p class=\"text-xs text-yellow-600 mt-2 font-semibold\">Mitigaci\u00f3n Sugerida: ${s.mitigation}<\/p>\n\n<\/div>\n\n`).join('');\n\n}\n\nfunction populateScenariosSection() {\n\nconst container = document.getElementById('scenarios-content');\n\nif (!container) return;\n\ncontainer.innerHTML = (appData.scenarios || []).map(s => `\n\n<div class=\"p-4 bg-${s.type === 'Optimista' ? 'emerald' : (s.type === 'Pesimista' ? 'red' : 'indigo')}-50 rounded-lg shadow-sm border border-${s.type === 'Optimista' ? 'emerald' : (s.type === 'Pesimista' ? 'red' : 'indigo')}-200\">\n\n<h4 class=\"font-semibold text-${s.type === 'Optimista' ? 'emerald' : (s.type === 'Pesimista' ? 'red' : 'indigo')}-800\">Escenario ${s.type}: ${s.name}<\/h4>\n\n<p class=\"text-sm text-slate-700 mt-1\">${s.description}<\/p>\n\n<\/div>\n\n`).join('');\n\n}\n\nfunction populateMediaTreatment() {\n\nconst overallToneDescription = document.getElementById('overall-tone-description');\n\nif (overallToneDescription) overallToneDescription.textContent = appData.mediaTreatment.overallTone.description || '';\n\nconst dominantThemesList = document.getElementById('dominant-themes-list');\n\nif (dominantThemesList) dominantThemesList.innerHTML = (appData.mediaTreatment.dominantThemes || []).map(t => `\n\n<li class=\"p-3 bg-indigo-50 rounded-lg border border-indigo-200\">\n\n<h5 class=\"font-semibold text-indigo-700\">${t.theme}<\/h5>\n\n<p class=\"text-sm text-slate-700\">Cobertura: ${t.coverage}, Tono: ${t.tone}<\/p>\n\n<p class=\"text-xs text-slate-600 mt-1\">Impacto: ${t.impact}<\/p>\n\n<\/li>\n\n`).join('');\n\nconst mediaFramingList = document.getElementById('media-framing-list');\n\nif (mediaFramingList) mediaFramingList.innerHTML = (appData.mediaTreatment.mediaFraming || []).map(f => `\n\n<li class=\"p-3 bg-indigo-50 rounded-lg border border-indigo-200\">\n\n<h5 class=\"font-semibold text-indigo-700\">${f.mediaType}<\/h5>\n\n<p class=\"text-sm text-slate-700\">${f.framing}<\/p>\n\n<\/li>\n\n`).join('');\n\n}\n\nfunction initMediaTreatmentChart() {\n\ninitializeChart(chartConfigs.find(c => c.id === 'mediaTreatmentSentimentChart'), document.getElementById('mediaTreatmentSentimentChart'));\n\n}\n\nfunction populateMediaSelector() {\n\nconst selector = document.getElementById('media-selector');\n\nif (!selector) return;\n\nselector.innerHTML = ''; \/\/ Clear existing options\n\n(appData.mediaTreatment.mediaOutletsSentiment || []).forEach(media => {\n\nconst option = document.createElement('option');\n\noption.value = media.name;\n\noption.textContent = media.name;\n\nselector.appendChild(option);\n\n});\n\n\/\/ Add event listener only once\n\nif (!selector.dataset.listenerAdded) {\n\nselector.addEventListener('change', (event) => {\n\nupdateSpecificMediaSentimentChart(event.target.value);\n\n});\n\nselector.dataset.listenerAdded = 'true';\n\n}\n\n}\n\nfunction updateSpecificMediaSentimentChart(mediaName) {\n\nconst media = (appData.mediaTreatment.mediaOutletsSentiment || []).find(m => m.name === mediaName);\n\nif (!media) {\n\nreturn;\n\n}\n\nconst titleElem = document.getElementById('specific-media-title');\n\nif (titleElem) titleElem.textContent = media.name;\n\nconst descElem = document.getElementById('specific-media-description');\n\nif (descElem) descElem.textContent = media.description;\n\nconst chartConfig = chartConfigs.find(c => c.id === 'specificMediaSentimentChart');\n\nif (chartConfig) {\n\nchartConfig.data.datasets[0].data = [media.sentiment?.positive ?? 0, media.sentiment?.neutral ?? 0, media.sentiment?.negative ?? 0];\n\ninitializeChart(chartConfig, document.getElementById('specificMediaSentimentChart'));\n\n}\n\n}\n\n\/\/ --- Funci\u00f3n para poblar el informe consolidado y generar el PDF ---\n\nfunction populateConsolidatedReport() {\n\nconst container = document.getElementById('consolidated-report-content');\n\nif (!container) {\n\nconsole.error(\"Error: consolidated-report-content container not found.\");\n\nreturn;\n\n}\n\n\/\/ HTML content for the consolidated report\n\n\/\/ Nota: Los gr\u00e1ficos en esta secci\u00f3n son solo menciones conceptuales, no canvas interactivos.\n\nlet htmlContent = `\n\n<p class=\"text-slate-700 leading-relaxed mb-6\">\n\nEl presente informe consolidado ofrece una s\u00edntesis ejecutiva de los principales hallazgos y datos de inteligencia de medios para el Ayuntamiento de Dos Hermanas durante el periodo Mayo 2023 - Junio 2025. Refleja una gesti\u00f3n municipal proactiva con logros significativos en diversas \u00e1reas, aunque tambi\u00e9n destaca desaf\u00edos persistentes en la percepci\u00f3n ciudadana y la comunicaci\u00f3n.\n\n<\/p>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\u2696\ufe0f<\/span> Balanza Reputacional General\n\n<\/h4>\n\n<p class=\"text-slate-700 font-semibold mb-2\">El sentimiento general del per\u00edodo es **${appData.balance.overallSentiment}% Positivo**, con una tendencia ${appData.balance.overallSentiment >= 60 ? 'favorable' : (appData.balance.overallSentiment >= 40 ? 'dual' : 'cr\u00edtica')}.<\/p>\n\n<div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mt-6\">\n\n<div class=\"bg-green-50 p-4 rounded-lg shadow-sm border border-green-200\">\n\n<h5 class=\"text-lg font-semibold text-green-800 mb-2\">Fortalezas Destacadas:<\/h5>\n\n<ul class=\"list-disc list-inside ml-4 text-base text-slate-700 space-y-1\">\n\n${(appData.balance.logros || []).map(l => `<li><strong class=\"font-medium\">${l.title}:<\/strong> ${l.description}<\/li>`).join('')}\n\n<\/ul>\n\n<\/div>\n\n<div class=\"bg-red-50 p-4 rounded-lg shadow-sm border border-red-200\">\n\n<h5 class=\"text-lg font-semibold text-red-800 mb-2\">Debilidades Clave:<\/h5>\n\n<ul class=\"list-disc list-inside ml-4 text-base text-slate-700 space-y-1\">\n\n${(appData.balance.riesgos || []).map(r => `<li><strong class=\"font-medium\">${r.title}:<\/strong> ${r.description}<\/li>`).join('')}\n\n<\/ul>\n\n<\/div>\n\n<\/div>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200 mt-6\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Sentimiento del Alcalde<\/th>\n\n<th class=\"p-3\">Porcentaje (%)<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium text-emerald-700\">Positivo<\/td>\n\n<td class=\"p-3 text-slate-600\">${appData.alcalde.sentiment?.positive ?? 0}<\/td>\n\n<\/tr>\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium text-indigo-700\">Neutral<\/td>\n\n<td class=\"p-3 text-slate-600\">${appData.alcalde.sentiment?.neutral ?? 0}<\/td>\n\n<\/tr>\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium text-red-700\">Negativo<\/td>\n\n<td class=\"p-3 text-slate-600\">${appData.alcalde.sentiment?.negative ?? 0}<\/td>\n\n<\/tr>\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udcc8<\/span> Evoluci\u00f3n del Sentimiento (\u00daltimo Trimestre 2024 \u2013 Junio 2025)\n\n<\/h4>\n\n<p class=\"text-slate-700 leading-relaxed mb-4\">\n\nEl an\u00e1lisis de la evoluci\u00f3n del sentimiento muestra las tendencias de la percepci\u00f3n p\u00fablica hacia el Ayuntamiento de Dos Hermanas a lo largo de los \u00faltimos trimestres. Se observa una tendencia general hacia una mayor positividad, aunque el sentimiento negativo se mantiene estable.\n\n<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Per\u00edodo<\/th>\n\n<th class=\"p-3\">Positivo (%)<\/th>\n\n<th class=\"p-3\">Neutral (%)<\/th>\n\n<th class=\"p-3\">Negativo (%)<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.balance.sentimentTrend?.labels || []).map((label, index) => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${label}<\/td>\n\n<td class=\"p-3 text-slate-600\">${appData.balance.sentimentTrend?.positive[index] ?? 'N\/A'}<\/td>\n\n<td class=\"p-3 text-slate-600\">${appData.balance.sentimentTrend?.neutral[index] ?? 'N\/A'}<\/td>\n\n<td class=\"p-3 text-slate-600\">${appData.balance.sentimentTrend?.negative[index] ?? 'N\/A'}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udc64<\/span> Foco en el Alcalde\n\n<\/h4>\n\n<p class=\"text-slate-700 leading-relaxed mb-4\">${appData.alcalde.resumen || 'No hay resumen disponible.'}<\/p>\n\n<h5 class=\"font-semibold text-indigo-600 mt-4 mb-2\">Mensajes Clave:<\/h5>\n\n<ul class=\"list-disc list-inside ml-4 text-base text-slate-700\">\n\n${(appData.alcalde.mensajesClave || []).map(m => `<li>${m}<\/li>`).join('')}\n\n<\/ul>\n\n<h5 class=\"font-semibold text-red-600 mt-4 mb-2\">Desaf\u00edos Comunicativos:<\/h5>\n\n<ul class=\"list-disc list-inside ml-4 text-base text-slate-700\">\n\n${(appData.alcalde.desafiosComunicativos || []).map(d => `<li>${d}<\/li>`).join('')}\n\n<\/ul>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udc65<\/span> Mapa de Actores Clave y Redes de Resonancia\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">Identificaci\u00f3n de los principales medios, grupos ciudadanos y voces influyentes que configuran la conversaci\u00f3n p\u00fablica en Dos Hermanas.<\/p>\n\n<h5 class=\"font-semibold text-indigo-600 mb-2\">Medios Principales:<\/h5>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200 mb-4\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Nombre<\/th>\n\n<th class=\"p-3\">Tipo<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.actores.medios || []).map(m => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${m.name}<\/td>\n\n<td class=\"p-3 text-slate-600\">${m.type}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<h5 class=\"font-semibold text-indigo-600 mb-2\">Grupos Ciudadanos:<\/h5>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200 mb-4\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Nombre<\/th>\n\n<th class=\"p-3\">Rol<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.actores.ciudadanos || []).map(c => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${c.name}<\/td>\n\n<td class=\"p-3 text-slate-600\">${c.role}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<h5 class=\"font-semibold text-indigo-600 mb-2\">Voces Influyentes (Periodistas y Activistas):<\/h5>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Nombre<\/th>\n\n<th class=\"p-3\">Rol<\/th>\n\n<th class=\"p-3\">Descripci\u00f3n<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.actores.influyentes || []).map(i => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${i.name}<\/td>\n\n<td class=\"p-3 text-slate-600\">${i.role}<\/td>\n\n<td class=\"p-3 text-slate-600\">${i.description}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udcbb<\/span> An\u00e1lisis Digital\n\n<\/h4>\n\n<p class=\"text-slate-700\">El Ayuntamiento mantiene una presencia digital a trav\u00e9s de su sitio web y canal de YouTube. El alcance y engagement en redes sociales no son directamente cuantificables sin herramientas de monitoreo, pero se observa actividad en YouTube. La falta de integraci\u00f3n de redes sociales en la web principal es una debilidad.<\/p>\n\n<p class=\"text-slate-700\">Canales principales: ${(appData.digital.canalesOficiales || []).map(c => c.name).slice(0,3).join(', ')}.<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200 mt-4\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Canal<\/th>\n\n<th class=\"p-3\">Alcance Estimado (%)<\/th>\n\n<th class=\"p-3\">Engagement Estimado (%)<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.digital.redesSocialesMetrics.labels || []).map((label, index) => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${label}<\/td>\n\n<td class=\"p-3 text-slate-600\">${appData.digital.redesSocialesMetrics.reach[index] ?? 'N\/A'}<\/td>\n\n<td class=\"p-3 text-slate-600\">${appData.digital.redesSocialesMetrics.engagement[index] ?? 'N\/A'}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\uddd3\ufe0f<\/span> L\u00ednea de Tiempo: Eventos Clave (Mayo 2023 - Junio 2025)\n\n<\/h4>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200 mt-4\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Mes\/A\u00f1o<\/th>\n\n<th class=\"p-3\">Eventos Clave<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.timeline || []).map(monthData => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${monthData.month}<\/td>\n\n<td class=\"p-3 text-slate-600\">${(monthData.events || []).join(', ')}.<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\u26a0\ufe0f<\/span> Matriz de Riesgos y Oportunidades Reputacionales\n\n<\/h4>\n\n<h5 class=\"text-lg font-semibold text-red-600 mb-2\">Riesgos Clave:<\/h5>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200 mb-4\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Riesgo<\/th>\n\n<th class=\"p-3\">Impacto<\/th>\n\n<th class=\"p-3\">Probabilidad<\/th>\n\n<th class=\"p-3\">Acci\u00f3n de Control<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.matrizRO.riesgos || []).map(r => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${r.name}<\/td>\n\n<td class=\"p-3 text-slate-600\">${r.impact}<\/td>\n\n<td class=\"p-3 text-slate-600\">${r.likelihood}<\/td>\n\n<td class=\"p-3 text-slate-600\">${r.controlAction}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<h5 class=\"text-lg font-semibold text-emerald-600 mb-2\">Oportunidades Estrat\u00e9gicas:<\/h5>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Oportunidad<\/th>\n\n<th class=\"p-3\">Beneficio<\/th>\n\n<th class=\"p-3\">Estrategia<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.matrizRO.oportunidades || []).map(o => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${o.name}<\/td>\n\n<td class=\"p-3 text-slate-600\">${o.benefit}<\/td>\n\n<td class=\"p-3 text-slate-600\">${o.strategy}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83c\udf21\ufe0f<\/span> Term\u00f3metro Ciudadano: Percepci\u00f3n por Temas\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">Evaluaci\u00f3n cualitativa del sentimiento ciudadano hacia diferentes \u00e1reas de la gesti\u00f3n municipal (0 = muy negativo, 100 = muy positivo).<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Tema<\/th>\n\n<th class=\"p-3\">Sentimiento (%)<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.termometro || []).map(item => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${item.topic}<\/td>\n\n<td class=\"p-3 text-slate-600\">${item.sentiment}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83c\udfaf<\/span> Diagn\u00f3stico de Posicionamiento Reputacional\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-2\"><strong class=\"font-semibold\">Posicionamiento Actual:<\/strong> ${appData.posicionamiento.actual || ''}<\/p>\n\n<p class=\"text-slate-700 mb-2\"><strong class=\"font-semibold\">Posicionamiento Deseado:<\/strong> ${appData.posicionamiento.deseado || ''}<\/p>\n\n<p class=\"text-slate-700\"><strong class=\"font-semibold\">Brecha Reputacional:<\/strong> ${appData.posicionamiento.brecha || ''}<\/p>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83c\udfc6<\/span> Benchmarking: Comparativa con Otros Ayuntamientos\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">An\u00e1lisis comparativo conceptual con otras ciudades para identificar buenas pr\u00e1cticas y \u00e1reas de mejora.<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Ciudad<\/th>\n\n<th class=\"p-3\">Comparaci\u00f3n<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.benchmarking || []).map(city => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${city.city}<\/td>\n\n<td class=\"p-3 text-slate-600\">${city.comparison}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udcca<\/span> Panel de KPIs Estrat\u00e9gicos Clave\n\n<\/h4>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">KPI<\/th>\n\n<th class=\"p-3\">Valor<\/th>\n\n<th class=\"p-3\">Cambio<\/th>\n\n<th class=\"p-3\">Descripci\u00f3n<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.kpis.allKpis || []).map(kpi => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${kpi.title}<\/td>\n\n<td class=\"p-3 text-slate-600\">${kpi.value?.toLocaleString() ?? 'N\/A'}${kpi.unit || (kpi.isPercentage ? '%' : '')}<\/td>\n\n<td class=\"p-3 text-slate-600\">${kpi.change || 'N\/A'}<\/td>\n\n<td class=\"p-3 text-slate-600\">${kpi.description}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udcdd<\/span> Estrategia y Narrativa: Hacia un Relato Institucional \u00d3ptimo\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-2\"><strong class=\"font-semibold\">Narrativa Actual:<\/strong> ${appData.estrategia.narrativaActual || ''}<\/p>\n\n<p class=\"text-slate-700 mb-2\"><strong class=\"font-semibold\">Narrativa Recomendada:<\/strong> ${appData.estrategia.narrativaRecomendada || ''}<\/p>\n\n<h5 class=\"font-semibold text-indigo-600 mt-4 mb-2\">Acciones Clave para el Relato:<\/h5>\n\n<ul class=\"list-disc list-inside ml-4 text-base text-slate-700\">\n\n${(appData.estrategia.accionesClave || []).map(a => `<li>${a}<\/li>`).join('')}\n\n<\/ul>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udea8<\/span> Protocolo de Comunicaci\u00f3n de Crisis\n\n<\/h4>\n\n<h5 class=\"font-semibold text-indigo-600 mb-2\">Fases del Protocolo:<\/h5>\n\n<ul class=\"list-decimal list-inside ml-4 text-base text-slate-700 space-y-2\">\n\n${(appData.protocoloCrisis.fases || []).map(f => `<li><strong class=\"font-medium\">${f.name}:<\/strong> ${f.description}<\/li>`).join('')}\n\n<\/ul>\n\n<h5 class=\"font-semibold text-indigo-600 mt-4 mb-2\">Principios Fundamentales:<\/h5>\n\n<ul class=\"list-disc list-inside ml-4 text-base text-slate-700\">\n\n${(appData.protocoloCrisis.principios || []).map(p => `<li>${p}<\/li>`).join('')}\n\n<\/ul>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83c\udfa4<\/span> Foco en Vocer\u00edas: Perfiles Clave y Presencia Medi\u00e1tica\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">An\u00e1lisis de la visibilidad y el rol de los principales portavoces del Ayuntamiento en el ecosistema medi\u00e1tico.<\/p>\n\n<div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n\n${(appData.vocerias || []).map(v => `\n\n<div class=\"bg-indigo-50 p-3 rounded-lg shadow-sm border border-indigo-200\">\n\n<h5 class=\"font-semibold text-indigo-700\">${v.name}<\/h5>\n\n<p class=\"text-sm text-slate-700\">Rol: ${v.role}<\/p>\n\n<p class=\"text-xs text-slate-600 mt-1\">Presencia Medi\u00e1tica: ${v.mediaPresence}<\/p>\n\n<\/div>\n\n`).join('')}\n\n<\/div>\n\n<p class=\"text-xs text-slate-500 mt-3\">\n\n[Representaci\u00f3n visual de un gr\u00e1fico de barras mostrando el nivel de presencia medi\u00e1tica de cada portavoz.]\n\n<\/p>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\u26bd<\/span> Deportes en Dos Hermanas: Iniciativas y Proyecci\u00f3n\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">${appData.deportes.intro || ''}<\/p>\n\n<h5 class=\"font-semibold text-indigo-600 mb-2\">Programas e Iniciativas:<\/h5>\n\n<ul class=\"list-disc list-inside ml-4 text-base text-slate-700\">\n\n${(appData.deportes.programas || []).map(p => `<li>${p}<\/li>`).join('')}\n\n<\/ul>\n\n<h5 class=\"font-semibold text-indigo-600 mt-4 mb-2\">Eventos Destacados:<\/h5>\n\n<ul class=\"list-disc list-inside ml-4 text-base text-slate-700\">\n\n${(appData.deportes.destacados || []).map(d => `<li>${d}<\/li>`).join('')}\n\n<\/ul>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\uddfa\ufe0f<\/span> Mapa Narrativo: Conexiones y Temas Dominantes\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">${appData.narrativeMap.description || ''}<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Tema<\/th>\n\n<th class=\"p-3\">Actores Clave<\/th>\n\n<th class=\"p-3\">Sentimiento<\/th>\n\n<th class=\"p-3\">Conexiones<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.narrativeMap.elements || []).map(e => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${e.theme}<\/td>\n\n<td class=\"p-3 text-slate-600\">${e.actors}<\/td>\n\n<td class=\"p-3 text-slate-600 text-${e.sentiment === 'Positivo' ? 'emerald' : (e.sentiment === 'Negativo' ? 'red' : 'yellow')}-700 font-semibold\">${e.sentiment}<\/td>\n\n<td class=\"p-3 text-slate-600\">${(e.connections || []).join(', ')}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udde3\ufe0f<\/span> Brecha Say-Do: Discurso vs. Percepci\u00f3n Ciudadana\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">${appData.sayDoGap.description || ''}<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Aspecto<\/th>\n\n<th class=\"p-3\">Discurso Oficial<\/th>\n\n<th class=\"p-3\">Percepci\u00f3n Ciudadana<\/th>\n\n<th class=\"p-3\">Brecha<\/th>\n\n<th class=\"p-3\">Impacto Reputacional<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.sayDoGap.analysis || []).map(a => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${a.aspect}<\/td>\n\n<td class=\"p-3 text-slate-600\">${a.discourse}<\/td>\n\n<td class=\"p-3 text-slate-600\">${a.perception}<\/td>\n\n<td class=\"p-3 text-slate-600 font-semibold text-${a.gap === 'Alta' ? 'red' : (a.gap === 'Media' ? 'yellow' : 'blue')}-700\">${a.gap}<\/td>\n\n<td class=\"p-3 text-slate-600\">${a.impact}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udea8<\/span> Se\u00f1ales Tempranas y 'Cisnes Negros'\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">${appData.earlyWarnings.description || ''}<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Tipo<\/th>\n\n<th class=\"p-3\">Nombre<\/th>\n\n<th class=\"p-3\">Descripci\u00f3n<\/th>\n\n<th class=\"p-3\">Mitigaci\u00f3n Sugerida<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.earlyWarnings.signals || []).map(s => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${s.type}<\/td>\n\n<td class=\"p-3 text-slate-600\">${s.name}<\/td>\n\n<td class=\"p-3 text-slate-600\">${s.description}<\/td>\n\n<td class=\"p-3 text-slate-600\">${s.mitigation}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udd2e<\/span> Escenarios y Proyecci\u00f3n Reputacional\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">Proyecci\u00f3n de posibles escenarios futuros para la reputaci\u00f3n del Ayuntamiento, basados en la evoluci\u00f3n de los temas clave y la efectividad de las estrategias de comunicaci\u00f3n.<\/p>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Escenario<\/th>\n\n<th class=\"p-3\">Nombre<\/th>\n\n<th class=\"p-3\">Descripci\u00f3n<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.scenarios || []).map(s => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${s.type}<\/td>\n\n<td class=\"p-3 text-slate-600\">${s.name}<\/td>\n\n<td class=\"p-3 text-slate-600\">${s.description}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n<div class=\"consolidated-section-block consolidated-chapter mb-8\">\n\n<h4 class=\"text-2xl font-extrabold text-indigo-800 mb-3 flex items-center\">\n\n<span class=\"text-3xl mr-2\">\ud83d\udcf0<\/span> Tratamiento de los Medios de Comunicaci\u00f3n\n\n<\/h4>\n\n<p class=\"text-slate-700 mb-4\">${appData.mediaTreatment.overallTone.description || ''}<\/p>\n\n<h5 class=\"font-semibold text-indigo-600 mb-2\">Temas Dominantes y su Tratamiento:<\/h5>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200 mb-4\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Tema<\/th>\n\n<th class=\"p-3\">Cobertura<\/th>\n\n<th class=\"p-3\">Tono<\/th>\n\n<th class=\"p-3\">Impacto<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.mediaTreatment.dominantThemes || []).map(t => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${t.theme}<\/td>\n\n<td class=\"p-3 text-slate-600\">${t.coverage}<\/td>\n\n<td class=\"p-3 text-slate-600\">${t.tone}<\/td>\n\n<td class=\"p-3 text-slate-600\">${t.impact}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<h5 class=\"font-semibold text-indigo-600 mb-2\">Enfoque y Framing por Tipo de Medio:<\/h5>\n\n<div class=\"overflow-x-auto rounded-lg shadow-sm border border-slate-200\">\n\n<table class=\"w-full text-base text-left\">\n\n<thead class=\"bg-indigo-50 text-indigo-700 uppercase font-semibold\">\n\n<tr>\n\n<th class=\"p-3\">Tipo de Medio<\/th>\n\n<th class=\"p-3\">Framing<\/th>\n\n<\/tr>\n\n<\/thead>\n\n<tbody>\n\n${(appData.mediaTreatment.mediaFraming || []).map(f => `\n\n<tr class=\"border-b border-slate-200 hover:bg-slate-50\">\n\n<td class=\"p-3 font-medium\">${f.mediaType}<\/td>\n\n<td class=\"p-3 text-slate-600\">${f.framing}<\/td>\n\n<\/tr>\n\n`).join('')}\n\n<\/tbody>\n\n<\/table>\n\n<\/div>\n\n<\/div>\n\n`;\n\ncontainer.innerHTML = htmlContent;\n\n}\n\nfunction downloadPdf() {\n\nconst element = document.getElementById('consolidated-report-content');\n\nif (!element) {\n\nconsole.error(\"El contenido para el PDF no se encontr\u00f3.\");\n\nreturn;\n\n}\n\n\/\/ Clonar el elemento para aplicar estilos espec\u00edficos para el PDF sin afectar la visualizaci\u00f3n en pantalla\n\nconst clonedElement = element.cloneNode(true);\n\nclonedElement.classList.add('pdf-content-wrapper');\n\nclonedElement.style.width = '210mm'; \/\/ Ancho A4\n\nclonedElement.style.minHeight = '297mm'; \/\/ Alto A4\n\nclonedElement.style.padding = '20mm'; \/\/ M\u00e1rgenes\n\nclonedElement.style.boxSizing = 'border-box';\n\nclonedElement.style.backgroundColor = '#FFFFFF'; \/\/ Fondo blanco para el PDF\n\n\/\/ A\u00f1adir el elemento clonado al DOM temporalmente para que html2canvas lo capture correctamente\n\ndocument.body.appendChild(clonedElement);\n\nconst opt = {\n\nmargin: 10,\n\nfilename: `Informe_Dos_Hermanas_${appData.city}_2023-2025.pdf`,\n\nimage: { type: 'jpeg', quality: 0.98 },\n\nhtml2canvas: { scale: 2, logging: true, dpi: 192, letterRendering: true, useCORS: true },\n\njsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }\n\n};\n\nhtml2pdf().set(opt).from(clonedElement).save().then(() => {\n\n\/\/ Remover el elemento clonado del DOM despu\u00e9s de generar el PDF\n\ndocument.body.removeChild(clonedElement);\n\n});\n\n}\n\n\/\/ --- Event Listeners ---\n\nnavButtons.forEach(button => {\n\nbutton.addEventListener('click', () => {\n\nactivateSection(button.dataset.target);\n\n});\n\n});\n\nif (btnLogros) {\n\nbtnLogros.addEventListener('click', () => displayBalanceContent('logros'));\n\n}\n\nif (btnRiesgos) {\n\nbtnRiesgos.addEventListener('click', () => displayBalanceContent('riesgos'));\n\n}\n\nconst downloadPdfBtn = document.getElementById('download-pdf-btn');\n\nif (downloadPdfBtn) {\n\ndownloadPdfBtn.addEventListener('click', downloadPdf);\n\n}\n\n\/\/ Initial load: activate the first section\n\nactivateSection('balance');\n\n});\n\n<\/script>\n\n<\/body>\n\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>An\u00e1lisis Interactivo: Reputaci\u00f3n del Ayuntamiento de Dos Hermanas An\u00e1lisis de Reputaci\u00f3n y Presencia Digital Ayuntamiento de Dos Hermanas Balanza Reputacional Diagn\u00f3stico Posicionamiento Term\u00f3metro Ciudadano Panel de KPIs Mapa de Actores Foco en el Alcalde Foco en Vocer\u00edas An\u00e1lisis Digital Tratamiento Medios L\u00ednea de Tiempo Matriz R&#038;O Benchmarking Estrategia y Narrativa Protocolo Crisis Mapa Narrativo Brecha&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4],"tags":[],"class_list":["post-351","post","type-post","status-publish","format-standard","hentry","category-analisis"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/sgDuos-351","_links":{"self":[{"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/posts\/351","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/comments?post=351"}],"version-history":[{"count":2,"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/posts\/351\/revisions"}],"predecessor-version":[{"id":353,"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/posts\/351\/revisions\/353"}],"wp:attachment":[{"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/media?parent=351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/categories?post=351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buscomunicacion.com\/index.php\/wp-json\/wp\/v2\/tags?post=351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}