From a8c1d96b545ea13369e6b7a4739c00939f3370f6 Mon Sep 17 00:00:00 2001 From: Karim Khattabi Date: Mon, 23 Feb 2026 10:57:04 +0100 Subject: [PATCH] =?UTF-8?q?adici=C3=B3n=20mapa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- editor_lineas.html | 104 ++++++++ index.html | 23 +- public/data/lineas.json | 519 ++++------------------------------------ src/main.js | 92 +++++-- src/style.css | 117 ++++----- 5 files changed, 277 insertions(+), 578 deletions(-) create mode 100644 editor_lineas.html diff --git a/editor_lineas.html b/editor_lineas.html new file mode 100644 index 0000000..529bde8 --- /dev/null +++ b/editor_lineas.html @@ -0,0 +1,104 @@ + + + + + Bus Editor - EMTUSA Simulator + + + + +
+

Configuración de Línea

+ + + + + + +

Añadir Parada

+
+ + + + + + + + + + +
+ +

Paradas Actuales

+
+
+ +
+

JSON Resultante

+

Copia este código y pégalo en tu archivo .json usando VIM:

+ +
El JSON aparecerá aquí...
+
+ + + + + \ No newline at end of file diff --git a/index.html b/index.html index 41e3307..bd041d7 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,7 @@ Megafonías TsSAEx + @@ -39,7 +40,7 @@ -
+ @@ -49,8 +50,7 @@
campaignExterior
-

Configuración de letrero y megafonía externa para paradas. -

+

Configuración de letrero y megafonía externa.

open_in_newConfigurar Exterior @@ -79,20 +79,13 @@
-
-
edit_noteEditor de Líneas
-
- - +
+
+ mapMapa de Red TsSAEx
-
-
- addAñadir - Parada - Exportar JSON -
-

