Showing
6 changed files
with
753 additions
and
137 deletions
| ... | @@ -178,6 +178,10 @@ | ... | @@ -178,6 +178,10 @@ |
| 178 | min-height: 2px; | 178 | min-height: 2px; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | + :global(html.dark) .bar { | ||
| 182 | + background: rgba(107, 159, 212, 0.85); | ||
| 183 | + } | ||
| 184 | + | ||
| 181 | .bars:hover .bar { | 185 | .bars:hover .bar { |
| 182 | opacity: 0.35; | 186 | opacity: 0.35; |
| 183 | } | 187 | } | ... | ... |
| ... | @@ -11,6 +11,11 @@ | ... | @@ -11,6 +11,11 @@ |
| 11 | navigateResults | 11 | navigateResults |
| 12 | } from '$lib/stores/searchStore'; | 12 | } from '$lib/stores/searchStore'; |
| 13 | 13 | ||
| 14 | + let { | ||
| 15 | + preserveVista = false, | ||
| 16 | + vista = 'agregado' | ||
| 17 | + } = $props(); | ||
| 18 | + | ||
| 14 | let searchInputRef = $state(null); | 19 | let searchInputRef = $state(null); |
| 15 | let searchVal = $state(''); | 20 | let searchVal = $state(''); |
| 16 | let searchFocused = $state(false); | 21 | let searchFocused = $state(false); |
| ... | @@ -47,7 +52,10 @@ | ... | @@ -47,7 +52,10 @@ |
| 47 | } | 52 | } |
| 48 | 53 | ||
| 49 | function handleSearchSelect(result) { | 54 | function handleSearchSelect(result) { |
| 50 | - goto(`/objeto/${result.codigo}`); | 55 | + const url = preserveVista && vista === 'comparar' |
| 56 | + ? `/objeto/${result.codigo}?vista=comparar` | ||
| 57 | + : `/objeto/${result.codigo}`; | ||
| 58 | + goto(url); | ||
| 51 | searchVal = ''; | 59 | searchVal = ''; |
| 52 | clearSearch(); | 60 | clearSearch(); |
| 53 | searchFocused = false; | 61 | searchFocused = false; |
| ... | @@ -116,7 +124,7 @@ | ... | @@ -116,7 +124,7 @@ |
| 116 | display: flex; | 124 | display: flex; |
| 117 | align-items: center; | 125 | align-items: center; |
| 118 | gap: 0.5rem; | 126 | gap: 0.5rem; |
| 119 | - background: #f5f5f5; | 127 | + background: var(--search-bg, #f5f5f5); |
| 120 | border: none; | 128 | border: none; |
| 121 | border-radius: 8px; | 129 | border-radius: 8px; |
| 122 | padding: 0.625rem 1rem; | 130 | padding: 0.625rem 1rem; |
| ... | @@ -124,6 +132,10 @@ | ... | @@ -124,6 +132,10 @@ |
| 124 | width: 100%; | 132 | width: 100%; |
| 125 | } | 133 | } |
| 126 | 134 | ||
| 135 | + :global(html.dark) .objeto-search { | ||
| 136 | + --search-bg: rgba(255, 255, 255, 0.08); | ||
| 137 | + } | ||
| 138 | + | ||
| 127 | .objeto-search.focused { | 139 | .objeto-search.focused { |
| 128 | border-color: #6B9FD4; | 140 | border-color: #6B9FD4; |
| 129 | box-shadow: 0 0 0 3px rgba(107, 159, 212, 0.15); | 141 | box-shadow: 0 0 0 3px rgba(107, 159, 212, 0.15); | ... | ... |
| ... | @@ -57,4 +57,14 @@ | ... | @@ -57,4 +57,14 @@ |
| 57 | .vista-btn:active { | 57 | .vista-btn:active { |
| 58 | color: #555555; | 58 | color: #555555; |
| 59 | } | 59 | } |
| 60 | + | ||
| 61 | + :global(html.dark) .vista-btn { | ||
| 62 | + color: rgba(255, 255, 255, 0.6); | ||
| 63 | + text-decoration-color: rgba(255, 255, 255, 0.4); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + :global(html.dark) .vista-btn:hover { | ||
| 67 | + color: rgba(255, 255, 255, 0.85); | ||
| 68 | + text-decoration-color: rgba(255, 255, 255, 0.5); | ||
| 69 | + } | ||
| 60 | </style> | 70 | </style> | ... | ... |
| ... | @@ -3,6 +3,7 @@ | ... | @@ -3,6 +3,7 @@ |
| 3 | import { tweened } from 'svelte/motion'; | 3 | import { tweened } from 'svelte/motion'; |
| 4 | import { cubicOut } from 'svelte/easing'; | 4 | import { cubicOut } from 'svelte/easing'; |
| 5 | import { goto } from '$app/navigation'; | 5 | import { goto } from '$app/navigation'; |
| 6 | + import { page } from '$app/stores'; | ||
| 6 | import { supabase } from '$lib/supabase'; | 7 | import { supabase } from '$lib/supabase'; |
| 7 | import Spinner from '$lib/components/ui/Spinner.svelte'; | 8 | import Spinner from '$lib/components/ui/Spinner.svelte'; |
| 8 | import ObjetoSearch from '$lib/components/objeto/ObjetoSearch.svelte'; | 9 | import ObjetoSearch from '$lib/components/objeto/ObjetoSearch.svelte'; |
| ... | @@ -30,9 +31,88 @@ | ... | @@ -30,9 +31,88 @@ |
| 30 | let showInfo = $state(false); | 31 | let showInfo = $state(false); |
| 31 | let showDefinicionesModal = $state(false); | 32 | let showDefinicionesModal = $state(false); |
| 32 | let showMobileSidebar = $state(false); | 33 | let showMobileSidebar = $state(false); |
| 34 | + | ||
| 35 | + // Estado de vista | ||
| 33 | let vista = $state('agregado'); // 'agregado' | 'comparar' | 36 | let vista = $state('agregado'); // 'agregado' | 'comparar' |
| 34 | let isDark = $state(true); | 37 | let isDark = $state(true); |
| 35 | 38 | ||
| 39 | + // ══════════════════════════════════════════════════════════════ | ||
| 40 | + // MANEJO DE URL - Estado compartible | ||
| 41 | + // ══════════════════════════════════════════════════════════════ | ||
| 42 | + | ||
| 43 | + // Leer parámetros de URL | ||
| 44 | + function getUrlParams() { | ||
| 45 | + const params = $page.url.searchParams; | ||
| 46 | + return { | ||
| 47 | + vista: params.get('vista') || 'agregado', | ||
| 48 | + entidad: params.get('entidad') ? parseInt(params.get('entidad')) : null, | ||
| 49 | + entidadA: params.get('entidadA') ? parseInt(params.get('entidadA')) : null, | ||
| 50 | + entidadB: params.get('entidadB') ? parseInt(params.get('entidadB')) : null | ||
| 51 | + }; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + // Actualizar URL sin recargar la página | ||
| 55 | + function updateUrl(newParams = {}) { | ||
| 56 | + const url = new URL($page.url); | ||
| 57 | + | ||
| 58 | + // Limpiar parámetros anteriores | ||
| 59 | + url.searchParams.delete('vista'); | ||
| 60 | + url.searchParams.delete('entidad'); | ||
| 61 | + url.searchParams.delete('entidadA'); | ||
| 62 | + url.searchParams.delete('entidadB'); | ||
| 63 | + | ||
| 64 | + // Agregar nuevos parámetros según el modo | ||
| 65 | + if (newParams.vista === 'comparar') { | ||
| 66 | + url.searchParams.set('vista', 'comparar'); | ||
| 67 | + if (newParams.entidadA) url.searchParams.set('entidadA', newParams.entidadA); | ||
| 68 | + if (newParams.entidadB) url.searchParams.set('entidadB', newParams.entidadB); | ||
| 69 | + } else { | ||
| 70 | + // Vista agregada - solo agregar entidad si hay una seleccionada | ||
| 71 | + if (newParams.entidad) url.searchParams.set('entidad', newParams.entidad); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + goto(url.toString(), { replaceState: true, noScroll: true }); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + // Aplicar estado desde URL después de cargar entidades | ||
| 78 | + async function applyUrlState() { | ||
| 79 | + const params = getUrlParams(); | ||
| 80 | + | ||
| 81 | + // Aplicar vista | ||
| 82 | + vista = params.vista; | ||
| 83 | + | ||
| 84 | + if (params.vista === 'comparar') { | ||
| 85 | + // Modo comparación | ||
| 86 | + if (params.entidadA) { | ||
| 87 | + const entityA = entidades.find(e => e.entidad === params.entidadA); | ||
| 88 | + if (entityA) { | ||
| 89 | + entidadCompararA = entityA; | ||
| 90 | + datosCompararA = await loadDatosEntidad(entityA); | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + if (params.entidadB) { | ||
| 94 | + const entityB = entidades.find(e => e.entidad === params.entidadB); | ||
| 95 | + if (entityB) { | ||
| 96 | + entidadCompararB = entityB; | ||
| 97 | + datosCompararB = await loadDatosEntidad(entityB); | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + // Si no hay entidades en URL, inicializar con defaults | ||
| 101 | + if (!params.entidadA && !params.entidadB) { | ||
| 102 | + await initComparacion(); | ||
| 103 | + } | ||
| 104 | + } else { | ||
| 105 | + // Vista agregada | ||
| 106 | + if (params.entidad) { | ||
| 107 | + const entity = entidades.find(e => e.entidad === params.entidad); | ||
| 108 | + if (entity) { | ||
| 109 | + selectedEntity = entity; | ||
| 110 | + await loadData(); | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | + } | ||
| 114 | + } | ||
| 115 | + | ||
| 36 | 116 | ||
| 37 | // Parsear descripciones del objeto | 117 | // Parsear descripciones del objeto |
| 38 | function parseDescripciones(descripcionesStr) { | 118 | function parseDescripciones(descripcionesStr) { |
| ... | @@ -407,11 +487,53 @@ | ... | @@ -407,11 +487,53 @@ |
| 407 | 487 | ||
| 408 | let hoveredYearComparar = $state(null); | 488 | let hoveredYearComparar = $state(null); |
| 409 | let loadingComparacion = $state(false); | 489 | let loadingComparacion = $state(false); |
| 490 | + let isDefaultSelection = $state(false); // true si la selección es automática | ||
| 491 | + | ||
| 492 | + // Estado de alertas (cerradas por el usuario) | ||
| 493 | + let alertDefaultDismissed = $state(false); | ||
| 494 | + let alertRangosDismissed = $state(false); | ||
| 410 | 495 | ||
| 411 | // Entidades seleccionadas para comparar | 496 | // Entidades seleccionadas para comparar |
| 412 | let entidadCompararA = $state(null); | 497 | let entidadCompararA = $state(null); |
| 413 | let entidadCompararB = $state(null); | 498 | let entidadCompararB = $state(null); |
| 414 | 499 | ||
| 500 | + // Pre-seleccionar entidades al cambiar a modo comparar | ||
| 501 | + async function initComparacion() { | ||
| 502 | + // Si ya hay selección manual, no hacer nada | ||
| 503 | + if (entidadCompararA || entidadCompararB) return; | ||
| 504 | + | ||
| 505 | + if (selectedEntity) { | ||
| 506 | + // Si venimos de una entidad específica, pre-seleccionarla en A | ||
| 507 | + entidadCompararA = selectedEntity; | ||
| 508 | + loadingComparacion = true; | ||
| 509 | + datosCompararA = await loadDatosEntidad(selectedEntity); | ||
| 510 | + loadingComparacion = false; | ||
| 511 | + isDefaultSelection = false; // No es default porque el usuario ya eligió una entidad | ||
| 512 | + } else if (topEntidadesTotal.length >= 2) { | ||
| 513 | + // Si venimos de agregado, pre-seleccionar top 2 del ranking | ||
| 514 | + const top1 = entidades.find(e => e.entidad_desc === topEntidadesTotal[0].nombre); | ||
| 515 | + const top2 = entidades.find(e => e.entidad_desc === topEntidadesTotal[1].nombre); | ||
| 516 | + | ||
| 517 | + if (top1 && top2) { | ||
| 518 | + isDefaultSelection = true; | ||
| 519 | + loadingComparacion = true; | ||
| 520 | + | ||
| 521 | + entidadCompararA = top1; | ||
| 522 | + datosCompararA = await loadDatosEntidad(top1); | ||
| 523 | + | ||
| 524 | + entidadCompararB = top2; | ||
| 525 | + datosCompararB = await loadDatosEntidad(top2); | ||
| 526 | + | ||
| 527 | + loadingComparacion = false; | ||
| 528 | + } | ||
| 529 | + } | ||
| 530 | + } | ||
| 531 | + | ||
| 532 | + // Limpiar selección por defecto cuando el usuario cambia manualmente | ||
| 533 | + function clearDefaultSelection() { | ||
| 534 | + isDefaultSelection = false; | ||
| 535 | + } | ||
| 536 | + | ||
| 415 | // Datos cargados de cada entidad | 537 | // Datos cargados de cada entidad |
| 416 | let datosCompararA = $state({ anual: [], historico: null }); | 538 | let datosCompararA = $state({ anual: [], historico: null }); |
| 417 | let datosCompararB = $state({ anual: [], historico: null }); | 539 | let datosCompararB = $state({ anual: [], historico: null }); |
| ... | @@ -467,6 +589,9 @@ | ... | @@ -467,6 +589,9 @@ |
| 467 | dropdownAOpen = false; | 589 | dropdownAOpen = false; |
| 468 | searchA = ''; | 590 | searchA = ''; |
| 469 | entityLimitA = 30; | 591 | entityLimitA = 30; |
| 592 | + isDefaultSelection = false; // Selección manual | ||
| 593 | + alertDefaultDismissed = false; // Resetear alerta | ||
| 594 | + alertRangosDismissed = false; // Mostrar alerta de rangos si aplica | ||
| 470 | loadingComparacion = true; | 595 | loadingComparacion = true; |
| 471 | datosCompararA = await loadDatosEntidad(entidad); | 596 | datosCompararA = await loadDatosEntidad(entidad); |
| 472 | loadingComparacion = false; | 597 | loadingComparacion = false; |
| ... | @@ -478,20 +603,58 @@ | ... | @@ -478,20 +603,58 @@ |
| 478 | dropdownBOpen = false; | 603 | dropdownBOpen = false; |
| 479 | searchB = ''; | 604 | searchB = ''; |
| 480 | entityLimitB = 30; | 605 | entityLimitB = 30; |
| 606 | + isDefaultSelection = false; // Selección manual | ||
| 607 | + alertDefaultDismissed = false; // Resetear alerta | ||
| 608 | + alertRangosDismissed = false; // Mostrar alerta de rangos si aplica | ||
| 481 | loadingComparacion = true; | 609 | loadingComparacion = true; |
| 482 | datosCompararB = await loadDatosEntidad(entidad); | 610 | datosCompararB = await loadDatosEntidad(entidad); |
| 483 | loadingComparacion = false; | 611 | loadingComparacion = false; |
| 484 | } | 612 | } |
| 485 | 613 | ||
| 486 | // Selector de rango de años | 614 | // Selector de rango de años |
| 487 | - let rangoAños = $state('10'); // '5', '10', '15', 'todo' | 615 | + let rangoAños = $state('todo'); // '5', '10', '15', 'todo' |
| 488 | 616 | ||
| 489 | - // Años comunes entre ambas entidades | 617 | + // Años para comparación (comunes si hay 2 entidades, o los de la única seleccionada) |
| 490 | let añosComunesTotales = $derived.by(() => { | 618 | let añosComunesTotales = $derived.by(() => { |
| 491 | - if (!datosCompararA.anual.length || !datosCompararB.anual.length) return []; | 619 | + const añosA = datosCompararA.anual.map(d => d.gestion); |
| 492 | - const añosA = new Set(datosCompararA.anual.map(d => d.gestion)); | 620 | + const añosB = datosCompararB.anual.map(d => d.gestion); |
| 493 | - const añosB = new Set(datosCompararB.anual.map(d => d.gestion)); | 621 | + |
| 494 | - return [...añosA].filter(a => añosB.has(a)).sort((a, b) => a - b); | 622 | + // Si hay ambas entidades, usar años en común |
| 623 | + if (añosA.length && añosB.length) { | ||
| 624 | + const setB = new Set(añosB); | ||
| 625 | + return añosA.filter(a => setB.has(a)).sort((a, b) => a - b); | ||
| 626 | + } | ||
| 627 | + // Si solo hay A, usar sus años | ||
| 628 | + if (añosA.length) return [...añosA].sort((a, b) => a - b); | ||
| 629 | + // Si solo hay B, usar sus años | ||
| 630 | + if (añosB.length) return [...añosB].sort((a, b) => a - b); | ||
| 631 | + return []; | ||
| 632 | + }); | ||
| 633 | + | ||
| 634 | + // Flag para saber si estamos en modo "solo una entidad" | ||
| 635 | + let soloUnaEntidad = $derived( | ||
| 636 | + (entidadCompararA && !entidadCompararB) || (!entidadCompararA && entidadCompararB) | ||
| 637 | + ); | ||
| 638 | + | ||
| 639 | + // Información de rangos para advertencia | ||
| 640 | + let rangoInfoA = $derived.by(() => { | ||
| 641 | + if (!datosCompararA.anual.length) return null; | ||
| 642 | + const años = datosCompararA.anual.map(d => d.gestion).sort((a, b) => a - b); | ||
| 643 | + return { desde: años[0], hasta: años[años.length - 1], total: años.length }; | ||
| 644 | + }); | ||
| 645 | + | ||
| 646 | + let rangoInfoB = $derived.by(() => { | ||
| 647 | + if (!datosCompararB.anual.length) return null; | ||
| 648 | + const años = datosCompararB.anual.map(d => d.gestion).sort((a, b) => a - b); | ||
| 649 | + return { desde: años[0], hasta: años[años.length - 1], total: años.length }; | ||
| 650 | + }); | ||
| 651 | + | ||
| 652 | + // Detectar si hay diferencia significativa en los rangos | ||
| 653 | + let tienenRangosDiferentes = $derived.by(() => { | ||
| 654 | + if (!rangoInfoA || !rangoInfoB) return false; | ||
| 655 | + return rangoInfoA.desde !== rangoInfoB.desde || | ||
| 656 | + rangoInfoA.hasta !== rangoInfoB.hasta || | ||
| 657 | + rangoInfoA.total !== rangoInfoB.total; | ||
| 495 | }); | 658 | }); |
| 496 | 659 | ||
| 497 | // Años filtrados según el rango seleccionado | 660 | // Años filtrados según el rango seleccionado |
| ... | @@ -580,8 +743,25 @@ | ... | @@ -580,8 +743,25 @@ |
| 580 | }); | 743 | }); |
| 581 | 744 | ||
| 582 | // Colores | 745 | // Colores |
| 583 | - let colorA = '#2a9d8f'; | 746 | + // Colores para comparación (reactivos al tema) |
| 584 | - let colorB = '#f4a261'; | 747 | + let isDarkMode = $state(false); |
| 748 | + | ||
| 749 | + $effect(() => { | ||
| 750 | + if (typeof document !== 'undefined') { | ||
| 751 | + const checkDark = () => { | ||
| 752 | + isDarkMode = document.documentElement.classList.contains('dark'); | ||
| 753 | + }; | ||
| 754 | + checkDark(); | ||
| 755 | + const observer = new MutationObserver(checkDark); | ||
| 756 | + observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); | ||
| 757 | + return () => observer.disconnect(); | ||
| 758 | + } | ||
| 759 | + }); | ||
| 760 | + | ||
| 761 | + // Modo claro: gris-azulado pastel + terracota | ||
| 762 | + // Modo oscuro: azul claro + ámbar dorado | ||
| 763 | + let colorA = $derived(isDarkMode ? '#7EB8DA' : '#6B8299'); | ||
| 764 | + let colorB = $derived(isDarkMode ? '#D4A574' : '#C4897D'); | ||
| 585 | 765 | ||
| 586 | // Actualizar tweened de comparación | 766 | // Actualizar tweened de comparación |
| 587 | $effect(() => { | 767 | $effect(() => { |
| ... | @@ -673,10 +853,13 @@ | ... | @@ -673,10 +853,13 @@ |
| 673 | attributeFilter: ['class'] | 853 | attributeFilter: ['class'] |
| 674 | }); | 854 | }); |
| 675 | 855 | ||
| 676 | - // Cargar datos | 856 | + // Cargar datos base y entidades |
| 677 | const loadStart = performance.now(); | 857 | const loadStart = performance.now(); |
| 678 | await Promise.all([loadData(), loadEntidades()]); | 858 | await Promise.all([loadData(), loadEntidades()]); |
| 679 | console.log(`[CLIENT] Promise.all: ${(performance.now() - loadStart).toFixed(0)}ms`); | 859 | console.log(`[CLIENT] Promise.all: ${(performance.now() - loadStart).toFixed(0)}ms`); |
| 860 | + | ||
| 861 | + // Aplicar estado desde URL (después de tener entidades cargadas) | ||
| 862 | + await applyUrlState(); | ||
| 680 | console.log(`[CLIENT] onMount total: ${(performance.now() - mountStart).toFixed(0)}ms`); | 863 | console.log(`[CLIENT] onMount total: ${(performance.now() - mountStart).toFixed(0)}ms`); |
| 681 | 864 | ||
| 682 | // Cerrar dropdowns al hacer click fuera | 865 | // Cerrar dropdowns al hacer click fuera |
| ... | @@ -705,16 +888,21 @@ | ... | @@ -705,16 +888,21 @@ |
| 705 | $effect(() => { | 888 | $effect(() => { |
| 706 | if (mounted && objetoCodigo !== previousCodigo) { | 889 | if (mounted && objetoCodigo !== previousCodigo) { |
| 707 | previousCodigo = objetoCodigo; | 890 | previousCodigo = objetoCodigo; |
| 708 | - // Resetear estado | 891 | + // Resetear estado base |
| 709 | loading = true; | 892 | loading = true; |
| 710 | selectedEntity = null; | 893 | selectedEntity = null; |
| 711 | entidadCompararA = null; | 894 | entidadCompararA = null; |
| 712 | entidadCompararB = null; | 895 | entidadCompararB = null; |
| 713 | datosCompararA = { anual: [], historico: null }; | 896 | datosCompararA = { anual: [], historico: null }; |
| 714 | datosCompararB = { anual: [], historico: null }; | 897 | datosCompararB = { anual: [], historico: null }; |
| 715 | - vista = 'agregado'; | 898 | + alertDefaultDismissed = false; |
| 716 | - // Recargar datos | 899 | + alertRangosDismissed = false; |
| 717 | - loadData(); | 900 | + |
| 901 | + // Recargar datos y entidades, luego aplicar URL | ||
| 902 | + (async () => { | ||
| 903 | + await Promise.all([loadData(), loadEntidades()]); | ||
| 904 | + await applyUrlState(); | ||
| 905 | + })(); | ||
| 718 | } | 906 | } |
| 719 | }); | 907 | }); |
| 720 | 908 | ||
| ... | @@ -724,6 +912,49 @@ | ... | @@ -724,6 +912,49 @@ |
| 724 | if (mounted && selectedEntity !== previousEntity) { | 912 | if (mounted && selectedEntity !== previousEntity) { |
| 725 | previousEntity = selectedEntity; | 913 | previousEntity = selectedEntity; |
| 726 | loadData(); | 914 | loadData(); |
| 915 | + // Actualizar URL | ||
| 916 | + updateUrl({ | ||
| 917 | + vista: vista, | ||
| 918 | + entidad: selectedEntity?.entidad || null | ||
| 919 | + }); | ||
| 920 | + } | ||
| 921 | + }); | ||
| 922 | + | ||
| 923 | + // Actualizar URL cuando cambian entidades de comparación | ||
| 924 | + let prevEntidadA = entidadCompararA; | ||
| 925 | + let prevEntidadB = entidadCompararB; | ||
| 926 | + $effect(() => { | ||
| 927 | + if (mounted && vista === 'comparar') { | ||
| 928 | + if (prevEntidadA !== entidadCompararA || prevEntidadB !== entidadCompararB) { | ||
| 929 | + prevEntidadA = entidadCompararA; | ||
| 930 | + prevEntidadB = entidadCompararB; | ||
| 931 | + updateUrl({ | ||
| 932 | + vista: 'comparar', | ||
| 933 | + entidadA: entidadCompararA?.entidad || null, | ||
| 934 | + entidadB: entidadCompararB?.entidad || null | ||
| 935 | + }); | ||
| 936 | + } | ||
| 937 | + } | ||
| 938 | + }); | ||
| 939 | + | ||
| 940 | + // Actualizar URL cuando cambia el modo vista | ||
| 941 | + let previousVista = vista; | ||
| 942 | + $effect(() => { | ||
| 943 | + if (mounted && vista !== previousVista) { | ||
| 944 | + previousVista = vista; | ||
| 945 | + if (vista === 'comparar') { | ||
| 946 | + initComparacion(); | ||
| 947 | + updateUrl({ | ||
| 948 | + vista: 'comparar', | ||
| 949 | + entidadA: entidadCompararA?.entidad || null, | ||
| 950 | + entidadB: entidadCompararB?.entidad || null | ||
| 951 | + }); | ||
| 952 | + } else { | ||
| 953 | + updateUrl({ | ||
| 954 | + vista: 'agregado', | ||
| 955 | + entidad: selectedEntity?.entidad || null | ||
| 956 | + }); | ||
| 957 | + } | ||
| 727 | } | 958 | } |
| 728 | }); | 959 | }); |
| 729 | 960 | ||
| ... | @@ -991,16 +1222,24 @@ | ... | @@ -991,16 +1222,24 @@ |
| 991 | {/if} | 1222 | {/if} |
| 992 | 1223 | ||
| 993 | {:else} | 1224 | {:else} |
| 994 | - <!-- VISTA COMPARAR (mantiene layout original) --> | 1225 | + <!-- VISTA COMPARAR --> |
| 995 | - <div class="toolbar"> | 1226 | + <main class="main-comparar"> |
| 996 | - <ObjetoSearch /> | 1227 | + <!-- Card principal del gráfico --> |
| 997 | - <VistaToggle bind:vista /> | 1228 | + <div class="chart-card-comparar"> |
| 998 | - </div> | 1229 | + <!-- Header: pills + toggle --> |
| 999 | - <main> | 1230 | + <div class="chart-top-row"> |
| 1000 | - <!-- VISTA COMPARAR --> | 1231 | + <div class="main-title-pills"> |
| 1232 | + <span class="pill pill-nivel">{objeto.nivel}</span> | ||
| 1233 | + <span class="pill pill-codigo">{objeto.codigo}</span> | ||
| 1234 | + </div> | ||
| 1235 | + <VistaToggle bind:vista /> | ||
| 1236 | + </div> | ||
| 1001 | 1237 | ||
| 1002 | - <!-- Selectores de entidades con búsqueda --> | 1238 | + <!-- Título principal --> |
| 1003 | - <div class="comparador-selectors"> | 1239 | + <h2 class="main-title-name">{objeto.nombre}</h2> |
| 1240 | + | ||
| 1241 | + <!-- Selectores de entidades con búsqueda --> | ||
| 1242 | + <div class="comparador-selectors"> | ||
| 1004 | <div class="selector-group comparador-dropdown-container"> | 1243 | <div class="selector-group comparador-dropdown-container"> |
| 1005 | <span class="selector-dot" style="background: {colorA}"></span> | 1244 | <span class="selector-dot" style="background: {colorA}"></span> |
| 1006 | <div class="relative" style="flex: 1;"> | 1245 | <div class="relative" style="flex: 1;"> |
| ... | @@ -1080,20 +1319,65 @@ | ... | @@ -1080,20 +1319,65 @@ |
| 1080 | {/if} | 1319 | {/if} |
| 1081 | </div> | 1320 | </div> |
| 1082 | </div> | 1321 | </div> |
| 1322 | + | ||
| 1323 | + <!-- Buscador de objeto de gasto --> | ||
| 1324 | + <div class="comparador-search-wrapper"> | ||
| 1325 | + <ObjetoSearch preserveVista={true} {vista} /> | ||
| 1326 | + </div> | ||
| 1083 | </div> | 1327 | </div> |
| 1084 | 1328 | ||
| 1085 | - <!-- Mensaje si no hay entidades seleccionadas --> | 1329 | + <!-- Mensaje de selección por defecto --> |
| 1086 | - {#if !entidadCompararA || !entidadCompararB} | 1330 | + {#if isDefaultSelection && entidadCompararA && entidadCompararB && !alertDefaultDismissed} |
| 1087 | - <div class="comparador-placeholder"> | 1331 | + <div class="comparador-hint"> |
| 1088 | - <p>Selecciona dos entidades para comparar su gasto en <strong>{objeto.nombre}</strong></p> | 1332 | + <svg class="alert-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 1333 | + <circle cx="12" cy="12" r="10"/> | ||
| 1334 | + <line x1="12" y1="16" x2="12" y2="12"/> | ||
| 1335 | + <line x1="12" y1="8" x2="12.01" y2="8"/> | ||
| 1336 | + </svg> | ||
| 1337 | + <span>Mostrando las dos entidades con mayor gasto. Puedes cambiar la selección arriba.</span> | ||
| 1338 | + <button class="alert-close" onclick={() => alertDefaultDismissed = true} aria-label="Cerrar"> | ||
| 1339 | + <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| 1340 | + <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/> | ||
| 1341 | + </svg> | ||
| 1342 | + </button> | ||
| 1089 | </div> | 1343 | </div> |
| 1090 | - {:else if loadingComparacion} | 1344 | + {/if} |
| 1345 | + | ||
| 1346 | + <!-- Advertencia de rangos diferentes --> | ||
| 1347 | + {#if tienenRangosDiferentes && entidadCompararA && entidadCompararB && !loadingComparacion && !alertRangosDismissed} | ||
| 1348 | + <div class="comparador-warning"> | ||
| 1349 | + <svg class="alert-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| 1350 | + <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/> | ||
| 1351 | + <line x1="12" y1="9" x2="12" y2="13"/> | ||
| 1352 | + <line x1="12" y1="17" x2="12.01" y2="17"/> | ||
| 1353 | + </svg> | ||
| 1354 | + <span> | ||
| 1355 | + Rangos de tiempo diferentes: | ||
| 1356 | + <strong>{entidadCompararA.entidad_desc.substring(0, 20)}{entidadCompararA.entidad_desc.length > 20 ? '...' : ''}</strong> ({rangoInfoA?.desde}-{rangoInfoA?.hasta}) | ||
| 1357 | + vs | ||
| 1358 | + <strong>{entidadCompararB.entidad_desc.substring(0, 20)}{entidadCompararB.entidad_desc.length > 20 ? '...' : ''}</strong> ({rangoInfoB?.desde}-{rangoInfoB?.hasta}). | ||
| 1359 | + Solo se comparan {añosComunesTotales.length} años en común. | ||
| 1360 | + </span> | ||
| 1361 | + <button class="alert-close" onclick={() => alertRangosDismissed = true} aria-label="Cerrar"> | ||
| 1362 | + <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| 1363 | + <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/> | ||
| 1364 | + </svg> | ||
| 1365 | + </button> | ||
| 1366 | + </div> | ||
| 1367 | + {/if} | ||
| 1368 | + | ||
| 1369 | + <!-- Estados del comparador --> | ||
| 1370 | + {#if loadingComparacion} | ||
| 1091 | <div class="comparador-placeholder"> | 1371 | <div class="comparador-placeholder"> |
| 1092 | <Spinner size={48} color="var(--theme-texto, #5A5650)" /> | 1372 | <Spinner size={48} color="var(--theme-texto, #5A5650)" /> |
| 1093 | </div> | 1373 | </div> |
| 1374 | + {:else if !entidadCompararA && !entidadCompararB} | ||
| 1375 | + <div class="comparador-placeholder"> | ||
| 1376 | + <p>Selecciona dos entidades para comparar su gasto en <strong>{objeto.nombre}</strong></p> | ||
| 1377 | + </div> | ||
| 1094 | {:else if añosComparacion.length === 0} | 1378 | {:else if añosComparacion.length === 0} |
| 1095 | <div class="comparador-placeholder"> | 1379 | <div class="comparador-placeholder"> |
| 1096 | - <p>Las entidades seleccionadas no tienen años en común para este objeto.</p> | 1380 | + <p>No hay datos disponibles para comparar.</p> |
| 1097 | </div> | 1381 | </div> |
| 1098 | {:else} | 1382 | {:else} |
| 1099 | <!-- Selector de rango de años --> | 1383 | <!-- Selector de rango de años --> |
| ... | @@ -1110,28 +1394,28 @@ | ... | @@ -1110,28 +1394,28 @@ |
| 1110 | {/if} | 1394 | {/if} |
| 1111 | 1395 | ||
| 1112 | <!-- Gráfico comparativo --> | 1396 | <!-- Gráfico comparativo --> |
| 1113 | - <div class="chart-section"> | 1397 | + <div class="chart-header"> |
| 1114 | - <div class="chart-header"> | 1398 | + <span class="chart-title">Bs/habitante <span class="chart-period">· {displayPeriodoComparar}</span></span> |
| 1115 | - <span class="chart-title">Bs/habitante</span> | 1399 | + </div> |
| 1116 | - <span class="chart-period">{displayPeriodoComparar}</span> | ||
| 1117 | - </div> | ||
| 1118 | - | ||
| 1119 | - <div class="chart-wrapper chart-wrapper-scroll"> | ||
| 1120 | - <div class="y-axis y-axis-sticky"> | ||
| 1121 | - <span class="y-label">Bs {formatMonto(Math.round(maxComparacion))}</span> | ||
| 1122 | - <span class="y-label">Bs {formatMonto(Math.round(maxComparacion / 2))}</span> | ||
| 1123 | - <span class="y-label">Bs 0</span> | ||
| 1124 | - </div> | ||
| 1125 | 1400 | ||
| 1126 | - <div | 1401 | + <div class="chart-comparar-wrapper"> |
| 1127 | - class="chart chart-comparar" | 1402 | + <!-- Área principal del gráfico --> |
| 1128 | - class:chart-muchos-años={añosComparacion.length > 15} | 1403 | + <div class="chart-comparar-inner"> |
| 1129 | - onmouseleave={() => hoveredYearComparar = null} | 1404 | + <!-- Y-axis labels --> |
| 1130 | - role="group" | 1405 | + <span class="y-label-comparar" style="bottom: 100%">Bs {formatMonto(Math.round(maxComparacion))}</span> |
| 1131 | - > | 1406 | + <span class="y-label-comparar" style="bottom: 50%">Bs {formatMonto(Math.round(maxComparacion / 2))}</span> |
| 1407 | + <span class="y-label-comparar" style="bottom: 0%">Bs 0</span> | ||
| 1408 | + | ||
| 1409 | + <!-- Grid lines --> | ||
| 1410 | + <div class="grid-line-comparar" style="bottom: 100%"></div> | ||
| 1411 | + <div class="grid-line-comparar" style="bottom: 50%"></div> | ||
| 1412 | + <div class="grid-line-comparar" style="bottom: 0%"></div> | ||
| 1413 | + | ||
| 1414 | + <!-- Barras --> | ||
| 1415 | + <div class="bars-comparar" onmouseleave={() => hoveredYearComparar = null} role="group"> | ||
| 1132 | {#each añosComparacion as año, i} | 1416 | {#each añosComparacion as año, i} |
| 1133 | <div | 1417 | <div |
| 1134 | - class="bar-group" | 1418 | + class="bar-group-comparar" |
| 1135 | class:active={hoveredYearComparar === año} | 1419 | class:active={hoveredYearComparar === año} |
| 1136 | onmouseenter={() => hoveredYearComparar = año} | 1420 | onmouseenter={() => hoveredYearComparar = año} |
| 1137 | role="button" | 1421 | role="button" |
| ... | @@ -1139,33 +1423,62 @@ | ... | @@ -1139,33 +1423,62 @@ |
| 1139 | > | 1423 | > |
| 1140 | <div class="bars-pair"> | 1424 | <div class="bars-pair"> |
| 1141 | <div | 1425 | <div |
| 1142 | - class="bar bar-a" | 1426 | + class="bar-comparar" |
| 1143 | - style="height: {((datosGraficoA[i]?.per_capita || 0) / maxComparacion) * 100}%; --bar-color: {colorA}" | 1427 | + style="height: {((datosGraficoA[i]?.per_capita || 0) / maxComparacion) * 100}%; background: {colorA}" |
| 1144 | ></div> | 1428 | ></div> |
| 1145 | <div | 1429 | <div |
| 1146 | - class="bar bar-b" | 1430 | + class="bar-comparar" |
| 1147 | - style="height: {((datosGraficoB[i]?.per_capita || 0) / maxComparacion) * 100}%; --bar-color: {colorB}" | 1431 | + style="height: {((datosGraficoB[i]?.per_capita || 0) / maxComparacion) * 100}%; background: {colorB}" |
| 1148 | ></div> | 1432 | ></div> |
| 1149 | </div> | 1433 | </div> |
| 1150 | - <span class="bar-label visible" class:highlight={hoveredYearComparar === año}>{año}</span> | ||
| 1151 | </div> | 1434 | </div> |
| 1152 | {/each} | 1435 | {/each} |
| 1153 | </div> | 1436 | </div> |
| 1154 | </div> | 1437 | </div> |
| 1155 | 1438 | ||
| 1156 | - <div class="chart-legend"> | 1439 | + <!-- Eje X --> |
| 1440 | + <div class="x-axis-comparar"> | ||
| 1441 | + {#each añosComparacion as año, i} | ||
| 1442 | + {@const isFirst = i === 0} | ||
| 1443 | + {@const isLast = i === añosComparacion.length - 1} | ||
| 1444 | + {@const isMid = i === Math.floor(añosComparacion.length / 2) && añosComparacion.length > 5} | ||
| 1445 | + {@const showLabel = isFirst || isLast || isMid || hoveredYearComparar === año} | ||
| 1446 | + <span class="x-label-comparar" class:visible={showLabel}>{año}</span> | ||
| 1447 | + {/each} | ||
| 1448 | + </div> | ||
| 1449 | + </div> | ||
| 1450 | + | ||
| 1451 | + <div class="chart-legend"> | ||
| 1452 | + {#if entidadCompararA} | ||
| 1157 | <span class="legend-item"><span class="legend-dot" style="background: {colorA}"></span>{entidadCompararA.entidad_desc}</span> | 1453 | <span class="legend-item"><span class="legend-dot" style="background: {colorA}"></span>{entidadCompararA.entidad_desc}</span> |
| 1454 | + {/if} | ||
| 1455 | + {#if entidadCompararB} | ||
| 1158 | <span class="legend-item"><span class="legend-dot" style="background: {colorB}"></span>{entidadCompararB.entidad_desc}</span> | 1456 | <span class="legend-item"><span class="legend-dot" style="background: {colorB}"></span>{entidadCompararB.entidad_desc}</span> |
| 1159 | - </div> | 1457 | + {:else} |
| 1458 | + <span class="legend-item legend-pending"><span class="legend-dot" style="background: {colorB}; opacity: 0.3"></span>Selecciona una entidad</span> | ||
| 1459 | + {/if} | ||
| 1460 | + </div> | ||
| 1461 | + {/if} | ||
| 1462 | + </div> | ||
| 1463 | + | ||
| 1464 | + <!-- Mensaje para seleccionar segunda entidad --> | ||
| 1465 | + {#if soloUnaEntidad} | ||
| 1466 | + <div class="comparador-hint comparador-hint-select"> | ||
| 1467 | + <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| 1468 | + <path d="M5 12h14M12 5l7 7-7 7"/> | ||
| 1469 | + </svg> | ||
| 1470 | + <span>Selecciona la segunda entidad arriba para ver la comparación completa.</span> | ||
| 1160 | </div> | 1471 | </div> |
| 1472 | + {/if} | ||
| 1161 | 1473 | ||
| 1162 | - <!-- KPIs comparativos - tabla --> | 1474 | + <!-- KPIs comparativos - tabla (solo cuando hay ambas entidades) --> |
| 1163 | - <div class="kpis-tabla"> | 1475 | + {#if entidadCompararA && entidadCompararB} |
| 1476 | + <div class="kpis-card-comparar"> | ||
| 1164 | <!-- Header --> | 1477 | <!-- Header --> |
| 1165 | <div class="tabla-header"> | 1478 | <div class="tabla-header"> |
| 1166 | <span class="tabla-label"></span> | 1479 | <span class="tabla-label"></span> |
| 1167 | - <span class="tabla-val" style="color: {colorA}">{entidadCompararA.entidad_desc?.slice(0, 20)}{entidadCompararA.entidad_desc?.length > 20 ? '...' : ''}</span> | 1480 | + <span class="tabla-val tabla-entidad" style="color: {colorA}">{entidadCompararA.entidad_desc}</span> |
| 1168 | - <span class="tabla-val" style="color: {colorB}">{entidadCompararB.entidad_desc?.slice(0, 20)}{entidadCompararB.entidad_desc?.length > 20 ? '...' : ''}</span> | 1481 | + <span class="tabla-val tabla-entidad" style="color: {colorB}">{entidadCompararB.entidad_desc}</span> |
| 1169 | </div> | 1482 | </div> |
| 1170 | <!-- Gasto --> | 1483 | <!-- Gasto --> |
| 1171 | <div class="tabla-row"> | 1484 | <div class="tabla-row"> |
| ... | @@ -1192,7 +1505,7 @@ | ... | @@ -1192,7 +1505,7 @@ |
| 1192 | <span class="tabla-val">#{displayRankingB} de {displayNEntidadesB}</span> | 1505 | <span class="tabla-val">#{displayRankingB} de {displayNEntidadesB}</span> |
| 1193 | </div> | 1506 | </div> |
| 1194 | </div> | 1507 | </div> |
| 1195 | - {/if} | 1508 | + {/if} |
| 1196 | 1509 | ||
| 1197 | </main> | 1510 | </main> |
| 1198 | {/if} | 1511 | {/if} |
| ... | @@ -1823,6 +2136,31 @@ | ... | @@ -1823,6 +2136,31 @@ |
| 1823 | border-left-color: var(--theme-accent); | 2136 | border-left-color: var(--theme-accent); |
| 1824 | } | 2137 | } |
| 1825 | 2138 | ||
| 2139 | + :global(html.dark) .tree-node-current .tree-code, | ||
| 2140 | + :global(html.dark) .tree-node-current .tree-name { | ||
| 2141 | + color: #1a1a1a; | ||
| 2142 | + } | ||
| 2143 | + | ||
| 2144 | + /* Dark mode - Context card texts */ | ||
| 2145 | + :global(html.dark) .context-desc, | ||
| 2146 | + :global(html.dark) .context-hint { | ||
| 2147 | + color: rgba(255, 255, 255, 0.6); | ||
| 2148 | + } | ||
| 2149 | + | ||
| 2150 | + /* Dark mode - Definición */ | ||
| 2151 | + :global(html.dark) .def-status, | ||
| 2152 | + :global(html.dark) .def-btn { | ||
| 2153 | + color: rgba(255, 255, 255, 0.7); | ||
| 2154 | + } | ||
| 2155 | + | ||
| 2156 | + :global(html.dark) .def-btn { | ||
| 2157 | + background: rgba(255, 255, 255, 0.1); | ||
| 2158 | + } | ||
| 2159 | + | ||
| 2160 | + :global(html.dark) .def-btn:hover { | ||
| 2161 | + background: rgba(255, 255, 255, 0.15); | ||
| 2162 | + } | ||
| 2163 | + | ||
| 1826 | :global(html.dark) .tree-children { | 2164 | :global(html.dark) .tree-children { |
| 1827 | border-left-color: rgba(201, 167, 81, 0.3); | 2165 | border-left-color: rgba(201, 167, 81, 0.3); |
| 1828 | } | 2166 | } |
| ... | @@ -2086,8 +2424,9 @@ | ... | @@ -2086,8 +2424,9 @@ |
| 2086 | background: var(--theme-fill); | 2424 | background: var(--theme-fill); |
| 2087 | border: 1px solid var(--theme-borde); | 2425 | border: 1px solid var(--theme-borde); |
| 2088 | border-radius: 6px; | 2426 | border-radius: 6px; |
| 2427 | + font-family: 'Qanelas', var(--font-sans); | ||
| 2089 | color: var(--theme-titulo); | 2428 | color: var(--theme-titulo); |
| 2090 | - font-size: 0.875rem; | 2429 | + font-size: 0.8125rem; |
| 2091 | } | 2430 | } |
| 2092 | .search-input:focus { | 2431 | .search-input:focus { |
| 2093 | outline: none; | 2432 | outline: none; |
| ... | @@ -2105,6 +2444,7 @@ | ... | @@ -2105,6 +2444,7 @@ |
| 2105 | padding: 0.625rem 0.75rem; | 2444 | padding: 0.625rem 0.75rem; |
| 2106 | background: transparent; | 2445 | background: transparent; |
| 2107 | border: none; | 2446 | border: none; |
| 2447 | + font-family: 'Qanelas', var(--font-sans); | ||
| 2108 | color: var(--theme-titulo); | 2448 | color: var(--theme-titulo); |
| 2109 | font-size: 0.813rem; | 2449 | font-size: 0.813rem; |
| 2110 | text-align: left; | 2450 | text-align: left; |
| ... | @@ -2176,21 +2516,12 @@ | ... | @@ -2176,21 +2516,12 @@ |
| 2176 | padding-bottom: 1.5rem; | 2516 | padding-bottom: 1.5rem; |
| 2177 | } | 2517 | } |
| 2178 | 2518 | ||
| 2179 | - .chart-section:has(.chart-comparar) { | ||
| 2180 | - margin-bottom: 0; | ||
| 2181 | - } | ||
| 2182 | - | ||
| 2183 | - .chart-section:has(.chart-comparar) .y-axis { | ||
| 2184 | - height: calc(100vh - 380px); | ||
| 2185 | - min-height: 140px; | ||
| 2186 | - max-height: 280px; | ||
| 2187 | - } | ||
| 2188 | - | ||
| 2189 | .chart-top-row { | 2519 | .chart-top-row { |
| 2190 | display: flex; | 2520 | display: flex; |
| 2191 | justify-content: space-between; | 2521 | justify-content: space-between; |
| 2192 | align-items: center; | 2522 | align-items: center; |
| 2193 | margin-bottom: 0.375rem; | 2523 | margin-bottom: 0.375rem; |
| 2524 | + flex-shrink: 0; | ||
| 2194 | } | 2525 | } |
| 2195 | 2526 | ||
| 2196 | .main-title-pills { | 2527 | .main-title-pills { |
| ... | @@ -2223,10 +2554,12 @@ | ... | @@ -2223,10 +2554,12 @@ |
| 2223 | color: var(--theme-titulo); | 2554 | color: var(--theme-titulo); |
| 2224 | margin: 0 0 0.5rem 0; | 2555 | margin: 0 0 0.5rem 0; |
| 2225 | line-height: 1.2; | 2556 | line-height: 1.2; |
| 2557 | + flex-shrink: 0; | ||
| 2226 | } | 2558 | } |
| 2227 | 2559 | ||
| 2228 | .chart-header { | 2560 | .chart-header { |
| 2229 | margin-bottom: 0.5rem; | 2561 | margin-bottom: 0.5rem; |
| 2562 | + flex-shrink: 0; | ||
| 2230 | } | 2563 | } |
| 2231 | 2564 | ||
| 2232 | .chart-title { | 2565 | .chart-title { |
| ... | @@ -2260,6 +2593,7 @@ | ... | @@ -2260,6 +2593,7 @@ |
| 2260 | .chart-wrapper { | 2593 | .chart-wrapper { |
| 2261 | display: flex; | 2594 | display: flex; |
| 2262 | gap: 0.75rem; | 2595 | gap: 0.75rem; |
| 2596 | + position: relative; | ||
| 2263 | } | 2597 | } |
| 2264 | 2598 | ||
| 2265 | .chart-wrapper-scroll { | 2599 | .chart-wrapper-scroll { |
| ... | @@ -2295,10 +2629,6 @@ | ... | @@ -2295,10 +2629,6 @@ |
| 2295 | min-width: max-content; | 2629 | min-width: max-content; |
| 2296 | } | 2630 | } |
| 2297 | 2631 | ||
| 2298 | - .chart-muchos-años .bar-group { | ||
| 2299 | - min-width: 40px; | ||
| 2300 | - } | ||
| 2301 | - | ||
| 2302 | .y-axis { | 2632 | .y-axis { |
| 2303 | display: flex; | 2633 | display: flex; |
| 2304 | flex-direction: column; | 2634 | flex-direction: column; |
| ... | @@ -2390,9 +2720,18 @@ | ... | @@ -2390,9 +2720,18 @@ |
| 2390 | text-align: center; | 2720 | text-align: center; |
| 2391 | min-width: 0; | 2721 | min-width: 0; |
| 2392 | padding: 0.625rem 0.5rem; | 2722 | padding: 0.625rem 0.5rem; |
| 2393 | - background: var(--theme-body); | 2723 | + background: transparent; |
| 2394 | border-radius: 8px; | 2724 | border-radius: 8px; |
| 2395 | - border: 1px solid var(--theme-borde); | 2725 | + border: 1px solid rgba(0, 0, 0, 0.08); |
| 2726 | + } | ||
| 2727 | + | ||
| 2728 | + :global(html.dark) .kpi { | ||
| 2729 | + border-color: rgba(255, 255, 255, 0.1); | ||
| 2730 | + } | ||
| 2731 | + | ||
| 2732 | + :global(html.dark) .kpi-value, | ||
| 2733 | + :global(html.dark) .kpi-label { | ||
| 2734 | + color: rgba(255, 255, 255, 0.7); | ||
| 2396 | } | 2735 | } |
| 2397 | 2736 | ||
| 2398 | .kpi-value { | 2737 | .kpi-value { |
| ... | @@ -2507,6 +2846,20 @@ | ... | @@ -2507,6 +2846,20 @@ |
| 2507 | text-align: right; | 2846 | text-align: right; |
| 2508 | } | 2847 | } |
| 2509 | 2848 | ||
| 2849 | + /* Dark mode - Ranking texts */ | ||
| 2850 | + :global(html.dark) .ranking-desc { | ||
| 2851 | + color: rgba(255, 255, 255, 0.6); | ||
| 2852 | + } | ||
| 2853 | + | ||
| 2854 | + :global(html.dark) .ranking-position, | ||
| 2855 | + :global(html.dark) .ranking-pct { | ||
| 2856 | + color: rgba(255, 255, 255, 0.85); | ||
| 2857 | + } | ||
| 2858 | + | ||
| 2859 | + :global(html.dark) .ranking-name { | ||
| 2860 | + color: rgba(255, 255, 255, 0.7); | ||
| 2861 | + } | ||
| 2862 | + | ||
| 2510 | .see-all { | 2863 | .see-all { |
| 2511 | background: transparent; | 2864 | background: transparent; |
| 2512 | border: 1px solid var(--theme-borde); | 2865 | border: 1px solid var(--theme-borde); |
| ... | @@ -2525,25 +2878,82 @@ | ... | @@ -2525,25 +2878,82 @@ |
| 2525 | } | 2878 | } |
| 2526 | 2879 | ||
| 2527 | /* Comparador inline */ | 2880 | /* Comparador inline */ |
| 2881 | + .main-comparar { | ||
| 2882 | + display: flex; | ||
| 2883 | + flex-direction: column; | ||
| 2884 | + gap: 0.75rem; | ||
| 2885 | + padding: 0.75rem 2rem 1.5rem; | ||
| 2886 | + width: 100%; | ||
| 2887 | + max-width: 1200px; | ||
| 2888 | + margin: 0 auto; | ||
| 2889 | + min-height: calc(100vh - 60px); | ||
| 2890 | + } | ||
| 2891 | + | ||
| 2892 | + .chart-card-comparar { | ||
| 2893 | + background: var(--theme-surface); | ||
| 2894 | + border-radius: 16px; | ||
| 2895 | + padding: 1rem 1.5rem; | ||
| 2896 | + margin-bottom: 0.75rem; | ||
| 2897 | + display: flex; | ||
| 2898 | + flex-direction: column; | ||
| 2899 | + flex: 1; | ||
| 2900 | + min-height: 0; | ||
| 2901 | + } | ||
| 2902 | + | ||
| 2528 | .comparador-selectors { | 2903 | .comparador-selectors { |
| 2529 | display: flex; | 2904 | display: flex; |
| 2530 | - align-items: flex-start; | 2905 | + align-items: center; |
| 2531 | gap: 1rem; | 2906 | gap: 1rem; |
| 2532 | - margin-bottom: 0.75rem; | 2907 | + margin-bottom: 1rem; |
| 2908 | + flex-shrink: 0; | ||
| 2909 | + } | ||
| 2910 | + | ||
| 2911 | + .comparador-search-wrapper { | ||
| 2912 | + flex: 1; | ||
| 2913 | + max-width: 280px; | ||
| 2533 | } | 2914 | } |
| 2534 | 2915 | ||
| 2535 | .comparador-dropdown-container { | 2916 | .comparador-dropdown-container { |
| 2536 | position: relative; | 2917 | position: relative; |
| 2537 | } | 2918 | } |
| 2538 | 2919 | ||
| 2920 | + .selector-btn { | ||
| 2921 | + display: flex; | ||
| 2922 | + align-items: center; | ||
| 2923 | + gap: 0.5rem; | ||
| 2924 | + padding: 0.625rem 1rem; | ||
| 2925 | + background: var(--theme-body); | ||
| 2926 | + border: 1px solid var(--theme-borde); | ||
| 2927 | + border-radius: 8px; | ||
| 2928 | + font-family: 'Qanelas', var(--font-sans); | ||
| 2929 | + font-size: 0.8125rem; | ||
| 2930 | + color: var(--theme-titulo); | ||
| 2931 | + cursor: pointer; | ||
| 2932 | + transition: border-color 0.2s, background 0.2s; | ||
| 2933 | + } | ||
| 2934 | + | ||
| 2935 | + .selector-btn:hover { | ||
| 2936 | + border-color: var(--theme-accent); | ||
| 2937 | + background: var(--theme-surface-hover); | ||
| 2938 | + } | ||
| 2939 | + | ||
| 2539 | .comparador-btn { | 2940 | .comparador-btn { |
| 2540 | width: 100%; | 2941 | width: 100%; |
| 2541 | justify-content: space-between; | 2942 | justify-content: space-between; |
| 2542 | } | 2943 | } |
| 2543 | 2944 | ||
| 2544 | .comparador-panel { | 2945 | .comparador-panel { |
| 2946 | + position: absolute; | ||
| 2947 | + top: calc(100% + 4px); | ||
| 2948 | + left: 0; | ||
| 2545 | width: 100%; | 2949 | width: 100%; |
| 2546 | min-width: 280px; | 2950 | min-width: 280px; |
| 2951 | + background: var(--theme-surface); | ||
| 2952 | + border: 1px solid var(--theme-borde); | ||
| 2953 | + border-radius: 10px; | ||
| 2954 | + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); | ||
| 2955 | + z-index: 100; | ||
| 2956 | + overflow: hidden; | ||
| 2547 | } | 2957 | } |
| 2548 | 2958 | ||
| 2549 | .comparador-placeholder { | 2959 | .comparador-placeholder { |
| ... | @@ -2559,6 +2969,7 @@ | ... | @@ -2559,6 +2969,7 @@ |
| 2559 | } | 2969 | } |
| 2560 | 2970 | ||
| 2561 | .comparador-placeholder p { | 2971 | .comparador-placeholder p { |
| 2972 | + font-family: 'Qanelas', var(--font-sans); | ||
| 2562 | color: var(--theme-texto); | 2973 | color: var(--theme-texto); |
| 2563 | font-size: 0.875rem; | 2974 | font-size: 0.875rem; |
| 2564 | margin: 0; | 2975 | margin: 0; |
| ... | @@ -2568,14 +2979,99 @@ | ... | @@ -2568,14 +2979,99 @@ |
| 2568 | color: var(--theme-texto); | 2979 | color: var(--theme-texto); |
| 2569 | } | 2980 | } |
| 2570 | 2981 | ||
| 2982 | + .comparador-hint { | ||
| 2983 | + display: flex; | ||
| 2984 | + align-items: flex-start; | ||
| 2985 | + gap: 0.5rem; | ||
| 2986 | + padding: 0.75rem 1rem; | ||
| 2987 | + background: rgba(107, 159, 212, 0.1); | ||
| 2988 | + border-radius: 8px; | ||
| 2989 | + margin-bottom: 0.75rem; | ||
| 2990 | + font-family: 'Qanelas', var(--font-sans); | ||
| 2991 | + font-size: 0.8125rem; | ||
| 2992 | + color: #6B9FD4; | ||
| 2993 | + flex-shrink: 0; | ||
| 2994 | + } | ||
| 2995 | + | ||
| 2996 | + .comparador-hint .alert-icon { | ||
| 2997 | + flex-shrink: 0; | ||
| 2998 | + margin-top: 0.1rem; | ||
| 2999 | + } | ||
| 3000 | + | ||
| 3001 | + .comparador-hint span { | ||
| 3002 | + flex: 1; | ||
| 3003 | + } | ||
| 3004 | + | ||
| 3005 | + .comparador-warning { | ||
| 3006 | + display: flex; | ||
| 3007 | + align-items: flex-start; | ||
| 3008 | + gap: 0.5rem; | ||
| 3009 | + padding: 0.75rem 1rem; | ||
| 3010 | + background: rgba(230, 176, 75, 0.1); | ||
| 3011 | + border-radius: 8px; | ||
| 3012 | + margin-bottom: 0.75rem; | ||
| 3013 | + font-family: 'Qanelas', var(--font-sans); | ||
| 3014 | + font-size: 0.8125rem; | ||
| 3015 | + color: #C9A751; | ||
| 3016 | + flex-shrink: 0; | ||
| 3017 | + } | ||
| 3018 | + | ||
| 3019 | + .comparador-warning .alert-icon { | ||
| 3020 | + flex-shrink: 0; | ||
| 3021 | + margin-top: 0.1rem; | ||
| 3022 | + } | ||
| 3023 | + | ||
| 3024 | + .comparador-warning span { | ||
| 3025 | + flex: 1; | ||
| 3026 | + } | ||
| 3027 | + | ||
| 3028 | + .comparador-warning strong { | ||
| 3029 | + color: inherit; | ||
| 3030 | + } | ||
| 3031 | + | ||
| 3032 | + /* Botón cerrar alertas */ | ||
| 3033 | + .alert-close { | ||
| 3034 | + flex-shrink: 0; | ||
| 3035 | + display: flex; | ||
| 3036 | + align-items: center; | ||
| 3037 | + justify-content: center; | ||
| 3038 | + padding: 0.25rem; | ||
| 3039 | + border: none; | ||
| 3040 | + background: transparent; | ||
| 3041 | + color: inherit; | ||
| 3042 | + opacity: 0.6; | ||
| 3043 | + cursor: pointer; | ||
| 3044 | + border-radius: 4px; | ||
| 3045 | + transition: opacity 0.15s, background 0.15s; | ||
| 3046 | + } | ||
| 3047 | + | ||
| 3048 | + .alert-close:hover { | ||
| 3049 | + opacity: 1; | ||
| 3050 | + background: rgba(0, 0, 0, 0.1); | ||
| 3051 | + } | ||
| 3052 | + | ||
| 3053 | + :global(html.dark) .alert-close:hover { | ||
| 3054 | + background: rgba(255, 255, 255, 0.1); | ||
| 3055 | + } | ||
| 3056 | + | ||
| 3057 | + :global(html.dark) .comparador-hint { | ||
| 3058 | + background: rgba(107, 159, 212, 0.15); | ||
| 3059 | + } | ||
| 3060 | + | ||
| 3061 | + :global(html.dark) .comparador-warning { | ||
| 3062 | + background: rgba(201, 167, 81, 0.15); | ||
| 3063 | + } | ||
| 3064 | + | ||
| 2571 | .rango-selector { | 3065 | .rango-selector { |
| 2572 | display: flex; | 3066 | display: flex; |
| 2573 | align-items: center; | 3067 | align-items: center; |
| 2574 | gap: 0.75rem; | 3068 | gap: 0.75rem; |
| 2575 | margin-bottom: 0.75rem; | 3069 | margin-bottom: 0.75rem; |
| 3070 | + flex-shrink: 0; | ||
| 2576 | } | 3071 | } |
| 2577 | 3072 | ||
| 2578 | .rango-label { | 3073 | .rango-label { |
| 3074 | + font-family: 'Qanelas', var(--font-sans); | ||
| 2579 | font-size: 0.75rem; | 3075 | font-size: 0.75rem; |
| 2580 | color: var(--theme-texto); | 3076 | color: var(--theme-texto); |
| 2581 | } | 3077 | } |
| ... | @@ -2587,24 +3083,31 @@ | ... | @@ -2587,24 +3083,31 @@ |
| 2587 | 3083 | ||
| 2588 | .rango-btn { | 3084 | .rango-btn { |
| 2589 | padding: 0.375rem 0.75rem; | 3085 | padding: 0.375rem 0.75rem; |
| 3086 | + font-family: 'Qanelas', var(--font-sans); | ||
| 2590 | font-size: 0.6875rem; | 3087 | font-size: 0.6875rem; |
| 2591 | - font-family: 'DM Mono', monospace; | 3088 | + font-weight: 500; |
| 2592 | color: var(--theme-texto); | 3089 | color: var(--theme-texto); |
| 2593 | background: transparent; | 3090 | background: transparent; |
| 2594 | - border: none; | 3091 | + border: 1px solid transparent; |
| 2595 | border-radius: 6px; | 3092 | border-radius: 6px; |
| 2596 | cursor: pointer; | 3093 | cursor: pointer; |
| 2597 | transition: all 0.2s; | 3094 | transition: all 0.2s; |
| 2598 | } | 3095 | } |
| 2599 | 3096 | ||
| 2600 | .rango-btn:hover { | 3097 | .rango-btn:hover { |
| 2601 | - color: var(--theme-texto); | 3098 | + color: var(--theme-titulo); |
| 2602 | - background: rgba(255,255,255,0.05); | 3099 | + background: var(--theme-surface-hover); |
| 2603 | } | 3100 | } |
| 2604 | 3101 | ||
| 2605 | .rango-btn.active { | 3102 | .rango-btn.active { |
| 2606 | color: var(--theme-titulo); | 3103 | color: var(--theme-titulo); |
| 2607 | - background: rgba(255,255,255,0.1); | 3104 | + background: #e8e8e8; |
| 3105 | + border-color: transparent; | ||
| 3106 | + font-weight: 600; | ||
| 3107 | + } | ||
| 3108 | + | ||
| 3109 | + :global(html.dark) .rango-btn.active { | ||
| 3110 | + background: rgba(255, 255, 255, 0.15); | ||
| 2608 | } | 3111 | } |
| 2609 | 3112 | ||
| 2610 | .dropdown-item:disabled { | 3113 | .dropdown-item:disabled { |
| ... | @@ -2648,63 +3151,118 @@ | ... | @@ -2648,63 +3151,118 @@ |
| 2648 | font-size: 0.75rem; | 3151 | font-size: 0.75rem; |
| 2649 | color: var(--theme-texto); | 3152 | color: var(--theme-texto); |
| 2650 | flex-shrink: 0; | 3153 | flex-shrink: 0; |
| 3154 | + padding: 0.5rem 0; | ||
| 2651 | } | 3155 | } |
| 2652 | 3156 | ||
| 2653 | - .chart-comparar { | 3157 | + .chart-comparar-wrapper { |
| 2654 | - gap: 1.5rem; | 3158 | + position: relative; |
| 2655 | - justify-content: center; | 3159 | + width: 100%; |
| 2656 | - height: calc(100vh - 380px); | 3160 | + flex: 1; |
| 2657 | - min-height: 140px; | 3161 | + min-height: 180px; |
| 2658 | - max-height: 280px; | 3162 | + } |
| 3163 | + | ||
| 3164 | + .chart-comparar-inner { | ||
| 3165 | + position: absolute; | ||
| 3166 | + top: 10px; | ||
| 3167 | + bottom: 30px; | ||
| 3168 | + left: 50px; | ||
| 3169 | + right: 10px; | ||
| 3170 | + } | ||
| 3171 | + | ||
| 3172 | + .y-label-comparar { | ||
| 3173 | + position: absolute; | ||
| 3174 | + left: -50px; | ||
| 3175 | + width: 45px; | ||
| 3176 | + text-align: right; | ||
| 3177 | + transform: translateY(50%); | ||
| 3178 | + font-family: 'Qanelas', var(--font-sans); | ||
| 3179 | + font-size: 0.6875rem; | ||
| 3180 | + color: var(--theme-texto); | ||
| 3181 | + white-space: nowrap; | ||
| 2659 | } | 3182 | } |
| 2660 | 3183 | ||
| 2661 | - .chart-comparar + .chart-legend + .kpis-comparar { | 3184 | + .grid-line-comparar { |
| 2662 | - margin-top: 0; | 3185 | + position: absolute; |
| 3186 | + left: 0; | ||
| 3187 | + right: 0; | ||
| 3188 | + border-top: 0.5px dotted var(--theme-texto); | ||
| 3189 | + opacity: 0.15; | ||
| 3190 | + pointer-events: none; | ||
| 2663 | } | 3191 | } |
| 2664 | 3192 | ||
| 2665 | - .bar-group { | 3193 | + .bars-comparar { |
| 3194 | + position: absolute; | ||
| 3195 | + top: 0; | ||
| 3196 | + left: 0; | ||
| 3197 | + right: 0; | ||
| 3198 | + bottom: 0; | ||
| 2666 | display: flex; | 3199 | display: flex; |
| 2667 | - flex-direction: column; | 3200 | + align-items: flex-end; |
| 2668 | - align-items: center; | 3201 | + gap: 3px; |
| 3202 | + } | ||
| 3203 | + | ||
| 3204 | + .bar-group-comparar { | ||
| 3205 | + flex: 1; | ||
| 2669 | height: 100%; | 3206 | height: 100%; |
| 3207 | + display: flex; | ||
| 3208 | + align-items: flex-end; | ||
| 3209 | + justify-content: center; | ||
| 3210 | + cursor: pointer; | ||
| 2670 | } | 3211 | } |
| 2671 | 3212 | ||
| 2672 | - .bars-pair { | 3213 | + .bar-group-comparar .bars-pair { |
| 2673 | display: flex; | 3214 | display: flex; |
| 2674 | align-items: flex-end; | 3215 | align-items: flex-end; |
| 2675 | - gap: 4px; | 3216 | + gap: 2px; |
| 3217 | + height: 100%; | ||
| 3218 | + width: 100%; | ||
| 3219 | + justify-content: center; | ||
| 3220 | + } | ||
| 3221 | + | ||
| 3222 | + .bar-comparar { | ||
| 2676 | flex: 1; | 3223 | flex: 1; |
| 3224 | + max-width: 24px; | ||
| 3225 | + border-radius: 3px 3px 0 0; | ||
| 3226 | + min-height: 2px; | ||
| 3227 | + transition: opacity 0.15s ease; | ||
| 2677 | } | 3228 | } |
| 2678 | 3229 | ||
| 2679 | - .bar-a, .bar-b { | 3230 | + .bars-comparar:hover .bar-comparar { |
| 2680 | - width: 20px; | 3231 | + opacity: 0.35; |
| 2681 | - border-radius: 4px 4px 0 0; | ||
| 2682 | - min-height: 4px; | ||
| 2683 | - background: var(--bar-color); | ||
| 2684 | - transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), filter 0.25s ease; | ||
| 2685 | } | 3232 | } |
| 2686 | 3233 | ||
| 2687 | - .bar-group.active .bar-a, | 3234 | + .bar-group-comparar.active .bar-comparar { |
| 2688 | - .bar-group.active .bar-b { | 3235 | + opacity: 1; |
| 2689 | - filter: brightness(1.15); | ||
| 2690 | } | 3236 | } |
| 2691 | 3237 | ||
| 2692 | - .bar-group { | 3238 | + .x-axis-comparar { |
| 2693 | - cursor: pointer; | 3239 | + position: absolute; |
| 2694 | - padding: 0.5rem 0.35rem; | 3240 | + bottom: 0; |
| 2695 | - margin: -0.5rem -0.35rem; | 3241 | + left: 50px; |
| 2696 | - border-radius: 6px; | 3242 | + right: 10px; |
| 2697 | - transition: background 0.3s cubic-bezier(0.4, 0, 0.2, 1); | 3243 | + height: 30px; |
| 3244 | + display: flex; | ||
| 3245 | + align-items: center; | ||
| 2698 | } | 3246 | } |
| 2699 | 3247 | ||
| 2700 | - .bar-group.active { | 3248 | + .x-label-comparar { |
| 2701 | - background: rgba(42, 157, 143, 0.15); | 3249 | + flex: 1; |
| 3250 | + text-align: center; | ||
| 3251 | + font-family: 'Qanelas', var(--font-sans); | ||
| 3252 | + font-size: 0.6875rem; | ||
| 3253 | + color: var(--theme-texto); | ||
| 3254 | + opacity: 0; | ||
| 3255 | + transition: opacity 0.2s ease; | ||
| 2702 | } | 3256 | } |
| 2703 | 3257 | ||
| 2704 | - .bar-label.highlight { | 3258 | + .x-label-comparar.visible { |
| 2705 | - color: var(--theme-titulo); | 3259 | + opacity: 1; |
| 2706 | - font-weight: 500; | 3260 | + } |
| 2707 | - transition: color 0.25s ease; | 3261 | + |
| 3262 | + .kpis-card-comparar { | ||
| 3263 | + background: var(--theme-surface); | ||
| 3264 | + border-radius: 16px; | ||
| 3265 | + padding: 0.75rem 1.25rem; | ||
| 2708 | } | 3266 | } |
| 2709 | 3267 | ||
| 2710 | .chart-legend { | 3268 | .chart-legend { |
| ... | @@ -2713,12 +3271,14 @@ | ... | @@ -2713,12 +3271,14 @@ |
| 2713 | gap: 2rem; | 3271 | gap: 2rem; |
| 2714 | margin-top: 0.5rem; | 3272 | margin-top: 0.5rem; |
| 2715 | margin-bottom: 0.75rem; | 3273 | margin-bottom: 0.75rem; |
| 3274 | + flex-shrink: 0; | ||
| 2716 | } | 3275 | } |
| 2717 | 3276 | ||
| 2718 | .legend-item { | 3277 | .legend-item { |
| 2719 | display: flex; | 3278 | display: flex; |
| 2720 | align-items: center; | 3279 | align-items: center; |
| 2721 | gap: 0.5rem; | 3280 | gap: 0.5rem; |
| 3281 | + font-family: 'Qanelas', var(--font-sans); | ||
| 2722 | font-size: 0.75rem; | 3282 | font-size: 0.75rem; |
| 2723 | color: var(--theme-texto); | 3283 | color: var(--theme-texto); |
| 2724 | } | 3284 | } |
| ... | @@ -2729,52 +3289,64 @@ | ... | @@ -2729,52 +3289,64 @@ |
| 2729 | border-radius: 3px; | 3289 | border-radius: 3px; |
| 2730 | } | 3290 | } |
| 2731 | 3291 | ||
| 2732 | - /* KPIs comparativos - tabla */ | 3292 | + .legend-pending { |
| 2733 | - .kpis-tabla { | 3293 | + opacity: 0.5; |
| 2734 | - background: transparent; | 3294 | + font-style: italic; |
| 2735 | - box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08); | ||
| 2736 | - border-radius: 10px; | ||
| 2737 | - padding: 0.5rem 1rem; | ||
| 2738 | } | 3295 | } |
| 2739 | 3296 | ||
| 3297 | + .comparador-hint-select { | ||
| 3298 | + margin-top: 0.75rem; | ||
| 3299 | + } | ||
| 3300 | + | ||
| 3301 | + /* KPIs comparativos - tabla */ | ||
| 3302 | + /* Tabla styles inside kpis-card-comparar */ | ||
| 3303 | + | ||
| 2740 | .tabla-header { | 3304 | .tabla-header { |
| 2741 | display: grid; | 3305 | display: grid; |
| 2742 | - grid-template-columns: 1fr 1fr 1fr; | 3306 | + grid-template-columns: 1fr 1.2fr 1.2fr; |
| 2743 | - gap: 1rem; | 3307 | + gap: 0.75rem; |
| 2744 | padding-bottom: 0.375rem; | 3308 | padding-bottom: 0.375rem; |
| 2745 | border-bottom: 1px solid var(--theme-borde); | 3309 | border-bottom: 1px solid var(--theme-borde); |
| 2746 | - margin-bottom: 0.375rem; | 3310 | + margin-bottom: 0.25rem; |
| 2747 | } | 3311 | } |
| 2748 | 3312 | ||
| 2749 | .tabla-header .tabla-val { | 3313 | .tabla-header .tabla-val { |
| 2750 | - font-family: 'DM Mono', monospace; | 3314 | + font-family: 'Qanelas', var(--font-sans); |
| 2751 | font-size: 0.625rem; | 3315 | font-size: 0.625rem; |
| 3316 | + font-weight: 500; | ||
| 2752 | letter-spacing: 0.05em; | 3317 | letter-spacing: 0.05em; |
| 2753 | text-transform: uppercase; | 3318 | text-transform: uppercase; |
| 2754 | text-align: center; | 3319 | text-align: center; |
| 2755 | } | 3320 | } |
| 2756 | 3321 | ||
| 3322 | + .tabla-entidad { | ||
| 3323 | + font-size: 0.6875rem; | ||
| 3324 | + line-height: 1.3; | ||
| 3325 | + word-break: break-word; | ||
| 3326 | + hyphens: auto; | ||
| 3327 | + } | ||
| 3328 | + | ||
| 2757 | .tabla-row { | 3329 | .tabla-row { |
| 2758 | display: grid; | 3330 | display: grid; |
| 2759 | - grid-template-columns: 1fr 1fr 1fr; | 3331 | + grid-template-columns: 1fr 1.2fr 1.2fr; |
| 2760 | - gap: 1rem; | 3332 | + gap: 0.75rem; |
| 2761 | - padding: 0.25rem 0; | 3333 | + padding: 0.1875rem 0; |
| 2762 | } | 3334 | } |
| 2763 | 3335 | ||
| 2764 | .tabla-label { | 3336 | .tabla-label { |
| 2765 | - font-family: 'DM Mono', monospace; | 3337 | + font-family: 'Qanelas', var(--font-sans); |
| 2766 | - font-size: 0.75rem; | 3338 | + font-size: 0.6875rem; |
| 2767 | font-weight: 500; | 3339 | font-weight: 500; |
| 2768 | color: var(--theme-texto); | 3340 | color: var(--theme-texto); |
| 2769 | display: flex; | 3341 | display: flex; |
| 2770 | align-items: center; | 3342 | align-items: center; |
| 2771 | text-transform: uppercase; | 3343 | text-transform: uppercase; |
| 2772 | - letter-spacing: 0.03em; | 3344 | + letter-spacing: 0.05em; |
| 2773 | } | 3345 | } |
| 2774 | 3346 | ||
| 2775 | .tabla-val { | 3347 | .tabla-val { |
| 2776 | - font-family: 'DM Mono', monospace; | 3348 | + font-family: 'Qanelas', var(--font-sans); |
| 2777 | - font-size: 0.9375rem; | 3349 | + font-size: 0.875rem; |
| 2778 | font-weight: 500; | 3350 | font-weight: 500; |
| 2779 | color: var(--theme-titulo); | 3351 | color: var(--theme-titulo); |
| 2780 | text-align: center; | 3352 | text-align: center; |
| ... | @@ -2947,6 +3519,16 @@ | ... | @@ -2947,6 +3519,16 @@ |
| 2947 | font-size: 0.45rem; | 3519 | font-size: 0.45rem; |
| 2948 | } | 3520 | } |
| 2949 | 3521 | ||
| 3522 | + .main-comparar { | ||
| 3523 | + padding: 0.75rem; | ||
| 3524 | + } | ||
| 3525 | + | ||
| 3526 | + .chart-card-comparar, | ||
| 3527 | + .kpis-card-comparar { | ||
| 3528 | + padding: 1rem; | ||
| 3529 | + border-radius: 12px; | ||
| 3530 | + } | ||
| 3531 | + | ||
| 2950 | .comparador-selectors { | 3532 | .comparador-selectors { |
| 2951 | flex-direction: column; | 3533 | flex-direction: column; |
| 2952 | gap: 0.75rem; | 3534 | gap: 0.75rem; |
| ... | @@ -2956,6 +3538,14 @@ | ... | @@ -2956,6 +3538,14 @@ |
| 2956 | display: none; | 3538 | display: none; |
| 2957 | } | 3539 | } |
| 2958 | 3540 | ||
| 3541 | + .comparador-search-wrapper { | ||
| 3542 | + max-width: 100%; | ||
| 3543 | + } | ||
| 3544 | + | ||
| 3545 | + .chart-container-comparar { | ||
| 3546 | + min-height: 180px; | ||
| 3547 | + } | ||
| 3548 | + | ||
| 2959 | /* Ranking responsive */ | 3549 | /* Ranking responsive */ |
| 2960 | .ranking-title { | 3550 | .ranking-title { |
| 2961 | font-size: 1.25rem; | 3551 | font-size: 1.25rem; | ... | ... |
static/fail.png
0 → 100644
257 KB
static/problem.png
0 → 100644
71.8 KB
-
Please register or login to post a comment