{"id":4859,"date":"2025-10-30T11:26:24","date_gmt":"2025-10-30T09:26:24","guid":{"rendered":"https:\/\/northwindlapland.com\/?page_id=4859"},"modified":"2026-04-18T16:21:53","modified_gmt":"2026-04-18T13:21:53","slug":"northern-light-alert","status":"publish","type":"page","link":"https:\/\/northwindlapland.com\/fr\/northern-light-alert\/","title":{"rendered":"ALERTE AURORES BOR\u00c9ALES YLL\u00c4S"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"4859\" class=\"elementor elementor-4859\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-17034839 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"17034839\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ea6803c\" data-id=\"ea6803c\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-092ab9b elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"092ab9b\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0157841\" data-id=\"0157841\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5b01750 elementor-widget elementor-widget-html\" data-id=\"5b01750\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n  <title>Northern Lights Alert \u2013 North Wind Lapland<\/title>\n  <link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.5.0\/css\/all.min.css\">\n  <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/emailjs-com@3\/dist\/email.min.js\"><\/script>\n  <style>\n    :root{\n      --primary:#1a365d;--secondary:#2d3748;--accent:#4a5568;--highlight:#63b3ed;\n      --text:#e2e8f0;--success:#48bb78;--warning:#ed8936;--danger:#f56565;--dark-bg:#0f172a;\n    }\n    *{box-sizing:border-box;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif}\n    body{margin:0;background:linear-gradient(135deg,#0f172a,#1e293b,#334155);color:var(--text);min-height:100vh}\n    .nwl-container{max-width:1200px;margin:0 auto;padding:20px}\n    .nwl-header{display:flex;justify-content:space-between;align-items:center;padding:20px 0;border-bottom:1px solid rgba(255,255,255,.1);margin-bottom:26px;flex-wrap:wrap;gap:15px}\n    .nwl-logo-row{display:flex;align-items:center;gap:14px}\n    .nwl-logo{width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,var(--highlight),#90cdf4);display:flex;align-items:center;justify-content:center;font-weight:900;color:var(--primary);font-size:24px;box-shadow:0 4px 10px rgba(99,179,237,.3)}\n    .nwl-brand-name{font-size:24px;font-weight:900}\n    .nwl-powered{font-size:14px;opacity:.85}\n    .nwl-powered a{color:var(--highlight);text-decoration:none}\n    .nwl-powered a:hover{text-decoration:underline}\n    .nwl-time{font-size:1.05rem;background:rgba(255,255,255,.05);padding:10px 14px;border-radius:10px;border:1px solid rgba(255,255,255,.1)}\n    .nwl-hero{text-align:center;padding:18px 0 26px;margin-bottom:10px}\n    .nwl-hero h1{font-size:2.45rem;margin-bottom:12px;background:linear-gradient(to right,#a8edea,#fed6e3);-webkit-background-clip:text;background-clip:text;color:transparent}\n    .nwl-hero p{font-size:1.15rem;max-width:900px;margin:0 auto 14px;opacity:.92}\n    .nwl-location{display:flex;justify-content:center;align-items:center;gap:8px;margin-top:8px;opacity:.85}\n    .nwl-btn{background:linear-gradient(to right,var(--highlight),#90cdf4);color:var(--primary);border:none;padding:12px 22px;border-radius:10px;font-weight:900;cursor:pointer;transition:.2s;display:inline-flex;align-items:center;gap:10px;justify-content:center}\n    .nwl-btn:hover{transform:translateY(-2px);box-shadow:0 5px 15px rgba(99,179,237,.35)}\n    .nwl-btn:disabled{opacity:.6;cursor:not-allowed;transform:none;box-shadow:none}\n    .nwl-btn-block{width:100%}\n    .nwl-btn-danger{background:linear-gradient(to right,var(--danger),#fc8181);color:#1a1a1a}\n    .nwl-dashboard{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-bottom:24px}\n    @media(max-width:768px){.nwl-dashboard{grid-template-columns:1fr}.nwl-header{flex-direction:column;text-align:center}.nwl-logo-row{justify-content:center}.nwl-hero h1{font-size:2rem}}\n    .nwl-card{background:rgba(255,255,255,.05);border-radius:16px;padding:22px;box-shadow:0 10px 30px rgba(0,0,0,.2);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1);transition:.2s}\n    .nwl-card:hover{transform:translateY(-3px);box-shadow:0 15px 35px rgba(0,0,0,.3)}\n    .nwl-card h2{font-size:1.45rem;margin-bottom:16px;color:var(--highlight);display:flex;align-items:center;gap:10px}\n    .nwl-status{display:flex;align-items:center;gap:10px;margin-bottom:14px}\n    .nwl-dot{width:12px;height:12px;border-radius:50%}\n    .nwl-dot.active{background:var(--success);box-shadow:0 0 10px var(--success);animation:nwl-pulse 2s infinite}\n    .nwl-dot.inactive{background:var(--danger)}\n    @keyframes nwl-pulse{0%{opacity:1}50%{opacity:.5}100%{opacity:1}}\n    .nwl-meter{height:30px;background:rgba(255,255,255,.1);border-radius:16px;overflow:hidden;position:relative;margin:14px 0}\n    .nwl-fill{height:100%;width:0%;background:linear-gradient(to right,var(--warning),var(--success));border-radius:1664;transition:width 1s}\n    .nwl-meter-text{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-weight:900;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.5)}\n    .nwl-aurora{height:190px;border-radius:12px;margin-top:14px;position:relative;overflow:hidden;background:linear-gradient(135deg,#0f2027,#2c5364);display:flex;align-items:center;justify-content:center}\n    .nwl-aurora::before{content:\"\";position:absolute;inset:-60%;background:linear-gradient(45deg,rgba(72,187,120,.2) 0%,rgba(99,179,237,.3) 25%,rgba(147,51,234,.2) 50%,rgba(236,72,153,.3) 75%,rgba(239,68,68,.2) 100%);animation:nwl-aurora 10s linear infinite;opacity:.75}\n    @keyframes nwl-aurora{0%{transform:translate(-25%,-25%)}100%{transform:translate(25%,25%)}}\n    .nwl-aurora-msg{position:relative;z-index:1;font-weight:900;opacity:.95}\n    .nwl-form{margin-top:10px}\n    .nwl-group{margin-bottom:14px}\n    .nwl-label{display:block;margin-bottom:8px;font-weight:700}\n    .nwl-input,.nwl-select{width:100%;padding:12px 14px;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2);border-radius:10px;color:var(--text);font-size:1rem;transition:.2s}\n    .nwl-input:focus,.nwl-select:focus{outline:none;border-color:var(--highlight);box-shadow:0 0 0 2px rgba(99,179,237,.2)}\n    .nwl-check{display:flex;align-items:center;gap:10px;margin:10px 0 14px}\n    .nwl-factors{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-top:16px}\n    @media(max-width:768px){.nwl-factors{grid-template-columns:1fr}}\n    .nwl-factor{background:rgba(255,255,255,.05);border-radius:12px;padding:14px;transition:.2s}\n    .nwl-factor:hover{background:rgba(255,255,255,.08)}\n    .nwl-factor.good{border-left:4px solid var(--success)}\n    .nwl-factor.moderate{border-left:4px solid var(--warning)}\n    .nwl-factor.poor{border-left:4px solid var(--danger)}\n    .nwl-factor h3{display:flex;align-items:center;gap:10px;font-size:1.05rem;margin:0}\n    .nwl-factor-value{font-size:1.55rem;font-weight:900;margin:8px 0}\n    .nwl-factor-status{font-size:.95rem;opacity:.9}\n    .nwl-source{font-size:.8rem;opacity:.6;margin-top:6px}\n    .nwl-history{margin-top:18px}\n    .nwl-item{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:14px;background:rgba(255,255,255,.05);border-radius:12px;margin-bottom:12px;border-left:4px solid var(--highlight)}\n    .nwl-item-title{font-weight:900}\n    .nwl-item-time{font-size:.9rem;opacity:.8}\n    .nwl-item-meta{font-size:.82rem;opacity:.72;margin-top:4px}\n    .nwl-item-prob{font-weight:900;color:var(--highlight)}\n    .nwl-footer{text-align:center;padding:18px 0 12px;margin-top:18px;border-top:1px solid rgba(255,255,255,.1);opacity:.9}\n    .nwl-footer a{color:var(--highlight);text-decoration:none}\n    .nwl-footer a:hover{text-decoration:underline}\n    .nwl-toast{position:fixed;top:20px;right:20px;max-width:520px;z-index:999999;padding:14px 16px;border-radius:10px;color:#fff;background:var(--success);box-shadow:0 5px 15px rgba(0,0,0,.25);transform:translateX(150%);transition:transform .25s ease;display:flex;align-items:center;gap:10px}\n    .nwl-toast.show{transform:translateX(0)}\n    .nwl-toast.error{background:var(--danger)}\n    .nwl-toast.warning{background:var(--warning)}\n  <\/style>\n<\/head>\n<body>\n<div class=\"nwl-instance\">\n  <div class=\"nwl-container\">\n    <header class=\"nwl-header\">\n      <div class=\"nwl-logo-row\">\n        <div class=\"nwl-logo\">NWL<\/div>\n        <div>\n          <div class=\"nwl-brand-name\">North Wind Lapland<\/div>\n          <div class=\"nwl-powered\">Powered by <a href=\"https:\/\/northwindlapland.com\" target=\"_blank\" rel=\"noopener\">northwindlapland.com<\/a><\/div>\n        <\/div>\n      <\/div>\n      <div class=\"nwl-time\" data-nwl=\"time\">--<\/div>\n    <\/header>\n\n    <section class=\"nwl-hero\">\n      <h1>Northern Lights Alert System<\/h1>\n      <p>Get notified when the probability of seeing the Northern Lights in Yll\u00e4s, Finland is over 50%.<\/p>\n      <div class=\"nwl-location\"><i class=\"fa-solid fa-location-dot\"><\/i><span>Yll\u00e4s, Finnish Lapland<\/span><\/div>\n      <button class=\"nwl-btn\" type=\"button\" data-nwl=\"updateBtn\" style=\"margin-top:14px\">\n        <i class=\"fa-solid fa-rotate\"><\/i><span>Update Data<\/span>\n      <\/button>\n    <\/section>\n\n    <div class=\"nwl-dashboard\">\n      <div class=\"nwl-card\">\n        <h2><i class=\"fa-solid fa-chart-column\"><\/i> Current Probability<\/h2>\n        <div class=\"nwl-status\">\n          <div class=\"nwl-dot inactive\" data-nwl=\"dot\"><\/div>\n          <span data-nwl=\"status\">Loading data...<\/span>\n        <\/div>\n        <div class=\"nwl-meter\">\n          <div class=\"nwl-fill\" data-nwl=\"fill\"><\/div>\n          <div class=\"nwl-meter-text\" data-nwl=\"prob\">0%<\/div>\n        <\/div>\n        <p data-nwl=\"desc\">Calculating probability based on current conditions...<\/p>\n        <div class=\"nwl-aurora\">\n          <div class=\"nwl-aurora-msg\" data-nwl=\"auroraMsg\">Aurora conditions visualization<\/div>\n        <\/div>\n        <div class=\"nwl-factors\">\n          <div class=\"nwl-factor\" data-nwl=\"kpFactor\">\n            <h3><i class=\"fa-solid fa-chart-line\"><\/i> Kp Index<\/h3>\n            <div class=\"nwl-factor-value\" data-nwl=\"kpValue\">--<\/div>\n            <div class=\"nwl-factor-status\" data-nwl=\"kpStatus\">Loading...<\/div>\n            <div class=\"nwl-source\">NOAA Space Weather<\/div>\n          <\/div>\n          <div class=\"nwl-factor\" data-nwl=\"speedFactor\">\n            <h3><i class=\"fa-solid fa-wind\"><\/i> Solar Wind<\/h3>\n            <div class=\"nwl-factor-value\" data-nwl=\"speedValue\">-- km\/s<\/div>\n            <div class=\"nwl-factor-status\" data-nwl=\"speedStatus\">Loading...<\/div>\n            <div class=\"nwl-source\">DSCOVR Satellite<\/div>\n          <\/div>\n          <div class=\"nwl-factor\" data-nwl=\"cloudsFactor\">\n            <h3><i class=\"fa-solid fa-cloud\"><\/i> Cloud Coverage<\/h3>\n            <div class=\"nwl-factor-value\" data-nwl=\"cloudsValue\">--%<\/div>\n            <div class=\"nwl-factor-status\" data-nwl=\"cloudsStatus\">Loading...<\/div>\n            <div class=\"nwl-source\">Open-Meteo API<\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"nwl-card\">\n        <h2><i class=\"fa-solid fa-bell\"><\/i> Alert Settings<\/h2>\n        <div style=\"opacity:.9;margin-bottom:10px\">Get notifications when the probability exceeds 50%.<\/div>\n        <div class=\"nwl-form\">\n          <div class=\"nwl-group\">\n            <label class=\"nwl-label\"><i class=\"fa-solid fa-user\"><\/i> Your Name<\/label>\n            <input class=\"nwl-input\" type=\"text\" data-nwl=\"nameInput\" placeholder=\"Enter your name\">\n          <\/div>\n          <div class=\"nwl-group\">\n            <label class=\"nwl-label\"><i class=\"fa-solid fa-envelope\"><\/i> Email Address<\/label>\n            <input class=\"nwl-input\" type=\"email\" data-nwl=\"emailInput\" placeholder=\"Enter your email\">\n          <\/div>\n          <div class=\"nwl-check\">\n            <input type=\"checkbox\" checked data-nwl=\"hoursInput\">\n            <label style=\"margin:0\">Only send alerts between 6 PM and 2 AM (optimal viewing hours)<\/label>\n          <\/div>\n          <button class=\"nwl-btn nwl-btn-block\" type=\"button\" data-nwl=\"saveBtn\">\n            <i class=\"fa-solid fa-floppy-disk\"><\/i><span>Save Alert Settings<\/span>\n          <\/button>\n          <div class=\"nwl-group\" style=\"margin-top:14px\">\n            <button class=\"nwl-btn nwl-btn-danger nwl-btn-block\" type=\"button\" data-nwl=\"unsubBtn\">\n              <i class=\"fa-solid fa-ban\"><\/i><span>Unsubscribe from Alerts<\/span>\n            <\/button>\n            <small style=\"opacity:.7;display:block;text-align:center;margin-top:6px\">Remove your email from alert notifications<\/small>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <div class=\"nwl-card nwl-history\">\n      <h2><i class=\"fa-solid fa-clock-rotate-left\"><\/i> Recent Updates<\/h2>\n      <div data-nwl=\"history\"><\/div>\n      <div style=\"margin-top:10px;opacity:.85\" data-nwl=\"last\">Last update: --<\/div>\n    <\/div>\n\n    <div class=\"nwl-footer\">\n      \u00a9 2025 North Wind Lapland | Yll\u00e4s, Finland |\n      <a href=\"https:\/\/northwindlapland.com\" target=\"_blank\" rel=\"noopener\">northwindlapland.com<\/a>\n      <div style=\"margin-top:10px;opacity:.75;font-size:.92rem\">\n        This service provides probability estimates based on available data. Actual aurora visibility may vary.\n      <\/div>\n      <div style=\"margin-top:16px\">\n        <a style=\"font-size:2.5em;font-weight:900;color:#BAFAF8;text-decoration:none\"\n           href=\"https:\/\/northwindlapland.com\/northern-lights-experiences\/\" target=\"_blank\" rel=\"noopener\">\n          BOOK YOUR NORTHERN LIGHTS ADVENTURE HERE\n        <\/a>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div class=\"nwl-toast\" data-nwl=\"toast\" aria-live=\"polite\">\n  <i class=\"fa-solid fa-bell\"><\/i>\n  <div data-nwl=\"toastMsg\">Notification<\/div>\n<\/div>\n\n<script>\n(function(){\n  \"use strict\";\n\n  var LAT = 67.567, LON = 24.25, TZ = \"Europe\/Helsinki\";\n  var SWPC_KP       = \"https:\/\/services.swpc.noaa.gov\/products\/noaa-planetary-k-index.json\";\n  var DSCOVR_PLASMA = \"https:\/\/services.swpc.noaa.gov\/products\/solar-wind\/plasma-2-hour.json\";\n  var DSCOVR_MAG    = \"https:\/\/services.swpc.noaa.gov\/products\/solar-wind\/mag-2-hour.json\";\n  var METEO = \"https:\/\/api.open-meteo.com\/v1\/forecast?latitude=\"+LAT+\"&longitude=\"+LON+\"&hourly=cloud_cover&timezone=\"+encodeURIComponent(TZ);\n  var SUN   = \"https:\/\/api.sunrise-sunset.org\/json?lat=\"+LAT+\"&lng=\"+LON+\"&formatted=0\";\n\n  var EMAILJS_SERVICE      = \"service_7byxgtg\";\n  var EMAILJS_TEMPLATE     = \"template_NLAY\";\n  var EMAILJS_TEMPLATE_SUB = \"template_SUBSCRIBE\"; \/\/ Step 1: create this template in EmailJS dashboard\n  var EMAILJS_USER         = \"zGhAFRH-5GkMbtRBN\";\n  var ALERT_THRESHOLD      = 50;\n  var REFRESH_MS = 15 * 60 * 1000;\n\n  function fetchJson(url){\n    var u = url + (url.indexOf(\"?\")>=0?\"&\":\"?\")+\"_=\"+Date.now();\n    return fetch(u,{cache:\"no-store\"}).then(function(r){if(!r.ok)throw new Error(\"HTTP \"+r.status);return r.json();});\n  }\n\n  function lastNumericRow(arr,col){\n    if(!Array.isArray(arr))return null;\n    for(var i=arr.length-1;i>=0;i--){var row=arr[i];if(!Array.isArray(row)||row.length<=col)continue;var v=parseFloat(row[col]);if(isFinite(v))return row;}\n    return null;\n  }\n\n  function nearestHourIndex(times){\n    var now=Date.now(),best=0,diff=1e18;\n    for(var i=0;i<times.length;i++){var d=Math.abs(new Date(times[i]).getTime()-now);if(d<diff){diff=d;best=i;}}\n    return best;\n  }\n\n  function computeProb(data){\n    var kp=isFinite(data.kp)?data.kp:0, r=Math.round(kp);\n    var kpScore=r<=0?5:r===1?25:r===2?45:r===3?55:r===4?76:r===5?85:r===6?90:95;\n    var cloud=isFinite(data.cloudPct)?data.cloudPct:50;\n    var cf=cloud<=10?1:cloud<=30?.95:cloud<=50?.85:cloud<=70?.7:cloud<=90?.55:.4;\n    var df=data.isNight?1:.45;\n    return Math.round(Math.min(98,Math.max(5,kpScore*cf*df)));\n  }\n\n  function descProb(p){\n    if(p<15)return\"Aurora chance around \"+p+\"% \u2013 Very low, but not impossible.\";\n    if(p<35)return\"Aurora chance around \"+p+\"% \u2013 Low, but worth a quick look if the sky opens.\";\n    if(p<60)return\"Aurora chance around \"+p+\"% \u2013 Moderate. Go out during the clearest periods.\";\n    if(p<85)return\"Aurora chance around \"+p+\"% \u2013 High. Conditions are favorable; plan time outside.\";\n    return\"Aurora chance around \"+p+\"% \u2013 Very high. Strong auroras likely if skies are at least partly clear.\";\n  }\n\n  function descCloud(c){\n    if(!isFinite(c)||c==null)return\"Cloud cover data not available.\";\n    var r=Math.round(c);\n    if(r<=10)return\"Clear sky. Excellent visibility.\";\n    if(r<=30)return\"Mostly clear. Very good visibility.\";\n    if(r<=50)return\"Partly cloudy. Wait for gaps.\";\n    if(r<=70)return\"Many clouds. Watch for breaks.\";\n    if(r<=90)return\"Mostly cloudy. Only visible through breaks.\";\n    return\"Overcast. Unlikely to see from the ground.\";\n  }\n\n  function setFactor(factorEl,valueEl,statusEl,value,type){\n    var cls=\"poor\";\n    if(value==null||!isFinite(value)){\n      valueEl.textContent=type===\"speed\"?\"\u2013 km\/s\":type===\"clouds\"?\"--%\":\"\u2013\";\n      statusEl.textContent=\"No data\"; factorEl.className=\"nwl-factor\"; return;\n    }\n    if(type===\"kp\"){\n      valueEl.textContent=value.toFixed(1);\n      cls=value>=3?\"good\":value>=2?\"moderate\":\"poor\";\n      statusEl.textContent=value>=5?\"Excellent\":value>=3?\"Good\":value>=2?\"Moderate\":\"Poor\";\n    } else if(type===\"speed\"){\n      valueEl.textContent=Math.round(value)+\" km\/s\";\n      cls=value>=450?\"good\":value>=300?\"moderate\":\"poor\";\n      statusEl.textContent=value>=600?\"Excellent\":value>=450?\"Good\":value>=300?\"Moderate\":\"Poor\";\n    } else {\n      valueEl.textContent=Math.round(value)+\"%\";\n      cls=value<50?\"good\":value<80?\"moderate\":\"poor\";\n      statusEl.textContent=descCloud(value);\n    }\n    statusEl.style.color=cls===\"good\"?\"var(--success)\":cls===\"moderate\"?\"var(--warning)\":\"var(--danger)\";\n    factorEl.className=\"nwl-factor \"+cls;\n  }\n\n  var emailReady=false;\n  function initEmailJS(){try{if(!window.emailjs)return;window.emailjs.init(EMAILJS_USER);emailReady=true;}catch(e){}}\n  (function tick(n){initEmailJS();if(emailReady||n>=20)return;setTimeout(function(){tick(n+1);},250);})(0);\n\n  function sendAlert(state,data,prob){\n    if(!emailReady||!window.emailjs)return Promise.resolve(false);\n    var email=(state.emailInput.value||\"\").trim();if(!email)return Promise.resolve(false);\n    return window.emailjs.send(EMAILJS_SERVICE,EMAILJS_TEMPLATE,{\n      name:(state.nameInput.value||\"\").trim()||\"Aurora watcher\",email:email,probability:prob,\n      kp:data.kp!=null&&isFinite(data.kp)?data.kp.toFixed(1):\"N\/A\",\n      speed:data.speed!=null&&isFinite(data.speed)?Math.round(data.speed):\"N\/A\",\n      bz:data.bz!=null&&isFinite(data.bz)?data.bz.toFixed(1):\"N\/A\",\n      clouds:data.cloudPct!=null&&isFinite(data.cloudPct)?Math.round(data.cloudPct):\"N\/A\",\n      local_time:new Date().toLocaleString(undefined,{timeZone:TZ})\n    }).then(function(){return true;}).catch(function(){return false;});\n  }\n\n  function throttleOK(){\n    var key=\"nwlLastEmailSentAt\",last=localStorage.getItem(key),now=Date.now();\n    if(!last){localStorage.setItem(key,String(now));return true;}\n    var t=parseInt(last,10);if(!isFinite(t))t=0;\n    if(now-t>=30*60*1000){localStorage.setItem(key,String(now));return true;}\n    return false;\n  }\n\n  function toast(state,msg,type){\n    type=type||\"success\";\n    state.toastMsg.textContent=msg;\n    state.toast.className=\"nwl-toast show\"+(type!==\"success\"?\" \"+type:\"\");\n    clearTimeout(state._tt);\n    state._tt=setTimeout(function(){state.toast.classList.remove(\"show\");},7000);\n  }\n\n  function addHistory(state,prob,data){\n    var timeStr=new Date().toLocaleTimeString(\"en-FI\",{hour:\"2-digit\",minute:\"2-digit\",timeZone:TZ});\n    var item=document.createElement(\"div\"); item.className=\"nwl-item\";\n    var left=document.createElement(\"div\");\n    left.innerHTML='<div class=\"nwl-item-title\">Probability update<\/div>'\n      +'<div class=\"nwl-item-time\">Today, '+timeStr+'<\/div>'\n      +'<div class=\"nwl-item-meta\">Kp: '+(data.kp!=null&&isFinite(data.kp)?data.kp.toFixed(1):\"\u2013\")\n      +' | Wind: '+(data.speed!=null&&isFinite(data.speed)?Math.round(data.speed):\"\u2013\")+' km\/s'\n      +' | Clouds: '+(data.cloudPct!=null&&isFinite(data.cloudPct)?Math.round(data.cloudPct):\"\u2013\")+'%<\/div>';\n    var right=document.createElement(\"div\"); right.className=\"nwl-item-prob\"; right.textContent=prob+\"%\";\n    item.appendChild(left); item.appendChild(right);\n    state.history.insertBefore(item,state.history.firstChild);\n    while(state.history.children.length>5)state.history.removeChild(state.history.lastChild);\n  }\n\n  function setUpdating(state,on){\n    state.updateBtn.disabled=on;\n    state.updateBtn.innerHTML=(on?'<i class=\"fa-solid fa-spinner fa-spin\"><\/i><span>Updating...<\/span>'\n      :'<i class=\"fa-solid fa-rotate\"><\/i><span>Update Data<\/span>');\n  }\n\n  function updateClock(state){\n    try{state.time.textContent=new Date().toLocaleString(\"en-FI\",{weekday:\"long\",year:\"numeric\",month:\"long\",day:\"numeric\",hour:\"2-digit\",minute:\"2-digit\",second:\"2-digit\",timeZone:TZ});}\n    catch(e){state.time.textContent=new Date().toString();}\n  }\n\n  function fetchAll(){\n    return Promise.all([\n      fetchJson(SWPC_KP).catch(function(){return null;}),\n      fetchJson(DSCOVR_PLASMA).catch(function(){return null;}),\n      fetchJson(DSCOVR_MAG).catch(function(){return null;}),\n      fetchJson(METEO).catch(function(){return null;}),\n      fetchJson(SUN).catch(function(){return null;})\n    ]).then(function(res){\n      var kpD=res[0],plasma=res[1],mag=res[2],meteo=res[3],sun=res[4];\n      var kp=null,speed=null,bz=null,cloudPct=null,isNight=true;\n      if(Array.isArray(kpD)){var r=lastNumericRow(kpD,1);if(r)kp=parseFloat(r[1]);}\n      if(Array.isArray(plasma)){var r=lastNumericRow(plasma,2);if(r)speed=parseFloat(r[2]);}\n      if(Array.isArray(mag)){var r=lastNumericRow(mag,2);if(r)bz=parseFloat(r[2]);}\n      if(meteo&&meteo.hourly&&Array.isArray(meteo.hourly.time)){var idx=nearestHourIndex(meteo.hourly.time);cloudPct=meteo.hourly.cloud_cover[idx];}\n      if(sun&&sun.status===\"OK\"&&sun.results){var now=new Date(),sr=new Date(sun.results.sunrise),ss=new Date(sun.results.sunset);isNight=(now<sr||now>ss);}\n      return{kp:kp,speed:speed,bz:bz,cloudPct:cloudPct,isNight:isNight};\n    });\n  }\n\n  function updateUI(state,prob,data){\n    state.fill.style.width=prob+\"%\";\n    state.prob.textContent=prob+\"%\";\n    state.desc.textContent=descProb(prob);\n    if(prob>=ALERT_THRESHOLD){\n      state.dot.className=\"nwl-dot active\";\n      state.status.textContent=\"High probability of Northern Lights!\";\n      state.status.style.color=\"var(--success)\";\n      state.auroraMsg.textContent=\"High Aurora Activity Expected\";\n    } else {\n      state.dot.className=\"nwl-dot inactive\";\n      state.status.textContent=\"Lower probability of Northern Lights at the moment\";\n      state.status.style.color=\"var(--text)\";\n      state.auroraMsg.textContent=\"Lower Aurora Activity Expected\";\n    }\n    setFactor(state.kpFactor,state.kpValue,state.kpStatus,data.kp,\"kp\");\n    setFactor(state.speedFactor,state.speedValue,state.speedStatus,data.speed,\"speed\");\n    setFactor(state.cloudsFactor,state.cloudsValue,state.cloudsStatus,data.cloudPct,\"clouds\");\n    addHistory(state,prob,data);\n    state.last.textContent=\"Last update: \"+new Date().toLocaleString(undefined,{timeZone:TZ});\n  }\n\n  function runUpdate(state){\n    setUpdating(state,true);\n    toast(state,\"Fetching live data\u2026\");\n    return fetchAll().then(function(data){\n      var prob=computeProb(data);\n      updateUI(state,prob,data);\n      var email=(state.emailInput.value||\"\").trim();\n      var activeOnly=!!state.hoursInput.checked;\n      var canSend=email&&(!activeOnly||data.isNight)&&throttleOK();\n      if(prob>=ALERT_THRESHOLD&&canSend){\n        toast(state,\"High probability (\"+prob+\"%). Sending email\u2026\");\n        return sendAlert(state,data,prob).then(function(sent){\n          toast(state,sent?\"Email sent \u2705\":\"Email not sent (EmailJS not configured)\",sent?\"success\":\"warning\");\n        });\n      }\n      toast(state,\"Data updated successfully!\");\n    }).catch(function(err){\n      toast(state,\"Update failed: \"+(err&&err.message?err.message:\"Unknown error\"),\"error\");\n    }).finally(function(){setUpdating(state,false);});\n  }\n\n  var root=document.querySelector(\".nwl-instance\");\n  var state={\n    time:root.querySelector('[data-nwl=\"time\"]'),\n    dot:root.querySelector('[data-nwl=\"dot\"]'),\n    status:root.querySelector('[data-nwl=\"status\"]'),\n    fill:root.querySelector('[data-nwl=\"fill\"]'),\n    prob:root.querySelector('[data-nwl=\"prob\"]'),\n    desc:root.querySelector('[data-nwl=\"desc\"]'),\n    auroraMsg:root.querySelector('[data-nwl=\"auroraMsg\"]'),\n    updateBtn:root.querySelector('[data-nwl=\"updateBtn\"]'),\n    saveBtn:root.querySelector('[data-nwl=\"saveBtn\"]'),\n    unsubBtn:root.querySelector('[data-nwl=\"unsubBtn\"]'),\n    nameInput:root.querySelector('[data-nwl=\"nameInput\"]'),\n    emailInput:root.querySelector('[data-nwl=\"emailInput\"]'),\n    hoursInput:root.querySelector('[data-nwl=\"hoursInput\"]'),\n    kpFactor:root.querySelector('[data-nwl=\"kpFactor\"]'),\n    kpValue:root.querySelector('[data-nwl=\"kpValue\"]'),\n    kpStatus:root.querySelector('[data-nwl=\"kpStatus\"]'),\n    speedFactor:root.querySelector('[data-nwl=\"speedFactor\"]'),\n    speedValue:root.querySelector('[data-nwl=\"speedValue\"]'),\n    speedStatus:root.querySelector('[data-nwl=\"speedStatus\"]'),\n    cloudsFactor:root.querySelector('[data-nwl=\"cloudsFactor\"]'),\n    cloudsValue:root.querySelector('[data-nwl=\"cloudsValue\"]'),\n    cloudsStatus:root.querySelector('[data-nwl=\"cloudsStatus\"]'),\n    history:root.querySelector('[data-nwl=\"history\"]'),\n    last:root.querySelector('[data-nwl=\"last\"]'),\n    toast:document.querySelector('[data-nwl=\"toast\"]'),\n    toastMsg:document.querySelector('[data-nwl=\"toastMsg\"]')\n  };\n\n  updateClock(state);\n  setInterval(function(){updateClock(state);},1000);\n\n  var raw=localStorage.getItem(\"northernLightsPreferences_app\");\n  if(raw){try{var p=JSON.parse(raw);state.nameInput.value=p.name||\"\";state.emailInput.value=p.email||\"\";state.hoursInput.checked=(p.activeHours!==false);}catch(e){}}\n\n  state.updateBtn.addEventListener(\"click\",function(){runUpdate(state);});\n\n  \/\/ Step 2: Save settings AND send subscriber notification to info@northwindlapland.com\n  state.saveBtn.addEventListener(\"click\",function(){\n    var name=(state.nameInput.value||\"\").trim();\n    var email=(state.emailInput.value||\"\").trim();\n    if(!email)return toast(state,\"Please enter your email address first\",\"error\");\n    localStorage.setItem(\"northernLightsPreferences_app\",JSON.stringify({\n      name:name,email:email,\n      activeHours:!!state.hoursInput.checked,\n      savedAt:new Date().toISOString()\n    }));\n    toast(state,\"Preferences saved successfully!\");\n    if(emailReady&&window.emailjs){\n      window.emailjs.send(EMAILJS_SERVICE,EMAILJS_TEMPLATE_SUB,{\n        subscriber_name:name||\"Not provided\",\n        subscriber_email:email,\n        active_hours:state.hoursInput.checked?\"Yes (6 PM\u20132 AM only)\":\"No (anytime)\",\n        signed_at:new Date().toLocaleString(undefined,{timeZone:TZ})\n      }).catch(function(){}); \/\/ silent fail \u2014 subscriber already saved locally\n    }\n  });\n\n  state.unsubBtn.addEventListener(\"click\",function(){\n    var email=(state.emailInput.value||\"\").trim();\n    if(!email)return toast(state,\"Please enter your email address first\",\"error\");\n    if(!confirm(\"Unsubscribe \"+email+\" from Northern Lights alerts?\"))return;\n    localStorage.removeItem(\"northernLightsPreferences_app\");\n    state.nameInput.value=\"\";state.emailInput.value=\"\";\n    toast(state,\"\u2705 Unsubscribed: \"+email);\n  });\n\n  runUpdate(state);\n  setInterval(function(){runUpdate(state);},REFRESH_MS);\n})();\n<\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Northern Lights Alert \u2013 North Wind Lapland NWL North Wind Lapland Powered by northwindlapland.com &#8212; Northern Lights Alert System Get notified when the probability of seeing the Northern Lights in Yll\u00e4s, Finland is over 50%. Yll\u00e4s, Finnish Lapland Update Data Current Probability Loading data&#8230; 0% Calculating probability based on current conditions&#8230; Aurora conditions visualization Kp [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":4862,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-4859","page","type-page","status-publish","has-post-thumbnail","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/pages\/4859","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/comments?post=4859"}],"version-history":[{"count":144,"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/pages\/4859\/revisions"}],"predecessor-version":[{"id":6026,"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/pages\/4859\/revisions\/6026"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/media\/4862"}],"wp:attachment":[{"href":"https:\/\/northwindlapland.com\/fr\/wp-json\/wp\/v2\/media?parent=4859"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}