{"id":7322,"date":"2025-11-17T02:24:32","date_gmt":"2025-11-17T07:24:32","guid":{"rendered":"https:\/\/www.ezcalculatoronline.com\/?page_id=7322"},"modified":"2026-10-29T23:53:06","modified_gmt":"2026-10-30T04:53:06","slug":"aurora","status":"publish","type":"page","link":"https:\/\/www.ezcalculatoronline.com\/online-tools\/aurora\/","title":{"rendered":"Aurora"},"content":{"rendered":"<div id=\"tdi_1\" class=\"tdc-zone\"><div class=\"tdc_zone tdi_2  wpb_row td-pb-row\"  >\n<style scoped>\n\n\/* custom css *\/\n.tdi_2{\r\n                    min-height: 0;\r\n                }\n<\/style><div id=\"tdi_3\" class=\"tdc-row\"><div class=\"vc_row tdi_4  wpb_row td-pb-row\" >\n<style scoped>\n\n\/* custom css *\/\n.tdi_4,\r\n                .tdi_4 .tdc-columns{\r\n                    min-height: 0;\r\n                }.tdi_4,\r\n\t\t\t\t.tdi_4 .tdc-columns{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_4 .tdc-columns{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}\n<\/style><div class=\"vc_column tdi_6  wpb_column vc_column_container tdc-column td-pb-span12\">\n<style scoped>\n\n\/* custom css *\/\n.tdi_6{\r\n                    vertical-align: baseline;\r\n                }.tdi_6 > .wpb_wrapper,\r\n\t\t\t\t.tdi_6 > .wpb_wrapper > .tdc-elements{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_6 > .wpb_wrapper > .tdc-elements{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}.tdi_6 > .wpb_wrapper > .vc_row_inner{\r\n\t\t\t\t    width: auto;\r\n\t\t\t\t}.tdi_6 > .wpb_wrapper{\r\n\t\t\t\t    width: auto;\r\n\t\t\t\t    height: auto;\r\n\t\t\t\t}\n<\/style><div class=\"wpb_wrapper\" ><div class=\"wpb_wrapper td_block_wrap vc_raw_html tdi_8 \">\n<style scoped>\n\n\/* inline tdc_css att *\/\n\n.tdi_8{\npadding-top:20px !important;\n}\n\n<\/style><div class=\"td-fix-index\"><!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n<title>Aurora Forecast Tracker<\/title>\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700;800&family=Space+Grotesk:wght@500;700&display=swap\" rel=\"stylesheet\">\r\n<link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.css\">\r\n<link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.5.1\/css\/all.min.css\">\r\n<style>\r\n\/* All styles are scoped under #aft so the tool is safe to embed in WordPress *\/\r\n#aft{\r\n  --bg:#f4f7fb;--panel:#ffffff;--panel2:#f5f8fc;--line:rgba(30,50,100,.11);\r\n  --text:#16203a;--muted:#66728f;--acc:#0f9f63;--acc2:#6b4cff;--warn:#c98200;--bad:#dc2f4f;--info:#1d8fd1;\r\n  position:relative;background:var(--bg);color:var(--text);font-family:Inter,system-ui,-apple-system,sans-serif;\r\n  min-height:100vh;overflow:hidden;padding:0 0 28px;line-height:1.45;-webkit-font-smoothing:antialiased;\r\n}\r\n#aft *{box-sizing:border-box}\r\n#aft button{font-family:inherit}\r\n#aft .sky{position:absolute;inset:0;pointer-events:none;z-index:0;\r\n  background:\r\n    radial-gradient(ellipse 70% 40% at 15% -10%,rgba(15,159,99,.10),transparent 62%),\r\n    radial-gradient(ellipse 55% 34% at 85% -8%,rgba(107,76,255,.10),transparent 62%);\r\n  animation:aftGlow 16s ease-in-out infinite alternate}\r\n@keyframes aftGlow{0%{opacity:.75;transform:translateX(-1.5%)}100%{opacity:1;transform:translateX(1.5%)}}\r\n\r\n\/* Header *\/\r\n#aft .hdr{position:relative;z-index:2;max-width:1440px;margin:0 auto;padding:22px 18px 8px;display:flex;justify-content:space-between;align-items:center;gap:14px;flex-wrap:wrap}\r\n#aft .brand{display:flex;align-items:center;gap:14px}\r\n#aft .logo{width:48px;height:48px;border-radius:14px;display:grid;place-items:center;font-size:20px;color:#fff;\r\n  background:linear-gradient(135deg,var(--acc),var(--acc2));box-shadow:0 6px 18px rgba(15,159,99,.25)}\r\n#aft h1{font-family:'Space Grotesk',Inter,sans-serif;font-size:26px;margin:0;font-weight:700;letter-spacing:.2px;color:var(--text);line-height:1.15}\r\n#aft .hdr p{margin:2px 0 0;color:var(--muted);font-size:13px}\r\n#aft .hdr-r{display:flex;gap:8px;align-items:center;flex-wrap:wrap}\r\n#aft .pill{display:inline-flex;align-items:center;gap:7px;padding:7px 12px;border-radius:999px;font-size:12.5px;font-weight:600;\r\n  background:var(--panel2);border:1px solid var(--line);color:var(--text);white-space:nowrap}\r\n#aft .pill .dot{width:8px;height:8px;border-radius:50%;background:var(--muted)}\r\n#aft .pill.live .dot{background:var(--acc);box-shadow:0 0 10px var(--acc);animation:aftPulse 1.8s infinite}\r\n#aft .pill.partial .dot{background:var(--warn)}\r\n#aft .pill.off .dot{background:var(--bad)}\r\n#aft .pill.muted{color:var(--muted);font-weight:500}\r\n@keyframes aftPulse{50%{opacity:.35}}\r\n#aft .ibtn{width:36px;height:36px;border-radius:10px;border:1px solid var(--line);background:var(--panel2);color:var(--text);cursor:pointer;transition:.2s}\r\n#aft .ibtn:hover{background:#e9eef6}\r\n#aft .ibtn.spin i{animation:aftSpin 1s linear infinite}\r\n@keyframes aftSpin{to{transform:rotate(360deg)}}\r\n\r\n\/* Layout *\/\r\n#aft .grid{position:relative;z-index:2;max-width:1440px;margin:10px auto 0;padding:0 18px;display:grid;gap:16px;\r\n  grid-template-columns:minmax(0,1.65fr) minmax(0,1fr);\r\n  grid-template-areas:\"map score\" \"map loc\" \"fc wind\";}\r\n#aft .a-map{grid-area:map}#aft .a-score{grid-area:score}#aft .a-loc{grid-area:loc}#aft .a-wind{grid-area:wind}#aft .a-fc{grid-area:fc}\r\n#aft .card{min-width:0;background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:18px;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 4px 20px rgba(30,50,100,.07)}\r\n#aft .ct{display:flex;justify-content:space-between;align-items:center;gap:10px;margin:0 0 14px;font-size:14px;font-weight:700;letter-spacing:.3px;text-transform:uppercase;color:#2a3655}\r\n#aft .ct i{color:var(--acc);margin-right:8px}\r\n#aft .ct small{font-weight:500;text-transform:none;color:var(--muted);letter-spacing:0;font-size:12px}\r\n\r\n\/* Score card *\/\r\n#aft .score-wrap{display:flex;gap:18px;align-items:center}\r\n#aft .gauge{--p:0;--gc:var(--muted);flex:0 0 auto;width:148px;height:148px;border-radius:50%;position:relative;display:grid;place-items:center;\r\n  background:conic-gradient(var(--gc) calc(var(--p)*1%),#e8edf5 0);transition:--p .8s}\r\n#aft .gauge::before{content:\"\";position:absolute;inset:11px;border-radius:50%;background:#fff;box-shadow:inset 0 0 16px rgba(30,50,100,.08)}\r\n#aft .gauge .gv{position:relative;text-align:center}\r\n#aft .gauge .gn{font-family:'Space Grotesk',sans-serif;font-size:40px;font-weight:700;line-height:1}\r\n#aft .gauge .gl{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.8px;margin-top:4px}\r\n#aft .verdict{font-family:'Space Grotesk',sans-serif;font-size:22px;font-weight:700;margin:0 0 4px}\r\n#aft .rec{font-size:13.5px;color:#3d4866;margin:0}\r\n#aft .chips{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:16px}\r\n#aft .chip{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:10px 12px;min-width:0}\r\n#aft .chip .k{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.6px;display:flex;align-items:center;gap:6px}\r\n#aft .chip .v{font-size:16px;font-weight:700;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\r\n#aft .chip .s{font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\r\n\r\n\/* Location *\/\r\n#aft .loc-name{font-size:17px;font-weight:700;margin:0 0 2px;display:flex;align-items:center;gap:8px}\r\n#aft .loc-sub{font-size:12.5px;color:var(--muted);margin:0 0 12px}\r\n#aft .search{position:relative;display:flex;gap:8px}\r\n#aft .inp{width:100%;padding:11px 12px;border-radius:11px;border:1px solid var(--line);background:#fff;color:var(--text);font-size:14px;outline:none;transition:.2s}\r\n#aft .inp:focus{border-color:var(--acc);box-shadow:0 0 0 3px rgba(15,159,99,.15)}\r\n#aft .btn{border:none;border-radius:11px;padding:11px 14px;font-weight:600;font-size:14px;cursor:pointer;transition:.2s;display:inline-flex;align-items:center;justify-content:center;gap:8px}\r\n#aft .btn-p{background:linear-gradient(135deg,var(--acc),#119db0);color:#fff}\r\n#aft .btn-p:hover{filter:brightness(1.08)}\r\n#aft .btn-g{background:var(--panel2);border:1px solid var(--line);color:var(--text)}\r\n#aft .btn-g:hover{background:#e9eef6}\r\n#aft .sugg{position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:1000;background:#fff;border:1px solid var(--line);border-radius:12px;overflow:hidden;box-shadow:0 14px 40px rgba(30,50,100,.15);display:none}\r\n#aft .sugg.show{display:block}\r\n#aft .sugg div{padding:10px 12px;cursor:pointer;font-size:13.5px;border-bottom:1px solid var(--line)}\r\n#aft .sugg div:last-child{border-bottom:none}\r\n#aft .sugg div:hover,#aft .sugg div.on{background:rgba(15,159,99,.08)}\r\n#aft .sugg small{color:var(--muted);display:block;font-size:11.5px}\r\n#aft .row2{display:flex;gap:8px;margin-top:10px}\r\n#aft .status{font-size:12px;color:var(--muted);margin-top:10px;min-height:16px}\r\n#aft .favs{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}\r\n#aft .favs button{font-size:12px;padding:5px 10px;border-radius:999px;border:1px solid var(--line);background:#fff;color:#3d4866;cursor:pointer}\r\n#aft .favs button:hover{border-color:var(--acc);color:var(--acc)}\r\n\r\n\/* Map *\/\r\n#aft .map-card{padding:0;overflow:hidden;display:flex;flex-direction:column;min-height:600px}\r\n#aft .map-bar{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:12px 14px;border-bottom:1px solid var(--line);flex-wrap:wrap}\r\n#aft .seg{display:inline-flex;background:#eef2f8;border:1px solid var(--line);border-radius:11px;padding:3px}\r\n#aft .seg button{border:none;background:transparent;color:var(--muted);padding:7px 12px;border-radius:8px;cursor:pointer;font-weight:600;font-size:13px}\r\n#aft .seg button.on{background:#fff;color:var(--acc);box-shadow:0 1px 4px rgba(30,50,100,.12)}\r\n#aft .tog{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:#3d4866;cursor:pointer;user-select:none;padding:6px 8px;border-radius:8px}\r\n#aft .tog input{accent-color:var(--acc)}\r\n#aft .map-body{position:relative;flex:1;min-height:480px}\r\n#aft #aft-map,#aft .static-view{position:absolute;inset:0}\r\n#aft #aft-map{background:#e9eef3;z-index:1}\r\n#aft .static-view{display:none;background:#0b1020;z-index:20}\r\n#aft .static-view img{width:100%;height:100%;object-fit:contain}\r\n#aft .imgmsg{position:absolute;inset:0;display:none;place-items:center;text-align:center;color:#c9d2e8;font-size:14px;line-height:1.7}\r\n#aft .imgmsg i{font-size:30px;opacity:.6}\r\n#aft .imgmsg a{color:#7fd8ff}\r\n#aft .static-tog{position:absolute;bottom:14px;right:14px;z-index:5}\r\n#aft .legend{position:absolute;left:14px;bottom:14px;z-index:500;background:rgba(255,255,255,.94);border:1px solid var(--line);border-radius:12px;padding:10px 12px;font-size:11.5px;color:var(--text);box-shadow:0 4px 14px rgba(30,50,100,.1);backdrop-filter:blur(8px)}\r\n#aft .legend .bar{width:170px;height:8px;border-radius:4px;margin:6px 0 3px;\r\n  background:linear-gradient(90deg,rgba(0,190,100,.3),#00be64 15%,#8cc800 35%,#f0a800 55%,#f04030 75%,#d01890)}\r\n#aft .legend .lab{display:flex;justify-content:space-between;color:var(--muted)}\r\n#aft .ov-time{position:absolute;top:12px;right:12px;z-index:500;font-size:11.5px;background:rgba(255,255,255,.94);border:1px solid var(--line);border-radius:999px;padding:5px 10px;color:var(--text)}\r\n#aft .map-hint{font-size:11.5px;color:var(--muted);padding:8px 14px;border-top:1px solid var(--line)}\r\n#aft .map-card:fullscreen{border-radius:0}\r\n#aft .leaflet-container{font-family:inherit}\r\n#aft .leaflet-bar a{background:#fff;color:#16203a;border-color:var(--line)}\r\n#aft .leaflet-bar a:hover{background:#eef2f8}\r\n#aft .leaflet-control-attribution{background:rgba(255,255,255,.8)!important;color:#66728f}\r\n#aft .leaflet-control-attribution a{color:#3b5bdb}\r\n#aft .aft-ov{image-rendering:auto;mix-blend-mode:multiply}\r\n#aft .pin{width:22px;height:22px;border-radius:50%;background:var(--acc);border:3px solid #fff;box-shadow:0 0 0 0 rgba(15,159,99,.55);animation:aftRing 2s infinite}\r\n@keyframes aftRing{0%{box-shadow:0 0 0 0 rgba(15,159,99,.55)}100%{box-shadow:0 0 0 18px rgba(15,159,99,0)}}\r\n\r\n\/* Solar wind *\/\r\n#aft .wind-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}\r\n#aft .stat{background:var(--panel2);border:1px solid var(--line);border-radius:14px;padding:12px}\r\n#aft .stat .k{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.6px}\r\n#aft .stat .v{font-family:'Space Grotesk',sans-serif;font-size:24px;font-weight:700;margin-top:2px}\r\n#aft .stat .v small{font-size:12px;color:var(--muted);font-family:Inter,sans-serif;font-weight:500;margin-left:3px}\r\n#aft .stat .t{font-size:11.5px;margin-top:2px;color:var(--muted)}\r\n#aft .spark{height:30px;margin-top:6px}\r\n#aft .spark svg{width:100%;height:100%;display:block}\r\n#aft .gbadge{display:inline-block;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:700;margin-left:6px;vertical-align:middle}\r\n#aft .explain{margin-top:12px;font-size:12px;color:var(--muted);background:rgba(29,143,209,.06);border:1px solid rgba(29,143,209,.2);border-radius:12px;padding:10px 12px}\r\n\r\n\/* Forecast *\/\r\n#aft .best{display:flex;gap:12px;align-items:center;padding:12px 14px;border-radius:14px;margin-bottom:14px;\r\n  background:linear-gradient(135deg,rgba(15,159,99,.08),rgba(107,76,255,.08));border:1px solid rgba(15,159,99,.25)}\r\n#aft .best i{font-size:22px;color:var(--acc)}\r\n#aft .best b{display:block;font-size:14.5px}\r\n#aft .best span{font-size:12.5px;color:#3d4866}\r\n#aft .kpchart{width:100%;height:150px;margin-bottom:10px}\r\n#aft .kpchart svg{width:100%;height:100%;display:block}\r\n#aft .fc-wrap{max-height:360px;overflow:auto;border-radius:12px;border:1px solid var(--line)}\r\n#aft table.fc{width:100%;border-collapse:collapse;font-size:13px}\r\n#aft table.fc th{position:sticky;top:0;background:#f3f6fb;color:var(--muted);font-weight:600;font-size:11px;text-transform:uppercase;letter-spacing:.6px;text-align:left;padding:9px 10px;z-index:1}\r\n#aft table.fc td{padding:8px 10px;border-top:1px solid var(--line);white-space:nowrap}\r\n#aft table.fc tr.day td{background:#f7f9fc;font-weight:700;font-size:12px;color:#2a3655;padding:7px 10px}\r\n#aft table.fc tr.now td{background:rgba(15,159,99,.07)}\r\n#aft .kpcell{display:flex;align-items:center;gap:8px;min-width:120px}\r\n#aft .kpbar{flex:1;height:6px;border-radius:3px;background:#e8edf5;overflow:hidden}\r\n#aft .kpbar i{display:block;height:100%;border-radius:3px}\r\n#aft .sc{display:inline-block;min-width:44px;text-align:center;padding:3px 8px;border-radius:7px;font-weight:700;font-size:12px}\r\n#aft .muted{color:var(--muted)}\r\n#aft .foot{position:relative;z-index:2;max-width:1440px;margin:18px auto 0;padding:0 18px;font-size:11.5px;color:var(--muted);text-align:center}\r\n#aft .foot a{color:var(--acc2)}\r\n\r\n@media (max-width:1100px){\r\n  #aft .grid{grid-template-columns:minmax(0,1fr);grid-template-areas:\"score\" \"loc\" \"map\" \"wind\" \"fc\"}\r\n  #aft .map-card{min-height:520px}\r\n  #aft .map-body{min-height:420px}\r\n}\r\n#aft .sky-lbl{margin-left:4px}\r\n#aft .now-lbl{margin-left:4px}\r\n#aft .mapdrag{display:none}\r\n#aft .hint-mob{display:none}\r\n#aft .map-card.pfs{position:fixed;inset:0;z-index:99999;border-radius:0;min-height:0;height:100%;height:100dvh}\r\n@media (max-width:760px){\r\n  #aft{padding-bottom:16px}\r\n  #aft .hdr{padding:14px 12px 4px;gap:10px}\r\n  #aft .brand{gap:10px}\r\n  #aft .logo{width:40px;height:40px;border-radius:12px;font-size:17px}\r\n  #aft h1{font-size:20px}\r\n  #aft .hdr p{font-size:12px}\r\n  #aft .hdr-r{width:100%;justify-content:space-between}\r\n  #aft .hdr-r .pill.muted{flex:1;justify-content:center;overflow:hidden;text-overflow:ellipsis}\r\n  #aft .grid{padding:0 10px;gap:12px;margin-top:6px}\r\n  #aft .card{padding:14px;border-radius:16px}\r\n  #aft .ct{font-size:12.5px;margin-bottom:12px;flex-wrap:wrap}\r\n  #aft .ct small{font-size:11px}\r\n\r\n  \/* score *\/\r\n  #aft .score-wrap{flex-direction:column;text-align:center;gap:12px}\r\n  #aft .gauge{width:132px;height:132px}\r\n  #aft .gauge .gn{font-size:36px}\r\n  #aft .verdict{font-size:19px}\r\n  #aft .rec{font-size:13px}\r\n  #aft .chips{gap:6px;margin-top:14px}\r\n  #aft .chip{padding:9px 10px}\r\n  #aft .chip .v{font-size:14.5px}\r\n  #aft .chip .k{font-size:10px}\r\n  #aft .chip .s{font-size:10.5px}\r\n\r\n  \/* location *\/\r\n  #aft .inp{font-size:16px;padding:11px 10px} \/* 16px stops iOS zoom-on-focus *\/\r\n  #aft .row2.coords{display:grid;grid-template-columns:1fr 1fr auto}\r\n  #aft .favs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:4px;scrollbar-width:none}\r\n  #aft .favs::-webkit-scrollbar{display:none}\r\n  #aft .favs button{flex:0 0 auto;padding:7px 12px;font-size:12.5px}\r\n\r\n  \/* map *\/\r\n  #aft .map-card{min-height:0}\r\n  #aft .map-bar{padding:10px;gap:8px}\r\n  #aft .map-bar .seg{width:100%}\r\n  #aft .map-bar .seg button{flex:1;padding:9px 6px}\r\n  #aft .map-tools{width:100%;justify-content:space-between}\r\n  #aft .map-body{min-height:0;height:62vh;max-height:520px;flex:none}\r\n  #aft .map-card.pfs .map-body{height:auto;max-height:none;flex:1}\r\n  #aft .mapdrag{display:inline-grid;place-items:center}\r\n  #aft .mapdrag.on{background:rgba(15,159,99,.12);color:var(--acc);border-color:var(--acc)}\r\n  #aft .legend{left:8px;bottom:8px;padding:7px 9px;font-size:10.5px}\r\n  #aft .legend .bar{width:110px;margin:4px 0 2px}\r\n  #aft .ov-time{top:8px;right:8px;font-size:10.5px;padding:4px 8px}\r\n  #aft .map-hint{font-size:11px;padding:8px 10px}\r\n  #aft .hint-desk{display:none}\r\n  #aft .hint-mob{display:inline}\r\n  #aft .static-tog{bottom:10px;right:10px}\r\n  #aft .leaflet-control-zoom a{width:34px;height:34px;line-height:34px}\r\n\r\n  \/* wind *\/\r\n  #aft .wind-grid{gap:8px}\r\n  #aft .stat{padding:10px}\r\n  #aft .stat .v{font-size:21px}\r\n  #aft .stat .t{font-size:11px}\r\n\r\n  \/* forecast *\/\r\n  #aft .best{padding:10px 12px;gap:10px}\r\n  #aft .best b{font-size:13.5px}\r\n  #aft .best span{font-size:12px}\r\n  #aft .kpchart{height:130px}\r\n  #aft .fc-wrap{max-height:420px}\r\n  #aft table.fc{font-size:12.5px}\r\n  #aft table.fc th{padding:8px 6px;font-size:10px}\r\n  #aft table.fc td{padding:8px 6px}\r\n  #aft table.fc tr.day td{padding:6px}\r\n  #aft .kpcell{min-width:0;gap:5px}\r\n  #aft .kpbar{min-width:28px}\r\n  #aft .kpcell .gbadge{display:none}\r\n  #aft .sky-lbl,#aft .now-lbl{display:none}\r\n  #aft .sc{min-width:36px;padding:3px 6px}\r\n  #aft .foot{padding:0 12px;font-size:11px}\r\n}\r\n@media (max-width:380px){\r\n  #aft h1{font-size:18px}\r\n  #aft .hdr p{display:none}\r\n  #aft .chip .v{font-size:13.5px}\r\n  #aft table.fc th:nth-child(4),#aft table.fc td:nth-child(4){display:none}\r\n}\r\n<\/style>\r\n<\/head>\r\n<body>\r\n<div id=\"aft\">\r\n  <div class=\"sky\"><\/div>\r\n\r\n  <header class=\"hdr\">\r\n    <div class=\"brand\">\r\n      <div class=\"logo\"><i class=\"fas fa-wand-magic-sparkles\"><\/i><\/div>\r\n      <div>\r\n        <h1>Aurora Forecast Tracker<\/h1>\r\n        <p>Live NOAA SWPC data \u00b7 OVATION aurora oval \u00b7 local darkness, clouds &amp; moon<\/p>\r\n      <\/div>\r\n    <\/div>\r\n    <div class=\"hdr-r\">\r\n      <span id=\"aft-status\" class=\"pill\"><span class=\"dot\"><\/span><span>Loading\u2026<\/span><\/span>\r\n      <span id=\"aft-updated\" class=\"pill muted\">--<\/span>\r\n      <button class=\"ibtn\" id=\"aft-refresh\" title=\"Refresh now\"><i class=\"fas fa-rotate\"><\/i><\/button>\r\n    <\/div>\r\n  <\/header>\r\n\r\n  <main class=\"grid\">\r\n\r\n    <!-- SCORE -->\r\n    <section class=\"card a-score\">\r\n      <div class=\"ct\"><span><i class=\"fas fa-eye\"><\/i>Viewing chance now<\/span><small id=\"aft-place-mini\">--<\/small><\/div>\r\n      <div class=\"score-wrap\">\r\n        <div class=\"gauge\" id=\"aft-gauge\"><div class=\"gv\"><div class=\"gn\" id=\"aft-score\">--<\/div><div class=\"gl\">Score<\/div><\/div><\/div>\r\n        <div>\r\n          <p class=\"verdict\" id=\"aft-verdict\">Calculating\u2026<\/p>\r\n          <p class=\"rec\" id=\"aft-rec\">Fetching live space-weather data.<\/p>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"chips\">\r\n        <div class=\"chip\"><div class=\"k\"><i class=\"fas fa-bolt\"><\/i>Aurora nearby<\/div><div class=\"v\" id=\"c-ov\">--<\/div><div class=\"s\" id=\"c-ov-s\">NOAA OVATION<\/div><\/div>\r\n        <div class=\"chip\"><div class=\"k\"><i class=\"fas fa-gauge-high\"><\/i>Kp needed<\/div><div class=\"v\" id=\"c-kpn\">--<\/div><div class=\"s\" id=\"c-kpn-s\">--<\/div><\/div>\r\n        <div class=\"chip\"><div class=\"k\"><i class=\"fas fa-cloud\"><\/i>Cloud cover<\/div><div class=\"v\" id=\"c-cloud\">--<\/div><div class=\"s\" id=\"c-cloud-s\">Open-Meteo<\/div><\/div>\r\n        <div class=\"chip\"><div class=\"k\"><i class=\"fas fa-sun\"><\/i>Darkness<\/div><div class=\"v\" id=\"c-dark\">--<\/div><div class=\"s\" id=\"c-dark-s\">--<\/div><\/div>\r\n        <div class=\"chip\"><div class=\"k\"><i class=\"fas fa-moon\"><\/i>Moon<\/div><div class=\"v\" id=\"c-moon\">--<\/div><div class=\"s\" id=\"c-moon-s\">--<\/div><\/div>\r\n        <div class=\"chip\"><div class=\"k\"><i class=\"fas fa-compass\"><\/i>Look<\/div><div class=\"v\" id=\"c-look\">--<\/div><div class=\"s\" id=\"c-look-s\">--<\/div><\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- LOCATION -->\r\n    <section class=\"card a-loc\">\r\n      <div class=\"ct\"><span><i class=\"fas fa-location-dot\"><\/i>Location<\/span><small>Click or drag on the map too<\/small><\/div>\r\n      <p class=\"loc-name\"><span id=\"aft-place\">--<\/span><\/p>\r\n      <p class=\"loc-sub\" id=\"aft-coords\">--<\/p>\r\n      <div class=\"search\">\r\n        <input id=\"aft-q\" class=\"inp\" type=\"text\" placeholder=\"Search a city, e.g. Troms\u00f8, Reykjavik\u2026\" autocomplete=\"off\">\r\n        <button class=\"btn btn-p\" id=\"aft-go\" title=\"Search\"><i class=\"fas fa-magnifying-glass\"><\/i><\/button>\r\n        <div class=\"sugg\" id=\"aft-sugg\"><\/div>\r\n      <\/div>\r\n      <div class=\"row2\">\r\n        <button class=\"btn btn-g\" id=\"aft-gps\" style=\"flex:1\"><i class=\"fas fa-location-crosshairs\"><\/i>Use my location<\/button>\r\n      <\/div>\r\n      <div class=\"row2 coords\">\r\n        <input id=\"aft-lat\" class=\"inp\" type=\"number\" step=\"any\" placeholder=\"Latitude\">\r\n        <input id=\"aft-lon\" class=\"inp\" type=\"number\" step=\"any\" placeholder=\"Longitude\">\r\n        <button class=\"btn btn-g\" id=\"aft-set\" title=\"Apply coordinates\"><i class=\"fas fa-check\"><\/i><\/button>\r\n      <\/div>\r\n      <div class=\"favs\" id=\"aft-favs\"><\/div>\r\n      <div class=\"status\" id=\"aft-lstatus\"><\/div>\r\n    <\/section>\r\n\r\n    <!-- MAP -->\r\n    <section class=\"card map-card a-map\" id=\"aft-mapcard\">\r\n      <div class=\"map-bar\">\r\n        <div class=\"seg\">\r\n          <button class=\"on\" data-view=\"map\"><i class=\"fas fa-map\"><\/i> Live map<\/button>\r\n          <button data-view=\"static\"><i class=\"fas fa-image\"><\/i> NOAA image<\/button>\r\n        <\/div>\r\n        <div class=\"map-tools\" style=\"display:flex;align-items:center;gap:4px;flex-wrap:wrap\">\r\n          <label class=\"tog\"><input type=\"checkbox\" id=\"t-oval\" checked> Aurora oval<\/label>\r\n          <label class=\"tog\"><input type=\"checkbox\" id=\"t-night\" checked> Day \/ night<\/label>\r\n          <span style=\"display:inline-flex;gap:6px\">\r\n            <button class=\"ibtn mapdrag\" id=\"aft-drag\" title=\"Allow moving the map with one finger\"><i class=\"fas fa-hand\"><\/i><\/button>\r\n            <button class=\"ibtn\" id=\"aft-fs\" title=\"Fullscreen\"><i class=\"fas fa-expand\"><\/i><\/button>\r\n          <\/span>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"map-body\">\r\n        <div id=\"aft-map\"><\/div>\r\n        <div class=\"ov-time\" id=\"aft-ovtime\">OVATION: --<\/div>\r\n        <div class=\"legend\" id=\"aft-legend\">\r\n          <b>Aurora probability<\/b>\r\n          <div class=\"bar\"><\/div>\r\n          <div class=\"lab\"><span>Low<\/span><span>50%<\/span><span>90%+<\/span><\/div>\r\n        <\/div>\r\n        <div class=\"static-view\" id=\"aft-static\">\r\n          <img id=\"aft-img\" alt=\"NOAA OVATION aurora forecast image\">\r\n          <div id=\"aft-imgmsg\" class=\"imgmsg\"><div><i class=\"fas fa-image\"><\/i><br>NOAA image is temporarily unavailable.<br><a href=\"https:\/\/www.swpc.noaa.gov\/products\/aurora-30-minute-forecast\" target=\"_blank\" rel=\"noopener\">Open it on swpc.noaa.gov<\/a><\/div><\/div>\r\n          <div class=\"seg static-tog\">\r\n            <button class=\"on\" data-hem=\"north\">North<\/button>\r\n            <button data-hem=\"south\">South<\/button>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"map-hint\"><i class=\"fas fa-circle-info\"><\/i> Coloured glow = NOAA OVATION 30\u201390 min aurora forecast. Shaded area = night side of Earth. <span class=\"hint-desk\">Click anywhere on the map to check that spot.<\/span><span class=\"hint-mob\">Tap to pick a spot \u00b7 pinch to zoom \u00b7 tap <i class=\"fas fa-hand\"><\/i> to pan.<\/span><\/div>\r\n    <\/section>\r\n\r\n    <!-- SOLAR WIND -->\r\n    <section class=\"card a-wind\">\r\n      <div class=\"ct\"><span><i class=\"fas fa-satellite-dish\"><\/i>Space weather now<\/span><small id=\"aft-windtime\">--<\/small><\/div>\r\n      <div class=\"wind-grid\">\r\n        <div class=\"stat\"><div class=\"k\">Kp index<\/div><div class=\"v\"><span id=\"w-kp\">--<\/span><span id=\"w-g\"><\/span><\/div><div class=\"t\" id=\"w-kp-t\">--<\/div><\/div>\r\n        <div class=\"stat\"><div class=\"k\">Bz (IMF)<\/div><div class=\"v\"><span id=\"w-bz\">--<\/span><small>nT<\/small><\/div><div class=\"t\" id=\"w-bz-t\">--<\/div><div class=\"spark\" id=\"s-bz\"><\/div><\/div>\r\n        <div class=\"stat\"><div class=\"k\">Wind speed<\/div><div class=\"v\"><span id=\"w-sp\">--<\/span><small>km\/s<\/small><\/div><div class=\"t\" id=\"w-sp-t\">--<\/div><div class=\"spark\" id=\"s-sp\"><\/div><\/div>\r\n        <div class=\"stat\"><div class=\"k\">Density<\/div><div class=\"v\"><span id=\"w-de\">--<\/span><small>p\/cm\u00b3<\/small><\/div><div class=\"t\" id=\"w-de-t\">--<\/div><div class=\"spark\" id=\"s-de\"><\/div><\/div>\r\n      <\/div>\r\n      <div class=\"explain\"><b>Quick guide:<\/b> Higher Kp pushes the aurora toward the equator. A <b>negative (south) Bz<\/b> and fast wind (&gt;500 km\/s) make displays brighter and more likely.<\/div>\r\n    <\/section>\r\n\r\n    <!-- FORECAST -->\r\n    <section class=\"card a-fc\">\r\n      <div class=\"ct\"><span><i class=\"fas fa-calendar-days\"><\/i>3-day forecast for your location<\/span><small id=\"aft-tz\">--<\/small><\/div>\r\n      <div class=\"best\" id=\"aft-best\"><i class=\"fas fa-star\"><\/i><div><b>Finding the best window\u2026<\/b><span>Combining NOAA Kp forecast, darkness and clouds.<\/span><\/div><\/div>\r\n      <div class=\"kpchart\" id=\"aft-kpchart\"><\/div>\r\n      <div class=\"fc-wrap\">\r\n        <table class=\"fc\">\r\n          <thead><tr><th>Time<\/th><th>Kp (NOAA)<\/th><th>Clouds<\/th><th>Sky<\/th><th>Score<\/th><\/tr><\/thead>\r\n          <tbody id=\"aft-fc\"><tr><td colspan=\"5\" class=\"muted\" style=\"text-align:center;padding:24px\">Loading\u2026<\/td><\/tr><\/tbody>\r\n        <\/table>\r\n      <\/div>\r\n    <\/section>\r\n\r\n  <\/main>\r\n\r\n  <div class=\"foot\">\r\n    Data: <a href=\"https:\/\/www.swpc.noaa.gov\/\" target=\"_blank\" rel=\"noopener\">NOAA SWPC<\/a> (Kp, solar wind, OVATION) \u00b7\r\n    <a href=\"https:\/\/open-meteo.com\/\" target=\"_blank\" rel=\"noopener\">Open-Meteo<\/a> (clouds) \u00b7\r\n    <a href=\"https:\/\/photon.komoot.io\/\" target=\"_blank\" rel=\"noopener\">Photon<\/a> (search). Scores are estimates \u2014 aurora is never guaranteed.\r\n  <\/div>\r\n<\/div>\r\n\r\n<script src=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.js\"><\/script>\r\n<script>\r\n(function () {\r\n  'use strict';\r\n  const $ = id => document.getElementById(id);\r\n  const D2R = Math.PI \/ 180, R2D = 180 \/ Math.PI;\r\n  const HOUR = 3600e3;\r\n  const REFRESH_MS = 5 * 60e3;\r\n  const MAG_POLE = { lat: 80.7, lon: -72.7 }; \/\/ geomagnetic dipole pole (approx.)\r\n\r\n  const API = {\r\n    kp1m: 'https:\/\/services.swpc.noaa.gov\/json\/planetary_k_index_1m.json',\r\n    kp3h: 'https:\/\/services.swpc.noaa.gov\/products\/noaa-planetary-k-index.json',\r\n    kpfc: 'https:\/\/services.swpc.noaa.gov\/products\/noaa-planetary-k-index-forecast.json',\r\n    \/\/ NOAA retired products\/solar-wind\/* in 2026; these are the RTSW replacements\r\n    mag: 'https:\/\/services.swpc.noaa.gov\/json\/rtsw\/rtsw_mag_1m.json',\r\n    plasma: 'https:\/\/services.swpc.noaa.gov\/json\/rtsw\/rtsw_wind_1m.json',\r\n    magOld: 'https:\/\/services.swpc.noaa.gov\/products\/solar-wind\/mag-2-hour.json',\r\n    plasmaOld: 'https:\/\/services.swpc.noaa.gov\/products\/solar-wind\/plasma-2-hour.json',\r\n    ovation: 'https:\/\/services.swpc.noaa.gov\/json\/ovation_aurora_latest.json',\r\n    imgs: {\r\n      north: ['https:\/\/services.swpc.noaa.gov\/images\/aurora-forecast-northern-hemisphere.jpg',\r\n              'https:\/\/services.swpc.noaa.gov\/images\/animations\/ovation\/north\/latest.jpg'],\r\n      south: ['https:\/\/services.swpc.noaa.gov\/images\/aurora-forecast-southern-hemisphere.jpg',\r\n              'https:\/\/services.swpc.noaa.gov\/images\/animations\/ovation\/south\/latest.jpg']\r\n    }\r\n  };\r\n\r\n  const FAVS = [\r\n    ['Fairbanks', 64.84, -147.72], ['Troms\u00f8', 69.65, 18.96], ['Reykjavik', 64.15, -21.94],\r\n    ['Yellowknife', 62.45, -114.37], ['Rovaniemi', 66.50, 25.73], ['Winnipeg', 49.90, -97.14], ['Hobart', -42.88, 147.33]\r\n  ];\r\n\r\n  const S = {\r\n    lat: 64.84, lon: -147.72, name: 'Fairbanks, United States',\r\n    tz: safeTZ(Intl.DateTimeFormat().resolvedOptions().timeZone),\r\n    kp: null, kpTime: null, bz: null, speed: null, density: null, windTime: null,\r\n    bzSeries: [], spSeries: [], deSeries: [],\r\n    grid: null, ovTime: null, kpfc: [], clouds: [], cloudNow: null,\r\n    nextRefresh: Date.now() + REFRESH_MS\r\n  };\r\n\r\n  try {\r\n    const saved = JSON.parse(localStorage.getItem('aft_loc') || 'null');\r\n    if (saved && isFinite(saved.lat) && isFinite(saved.lon)) { S.lat = saved.lat; S.lon = saved.lon; S.name = saved.name || S.name; }\r\n  } catch (e) {}\r\n\r\n  \/* ---------- helpers ---------- *\/\r\n  function safeTZ(tz) { try { new Intl.DateTimeFormat('en-US', { timeZone: tz }); return tz; } catch (e) { return 'UTC'; } }\r\n  function num(v) { if (v === null || v === undefined || v === '') return null; const n = parseFloat(v); return isNaN(n) ? null : n; }\r\n  function clamp(v, a, b) { return Math.max(a, Math.min(b, v)); }\r\n  function parseUTC(s) {\r\n    if (typeof s === 'number') return s;\r\n    let str = String(s || '').trim().replace(' ', 'T');\r\n    if (!\/([zZ]|[+-]\\d\\d:?\\d\\d)$\/.test(str)) str += 'Z';\r\n    return Date.parse(str);\r\n  }\r\n  \/\/ Accept both SWPC formats: [[header...],[row...]] or [{key:val}]\r\n  function rows(data) {\r\n    if (!Array.isArray(data) || !data.length) return [];\r\n    if (Array.isArray(data[0])) {\r\n      const h = data[0].map(k => String(k).toLowerCase());\r\n      return data.slice(1).map(r => { const o = {}; h.forEach((k, i) => o[k] = r[i]); return o; });\r\n    }\r\n    return data.map(o => { const n = {}; for (const k in o) n[k.toLowerCase()] = o[k]; return n; });\r\n  }\r\n  async function getJSON(url, ms = 20000) {\r\n    const ctl = new AbortController(); const t = setTimeout(() => ctl.abort(), ms);\r\n    try { const r = await fetch(url, { signal: ctl.signal, cache: 'no-store' }); if (!r.ok) throw new Error(r.status); return await r.json(); }\r\n    finally { clearTimeout(t); }\r\n  }\r\n  function fmt(t, opts) { try { return new Intl.DateTimeFormat('en-US', Object.assign({ timeZone: S.tz }, opts)).format(new Date(t)); } catch (e) { return new Date(t).toLocaleString(); } }\r\n  const fHour = t => fmt(t, { hour: 'numeric' });\r\n  const fTime = t => fmt(t, { hour: 'numeric', minute: '2-digit' });\r\n  const fDay = t => fmt(t, { weekday: 'short', month: 'short', day: 'numeric' });\r\n  const dayKey = t => fmt(t, { year: 'numeric', month: '2-digit', day: '2-digit' });\r\n  function wrapLon(lon) { return ((lon + 540) % 360) - 180; }\r\n\r\n  function kpColor(kp) { return kp >= 7 ? '#c026d3' : kp >= 6 ? '#dc2626' : kp >= 5 ? '#ea580c' : kp >= 4 ? '#d97706' : kp >= 3 ? '#65a30d' : '#16a34a'; }\r\n  function gScale(kp) { if (kp == null) return null; const k = Math.floor(kp + 0.001); return k >= 9 ? 'G5' : k >= 8 ? 'G4' : k >= 7 ? 'G3' : k >= 6 ? 'G2' : k >= 5 ? 'G1' : null; }\r\n  function kpLabel(kp) { return kp >= 7 ? 'Strong storm' : kp >= 5 ? 'Geomagnetic storm' : kp >= 4 ? 'Active' : kp >= 3 ? 'Unsettled' : 'Quiet'; }\r\n  function scoreColor(s) { return s >= 60 ? '#16a34a' : s >= 35 ? '#65a30d' : s >= 15 ? '#d97706' : s >= 5 ? '#ea580c' : '#94a3b8'; }\r\n\r\n  \/* ---------- astronomy ---------- *\/\r\n  function sunPos(date) {\r\n    const d = date \/ 86400000 + 2440587.5 - 2451545.0;\r\n    const g = (357.529 + 0.98560028 * d) * D2R;\r\n    const q = 280.459 + 0.98564736 * d;\r\n    const L = (q + 1.915 * Math.sin(g) + 0.020 * Math.sin(2 * g)) * D2R;\r\n    const e = (23.439 - 0.00000036 * d) * D2R;\r\n    const ra = Math.atan2(Math.cos(e) * Math.sin(L), Math.cos(L)) * R2D;\r\n    const dec = Math.asin(Math.sin(e) * Math.sin(L));\r\n    const gmst = ((18.697374558 + 24.06570982441908 * d) % 24 + 24) % 24;\r\n    return { dec, lon: wrapLon(ra - gmst * 15) };\r\n  }\r\n  function sunAlt(lat, lon, t) {\r\n    const s = sunPos(t); const H = (lon - s.lon) * D2R, p = lat * D2R;\r\n    return Math.asin(Math.sin(p) * Math.sin(s.dec) + Math.cos(p) * Math.cos(s.dec) * Math.cos(H)) * R2D;\r\n  }\r\n  function darkFactor(alt) { return alt <= -12 ? 1 : alt <= -9 ? 0.75 : alt <= -6 ? 0.35 : 0; }\r\n  function moonInfo(t) {\r\n    const syn = 29.530588853, ref = Date.UTC(2000, 0, 6, 18, 14);\r\n    let ph = ((t - ref) \/ 86400000 \/ syn) % 1; if (ph < 0) ph += 1;\r\n    const illum = Math.round((1 - Math.cos(2 * Math.PI * ph)) \/ 2 * 100);\r\n    const names = ['New moon', 'Waxing crescent', 'First quarter', 'Waxing gibbous', 'Full moon', 'Waning gibbous', 'Last quarter', 'Waning crescent'];\r\n    return { illum, name: names[Math.round(ph * 8) % 8] };\r\n  }\r\n  function magLat(lat, lon) {\r\n    const p = lat * D2R, pp = MAG_POLE.lat * D2R, dl = (lon - MAG_POLE.lon) * D2R;\r\n    return Math.asin(Math.sin(p) * Math.sin(pp) + Math.cos(p) * Math.cos(pp) * Math.cos(dl)) * R2D;\r\n  }\r\n  \/\/ Rough Kp \u2192 visibility relationship based on geomagnetic latitude (view-line model)\r\n  function kpBoundary(kp) { return 64.5 - 2.2 * kp; }\r\n  function kpChance(kp, mlat) {\r\n    const a = Math.abs(mlat), b = kpBoundary(kp);\r\n    let c = 100 \/ (1 + Math.exp(-(a - b) \/ 1.6));\r\n    if (a > 78) c *= 0.65; \/\/ deep polar cap: oval often equatorward\r\n    return c;\r\n  }\r\n  function kpNeeded(mlat) { return (64.5 - Math.abs(mlat)) \/ 2.2; }\r\n  function darkWindow(lat, lon, from) {\r\n    let start = null, end = null;\r\n    for (let t = from; t < from + 36 * HOUR; t += 10 * 60e3) {\r\n      const dark = sunAlt(lat, lon, t) <= -12;\r\n      if (dark && start === null) start = t;\r\n      if (!dark && start !== null) { end = t; break; }\r\n    }\r\n    return { start, end };\r\n  }\r\n\r\n  \/* ---------- OVATION ---------- *\/\r\n  const G = (lo, la) => S.grid[((lo % 360 + 360) % 360) * 181 + la];\r\n  function ovationAt(lat, lon) {\r\n    if (!S.grid) return null;\r\n    const la = clamp(Math.round(lat), -90, 90) + 90, lo = Math.round(lon);\r\n    const overhead = G(lo, la);\r\n    let near = overhead; const dir = lat >= 0 ? 1 : -1;\r\n    for (let d = 1; d <= 9; d++) {\r\n      const l2 = la + dir * d; if (l2 < 0 || l2 > 180) break;\r\n      const w = 1 - d \/ 10;\r\n      for (let dl = -4; dl <= 4; dl++) near = Math.max(near, G(lo + dl, l2) * w);\r\n    }\r\n    return { overhead, near: Math.round(near) };\r\n  }\r\n  const LUT = (() => {\r\n    const stops = [[0, 0, 190, 100, 0], [2, 0, 190, 100, 40], [10, 0, 190, 100, 150], [30, 140, 200, 0, 190], [50, 240, 168, 0, 210], [70, 240, 64, 48, 225], [90, 208, 24, 144, 235], [101, 208, 24, 144, 235]];\r\n    const lut = [];\r\n    for (let v = 0; v <= 100; v++) {\r\n      let i = 0; while (stops[i + 1][0] < v) i++;\r\n      const a = stops[i], b = stops[i + 1], t = (v - a[0]) \/ (b[0] - a[0]);\r\n      lut.push([0, 1, 2, 3].map(k => Math.round(a[k + 1] + (b[k + 1] - a[k + 1]) * t)));\r\n    }\r\n    return lut;\r\n  })();\r\n  function buildOvImage() {\r\n    const W = 720, H = 720, g = S.grid;\r\n    const cv = document.createElement('canvas'); cv.width = W; cv.height = H;\r\n    const ctx = cv.getContext('2d'); const img = ctx.createImageData(W, H); const d = img.data;\r\n    for (let y = 0; y < H; y++) {\r\n      const lat = Math.atan(Math.sinh(Math.PI * (1 - 2 * (y + 0.5) \/ H))) * R2D;\r\n      const fy = lat + 90, y0 = Math.floor(fy), y1 = Math.min(180, y0 + 1), ty = fy - y0;\r\n      for (let x = 0; x < W; x++) {\r\n        const fx = (-180 + (x + 0.5) * 360 \/ W + 360) % 360;\r\n        const x0 = Math.floor(fx) % 360, x1 = (x0 + 1) % 360, tx = fx - Math.floor(fx);\r\n        const v = (g[x0 * 181 + y0] * (1 - tx) + g[x1 * 181 + y0] * tx) * (1 - ty) + (g[x0 * 181 + y1] * (1 - tx) + g[x1 * 181 + y1] * tx) * ty;\r\n        if (v < 1) continue;\r\n        const c = LUT[Math.min(100, Math.round(v))], i = (y * W + x) * 4;\r\n        d[i] = c[0]; d[i + 1] = c[1]; d[i + 2] = c[2]; d[i + 3] = c[3];\r\n      }\r\n    }\r\n    ctx.putImageData(img, 0, 0);\r\n    return cv.toDataURL('image\/png');\r\n  }\r\n\r\n  \/* ---------- map ---------- *\/\r\n  let map, marker, nightLayer, ovLayer;\r\n  const OV_BOUNDS = [[-85.0511, -180], [85.0511, 180]];\r\n  const isSmall = () => window.matchMedia('(max-width:760px)').matches;\r\n  function setDrag(on) {\r\n    if (!map) return;\r\n    on ? map.dragging.enable() : map.dragging.disable();\r\n    $('aft-drag').classList.toggle('on', on);\r\n  }\r\n  function initMap() {\r\n    const small = isSmall();\r\n    map = L.map('aft-map', { zoomControl: true, minZoom: 1, worldCopyJump: true, dragging: !small, scrollWheelZoom: !small, tap: true })\r\n      .setView([S.lat, S.lon], small ? 2 : 3);\r\n    L.tileLayer('https:\/\/server.arcgisonline.com\/ArcGIS\/rest\/services\/Canvas\/World_Light_Gray_Base\/MapServer\/tile\/{z}\/{y}\/{x}', { maxZoom: 16, attribution: 'Tiles &copy; Esri' }).addTo(map);\r\n    map.createPane('labels'); map.getPane('labels').style.zIndex = 650; map.getPane('labels').style.pointerEvents = 'none';\r\n    L.tileLayer('https:\/\/server.arcgisonline.com\/ArcGIS\/rest\/services\/Canvas\/World_Light_Gray_Reference\/MapServer\/tile\/{z}\/{y}\/{x}', { maxZoom: 16, pane: 'labels' }).addTo(map);\r\n    nightLayer = L.polygon([], { stroke: false, fillColor: '#1c2b55', fillOpacity: 0.16, interactive: false }).addTo(map);\r\n    const icon = L.divIcon({ className: '', html: '<div class=\"pin\"><\/div>', iconSize: [22, 22], iconAnchor: [11, 11] });\r\n    marker = L.marker([S.lat, S.lon], { draggable: true, icon }).addTo(map);\r\n    marker.on('dragend', e => { const p = e.target.getLatLng(); setLocation(p.lat, wrapLon(p.lng), null, false); });\r\n    map.on('click', e => setLocation(e.latlng.lat, wrapLon(e.latlng.lng), null, false));\r\n    drawNight();\r\n    setTimeout(() => map.invalidateSize(), 250);\r\n  }\r\n  function drawNight() {\r\n    const s = sunPos(Date.now()); const pts = [];\r\n    const tanDec = Math.tan(Math.abs(s.dec) < 1e-4 ? 1e-4 : s.dec);\r\n    for (let lon = -180; lon <= 180; lon += 2) {\r\n      const lat = Math.atan(-Math.cos((lon - s.lon) * D2R) \/ tanDec) * R2D;\r\n      pts.push([clamp(lat, -85, 85), lon]);\r\n    }\r\n    const pole = s.dec > 0 ? -85 : 85;\r\n    pts.push([pole, 180], [pole, -180]);\r\n    nightLayer.setLatLngs(pts);\r\n  }\r\n  function updateOverlay() {\r\n    if (!S.grid || !map) return;\r\n    const url = buildOvImage();\r\n    if (ovLayer) ovLayer.setUrl(url);\r\n    else { ovLayer = L.imageOverlay(url, OV_BOUNDS, { opacity: 0.9, interactive: false, className: 'aft-ov' }); if ($('t-oval').checked) ovLayer.addTo(map); }\r\n  }\r\n\r\n  \/* ---------- data ---------- *\/\r\n  \/\/ RTSW: object records, newest first, may mix spacecraft (source\/active). Keep active, last 2 h, oldest\u2192newest.\r\n  function recentRTSW(data) {\r\n    let r = rows(data).map(o => Object.assign(o, { _t: parseUTC(o.time_tag) })).filter(o => !isNaN(o._t));\r\n    if (r.some(o => 'active' in o)) {\r\n      const act = r.filter(o => o.active === true || o.active === 1 || String(o.active).toLowerCase() === 'true');\r\n      if (act.length) r = act;\r\n    }\r\n    r.sort((a, b) => a._t - b._t);\r\n    const seen = new Set(); r = r.filter(o => !seen.has(o._t) && seen.add(o._t));\r\n    if (!r.length) return r;\r\n    const end = r[r.length - 1]._t;\r\n    return r.filter(o => o._t >= end - 2 * HOUR);\r\n  }\r\n\r\n  async function fetchSpaceWeather() {\r\n    const keys = ['kp1m', 'kp3h', 'kpfc', 'mag', 'plasma', 'ovation'];\r\n    const res = await Promise.allSettled(keys.map(k => getJSON(API[k])));\r\n    const R = {}; let ok = 0;\r\n    res.forEach((r, i) => { if (r.status === 'fulfilled') { R[keys[i]] = r.value; ok++; } else console.warn('Fetch failed:', keys[i], r.reason); });\r\n\r\n    \/\/ Kp now (1-minute estimate, fall back to 3-hour)\r\n    let kp = null, kpT = null;\r\n    if (R.kp1m) {\r\n      const r = rows(R.kp1m);\r\n      for (let i = r.length - 1; i >= 0; i--) { const v = num(r[i].estimated_kp ?? r[i].kp_index); if (v != null) { kp = v; kpT = parseUTC(r[i].time_tag); break; } }\r\n    }\r\n    if (kp == null && R.kp3h) {\r\n      const r = rows(R.kp3h);\r\n      for (let i = r.length - 1; i >= 0; i--) { const v = num(r[i].kp ?? r[i].kp_index); if (v != null) { kp = v; kpT = parseUTC(r[i].time_tag); break; } }\r\n    }\r\n    if (kp != null) { S.kp = kp; S.kpTime = kpT; }\r\n\r\n    \/\/ Kp forecast\r\n    if (R.kpfc) {\r\n      const fc = rows(R.kpfc).map(o => ({ t: parseUTC(o.time_tag), kp: num(o.kp ?? o.kp_index ?? o.estimated_kp), type: String(o.observed || '').toLowerCase() }))\r\n        .filter(x => !isNaN(x.t) && x.kp != null).sort((a, b) => a.t - b.t);\r\n      if (fc.length) S.kpfc = fc;\r\n    }\r\n\r\n    \/\/ Solar wind magnetic field\r\n    \/\/ Fall back to the old feeds only if the new ones fail\r\n    if (!R.mag) { try { R.mag = await getJSON(API.magOld); ok++; } catch (e) {} }\r\n    if (!R.plasma) { try { R.plasma = await getJSON(API.plasmaOld); ok++; } catch (e) {} }\r\n    if (R.mag) {\r\n      const r = recentRTSW(R.mag).map(o => ({ t: o._t, bz: num(o.bz_gsm ?? o.bz) })).filter(x => x.bz != null);\r\n      if (r.length) { S.bz = r[r.length - 1].bz; S.windTime = r[r.length - 1].t; S.bzSeries = r.map(x => x.bz); }\r\n    }\r\n    if (R.plasma) {\r\n      const r = recentRTSW(R.plasma).map(o => ({ t: o._t, sp: num(o.proton_speed ?? o.speed), de: num(o.proton_density ?? o.density) }));\r\n      const sp = r.filter(x => x.sp != null), de = r.filter(x => x.de != null);\r\n      if (sp.length) { S.speed = sp[sp.length - 1].sp; S.spSeries = sp.map(x => x.sp); }\r\n      if (de.length) { S.density = de[de.length - 1].de; S.deSeries = de.map(x => x.de); }\r\n    }\r\n\r\n    \/\/ OVATION grid\r\n    if (R.ovation && Array.isArray(R.ovation.coordinates)) {\r\n      const g = new Uint8Array(360 * 181);\r\n      for (const c of R.ovation.coordinates) {\r\n        const lo = ((Math.round(c[0]) % 360) + 360) % 360, la = Math.round(c[1]) + 90;\r\n        if (la >= 0 && la <= 180) g[lo * 181 + la] = Math.min(255, Math.max(0, c[2] | 0));\r\n      }\r\n      S.grid = g;\r\n      S.ovTime = parseUTC(R.ovation['Forecast Time'] || R.ovation['Observation Time']);\r\n      updateOverlay();\r\n    }\r\n    setStatus(ok, keys.length);\r\n  }\r\n\r\n  async function fetchClouds() {\r\n    const url = `https:\/\/api.open-meteo.com\/v1\/forecast?latitude=${S.lat.toFixed(3)}&longitude=${S.lon.toFixed(3)}&hourly=cloud_cover&current=cloud_cover&past_days=1&forecast_days=4&timezone=auto`;\r\n    try {\r\n      const d = await getJSON(url);\r\n      const off = (d.utc_offset_seconds || 0) * 1000;\r\n      S.clouds = (d.hourly && d.hourly.time || []).map((t, i) => ({ t: Date.parse(t + ':00Z') - off, cc: num(d.hourly.cloud_cover[i]) })).filter(x => x.cc != null);\r\n      S.cloudNow = d.current ? num(d.current.cloud_cover) : null;\r\n      if (d.timezone) S.tz = safeTZ(d.timezone);\r\n      S.cloudTime = Date.now();\r\n    } catch (e) { console.warn('Cloud fetch failed', e); S.clouds = []; S.cloudNow = null; }\r\n  }\r\n  function avgCloud(t0, t1) {\r\n    const v = S.clouds.filter(x => x.t >= t0 && x.t < t1);\r\n    return v.length ? v.reduce((a, b) => a + b.cc, 0) \/ v.length : null;\r\n  }\r\n\r\n  \/* ---------- rendering ---------- *\/\r\n  function setStatus(ok, total) {\r\n    const el = $('aft-status');\r\n    el.className = 'pill ' + (ok === total ? 'live' : ok > 0 ? 'partial' : 'off');\r\n    el.lastElementChild.textContent = ok === total ? 'Live NOAA data' : ok > 0 ? 'Partial data' : 'Offline';\r\n  }\r\n\r\n  function spark(el, vals, color, zero) {\r\n    if (!vals || vals.length < 2) { el.innerHTML = ''; return; }\r\n    const step = Math.max(1, Math.floor(vals.length \/ 60));\r\n    const v = vals.filter((_, i) => i % step === 0 || i === vals.length - 1);\r\n    const w = 120, h = 30;\r\n    let mn = Math.min(...v), mx = Math.max(...v);\r\n    if (zero) { mn = Math.min(mn, 0); mx = Math.max(mx, 0); }\r\n    const rg = (mx - mn) || 1, Y = x => h - 2 - (x - mn) \/ rg * (h - 4);\r\n    const pts = v.map((x, i) => `${(i \/ (v.length - 1) * w).toFixed(1)},${Y(x).toFixed(1)}`);\r\n    const zl = zero ? `<line x1=\"0\" x2=\"${w}\" y1=\"${Y(0)}\" y2=\"${Y(0)}\" stroke=\"rgba(30,50,100,.25)\" stroke-dasharray=\"3 3\" stroke-width=\"1\"\/>` : '';\r\n    el.innerHTML = `<svg viewBox=\"0 0 ${w} ${h}\" preserveAspectRatio=\"none\">${zl}<polyline fill=\"none\" stroke=\"${color}\" stroke-width=\"1.6\" stroke-linejoin=\"round\" points=\"${pts.join(' ')}\" vector-effect=\"non-scaling-stroke\"\/><\/svg>`;\r\n  }\r\n\r\n  function renderWind() {\r\n    const kp = S.kp;\r\n    $('w-kp').textContent = kp == null ? '--' : kp.toFixed(1);\r\n    $('w-kp').style.color = kp == null ? '' : kpColor(kp);\r\n    const g = gScale(kp);\r\n    $('w-g').innerHTML = g ? `<span class=\"gbadge\" style=\"background:${kpColor(kp)};color:#fff\">${g}<\/span>` : '';\r\n    $('w-kp-t').textContent = kp == null ? 'No data' : kpLabel(kp);\r\n\r\n    const bz = S.bz, bzEl = $('w-bz');\r\n    bzEl.textContent = bz == null ? '--' : (bz > 0 ? '+' : '') + bz.toFixed(1);\r\n    const bzCol = bz == null ? '' : bz <= -10 ? 'var(--bad)' : bz <= -5 ? 'var(--warn)' : bz < 0 ? 'var(--acc)' : 'var(--muted)';\r\n    bzEl.style.color = bzCol;\r\n    $('w-bz-t').textContent = bz == null ? 'No data' : bz <= -10 ? 'Strongly south \u2014 excellent' : bz <= -5 ? 'South \u2014 favourable' : bz < 0 ? 'Slightly south' : 'North \u2014 unfavourable';\r\n    spark($('s-bz'), S.bzSeries, '#1d8fd1', true);\r\n\r\n    const sp = S.speed;\r\n    $('w-sp').textContent = sp == null ? '--' : Math.round(sp);\r\n    $('w-sp').style.color = sp == null ? '' : sp >= 600 ? 'var(--bad)' : sp >= 500 ? 'var(--warn)' : '';\r\n    $('w-sp-t').textContent = sp == null ? 'No data' : sp >= 600 ? 'Very fast' : sp >= 500 ? 'Elevated' : sp >= 400 ? 'Moderate' : 'Slow';\r\n    spark($('s-sp'), S.spSeries, '#0f9f63');\r\n\r\n    const de = S.density;\r\n    $('w-de').textContent = de == null ? '--' : de.toFixed(1);\r\n    $('w-de-t').textContent = de == null ? 'No data' : de >= 15 ? 'High' : de >= 5 ? 'Normal' : 'Low';\r\n    spark($('s-de'), S.deSeries, '#6b4cff');\r\n\r\n    $('aft-windtime').textContent = S.windTime ? 'DSCOVR \u00b7 ' + fTime(S.windTime) : '';\r\n    $('aft-ovtime').textContent = S.ovTime ? 'OVATION forecast for ' + fTime(S.ovTime) : 'OVATION: --';\r\n  }\r\n\r\n  function renderLocal() {\r\n    const now = Date.now();\r\n    const ml = magLat(S.lat, S.lon);\r\n    const north = S.lat >= 0;\r\n    const alt = sunAlt(S.lat, S.lon, now), dark = darkFactor(alt);\r\n    const moon = moonInfo(now);\r\n    const cloud = S.cloudNow;\r\n    const ov = ovationAt(S.lat, S.lon);\r\n    const kp = S.kp == null ? 2 : S.kp;\r\n\r\n    \/\/ Aurora chance: OVATION nowcast if available, blended with Kp model\r\n    const kpC = kpChance(kp, ml);\r\n    let auroraC = kpC;\r\n    if (ov) auroraC = Math.max(Math.min(100, ov.near * 1.5), kpC * 0.6);\r\n    let score = auroraC * dark * (cloud == null ? 1 : (1 - cloud \/ 100));\r\n    if (moon.illum > 70 && dark > 0) score *= 0.9;\r\n    score = Math.round(clamp(score, 0, 100));\r\n\r\n    \/\/ Gauge\r\n    const gEl = $('aft-gauge');\r\n    gEl.style.setProperty('--p', score);\r\n    gEl.style.setProperty('--gc', scoreColor(score));\r\n    $('aft-score').textContent = score;\r\n    $('aft-score').style.color = scoreColor(score);\r\n\r\n    let verdict, rec;\r\n    if (dark === 0) {\r\n      verdict = 'Too bright right now';\r\n      const w = darkWindow(S.lat, S.lon, now);\r\n      rec = w.start ? `The sun is up or twilight is too bright. Proper darkness from ${fTime(w.start)}${w.end ? ' to ' + fTime(w.end) : ''}.` : 'No true darkness in the next 36 hours at this location (midnight sun \/ polar twilight).';\r\n    } else if (score >= 60) { verdict = 'Great chance \u2014 go outside!'; rec = `Find a dark spot away from city lights and look ${north ? 'north' : 'south'}, then overhead.`; }\r\n    else if (score >= 35) { verdict = 'Good chance'; rec = `Aurora is likely nearby. Look ${north ? 'north' : 'south'}; a phone camera can reveal faint colour.`; }\r\n    else if (score >= 15) { verdict = 'Possible, low on the horizon'; rec = `Watch the ${north ? 'northern' : 'southern'} horizon from a dark location. Keep an eye on Bz.`; }\r\n    else if (score >= 5) { verdict = 'Unlikely'; rec = cloud != null && cloud > 70 ? 'Clouds are the main problem right now.' : 'Activity is too weak for this latitude at the moment.'; }\r\n    else { verdict = 'Very unlikely'; rec = cloud != null && cloud > 85 ? 'Overcast skies block the view.' : `You would need about Kp ${Math.max(0, Math.ceil(kpNeeded(ml)))} for aurora here.`; }\r\n    $('aft-verdict').textContent = verdict;\r\n    $('aft-rec').textContent = rec;\r\n\r\n    \/\/ Chips\r\n    $('c-ov').textContent = ov ? ov.near + '%' : Math.round(kpC) + '%';\r\n    $('c-ov-s').textContent = ov ? `Overhead ${ov.overhead}% \u00b7 NOAA OVATION` : 'Kp model (OVATION unavailable)';\r\n    const need = kpNeeded(ml);\r\n    $('c-kpn').textContent = need <= 0 ? 'Any Kp' : need > 9 ? '9+ (rare)' : 'Kp ' + Math.ceil(need * 2) \/ 2;\r\n    $('c-kpn').style.color = S.kp != null && S.kp >= need ? 'var(--acc)' : '';\r\n    $('c-kpn-s').textContent = `Now Kp ${S.kp == null ? '--' : S.kp.toFixed(1)} \u00b7 mag. lat ${Math.abs(ml).toFixed(1)}\u00b0`;\r\n    $('c-cloud').textContent = cloud == null ? '--' : Math.round(cloud) + '%';\r\n    $('c-cloud').style.color = cloud == null ? '' : cloud <= 30 ? 'var(--acc)' : cloud <= 70 ? 'var(--warn)' : 'var(--bad)';\r\n    $('c-cloud-s').textContent = cloud == null ? 'Unavailable' : cloud <= 30 ? 'Mostly clear' : cloud <= 70 ? 'Partly cloudy' : 'Overcast';\r\n    $('c-dark').textContent = alt <= -12 ? 'Dark' : alt <= -6 ? 'Twilight' : alt <= 0 ? 'Civil twilight' : 'Daylight';\r\n    $('c-dark').style.color = alt <= -12 ? 'var(--acc)' : alt <= -6 ? 'var(--warn)' : 'var(--bad)';\r\n    const w = darkWindow(S.lat, S.lon, now);\r\n    $('c-dark-s').textContent = w.start ? (w.start <= now + 10 * 60e3 ? 'Until ' + (w.end ? fTime(w.end) : '\u2014') : 'From ' + fTime(w.start)) : 'No dark hours soon';\r\n    $('c-moon').textContent = moon.illum + '% lit';\r\n    $('c-moon-s').textContent = moon.name + (moon.illum > 70 ? ' \u00b7 bright sky' : '');\r\n    $('c-look').textContent = north ? 'North \u2191' : 'South \u2193';\r\n    $('c-look-s').textContent = Math.abs(ml) > 66 ? 'Also overhead' : 'Low on horizon first';\r\n\r\n    $('aft-place').textContent = S.name;\r\n    $('aft-place-mini').textContent = S.name.split(',')[0];\r\n    $('aft-coords').textContent = `${S.lat.toFixed(3)}\u00b0, ${S.lon.toFixed(3)}\u00b0 \u00b7 geomagnetic lat ${ml.toFixed(1)}\u00b0`;\r\n    $('aft-tz').textContent = 'Times in ' + S.tz.replace(\/_\/g, ' ');\r\n\r\n    S._ml = ml;\r\n    renderForecast(ml);\r\n  }\r\n\r\n  function renderForecast(ml) {\r\n    const now = Date.now();\r\n    const all = S.kpfc;\r\n    const body = $('aft-fc');\r\n    if (!all.length) { body.innerHTML = '<tr><td colspan=\"5\" class=\"muted\" style=\"text-align:center;padding:24px\">Kp forecast unavailable right now.<\/td><\/tr>'; $('aft-kpchart').innerHTML = ''; return; }\r\n\r\n    const slots = all.filter(x => x.t + 3 * HOUR > now).slice(0, 24).map(x => {\r\n      const mid = x.t + 1.5 * HOUR;\r\n      const alt = sunAlt(S.lat, S.lon, mid), df = darkFactor(alt);\r\n      const cc = avgCloud(x.t, x.t + 3 * HOUR);\r\n      const sc = Math.round(clamp(kpChance(x.kp, ml) * df * (cc == null ? 1 : 1 - cc \/ 100), 0, 100));\r\n      return Object.assign({}, x, { alt, df, cc, sc, isNow: x.t <= now && now < x.t + 3 * HOUR });\r\n    });\r\n\r\n    \/\/ Best window\r\n    const best = slots.reduce((a, b) => (b.sc > (a ? a.sc : -1) ? b : a), null);\r\n    const bEl = $('aft-best');\r\n    if (best && best.sc >= 5) {\r\n      bEl.innerHTML = `<i class=\"fas fa-star\"><\/i><div><b>Best window: ${fDay(best.t)}, ${fHour(best.t)} \u2013 ${fHour(best.t + 3 * HOUR)}<\/b><span>Score ${best.sc}\/100 \u00b7 Kp ${best.kp.toFixed(2)}${best.cc != null ? ' \u00b7 ' + Math.round(best.cc) + '% cloud' : ''}<\/span><\/div>`;\r\n    } else {\r\n      bEl.innerHTML = `<i class=\"fas fa-cloud-moon\"><\/i><div><b>No good viewing windows in the next 3 days<\/b><span>Here you'd need about Kp ${Math.max(0, Math.ceil(kpNeeded(ml)))}${slots.length ? '; max forecast is Kp ' + Math.max(...slots.map(s => s.kp)).toFixed(1) : ''}. Check back \u2014 forecasts change fast.<\/span><\/div>`;\r\n    }\r\n\r\n    \/\/ Table\r\n    let html = '', curDay = '';\r\n    for (const s of slots) {\r\n      const dk = dayKey(s.t);\r\n      if (dk !== curDay) { html += `<tr class=\"day\"><td colspan=\"5\">${fDay(s.t)}<\/td><\/tr>`; curDay = dk; }\r\n      const g = gScale(s.kp);\r\n      const sky = s.df >= 1 ? '<i class=\"fas fa-moon\" style=\"color:#4c5fa8\" title=\"Dark\"><\/i><span class=\"sky-lbl\">Dark<\/span>' : s.df > 0 ? '<i class=\"fas fa-cloud-sun\" style=\"color:var(--warn)\" title=\"Twilight\"><\/i><span class=\"sky-lbl\">Twilight<\/span>' : '<i class=\"fas fa-sun\" style=\"color:#e0a100\" title=\"Daylight\"><\/i><span class=\"sky-lbl\">Day<\/span>';\r\n      const ccTxt = s.cc == null ? '<span class=\"muted\">--<\/span>' : `<span style=\"color:${s.cc <= 30 ? 'var(--acc)' : s.cc <= 70 ? 'var(--warn)' : 'var(--bad)'}\">${Math.round(s.cc)}%<\/span>`;\r\n      html += `<tr class=\"${s.isNow ? 'now' : ''}\">\r\n        <td>${fHour(s.t)}\u2013${fHour(s.t + 3 * HOUR)}${s.isNow ? ' <span class=\"muted now-lbl\">(now)<\/span>' : ''}<\/td>\r\n        <td><div class=\"kpcell\"><div class=\"kpbar\"><i style=\"width:${s.kp \/ 9 * 100}%;background:${kpColor(s.kp)}\"><\/i><\/div><b style=\"color:${kpColor(s.kp)}\">${s.kp.toFixed(1)}<\/b>${g ? `<span class=\"gbadge\" style=\"background:${kpColor(s.kp)};color:#fff;margin-left:0\">${g}<\/span>` : ''}<\/div><\/td>\r\n        <td>${ccTxt}<\/td><td>${sky}<\/td>\r\n        <td><span class=\"sc\" style=\"background:${scoreColor(s.sc)}22;color:${scoreColor(s.sc)}\">${s.sc}<\/span><\/td><\/tr>`;\r\n    }\r\n    body.innerHTML = html;\r\n\r\n    \/\/ Chart: last 24h observed + forecast\r\n    const cs = all.filter(x => x.t >= now - 24 * HOUR).slice(0, 32);\r\n    const box = $('aft-kpchart');\r\n    const W = Math.max(280, Math.round(box.clientWidth || 640)), H = Math.round(box.clientHeight || 150);\r\n    const top = 10, bot = 24, left = 22, n = cs.length, bw = (W - left) \/ n, ph = H - top - bot, narrow = W < 480;\r\n    let svg = `<svg viewBox=\"0 0 ${W} ${H}\" width=\"${W}\" height=\"${H}\">`;\r\n    [3, 5, 7, 9].forEach(k => { const y = top + ph - k \/ 9 * ph; svg += `<line x1=\"${left}\" x2=\"${W}\" y1=\"${y}\" y2=\"${y}\" stroke=\"rgba(30,50,100,${k === 5 ? .25 : .1})\" stroke-dasharray=\"${k === 5 ? '4 4' : '2 4'}\"\/><text x=\"2\" y=\"${y + 4}\" fill=\"#66728f\" font-size=\"10\">${k}<\/text>`; });\r\n    let lastDay = '';\r\n    cs.forEach((x, i) => {\r\n      const h = Math.max(2, x.kp \/ 9 * ph), xx = left + i * bw, y = top + ph - h;\r\n      const obs = x.type === 'observed' || x.type === 'estimated';\r\n      const isNow = x.t <= now && now < x.t + 3 * HOUR;\r\n      svg += `<rect x=\"${(xx + 1.5).toFixed(1)}\" y=\"${y.toFixed(1)}\" width=\"${(bw - 3).toFixed(1)}\" height=\"${h.toFixed(1)}\" rx=\"2\" fill=\"${kpColor(x.kp)}\" opacity=\"${obs ? .4 : .95}\"${isNow ? ' stroke=\"#16203a\" stroke-width=\"1.5\"' : ''}><title>${fDay(x.t)} ${fHour(x.t)} \u00b7 Kp ${x.kp.toFixed(2)} (${x.type || 'forecast'})<\/title><\/rect>`;\r\n      const dk = dayKey(x.t);\r\n      if (dk !== lastDay) { svg += `<line x1=\"${xx}\" x2=\"${xx}\" y1=\"${top}\" y2=\"${H - bot + 4}\" stroke=\"rgba(30,50,100,.15)\"\/><text x=\"${xx + 4}\" y=\"${H - 6}\" fill=\"#2a3655\" font-size=\"${narrow ? 9.5 : 10.5}\">${fmt(x.t, narrow ? { weekday: 'short' } : { weekday: 'short', day: 'numeric' })}<\/text>`; lastDay = dk; }\r\n    });\r\n    if (!narrow) svg += `<text x=\"${W - 4}\" y=\"${top + 9}\" text-anchor=\"end\" fill=\"#66728f\" font-size=\"10\">faded = observed \u00b7 bright = forecast<\/text>`;\r\n    svg += '<\/svg>';\r\n    $('aft-kpchart').innerHTML = svg;\r\n  }\r\n\r\n  \/* ---------- location ---------- *\/\r\n  let locSeq = 0;\r\n  async function setLocation(lat, lon, name, pan = true) {\r\n    lat = clamp(lat, -90, 90); lon = wrapLon(lon);\r\n    S.lat = lat; S.lon = lon; S.name = name || `${lat.toFixed(2)}\u00b0, ${lon.toFixed(2)}\u00b0`;\r\n    $('aft-lat').value = lat.toFixed(3); $('aft-lon').value = lon.toFixed(3);\r\n    if (marker) marker.setLatLng([lat, lon]);\r\n    if (map && pan) map.flyTo([lat, lon], Math.max(map.getZoom(), 3), { duration: 0.8 });\r\n    const seq = ++locSeq;\r\n    renderLocal();\r\n    await fetchClouds();\r\n    if (seq !== locSeq) return;\r\n    if (!name) {\r\n      const n = await reverseGeocode(lat, lon);\r\n      if (seq !== locSeq) return;\r\n      if (n) S.name = n;\r\n    }\r\n    saveLoc(); renderLocal();\r\n  }\r\n  function saveLoc() { try { localStorage.setItem('aft_loc', JSON.stringify({ lat: S.lat, lon: S.lon, name: S.name })); } catch (e) {} }\r\n  function placeLabel(p) {\r\n    const parts = [p.name, p.city !== p.name ? p.city : null, p.state, p.country].filter(Boolean);\r\n    return [...new Set(parts)].slice(0, 3).join(', ');\r\n  }\r\n  async function reverseGeocode(lat, lon) {\r\n    try {\r\n      const d = await getJSON(`https:\/\/photon.komoot.io\/reverse?lat=${lat}&lon=${lon}&lang=en`, 8000);\r\n      if (d.features && d.features.length) return placeLabel(d.features[0].properties);\r\n    } catch (e) {}\r\n    return null;\r\n  }\r\n\r\n  let searchTimer, results = [], active = -1;\r\n  async function search(q, pickFirst) {\r\n    const st = $('aft-lstatus');\r\n    if (!q) { st.textContent = 'Type a city name to search.'; return; }\r\n    st.textContent = 'Searching\u2026';\r\n    try {\r\n      const d = await getJSON(`https:\/\/photon.komoot.io\/api\/?q=${encodeURIComponent(q)}&limit=6&lang=en`, 10000);\r\n      results = (d.features || []).map(f => ({ lat: f.geometry.coordinates[1], lon: f.geometry.coordinates[0], label: placeLabel(f.properties), type: f.properties.type || f.properties.osm_value || '' }));\r\n      if (!results.length) { st.textContent = 'No results. Try \"City, Country\".'; hideSugg(); return; }\r\n      st.textContent = '';\r\n      if (pickFirst) { choose(0); return; }\r\n      showSugg();\r\n    } catch (e) { st.textContent = 'Search failed \u2014 check your connection.'; }\r\n  }\r\n  function showSugg() {\r\n    active = -1;\r\n    const box = $('aft-sugg');\r\n    box.innerHTML = results.map((r, i) => `<div data-i=\"${i}\">${r.label.split(',')[0]}<small>${r.label.split(',').slice(1).join(',').trim() || r.type} \u00b7 ${r.lat.toFixed(2)}, ${r.lon.toFixed(2)}<\/small><\/div>`).join('');\r\n    box.classList.add('show');\r\n  }\r\n  function hideSugg() { $('aft-sugg').classList.remove('show'); }\r\n  function choose(i) {\r\n    const r = results[i]; if (!r) return;\r\n    hideSugg(); $('aft-q').value = '';\r\n    $('aft-lstatus').textContent = 'Showing: ' + r.label;\r\n    setLocation(r.lat, r.lon, r.label);\r\n  }\r\n\r\n  \/* ---------- events ---------- *\/\r\n  function bind() {\r\n    const q = $('aft-q');\r\n    q.addEventListener('input', () => {\r\n      clearTimeout(searchTimer);\r\n      const v = q.value.trim();\r\n      if (v.length < 3) { hideSugg(); return; }\r\n      searchTimer = setTimeout(() => search(v, false), 400);\r\n    });\r\n    q.addEventListener('keydown', e => {\r\n      const box = $('aft-sugg'), items = box.querySelectorAll('div');\r\n      if (e.key === 'ArrowDown' && items.length) { e.preventDefault(); active = (active + 1) % items.length; }\r\n      else if (e.key === 'ArrowUp' && items.length) { e.preventDefault(); active = (active - 1 + items.length) % items.length; }\r\n      else if (e.key === 'Enter') { e.preventDefault(); if (box.classList.contains('show') && active >= 0) choose(active); else { clearTimeout(searchTimer); search(q.value.trim(), true); } return; }\r\n      else if (e.key === 'Escape') { hideSugg(); return; }\r\n      items.forEach((el, i) => el.classList.toggle('on', i === active));\r\n    });\r\n    $('aft-sugg').addEventListener('click', e => { const d = e.target.closest('[data-i]'); if (d) choose(+d.dataset.i); });\r\n    document.addEventListener('click', e => { if (!e.target.closest('#aft .search')) hideSugg(); });\r\n    $('aft-go').onclick = () => { clearTimeout(searchTimer); search(q.value.trim(), true); };\r\n\r\n    $('aft-gps').onclick = () => {\r\n      const st = $('aft-lstatus');\r\n      if (!navigator.geolocation) { st.textContent = 'Geolocation is not supported by this browser.'; return; }\r\n      st.textContent = 'Locating\u2026';\r\n      navigator.geolocation.getCurrentPosition(\r\n        p => { st.textContent = 'Location detected.'; setLocation(p.coords.latitude, p.coords.longitude, null); },\r\n        () => { st.textContent = 'Location permission denied \u2014 use search instead.'; },\r\n        { timeout: 12000, enableHighAccuracy: true, maximumAge: 600000 }\r\n      );\r\n    };\r\n    const applyCoords = () => {\r\n      const la = parseFloat($('aft-lat').value), lo = parseFloat($('aft-lon').value);\r\n      if (isNaN(la) || isNaN(lo) || Math.abs(la) > 90) { $('aft-lstatus').textContent = 'Enter a valid latitude (\u221290\u202690) and longitude.'; return; }\r\n      setLocation(la, lo, null);\r\n    };\r\n    $('aft-set').onclick = applyCoords;\r\n    ['aft-lat', 'aft-lon'].forEach(id => $(id).addEventListener('keydown', e => { if (e.key === 'Enter') applyCoords(); }));\r\n\r\n    $('aft-favs').innerHTML = FAVS.map((f, i) => `<button data-f=\"${i}\">${f[0]}<\/button>`).join('');\r\n    $('aft-favs').addEventListener('click', e => { const b = e.target.closest('[data-f]'); if (!b) return; const f = FAVS[+b.dataset.f]; setLocation(f[1], f[2], null); });\r\n\r\n    document.querySelectorAll('#aft [data-view]').forEach(b => b.onclick = () => {\r\n      document.querySelectorAll('#aft [data-view]').forEach(x => x.classList.toggle('on', x === b));\r\n      const st = b.dataset.view === 'static';\r\n      $('aft-static').style.display = st ? 'block' : 'none';\r\n      $('aft-map').style.visibility = st ? 'hidden' : 'visible';\r\n      $('aft-legend').style.display = st ? 'none' : '';\r\n      $('aft-ovtime').style.display = st ? 'none' : '';\r\n      if (st) loadStatic(document.querySelector('#aft [data-hem].on').dataset.hem); else setTimeout(() => map.invalidateSize(), 60);\r\n    });\r\n    document.querySelectorAll('#aft [data-hem]').forEach(b => b.onclick = () => {\r\n      document.querySelectorAll('#aft [data-hem]').forEach(x => x.classList.toggle('on', x === b));\r\n      loadStatic(b.dataset.hem);\r\n    });\r\n    $('t-oval').onchange = e => { if (!ovLayer) return; e.target.checked ? ovLayer.addTo(map) : map.removeLayer(ovLayer); };\r\n    $('t-night').onchange = e => { e.target.checked ? nightLayer.addTo(map) : map.removeLayer(nightLayer); };\r\n    const pseudoFS = on => {\r\n      const el = $('aft-mapcard');\r\n      el.classList.toggle('pfs', on);\r\n      document.documentElement.style.overflow = on ? 'hidden' : '';\r\n      $('aft-fs').innerHTML = on ? '<i class=\"fas fa-compress\"><\/i>' : '<i class=\"fas fa-expand\"><\/i>';\r\n      if (on && isSmall()) setDrag(true);\r\n      setTimeout(() => map.invalidateSize(), 150);\r\n    };\r\n    $('aft-drag').onclick = () => setDrag(!map.dragging.enabled());\r\n    $('aft-fs').onclick = () => {\r\n      const el = $('aft-mapcard');\r\n      if (el.classList.contains('pfs')) { pseudoFS(false); if (isSmall()) setDrag(false); return; }\r\n      if (document.fullscreenElement) document.exitFullscreen();\r\n      else if (el.requestFullscreen) el.requestFullscreen().catch(() => pseudoFS(true));\r\n      else pseudoFS(true);\r\n    };\r\n    document.addEventListener('fullscreenchange', () => {\r\n      $('aft-fs').innerHTML = document.fullscreenElement ? '<i class=\"fas fa-compress\"><\/i>' : '<i class=\"fas fa-expand\"><\/i>';\r\n      if (isSmall()) setDrag(!!document.fullscreenElement);\r\n      setTimeout(() => map.invalidateSize(), 150);\r\n    });\r\n    $('aft-refresh').onclick = () => refreshAll(true);\r\n    let rT;\r\n    window.addEventListener('resize', () => {\r\n      clearTimeout(rT);\r\n      rT = setTimeout(() => {\r\n        if (map) { map.invalidateSize(); if (!$('aft-mapcard').classList.contains('pfs') && !document.fullscreenElement) setDrag(!isSmall()); }\r\n        if (S._ml != null) renderForecast(S._ml);\r\n      }, 200);\r\n    });\r\n  }\r\n  function loadStatic(hem) {\r\n    const img = $('aft-img'), list = API.imgs[hem] || API.imgs.north, msg = $('aft-imgmsg');\r\n    let i = 0; msg.style.display = 'none'; img.style.display = '';\r\n    img.onerror = () => {\r\n      i++;\r\n      if (i < list.length) img.src = `${list[i]}?t=${Date.now()}`;\r\n      else { img.style.display = 'none'; msg.style.display = 'grid'; }\r\n    };\r\n    img.src = `${list[0]}?t=${Date.now()}`;\r\n  }\r\n\r\n  \/* ---------- refresh loop ---------- *\/\r\n  let busy = false;\r\n  async function refreshAll(withClouds) {\r\n    if (busy) return; busy = true;\r\n    $('aft-refresh').classList.add('spin');\r\n    try {\r\n      await Promise.all([fetchSpaceWeather(), withClouds ? fetchClouds() : Promise.resolve()]);\r\n      drawNight(); renderWind(); renderLocal();\r\n      if ($('aft-static').style.display === 'block') loadStatic(document.querySelector('#aft [data-hem].on').dataset.hem);\r\n    } finally {\r\n      busy = false; $('aft-refresh').classList.remove('spin');\r\n      S.lastUpdate = Date.now(); S.nextRefresh = Date.now() + REFRESH_MS;\r\n    }\r\n  }\r\n  function tick() {\r\n    const left = Math.max(0, S.nextRefresh - Date.now());\r\n    const m = Math.floor(left \/ 60000), s = Math.floor(left \/ 1000) % 60;\r\n    $('aft-updated').textContent = S.lastUpdate ? `Updated ${new Date(S.lastUpdate).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} \u00b7 next ${m}:${String(s).padStart(2, '0')}` : 'Loading\u2026';\r\n    if (left === 0 && !busy) refreshAll(Date.now() - (S.cloudTime || 0) > 30 * 60e3).then(() => {});\r\n  }\r\n\r\n  \/* ---------- init ---------- *\/\r\n  async function init() {\r\n    initMap(); bind();\r\n    $('aft-lat').value = S.lat.toFixed(3); $('aft-lon').value = S.lon.toFixed(3);\r\n    renderLocal();\r\n    await refreshAll(true);\r\n    S.cloudTime = Date.now();\r\n    setInterval(tick, 1000);\r\n  }\r\n  init();\r\n})();\r\n<\/script>\r\n<\/body>\r\n<\/html><\/div><\/div><div class=\"wpb_wrapper td_block_wrap vc_raw_html tdi_10 \"><div class=\"td-fix-index\"><script async src=\"https:\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js?client=ca-pub-7396755811986582\"\n     crossorigin=\"anonymous\"><\/script>\n<!-- 980x120 -->\n<ins class=\"adsbygoogle\"\n     style=\"display:inline-block;width:980px;height:120px\"\n     data-ad-client=\"ca-pub-7396755811986582\"\n     data-ad-slot=\"5970608912\"><\/ins>\n<script>\n     (adsbygoogle = window.adsbygoogle || []).push({});\n<\/script><\/div><\/div><div class=\"wpb_wrapper wpb_text_column td_block_wrap td_block_wrap vc_column_text tdi_11  tagdiv-type td-pb-border-top td_block_template_1\"  data-td-block-uid=\"tdi_11\" ><div class=\"td-block-title-wrap\"><\/div><div class=\"td-fix-index\"><h2 data-start=\"99\" data-end=\"172\"><strong>Aurora Forecast Tracker \u2013 Track the Northern Lights Easily<\/strong><\/h2>\n<p data-start=\"174\" data-end=\"396\">If you love astronomy or simply want to catch the <strong data-start=\"224\" data-end=\"243\">aurora borealis<\/strong>, the <strong data-start=\"249\" data-end=\"276\">Aurora Forecast Tracker<\/strong> from NOAA SWPC is a must-have tool. It allows you to track and forecast auroral activity accurately and in real-time.<\/p>\n<p data-start=\"174\" data-end=\"396\"><img decoding=\"async\" class=\"aligncenter wp-image-7356 size-large\" src=\"https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/Aurora-1024x1024.jpg\" alt=\"\" width=\"1024\" height=\"1024\" srcset=\"https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/Aurora-1024x1024.jpg 1024w, https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/Aurora-300x300.jpg 300w, https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/Aurora-150x150.jpg 150w, https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/Aurora-768x768.jpg 768w, https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/Aurora-696x696.jpg 696w, https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/Aurora-1068x1068.jpg 1068w, https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/Aurora.jpg 1080w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<h2 data-start=\"398\" data-end=\"414\"><strong>Features<\/strong><\/h2>\n<p data-start=\"419\" data-end=\"685\"><strong data-start=\"419\" data-end=\"435\">Forecast Map<\/strong><br data-start=\"435\" data-end=\"438\" \/>The tool shows <strong data-start=\"456\" data-end=\"520\">areas where the aurora may be visible in the next 30 minutes<\/strong>, helping you quickly determine the best spots for aurora viewing. The map is <strong data-start=\"598\" data-end=\"639\">updated automatically every 5 minutes<\/strong>, keeping you informed with the latest data.<\/p>\n<ol data-start=\"416\" data-end=\"1646\">\n<li data-start=\"687\" data-end=\"1094\">\n<p data-start=\"690\" data-end=\"796\"><strong data-start=\"690\" data-end=\"726\">Kp Index \u2013 Aurora Activity Level<\/strong><br data-start=\"726\" data-end=\"729\" \/>The Kp Index measures auroral activity on a scale from 0 to 9:<\/p>\n<ul data-start=\"800\" data-end=\"1094\">\n<li data-start=\"800\" data-end=\"856\">\n<p data-start=\"802\" data-end=\"856\"><strong data-start=\"802\" data-end=\"813\">Kp \u2265 5:<\/strong> Aurora may be visible at high latitudes.\n<\/li>\n<li data-start=\"860\" data-end=\"1094\">\n<p data-start=\"862\" data-end=\"1094\">The tool provides <strong data-start=\"880\" data-end=\"902\">3-day Kp forecasts<\/strong>, allowing you to plan ahead.<br data-start=\"931\" data-end=\"934\" \/>For example, NOAA\u2019s forecast for Nov 17-19, 2025, shows a peak Kp of 4.67 (G1 \u2013 minor geomagnetic storm), enough for aurora visibility in northern regions.\n<\/li>\n<\/ul>\n<\/li>\n<li data-start=\"1096\" data-end=\"1314\">\n<p data-start=\"1099\" data-end=\"1314\"><strong data-start=\"1099\" data-end=\"1122\">Check Your Location<\/strong><br data-start=\"1122\" data-end=\"1125\" \/>You can <strong data-start=\"1136\" data-end=\"1199\">check if your current location has aurora viewing potential<\/strong>. With location access, the map automatically pinpoints your area and shows the probability of seeing the aurora.\n<\/li>\n<li data-start=\"1316\" data-end=\"1646\">\n<p data-start=\"1319\" data-end=\"1345\"><strong data-start=\"1319\" data-end=\"1343\">Additional NOAA Data<\/strong><\/p>\n<ul data-start=\"1349\" data-end=\"1646\">\n<li data-start=\"1349\" data-end=\"1429\">\n<p data-start=\"1351\" data-end=\"1429\"><strong data-start=\"1351\" data-end=\"1380\">Solar Radiation Activity:<\/strong> Forecasts minor or greater solar storms (S1+).\n<\/li>\n<li data-start=\"1433\" data-end=\"1646\">\n<p data-start=\"1435\" data-end=\"1646\"><strong data-start=\"1435\" data-end=\"1455\">Radio Blackouts:<\/strong> Forecasts R1-R3 levels that may affect radio signals.<br data-start=\"1509\" data-end=\"1512\" \/>All information is continuously updated, so you not only track auroras but also stay informed about <strong data-start=\"1615\" data-end=\"1643\">space weather conditions<\/strong>.\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h2 data-start=\"1648\" data-end=\"1670\"><strong>Quick Guide to Use<\/strong><\/h2>\n<ol data-start=\"1672\" data-end=\"1928\">\n<li data-start=\"1736\" data-end=\"1790\">\n<p data-start=\"1739\" data-end=\"1790\"><strong data-start=\"1739\" data-end=\"1764\">Allow location access<\/strong> for accurate forecasts.\n<\/li>\n<li data-start=\"1791\" data-end=\"1850\">\n<p data-start=\"1794\" data-end=\"1850\">Check the <strong data-start=\"1804\" data-end=\"1830\">30-minute forecast map<\/strong> and <strong data-start=\"1835\" data-end=\"1847\">Kp Index<\/strong>.\n<\/li>\n<li data-start=\"1851\" data-end=\"1928\">\n<p data-start=\"1854\" data-end=\"1928\">Plan your aurora viewing if Kp \u2265 5 and weather conditions are favorable.\n<\/li>\n<\/ol>\n<h2 data-start=\"51\" data-end=\"112\"><strong data-start=\"57\" data-end=\"112\">Latitudes &#038; Coordinates Where Aurora Is Easy to See<\/strong><\/h2>\n<div class=\"_tableContainer_1rjym_1\">\n<div class=\"group _tableWrapper_1rjym_13 flex w-fit flex-col-reverse\" tabindex=\"-1\">\n<table class=\"w-fit min-w-(--thread-content-width)\" data-start=\"114\" data-end=\"788\">\n<thead data-start=\"114\" data-end=\"157\">\n<tr data-start=\"114\" data-end=\"157\">\n<th data-start=\"114\" data-end=\"125\" data-col-size=\"sm\">Location<\/th>\n<th data-start=\"125\" data-end=\"136\" data-col-size=\"sm\">Latitude<\/th>\n<th data-start=\"136\" data-end=\"148\" data-col-size=\"sm\">Longitude<\/th>\n<th data-start=\"148\" data-end=\"157\" data-col-size=\"md\">Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody data-start=\"201\" data-end=\"788\">\n<tr data-start=\"201\" data-end=\"293\">\n<td data-start=\"201\" data-end=\"222\" data-col-size=\"sm\"><strong data-start=\"203\" data-end=\"221\">Troms\u00f8, Norway<\/strong><\/td>\n<td data-col-size=\"sm\" data-start=\"222\" data-end=\"233\">~69.6\u00b0 N<\/td>\n<td data-col-size=\"sm\" data-start=\"233\" data-end=\"243\">18.9\u00b0 E<\/td>\n<td data-col-size=\"md\" data-start=\"243\" data-end=\"293\">One of the best places on Earth to see auroras<\/td>\n<\/tr>\n<tr data-start=\"294\" data-end=\"374\">\n<td data-start=\"294\" data-end=\"319\" data-col-size=\"sm\"><strong data-start=\"296\" data-end=\"318\">Reykjav\u00edk, Iceland<\/strong><\/td>\n<td data-col-size=\"sm\" data-start=\"319\" data-end=\"330\">~64.1\u00b0 N<\/td>\n<td data-col-size=\"sm\" data-start=\"330\" data-end=\"341\">-21.8\u00b0 W<\/td>\n<td data-col-size=\"md\" data-start=\"341\" data-end=\"374\">Aurora visible even at Kp 2\u20133<\/td>\n<\/tr>\n<tr data-start=\"375\" data-end=\"451\">\n<td data-start=\"375\" data-end=\"399\" data-col-size=\"sm\"><strong data-start=\"377\" data-end=\"398\">Fairbanks, Alaska<\/strong><\/td>\n<td data-col-size=\"sm\" data-start=\"399\" data-end=\"410\">~64.8\u00b0 N<\/td>\n<td data-col-size=\"sm\" data-start=\"410\" data-end=\"422\">-147.7\u00b0 W<\/td>\n<td data-col-size=\"md\" data-start=\"422\" data-end=\"451\">Very high aurora activity<\/td>\n<\/tr>\n<tr data-start=\"452\" data-end=\"530\">\n<td data-start=\"452\" data-end=\"478\" data-col-size=\"sm\"><strong data-start=\"454\" data-end=\"477\">Yellowknife, Canada<\/strong><\/td>\n<td data-col-size=\"sm\" data-start=\"478\" data-end=\"489\">~62.4\u00b0 N<\/td>\n<td data-col-size=\"sm\" data-start=\"489\" data-end=\"501\">-114.4\u00b0 W<\/td>\n<td data-col-size=\"md\" data-start=\"501\" data-end=\"530\">Famous for strong auroras<\/td>\n<\/tr>\n<tr data-start=\"531\" data-end=\"614\">\n<td data-start=\"531\" data-end=\"554\" data-col-size=\"sm\"><strong data-start=\"533\" data-end=\"553\">Iqaluit, Nunavut<\/strong><\/td>\n<td data-col-size=\"sm\" data-start=\"554\" data-end=\"565\">~63.7\u00b0 N<\/td>\n<td data-col-size=\"sm\" data-start=\"565\" data-end=\"576\">-68.5\u00b0 W<\/td>\n<td data-col-size=\"md\" data-start=\"576\" data-end=\"614\">Frequently inside the auroral oval<\/td>\n<\/tr>\n<tr data-start=\"615\" data-end=\"694\">\n<td data-start=\"615\" data-end=\"638\" data-col-size=\"sm\"><strong data-start=\"617\" data-end=\"637\">Murmansk, Russia<\/strong><\/td>\n<td data-col-size=\"sm\" data-start=\"638\" data-end=\"649\">~68.9\u00b0 N<\/td>\n<td data-col-size=\"sm\" data-start=\"649\" data-end=\"659\">33.1\u00b0 E<\/td>\n<td data-col-size=\"md\" data-start=\"659\" data-end=\"694\">Consistently in the aurora zone<\/td>\n<\/tr>\n<tr data-start=\"695\" data-end=\"788\">\n<td data-start=\"695\" data-end=\"720\" data-col-size=\"sm\"><strong data-start=\"697\" data-end=\"719\">Rovaniemi, Finland<\/strong><\/td>\n<td data-col-size=\"sm\" data-start=\"720\" data-end=\"731\">~66.5\u00b0 N<\/td>\n<td data-col-size=\"sm\" data-start=\"731\" data-end=\"741\">25.7\u00b0 E<\/td>\n<td data-col-size=\"md\" data-start=\"741\" data-end=\"788\">Lapland region, excellent aurora visibility<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h2 data-start=\"1930\" data-end=\"1942\"><strong>Benefits<\/strong><\/h2>\n<ul data-start=\"1944\" data-end=\"2166\">\n<li data-start=\"1944\" data-end=\"1989\">\n<p data-start=\"1946\" data-end=\"1989\">Predicts the best time to see the aurora.\n<\/li>\n<li data-start=\"1990\" data-end=\"2045\">\n<p data-start=\"1992\" data-end=\"2045\"><strong data-start=\"1992\" data-end=\"2019\">Updated every 5 minutes<\/strong> for real-time accuracy.\n<\/li>\n<li data-start=\"2046\" data-end=\"2166\">\n<p data-start=\"2048\" data-end=\"2166\">Includes solar radiation and radio blackout forecasts, useful for amateur astronomers and space weather enthusiasts.\n<\/li>\n<\/ul>\n<p data-start=\"2173\" data-end=\"2395\"><strong data-start=\"2173\" data-end=\"2186\">In short:<\/strong> With <strong data-start=\"2192\" data-end=\"2219\">Aurora Forecast Tracker<\/strong>, spotting the northern lights has never been easier. A few clicks give you real-time insight into aurora activity near you and the best time to catch this natural spectacle.<\/p>\n<\/div><\/div><\/div><\/div><\/div><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":7356,"parent":4298,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-7322","page","type-page","status-publish","has-post-thumbnail"],"rankMath":{"parentDomain":"ezcalculatoronline.com","noFollowDomains":[],"noFollowExcludeDomains":[],"noFollowExternalLinks":false,"featuredImageNotice":"The featured image should be at least 200 by 200 pixels to be picked up by Facebook and other social media sites.","pluginReviewed":false,"postSettings":{"linkSuggestions":true,"useFocusKeyword":false},"frontEndScore":false,"postName":"aurora","permalinkFormat":"https:\/\/www.ezcalculatoronline.com\/%pagename%\/","showLockModifiedDate":true,"assessor":{"focusKeywordLink":"https:\/\/www.ezcalculatoronline.com\/wp-admin\/edit.php?focus_keyword=%focus_keyword%&post_type=%post_type%","hasTOCPlugin":false,"primaryTaxonomy":false,"serpData":{"title":"Aurora Forecast Tracker: Real-Time Northern Lights Map","description":"Track aurora activity with the Aurora Forecast Tracker. Check your location, Kp index, and 30-min forecast for the best northern lights viewing.","focusKeywords":"Aurora","pillarContent":false,"canonicalUrl":"","breadcrumbTitle":"","advancedRobots":{"max-snippet":"-1","max-video-preview":"-1","max-image-preview":"large"},"facebookTitle":"","facebookDescription":"","facebookImage":"","facebookImageID":"","facebookHasOverlay":false,"facebookImageOverlay":"","facebookAuthor":"","twitterCardType":"","twitterUseFacebook":true,"twitterTitle":"","twitterDescription":"","twitterImage":"","twitterImageID":"","twitterHasOverlay":false,"twitterImageOverlay":"","twitterPlayerUrl":"","twitterPlayerSize":"","twitterPlayerStream":"","twitterPlayerStreamCtype":"","twitterAppDescription":"","twitterAppIphoneName":"","twitterAppIphoneID":"","twitterAppIphoneUrl":"","twitterAppIpadName":"","twitterAppIpadID":"","twitterAppIpadUrl":"","twitterAppGoogleplayName":"","twitterAppGoogleplayID":"","twitterAppGoogleplayUrl":"","twitterAppCountry":"","robots":{"index":true},"twitterAuthor":"username","primaryTerm":0,"authorName":"Thien Nguyen","titleTemplate":"%title% %sep% %sitename%","descriptionTemplate":"%excerpt%","showScoreFrontend":true,"lockModifiedDate":false},"powerWords":["a cut above","absolute","absolutely","absolutely lowest","absurd","abuse","accurate","accuse","achieve","actionable","adaptable","adequate","admit","adorable","advantage","advice","affordable","aggravate","aggressive","agitated","agonizing","agony","alarmed","alarming","alienated","aligned","alive","all-inclusive","alluring","always","amazing","amp","animated","annihilate","announcing","anonymous","antagonistic","anxious","apocalypse","appalled","approved","approving","argumentative","armageddon","arrogant","ass kicking","assault","assured","astonishing","astounded","astounding","at ease","atrocious","attack","attractive","audacity","authentic","authoritative","authority","avoid","aware","awe-inspiring","awesome","awkward","backbone","backdoor","backed","backlash","backstabbing","badass","balanced","banned","bargain","barrage","basic","battle","beaming","beat down","beating","beautiful","beauty","begging","behind the scenes","belief","belong","best","best-selling","better","beware","big","billion","black market","blacklisted","blast","blessed","blinded","blissful","blood","bloodbath","bloodcurdling","bloody","blunder","blushing","bold","bomb","bona","bona fide","bonanza","bonus","bootleg","bottom line","bountiful","brave","bravery","brazen","break","breaking","breakthrough","breathtaking","bright","brilliant","broke","brutal","budget","buffoon","bullshit","bully","bumbling","buy","cadaver","calm","cancel anytime","capable","captivate","captivating","carefree","case study","cash","cataclysmic","catapult","catastrophe","caution","censored","centered","certain","certainly","certified","challenge","charming","cheap","cheat","cheat-sheet","cheer","cheerful","child-like","clarity","classified","clear","clueless","collapse","colorful","colossal","comfortable","compare","competitive","complete","completely","completeness","comprehensive","compromise","compulsive","concealed","conclusive","condemning","condescending","confess","confession","confessions","confident","confidential","conquer","conscientious","constructive","content","contrary","controlling","controversial","convenient","convert","cool","cooperative","copy","corpse","corrupt","corrupting","courage","courageous","cover-up","covert","coward","cowardly","crammed","crave","crazy","create","creative","cringeworthy","cripple","crisis","critical","crooked","crush","crushing","damaging","danger","dangerous","daring","dazzling","dead","deadline","deadly","death","decadent","deceived","deceptive","deep","defiance","definitely","definitive","defying","dejected","delicious","delight","delighted","delightful","delirious","delivered","demoralizing","deplorable","depraved","desire","desperate","despicable","destiny","destroy","detailed","devastating","devoted","diagnosed","direct","dirty","disadvantages","disastrous","discount","discover","disdainful","disempowered","disgusted","disgusting","dishonest","disillusioned","disoriented","distracted","distraught","distressed","distrustful","divulge","document","dollar","dominate","doomed","double","doubtful","download","dreadful","dreamy","drive","drowning","dumb","dynamic","eager","earnest","easily","easy","economical","ecstatic","edge","effective","efficient","effortless","elated","eliminate","elite","embarrass","embarrassed","embarrassing","emergency","emerging","emphasize","empowered","enchant","encouraged","endorsed","energetic","energy","enormous","enraged","enthusiastic","envy","epic","epidemic","essential","ethical","euphoric","evil","exactly","exasperated","excellent","excited","excitement","exciting","exclusive","exclusivity","excruciating","exhilarated","expensive","expert","explode","exploit","explosive","exposed","exquisite","extra","extraordinary","extremely","exuberant","eye-opening","fail","fail-proof","failure","faith","famous","fantasy","fascinating","fatigued","faux","faux pas","fearless","feast","feeble","festive","fide","fierce","fight","final","fine","fired","first","first ever","flirt","fluid","focus","focused","fool","fooled","foolish","forbidden","force-fed","forever","forgiving","forgotten","formula","fortune","foul","frantic","free","freebie","freedom","frenzied","frenzy","frightening","frisky","frugal","frustrated","fulfill","fulfilled","full","fully","fun","fun-loving","fundamentals","funniest","funny","furious","gambling","gargantuan","genius","genuine","gift","gigantic","giveaway","glamorous","gleeful","glorious","glowing","goddamn","gorgeous","graceful","grateful","gratified","gravity","great","greatest","greatness","greed","greedy","gripping","grit","grounded","growth","guaranteed","guilt","guilt-free","gullible","guts","hack","happiness","happy","harmful","harsh","hate","have you heard","havoc","hazardous","healthy","heart","heartbreaking","heartwarming","heavenly","hell","helpful","helplessness","hero","hesitant","hidden","high tech","highest","highly effective","hilarious","hoak","hoax","honest","honored","hope","hopeful","horribly","horrific","horrifying","horror","hostile","how to","huge","humility","humor","hurricane","hurry","hypnotic","idiot","ignite","illegal","illusive","imagination","immediately","imminently","impatience","impatient","impenetrable","important","impressive","improved","in the zone","incapable","incapacitated","incompetent","inconsiderate","increase","incredible","indecisive","indulgence","indulgent","inexpensive","inferior","informative","infuriated","ingredients","innocent","innovative","insane","insecure","insider","insidious","inspired","inspiring","instant savings","instantly","instructive","insult","intel","intelligent","intense","interesting","intriguing","introducing","invasion","investment","iron-clad","ironclad","irresistible","irs","is here","jackpot","jail","jaw-dropping","jealous","jeopardy","jittery","jovial","joyous","jubilant","judgmental","jumpstart","just arrived","keen","kickass","kickstart","kill","killed","killing","kills","know it all","lame","largest","lascivious","last","last chance","last minute","latest","laugh","laughing","launch","launching","lavishly","lawsuit","lazy","left behind","legendary","legitimate","liberal","liberated","lick","lies","life-changing","lifetime","light","lighthearted","likely","limited","literally","little-known","loathsome","lonely","looming","loser","lost","love","lucrative","lunatic","lurking","lust","luxurious","luxury","lying","magic","magical","magnificent","mainstream","malicious","mammoth","manipulative","marked down","massive","master","masterclass","maul","mediocre","meditative","meltdown","memorability","memorable","menacing","mesmerizing","meticulous","mind-blowing","minimalist","miracle","mired","mischievous","misgiving","missing out","mistake","monetize","money","moneyback","moneygrubbing","monumental","most important","motivated","mouth-watering","murder","mystery","nail","naked","natural","naughty","nazi","nest egg","never","new","nightmare","no good","no obligation","no one talks about","no questions asked","no risk","no strings attached","non-controlling","noted","novelty","now","obnoxious","obsessed","obsession","obvious","odd","off-kilter","off-limits","off-the record","offensive","official","okay","on-demand","open-minded","opportunities","optimistic","ordeal","outlawed","outrageousness","outstanding","overcome","overjoyed","overnight","overwhelmed","packed","painful","painless","painstaking","pale","panic","panicked","paralyzed","pas","passionate","pathetic","pay zero","payback","perfect","peril","perplexed","perspective","pessimistic","pioneering","piranha","pitfall","pitiful","placid","plague","played","playful","pleased","pluck","plummet","plunge","poison","poisonous","polarizing","poor","popular","portfolio","pound","powerful","powerless","practical","preposterous","prestige","price","priceless","pride","prison","privacy","private","privileged","prize","problem","productive","professional","profit","profitable","profound","promiscuous","promising","promote","protect","protected","proven","provocative","provoke","psychological","pummel","punch","punish","pus","quadruple","quality","quarrelsome","quick","quick-start","quickly","quiet","radiant","rare","ravenous","rebellious","recession-proof","reckoning","recognized","recommend","recreate","reduced","reflective","refugee","refund","refundable","reject","relaxed","release","relentless","reliable","remarkable","replicate","report","reprimanding","repulsed","repulsive","research","resentful","resourceful","responsible","responsive","rested","restricted","results","retaliating","reveal","revealing","revenge","revengeful","revisited","revolting","revolutionary","reward","rich","ridiculous","risky","riveting","rookie","rowdy","ruin","rules","ruthless","sabotaging","sacred","sadistic","sadly","sadness","safe","safety","sale","sampler","sarcastic","satisfied","savage","savagery","save","savings","savvy","scam","scandal","scandalous","scarce","scared","scary","scornful","scream","searing","secret","secret agenda","secret plot","secrets","secure","security","seductive","seething","seize","selected","self-hating","self-sufficient","sensational","senseless","sensual","serene","seriously","severe","sex","sexy","shaking","shameful","shameless","shaming","shatter","shellacking","shocking","should","shrewd","sick and tired","signs","silly","simple","simplicity","simplified","simplistic","sincere","sinful","sins","six-figure","sizable","sizzle","sizzled","sizzles","sizzling","sizzlingly","skill","skyrocket","slaughter","slave","sleazy","sleeping","sly","smash","smiling","smug","smuggle","smuggled","sneak-peek","sneaky","sniveling","snob","snooty","snotty","soar","soaring","solid","solution","spank","special","spectacular","speedy","spell-binding","spine","spirit","spirited","spiteful","spoiler","spontaneous","spotlight","spunky","squirming","stable","staggering","startling","steady","steal","stealthy","steamy","step-by-step","still","stoic","stop","strange","strangle","strategy","stressed","strong","strongly suggest","struggle","stuck up","studies","stunning","stupid","stupid-simple","sturdy","sublime","succeed","success","successful","suck","suddenly","suffer","sunny","super","super-human","superb","supercharge","superior","supported","supportive","sure","sure fire","surefire","surge","surging","surprise","surprised","surprising","survival","survive","suspicious","sweaty","swoon","swoon-worthy","tailspin","tank","tantalizing","targeted","tawdry","tease","technology","teetering","tempting","tenacious","tense","terrible","terrific","terrified","terrifying","terror","terrorist","tested","thankful","the truth","threaten","threatened","thrilled","thrilling","thug","ticked off","tickled","timely","today","torture","toxic","track record","trade secret","tragedy","tragic","transform","transparency","trap","trapped","trauma","traumatized","treacherous","treasure","tremendous","trend","tricks","triggers","triple","triumph","truly","trusting","trustworthy","truth","truthful","turbo-charge","turbocharges","tweaks","twitching","ultimate","unadulterated","unassuming","unauthorized","unbelievable","unburdened","uncaring","uncensored","uncertain","uncomfortable","unconditional","uncontrollable","unconventional","uncovered","undeniable","under priced","undercover","underground","underhanded","underused","unexpected","unforgettable","unheard of","unhurried","uninterested","unique","unjustified","unknowingly","unleashed","unlimited","unlock","unparalleled","unpopular","unreliable","unresponsive","unseen","unstable","unstoppable","unsure","unsurpassed","untapped","unusual","up-sell","upbeat","uplifted","uplifting","urge","urgent","useful","useless","validate","valor","valuable","value","vanquish","vaporize","venomous","verify","vibrant","vicious","victim","victory","vigorous","vilified","vindictive","violated","violent","volatile","vulnerable","waiting","wanted","wanton","warning","waste","weak","wealth","weird","what no one tells you","whip","whopping","wicked","wild","willpower","withheld","wonderful","wondrous","woozy","world","worry","worst","worthwhile","wounded","wreaking","youthful","zen","zinger"],"diacritics":{"A":"[\\u0041\\u24B6\\uFF21\\u00C0\\u00C1\\u00C2\\u1EA6\\u1EA4\\u1EAA\\u1EA8\\u00C3\\u0100\\u0102\\u1EB0\\u1EAE\\u1EB4\\u1EB2\\u0226\\u01E0\\u00C4\\u01DE\\u1EA2\\u00C5\\u01FA\\u01CD\\u0200\\u0202\\u1EA0\\u1EAC\\u1EB6\\u1E00\\u0104\\u023A\\u2C6F]","AA":"[\\uA732]","AE":"[\\u00C6\\u01FC\\u01E2]","AO":"[\\uA734]","AU":"[\\uA736]","AV":"[\\uA738\\uA73A]","AY":"[\\uA73C]","B":"[\\u0042\\u24B7\\uFF22\\u1E02\\u1E04\\u1E06\\u0243\\u0182\\u0181]","C":"[\\u0043\\u24B8\\uFF23\\u0106\\u0108\\u010A\\u010C\\u00C7\\u1E08\\u0187\\u023B\\uA73E]","D":"[\\u0044\\u24B9\\uFF24\\u1E0A\\u010E\\u1E0C\\u1E10\\u1E12\\u1E0E\\u0110\\u018B\\u018A\\u0189\\uA779]","DZ":"[\\u01F1\\u01C4]","Dz":"[\\u01F2\\u01C5]","E":"[\\u0045\\u24BA\\uFF25\\u00C8\\u00C9\\u00CA\\u1EC0\\u1EBE\\u1EC4\\u1EC2\\u1EBC\\u0112\\u1E14\\u1E16\\u0114\\u0116\\u00CB\\u1EBA\\u011A\\u0204\\u0206\\u1EB8\\u1EC6\\u0228\\u1E1C\\u0118\\u1E18\\u1E1A\\u0190\\u018E]","F":"[\\u0046\\u24BB\\uFF26\\u1E1E\\u0191\\uA77B]","G":"[\\u0047\\u24BC\\uFF27\\u01F4\\u011C\\u1E20\\u011E\\u0120\\u01E6\\u0122\\u01E4\\u0193\\uA7A0\\uA77D\\uA77E]","H":"[\\u0048\\u24BD\\uFF28\\u0124\\u1E22\\u1E26\\u021E\\u1E24\\u1E28\\u1E2A\\u0126\\u2C67\\u2C75\\uA78D]","I":"[\\u0049\\u24BE\\uFF29\\u00CC\\u00CD\\u00CE\\u0128\\u012A\\u012C\\u0130\\u00CF\\u1E2E\\u1EC8\\u01CF\\u0208\\u020A\\u1ECA\\u012E\\u1E2C\\u0197]","J":"[\\u004A\\u24BF\\uFF2A\\u0134\\u0248]","K":"[\\u004B\\u24C0\\uFF2B\\u1E30\\u01E8\\u1E32\\u0136\\u1E34\\u0198\\u2C69\\uA740\\uA742\\uA744\\uA7A2]","L":"[\\u004C\\u24C1\\uFF2C\\u013F\\u0139\\u013D\\u1E36\\u1E38\\u013B\\u1E3C\\u1E3A\\u0141\\u023D\\u2C62\\u2C60\\uA748\\uA746\\uA780]","LJ":"[\\u01C7]","Lj":"[\\u01C8]","M":"[\\u004D\\u24C2\\uFF2D\\u1E3E\\u1E40\\u1E42\\u2C6E\\u019C]","N":"[\\u004E\\u24C3\\uFF2E\\u01F8\\u0143\\u00D1\\u1E44\\u0147\\u1E46\\u0145\\u1E4A\\u1E48\\u0220\\u019D\\uA790\\uA7A4]","NJ":"[\\u01CA]","Nj":"[\\u01CB]","O":"[\\u004F\\u24C4\\uFF2F\\u00D2\\u00D3\\u00D4\\u1ED2\\u1ED0\\u1ED6\\u1ED4\\u00D5\\u1E4C\\u022C\\u1E4E\\u014C\\u1E50\\u1E52\\u014E\\u022E\\u0230\\u00D6\\u022A\\u1ECE\\u0150\\u01D1\\u020C\\u020E\\u01A0\\u1EDC\\u1EDA\\u1EE0\\u1EDE\\u1EE2\\u1ECC\\u1ED8\\u01EA\\u01EC\\u00D8\\u01FE\\u0186\\u019F\\uA74A\\uA74C]","OI":"[\\u01A2]","OO":"[\\uA74E]","OU":"[\\u0222]","P":"[\\u0050\\u24C5\\uFF30\\u1E54\\u1E56\\u01A4\\u2C63\\uA750\\uA752\\uA754]","Q":"[\\u0051\\u24C6\\uFF31\\uA756\\uA758\\u024A]","R":"[\\u0052\\u24C7\\uFF32\\u0154\\u1E58\\u0158\\u0210\\u0212\\u1E5A\\u1E5C\\u0156\\u1E5E\\u024C\\u2C64\\uA75A\\uA7A6\\uA782]","S":"[\\u0053\\u24C8\\uFF33\\u1E9E\\u015A\\u1E64\\u015C\\u1E60\\u0160\\u1E66\\u1E62\\u1E68\\u0218\\u015E\\u2C7E\\uA7A8\\uA784]","T":"[\\u0054\\u24C9\\uFF34\\u1E6A\\u0164\\u1E6C\\u021A\\u0162\\u1E70\\u1E6E\\u0166\\u01AC\\u01AE\\u023E\\uA786]","TZ":"[\\uA728]","U":"[\\u0055\\u24CA\\uFF35\\u00D9\\u00DA\\u00DB\\u0168\\u1E78\\u016A\\u1E7A\\u016C\\u00DC\\u01DB\\u01D7\\u01D5\\u01D9\\u1EE6\\u016E\\u0170\\u01D3\\u0214\\u0216\\u01AF\\u1EEA\\u1EE8\\u1EEE\\u1EEC\\u1EF0\\u1EE4\\u1E72\\u0172\\u1E76\\u1E74\\u0244]","V":"[\\u0056\\u24CB\\uFF36\\u1E7C\\u1E7E\\u01B2\\uA75E\\u0245]","VY":"[\\uA760]","W":"[\\u0057\\u24CC\\uFF37\\u1E80\\u1E82\\u0174\\u1E86\\u1E84\\u1E88\\u2C72]","X":"[\\u0058\\u24CD\\uFF38\\u1E8A\\u1E8C]","Y":"[\\u0059\\u24CE\\uFF39\\u1EF2\\u00DD\\u0176\\u1EF8\\u0232\\u1E8E\\u0178\\u1EF6\\u1EF4\\u01B3\\u024E\\u1EFE]","Z":"[\\u005A\\u24CF\\uFF3A\\u0179\\u1E90\\u017B\\u017D\\u1E92\\u1E94\\u01B5\\u0224\\u2C7F\\u2C6B\\uA762]","a":"[\\u0061\\u24D0\\uFF41\\u1E9A\\u00E0\\u00E1\\u00E2\\u1EA7\\u1EA5\\u1EAB\\u1EA9\\u00E3\\u0101\\u0103\\u1EB1\\u1EAF\\u1EB5\\u1EB3\\u0227\\u01E1\\u00E4\\u01DF\\u1EA3\\u00E5\\u01FB\\u01CE\\u0201\\u0203\\u1EA1\\u1EAD\\u1EB7\\u1E01\\u0105\\u2C65\\u0250]","aa":"[\\uA733]","ae":"[\\u00E6\\u01FD\\u01E3]","ao":"[\\uA735]","au":"[\\uA737]","av":"[\\uA739\\uA73B]","ay":"[\\uA73D]","b":"[\\u0062\\u24D1\\uFF42\\u1E03\\u1E05\\u1E07\\u0180\\u0183\\u0253]","c":"[\\u0063\\u24D2\\uFF43\\u0107\\u0109\\u010B\\u010D\\u00E7\\u1E09\\u0188\\u023C\\uA73F\\u2184]","d":"[\\u0064\\u24D3\\uFF44\\u1E0B\\u010F\\u1E0D\\u1E11\\u1E13\\u1E0F\\u0111\\u018C\\u0256\\u0257\\uA77A]","dz":"[\\u01F3\\u01C6]","e":"[\\u0065\\u24D4\\uFF45\\u00E8\\u00E9\\u00EA\\u1EC1\\u1EBF\\u1EC5\\u1EC3\\u1EBD\\u0113\\u1E15\\u1E17\\u0115\\u0117\\u00EB\\u1EBB\\u011B\\u0205\\u0207\\u1EB9\\u1EC7\\u0229\\u1E1D\\u0119\\u1E19\\u1E1B\\u0247\\u025B\\u01DD]","f":"[\\u0066\\u24D5\\uFF46\\u1E1F\\u0192\\uA77C]","g":"[\\u0067\\u24D6\\uFF47\\u01F5\\u011D\\u1E21\\u011F\\u0121\\u01E7\\u0123\\u01E5\\u0260\\uA7A1\\u1D79\\uA77F]","h":"[\\u0068\\u24D7\\uFF48\\u0125\\u1E23\\u1E27\\u021F\\u1E25\\u1E29\\u1E2B\\u1E96\\u0127\\u2C68\\u2C76\\u0265]","hv":"[\\u0195]","i":"[\\u0069\\u24D8\\uFF49\\u00EC\\u00ED\\u00EE\\u0129\\u012B\\u012D\\u00EF\\u1E2F\\u1EC9\\u01D0\\u0209\\u020B\\u1ECB\\u012F\\u1E2D\\u0268\\u0131]","j":"[\\u006A\\u24D9\\uFF4A\\u0135\\u01F0\\u0249]","k":"[\\u006B\\u24DA\\uFF4B\\u1E31\\u01E9\\u1E33\\u0137\\u1E35\\u0199\\u2C6A\\uA741\\uA743\\uA745\\uA7A3]","l":"[\\u006C\\u24DB\\uFF4C\\u0140\\u013A\\u013E\\u1E37\\u1E39\\u013C\\u1E3D\\u1E3B\\u017F\\u0142\\u019A\\u026B\\u2C61\\uA749\\uA781\\uA747]","lj":"[\\u01C9]","m":"[\\u006D\\u24DC\\uFF4D\\u1E3F\\u1E41\\u1E43\\u0271\\u026F]","n":"[\\u006E\\u24DD\\uFF4E\\u01F9\\u0144\\u00F1\\u1E45\\u0148\\u1E47\\u0146\\u1E4B\\u1E49\\u019E\\u0272\\u0149\\uA791\\uA7A5]","nj":"[\\u01CC]","o":"[\\u006F\\u24DE\\uFF4F\\u00F2\\u00F3\\u00F4\\u1ED3\\u1ED1\\u1ED7\\u1ED5\\u00F5\\u1E4D\\u022D\\u1E4F\\u014D\\u1E51\\u1E53\\u014F\\u022F\\u0231\\u00F6\\u022B\\u1ECF\\u0151\\u01D2\\u020D\\u020F\\u01A1\\u1EDD\\u1EDB\\u1EE1\\u1EDF\\u1EE3\\u1ECD\\u1ED9\\u01EB\\u01ED\\u00F8\\u01FF\\u0254\\uA74B\\uA74D\\u0275]","oi":"[\\u01A3]","ou":"[\\u0223]","oo":"[\\uA74F]","p":"[\\u0070\\u24DF\\uFF50\\u1E55\\u1E57\\u01A5\\u1D7D\\uA751\\uA753\\uA755]","q":"[\\u0071\\u24E0\\uFF51\\u024B\\uA757\\uA759]","r":"[\\u0072\\u24E1\\uFF52\\u0155\\u1E59\\u0159\\u0211\\u0213\\u1E5B\\u1E5D\\u0157\\u1E5F\\u024D\\u027D\\uA75B\\uA7A7\\uA783]","s":"[\\u0073\\u24E2\\uFF53\\u015B\\u1E65\\u015D\\u1E61\\u0161\\u1E67\\u1E63\\u1E69\\u0219\\u015F\\u023F\\uA7A9\\uA785\\u1E9B]","ss":"[\\u00DF]","t":"[\\u0074\\u24E3\\uFF54\\u1E6B\\u1E97\\u0165\\u1E6D\\u021B\\u0163\\u1E71\\u1E6F\\u0167\\u01AD\\u0288\\u2C66\\uA787]","tz":"[\\uA729]","u":"[\\u0075\\u24E4\\uFF55\\u00F9\\u00FA\\u00FB\\u0169\\u1E79\\u016B\\u1E7B\\u016D\\u00FC\\u01DC\\u01D8\\u01D6\\u01DA\\u1EE7\\u016F\\u0171\\u01D4\\u0215\\u0217\\u01B0\\u1EEB\\u1EE9\\u1EEF\\u1EED\\u1EF1\\u1EE5\\u1E73\\u0173\\u1E77\\u1E75\\u0289]","v":"[\\u0076\\u24E5\\uFF56\\u1E7D\\u1E7F\\u028B\\uA75F\\u028C]","vy":"[\\uA761]","w":"[\\u0077\\u24E6\\uFF57\\u1E81\\u1E83\\u0175\\u1E87\\u1E85\\u1E98\\u1E89\\u2C73]","x":"[\\u0078\\u24E7\\uFF58\\u1E8B\\u1E8D]","y":"[\\u0079\\u24E8\\uFF59\\u1EF3\\u00FD\\u0177\\u1EF9\\u0233\\u1E8F\\u00FF\\u1EF7\\u1E99\\u1EF5\\u01B4\\u024F\\u1EFF]","z":"[\\u007A\\u24E9\\uFF5A\\u017A\\u1E91\\u017C\\u017E\\u1E93\\u1E95\\u01B6\\u0225\\u0240\\u2C6C\\uA763]"},"researchesTests":["contentHasTOC","contentHasShortParagraphs","contentHasAssets","keywordInTitle","keywordInMetaDescription","keywordInPermalink","keywordIn10Percent","keywordInContent","keywordInSubheadings","keywordInImageAlt","keywordDensity","keywordNotUsed","lengthContent","lengthPermalink","linksHasInternal","linksHasExternals","linksNotAllExternals","titleStartWithKeyword","titleSentiment","titleHasPowerWords","titleHasNumber","hasContentAI"],"hasRedirection":true,"hasBreadcrumb":true},"homeUrl":"https:\/\/www.ezcalculatoronline.com","objectID":7322,"objectType":"post","locale":"en","localeFull":"en_US","overlayImages":{"play":{"name":"Play icon","url":"https:\/\/www.ezcalculatoronline.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-play.png","path":"\/home\/dh_7btfqe\/ezcalculatoronline.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-play.png","position":"middle_center"},"gif":{"name":"GIF icon","url":"https:\/\/www.ezcalculatoronline.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-gif.png","path":"\/home\/dh_7btfqe\/ezcalculatoronline.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-gif.png","position":"middle_center"}},"defautOgImage":"https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/11\/EZCALCULATORONLINE-LOGO-2.png","customPermalinks":true,"isUserRegistered":false,"autoSuggestKeywords":false,"connectSiteUrl":"https:\/\/rankmath.com\/auth?site=https%3A%2F%2Fwww.ezcalculatoronline.com&r=https%3A%2F%2Fwww.ezcalculatoronline.com%2Fsk%2Fwp-json%2Fwp%2Fv2%2Fpages%2F7322%3Fnonce%3Def66145470","maxTags":5,"trendsIcon":"<svg viewBox=\"0 0 610 610\"><path d=\"M18.85,446,174.32,290.48l58.08,58.08L76.93,504a14.54,14.54,0,0,1-20.55,0L18.83,466.48a14.54,14.54,0,0,1,0-20.55Z\" style=\"fill:#4285f4\"\/><path d=\"M242.65,242.66,377.59,377.6l-47.75,47.75a14.54,14.54,0,0,1-20.55,0L174.37,290.43l47.75-47.75A14.52,14.52,0,0,1,242.65,242.66Z\" style=\"fill:#ea4335\"\/><polygon points=\"319.53 319.53 479.26 159.8 537.34 217.88 377.61 377.62 319.53 319.53\" style=\"fill:#fabb05\"\/><path d=\"M594.26,262.73V118.61h0a16.94,16.94,0,0,0-16.94-16.94H433.2a16.94,16.94,0,0,0-12,28.92L565.34,274.71h0a16.94,16.94,0,0,0,28.92-12Z\" style=\"fill:#34a853\"\/><rect width=\"610\" height=\"610\" style=\"fill:none\"\/><\/svg>","showScore":true,"siteFavIcon":"https:\/\/www.ezcalculatoronline.com\/wp-content\/uploads\/2025\/05\/cropped-ezcaculator-32x32.webp","canUser":{"general":false,"advanced":false,"snippet":false,"social":false,"analysis":false,"analytics":false,"content_ai":false},"showKeywordIntent":true,"isPro":false,"is_front_page":false,"trendsUpgradeLink":"https:\/\/rankmath.com\/pricing\/?utm_source=Plugin&utm_medium=CE%20General%20Tab%20Trends&utm_campaign=WP","trendsUpgradeLabel":"Upgrade","trendsPreviewImage":"https:\/\/www.ezcalculatoronline.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/trends-preview.jpg","currentEditor":false,"homepageData":{"assessor":{"powerWords":["a cut above","absolute","absolutely","absolutely lowest","absurd","abuse","accurate","accuse","achieve","actionable","adaptable","adequate","admit","adorable","advantage","advice","affordable","aggravate","aggressive","agitated","agonizing","agony","alarmed","alarming","alienated","aligned","alive","all-inclusive","alluring","always","amazing","amp","animated","annihilate","announcing","anonymous","antagonistic","anxious","apocalypse","appalled","approved","approving","argumentative","armageddon","arrogant","ass kicking","assault","assured","astonishing","astounded","astounding","at ease","atrocious","attack","attractive","audacity","authentic","authoritative","authority","avoid","aware","awe-inspiring","awesome","awkward","backbone","backdoor","backed","backlash","backstabbing","badass","balanced","banned","bargain","barrage","basic","battle","beaming","beat down","beating","beautiful","beauty","begging","behind the scenes","belief","belong","best","best-selling","better","beware","big","billion","black market","blacklisted","blast","blessed","blinded","blissful","blood","bloodbath","bloodcurdling","bloody","blunder","blushing","bold","bomb","bona","bona fide","bonanza","bonus","bootleg","bottom line","bountiful","brave","bravery","brazen","break","breaking","breakthrough","breathtaking","bright","brilliant","broke","brutal","budget","buffoon","bullshit","bully","bumbling","buy","cadaver","calm","cancel anytime","capable","captivate","captivating","carefree","case study","cash","cataclysmic","catapult","catastrophe","caution","censored","centered","certain","certainly","certified","challenge","charming","cheap","cheat","cheat-sheet","cheer","cheerful","child-like","clarity","classified","clear","clueless","collapse","colorful","colossal","comfortable","compare","competitive","complete","completely","completeness","comprehensive","compromise","compulsive","concealed","conclusive","condemning","condescending","confess","confession","confessions","confident","confidential","conquer","conscientious","constructive","content","contrary","controlling","controversial","convenient","convert","cool","cooperative","copy","corpse","corrupt","corrupting","courage","courageous","cover-up","covert","coward","cowardly","crammed","crave","crazy","create","creative","cringeworthy","cripple","crisis","critical","crooked","crush","crushing","damaging","danger","dangerous","daring","dazzling","dead","deadline","deadly","death","decadent","deceived","deceptive","deep","defiance","definitely","definitive","defying","dejected","delicious","delight","delighted","delightful","delirious","delivered","demoralizing","deplorable","depraved","desire","desperate","despicable","destiny","destroy","detailed","devastating","devoted","diagnosed","direct","dirty","disadvantages","disastrous","discount","discover","disdainful","disempowered","disgusted","disgusting","dishonest","disillusioned","disoriented","distracted","distraught","distressed","distrustful","divulge","document","dollar","dominate","doomed","double","doubtful","download","dreadful","dreamy","drive","drowning","dumb","dynamic","eager","earnest","easily","easy","economical","ecstatic","edge","effective","efficient","effortless","elated","eliminate","elite","embarrass","embarrassed","embarrassing","emergency","emerging","emphasize","empowered","enchant","encouraged","endorsed","energetic","energy","enormous","enraged","enthusiastic","envy","epic","epidemic","essential","ethical","euphoric","evil","exactly","exasperated","excellent","excited","excitement","exciting","exclusive","exclusivity","excruciating","exhilarated","expensive","expert","explode","exploit","explosive","exposed","exquisite","extra","extraordinary","extremely","exuberant","eye-opening","fail","fail-proof","failure","faith","famous","fantasy","fascinating","fatigued","faux","faux pas","fearless","feast","feeble","festive","fide","fierce","fight","final","fine","fired","first","first ever","flirt","fluid","focus","focused","fool","fooled","foolish","forbidden","force-fed","forever","forgiving","forgotten","formula","fortune","foul","frantic","free","freebie","freedom","frenzied","frenzy","frightening","frisky","frugal","frustrated","fulfill","fulfilled","full","fully","fun","fun-loving","fundamentals","funniest","funny","furious","gambling","gargantuan","genius","genuine","gift","gigantic","giveaway","glamorous","gleeful","glorious","glowing","goddamn","gorgeous","graceful","grateful","gratified","gravity","great","greatest","greatness","greed","greedy","gripping","grit","grounded","growth","guaranteed","guilt","guilt-free","gullible","guts","hack","happiness","happy","harmful","harsh","hate","have you heard","havoc","hazardous","healthy","heart","heartbreaking","heartwarming","heavenly","hell","helpful","helplessness","hero","hesitant","hidden","high tech","highest","highly effective","hilarious","hoak","hoax","honest","honored","hope","hopeful","horribly","horrific","horrifying","horror","hostile","how to","huge","humility","humor","hurricane","hurry","hypnotic","idiot","ignite","illegal","illusive","imagination","immediately","imminently","impatience","impatient","impenetrable","important","impressive","improved","in the zone","incapable","incapacitated","incompetent","inconsiderate","increase","incredible","indecisive","indulgence","indulgent","inexpensive","inferior","informative","infuriated","ingredients","innocent","innovative","insane","insecure","insider","insidious","inspired","inspiring","instant savings","instantly","instructive","insult","intel","intelligent","intense","interesting","intriguing","introducing","invasion","investment","iron-clad","ironclad","irresistible","irs","is here","jackpot","jail","jaw-dropping","jealous","jeopardy","jittery","jovial","joyous","jubilant","judgmental","jumpstart","just arrived","keen","kickass","kickstart","kill","killed","killing","kills","know it all","lame","largest","lascivious","last","last chance","last minute","latest","laugh","laughing","launch","launching","lavishly","lawsuit","lazy","left behind","legendary","legitimate","liberal","liberated","lick","lies","life-changing","lifetime","light","lighthearted","likely","limited","literally","little-known","loathsome","lonely","looming","loser","lost","love","lucrative","lunatic","lurking","lust","luxurious","luxury","lying","magic","magical","magnificent","mainstream","malicious","mammoth","manipulative","marked down","massive","master","masterclass","maul","mediocre","meditative","meltdown","memorability","memorable","menacing","mesmerizing","meticulous","mind-blowing","minimalist","miracle","mired","mischievous","misgiving","missing out","mistake","monetize","money","moneyback","moneygrubbing","monumental","most important","motivated","mouth-watering","murder","mystery","nail","naked","natural","naughty","nazi","nest egg","never","new","nightmare","no good","no obligation","no one talks about","no questions asked","no risk","no strings attached","non-controlling","noted","novelty","now","obnoxious","obsessed","obsession","obvious","odd","off-kilter","off-limits","off-the record","offensive","official","okay","on-demand","open-minded","opportunities","optimistic","ordeal","outlawed","outrageousness","outstanding","overcome","overjoyed","overnight","overwhelmed","packed","painful","painless","painstaking","pale","panic","panicked","paralyzed","pas","passionate","pathetic","pay zero","payback","perfect","peril","perplexed","perspective","pessimistic","pioneering","piranha","pitfall","pitiful","placid","plague","played","playful","pleased","pluck","plummet","plunge","poison","poisonous","polarizing","poor","popular","portfolio","pound","powerful","powerless","practical","preposterous","prestige","price","priceless","pride","prison","privacy","private","privileged","prize","problem","productive","professional","profit","profitable","profound","promiscuous","promising","promote","protect","protected","proven","provocative","provoke","psychological","pummel","punch","punish","pus","quadruple","quality","quarrelsome","quick","quick-start","quickly","quiet","radiant","rare","ravenous","rebellious","recession-proof","reckoning","recognized","recommend","recreate","reduced","reflective","refugee","refund","refundable","reject","relaxed","release","relentless","reliable","remarkable","replicate","report","reprimanding","repulsed","repulsive","research","resentful","resourceful","responsible","responsive","rested","restricted","results","retaliating","reveal","revealing","revenge","revengeful","revisited","revolting","revolutionary","reward","rich","ridiculous","risky","riveting","rookie","rowdy","ruin","rules","ruthless","sabotaging","sacred","sadistic","sadly","sadness","safe","safety","sale","sampler","sarcastic","satisfied","savage","savagery","save","savings","savvy","scam","scandal","scandalous","scarce","scared","scary","scornful","scream","searing","secret","secret agenda","secret plot","secrets","secure","security","seductive","seething","seize","selected","self-hating","self-sufficient","sensational","senseless","sensual","serene","seriously","severe","sex","sexy","shaking","shameful","shameless","shaming","shatter","shellacking","shocking","should","shrewd","sick and tired","signs","silly","simple","simplicity","simplified","simplistic","sincere","sinful","sins","six-figure","sizable","sizzle","sizzled","sizzles","sizzling","sizzlingly","skill","skyrocket","slaughter","slave","sleazy","sleeping","sly","smash","smiling","smug","smuggle","smuggled","sneak-peek","sneaky","sniveling","snob","snooty","snotty","soar","soaring","solid","solution","spank","special","spectacular","speedy","spell-binding","spine","spirit","spirited","spiteful","spoiler","spontaneous","spotlight","spunky","squirming","stable","staggering","startling","steady","steal","stealthy","steamy","step-by-step","still","stoic","stop","strange","strangle","strategy","stressed","strong","strongly suggest","struggle","stuck up","studies","stunning","stupid","stupid-simple","sturdy","sublime","succeed","success","successful","suck","suddenly","suffer","sunny","super","super-human","superb","supercharge","superior","supported","supportive","sure","sure fire","surefire","surge","surging","surprise","surprised","surprising","survival","survive","suspicious","sweaty","swoon","swoon-worthy","tailspin","tank","tantalizing","targeted","tawdry","tease","technology","teetering","tempting","tenacious","tense","terrible","terrific","terrified","terrifying","terror","terrorist","tested","thankful","the truth","threaten","threatened","thrilled","thrilling","thug","ticked off","tickled","timely","today","torture","toxic","track record","trade secret","tragedy","tragic","transform","transparency","trap","trapped","trauma","traumatized","treacherous","treasure","tremendous","trend","tricks","triggers","triple","triumph","truly","trusting","trustworthy","truth","truthful","turbo-charge","turbocharges","tweaks","twitching","ultimate","unadulterated","unassuming","unauthorized","unbelievable","unburdened","uncaring","uncensored","uncertain","uncomfortable","unconditional","uncontrollable","unconventional","uncovered","undeniable","under priced","undercover","underground","underhanded","underused","unexpected","unforgettable","unheard of","unhurried","uninterested","unique","unjustified","unknowingly","unleashed","unlimited","unlock","unparalleled","unpopular","unreliable","unresponsive","unseen","unstable","unstoppable","unsure","unsurpassed","untapped","unusual","up-sell","upbeat","uplifted","uplifting","urge","urgent","useful","useless","validate","valor","valuable","value","vanquish","vaporize","venomous","verify","vibrant","vicious","victim","victory","vigorous","vilified","vindictive","violated","violent","volatile","vulnerable","waiting","wanted","wanton","warning","waste","weak","wealth","weird","what no one tells you","whip","whopping","wicked","wild","willpower","withheld","wonderful","wondrous","woozy","world","worry","worst","worthwhile","wounded","wreaking","youthful","zen","zinger"],"diacritics":true,"researchesTests":["contentHasTOC","contentHasShortParagraphs","contentHasAssets","keywordInTitle","keywordInMetaDescription","keywordInPermalink","keywordIn10Percent","keywordInContent","keywordInSubheadings","keywordInImageAlt","keywordDensity","keywordNotUsed","lengthContent","lengthPermalink","linksHasInternal","linksHasExternals","linksNotAllExternals","titleStartWithKeyword","titleSentiment","titleHasPowerWords","titleHasNumber","hasContentAI"],"hasBreadcrumb":true,"serpData":{"title":"%sitename% %sep% %sitedesc%","description":"%sitedesc%","titleTemplate":"%sitename% %page% %sep% %sitedesc%","descriptionTemplate":"","focusKeywords":"","breadcrumbTitle":"Home","robots":{"index":true},"advancedRobots":{"max-snippet":"-1","max-video-preview":"-1","max-image-preview":"large"},"facebookTitle":"","facebookDescription":"","facebookImage":"","facebookImageID":""}}},"tocTitle":"Table of Contents","tocExcludeHeadings":[],"listStyle":"ul"},"_links":{"self":[{"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/pages\/7322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/comments?post=7322"}],"version-history":[{"count":11,"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/pages\/7322\/revisions"}],"predecessor-version":[{"id":10711,"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/pages\/7322\/revisions\/10711"}],"up":[{"embeddable":true,"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/pages\/4298"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/media\/7356"}],"wp:attachment":[{"href":"https:\/\/www.ezcalculatoronline.com\/wp-json\/wp\/v2\/media?parent=7322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}