// ------------------------------------------------------------------------ // almanac-calendar.js - Extended event calendar for the "What's Coming" // panel and getUpcomingEvents() export. // // Includes all events from COSMIC_CALENDAR plus multi-year entries. // Each entry has a 'latHint': // null = global / no hint // 'north' = better from northern latitudes // 'south' = better from southern latitudes // 'path:...' = specific eclipse path note // ------------------------------------------------------------------------ export const ALMANAC_CALENDAR = [ // 2026 events (covers rest of year from today) { id: 'lunar-eclipse-2026-mar', emoji: '🌕', title: 'Total Lunar Eclipse', desc: 'The Moon turns deep red as it passes through Earth\'s shadow. Visible from Europe, Africa, and the Americas.', start: '2026-03-03', peak: '2026-03-03', color: '#3a0a0a', textColor: '#ffd8d8', latHint: null, type: 'eclipse', }, { id: 'lyrids-2026', emoji: '☄️', title: 'Lyrid Meteor Shower', desc: 'Up to 20 meteors/hour at peak. Active Apr 16–25, best after midnight from a dark site.', start: '2026-04-16', peak: '2026-04-22', color: '#2a1a5a', textColor: '#e8d8ff', latHint: 'north', type: 'meteor', }, { id: 'eta-aquariids-2026', emoji: '☄️', title: 'Eta Aquariid Meteor Shower', desc: 'Debris from Halley\'s Comet — up to 50/hour before dawn. Best from southern latitudes but visible worldwide.', start: '2026-04-19', peak: '2026-05-06', color: '#2a1a5a', textColor: '#e8d8ff', latHint: 'south', type: 'meteor', }, { id: 'mars-conjunction-2026', emoji: '🔴', title: 'Mars & Venus Conjunction', desc: 'Mars and Venus appear strikingly close in the evening sky — a beautiful naked-eye pairing.', start: '2026-06-30', peak: '2026-07-01', color: '#2a1520', textColor: '#ffc8d8', latHint: null, type: 'planetary', }, { id: 'perseids-2026', emoji: '☄️', title: 'Perseid Meteor Shower', desc: 'One of the best showers of the year — up to 100/hour at peak, no need for a telescope.', start: '2026-07-17', peak: '2026-08-12', color: '#3a1a00', textColor: '#ffe8c0', latHint: 'north', type: 'meteor', }, { id: 'solar-eclipse-2026-aug', emoji: '🌑', title: 'Total Solar Eclipse', desc: 'The path of totality crosses Spain, Iceland, and Greenland. Partial eclipse visible across most of Europe.', start: '2026-08-12', peak: '2026-08-12', color: '#1a0a2a', textColor: '#d8c8f8', latHint: 'path:Spain, Iceland, Greenland — partial eclipse across UK & Europe', type: 'eclipse', }, { id: 'saturn-opposition-2026', emoji: '🪐', title: 'Saturn at Opposition', desc: 'Saturn is at its closest and brightest — rings tilted beautifully toward Earth. Visible all night.', start: '2026-09-23', peak: '2026-09-23', color: '#1a2a3a', textColor: '#c8e8ff', latHint: null, type: 'planetary', }, { id: 'orionids-2026', emoji: '☄️', title: 'Orionid Meteor Shower', desc: 'Fast, bright meteors from Halley\'s Comet — up to 25/hour. Active Oct 2 – Nov 7.', start: '2026-10-02', peak: '2026-10-21', color: '#2a1a5a', textColor: '#e8d8ff', latHint: null, type: 'meteor', }, { id: 'jupiter-opposition-2026', emoji: '🪐', title: 'Jupiter at Opposition', desc: 'Jupiter at its closest — you can see its cloud bands and four Galilean moons with binoculars.', start: '2026-10-08', peak: '2026-10-08', color: '#1a2a3a', textColor: '#c8e8ff', latHint: null, type: 'planetary', }, { id: 'leonids-2026', emoji: '☄️', title: 'Leonid Meteor Shower', desc: 'Fast, bright meteors from comet Tempel-Tuttle. Up to 15/hour at peak.', start: '2026-11-06', peak: '2026-11-17', color: '#2a1a5a', textColor: '#e8d8ff', latHint: null, type: 'meteor', }, { id: 'geminids-2026', emoji: '☄️', title: 'Geminid Meteor Shower', desc: 'The finest shower of the year — up to 150 meteors/hour, visible even before midnight.', start: '2026-12-04', peak: '2026-12-13', color: '#3a1a00', textColor: '#ffe8c0', latHint: 'north', type: 'meteor', }, { id: 'ursids-2026', emoji: '☄️', title: 'Ursid Meteor Shower', desc: 'A quieter shower near the winter solstice — circumpolar, so best from northern latitudes.', start: '2026-12-17', peak: '2026-12-22', color: '#2a1a5a', textColor: '#e8d8ff', latHint: 'north', type: 'meteor', }, // -- 2027 ------------------------------------------------------------- { id: 'quadrantids-2027', emoji: '☄️', title: 'Quadrantid Meteor Shower', desc: 'Up to 120 meteors/hour at peak — one of the strongest showers but with a very sharp peak. Best in the hours before dawn on 4 Jan.', start: '2027-01-01', peak: '2027-01-04', color: '#2a1a5a', textColor: '#e8d8ff', latHint: 'north', type: 'meteor', }, { id: 'annular-solar-eclipse-2027-feb', emoji: '🌑', title: 'Annular Solar Eclipse', desc: 'A "ring of fire" eclipse visible from parts of South America, Africa and the Indian Ocean. Partial eclipse across much of the southern hemisphere.', start: '2027-02-06', peak: '2027-02-06', color: '#1a0a2a', textColor: '#d8c8f8', latHint: 'path:South America, southern Africa, Indian Ocean', type: 'eclipse', }, { id: 'mars-opposition-2027', emoji: '🔴', title: 'Mars at Opposition', desc: 'Mars is at its closest and brightest — a vivid red beacon visible all night long. Good binoculars reveal its distinct colour.', start: '2027-02-19', peak: '2027-02-19', color: '#2a1520', textColor: '#ffc8d8', latHint: null, type: 'planetary', }, { id: 'lyrids-2027', emoji: '☄️', title: 'Lyrid Meteor Shower', desc: 'Up to 20 meteors/hour at peak. Note: bright waning gibbous moon may reduce visibility this year. Active Apr 16–25.', start: '2027-04-16', peak: '2027-04-23', color: '#2a1a5a', textColor: '#e8d8ff', latHint: 'north', type: 'meteor', }, { id: 'eta-aquariids-2027', emoji: '☄️', title: 'Eta Aquariid Meteor Shower', desc: 'Debris from Halley\'s Comet — up to 50/hour before dawn. New moon on 6 May means excellent dark skies this year.', start: '2027-04-19', peak: '2027-05-05', color: '#2a1a5a', textColor: '#e8d8ff', latHint: 'south', type: 'meteor', }, { id: 'perseids-2027', emoji: '☄️', title: 'Perseid Meteor Shower', desc: 'One of the best showers of the year — up to 100/hour at peak, no telescope needed. Active Jul 17 – Aug 24.', start: '2027-07-17', peak: '2027-08-13', color: '#3a1a00', textColor: '#ffe8c0', latHint: 'north', type: 'meteor', }, { id: 'total-solar-eclipse-2027-aug', emoji: '🌑', title: 'Total Solar Eclipse', desc: 'One of the longest total solar eclipses of the century. Path of totality crosses Morocco, Spain, Algeria, Libya, Egypt and Saudi Arabia.', start: '2027-08-02', peak: '2027-08-02', color: '#1a0a2a', textColor: '#d8c8f8', latHint: 'path:Morocco, Spain, Algeria, Libya, Egypt, Saudi Arabia', type: 'eclipse', }, { id: 'venus-jupiter-conjunction-2027', emoji: '🪐', title: 'Venus & Jupiter Conjunction', desc: 'Venus and Jupiter appear strikingly close together in the evening sky — a dazzling naked-eye pairing of the two brightest planets.', start: '2027-08-23', peak: '2027-08-25', color: '#1a2a3a', textColor: '#c8e8ff', latHint: null, type: 'planetary', }, { id: 'orionids-2027', emoji: '☄️', title: 'Orionid Meteor Shower', desc: 'Fast, bright meteors from Halley\'s Comet debris — up to 25/hour. Active Oct 2 – Nov 7.', start: '2027-10-02', peak: '2027-10-21', color: '#2a1a5a', textColor: '#e8d8ff', latHint: null, type: 'meteor', }, { id: 'leonids-2027', emoji: '☄️', title: 'Leonid Meteor Shower', desc: 'Fast meteors from comet Tempel-Tuttle. Up to 15/hour at peak. Active Nov 6–30.', start: '2027-11-06', peak: '2027-11-17', color: '#2a1a5a', textColor: '#e8d8ff', latHint: null, type: 'meteor', }, { id: 'geminids-2027', emoji: '☄️', title: 'Geminid Meteor Shower', desc: 'The finest shower of the year — up to 150 meteors/hour, visible even before midnight. Active Dec 4–20.', start: '2027-12-04', peak: '2027-12-14', color: '#3a1a00', textColor: '#ffe8c0', latHint: 'north', type: 'meteor', }, { id: 'ursids-2027', emoji: '☄️', title: 'Ursid Meteor Shower', desc: 'A quieter shower near the winter solstice — circumpolar, best from northern latitudes. Active Dec 17–26.', start: '2027-12-17', peak: '2027-12-22', color: '#2a1a5a', textColor: '#e8d8ff', latHint: 'north', type: 'meteor', }, ]; // Returns a location-aware visibility note for an almanac entry. // lat = user's latitude. export function getVisibilityNote(entry, lat) { if (!entry.latHint) return null; if (entry.latHint.startsWith('path:')) { return entry.latHint.replace('path:', '').trim(); } if (entry.latHint === 'north') { if (lat >= 45) return 'Well placed for your latitude'; if (lat >= 20) return 'Visible from your location'; return 'Better from northern latitudes'; } if (entry.latHint === 'south') { if (lat <= 10) return 'Well placed for your latitude'; if (lat <= 40) return 'Visible from your location'; return 'Better from southern latitudes'; } return null; } // --- MAIN ALMANAC EXPORT ------------------------------------------------- // Returns events with peak dates in the next 'days' days (default 90), // sorted by peak date, with a visibility note added. export function getUpcomingEvents(location, days = 90) { const today = new Date(); today.setHours(0, 0, 0, 0); const cutoff = new Date(today); cutoff.setDate(cutoff.getDate() + days); const todayStr = today.toISOString().slice(0, 10); const cutoffStr = cutoff.toISOString().slice(0, 10); return ALMANAC_CALENDAR .filter(ev => ev.peak >= todayStr && ev.peak <= cutoffStr) .sort((a, b) => a.peak.localeCompare(b.peak)) .map(ev => ({ ...ev, visibilityNote: getVisibilityNote(ev, location?.lat ?? 51), daysUntil: Math.round((new Date(ev.peak + 'T00:00Z') - today) / 86400000), })); }