/* Shared plain-language alert helpers (used by the weather app and the station dashboard) */ (() => { 'use strict'; const GLOSSARY = { 'heat advisory': 'Dangerously hot conditions expected. Limit time outdoors, drink plenty of water, and check on children, older adults and pets.', 'excessive heat watch': 'Conditions are favorable for life-threatening heat in the next day or two. Plan ahead.', 'excessive heat warning': 'Life-threatening heat is occurring or imminent. Avoid outdoor activity and stay cool.', 'extreme heat watch': 'Conditions are favorable for life-threatening heat in the next day or two. Plan ahead.', 'extreme heat warning': 'Life-threatening heat is occurring or imminent. Avoid outdoor activity and stay cool.', 'severe thunderstorm watch': 'Storms capable of damaging wind or large hail are possible in the area. Stay alert and be ready to take shelter.', 'severe thunderstorm warning': 'A severe storm with damaging wind and/or large hail is happening or imminent. Move indoors away from windows.', 'tornado watch': 'Conditions are favorable for tornadoes. Stay alert and know where you would take shelter.', 'tornado warning': 'A tornado is occurring or imminent. Take shelter immediately in the lowest, most interior room.', 'special weather statement': 'A short notice about a significant but non-warning weather event, often a strong storm, gusty winds, dense fog or sudden changes.', 'flood watch': 'Flooding is possible. Be prepared to move to higher ground and avoid low-lying areas.', 'flood advisory': 'Minor flooding is occurring or expected. Avoid flooded roads and low spots.', 'flood warning': 'Flooding is happening or imminent. Move to higher ground and never drive through flood water.', 'flash flood watch': 'Flash flooding is possible. Be ready to move to higher ground quickly.', 'flash flood warning': 'Flash flooding is occurring or imminent. Move to higher ground now.', 'wind advisory': 'Sustained or gusty winds that can blow around unsecured objects and make driving difficult for high-profile vehicles.', 'high wind watch': 'Damaging winds are possible. Secure outdoor objects.', 'high wind warning': 'Damaging winds are occurring or imminent. Secure objects and avoid travel if possible.', 'freeze watch': 'A freeze is possible. Protect sensitive plants, pets and exposed pipes.', 'freeze warning': 'Temperatures at or below freezing are expected. Protect plants, pets and exposed pipes.', 'frost advisory': 'Frost is expected and can damage sensitive plants.', 'hard freeze warning': 'Severe freezing temperatures are expected. Protect plants, pets and pipes.', 'winter storm watch': 'Heavy snow and/or ice is possible. Prepare for hazardous travel.', 'winter storm warning': 'Heavy snow and/or ice is occurring or imminent. Travel may be dangerous or impossible.', 'winter weather advisory': 'Snow, sleet or freezing rain will cause slippery roads and travel difficulty.', 'ice storm warning': 'Significant ice accumulation is expected. Power outages and dangerous travel are likely.', 'blizzard warning': 'Heavy snow with strong winds and very low visibility. Avoid travel.', 'wind chill advisory': 'Dangerously cold wind chills are expected. Dress in layers and limit time outside.', 'wind chill warning': 'Life-threatening wind chills are expected. Frostbite can occur quickly.', 'dense fog advisory': 'Fog is reducing visibility to a quarter mile or less. Slow down and use low-beam headlights.', 'dense smoke advisory': 'Smoke is reducing visibility and air quality.', 'air quality alert': 'Air quality is unhealthy for some or all people. Limit prolonged outdoor exertion.', 'red flag warning': 'Dry, windy and warm conditions create a high wildfire risk. Avoid open flames and outdoor burning.', 'fire weather watch': 'Conditions may soon create a high wildfire risk.', 'rip current statement': 'Dangerous rip currents at the beach. Stay out of the water or swim near a lifeguard.', 'coastal flood advisory': 'Minor coastal flooding is expected.', 'coastal flood warning': 'Significant coastal flooding is occurring or imminent.', 'small craft advisory': 'Winds or seas hazardous to small boats.', 'tropical storm watch': 'Tropical storm conditions are possible within about 48 hours.', 'tropical storm warning': 'Tropical storm conditions are expected within about 36 hours.', 'hurricane watch': 'Hurricane conditions are possible within about 48 hours.', 'hurricane warning': 'Hurricane conditions are expected within about 36 hours.', 'hazardous weather outlook': 'An outlook of possible hazardous weather in the next several days.', 'severe weather statement': 'An update on an ongoing severe storm warning.', 'flood statement': 'An update on an ongoing flood warning.', 'storm surge watch': 'Life-threatening storm surge flooding is possible within about 48 hours. Know your evacuation zone and be ready to leave.', 'storm surge warning': 'Life-threatening storm surge flooding is expected within about 36 hours. Follow evacuation orders from local officials immediately.', 'hurricane local statement': 'Local details on a hurricane threat: expected winds, rain, surge and tornado risk for your area, and what officials are advising.', 'tropical cyclone statement': 'Local details on a tropical storm or hurricane threat for your area.', 'tropical depression watch': 'A tropical depression may affect the area; heavy rain and gusty wind are possible.', 'extreme wind warning': 'Extreme, hurricane-force winds (115+ mph) are about to hit. Take shelter now in the strongest part of a sturdy building.', 'hurricane force wind watch': 'Hurricane-force winds are possible over marine areas. Stay in port.', 'hurricane force wind warning': 'Hurricane-force winds are expected over marine areas. Dangerous for all vessels.', 'storm warning': 'Strong marine winds (48–63 knots) expected. Dangerous for all vessels.', 'gale warning': 'Strong marine winds (34–47 knots) expected. Hazardous for small and large vessels.', 'gale watch': 'Gale-force marine winds are possible.', 'special marine warning': 'Short-lived, hazardous marine weather (strong winds, waterspouts, hail) is happening. Seek safe harbor.', 'high surf advisory': 'Large breaking waves make swimming and surfing dangerous.', 'high surf warning': 'Very large breaking waves are expected: dangerous and life-threatening at the shore.', 'beach hazards statement': 'Hazards at the beach such as rip currents or high surf. Swim near a lifeguard.', 'lake wind advisory': 'Gusty lake winds can create hazardous waves for small boats.', 'dust storm warning': 'Blowing dust is reducing visibility to near zero. Pull off the road and turn off your lights.', 'tornado emergency': 'A confirmed large and destructive tornado is moving toward a populated area. Take cover immediately.', 'flash flood emergency': 'Catastrophic, life-threatening flash flooding is happening. Move to higher ground now.', }; function meaning(event) { const e = String(event || '').toLowerCase().trim(); if (GLOSSARY[e]) return GLOSSARY[e]; if (e.endsWith('watch')) return 'A Watch: conditions are favorable for this hazard. Stay alert and be ready to act.'; if (e.endsWith('warning')) return 'A Warning: this hazard is happening or imminent. Take action now.'; if (e.endsWith('advisory')) return 'An Advisory: conditions may cause inconvenience or danger if you are not careful.'; if (e.endsWith('statement')) return 'An informational statement about developing or ongoing weather.'; return ''; } // NWS text is often structured "* WHAT...", "* WHERE...", "* WHEN..."; lead with the WHAT part function firstSentence(t, max = 220) { const what = String(t || '').match(/\*\s*WHAT\.\.\.([\s\S]*?)(?:\n\s*\n|\*\s*[A-Z ]+\.\.\.|$)/); const c = (what ? what[1] : String(t || '')).replace(/\s+/g, ' ').trim(); const m = c.match(/^.*?[.!?](\s|$)/); const r = (m ? m[0] : c).trim(); return r.length > max ? r.slice(0, max - 3) + '…' : r; } const area = (a) => String(a || '').replace(/;\s*/g, ', '); const when = (iso) => (iso ? new Date(iso).toLocaleString([], { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : ''); const esc = (s) => String(s ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); // "ends in 3h 10m" / "ended" for active alerts function remaining(iso) { if (!iso) return ''; const ms = Date.parse(iso) - Date.now(); if (!Number.isFinite(ms)) return ''; if (ms <= 0) return 'expired'; const m = Math.round(ms / 60000); return m < 60 ? `ends in ${m} min` : m < 1440 ? `ends in ${Math.floor(m / 60)}h ${m % 60}m` : `ends in ${Math.round(m / 144) / 10}d`.replace('.0d', 'd'); } window.AlertInfo = { meaning, firstSentence, area, when, esc, remaining, GLOSSARY }; })();