+        
+
diff --git a/public/data/lineas.json b/public/data/lineas.json index e487d60..ebfffb9 100644 --- a/public/data/lineas.json +++ b/public/data/lineas.json @@ -2,484 +2,57 @@ "L1": { "nombre": "Línea 1", "paradas": [ - { - "id": "zafra", - "nombre": "Zafra", - "enlaces": [ - "todas" - ] - }, - { - "id": "caro_baroja", - "nombre": "Julio Caro Baroja (Aqualon)", - "enlaces": [] - }, - { - "id": "alemania_ruiz_alda", - "nombre": "Avda. Alemania (Ruiz de Alda)", - "enlaces": [] - }, - { - "id": "alemania_plaza_toros", - "nombre": "Avda. Alemania (Plaza de Toros)", - "enlaces": [] - }, - { - "id": "bda_navidad", - "nombre": "Bda. Navidad", - "enlaces": [] - }, - { - "id": "don_bosco", - "nombre": "Don Bosco", - "enlaces": [] - }, - { - "id": "plaza_dolores", - "nombre": "Plaza de los Dolores", - "enlaces": [] - }, - { - "id": "bda_carmen", - "nombre": "Barriada del Carmen", - "enlaces": [] - }, - { - "id": "humilladero", - "nombre": "Humilladero", - "enlaces": [] - }, - { - "id": "cardenas", - "nombre": "Cardeñas", - "enlaces": [] - }, - { - "id": "orden_baja", - "nombre": "Orden Baja", - "enlaces": [ - "L2", - "L3", - "L4", - "L8" - ] - }, - { - "id": "gonzalo_berceo", - "nombre": "Gonzalo de Berceo", - "enlaces": [ - "L8" - ] - }, - { - "id": "plaza_nino_miguel", - "nombre": "Plaza Niño Miguel", - "enlaces": [] - }, - { - "id": "magnolia", - "nombre": "Magnolia", - "enlaces": [ - "L7" - ] - }, - { - "id": "hospital_jrj", - "nombre": "Hospital Juan Ramón Jiménez", - "enlaces": [ - "" - ] - }, - { - "id": "plaza_amapolas", - "nombre": "Plaza las Amapolas", - "enlaces": [] - }, - { - "id": "andalucia_castano", - "nombre": "Av. Andalucía (Castaño Robledo)", - "enlaces": [] - }, - { - "id": "monumento_futbol", - "nombre": "Monumento al Fútbol", - "enlaces": [] - }, - { - "id": "relaciones_laborales", - "nombre": "Relaciones Laborales (Univ.)", - "enlaces": [] - }, - { - "id": "vista_alegre", - "nombre": "Vista Alegre-Universidad", - "enlaces": [] - }, - { - "id": "holea", - "nombre": "Centro Comercial Holea", - "enlaces": [] - }, - { - "id": "cruce_romeralejo", - "nombre": "Cruce Romeralejo", - "enlaces": [] - }, - { - "id": "universidad_artes", - "nombre": "Univ. Avenida de las Artes", - "enlaces": [] - }, - { - "id": "palacio_deportes", - "nombre": "Palacio de Deportes", - "enlaces": [] - }, - { - "id": "higueral", - "nombre": "Higueral (Fuerzas Armadas)", - "enlaces": [] - }, - { - "id": "bda_jose_antonio", - "nombre": "Bda. José Antonio", - "enlaces": [] - }, - { - "id": "isla_chica", - "nombre": "Isla Chica", - "enlaces": [ - "L3", - "L5", - "L6" - ] - }, - { - "id": "las_delicias", - "nombre": "Las Delicias", - "enlaces": [] - }, - { - "id": "el_arbol", - "nombre": "El Árbol", - "enlaces": [] - }, - { - "id": "gasolinera", - "nombre": "Gasolinera", - "enlaces": [] - }, - { - "id": "estacion_ffcc", - "nombre": "Estación de Ferrocarril", - "enlaces": [ - "L2", - "L8" - ] - }, - { - "id": "punto", - "nombre": "El Punto", - "enlaces": [ - "L2" - ] - }, - { - "id": "estacion_sevilla", - "nombre": "Estación de Sevilla", - "enlaces": [] - }, - { - "id": "nuevo_mercado", - "nombre": "Nuevo Mercado", - "enlaces": [ - "L2" - ] - } + { "id": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] }, + { "id": "caro_baroja", "nombre": "Julio Caro Baroja (Aqualon)", "enlaces": [], "coords": [37.2585, -6.9556] }, + { "id": "alemania_ruiz_alda", "nombre": "Avda. Alemania (Ruiz de Alda)", "enlaces": [], "coords": [37.2628, -6.9535] }, + { "id": "alemania_plaza_toros", "nombre": "Avda. Alemania (Plaza de Toros)", "enlaces": [], "coords": [37.2671, -6.9532] }, + { "id": "bda_navidad", "nombre": "Bda. Navidad", "enlaces": [], "coords": [37.2721, -6.9575] }, + { "id": "don_bosco", "nombre": "Don Bosco", "enlaces": [], "coords": [37.2715, -6.9525] }, + { "id": "plaza_dolores", "nombre": "Plaza de los Dolores", "enlaces": [], "coords": [37.2724, -6.9495] }, + { "id": "bda_carmen", "nombre": "Barriada del Carmen", "enlaces": [], "coords": [37.2750, -6.9498] }, + { "id": "humilladero", "nombre": "Humilladero", "enlaces": [], "coords": [37.2798, -6.9501] }, + { "id": "cardenas", "nombre": "Cardeñas", "enlaces": [], "coords": [37.2842, -6.9485] }, + { "id": "orden_baja", "nombre": "Orden Baja", "enlaces": ["L2", "L3", "L4", "L8"], "coords": [37.2785, -6.9492] }, + { "id": "gonzalo_berceo", "nombre": "Gonzalo de Berceo", "enlaces": ["L8"], "coords": [37.2762, -6.9442] }, + { "id": "plaza_nino_miguel", "nombre": "Plaza Niño Miguel", "enlaces": [], "coords": [37.2748, -6.9385] }, + { "id": "magnolia", "nombre": "Magnolia", "enlaces": ["L7"], "coords": [37.2725, -6.9358] }, + { "id": "hospital_jrj", "nombre": "Hospital Juan Ramón Jiménez", "enlaces": [], "coords": [37.2728, -6.9315] }, + { "id": "plaza_amapolas", "nombre": "Plaza las Amapolas", "enlaces": [], "coords": [37.2695, -6.9328] }, + { "id": "andalucia_castano", "nombre": "Av. Andalucía (Castaño Robledo)", "enlaces": [], "coords": [37.2682, -6.9378] }, + { "id": "monumento_futbol", "nombre": "Monumento al Fútbol", "enlaces": [], "coords": [37.2655, -6.9405] }, + { "id": "relaciones_laborales", "nombre": "Relaciones Laborales (Univ.)", "enlaces": [], "coords": [37.2678, -6.9285] }, + { "id": "vista_alegre", "nombre": "Vista Alegre-Universidad", "enlaces": [], "coords": [37.2685, -6.9225] }, + { "id": "holea", "nombre": "Centro Comercial Holea", "enlaces": [], "coords": [37.2698, -6.9185] }, + { "id": "cruce_romeralejo", "nombre": "Cruce Romeralejo", "enlaces": [], "coords": [37.2652, -6.9155] }, + { "id": "universidad_artes", "nombre": "Univ. Avenida de las Artes", "enlaces": [], "coords": [37.2605, -6.9188] }, + { "id": "palacio_deportes", "nombre": "Palacio de Deportes", "enlaces": [], "coords": [37.2575, -6.9245] }, + { "id": "higueral", "nombre": "Higueral (Fuerzas Armadas)", "enlaces": [], "coords": [37.2588, -6.9312] }, + { "id": "bda_jose_antonio", "nombre": "Bda. José Antonio", "enlaces": [], "coords": [37.2562, -6.9352] }, + { "id": "isla_chica", "nombre": "Isla Chica", "enlaces": ["L3", "L5", "L6"], "coords": [37.2545, -6.9382] }, + { "id": "las_delicias", "nombre": "Las Delicias", "enlaces": [], "coords": [37.2528, -6.9425] }, + { "id": "el_arbol", "nombre": "El Árbol", "enlaces": [], "coords": [37.2512, -6.9465] }, + { "id": "gasolinera", "nombre": "Gasolinera", "enlaces": [], "coords": [37.2498, -6.9495] }, + { "id": "estacion_ffcc", "nombre": "Estación de Ferrocarril", "enlaces": ["L2", "L8"], "coords": [37.2485, -6.9452] }, + { "id": "punto", "nombre": "El Punto", "enlaces": ["L2"], "coords": [37.2525, -6.9472] }, + { "id": "estacion_sevilla", "nombre": "Estación de Sevilla", "enlaces": [], "coords": [37.2515, -6.9515] }, + { "id": "nuevo_mercado", "nombre": "Nuevo Mercado", "enlaces": ["L2"], "coords": [37.2535, -6.9545] } ] }, "L2": { "nombre": "Línea 2", "paradas": [ - { - "id": "zafra", - "nombre": "Zafra", - "enlaces": [ - "todas" - ] - }, - { - "id": "nuevo-mercado", - "nombre": "Nuevo Mercado", - "enlaces": [ - "L6" - ] - }, - { - "id": "villa-madrid", - "nombre": "Villa de Madrid", - "enlaces": [ - "L6" - ] - }, - { - "id": "avenida-italia", - "nombre": "Avenida Italia Estación de Sevilla", - "enlaces": [ - "L6" - ] - }, - { - "id": "el-punto", - "nombre": "El Punto", - "enlaces": [ - "L6" - ] - }, - { - "id": "estacion-ferrocarril", - "nombre": "Estación de Ferrocarril", - "enlaces": [ - "L1", - "L5", - "L6", - "L7", - "L7H", - "L7HP", - "L8" - ] - }, - { - "id": "juzgados", - "nombre": "Juzgados", - "enlaces": [ - "L6" - ] - }, - { - "id": "barrio-obrero", - "nombre": "Barrio Obrero", - "enlaces": [] - }, - { - "id": "el-porvenir", - "nombre": "El Porvenir", - "enlaces": [ - "L4" - ] - }, - { - "id": "las-delicias", - "nombre": "Las Delicias", - "enlaces": [ - "L4" - ] - }, - { - "id": "isla-chica", - "nombre": "Isla Chica", - "enlaces": [ - "L4" - ] - }, - { - "id": "jose-antonio", - "nombre": "Bda. José Antonio", - "enlaces": [] - }, - { - "id": "fuerzas-armadas", - "nombre": "Fuerzas Armadas Los Rosales", - "enlaces": [] - }, - { - "id": "palacio-deportes", - "nombre": "Palacio de Deportes", - "enlaces": [ - "L6" - ] - }, - { - "id": "ciencias-educacion", - "nombre": "Ciencias de la Educación (Universidad)", - "enlaces": [] - }, - { - "id": "biblioteca-universidad", - "nombre": "Biblioteca (Universidad)", - "enlaces": [] - }, - { - "id": "monumento-futbol", - "nombre": "Monumento al Fútbol", - "enlaces": [ - "L1", - "L7", - "L7H", - "L7HP" - ] - }, - { - "id": "relaciones-laborales", - "nombre": "Relaciones Laborales (Universidad)", - "enlaces": [ - "L1", - "L6", - "L7", - "L7H", - "L7HP" - ] - }, - { - "id": "vista-alegre", - "nombre": "Vista Alegre-Universidad", - "enlaces": [ - "L1", - "L5", - "L6", - "L7", - "L7H", - "L7HP" - ] - }, - { - "id": "holea", - "nombre": "Centro Comercial Holea", - "enlaces": [ - "L1", - "L5", - "L6", - "L7", - "L7H", - "L7HP" - ] - }, - { - "id": "plaza-amapolas", - "nombre": "Plaza las Amapolas", - "enlaces": [ - "L6", - "L7", - "L7H", - "L7HP" - ] - }, - { - "id": "hospital", - "nombre": "Hospital JRJ", - "enlaces": [ - "L1", - "L5", - "L6", - "L7", - "L7H", - "L7HP", - "L8" - ] - }, - { - "id": "magnolia", - "nombre": "Magnolia", - "enlaces": [ - "L8" - ] - }, - { - "id": "orden-alta", - "nombre": "Orden Alta", - "enlaces": [ - "L4" - ] - }, - { - "id": "gonzalo-berceo-alto", - "nombre": "Gonzalo de Berceo (Alto)", - "enlaces": [ - "L8" - ] - }, - { - "id": "gonzalo-berceo-bajo", - "nombre": "Gonzalo de Berceo (Bajo)", - "enlaces": [ - "L8" - ] - }, - { - "id": "orden-baja", - "nombre": "Orden Baja", - "enlaces": [ - "L1", - "L3", - "L4", - "L8" - ] - }, - { - "id": "legion-espanola", - "nombre": "Legión Española", - "enlaces": [] - }, - { - "id": "cardenas", - "nombre": "Cardeñas", - "enlaces": [] - }, - { - "id": "humilladero", - "nombre": "Humilladero", - "enlaces": [] - }, - { - "id": "barriada-carmen", - "nombre": "Barriada del Carmen", - "enlaces": [] - }, - { - "id": "santa-lucia", - "nombre": "Santa Lucía", - "enlaces": [] - }, - { - "id": "santa-eulalia", - "nombre": "Santa Eulalia", - "enlaces": [] - }, - { - "id": "barriada-navidad", - "nombre": "Bda. Navidad", - "enlaces": [] - }, - { - "id": "molino-vega", - "nombre": "Molino de la Vega", - "enlaces": [ - "L3", - "L4", - "L6" - ] - }, - { - "id": "paseo-palmeras", - "nombre": "Paseo de las Palmeras", - "enlaces": [ - "L3", - "L4", - "L6" - ] - }, - { - "id": "aqualon", - "nombre": "Julio Caro Baroja (Aqualon)", - "enlaces": [] - }, - { - "id": "zafra", - "nombre": "Zafra", - "enlaces": [ - "todas" - ] - } + { "id": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] }, + { "id": "nuevo-mercado", "nombre": "Nuevo Mercado", "enlaces": ["L6"], "coords": [37.2535, -6.9545] }, + { "id": "villa-madrid", "nombre": "Villa de Madrid", "enlaces": ["L6"], "coords": [37.2518, -6.9562] }, + { "id": "avenida-italia", "nombre": "Avenida Italia Estación de Sevilla", "enlaces": ["L6"], "coords": [37.2515, -6.9515] }, + { "id": "el-punto", "nombre": "El Punto", "enlaces": ["L6"], "coords": [37.2525, -6.9472] }, + { "id": "estacion-ferrocarril", "nombre": "Estación de Ferrocarril", "enlaces": ["L1", "L5", "L6", "L8"], "coords": [37.2485, -6.9452] }, + { "id": "barrio-obrero", "nombre": "Barrio Obrero", "enlaces": [], "coords": [37.2548, -6.9362] }, + { "id": "isla-chica", "nombre": "Isla Chica", "enlaces": ["L4"], "coords": [37.2545, -6.9382] }, + { "id": "hospital", "nombre": "Hospital JRJ", "enlaces": ["L1", "L8"], "coords": [37.2728, -6.9315] }, + { "id": "orden-alta", "nombre": "Orden Alta", "enlaces": ["L4"], "coords": [37.2782, -6.9422] }, + { "id": "molino-vega", "nombre": "Molino de la Vega", "enlaces": ["L3", "L4", "L6"], "coords": [37.2612, -6.9555] }, + { "id": "zafra_fin", "id_real": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] } ] } } \ No newline at end of file diff --git a/src/main.js b/src/main.js index 046555b..a1aeb21 100644 --- a/src/main.js +++ b/src/main.js @@ -5,6 +5,8 @@ let dbInt = {}; let dbExt = { lineas: {} }; let audioActual = null; let mapa = null; +let marcadoresActuales = []; // Para limpiar el mapa al cambiar de línea +let rutaActual = null; // Para limpiar la línea trazada const get = (id) => document.getElementById(id); @@ -36,15 +38,60 @@ function play(cola, volId = 'vol') { }); } -// --- 2. INICIO Y MAPA --- +// --- 2. LÓGICA DEL MAPA --- function inicializarMapa() { - if (get('map') && !mapa) { - mapa = L.map('map', { zoomControl: false }).setView([37.2614, -6.9447], 14); + const mapContainer = get('map'); + if (mapContainer && !mapa) { + mapa = L.map('map', { + zoomControl: false, + attributionControl: false + }).setView([37.2614, -6.9447], 14); + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(mapa); L.control.zoom({ position: 'bottomright' }).addTo(mapa); } } +function actualizarMapa(paradas) { + // 1. Limpiar elementos previos + marcadoresActuales.forEach(m => mapa.removeLayer(m)); + marcadoresActuales = []; + if (rutaActual) mapa.removeLayer(rutaActual); + + const puntos = []; + + // 2. Crear nuevos marcadores + paradas.forEach(p => { + if (p.coords) { + const marker = L.circleMarker(p.coords, { + radius: 8, + fillColor: "#6d5e00", + color: "#ffffff", + weight: 2, + opacity: 1, + fillOpacity: 0.8 + }).addTo(mapa).bindPopup(`${p.nombre}`); + + marcadoresActuales.push(marker); + puntos.push(p.coords); + } + }); + + // 3. Dibujar la línea de trayecto + if (puntos.length > 0) { + rutaActual = L.polyline(puntos, { + color: '#6d5e00', + weight: 4, + opacity: 0.6, + dashArray: '10, 10' + }).addTo(mapa); + + // 4. Ajustar vista para que quepa toda la línea + mapa.fitBounds(L.latLngBounds(puntos), { padding: [50, 50] }); + } +} + +// --- 3. INICIO Y CARGA DE DATOS --- async function init() { try { const [resInt, resExt] = await Promise.all([ @@ -54,13 +101,12 @@ async function init() { dbInt = await resInt.json(); dbExt = await resExt.json(); - // Rellenar selector de línea INTERIOR (desde lineas.json) + // Rellenar selector de línea INTERIOR const lineasIntHTML = Object.keys(dbInt).map(id => `
${id}
`).join(''); if (get('int-linea')) get('int-linea').innerHTML = lineasIntHTML; - // Rellenar selector de línea EXTERIOR (desde exterior.json exclusivamente) - // Esto arregla que no se lean las líneas L3, L3CE, etc. + // Rellenar selector de línea EXTERIOR if (get('ext-linea')) { const lineasExtHTML = Object.keys(dbExt.lineas).map(id => `
${id}
`).join(''); @@ -80,17 +126,20 @@ async function init() { } finally { get('loading-screen').style.display = 'none'; get('app').style.display = 'flex'; - if (mapa) mapa.invalidateSize(); + setTimeout(() => { if (mapa) mapa.invalidateSize(); }, 250); } } -// --- 3. LÓGICA DE INTERIOR --- +// --- 4. EVENTOS PANEL INTERIOR --- get('int-linea')?.addEventListener('change', (e) => { const linea = dbInt[e.target.value]; if (linea && get('int-parada')) { get('int-parada').innerHTML = linea.paradas.map(p => `
${p.nombre}
`).join(''); get('int-parada').disabled = false; + + // Actualizar Waypoints en el mapa + actualizarMapa(linea.paradas); } }); @@ -102,6 +151,11 @@ get('btn-int')?.addEventListener('click', () => { const paradaData = dbInt[lId].paradas.find(p => p.id === pId); const tipo = document.querySelector('md-radio[name="tipo"][checked]')?.value || "actual"; + // Mover el mapa a la parada anunciada + if (paradaData.coords) { + mapa.flyTo(paradaData.coords, 16); + } + let cola = [ { file: `audio/parada_${tipo}.wav`, gap: 150 }, { file: `audio/${pId}.wav`, gap: 350 } @@ -124,11 +178,11 @@ get('btn-int')?.addEventListener('click', () => { play(cola, 'vol'); }); -// --- 4. LÓGICA DE EXTERIOR --- +// --- 5. EVENTOS PANEL EXTERIOR --- +get('btn-abrir-exterior').onclick = () => get('dialog-exterior').show(); get('ext-linea')?.addEventListener('change', (e) => { - const lineaId = e.target.value; // Ejemplo: "L3" - // Buscamos directamente en el objeto lineas del exterior.json + const lineaId = e.target.value; const datosLinea = dbExt.lineas[lineaId]; const selDest = get('ext-destino'); @@ -136,26 +190,17 @@ get('ext-linea')?.addEventListener('change', (e) => { selDest.innerHTML = datosLinea.destinos.map(d => `
${d}
`).join(''); selDest.disabled = false; - } else { - if (selDest) { - selDest.innerHTML = ""; - selDest.disabled = true; - } } }); get('btn-reproducir-ext')?.addEventListener('click', () => { - const linea = get('ext-linea').value; // Ejemplo: "L1" + const linea = get('ext-linea').value; const destino = get('ext-destino').value; const coche = get('ext-coche').value; - if (!linea || !destino || !coche) { - alert("Por favor, selecciona línea, destino y coche"); - return; - } + if (!linea || !destino || !coche) return; const destFile = destino.toLowerCase().replace(/ /g, "_"); - // Quitamos la 'L' para el nombre del audio si tus audios son "linea_1.wav" const lineaNum = linea.replace('L', ''); play([ @@ -165,8 +210,7 @@ get('btn-reproducir-ext')?.addEventListener('click', () => { ], 'vol-ext'); }); -// --- 5. BOTONES ESPECIALES --- -get('btn-abrir-exterior').onclick = () => get('dialog-exterior').show(); +// --- 6. BOTONES ESPECIALES --- get('btn-colision').onclick = () => play([{ file: `audio/colision.wav` }]); get('btn-hora').onclick = () => play([{ file: `audio/hora_salida.wav` }]); get('btn-saldo').onclick = () => play([{ file: `audio/atencion_saldo.wav` }]); diff --git a/src/style.css b/src/style.css index d8847bb..145768d 100644 --- a/src/style.css +++ b/src/style.css @@ -22,15 +22,13 @@ body { md-icon { font-family: 'Material Symbols Outlined' !important; } -/* --- MARCA Megafonías TsSAEx --- */ +/* --- MARCA --- */ .brand-name { color: var(--md-sys-color-primary); - text-transform: none !important; - font-variant: normal !important; letter-spacing: -0.5px; } -/* --- SPLASH SCREEN RESPONSIVE --- */ +/* --- SPLASH SCREEN --- */ #loading-screen { position: fixed; inset: 0; @@ -39,7 +37,6 @@ md-icon { font-family: 'Material Symbols Outlined' !important; } justify-content: center; align-items: center; z-index: 2000; - transition: opacity 0.5s ease; } .loading-content { @@ -47,31 +44,17 @@ md-icon { font-family: 'Material Symbols Outlined' !important; } flex-direction: column; align-items: center; width: 90%; - max-width: 400px; -} - -.splash-logo { - width: 100%; - max-width: 250px; - height: auto; - margin-bottom: 30px; - animation: pulse 2s infinite ease-in-out; -} - -.loading-title { - font-size: 2rem; - margin-bottom: 24px; - text-align: center; } +.splash-logo { width: 200px; height: auto; margin-bottom: 30px; animation: pulse 2s infinite ease-in-out; } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } } -/* --- LAYOUT GRID --- */ +/* --- LAYOUT PRINCIPAL (DASHBOARD) --- */ #app { - display: none; /* Controlado por JS */ + display: none; flex-direction: column; padding: 24px; - max-width: 1400px; + max-width: 1600px; margin: 0 auto; gap: 24px; } @@ -80,11 +63,18 @@ md-icon { font-family: 'Material Symbols Outlined' !important; } .dashboard-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + /* 400px para botones, 1fr para el mapa */ + grid-template-columns: 400px 1fr; + grid-template-areas: + "interior mapa" + "exterior mapa" + "especiales mapa" + "volumen mapa"; gap: 20px; align-items: start; } +/* --- TARJETAS --- */ .m3-card { background-color: var(--md-sys-color-surface-container); border-radius: 28px; @@ -95,9 +85,32 @@ md-icon { font-family: 'Material Symbols Outlined' !important; } box-shadow: 0 1px 3px rgba(0,0,0,0.1); } +/* Asignación de áreas */ +.m3-card:nth-child(1) { grid-area: interior; } +.m3-card:nth-child(2) { grid-area: exterior; } +.m3-card:nth-child(3) { grid-area: especiales; } +.m3-card:nth-child(4) { grid-area: volumen; } + .m3-card.secondary { background-color: var(--md-sys-color-secondary-container); } .m3-card.specials-card { background-color: #fceee9; } +/* --- ESTILO ESPECÍFICO DEL MAPA --- */ +.map-card { + grid-area: mapa; + padding: 0; /* Para que el mapa llegue al borde */ + overflow: hidden; + height: 800px; /* Altura fija para que luzca en desktop */ + position: sticky; + top: 24px; +} + +#map { + width: 100%; + height: 100%; + z-index: 1; +} + +/* --- CONTROLES INTERNOS --- */ .vol-header { display: flex; align-items: center; gap: 10px; font-weight: 500; opacity: 0.8; } .radio-container { @@ -108,53 +121,25 @@ md-icon { font-family: 'Material Symbols Outlined' !important; } padding: 16px; border-radius: 20px; } -.radio-container label { display: flex; align-items: center; gap: 12px; cursor: pointer; } -/* --- ESTILOS REGULACIÓN --- */ -#container-regulacion { - /* display: none; El JS lo cambia a flex */ - background: rgba(109, 94, 0, 0.08); /* Uso del color primary con baja opacidad */ - padding: 12px 16px; - border-radius: 20px; - border: 1px dashed var(--md-sys-color-primary); - animation: slideIn 0.3s ease-out; -} - -@keyframes slideIn { - from { opacity: 0; transform: translateY(-10px); } - to { opacity: 1; transform: translateY(0); } -} - -/* --- BOTONES Y ESPECIALES --- */ .button-grid-specials { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .danger-btn { --md-filled-tonal-button-container-color: var(--md-sys-color-error-container); } -/* --- EDITOR Y DIALOG --- */ -.editor-controls { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } -.parada-row { - display: grid; - grid-template-columns: 1fr 1fr 1fr 40px; - gap: 8px; - margin-top: 10px; - align-items: center; -} -.editor-actions { display: flex; gap: 10px; margin-top: 10px; } - -.dialog-layout { display: flex; flex-direction: column; gap: 16px; min-width: 300px; padding-top: 12px; } - -.json-preview { - background: #1e1e1e; color: #c5e1a5; padding: 15px; border-radius: 12px; - font-size: 0.8rem; overflow-x: auto; display: none; -} - -/* Responsividad extra */ -@media (min-width: 1100px) { - .editor-card { grid-column: span 2; } +/* --- RESPONSIVIDAD --- */ +@media (max-width: 1100px) { + .dashboard-grid { + grid-template-columns: 1fr; + grid-template-areas: + "mapa" + "interior" + "exterior" + "especiales" + "volumen"; + } + .map-card { height: 400px; position: static; } } @media (max-width: 480px) { - .dashboard-grid { grid-template-columns: 1fr; } - .editor-controls { grid-template-columns: 1fr; } - .parada-row { grid-template-columns: 1fr 1fr; } - .top-app-bar h1 { font-size: 1.8rem; } + .top-app-bar h1 { font-size: 1.6rem; } + .m3-card { padding: 16px; border-radius: 20px; } } \ No newline at end of file