PageSourceSearch

https://lunarapp-urania-production.up.railway.app/eclipses

html lunarapp-urania-production.up.railway.app collected 2026-10-03 12:12:52 UTC 37,400 bytes, 560 lines download raw bytes

1<!DOCTYPE html>
2<html lang="es">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <meta name="description" content="Próximos Eclipses Lunares y Solares">
7    <meta name="theme-color" content="#1a1a2e">
8    <title>Eclipses - Lunar App</title>
9    <link rel="preconnect" href="https://fonts.googleapis.com">
10    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11    <link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600&family=Cormorant+Garamond:wght@300;400;600&display=swap" rel="stylesheet">
12    <link rel="manifest" href="/static/manifest.json">
13    <link rel="stylesheet" href="/static/css/style.css">
14    
15    
16    <!-- AstroChart Library -->
17    
17<script src="https://unpkg.com/@astrodraw/astrochart"></script>
17
18    
19    <!-- Leaflet.js para Astrocartografía -->
20    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
21    
21<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
21
22    
23    <style>
24        .modal-carta{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.92);z-index:1000;overflow-y:auto;padding:0.5rem}
25        .modal-carta.active{display:block}
26        .modal-carta-contenido{max-width:960px;margin:0 auto;background:#0f0f1e;border-radius:12px;border:1px solid #2a2a4a;overflow:hidden}
27        .modal-carta-header{display:flex;justify-content:space-between;align-items:center;padding:1rem 1.5rem;background:linear-gradient(135deg,#1a1a3e,#0d0d2a);border-bottom:1px solid #d4af37}
28        .modal-carta-header h2{color:#d4af37;font-family:'Cinzel',serif;font-size:1.1rem;margin:0}
29        .modal-carta-cerrar{background:none;border:none;color:#eee;font-size:2rem;cursor:pointer;padding:0 0.5rem}
30        .modal-carta-body{padding:1rem 1.5rem}
31        .tabs-container{display:flex;gap:0.4rem;margin-bottom:1.2rem;flex-wrap:wrap}
32        .tab-btn{padding:0.5rem 1rem;background:#1a1a3e;border:1px solid #2a2a4a;border-radius:6px;color:#ccc;cursor:pointer;font-size:0.85rem;transition:all 0.2s}
33        .tab-btn.active{background:linear-gradient(135deg,#d4af37,#b8962e);color:#0f0f1e;font-weight:600;border-color:#d4af37}
34        .tab-content{display:none}.tab-content.active{display:block}
35        #astrochart-container{display:flex;justify-content:center;overflow:hidden}
36        #astrochart-container svg{max-width:100%;height:auto}
37        .tabla-posiciones{width:100%;border-collapse:collapse;font-size:0.9rem}
38        .tabla-posiciones th{background:#1a1a3e;color:#d4af37;padding:0.6rem;text-align:left;font-weight:600}
39        .tabla-posiciones td{padding:0.5rem 0.6rem;border-bottom:1px solid rgba(255,255,255,0.06)}
40        .tabla-posiciones tr:nth-child(even){background:rgba(255,255,255,0.03)}
41        .retrogrado{color:#ff6b6b}
42        .aspecto-row{display:flex;justify-content:space-between;padding:0.4rem 0;border-bottom:1px solid rgba(255,255,255,0.05);font-size:0.85rem}
43        .dato-tecnico{display:flex;justify-content:space-between;padding:0.6rem 0;border-bottom:1px solid rgba(255,255,255,0.06)}
44        .dato-tecnico-label{color:#888}.dato-tecnico-valor{color:#d4af37;font-weight:600}
45        .ubicacion-bar{display:flex;gap:0.5rem;align-items:center;flex-wrap:wrap;margin-bottom:1rem;padding:0.7rem;background:#1a1a3e;border-radius:8px;font-size:0.85rem}
46        .ubicacion-bar span{color:#888}.ubicacion-bar strong{color:#d4af37}
47        .btn-ubicacion{padding:0.35rem 0.7rem;background:#2a2a4a;border:none;border-radius:4px;color:#ccc;cursor:pointer;font-size:0.8rem}
48        .btn-ubicacion:hover{background:#d4af37;color:#0f0f1e}
49        .eclipse-clickeable{cursor:pointer;transition:transform 0.2s,box-shadow 0.2s}
50        .eclipse-clickeable:hover{transform:translateY(-2px);box-shadow:0 4px 15px rgba(212,175,55,0.15)}
51        .casas-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0.5rem}
52        .casa-item{padding:0.5rem;background:rgba(255,255,255,0.03);border-radius:4px;font-size:0.85rem}
53        .casa-num{color:#d4af37;font-weight:600}
54        #astrocarto-map{width:100%;height:450px;border-radius:8px;background:#1a2332;z-index:1}
55        .astrocarto-leyenda{display:flex;flex-wrap:wrap;gap:0.6rem;margin-top:0.8rem;padding:0.6rem;background:rgba(0,0,0,0.3);border-radius:6px;font-size:0.78rem}
56        .astrocarto-leyenda-item{display:flex;align-items:center;gap:0.3rem}
57        .astrocarto-leyenda-linea{width:24px;height:3px;border-radius:2px}
58        .astrocarto-info{margin-top:0.6rem;padding:0.6rem;background:rgba(212,175,55,0.06);border-radius:6px;font-size:0.8rem;color:#888;border-left:3px solid #d4af37}
59        @media(max-width:768px){
60            #astrocarto-map{height:350px}
61            .astrocarto-leyenda{font-size:0.72rem;gap:0.4rem}
62        }
63    </style>
64</head>
65<body>
66    <header class="header">
67        <div class="container">
68            <div class="logo-section">
69                <img src="/static/images/logo_urania.png" alt="La Nación de Urania" class="logo-img">
70                <div class="logo-text-container">
71                    <h1 class="logo">LA NACIÓN DE URANIA</h1>
72                    <p class="logo-subtitle">Organización Astrológica</p>
73                </div>
74            </div>
75            <button class="menu-toggle" id="menu-toggle" aria-label="Abrir menú">
76                <span class="hamburger-line"></span><span class="hamburger-line"></span><span class="hamburger-line"></span>
77            </button>
78            <nav class="nav" id="main-nav">
79                <a href="/" class="nav-link">Inicio</a>
80                <a href="/calendario" class="nav-link">Calendario</a>
81                <a href="/eclipses" class="nav-link active">Eclipses</a>
82                <a href="/streaming" class="nav-link">Streaming</a>
83                <a href="/carta-natal" class="nav-link">Carta Natal</a>
84                <a href="/notificaciones" class="nav-link">Notificaciones</a>
85            </nav>
86        </div>
87    </header>
88    <div class="menu-overlay" id="menu-overlay"></div>
89
90    <!-- Modal Carta Astral -->
91    <div class="modal-carta" id="modal-carta">
92        <div class="modal-carta-contenido">
93            <div class="modal-carta-header">
94                <h2 id="carta-titulo">Carta del Eclipse</h2>
95                <button class="modal-carta-cerrar" id="btn-cerrar-carta">&times;</button>
96            </div>
97            <div class="modal-carta-body">
98                <div class="ubicacion-bar">
99                    <span>📍</span><strong id="ubicacion-texto">Detectando...</strong>
100                    <button class="btn-ubicacion" onclick="cambiarUbicacion()">📍 Cambiar</button>
101                    <button class="btn-ubicacion" onclick="usarGPS()">🛰️ GPS</button>
102                </div>
103                <div class="tabs-container">
104                    <button class="tab-btn active" data-tab="carta">🔮 Carta</button>
105                    <button class="tab-btn" data-tab="posiciones">📊 Posiciones</button>
106                    <button class="tab-btn" data-tab="aspectos">⚡ Aspectos</button>
107                    <button class="tab-btn" data-tab="casas">🏠 Casas</button>
108                    <button class="tab-btn" data-tab="tecnicos">📋 Técnicos</button>
109                    <button class="tab-btn" data-tab="astrocarto">🌍 Astrocartografía</button>
110                </div>
111                <div class="tab-content active" id="tab-carta">
112                    <div id="astrochart-container"></div>
113                </div>
114                <div class="tab-content" id="tab-posiciones">
115                    <table class="tabla-posiciones" id="tabla-planetas">
116                        <thead><tr><th>Planeta</th><th>Signo</th><th>Grado</th><th>Long.</th><th></th></tr></thead><tbody></tbody>
117                    </table>
118                </div>
119                <div class="tab-content" id="tab-aspectos"><div id="aspectos-lista"></div></div>
120                <div class="tab-content" id="tab-casas"><div id="casas-info"></div></div>
121                <div class="tab-content" id="tab-tecnicos"><div id="datos-tecnicos"></div></div>
122                <div class="tab-content" id="tab-astrocarto">
123                    <div id="astrocarto-map"></div>
124                    <div class="astrocarto-leyenda" id="astrocarto-leyenda"></div>
125                    <div class="astrocarto-info">
126                        Las líneas muestran dónde cada planeta es angular (ASC subiendo, DSC poniéndose, MC culminando, IC en nadir) en el momento exacto del eclipse. Tu ubicación actual está marcada con 📍.
127                    </div>
128                </div>
129            </div>
130        </div>
131    </div>
132
133    <main class="main-container">
134        <section class="card">
135            <h2 class="card-title" style="text-align:center;">🌑 Próximos Eclipses 2025-2026 🌕</h2>
136            <p style="text-align:center;color:var(--color-texto-secundario);margin-top:0.5rem;">Toca un eclipse para ver su carta astral calculada para tu ubicación</p>
137        </section>
138        <div id="loading" class="loading-container"><div class="loading-spinner"></div><p>Calculando eclipses...</p></div>
139        <div id="eclipses-container" style="display:none;"></div>
140        <div class="acciones"><button class="btn-actualizar" onclick="window.location.href='/'">← Volver a Inicio</button></div>
141    </main>
142
143    <footer class="footer">
144        <p style="font-family:'Cinzel',serif;color:var(--color-dorado);margin-bottom:0.5rem;">© 2025 La Nación de Urania</p>
145        <p style="margin:0.25rem 0;">San Carlos de Bariloche, Argentina</p>
146        <p style="margin:0.25rem 0;"><a href="https://www.escuelaurania.com" target="_blank" style="color:var(--color-enlace);text-decoration:none;">www.escuelaurania.com</a></p>
147    </footer>
148
149    
149<script>
150    const API_BASE = window.location.origin;
151    const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
152    let userLat = -41.1335, userLon = -71.3103, userCiudad = 'San Carlos de Bariloche';
153    let currentEclipseData = null;
154    var astrocartoLoaded = false;
155    var astrocartoMap = null;
156
157    const SIGNOS_SIMBOLO = {'Aries':'♈','Tauro':'♉','Géminis':'♊','Cáncer':'♋','Leo':'♌','Virgo':'♍','Libra':'♎','Escorpio':'♏','Sagitario':'♐','Capricornio':'♑','Acuario':'♒','Piscis':'♓'};
158    const PLANETAS_SIMBOLO = {'Sol':'☉','Luna':'☽','Mercurio':'☿','Venus':'♀','Marte':'♂','Júpiter':'♃','Saturno':'♄','Urano':'♅','Neptuno':'♆','Plutón':'♇','Nodo Norte':'☊','Nodo Sur':'☋'};
159
160    // ===== GEO =====
161    function obtenerUbicacion(){
162        if(navigator.geolocation){
163            navigator.geolocation.getCurrentPosition(pos=>{
164                userLat=pos.coords.latitude;userLon=pos.coords.longitude;
165                userCiudad=userLat.toFixed(2)+'°, '+userLon.toFixed(2)+'°';
166                fetch('https://nominatim.openstreetmap.org/reverse?lat='+userLat+'&lon='+userLon+'&format=json&accept-language=es')
167                .then(r=>r.json()).then(d=>{if(d.address)userCiudad=d.address.city||d.address.town||d.address.village||userCiudad;}).catch(function(){});
168            },function(){},{timeout:5000});
169        }
170    }
171    function usarGPS(){
172        if(!navigator.geolocation){alert('GPS no disponible');return;}
173        navigator.geolocation.getCurrentPosition(function(pos){
174            userLat=pos.coords.latitude;userLon=pos.coords.longitude;
175            fetch('https://nominatim.openstreetmap.org/reverse?lat='+userLat+'&lon='+userLon+'&format=json&accept-language=es')
176            .then(r=>r.json()).then(function(d){if(d.address)userCiudad=d.address.city||d.address.town||d.address.village||userLat.toFixed(2)+'°, '+userLon.toFixed(2)+'°';if(currentEclipseData)recargarCarta();})
177            .catch(function(){if(currentEclipseData)recargarCarta();});
178        },function(){alert('No se pudo obtener GPS');},{timeout:10000});
179    }
180    function cambiarUbicacion(){
181        var c=prompt('Ingresá la ciudad (ej: Buenos Aires, Madrid, New York):');
182        if(!c)return;
183        fetch('https://nominatim.openstreetmap.org/search?q='+encodeURIComponent(c)+'&format=json&limit=1&accept-language=es')
184        .then(r=>r.json()).then(function(d){
185            if(d.length>0){userLat=parseFloat(d[0].lat);userLon=parseFloat(d[0].lon);userCiudad=d[0].display_name.split(',')[0];
186            alert('Ubicación: '+userCiudad+' ('+userLat.toFixed(2)+'°, '+userLon.toFixed(2)+'°)');if(currentEclipseData)recargarCarta();}
187            else alert('Ciudad no encontrada.');
188        }).catch(function(){alert('Error buscando la ciudad');});
189    }
190    function recargarCarta(){if(currentEclipseData)abrirCarta(currentEclipseData.jd,currentEclipseData.tipo,currentEclipseData.subtipo,currentEclipseData.fecha);}
191
192    // ===== INIT =====
193    document.addEventListener('DOMContentLoaded',function(){
194        var mt=document.getElementById('menu-toggle'),mn=document.getElementById('main-nav'),mo=document.getElementById('menu-overlay');
195        if(mt&&mn&&mo){
196            mt.addEventListener('click',function(){mt.classList.toggle('active');mn.classList.toggle('active');mo.classList.toggle('active');document.body.style.overflow=mn.classList.contains('active')?'hidden':'';});
197            mo.addEventListener('click',function(){mt.classList.remove('active');mn.classList.remove('active');mo.classList.remove('active');document.body.style.overflow='';});
198            mn.querySelectorAll('.nav-link').forEach(function(l){l.addEventListener('click',function(){mt.classList.remove('active');mn.classList.remove('active');mo.classList.remove('active');document.body.style.overflow='';});});
199        }
200        document.getElementById('btn-cerrar-carta').addEventListener('click',cerrarCarta);
201        document.getElementById('modal-carta').addEventListener('click',function(e){if(e.target===document.getElementById('modal-carta'))cerrarCarta();});
202        document.querySelectorAll('.tab-btn').forEach(function(b){b.addEventListener('click',function(){
203            document.querySelectorAll('.tab-btn').forEach(function(x){x.classList.remove('active');});
204            document.querySelectorAll('.tab-content').forEach(function(x){x.classList.remove('active');});
205            this.classList.add('active');document.getElementById('tab-'+this.dataset.tab).classList.add('active');
206            if(this.dataset.tab==='astrocarto' && currentEclipseData && !astrocartoLoaded) cargarAstrocartografia();
207        });});
208        obtenerUbicacion();cargarEclipses();
209    });
210
211    // ===== ECLIPSES LIST =====
212    async function cargarEclipses(){
213        try{var r=await fetch(API_BASE+'/api/eclipses?timezone='+encodeURIComponent(userTimezone));var d=await r.json();
214        if(d.exito)mostrarEclipses(d.eclipses);else mostrarError('Error al cargar');}
215        catch(e){mostrarError('Error: '+e.message);}
216    }
217    function mostrarEclipses(eclipses){
218        var ct=document.getElementById('eclipses-container');document.getElementById('loading').style.display='none';ct.style.display='block';
219        var mob=window.innerWidth<=768;
220        if(mob){
221            var h='<div style="display:flex;flex-direction:column;gap:1rem;">';
222            eclipses.forEach(function(ec){
223                var f=new Date(ec.timestamp),fs=f.toLocaleDateString('es-AR',{weekday:'short',day:'2-digit',month:'short',year:'numeric'}),
224                hu=f.toISOString().substr(11,5),hl=f.toLocaleTimeString('es-AR',{hour:'2-digit',minute:'2-digit'}),
225                ic=ec.tipo==='solar'?'☀️':'🌕',tx=(ec.tipo==='solar'?'Solar':'Lunar')+' '+ec.subtipo,ln=(SIGNOS_SIMBOLO[ec.signo]||'')+' '+ec.grado;
226                h+='<div class="eclipse-clickeable" style="background:var(--color-secundario);border-radius:8px;padding:1rem;border-left:4px solid var(--color-acento);" onclick="abrirCarta('+ec.jd+',\''+ec.tipo+'\',\''+ec.subtipo+'\',\''+ec.timestamp+'\')">';
227                h+='<div style="display:flex;justify-content:space-between;align-items:start;margin-bottom:0.5rem;"><div><div style="font-size:1.5rem;margin-bottom:0.25rem;">'+ic+'</div><div style="font-weight:600;color:var(--color-dorado);">'+tx+'</div></div><div style="text-align:right;font-size:0.9rem;color:var(--color-texto-secundario);">'+fs+'</div></div>';
228                h+='<div style="display:grid;grid-template-columns:auto 1fr;gap:0.5rem;font-size:0.9rem;margin-top:0.75rem;"><div style="color:var(--color-texto-secundario);">TU:</div><div>'+hu+'</div><div style="color:var(--color-texto-secundario);">Local:</div><div style="font-weight:600;color:var(--color-enlace);">'+hl+'</div><div style="color:var(--color-texto-secundario);">Longitud:</div><div>'+ln+'</div></div>';
229                h+='<div style="text-align:center;margin-top:0.75rem;"><button style="background:linear-gradient(135deg,#d4af37,#b8962e);color:#0f0f1e;border:none;padding:0.5rem 1.2rem;border-radius:8px;font-weight:700;font-size:0.85rem;cursor:pointer;font-family:Cinzel,serif;">&#128302; VER CARTA NATAL</button></div></div>';
230            });
231            h+='</div>';ct.innerHTML=h;
232        }else{
233            var h='<div style="overflow-x:auto;"><table style="width:100%;border-collapse:collapse;background:var(--color-secundario);border-radius:8px;"><thead><tr style="background:var(--color-acento);color:var(--color-texto);"><th style="padding:0.8rem;text-align:left;">Fecha</th><th style="padding:0.8rem;text-align:left;">TU</th><th style="padding:0.8rem;text-align:left;">Hora Local</th><th style="padding:0.8rem;text-align:left;">Tipo</th><th style="padding:0.8rem;text-align:left;">Long. Eclíptica</th><th style="padding:0.8rem;text-align:center;">Carta</th></tr></thead><tbody>';
234            eclipses.forEach(function(ec,i){
235                var f=new Date(ec.timestamp),fs=f.toLocaleDateString('es-AR',{day:'2-digit',month:'short',year:'numeric'}),hu=f.toISOString().substr(11,8),hl=f.toLocaleTimeString('es-AR',{hour:'2-digit',minute:'2-digit',second:'2-digit'}),
236                ic=ec.tipo==='solar'?'☀️':'🌕',tx=ic+' '+(ec.tipo==='solar'?'Solar':'Lunar')+' '+ec.subtipo,ln=(SIGNOS_SIMBOLO[ec.signo]||'')+' '+ec.grado,bg=i%2===0?'var(--color-secundario)':'rgba(0,0,0,0.2)';
237                h+='<tr class="eclipse-clickeable" style="background:'+bg+';" onclick="abrirCarta('+ec.jd+',\''+ec.tipo+'\',\''+ec.subtipo+'\',\''+ec.timestamp+'\')"><td style="padding:0.6rem;border-bottom:1px solid rgba(255,255,255,0.1);">'+fs+'</td><td style="padding:0.6rem;border-bottom:1px solid rgba(255,255,255,0.1);">'+hu+'</td><td style="padding:0.6rem;border-bottom:1px solid rgba(255,255,255,0.1);">'+hl+'</td><td style="padding:0.6rem;border-bottom:1px solid rgba(255,255,255,0.1);">'+tx+'</td><td style="padding:0.6rem;border-bottom:1px solid rgba(255,255,255,0.1);">'+ln+'</td><td style="padding:0.6rem;border-bottom:1px solid rgba(255,255,255,0.1);text-align:center;"><span style="cursor:pointer;font-size:1.2rem;">🔮</span></td></tr>';
238            });
239            h+='</tbody></table></div>';ct.innerHTML=h;
240        }
241    }
242    function mostrarError(m){var c=document.getElementById("eclipses-container");document.getElementById("loading").style.display="none";c.style.display="block";c.innerHTML='<div class="card" style="text-align:center;padding:2rem;"><p style="color:#ff6347;">❌ '+m+'</p><button class="btn-actualizar" onclick="cargarEclipses()" style="margin-top:1rem;">Reintentar</button></div>';}
243
244    // ===== CARTA ASTRAL =====
245    async function abrirCarta(jd,tipo,subtipo,timestamp){
246        currentEclipseData={jd:jd,tipo:tipo,subtipo:subtipo,fecha:timestamp};
247        astrocartoLoaded=false;
248        var f=new Date(timestamp),fs=f.toLocaleDateString('es-AR',{day:'2-digit',month:'long',year:'numeric'}),tt=tipo==='solar'?'Solar':'Lunar';
249        document.getElementById('carta-titulo').textContent='Eclipse '+tt+' '+subtipo+' — '+fs;
250        document.getElementById('ubicacion-texto').textContent=userCiudad+' ('+userLat.toFixed(2)+'°, '+userLon.toFixed(2)+'°)';
251        document.getElementById('modal-carta').classList.add('active');document.body.style.overflow='hidden';
252        document.querySelectorAll('.tab-btn').forEach(function(b){b.classList.remove('active');});
253        document.querySelectorAll('.tab-content').forEach(function(c){c.classList.remove('active');});
254        document.querySelector('.tab-btn[data-tab="carta"]').classList.add('active');
255        document.getElementById('tab-carta').classList.add('active');
256        document.getElementById('astrochart-container').innerHTML='<p style="text-align:center;color:#888;padding:2rem;">⏳ Calculando carta astral...</p>';
257        try{
258            var r=await fetch(API_BASE+'/api/eclipse/carta?jd='+jd+'&lat='+userLat+'&lon='+userLon+'&tipo='+tipo);
259            var data=await r.json();
260            if(data.exito){dibujarCartaAstroChart(data);llenarPosiciones(data.planetas);llenarAspectos(data.aspectos);llenarCasas(data.casas,data.angulares);llenarDatosTecnicos(data.datos_tecnicos,subtipo);}
261            else document.getElementById('astrochart-container').innerHTML='<p style="color:#ff6347;">❌ '+data.error+'</p>';
262        }catch(e){document.getElementById('astrochart-container').innerHTML='<p style="color:#ff6347;">❌ '+e.message+'</p>';}
263    }
264    function cerrarCarta(){document.getElementById('modal-carta').classList.remove('active');document.body.style.overflow='';}
265
266    // ===== DIBUJAR CON ASTROCHART LIBRARY =====
267    function dibujarCartaAstroChart(data){
268        // Limpiar contenedor
269        var container = document.getElementById('astrochart-container');
270        container.innerHTML = '';
271        
272        // Mapeo de nombres español -> inglés para la librería
273        var planetMap = {
274            'Sol':'Sun', 'Luna':'Moon', 'Mercurio':'Mercury', 'Venus':'Venus',
275            'Marte':'Mars', 'Júpiter':'Jupiter', 'Saturno':'Saturn',
276            'Urano':'Uranus', 'Neptuno':'Neptune', 'Plutón':'Pluto',
277            'Nodo Norte':'NNode'
278        };
279        
280        // Construir datos para AstroChart
281        var planets = {};
282        for (var nombre in planetMap) {
283            var p = data.planetas[nombre];
284            if (p) {
285                var key = planetMap[nombre];
286                if (p.retrogrado && nombre !== 'Nodo Norte' && nombre !== 'Nodo Sur') {
287                    planets[key] = [p.lon, -1];  // segundo valor negativo = retrógrado
288                } else {
289                    planets[key] = [p.lon];
290                }
291            }
292        }
293        
294        // Cúspides de casas (array de 12)
295        var cusps = [];
296        for (var i = 1; i <= 12; i++) {
297            var casa = data.casas['Casa ' + i];
298            cusps.push(casa ? casa.lon : (i - 1) * 30);
299        }
300        
301        var chartData = {
302            planets: planets,
303            cusps: cusps
304        };
305        
306        // Configuración de colores (tema oscuro elegante)
307        var settings = {
308            SYMBOL_SCALE: 1,
309            COLOR_BACKGROUND: "#0f0f1e",
310            POINTS_COLOR: "#d4af37",
311            SIGNS_COLOR: "#d4af37",
312            CIRCLE_COLOR: "#5a5a8a",
313            LINE_COLOR: "#4a4a7a",
314            CUSPS_FONT_COLOR: "#aaa",
315            MARGIN: 50,
316            PADDING: 24,
317            INNER_CIRCLE_RADIUS_RATIO: 6,
318            COLORS_SIGNS: [
319                "#CC3333", "#339933", "#CCCC33", "#6699CC",
320                "#FF8800", "#886644", "#CC66AA", "#993333",
321                "#9966CC", "#336655", "#339999", "#4466BB"
322            ],
323            ASPECTS: {
324                "conjunction":{"degree":0, "orbit":8, "color":"#FFD700"},
325                "sextile":{"degree":60, "orbit":6, "color":"#44DDDD"},
326                "square":{"degree":90, "orbit":7, "color":"#FF4444"},
327                "trine":{"degree":120, "orbit":8, "color":"#44FF88"},
328                "opposition":{"degree":180, "orbit":8, "color":"#FF6666"}
329            }
330        };
331        
332        // Determinar tamaño responsivo
333        var chartSize = 700;
334        
335        // Crear div con ID único
336        var chartDiv = document.createElement('div');
337        chartDiv.id = 'astro-paper-' + Date.now();
338        chartDiv.style.cssText = 'width:100%;display:flex;justify-content:center;';
339        container.appendChild(chartDiv);
340        
341        // Crear carta
342        try {
343            var chart = new astrochart.Chart(chartDiv.id, chartSize, chartSize, settings);
344            var radix = chart.radix(chartData);
345            
346            // Agregar puntos de interés (ASC, MC, DSC, IC)
347            radix.addPointsOfInterest({
348                "As": [cusps[0]],
349                "Ic": [cusps[3]],
350                "Ds": [cusps[6]],
351                "Mc": [cusps[9]]
352            });
353            
354            // Calcular y dibujar aspectos
355            radix.aspects();
356            
357            // Hacer SVG responsivo para móvil
358            var svgEl = chartDiv.querySelector('svg');
359            if (svgEl) { svgEl.style.maxWidth = '100%'; svgEl.style.height = 'auto'; }
360        } catch(e) {
361            container.innerHTML = '<p style="color:#ff6347;text-align:center;">Error al dibujar carta: ' + e.message + '</p>';
362            console.error('AstroChart error:', e);
363        }
364    }
365
366    // ===== LLENAR DATOS =====
367    function llenarPosiciones(pl){
368        var tbody=document.querySelector('#tabla-planetas tbody');
369        var orden=['Sol','Luna','Mercurio','Venus','Marte','Júpiter','Saturno','Urano','Neptuno','Plutón','Nodo Norte','Nodo Sur'];
370        tbody.innerHTML=orden.map(function(n){var p=pl[n];if(!p)return '';
371        var ret=p.retrogrado&&n!=='Nodo Norte'&&n!=='Nodo Sur'?'<span class="retrogrado">R</span>':'';
372        return '<tr><td>'+(PLANETAS_SIMBOLO[n]||'')+' '+n+'</td><td>'+(SIGNOS_SIMBOLO[p.signo]||'')+' '+p.signo+'</td><td>'+p.grado+'</td><td>'+p.lon.toFixed(2)+'°</td><td>'+ret+'</td></tr>';}).join('');
373    }
374    function llenarAspectos(asp){
375        var c=document.getElementById('aspectos-lista');
376        if(!asp.length){c.innerHTML='<p style="color:#888;">Sin aspectos</p>';return;}
377        c.innerHTML=asp.map(function(a){return '<div class="aspecto-row"><span>'+(PLANETAS_SIMBOLO[a.planeta1]||'')+' '+a.planeta1+' '+a.simbolo+' '+(PLANETAS_SIMBOLO[a.planeta2]||'')+' '+a.planeta2+'</span><span style="color:#888;">'+a.aspecto+' ('+a.orbe+'°)</span></div>';}).join('');
378    }
379    function llenarCasas(casas,ang){
380        var c=document.getElementById('casas-info');
381        var h='<h3 style="color:#d4af37;margin-bottom:0.5rem;">Puntos Angulares</h3>';
382        ['ASC','MC','DSC','IC'].forEach(function(p){var a=ang[p];if(a)h+='<div class="dato-tecnico"><span class="dato-tecnico-label">'+p+'</span><span class="dato-tecnico-valor">'+(SIGNOS_SIMBOLO[a.signo]||'')+' '+a.signo+' '+a.grado+'</span></div>';});
383        h+='<h3 style="color:#d4af37;margin:1rem 0 0.5rem;">Cúspides (Placidus)</h3><div class="casas-grid">';
384        for(var i=1;i<=12;i++){var ca=casas['Casa '+i];if(ca)h+='<div class="casa-item"><span class="casa-num">Casa '+i+':</span> '+(SIGNOS_SIMBOLO[ca.signo]||'')+' '+ca.signo+' '+ca.grado+'</div>';}
385        h+='</div>';c.innerHTML=h;
386    }
387    function llenarDatosTecnicos(d,sub){
388        var c=document.getElementById('datos-tecnicos'),t=d.tipo==='solar'?'Solar':'Lunar';
389        var h='<div class="dato-tecnico"><span class="dato-tecnico-label">Tipo</span><span class="dato-tecnico-valor">Eclipse '+t+' '+sub+'</span></div>';
390        h+='<div class="dato-tecnico"><span class="dato-tecnico-label">Máximo del eclipse (UTC)</span><span class="dato-tecnico-valor">'+d.fecha_utc+'</span></div>';
391        if(d.fecha_carta_utc)h+='<div class="dato-tecnico"><span class="dato-tecnico-label">'+(d.momento_carta||'Sicigia')+' (UTC)</span><span class="dato-tecnico-valor">'+d.fecha_carta_utc+'</span></div>';
392        h+='<div class="dato-tecnico"><span class="dato-tecnico-label">Día Juliano (carta)</span><span class="dato-tecnico-valor">'+d.jd.toFixed(4)+'</span></div>';
393        if(d.magnitud!==null&&d.magnitud!==undefined)h+='<div class="dato-tecnico"><span class="dato-tecnico-label">Magnitud</span><span class="dato-tecnico-valor">'+d.magnitud+'</span></div>';
394        h+='<div class="dato-tecnico"><span class="dato-tecnico-label">Ubicación</span><span class="dato-tecnico-valor">'+d.ubicacion_calculo.lat.toFixed(4)+'°, '+d.ubicacion_calculo.lon.toFixed(4)+'°</span></div>';
395        h+='<div style="margin-top:0.75rem;padding:0.75rem;background:rgba(212,175,55,0.08);border-radius:6px;font-size:0.85rem;color:#888;border-left:3px solid #d4af37;">La carta se levanta en el momento de la '+(d.tipo==='lunar'?'oposición':'conjunción')+' exacta, cuando el Sol y la Luna comparten grado eclíptico. El máximo del eclipse ocurre algunos minutos antes o después.</div>';
396        if(d.saros){
397            h+='<h3 style="color:#d4af37;margin:1.5rem 0 0.5rem;">Serie Saros</h3>';
398            h+='<div class="dato-tecnico"><span class="dato-tecnico-label">Serie</span><span class="dato-tecnico-valor">'+d.saros.saros+'</span></div>';
399            h+='<div class="dato-tecnico"><span class="dato-tecnico-label">Miembro</span><span class="dato-tecnico-valor">'+d.saros.miembro+'</span></div>';
400            h+='<div class="dato-tecnico"><span class="dato-tecnico-label">Tipo en la serie</span><span class="dato-tecnico-valor">'+(d.saros.tipo_saros||sub)+'</span></div>';
401            h+='<div style="margin-top:0.75rem;padding:0.75rem;background:rgba(212,175,55,0.08);border-radius:6px;font-size:0.85rem;color:#888;border-left:3px solid #d4af37;">La serie Saros '+d.saros.saros+' produce eclipses cada 18 años, 11 días y 8 horas. Este es el eclipse número '+d.saros.miembro+' de la serie.</div>';
402        }else{h+='<div class="dato-tecnico"><span class="dato-tecnico-label">Serie Saros</span><span style="color:#666;">No disponible</span></div>';}
403        c.innerHTML=h;
404    }
405
406    // ===== ASTROCARTOGRAFÍA =====
407    var PLANETA_COLORES = {
408        'Sol':'#FFD700','Luna':'#FFFFFF','Mercurio':'#00FF88',
409        'Venus':'#FF69B4','Marte':'#FF2222','Júpiter':'#AA77FF',
410        'Saturno':'#DDAA44','Urano':'#00CCDD','Neptuno':'#4488FF','Plutón':'#CC5555'
411    };
412    var PLANETA_SIMBOLOS_CORTOS = {
413        'Sol':'☉','Luna':'☽','Mercurio':'☿','Venus':'♀','Marte':'♂',
414        'Júpiter':'♃','Saturno':'♄','Urano':'♅','Neptuno':'♆','Plutón':'♇'
415    };
416
417    async function cargarAstrocartografia(){
418        if(!currentEclipseData) return;
419        var mapDiv = document.getElementById('astrocarto-map');
420        mapDiv.innerHTML='<p style="text-align:center;color:#888;padding:3rem;">⏳ Calculando líneas astrocartográficas...</p>';
421
422        try {
423            console.log('Astrocarto: fetching JD=', currentEclipseData.jd);
424            var tipoEcl = (currentEclipseData.tipo||'').toLowerCase().indexOf('solar')>=0 ? 'solar' : 'lunar';
425            var r = await fetch(API_BASE+'/api/eclipse/astrocartografia?jd='+currentEclipseData.jd+'&tipo='+tipoEcl);
426            console.log('Astrocarto: status=', r.status);
427            
428            if(!r.ok){
429                mapDiv.innerHTML='<p style="color:#ff6347;text-align:center;padding:2rem;">Error del servidor ('+r.status+'). Verificá que app.py tenga el endpoint /api/eclipse/astrocartografia</p>';
430                return;
431            }
432            
433            var txt = await r.text();
434            console.log('Astrocarto: response length=', txt.length);
435            
436            var data;
437            try { data = JSON.parse(txt); } catch(pe) {
438                console.error('Astrocarto: JSON parse fail', pe, txt.substring(0,200));
439                mapDiv.innerHTML='<p style="color:#ff6347;text-align:center;padding:2rem;">Respuesta no es JSON. Verificá app.py.</p>';
440                return;
441            }
442            
443            if(data.exito && data.lineas){
444                console.log('Astrocarto: planetas=', Object.keys(data.lineas).length);
445                dibujarAstrocartografia(data);
446                astrocartoLoaded=true;
447            } else {
448                mapDiv.innerHTML='<p style="color:#ff6347;text-align:center;padding:2rem;">'+(data.error||'Sin datos')+'</p>';
449            }
450        } catch(e){
451            console.error('Astrocarto: exception', e);
452            mapDiv.innerHTML='<p style="color:#ff6347;text-align:center;padding:2rem;">Error: '+e.message+'</p>';
453        }
454    }
455
456    function dibujarAstrocartografia(data){
457        var mapDiv = document.getElementById('astrocarto-map');
458
459        // Destruir mapa anterior ANTES de limpiar el contenedor
460        if(astrocartoMap){ try{ astrocartoMap.remove(); }catch(e){} astrocartoMap=null; }
461        mapDiv.innerHTML='';
462
463        setTimeout(function(){
464            try {
465                astrocartoMap = L.map(mapDiv, {center:[20,0], zoom:2, minZoom:1, maxZoom:8, worldCopyJump:true});
466                L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',{
467                    attribution:'&copy; CARTO &copy; OSM', subdomains:'abcd', maxZoom:19
468                }).addTo(astrocartoMap);
469
470                var lineas = data.lineas;
471                var total = 0;
472                var tipos = ['mc','ic','asc','dsc'];
473                var tipoEstilo = {
474                    mc:  {weight:1.8, dashArray:null},
475                    ic:  {weight:1.3, dashArray:'6,4'},
476                    asc: {weight:1.8, dashArray:null},
477                    dsc: {weight:1.3, dashArray:'4,3'}
478                };
479                var tipoLabel = {mc:' MC', ic:' IC', asc:' ASC', dsc:' DSC'};
480
481                for(var planeta in lineas){
482                    var info = lineas[planeta];
483                    var color = PLANETA_COLORES[planeta] || '#FFF';
484
485                    for(var ti=0; ti<tipos.length; ti++){
486                        var tipo = tipos[ti];
487                        var segs = info[tipo];
488                        if(!segs) continue;
489                        var est = tipoEstilo[tipo];
490
491                        for(var si=0; si<segs.length; si++){
492                            var seg = segs[si];
493                            if(!seg || seg.length < 2) continue;
494
495                            var polyOpts = {color:color, weight:est.weight, opacity:0.85, smoothFactor:1.5};
496                            if(est.dashArray) polyOpts.dashArray = est.dashArray;
497                            
498                            L.polyline(seg, polyOpts).addTo(astrocartoMap)
499                             .bindTooltip(PLANETA_SIMBOLOS_CORTOS[planeta]+' '+planeta+tipoLabel[tipo], {sticky:true});
500                            total++;
501                        }
502                    }
503                }
504
505                console.log('Astrocarto: drew', total, 'lines from', Object.keys(lineas).length, 'planets');
506
507                // Marcador del punto del eclipse (discreto)
508                if(data.eclipse_point && data.eclipse_point.lat){
509                    var ep = data.eclipse_point;
510                    var eclIcon = L.divIcon({
511                        html:'<div style="width:8px;height:8px;background:#FF4500;border:1.5px solid #fff;border-radius:50%;box-shadow:0 0 3px rgba(255,69,0,0.5);"></div>',
512                        className:'', iconSize:[11,11], iconAnchor:[5,5]
513                    });
514                    L.marker([ep.lat, ep.lon], {icon:eclIcon, zIndexOffset:1000})
515                     .addTo(astrocartoMap)
516                     .bindPopup('<b>'+(ep.desc||'Punto del eclipse')+'</b><br>Lat: '+ep.lat.toFixed(2)+'° Lon: '+ep.lon.toFixed(2)+'°');
517                }
518
519                // Marcador ubicación del usuario
520                L.marker([userLat, userLon], {
521                    icon: L.divIcon({html:'<span style="font-size:22px;">📍</span>', className:'', iconSize:[24,24], iconAnchor:[12,24]})
522                }).addTo(astrocartoMap).bindPopup('<b>'+userCiudad+'</b><br>'+userLat.toFixed(2)+'°, '+userLon.toFixed(2)+'°');
523
524                astrocartoMap.setView([userLat, userLon], 3);
525                construirLeyenda(lineas);
526                setTimeout(function(){ astrocartoMap.invalidateSize(); }, 200);
527
528            } catch(err) {
529                console.error('Astrocarto error:', err);
530                mapDiv.innerHTML='<p style="color:#ff6347;text-align:center;padding:2rem;">Error: '+err.message+'</p>';
531            }
532        }, 150);
533    }
534
535    function construirLeyenda(lineas){
536        var leyDiv = document.getElementById('astrocarto-leyenda');
537        var h = '';
538
539        // Planetas
540        for(var planeta in lineas){
541            var color = PLANETA_COLORES[planeta]||'#888';
542            var simb = PLANETA_SIMBOLOS_CORTOS[planeta]||'';
543            h += '<div class="astrocarto-leyenda-item">';
544            h += '<div class="astrocarto-leyenda-linea" style="background:'+color+';"></div>';
545            h += '<span>'+simb+' '+planeta+'</span>';
546            h += '</div>';
547        }
548
549        // Separador
550        h += '<span style="color:#555;margin:0 0.3rem;">|</span>';
551
552        // Tipos de línea
553        h += '<div class="astrocarto-leyenda-item"><div style="width:24px;height:3px;background:#aaa;"></div><span>MC/ASC</span></div>';
554        h += '<div class="astrocarto-leyenda-item"><div style="width:24px;height:0;border-top:3px dashed #aaa;"></div><span>IC/DSC</span></div>';
555
556        leyDiv.innerHTML = h;
557    }
558    </script>
vendor: 1 bytes, line 558
558
559<script src="/static/js/capacitor-fcm-init.js"></script>
559</body>
560</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.