const LiveConditionsWidget = ({ lat, lng }) => {
            const [data, setData] = useState({ weather: null, tides: null, aurora: null, liveSolar: null, solarHistory: null, asHistory: null });
            const [loading, setLoading] = useState(true);
            const [errorMsg, setErrorMsg] = useState("");
            const [activeAuroraInfo, setActiveAuroraInfo] = useState(null);
            const [activeSolarChart, setActiveSolarChart] = useState('bz');
            const [showAstroMetricsInfo, setShowAstroMetricsInfo] = useState(false);

            // Externalized instructional data
            const [auroraInfoData, setAuroraMetrics] = useState({});
            const [weatherMap, setWeatherMap] = useState(null);

            useEffect(() => {
                fetch('data/aurora_metrics.json').then(r => r.json()).then(setAuroraMetrics).catch(e => console.warn(e));
                fetch('data/weather_mapping.json').then(r => r.json()).then(setWeatherMap).catch(e => console.warn(e));
            }, []);

            const toggleAuroraInfo = (key) => {
                setActiveAuroraInfo(prev => prev === key ? null : key);
            };

            const getApproxMoonrise = () => {
                const knownNewMoon = new Date('2024-02-09T22:59:00Z').getTime();
                const now = new Date().getTime();
                const daysSinceNew = (now - knownNewMoon) / (24 * 60 * 60 * 1000);
                const cycle = daysSinceNew % 29.530588;
                let riseHour = 6 + (cycle / 29.530588) * 24;
                if (riseHour >= 24) riseHour -= 24;
                const hours = Math.floor(riseHour);
                const mins = Math.floor((riseHour - hours) * 60);
                return `${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`;
            };

            const getMoonIllumination = (timeInMillis) => {
                if (window.SunCalc) {
                    return Math.round(window.SunCalc.getMoonIllumination(new Date(timeInMillis)).fraction * 100);
                }
                const knownNewMoon = new Date('2024-02-09T22:59:00Z').getTime();
                const daysSinceNew = (timeInMillis - knownNewMoon) / (24 * 60 * 60 * 1000);
                const cycle = (daysSinceNew % 29.530588 + 29.530588) % 29.530588;
                return Math.round((1 - Math.cos((cycle / 29.530588) * 2 * Math.PI)) * 50);
            };

            const getSolarAzimuths = (latitude, dateObj) => {
                const start = new Date(dateObj.getFullYear(), 0, 0);
                const diff = dateObj - start;
                const oneDay = 1000 * 60 * 60 * 24;
                const dayOfYear = Math.floor(diff / oneDay);
                const declination = -23.44 * Math.cos((360 / 365) * (dayOfYear + 10) * (Math.PI / 180));
                const declRad = declination * (Math.PI / 180);
                const latRad = latitude * (Math.PI / 180);
                const cosAzimuth = Math.sin(declRad) / Math.cos(latRad);
                const azimuthRad = Math.acos(Math.max(-1, Math.min(1, cosAzimuth))); 
                let sunriseAzimuth = azimuthRad * (180 / Math.PI);
                let sunsetAzimuth = 360 - sunriseAzimuth;
                
                const getCompassDir = (degrees) => {
                    const val = Math.floor((degrees / 22.5) + 0.5);
                    const arr = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"];
                    return arr[(val % 16)];
                };

                return {
                    sunrise: `${Math.round(sunriseAzimuth)}° ${getCompassDir(sunriseAzimuth)}`,
                    sunset: `${Math.round(sunsetAzimuth)}° ${getCompassDir(sunsetAzimuth)}`
                };
            };

            const getTideTimes = () => {
                const epoch = new Date('2024-03-25T15:15:00Z').getTime();
                const tidalPeriod = 44714400; 
                const halfPeriod = tidalPeriod / 2;
                const now = new Date().getTime();
                const periodsSince = Math.floor((now - epoch) / tidalPeriod);
                const lastHigh = epoch + (periodsSince * tidalPeriod);
                let nextHigh = lastHigh + tidalPeriod;
                let nextLow = lastHigh + halfPeriod;
                if (nextLow < now) nextLow += tidalPeriod;

                return {
                    nextHigh: new Date(nextHigh).toLocaleTimeString('en-GB', {timeZone: 'Europe/London', hour: '2-digit', minute:'2-digit'}),
                    nextLow: new Date(nextLow).toLocaleTimeString('en-GB', {timeZone: 'Europe/London', hour: '2-digit', minute:'2-digit'})
                };
            };

            const getBzClass = (bz) => {
                if (bz === null) return "bg-slate-50 border-slate-200 text-slate-500";
                if (bz <= -10) return "bg-rose-50/50 border-rose-200 text-rose-700"; 
                if (bz <= -2) return "bg-emerald-50/50 border-emerald-200 text-emerald-700"; 
                if (bz <= 0) return "bg-amber-50/50 border-amber-200 text-amber-700"; 
                return "bg-rose-50/50 border-rose-200 text-rose-700"; 
            };
            const getBzLabel = (bz) => {
                if (bz === null) return "--";
                if (bz <= -10) return "Storm";
                if (bz <= -2) return "Good";
                if (bz <= 0) return "Fair";
                return "Poor"; 
            };

            const getSpeedClass = (s) => {
                if (s === null) return "bg-slate-50 border-slate-200 text-slate-500";
                if (s >= 600) return "bg-rose-50/50 border-rose-200 text-rose-700";
                if (s >= 450) return "bg-emerald-50/50 border-emerald-200 text-emerald-700";
                if (s >= 350) return "bg-amber-50/50 border-amber-200 text-amber-700";
                return "bg-emerald-50/50 border-emerald-200 text-emerald-700";
            };
            const getSpeedLabel = (s) => {
                if (s === null) return "--";
                if (s >= 600) return "High";
                if (s >= 450) return "Good";
                if (s >= 350) return "Normal";
                return "Good";
            };

            const getDensityClass = (d) => {
                if (d === null) return "bg-slate-50 border-slate-200 text-slate-500";
                if (d >= 20) return "bg-rose-50/50 border-rose-200 text-rose-700";
                if (d >= 10) return "bg-emerald-50/50 border-emerald-200 text-emerald-700";
                if (d >= 5) return "bg-amber-50/50 border-amber-200 text-amber-700";
                return "bg-slate-50 border-slate-200 text-slate-500";
            };
            const getDensityLabel = (d) => {
                if (d === null) return "--";
                if (d >= 20) return "High";
                if (d >= 10) return "Good";
                if (d >= 5) return "Normal";
                return "Low";
            };

            const getAsClass = (as) => {
                if (as === null) return "bg-slate-50 border-slate-200 text-slate-500";
                if (as <= -500) return "bg-rose-50/50 border-rose-200 text-rose-700"; // Major
                if (as <= -200) return "bg-emerald-50/50 border-emerald-200 text-emerald-700"; // Good
                if (as <= -100) return "bg-amber-50/50 border-amber-200 text-amber-700"; // Active
                if (as >= 100) return "bg-indigo-50/50 border-indigo-200 text-indigo-700"; // Charging
                return "bg-slate-50 border-slate-200 text-slate-500"; // Quiet
            };
            const getAsLabel = (as) => {
                if (as === null) return "--";
                if (as <= -500) return "Major";
                if (as <= -200) return "Good";
                if (as <= -100) return "Active";
                if (as >= 100) return "Charging";
                return "Quiet";
            };

            useEffect(() => {
                let isMounted = true;

                const fetchAuroraDataEnsemble = async () => {
                    const endpoints = [
                        'https://services.swpc.noaa.gov/products/solar-wind/mag-1-day.json',
                        'https://services.swpc.noaa.gov/products/solar-wind/plasma-1-day.json',
                        'https://services.swpc.noaa.gov/products/solar-wind/mag-7-day.json',
                        'https://services.swpc.noaa.gov/products/solar-wind/plasma-7-day.json',
                        'https://services.swpc.noaa.gov/products/noaa-planetary-k-index-forecast.json',
                        'https://services.swpc.noaa.gov/products/noaa-planetary-k-index.json'
                    ];

                    // Lowered timeout from 6000ms to 3000ms so NOAA APIs don't lag the weather map
                    const fetchWithTimeout = (url, ms = 3000) => {
                        return new Promise((resolve, reject) => {
                            const timer = setTimeout(() => reject(new Error('Timeout')), ms);
                            fetch(url, { cache: 'no-store' })
                                .then(res => { clearTimeout(timer); resolve(res.json()); })
                                .catch(err => { clearTimeout(timer); reject(err); });
                        });
                    };

                    const results = await Promise.allSettled(endpoints.map(url => fetchWithTimeout(url, 3000)));
                    
                    const extractValidData = (jsonArr, isMag) => {
                        let validPoints = [];
                        if (jsonArr && Array.isArray(jsonArr)) {
                            for (let i = 1; i < jsonArr.length; i++) {
                                const row = jsonArr[i];
                                if (isMag) {
                                    const bz = parseFloat(Array.isArray(row) ? row[3] : (row.bz_gsm || row.bz));
                                    if (!isNaN(bz) && bz > -500 && bz < 500) validPoints.push({ time: row[0] || row.time_tag, bz });
                                } else {
                                    const density = parseFloat(Array.isArray(row) ? row[1] : (row.proton_density || row.density));
                                    const speed = parseFloat(Array.isArray(row) ? row[2] : (row.proton_speed || row.speed));
                                    if (!isNaN(density) && !isNaN(speed) && density > -500 && density < 2000 && speed > 0 && speed < 4000) {
                                        validPoints.push({ time: row[0] || row.time_tag, density, speed });
                                    }
                                }
                            }
                        }
                        return validPoints;
                    };

                    const magData1 = results[0].status === 'fulfilled' ? extractValidData(results[0].value, true) : [];
                    const magData7 = results[2].status === 'fulfilled' ? extractValidData(results[2].value, true) : [];
                    const combinedMag = [...magData7, ...magData1].sort((a,b) => new Date(a.time) - new Date(b.time));

                    const plasmaData1 = results[1].status === 'fulfilled' ? extractValidData(results[1].value, false) : [];
                    const plasmaData7 = results[3].status === 'fulfilled' ? extractValidData(results[3].value, false) : [];
                    const combinedPlasma = [...plasmaData7, ...plasmaData1].sort((a,b) => new Date(a.time) - new Date(b.time));

                    let liveSolar = { bz: null, speed: null, density: null, asIndex: null };
                    if (combinedMag.length) liveSolar.bz = combinedMag[combinedMag.length - 1].bz;
                    if (combinedPlasma.length) {
                        liveSolar.speed = combinedPlasma[combinedPlasma.length - 1].density !== undefined ? combinedPlasma[combinedPlasma.length - 1].speed : null;
                        liveSolar.density = combinedPlasma[combinedPlasma.length - 1].density;
                    }
                    if (liveSolar.bz !== null && liveSolar.speed !== null) {
                        liveSolar.asIndex = calculateAS(liveSolar.bz, liveSolar.speed);
                    }

                    let auroraDays = null;
                    const forecastData = results[4].status === 'fulfilled' ? results[4].value : null;
                    const recentData = results[5].status === 'fulfilled' ? results[5].value : null;
                    
                    if (forecastData || recentData) {
                        let allKpPoints = [];
                        
                        const extractKp = (arr) => {
                            if (!arr || !Array.isArray(arr)) return;
                            for (let i = 0; i < arr.length; i++) {
                                const row = arr[i];
                                if (!row) continue;
                                let dateStr = String(row.time_tag || row.time || (Array.isArray(row) ? row[0] : ''));
                                if (dateStr && dateStr !== 'time_tag') {
                                    dateStr = dateStr.replace(' ', 'T');
                                    if (!dateStr.endsWith('Z')) dateStr += 'Z';
                                    const kp = parseFloat(Array.isArray(row) ? row[1] : (row.predicted_kp || row.kp || row.estimated_kp));
                                    if (!isNaN(kp)) {
                                        allKpPoints.push({ time: new Date(dateStr).getTime(), kp });
                                    }
                                }
                            }
                        };
                        
                        extractKp(forecastData);
                        extractKp(recentData);

                        const getMaxKpForNight = (baseDate) => {
                            let sunset = window.SunCalc ? window.SunCalc.getTimes(baseDate, lat, lng).sunset : null;
                            const nextDay = new Date(baseDate.getTime() + 24 * 60 * 60 * 1000);
                            let sunrise = window.SunCalc ? window.SunCalc.getTimes(nextDay, lat, lng).sunrise : null;

                            if (!sunset || isNaN(sunset.getTime())) {
                                sunset = new Date(baseDate);
                                sunset.setUTCHours(18, 0, 0, 0);
                            }
                            if (!sunrise || isNaN(sunrise.getTime())) {
                                sunrise = new Date(nextDay);
                                sunrise.setUTCHours(6, 0, 0, 0);
                            }

                            let max = 0;
                            let found = false;
                            allKpPoints.forEach(pt => {
                                if (pt.time >= sunset.getTime() && pt.time <= sunrise.getTime()) {
                                    if (pt.kp > max) max = pt.kp;
                                    found = true;
                                }
                            });
                            return found ? max : 0;
                        };

                        const now = new Date();
                        const localOffsetMs = (lng / 15) * 60 * 60 * 1000;
                        const noonUTC = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 12, 0, 0);
                        
                        const todayMidday = new Date(noonUTC - localOffsetMs);
                        const tmrwMidday = new Date(todayMidday.getTime() + 24 * 60 * 60 * 1000);
                        const dayAfterMidday = new Date(todayMidday.getTime() + 48 * 60 * 60 * 1000);

                        auroraDays = [
                            { dayName: 'Tonight', kp: getMaxKpForNight(todayMidday) },
                            { dayName: 'Tomorrow', kp: getMaxKpForNight(tmrwMidday) },
                            { dayName: dayAfterMidday.toLocaleDateString('en-GB', { weekday: 'short' }), kp: getMaxKpForNight(dayAfterMidday) }
                        ];
                    }

                    const histories = processSpaceWeatherData(
                        combinedMag.map(m => [m.time, 0, 0, m.bz]), 
                        combinedPlasma.map(p => [p.time, p.density, p.speed]), 
                        liveSolar
                    );

                    return { auroraDays, liveSolar, histories };
                };

                const fetchConditions = async (isInitial = true) => {
                    if (isInitial) setLoading(true);
                    if (isInitial) setErrorMsg("");
                    
                    const fetchWithTimeout = (url, ms = 6000) => {
                        return new Promise((resolve, reject) => {
                            const timer = setTimeout(() => reject(new Error('Timeout')), ms);
                            fetch(url, { cache: 'no-store' })
                                .then(res => { clearTimeout(timer); resolve(res); })
                                .catch(err => { clearTimeout(timer); reject(err); });
                        });
                    };

                    // --- 100% RELIABLE WEATHER FALLBACK STRATEGIES ---
                    
                    // Fallback Mapper 1: Wttr.in JSON
                    const fetchWttrFallback = async (lLat, lLng) => {
                        const res = await fetchWithTimeout(`https://wttr.in/${lLat},${lLng}?format=j1`, 6000);
                        if (!res.ok) throw new Error("Wttr failed");
                        const d = await res.json();
                        
                        const mapWttrCode = (codeStr) => {
                            const c = parseInt(codeStr);
                            if (c === 113) return 0;
                            if (c === 116) return 2;
                            if (c === 119 || c === 122) return 3;
                            if (c === 143 || c === 248 || c === 260) return 45;
                            if (c >= 263 && c <= 281) return 51;
                            if (c === 293 || c === 296) return 61;
                            if (c === 299 || c === 302) return 63;
                            if (c >= 305 && c <= 314) return 65;
                            if (c >= 317 && c <= 350) return 71;
                            if (c >= 353 && c <= 359) return 80;
                            if (c >= 362 && c <= 377) return 83;
                            if (c >= 386 && c <= 395) return 95;
                            return 3;
                        };

                        const parseAmPm = (timeStr, dateStr) => {
                            if (!timeStr || !timeStr.includes(':')) return `${dateStr}T12:00`;
                            const parts = timeStr.split(' ');
                            const timeParts = parts[0].split(':');
                            let h = parseInt(timeParts[0]);
                            const m = timeParts[1] || '00';
                            if (parts[1] && parts[1].toUpperCase() === 'PM' && h !== 12) h += 12;
                            if (parts[1] && parts[1].toUpperCase() === 'AM' && h === 12) h = 0;
                            return `${dateStr}T${h.toString().padStart(2, '0')}:${m}`;
                        };

                        const cw = d.current_condition[0];
                        const weatherJson = {
                            current_weather: {
                                temperature: parseFloat(cw.temp_C) || 0,
                                windspeed: Math.round(parseFloat(cw.windspeedMiles) || 0),
                                weathercode: mapWttrCode(cw.weatherCode)
                            },
                            daily: { time: [], temperature_2m_max: [], temperature_2m_min: [], sunrise: [], sunset: [], weathercode: [] },
                            hourly: { time: [], temperature_2m: [], precipitation_probability: [], cloudcover: [], cloudcover_high: [], visibility: [], relative_humidity_2m: [], dew_point_2m: [], windspeed_10m: [], windspeed_80m: [], is_day: [], weathercode: [] }
                        };

                        (d.weather || []).forEach(day => {
                            weatherJson.daily.time.push(day.date);
                            weatherJson.daily.temperature_2m_max.push(parseFloat(day.maxtempC) || 0);
                            weatherJson.daily.temperature_2m_min.push(parseFloat(day.mintempC) || 0);
                            const astro = (day.astronomy && day.astronomy[0]) || {};
                            weatherJson.daily.sunrise.push(parseAmPm(astro.sunrise, day.date));
                            weatherJson.daily.sunset.push(parseAmPm(astro.sunset, day.date));
                            weatherJson.daily.weathercode.push(mapWttrCode(day.hourly?.[4]?.weatherCode));

                            // Interpolate Wttr's 3-hourly blocks to perfect 1-hourly metrics
                            for (let i = 0; i < 8; i++) {
                                const hData = day.hourly?.[i];
                                if (!hData) continue;
                                const nextDay = d.weather[d.weather.indexOf(day)+1];
                                const hDataNext = i < 7 ? day.hourly[i+1] : (nextDay ? nextDay.hourly?.[0] : hData);
                                if (!hDataNext) continue;
                                
                                const startHour = i * 3;
                                const tempStart = parseFloat(hData.tempC) || 0;
                                const tempEnd = parseFloat(hDataNext.tempC) || 0;
                                const cloudStart = parseFloat(hData.cloudcover) || 0;
                                const cloudEnd = parseFloat(hDataNext.cloudcover) || 0;
                                const windStart = parseFloat(hData.windspeedMiles) || 0;
                                const windEnd = parseFloat(hDataNext.windspeedMiles) || 0;
                                const precipStart = parseFloat(hData.chanceofrain) || 0;
                                const precipEnd = parseFloat(hDataNext.chanceofrain) || 0;
                                const visStart = (parseFloat(hData.visibility) || 10) * 1000;
                                const visEnd = (parseFloat(hDataNext.visibility) || 10) * 1000;
                                const humStart = parseFloat(hData.humidity) || 50;
                                const humEnd = parseFloat(hDataNext.humidity) || 50;
                                
                                for (let j = 0; j < 3; j++) {
                                    const hour = startHour + j;
                                    if (hour >= 24) continue;
                                    const ratio = j / 3;
                                    
                                    weatherJson.hourly.time.push(`${day.date}T${hour.toString().padStart(2, '0')}:00`);
                                    const temp = tempStart + (tempEnd - tempStart) * ratio;
                                    weatherJson.hourly.temperature_2m.push(temp);
                                    const cloud = cloudStart + (cloudEnd - cloudStart) * ratio;
                                    weatherJson.hourly.cloudcover.push(cloud);
                                    weatherJson.hourly.cloudcover_high.push(cloud * 0.8);
                                    weatherJson.hourly.precipitation_probability.push(precipStart + (precipEnd - precipStart) * ratio);
                                    weatherJson.hourly.visibility.push(visStart + (visEnd - visStart) * ratio);
                                    const hum = humStart + (humEnd - humStart) * ratio;
                                    weatherJson.hourly.relative_humidity_2m.push(hum);
                                    weatherJson.hourly.dew_point_2m.push(temp - ((100 - hum) / 5)); 
                                    const wind = windStart + (windEnd - windStart) * ratio;
                                    weatherJson.hourly.windspeed_10m.push(Math.round(wind));
                                    weatherJson.hourly.windspeed_80m.push(Math.round(wind * 1.25));
                                    weatherJson.hourly.weathercode.push(mapWttrCode(hData.weatherCode));
                                    weatherJson.hourly.is_day.push(hour >= 6 && hour <= 18 ? 1 : 0);
                                }
                            }
                        });
                        return weatherJson;
                    };

                    // Fallback Mapper 2: Norwegian Meteorological Institute (met.no)
                    const fetchMetNoFallback = async (lLat, lLng) => {
                        const res = await fetchWithTimeout(`https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${lLat}&lon=${lLng}`, 6000);
                        if (!res.ok) throw new Error("Met.no failed");
                        const d = await res.json();
                        
                        const timeseries = d.properties?.timeseries;
                        if (!timeseries || timeseries.length === 0) throw new Error("Met.no empty");
                        
                        const nowData = timeseries[0].data.instant.details;
                        
                        const mapMetNoCode = (sym) => {
                            if (!sym) return 3;
                            if (sym.includes('clearsky')) return 0;
                            if (sym.includes('fair')) return 1;
                            if (sym.includes('partlycloudy')) return 2;
                            if (sym.includes('cloudy')) return 3;
                            if (sym.includes('fog')) return 45;
                            if (sym.includes('drizzle')) return 51;
                            if (sym.includes('rain')) return 61;
                            if (sym.includes('snow')) return 71;
                            if (sym.includes('sleet')) return 68;
                            if (sym.includes('thunder')) return 95;
                            return 3;
                        };

                        const weatherJson = {
                            current_weather: {
                                temperature: nowData.air_temperature || 0,
                                windspeed: Math.round((nowData.wind_speed || 0) * 2.23694),
                                weathercode: mapMetNoCode(timeseries[0].data.next_1_hours?.summary?.symbol_code)
                            },
                            daily: { time: [], temperature_2m_max: [], temperature_2m_min: [], sunrise: [], sunset: [], weathercode: [] },
                            hourly: { time: [], temperature_2m: [], precipitation_probability: [], cloudcover: [], cloudcover_high: [], visibility: [], relative_humidity_2m: [], dew_point_2m: [], windspeed_10m: [], windspeed_80m: [], is_day: [], weathercode: [] }
                        };

                        const daysMap = {};
                        timeseries.forEach(t => {
                            const dateStr = t.time.split('T')[0];
                            if (!daysMap[dateStr]) daysMap[dateStr] = { temps: [], codes: [] };
                            daysMap[dateStr].temps.push(t.data.instant.details.air_temperature || 0);
                            if (t.data.next_1_hours) daysMap[dateStr].codes.push(mapMetNoCode(t.data.next_1_hours.summary.symbol_code));
                            
                            if (t.time.endsWith(":00:00Z")) {
                                const localTime = new Date(t.time);
                                const tzAdjusted = new Date(localTime.getTime() - localTime.getTimezoneOffset() * 60000).toISOString().substring(0,16);
                                
                                weatherJson.hourly.time.push(tzAdjusted);
                                weatherJson.hourly.temperature_2m.push(t.data.instant.details.air_temperature || 0);
                                weatherJson.hourly.cloudcover.push(t.data.instant.details.cloud_area_fraction || 0);
                                weatherJson.hourly.cloudcover_high.push(t.data.instant.details.cloud_area_fraction_high || 0);
                                weatherJson.hourly.precipitation_probability.push((t.data.next_1_hours?.details?.precipitation_amount > 0) ? 80 : 0);
                                weatherJson.hourly.visibility.push(15000); 
                                weatherJson.hourly.relative_humidity_2m.push(t.data.instant.details.relative_humidity || 50);
                                weatherJson.hourly.dew_point_2m.push(t.data.instant.details.dew_point_temperature || ((t.data.instant.details.air_temperature||0) - 5));
                                const wMph = (t.data.instant.details.wind_speed || 0) * 2.23694;
                                weatherJson.hourly.windspeed_10m.push(Math.round(wMph));
                                weatherJson.hourly.windspeed_80m.push(Math.round(wMph * 1.25));
                                weatherJson.hourly.weathercode.push(mapMetNoCode(t.data.next_1_hours?.summary?.symbol_code));
                                const h = localTime.getHours();
                                weatherJson.hourly.is_day.push(h >= 6 && h <= 18 ? 1 : 0);
                            }
                        });

                        Object.keys(daysMap).slice(0, 7).forEach(d => {
                            weatherJson.daily.time.push(d);
                            weatherJson.daily.temperature_2m_max.push(Math.max(...daysMap[d].temps));
                            weatherJson.daily.temperature_2m_min.push(Math.min(...daysMap[d].temps));
                            weatherJson.daily.sunrise.push(`${d}T06:00`); 
                            weatherJson.daily.sunset.push(`${d}T18:00`); 
                            weatherJson.daily.weathercode.push(daysMap[d].codes[Math.floor(daysMap[d].codes.length / 2)] || 3);
                        });

                        return weatherJson;
                    };

                    const CACHE_KEY = `northernPixl_weather_${lat.toFixed(2)}_${lng.toFixed(2)}`;

                    const getWeatherTask = async () => {
                        let weatherJson = null;

                        // 1. Initial Cache Check
                        const cached = localStorage.getItem(CACHE_KEY);
                        if (cached) {
                            try {
                                const parsed = JSON.parse(cached);
                                if (Date.now() - parsed.timestamp < 30 * 60 * 1000) { // 30 mins freshness
                                    return parsed.data;
                                }
                            } catch (e) {}
                        }

                        const baseParams = `latitude=${lat.toFixed(5)}&longitude=${lng.toFixed(5)}&current_weather=true&daily=weathercode,temperature_2m_max,temperature_2m_min,sunrise,sunset&hourly=weathercode,cloudcover,cloudcover_low,cloudcover_mid,cloudcover_high,visibility,relative_humidity_2m,dew_point_2m,temperature_2m,precipitation_probability,is_day,windspeed_10m,windspeed_80m&timezone=Europe%2FLondon&windspeed_unit=mph`;
                        
                        // Concurrent Racing Strategies (Fixes long load times)
                        const strategies = [
                            // Strategy A: Direct Open-Meteo (Fastest)
                            (async () => {
                                const res = await fetchWithTimeout(`https://api.open-meteo.com/v1/forecast?${baseParams}`, 3000);
                                if (!res.ok) throw new Error("OM Direct failed");
                                return await res.json();
                            })(),
                            // Strategy B: Open-Meteo via AllOrigins (Bypasses IP Blocks)
                            (async () => {
                                const res = await fetchWithTimeout(`https://api.allorigins.win/raw?url=${encodeURIComponent(`https://api.open-meteo.com/v1/forecast?${baseParams}`)}`, 4000);
                                if (!res.ok) throw new Error("OM Proxy failed");
                                return await res.json();
                            })(),
                            // Strategy C: Wttr.in Fallback Mapper
                            fetchWttrFallback(lat, lng),
                            // Strategy D: Met.no (Norway) Fallback Mapper
                            fetchMetNoFallback(lat, lng)
                        ];

                        try {
                            // Race all strategies concurrently. The first one to successfully resolve wins!
                            weatherJson = await new Promise((resolve, reject) => {
                                let errors = [];
                                strategies.forEach(p => p.then(data => {
                                    if (data && data.current_weather) resolve(data);
                                    else throw new Error("Invalid format");
                                }).catch(e => {
                                    errors.push(e);
                                    if (errors.length === strategies.length) reject(new Error("All strategies failed"));
                                }));
                            });
                            
                            localStorage.setItem(CACHE_KEY, JSON.stringify({ timestamp: Date.now(), data: weatherJson }));
                            return weatherJson;
                        } catch (e) {
                            console.warn("Weather strategy failed, cascading to backup:", e.message);
                        }

                        // Ultimate fallback: Use stale cache if all strategies failed but we have old data
                        if (cached) {
                            try {
                                const parsed = JSON.parse(cached);
                                return parsed.data;
                            } catch(e) {}
                        }

                        throw new Error("All weather sources failed to load and no cache available.");
                    };

                    try {
                        // Execute Weather Fetching and Aurora Fetching simultaneously instead of sequentially
                        const [weatherJson, { auroraDays, liveSolar, histories }] = await Promise.all([
                            getWeatherTask(),
                            fetchAuroraDataEnsemble()
                        ]);

                        const expectedCoastLng = -1.45 - ((lat - 55.0) * 0.75);
                        const isCoastal = lat >= 54.7 && lat <= 56.0 && lng >= (expectedCoastLng - 0.15);

                        if(isMounted) {
                            setData({ 
                                weather: weatherJson, 
                                tides: isCoastal ? getTideTimes() : null, 
                                aurora: auroraDays,
                                liveSolar: liveSolar, 
                                solarHistory: histories.solarHistory,
                                asHistory: histories.asHistory
                            });
                            if (isInitial) setLoading(false);
                        }
                    } catch (err) {
                        console.warn("Failed to fetch live conditions:", err.message);
                        if(isMounted && isInitial) { setErrorMsg("Failed to connect to weather service."); setLoading(false); }
                    }
                };

                fetchConditions(true);
                const intervalId = setInterval(() => { fetchConditions(false); }, 5 * 60 * 1000); 

                return () => { isMounted = false; clearInterval(intervalId); };
            }, [lat, lng]);

            const renderSingleChart = (dataset, chartKey) => {
                if (!dataset || dataset.length === 0) return null;
                
                const validData = dataset.filter(d => d[chartKey] !== null && !isNaN(d[chartKey]));
                if (validData.length < 2) return <div className="h-24 flex items-center justify-center text-[10px] font-bold text-slate-400 uppercase tracking-widest bg-slate-50 rounded-xl">No recent data</div>;

                const min = Math.min(...validData.map(d => d[chartKey]));
                const max = Math.max(...validData.map(d => d[chartKey]));
                
                const range = max === min ? (max === 0 ? 1 : Math.abs(max * 0.1)) : (max - min);
                const padding = range * 0.15;
                const paddedMin = min - padding;
                const paddedMax = max + padding;
                const paddedRange = paddedMax - paddedMin;

                let color = '#10b981';
                if (chartKey === 'bz') color = (validData[validData.length-1]?.[chartKey] < 0 ? '#ef4444' : '#f59e0b');
                if (chartKey === 'speed') color = '#8b5cf6';
                if (chartKey === 'asIndex') color = '#0ea5e9';

                const points = dataset.map((d, i) => {
                    if (d[chartKey] === null || isNaN(d[chartKey])) return null;
                    const x = (i / (dataset.length - 1)) * 100;
                    const y = 100 - (((d[chartKey] - paddedMin) / paddedRange) * 100);
                    return { x, y, val: d[chartKey], time: d.timeLabel };
                }).filter(Boolean);

                const polylinePoints = points.map(p => `${p.x},${p.y}`).join(' ');
                const firstX = points[0].x;
                const lastX = points[points.length - 1].x;
                const fillPoints = `${firstX},100 ${polylinePoints} ${lastX},100`;

                let zeroLine = null;
                if (chartKey === 'bz' && paddedMax > 0 && paddedMin < 0) {
                    const zeroY = 100 - (((0 - paddedMin) / paddedRange) * 100);
                    zeroLine = (
                        <g>
                            <line x1="0" y1={zeroY} x2="100" y2={zeroY} stroke="#cbd5e1" strokeWidth="0.5" strokeDasharray="2 2" />
                            <text x="99" y={zeroY - 2} fontSize="5" fill="#94a3b8" fontWeight="bold" textAnchor="end">0</text>
                        </g>
                    );
                }

                const formatVal = (v) => {
                    if (chartKey === 'speed') return Math.round(v);
                    if (chartKey === 'asIndex') return Math.round(v) > 0 ? `+${Math.round(v)}` : `${Math.round(v)}`;
                    if (chartKey === 'bz') return `${v > 0 ? '+' : ''}${v.toFixed(1)}`;
                    return v.toFixed(1);
                };

                const midIdx = Math.floor((dataset.length - 1) / 2);
                const lastIdx = dataset.length - 1;

                return (
                    <div className="flex flex-col w-full relative animate-in fade-in">
                        <div className="h-24 w-full relative mb-1 flex">
                            <div className="absolute left-0 top-0 bottom-0 w-8 flex flex-col justify-between items-end text-[8px] font-bold text-slate-400 pb-1 pr-1.5 z-10 pointer-events-none">
                                <span>{formatVal(max)}</span>
                                <span>{formatVal(min)}</span>
                            </div>

                            <div className="flex-1 ml-8 relative border-b border-l border-slate-200">
                                <svg viewBox="0 0 100 100" preserveAspectRatio="none" className="w-full h-full overflow-visible">
                                    <defs>
                                        <linearGradient id={`grad-${chartKey}`} x1="0" x2="0" y1="0" y2="1">
                                            <stop offset="0%" stopColor={color} stopOpacity="0.25" />
                                            <stop offset="100%" stopColor={color} stopOpacity="0.0" />
                                        </linearGradient>
                                    </defs>
                                    {zeroLine}
                                    
                                    <polygon points={fillPoints} fill={`url(#grad-${chartKey})`} />
                                    <polyline points={polylinePoints} fill="none" stroke={color} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
                                    
                                    {points.map((p, i) => (
                                        <g key={i} className="group">
                                            <circle cx={p.x} cy={p.y} r="2" fill="white" stroke={color} strokeWidth="1.5" className="transition-all cursor-pointer" />
                                            <circle cx={p.x} cy={p.y} r="8" fill="transparent" className="cursor-pointer" />
                                            <text x={p.x} y={p.y - 4} fontSize="6" fill={color} fontWeight="bold" textAnchor={p.x > 80 ? "end" : p.x < 20 ? "start" : "middle"} className="opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none drop-shadow-md">
                                                {formatVal(p.val)}
                                            </text>
                                        </g>
                                    ))}
                                </svg>
                            </div>
                        </div>
                        
                        <div className="flex justify-between text-[8px] md:text-[9px] text-slate-400 font-bold uppercase tracking-widest pl-8 pr-1 mt-1">
                            <span>{dataset[0]?.timeLabel}</span>
                            <span>{dataset[midIdx]?.timeLabel}</span>
                            <span>{dataset[lastIdx]?.timeLabel}</span>
                        </div>
                    </div>
                );
            };

            if (loading) {
                return (
                    <div className="pt-2 pb-6 mt-2">
                        <div className="bg-white border border-slate-200 shadow-sm p-8 rounded-2xl flex flex-col items-center justify-center w-full min-h-[250px] animate-in fade-in">
                            <div className="w-10 h-10 border-4 border-slate-100 border-t-sky-500 rounded-full animate-spin mb-4"></div>
                            <span className="text-[10px] md:text-xs font-black uppercase tracking-widest text-slate-800 mb-1">Fetching Live Data</span>
                            <span className="text-[9px] md:text-[10px] font-bold text-slate-400 text-center max-w-[250px]">Connecting to weather networks and space observation satellites...</span>
                        </div>
                    </div>
                );
            }

            if (errorMsg || !data.weather || !data.weather.current_weather) {
                return (
                    <div className="p-4 border border-red-100 bg-red-50 rounded-2xl mt-4 text-red-600 text-xs font-bold flex items-center">
                        <Icon name="cloud" size={16} className="mr-2" /> Live conditions temporarily unavailable.
                    </div>
                );
            }

            const getWeatherInfo = (code, isNight = false) => {
                if (weatherMap && weatherMap.codes && weatherMap.codes[code]) {
                    const entry = weatherMap.codes[code];
                    return {
                        icon: (isNight && entry.nightIcon) ? entry.nightIcon : entry.icon,
                        text: (isNight && entry.nightText) ? entry.nightText : entry.text
                    };
                }
                if (code === 0) return { icon: isNight ? "moon" : "sun", text: isNight ? "Clear" : "Sunny" };
                if (code === 1 || code === 2) return { icon: isNight ? "cloudMoon" : "cloudSun", text: isNight ? "P. Cloudy" : "Sunny Intervals" };
                if (code === 3) return { icon: "cloud", text: "Cloudy" };
                return { icon: isNight ? "moon" : "sun", text: "Clear" };
            };

            const cw = data.weather.current_weather;
            const currentInfo = getWeatherInfo(cw.weathercode);
            const daily = data.weather.daily;
            const hourly = data.weather.hourly;

            const todayDate = daily?.sunrise?.[0] ? new Date(daily.sunrise[0]) : new Date();
            const azimuths = getSolarAzimuths(lat, todayDate);

            let exactMoonrise = "--:--";
            if (window.SunCalc) {
                const now = new Date();
                let moonTimes = window.SunCalc.getMoonTimes(now, lat, lng);
                
                if (!moonTimes.rise) {
                    const tomorrow = new Date(now);
                    tomorrow.setDate(tomorrow.getDate() + 1);
                    moonTimes = window.SunCalc.getMoonTimes(tomorrow, lat, lng);
                }
                
                if (moonTimes.rise) {
                    exactMoonrise = moonTimes.rise.toLocaleTimeString('en-GB', {timeZone: 'Europe/London', hour: '2-digit', minute:'2-digit'});
                }
            } else {
                exactMoonrise = getApproxMoonrise();
            }

            const todayInfo = {
                sunrise: daily?.sunrise?.[0] ? new Date(daily.sunrise[0]).toLocaleTimeString('en-GB', {timeZone: 'Europe/London', hour: '2-digit', minute:'2-digit'}) : "--:--",
                sunset: daily?.sunset?.[0] ? new Date(daily.sunset[0]).toLocaleTimeString('en-GB', {timeZone: 'Europe/London', hour: '2-digit', minute:'2-digit'}) : "--:--",
                sunriseAzimuth: azimuths.sunrise,
                sunsetAzimuth: azimuths.sunset,
                moonrise: exactMoonrise
            };
            
            const hourlyForecastData = (() => {
                if (!hourly || !hourly.temperature_2m) return null;
                const now = new Date();
                const currentHour = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours()).getTime();
                
                const result = [];
                for (let i = 0; i < hourly.time.length; i++) {
                    const hourTimeStr = hourly.time[i];
                    const hourDate = new Date(hourTimeStr);
                    const hourTime = hourDate.getTime();
                    
                    if (hourTime >= currentHour && result.length < 24) {
                        const timeLabel = hourTime === currentHour ? 'Now' : hourDate.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' });
                        const temp = Math.round(hourly.temperature_2m[i]);
                        const precip = hourly.precipitation_probability ? Math.round(hourly.precipitation_probability[i]) : 0;
                        const cloud = hourly.cloudcover ? Math.round(hourly.cloudcover[i]) : 0;
                        const wind = hourly.windspeed_10m ? Math.round(hourly.windspeed_10m[i]) : 0;
                        const weatherCode = hourly.weathercode[i];
                        const isNight = hourly.is_day ? hourly.is_day[i] === 0 : false;
                        
                        result.push({
                            time: timeLabel,
                            temp,
                            precip,
                            cloud,
                            wind,
                            isNight,
                            info: getWeatherInfo(weatherCode, isNight)
                        });
                    }
                }
                return result;
            })();

            const astroDays = [0, 1, 2].map(dayIndex => {
                if (!daily?.sunset?.[dayIndex] || !daily?.sunrise?.[dayIndex + 1] || !hourly?.time || !hourly?.cloudcover) return null;
                const sunsetTime = new Date(daily.sunset[dayIndex]).getTime();
                const sunriseTime = new Date(daily.sunrise[dayIndex + 1]).getTime();
                const dateObj = new Date(daily.sunset[dayIndex]);
                let dayName = 'Tonight';
                if (dayIndex === 1) dayName = 'Tomorrow Night';
                if (dayIndex === 2) dayName = dateObj.toLocaleDateString('en-GB', { weekday: 'long' }) + ' Night';

                const hourlyData = [];
                for (let i = 0; i < hourly.time.length; i++) {
                    const hourTime = new Date(hourly.time[i]).getTime();
                    if (hourTime >= sunsetTime && hourTime <= sunriseTime) {
                        const date = new Date(hourTime);
                        const timeStr = date.toLocaleTimeString('en-GB', { timeZone: 'Europe/London', hour: '2-digit', minute: '2-digit' });
                        const weatherCode = hourly.weathercode[i];
                        
                        // Core Data Values
                        // Added missing Math.round() fix here to prevent long decimals stretching the box
                        const cloud = Math.round(hourly.cloudcover[i] || 0); 
                        const cloudHigh = hourly.cloudcover_high ? Math.round(hourly.cloudcover_high[i]) : 0;
                        const vis = hourly.visibility ? hourly.visibility[i] : 24000;
                        const hum = hourly.relative_humidity_2m ? Math.round(hourly.relative_humidity_2m[i]) : 50;
                        const temp = hourly.temperature_2m[i];
                        const dew = hourly.dew_point_2m ? hourly.dew_point_2m[i] : (temp - 5);
                        const w10 = hourly.windspeed_10m ? hourly.windspeed_10m[i] : 0;
                        const w80 = hourly.windspeed_80m ? hourly.windspeed_80m[i] : w10;
                        
                        // Astro Analysis 1: Seeing (Atmospheric Turbulence via Wind Shear Profile)
                        const windShear = Math.abs(w80 - w10);
                        let seeing = "Avg";
                        if (windShear > 15 || w80 > 25) seeing = "Poor";
                        else if (windShear > 8 || w80 > 15) seeing = "Avg";
                        else if (windShear <= 4 && w80 <= 10) seeing = "Excl";
                        else seeing = "Good";
                        
                        // Astro Analysis 2: Transparency (Clarity / Haze / Fog)
                        let transparency = "Avg";
                        if (cloudHigh > 60 || vis < 8000 || hum > 90) transparency = "Poor";
                        else if (cloudHigh > 30 || vis < 15000 || hum > 80) transparency = "Avg";
                        else if (cloudHigh < 10 && vis > 20000 && hum < 70) transparency = "Excl";
                        else transparency = "Good";

                        // Astro Analysis 3: Dew Risk (Temperature dropping towards Dew Point)
                        const dewSpread = temp - dew;
                        let dewRisk = "Low";
                        if (dewSpread <= 1.0 || hum >= 95) dewRisk = "High";
                        else if (dewSpread <= 2.0 || hum >= 85) dewRisk = "Med";

                        // Color Coding Logic (Astro Specific Penalty Score)
                        let penalty = 0;
                        if (cloud > 20) penalty += (cloud - 20) * 1.5;
                        if (vis < 15000) penalty += 15;
                        if (seeing === "Poor") penalty += 20;
                        if (transparency === "Poor") penalty += 20;
                        
                        let colorClass = "text-red-700 bg-red-50 border-red-200"; 
                        if (penalty <= 15 && cloud <= 20) colorClass = "text-emerald-700 bg-emerald-50 border-emerald-200"; 
                        else if (penalty <= 40 && cloud <= 45) colorClass = "text-lime-700 bg-lime-50 border-lime-200"; 
                        else if (penalty <= 75 && cloud <= 75) colorClass = "text-amber-700 bg-amber-50 border-amber-200"; 

                        hourlyData.push({
                            time: timeStr, 
                            cloud, 
                            seeing, 
                            transparency, 
                            dewRisk,
                            moonIllumination: getMoonIllumination(hourTime),
                            info: getWeatherInfo(weatherCode, true), 
                            colorClass
                        });
                    }
                }
                return hourlyData.length > 0 ? { dayName, hourlyData } : null;
            }).filter(Boolean);

            const forecastDays = [0, 1, 2].map(i => {
                if (!daily || !daily.time[i]) return null;
                const date = new Date(daily.time[i]);
                const dayName = i === 0 ? 'Today' : date.toLocaleDateString('en-GB', { weekday: 'short' });
                const dateStr = daily.time[i];
                const targetHour = `${dateStr}T13:00`;
                const hourIdx = hourly?.time?.findIndex(t => t === targetHour);
                const codeToUse = (hourIdx !== -1 && hourIdx !== undefined) ? hourly.weathercode[hourIdx] : daily.weathercode[i];
                const info = getWeatherInfo(codeToUse);
                return { dayName, icon: info.icon, max: Math.round(daily.temperature_2m_max[i]), min: Math.round(daily.temperature_2m_min[i]) };
            }).filter(Boolean);

            return (
                <div className="pt-2 pb-6 mt-2">
                    {/* Weather & Astro Widget */}
                    <div className="bg-white border border-slate-200 shadow-sm p-4 md:p-5 rounded-2xl flex flex-col justify-between relative overflow-hidden w-full">
                        <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center w-full gap-4 sm:gap-0">
                            <div>
                                <div className="flex items-center text-slate-500 mb-2 z-10">
                                    <span className="text-[10px] font-black uppercase tracking-widest text-slate-400">Live Weather</span>
                                </div>
                                <div className="flex items-center space-x-3 z-10 my-1">
                                    <Icon name={currentInfo.icon} size={32} className="text-slate-800" />
                                    <span className="text-3xl md:text-4xl font-black tracking-tighter text-slate-900">{Math.round(cw.temperature)}°</span>
                                </div>
                                <div className="flex items-center text-slate-500 text-[11px] md:text-xs font-bold tracking-wide z-10">
                                    <span className="mr-3">{currentInfo.text}</span>
                                    <Icon name="wind" size={12} className="mr-1" />
                                    <span>{Math.round(cw.windspeed)} mph</span>
                                </div>
                            </div>
                            
                            {forecastDays.length > 0 && (
                                <div className="flex gap-4 md:gap-5 mt-1 sm:mt-0 w-full sm:w-auto justify-between sm:justify-end border-t border-slate-100 sm:border-0 pt-3 sm:pt-0">
                                    {forecastDays.map((day, idx) => (
                                        <div key={idx} className="flex flex-col items-center">
                                            <span className="text-[9px] md:text-[10px] font-black uppercase tracking-widest text-slate-400 mb-1">{day.dayName}</span>
                                            <Icon name={day.icon} size={24} className="text-slate-600 mb-1" />
                                            <span className="text-[10px] md:text-[11px] font-bold text-slate-800">{day.max}° <span className="text-slate-400 font-medium">{day.min}°</span></span>
                                        </div>
                                    ))}
                                </div>
                            )}
                        </div>
                        
                        {hourlyForecastData && hourlyForecastData.length > 0 && (
                            <div className="mt-5 pt-5 border-t border-slate-100 w-full overflow-hidden">
                                <div className="flex items-center mb-3">
                                    <Icon name="cloudSun" size={16} className="text-sky-600 mr-2 shrink-0" />
                                    <span className="text-[10px] md:text-xs font-bold text-slate-800 uppercase tracking-widest">Today's Hourly Forecast</span>
                                </div>
                                <div className="flex overflow-x-auto gap-2 pb-2 custom-scrollbar overscroll-x-contain">
                                    {hourlyForecastData.map((hour, hIdx) => (
                                        <div key={hIdx} className="flex flex-col items-center justify-center px-3 py-2.5 rounded-xl border border-slate-100 bg-slate-50 min-w-[72px] shrink-0">
                                            <span className="text-[10px] font-black mb-1 opacity-80">{hour.time}</span>
                                            <Icon name={hour.info.icon} size={18} className="my-1 text-slate-700" />
                                            <span className="text-[13px] font-black">{hour.temp}°</span>
                                            
                                            <div className="flex flex-col items-center gap-1.5 w-full mt-2 pt-2 border-t border-slate-200/60">
                                                <span className={`text-[9px] font-bold flex items-center justify-center w-full ${hour.precip > 0 ? 'text-sky-600' : 'text-slate-400'}`} title="Rain Probability">
                                                    <Icon name="rain" size={10} className="mr-1" /> {hour.precip}%
                                                </span>
                                                <span className="text-[9px] font-bold text-slate-500 flex items-center justify-center w-full" title="Cloud Cover">
                                                    <Icon name="cloud" size={10} className="mr-1 opacity-70" /> {hour.cloud}%
                                                </span>
                                                <span className={`text-[9px] font-bold flex items-center justify-center w-full ${hour.isNight ? 'text-indigo-500' : 'text-amber-500'}`} title={hour.isNight ? "Clear Sky" : "Sunshine"}>
                                                    <Icon name={hour.isNight ? "moon" : "sun"} size={10} className="mr-1 opacity-70" /> {100 - hour.cloud}%
                                                </span>
                                                <span className="text-[9px] font-bold text-slate-500 flex items-center justify-center w-full" title="Wind Speed">
                                                    <Icon name="wind" size={10} className="mr-1 opacity-70" /> {hour.wind}mph
                                                </span>
                                            </div>
                                        </div>
                                    ))}
                                </div>
                            </div>
                        )}

                        <div className="grid grid-cols-3 gap-2 mt-4 pt-4 border-t border-slate-100">
                            <div className="flex flex-col items-center text-center">
                                <span className="text-[8px] md:text-[9px] font-black uppercase tracking-widest text-slate-400 mb-1">Sunrise</span>
                                <span className="text-[10px] md:text-[11px] font-bold text-amber-600">{todayInfo.sunrise}</span>
                                <span className="text-[8px] font-bold text-slate-400 mt-0.5">{todayInfo.sunriseAzimuth}</span>
                            </div>
                            <div className="flex flex-col items-center text-center">
                                <span className="text-[8px] md:text-[9px] font-black uppercase tracking-widest text-slate-400 mb-1">Sunset</span>
                                <span className="text-[10px] md:text-[11px] font-bold text-orange-600">{todayInfo.sunset}</span>
                                <span className="text-[8px] font-bold text-slate-400 mt-0.5">{todayInfo.sunsetAzimuth}</span>
                            </div>
                            <div className="flex flex-col items-center text-center">
                                <span className="text-[8px] md:text-[9px] font-black uppercase tracking-widest text-slate-400 mb-1">Moonrise</span>
                                <span className="text-[10px] md:text-[11px] font-bold text-indigo-600">{todayInfo.moonrise}</span>
                                <span className="text-[8px] font-bold text-transparent mt-0.5">-</span>
                            </div>
                        </div>

                        {data.tides && (
                            <div className="mt-4 pt-4 border-t border-slate-100">
                                <div className="flex justify-between items-center bg-sky-50 rounded-xl p-3 px-4 border border-sky-100">
                                    <div className="flex items-center text-sky-800">
                                        <Icon name="waves" size={16} className="mr-2" />
                                        <span className="text-[10px] md:text-xs font-black uppercase tracking-widest">Coastal Tide</span>
                                    </div>
                                    <div className="flex gap-4 md:gap-6 text-sky-900">
                                        <div className="flex flex-col text-right">
                                            <span className="text-[8px] md:text-[9px] font-black uppercase tracking-widest text-sky-600/70 mb-0.5">Next High</span>
                                            <span className="text-[10px] md:text-[11px] font-bold">{data.tides.nextHigh || '--:--'}</span>
                                        </div>
                                        <div className="flex flex-col text-right">
                                            <span className="text-[8px] md:text-[9px] font-black uppercase tracking-widest text-sky-600/70 mb-0.5">Next Low</span>
                                            <span className="text-[10px] md:text-[11px] font-bold">{data.tides.nextLow || '--:--'}</span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        )}

                        {data.aurora && data.liveSolar && (
                            <div className="mt-5 pt-5 border-t border-slate-100">
                                <div className="flex items-center justify-between mb-4">
                                    <div className="flex items-center">
                                        <Icon name="sparkles" size={16} className="textemerald-600 mr-2 shrink-0" />
                                        <span className="text-[10px] md:text-xs font-bold text-slate-800 uppercase tracking-widest">Live Solar & Aurora</span>
                                    </div>
                                </div>
                                
                                {activeAuroraInfo && auroraInfoData[activeAuroraInfo] && (
                                    <div className="mb-4 bg-sky-50 border border-sky-100 rounded-2xl p-4 relative animate-in text-sky-900 shadow-sm">
                                        <button onClick={() => setActiveAuroraInfo(null)} className="absolute top-2 right-2 p-2 text-sky-400 hover:text-sky-600 transition-colors">
                                            <Icon name="x" size={16} />
                                        </button>
                                        <h4 className="font-black text-[10px] md:text-[11px] uppercase tracking-widest mb-2 pr-6">{auroraInfoData[activeAuroraInfo].title}</h4>
                                        <p className="text-[11px] md:text-xs leading-relaxed opacity-90">{auroraInfoData[activeAuroraInfo].desc}</p>
                                    </div>
                                )}

                                <div className="grid grid-cols-2 gap-3 md:gap-4 mb-6">
                                    <div className={`relative flex flex-col items-center justify-center p-4 md:p-5 rounded-2xl border-[1.5px] shadow-sm ${getAsClass(data.liveSolar.asIndex)}`}>
                                        <button onClick={() => toggleAuroraInfo('asIndex')} className="absolute top-2.5 right-2.5 text-current opacity-40 hover:opacity-100 transition-opacity p-1" title="What is AS Index?">
                                            <Icon name="info" size={14} />
                                        </button>
                                        <span className="text-[10px] md:text-[11px] font-black uppercase tracking-widest mb-1 opacity-70">AS INDEX</span>
                                        <div className="flex items-baseline justify-center gap-1 w-full my-1.5">
                                            <span className="text-3xl min-[375px]:text-4xl md:text-5xl font-black tracking-tighter leading-none">{data.liveSolar.asIndex !== null ? (data.liveSolar.asIndex > 0 ? `+${Math.round(Number(data.liveSolar.asIndex))}` : Math.round(Number(data.liveSolar.asIndex))) : '--'}</span>
                                            <span className="text-xs min-[375px]:text-sm font-bold opacity-80">nT</span>
                                        </div>
                                        <span className="text-[10px] font-bold uppercase mt-1 opacity-90 tracking-wide">{getAsLabel(data.liveSolar.asIndex)}</span>
                                    </div>
                                    <div className={`relative flex flex-col items-center justify-center p-4 md:p-5 rounded-2xl border-[1.5px] shadow-sm ${getBzClass(data.liveSolar.bz)}`}>
                                        <button onClick={() => toggleAuroraInfo('bz')} className="absolute top-2.5 right-2.5 text-current opacity-40 hover:opacity-100 transition-opacity p-1" title="What is IMF Bz?">
                                            <Icon name="info" size={14} />
                                        </button>
                                        <span className="text-[10px] md:text-[11px] font-black uppercase tracking-widest mb-1 opacity-70">IMF BZ</span>
                                        <div className="flex items-baseline justify-center gap-1 w-full my-1.5">
                                            <span className="text-3xl min-[375px]:text-4xl md:text-5xl font-black tracking-tighter leading-none">{data.liveSolar.bz !== null ? `${data.liveSolar.bz > 0 ? '+' : ''}${Number(data.liveSolar.bz).toFixed(1)}` : '--'}</span>
                                            <span className="text-xs min-[375px]:text-sm font-bold opacity-80">nT</span>
                                        </div>
                                        <span className="text-[10px] font-bold uppercase mt-1 opacity-90 tracking-wide">{getBzLabel(data.liveSolar.bz)}</span>
                                    </div>
                                    <div className={`relative flex flex-col items-center justify-center p-4 md:p-5 rounded-2xl border-[1.5px] shadow-sm ${getSpeedClass(data.liveSolar.speed)}`}>
                                        <button onClick={() => toggleAuroraInfo('speed')} className="absolute top-2.5 right-2.5 text-current opacity-40 hover:opacity-100 transition-opacity p-1" title="What is Solar Wind Speed?">
                                            <Icon name="info" size={14} />
                                        </button>
                                        <span className="text-[10px] md:text-[11px] font-black uppercase tracking-widest mb-1 opacity-70">SPEED</span>
                                        <div className="flex items-baseline justify-center gap-1 w-full my-1.5">
                                            <span className="text-3xl min-[375px]:text-4xl md:text-5xl font-black tracking-tighter leading-none">{data.liveSolar.speed !== null ? Math.round(Number(data.liveSolar.speed)) : '--'}</span>
                                            <span className="text-xs min-[375px]:text-sm font-bold opacity-80">km/s</span>
                                        </div>
                                        <span className="text-[10px] font-bold uppercase mt-1 opacity-90 tracking-wide">{getSpeedLabel(data.liveSolar.speed)}</span>
                                    </div>
                                    <div className={`relative flex flex-col items-center justify-center p-4 md:p-5 rounded-2xl border-[1.5px] shadow-sm ${getDensityClass(data.liveSolar.density)}`}>
                                        <button onClick={() => toggleAuroraInfo('density')} className="absolute top-2.5 right-2.5 text-current opacity-40 hover:opacity-100 transition-opacity p-1" title="What is Solar Wind Density?">
                                            <Icon name="info" size={14} />
                                        </button>
                                        <span className="text-[10px] md:text-[11px] font-black uppercase tracking-widest mb-1 opacity-70">DENSITY</span>
                                        <div className="flex items-baseline justify-center gap-1 w-full my-1.5">
                                            <span className="text-3xl min-[375px]:text-4xl md:text-5xl font-black tracking-tighter leading-none">{data.liveSolar.density !== null ? Number(data.liveSolar.density).toFixed(1) : '--'}</span>
                                            <span className="text-xs min-[375px]:text-sm font-bold opacity-80">p/cm³</span>
                                        </div>
                                        <span className="text-[10px] font-bold uppercase mt-1 opacity-90 tracking-wide">{getDensityLabel(data.liveSolar.density)}</span>
                                    </div>
                                </div>
                                <div className="grid grid-cols-3 gap-2.5">
                                    {data.aurora.map((day, idx) => {
                                        let colorClass = "bg-slate-50 border-slate-200 text-slate-700";
                                        if (day.kp >= 6) colorClass = "bg-rose-50 border-rose-200 text-rose-700";
                                        else if (day.kp >= 4.6) colorClass = "bg-emerald-50 border-emerald-200 text-emerald-700";
                                        else if (day.kp >= 3) colorClass = "bg-amber-50 border-amber-200 text-amber-700";
                                        
                                        return (
                                            <div key={idx} className={`relative flex flex-col items-center justify-center p-3 rounded-[1rem] border ${colorClass}`}>
                                                <button onClick={() => toggleAuroraInfo('kp')} className="absolute top-2 right-2 text-current opacity-40 hover:opacity-100 transition-opacity" title="What is the Kp Index?">
                                                    <Icon name="info" size={12} />
                                                </button>
                                                <span className="text-[9px] md:text-[10px] font-black uppercase tracking-widest mb-1 opacity-80 text-center mt-0.5">{day.dayName}</span>
                                                <span className="text-sm md:text-base font-black tracking-tight">Kp {day.kp.toFixed(1)}</span>
                                            </div>
                                        );
                                    })}
                                </div>
                                
                                {/* TREND CHARTS */}
                                {data.solarHistory && data.asHistory && (
                                    <div className="mt-6 flex flex-col gap-5">
                                        {/* AS INDEX GRAPH (60M / 10m Increments) */}
                                        <div className="bg-slate-50 border border-slate-100 rounded-2xl p-4 md:p-5 shadow-sm">
                                            <div className="flex justify-between items-center mb-2">
                                                <span className="text-[10px] font-black uppercase tracking-widest text-slate-500">AS INDEX (60M)</span>
                                            </div>
                                            {renderSingleChart(data.asHistory, 'asIndex')}
                                        </div>

                                        {/* SOLAR WIND GRAPH (2H / 15m Increments) */}
                                        <div className="bg-slate-50 border border-slate-100 rounded-2xl p-4 md:p-5 shadow-sm">
                                            <div className="flex flex-wrap items-center justify-between mb-4 gap-3">
                                                <span className="text-[10px] font-black uppercase tracking-widest text-slate-500 shrink-0">2-HOUR TREND (15M)</span>
                                                <div className="flex flex-wrap gap-1 bg-slate-200/60 p-1 rounded-xl shrink-0 ml-auto">
                                                    <button onClick={() => setActiveSolarChart('bz')} className={`text-[10px] font-bold px-3 py-1.5 rounded-lg transition-all ${activeSolarChart === 'bz' ? 'bg-white text-slate-800 shadow-sm' : 'text-slate-500 hover:text-slate-700'}`}>Bz</button>
                                                    <button onClick={() => setActiveSolarChart('speed')} className={`text-[10px] font-bold px-3 py-1.5 rounded-lg transition-all ${activeSolarChart === 'speed' ? 'bg-white text-slate-800 shadow-sm' : 'text-slate-500 hover:text-slate-700'}`}>Speed</button>
                                                    <button onClick={() => setActiveSolarChart('density')} className={`text-[10px] font-bold px-3 py-1.5 rounded-lg transition-all ${activeSolarChart === 'density' ? 'bg-white text-slate-800 shadow-sm' : 'text-slate-500 hover:text-slate-700'}`}>Density</button>
                                                </div>
                                            </div>
                                            {renderSingleChart(data.solarHistory, activeSolarChart)}
                                        </div>
                                    </div>
                                )}
                            </div>
                        )}

                        {astroDays.length > 0 && (
                            <div className="mt-5 pt-5 border-t border-slate-100">
                                <div className="flex flex-wrap items-center justify-between mb-4 gap-3 w-full">
                                    <div className="flex items-center shrink-0">
                                        <Icon name="moon" size={16} className="text-indigo-600 mr-2 shrink-0" />
                                        <span className="text-[10px] md:text-xs font-bold text-slate-800 uppercase tracking-widest">Astro Forecast <span className="hidden min-[375px]:inline">(Sunset to Sunrise)</span></span>
                                    </div>
                                    <div className="flex items-center gap-2 shrink-0 ml-auto">
                                        <div className="flex flex-col text-[8px] md:text-[9px] font-black text-slate-500 uppercase tracking-widest bg-slate-50 px-3 py-1.5 rounded-lg border border-slate-200 shadow-sm shrink-0 leading-tight gap-0.5 text-right">
                                            <span>Detailed Astro Metrics</span>
                                            <span className="text-slate-400">Seeing • Transp • Dew</span>
                                        </div>
                                        <button 
                                            onClick={() => setShowAstroMetricsInfo(!showAstroMetricsInfo)} 
                                            className={`p-2 rounded-lg border shadow-sm transition-colors shrink-0 ${showAstroMetricsInfo ? 'bg-indigo-100 border-indigo-200 text-indigo-600' : 'bg-slate-50 border-slate-200 text-slate-400 hover:text-indigo-500 hover:bg-indigo-50'}`} 
                                            title="What do these metrics mean?"
                                        >
                                            <Icon name="info" size={18} />
                                        </button>
                                    </div>
                                </div>
                                
                                {showAstroMetricsInfo && (
                                    <div className="mb-5 bg-indigo-50/80 border border-indigo-100 rounded-2xl p-4 md:p-5 relative animate-in text-indigo-900 shadow-sm">
                                        <button onClick={() => setShowAstroMetricsInfo(false)} className="absolute top-2.5 right-2.5 p-2 text-indigo-400 hover:text-indigo-600 transition-colors">
                                            <Icon name="x" size={16} />
                                        </button>
                                        <h4 className="font-black text-[10px] md:text-[11px] uppercase tracking-widest mb-3 pr-6 text-indigo-800 flex items-center gap-2">
                                            <Icon name="info" size={14} className="opacity-70" /> Understanding Astro Metrics
                                        </h4>
                                        <div className="space-y-3.5 text-[11px] md:text-xs leading-relaxed opacity-90">
                                            <p><strong className="font-black text-indigo-700 block mb-0.5">Seeing (Atmospheric Turbulence)</strong>Measures how much the air is moving. 'Excellent' seeing means the atmosphere is perfectly still, giving you crisp, pin-sharp stars. 'Poor' seeing means the stars will twinkle heavily and appear softer or bloated in your long exposures.</p>
                                            <p><strong className="font-black text-indigo-700 block mb-0.5">Transp. (Transparency)</strong>Measures the clarity of the sky, factoring in high-altitude haze, smoke, and moisture. 'Excellent' transparency provides a beautifully dark, high-contrast sky—essential for capturing faint details like the Milky Way or aurorae.</p>
                                            <p><strong className="font-black text-indigo-700 block mb-0.5">Dew (Lens Fogging Risk)</strong>Warns you when the air temperature is dropping dangerously close to the dew point. A 'High' risk means condensation is very likely to form on your camera lens, so you will need to use a USB lens heater to prevent it from fogging up during a time-lapse.</p>
                                        </div>
                                    </div>
                                )}
                                
                                <div className="flex flex-col gap-5">
                                    {astroDays.map((astroDay, idx) => (
                                        <div key={idx} className="flex flex-col">
                                            <span className="text-[9px] font-black text-slate-400 mb-2 uppercase tracking-widest">{astroDay.dayName}</span>
                                            <div className="flex overflow-x-auto gap-2 pb-2 custom-scrollbar overscroll-x-contain">
                                                {astroDay.hourlyData.map((hour, hIdx) => (
                                                    <div key={hIdx} className={`flex flex-col items-center justify-center px-3 py-2.5 rounded-xl border min-w-[86px] shrink-0 ${hour.colorClass}`}>
                                                        <span className="text-[10px] font-black mb-1 opacity-80">{hour.time}</span>
                                                        <Icon name={hour.info.icon} size={16} className="mb-2 text-current opacity-90" />
                                                        
                                                        <div className="flex flex-col w-full text-[8px] font-bold gap-[2px] mb-2 bg-white/30 p-1.5 rounded-md">
                                                            <div className="flex justify-between w-full items-center" title="Total Cloud Cover">
                                                                <span className="opacity-70">Cloud</span>
                                                                <span className="text-[9px] font-black">{hour.cloud}%</span>
                                                            </div>
                                                            <div className="flex justify-between w-full items-center" title="Atmospheric Transparency">
                                                                <span className="opacity-70">Transp.</span>
                                                                <span>{hour.transparency}</span>
                                                            </div>
                                                            <div className="flex justify-between w-full items-center" title="Astronomical Seeing (Atmospheric Turbulence)">
                                                                <span className="opacity-70">Seeing</span>
                                                                <span>{hour.seeing}</span>
                                                            </div>
                                                            <div className={`flex justify-between w-full items-center ${hour.dewRisk === 'High' ? 'text-blue-700 animate-pulse font-black' : ''}`} title="Dew Risk (Lens Fogging)">
                                                                <span className="opacity-70">Dew</span>
                                                                <span>{hour.dewRisk}</span>
                                                            </div>
                                                        </div>

                                                        <span className="text-[10px] font-black opacity-90 mt-auto flex items-center bg-white/40 px-1.5 py-0.5 rounded-md w-full justify-center" title="Moon Illumination">
                                                            <Icon name="moon" size={10} className="mr-1 opacity-70" /> {hour.moonIllumination}%
                                                        </span>
                                                    </div>
                                                ))}
                                            </div>
                                        </div>
                                    ))}
                                </div>
                            </div>
                        )}
                    </div>
                </div>
            );
        };
