{"id":61,"date":"2021-12-28T16:16:28","date_gmt":"2021-12-28T16:16:28","guid":{"rendered":"http:\/\/www.wbg.ee\/landingpage\/"},"modified":"2026-10-26T12:25:06","modified_gmt":"2026-10-26T10:25:06","slug":"avaleht","status":"publish","type":"page","link":"https:\/\/www.wbg.ee\/en\/","title":{"rendered":"Home"},"content":{"rendered":"\n<div class=\"ngg-x ngg-home\">\n<style>\n.ngg-home .ngg-x__in{max-width:1320px}\n@media(min-width:768px){.ngg-home .ngg-x__in{padding-left:max(12px,min(max(16px,5vw),calc(64px - (100vw - 1320px) \/ 2)));padding-right:max(12px,min(max(16px,5vw),calc(64px - (100vw - 1320px) \/ 2)))}}\n.ngg-home .ngg-in .ngg-x__in{padding-bottom:clamp(72px,8vw,120px)!important}\n#colophon{padding-bottom:96px!important}\n.ngg-home .ngg-in{min-height:clamp(620px,94vh,920px)}\n.ngg-home .ngg-in::before{background:linear-gradient(180deg,rgba(11,29,58,.35) 0%,rgba(11,29,58,0) 28%,rgba(11,29,58,.2) 55%,rgba(11,29,58,.88) 100%),linear-gradient(90deg,rgba(11,29,58,.6) 0%,rgba(11,29,58,.15) 60%,rgba(11,29,58,0) 100%)}\n.ngg-in__bgs{position:absolute;inset:0;z-index:-2;overflow:hidden;background:var(--n)}\n.ngg-in__bg{position:absolute;inset:0;width:100%!important;height:100%!important;max-width:none!important;object-fit:cover;opacity:0;transform:scale(1.05);transition:opacity .8s ease,transform 9s ease-out}\n.ngg-in__bg.is-on{opacity:1;transform:scale(1)}\n@media(min-width:900px){.ngg-in__bg[data-k=start],.ngg-in__bg[data-k=group]{left:36%!important;width:64%!important;-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 24%);mask-image:linear-gradient(90deg,transparent 0,#000 24%)}}\n.ngg-in__bg[data-k=start]{object-position:45% 28%}\n.ngg-in__bg[data-k=group]{object-position:55% 30%}\n.ngg-home .ngg-in .ngg-x-hero__t{font-size:clamp(46px,7.6vw,112px);max-width:12ch;margin-bottom:22px}\n.ngg-in__ask{display:block;margin:0 0 10px;font-size:12px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:#dbe5ee}\n.ngg-in__tabs{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 22px}\n.ngg-in__tab{appearance:none;-webkit-appearance:none;border:1.5px solid rgba(255,255,255,.5);background:rgba(11,29,58,.28);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#fff;border-radius:999px;min-height:50px;padding:0 22px;font:700 15px\/1 \"Google Sans\",system-ui,sans-serif;letter-spacing:.01em;cursor:pointer;transition:background .2s ease,color .2s ease,transform .15s ease,border-color .2s ease}\n.ngg-in__tab:hover{transform:translateY(-1px);background:rgba(255,255,255,.2)}\n.ngg-in__tab[aria-selected=true]{background:#fff;color:var(--n);border-color:#fff}\n.ngg-in__tab:focus-visible,.ngg-in__chip:focus-visible,.ngg-home a:focus-visible{outline:3px solid var(--pk);outline-offset:3px}\n.ngg-in__panel{max-width:620px}\n.ngg-in__panel[hidden]{display:none}\n.ngg-in__panel.is-in{animation:nggUp .45s ease both}\n@keyframes nggUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}\n.ngg-in__panel .ngg-x-hero__lead{margin-bottom:22px!important}\n.ngg-in__today{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:34px;font-size:14px;color:#fff}\n.ngg-in__today>b{font-size:12px;letter-spacing:.14em;text-transform:uppercase;margin-right:4px}\n.ngg-in__today [data-today]{display:contents}\n.ngg-in__today [data-today] span,.ngg-in__chip{display:inline-flex;align-items:center;gap:6px;min-height:38px;padding:0 14px;border-radius:999px;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.26);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#fff!important;font:500 14px\/1 \"Google Sans\",system-ui,sans-serif;text-decoration:none!important}\n.ngg-in__today [data-today] i{font-style:normal;opacity:.75}\n.ngg-in__chip{cursor:pointer;appearance:none;-webkit-appearance:none}\n.ngg-in__chip:hover{background:rgba(255,255,255,.22)}\n.ngg-now__grid{display:grid;gap:14px;grid-template-columns:1fr}\n@media(min-width:760px){.ngg-now__grid{grid-template-columns:repeat(3,minmax(0,1fr))}}\n.ngg-now .ngg-x-card{display:flex;flex-direction:column;gap:10px;height:100%}\n.ngg-now .ngg-x-card h3{margin-top:6px!important}\n.ngg-now .ngg-x-card p{color:var(--i5);font-size:15px;line-height:1.5}\n.ngg-now .ngg-x-flag{align-self:flex-start}\n.ngg-now .ngg-x-flag--blue{background:var(--o);color:#fff}\n.ngg-duo__grid{display:grid;gap:16px;grid-template-columns:1fr}\n@media(min-width:860px){.ngg-duo__grid{grid-template-columns:1fr 1fr}}\n.ngg-duo__card{position:relative;isolation:isolate;overflow:hidden;border-radius:28px;min-height:clamp(440px,52vw,620px);display:flex;flex-direction:column;justify-content:flex-end;padding:clamp(22px,3vw,36px);color:#fff;background:var(--n)}\n.ngg-duo__card img{position:absolute;inset:0;z-index:-2;width:100%!important;height:100%!important;max-width:none!important;object-fit:cover;transition:transform .6s ease}\n.ngg-duo__card::before{content:\"\";position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg,rgba(11,29,58,0) 30%,rgba(11,29,58,.88) 100%)}\n.ngg-duo__card .ngg-x-btn{align-self:flex-start}\n@media(max-width:600px){.ngg-in__today [data-today] span:nth-child(n+2){display:none}}\n.ngg-duo__card:hover img{transform:scale(1.03)}\n.ngg-duo__card .ngg-x-k{color:#e6eef5!important}\n.ngg-duo__card h3.ngg-x-h3{font-size:clamp(28px,3.2vw,42px)!important;letter-spacing:-.03em!important;color:#fff!important;max-width:14ch}\n.ngg-duo__card p{color:#e8eef4;font-size:16px;line-height:1.5;max-width:44ch;margin:0 0 16px!important}\n.ngg-duo__chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 18px;padding:0;list-style:none}\n.ngg-duo__chips li{list-style:none;border-radius:999px;padding:7px 12px;font-size:13px;font-weight:700;background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.28)}\n.ngg-duo__card--rae .ngg-duo__chips li:first-child{background:#ffafea;color:var(--n);border-color:#ffafea}\n.ngg-duo__card--vg .ngg-duo__chips li:first-child{background:var(--pk);color:var(--n);border-color:var(--pk)}\n.ngg-duo__deal{margin-top:16px;display:grid;gap:16px;align-items:center;background:#fff;border:1px solid var(--h);border-radius:24px;padding:clamp(20px,3vw,32px)}\n@media(min-width:900px){.ngg-duo__deal{grid-template-columns:1.2fr 1.6fr auto}}\n.ngg-duo__deal h3{margin:0!important}\n.ngg-duo__prices{display:flex;flex-wrap:wrap;gap:8px 20px;margin:0;padding:0;list-style:none}\n.ngg-duo__prices li{list-style:none;font-size:15px;color:var(--i5)}\n.ngg-duo__prices b{font-family:\"Bricolage Grotesque\",system-ui,sans-serif;font-stretch:87.5%;font-size:26px;letter-spacing:-.03em;color:var(--n);margin-right:6px}\n.ngg-ev__grid{display:grid;gap:16px;grid-template-columns:1fr}\n@media(min-width:860px){.ngg-ev__grid{grid-template-columns:1fr 1fr}}\n.ngg-ev__card{display:flex;flex-direction:column;background:#fff;border:1px solid var(--h);border-radius:28px;overflow:hidden}\n.ngg-ev__card .ngg-x-photo{border-radius:0;aspect-ratio:16\/10}\n.ngg-ev__body{padding:clamp(20px,2.6vw,30px);display:flex;flex-direction:column;gap:10px;flex:1}\n.ngg-ev__body p{color:var(--i5);font-size:16px;line-height:1.5}\n.ngg-ev__hours{display:inline-flex;align-self:flex-start;border-radius:999px;padding:6px 12px;font-size:13px;font-weight:700;background:var(--s)}\n.ngg-ev__body .ngg-x-btns{margin-top:auto;padding-top:8px}\n.ngg-nl__grid{display:grid;gap:28px;align-items:center}\n@media(min-width:900px){.ngg-nl__grid{grid-template-columns:1fr 1fr;gap:56px}}\n.ngg-nl form{margin:0}\n.ngg-nl input[type=email],.ngg-nl input[type=text]{width:100%;min-height:56px;border-radius:999px!important;border:1.5px solid rgba(255,255,255,.4)!important;background:rgba(255,255,255,.08)!important;color:#fff!important;padding:0 22px!important;font:400 16px \"Google Sans\",system-ui,sans-serif!important;margin:0 0 10px!important;box-shadow:none!important}\n.ngg-nl input::placeholder{color:#cfd9e2}\n.ngg-nl input[type=submit],.ngg-nl button[type=submit]{min-height:56px;border-radius:999px!important;border:0!important;background:var(--c)!important;color:var(--n)!important;padding:0 28px!important;font:700 15px\/1 \"Google Sans\",system-ui,sans-serif!important;letter-spacing:.05em;text-transform:uppercase;cursor:pointer}\n.ngg-nl label{color:#dbe5ee}\n.ngg-nl .mc4wp-response{color:#fff}\n.ngg-sp__grid{display:grid;gap:12px;grid-template-columns:repeat(3,minmax(0,1fr));margin:0;padding:0;list-style:none}\n@media(min-width:700px){.ngg-sp__grid{grid-template-columns:repeat(5,minmax(0,1fr))}}\n@media(min-width:1100px){.ngg-sp__grid{grid-template-columns:repeat(7,minmax(0,1fr))}}\n.ngg-sp__grid li{list-style:none;display:flex;align-items:center;justify-content:center;background:#fff;border:1px solid var(--h);border-radius:16px;aspect-ratio:3\/2;padding:12px}\n.ngg-sp__grid img{max-width:100%;max-height:56px;width:auto;height:auto;object-fit:contain}\n@media(max-width:600px){.ngg-in__tab{padding:0 16px;font-size:14px;min-height:46px}.ngg-home .ngg-in .ngg-x-hero__t{font-size:clamp(42px,12vw,60px)}.ngg-in__today{margin-top:24px}}\n@media(prefers-reduced-motion:reduce){.ngg-in__bg,.ngg-duo__card img{transition:none!important;transform:none!important}.ngg-in__panel.is-in{animation:none}}\n.ngg-in__steps{list-style:none;margin:0 0 18px!important;padding:0!important;display:flex;flex-wrap:wrap;gap:8px;counter-reset:nggs}.ngg-in__steps li{list-style:none;counter-increment:nggs;display:inline-flex;align-items:center;gap:8px;margin:0!important;padding:6px 14px 6px 6px;border-radius:999px;background:rgba(11,29,58,.55);border:1px solid rgba(255,255,255,.3);color:#fff;font-size:14px;font-weight:700;line-height:1.2}.ngg-in__steps li::before{content:counter(nggs);display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;background:#aff4ed;color:#0b1d3a;font-size:12px;font-weight:800}\n<\/style>\n<section class=\"ngg-x-hero ngg-in\" id=\"Algus\" data-ngg=\"home_entry\" aria-label=\"Valgeranna Golf\">\n<div class=\"ngg-in__bgs\" aria-hidden=\"true\">\n<img class=\"ngg-in__bg is-on\" data-k=\"play\" src=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg\" srcset=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-1536x863.jpg 1536w, https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg 2048w\" sizes=\"100vw\" alt=\"\" fetchpriority=\"high\" decoding=\"async\">\n<img class=\"ngg-in__bg\" data-k=\"start\" data-src=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2025-golfisobrannad-01-1536x1025.jpg\" width=\"1536\" height=\"1025\" alt=\"\" decoding=\"async\">\n<img class=\"ngg-in__bg\" data-k=\"group\" data-src=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-sampanjagolf-seltskond-17-1536x1028.jpg\" width=\"1536\" height=\"1028\" alt=\"\" decoding=\"async\">\n<\/div>\n<div class=\"ngg-x__in\">\n<span class=\"ngg-x-pill ngg-x-pill--glass\">Valgeranna Golf \u00b7 P\u00e4rnu County<\/span>\n<h1 class=\"ngg-x-hero__t\">18 holes by the river.<\/h1>\n<span class=\"ngg-in__ask\" id=\"ngg-in-ask\">What would you like to do?<\/span>\n<div class=\"ngg-in__tabs\" role=\"tablist\" aria-labelledby=\"ngg-in-ask\">\n<button type=\"button\" class=\"ngg-in__tab\" role=\"tab\" id=\"ngg-t-play\" aria-controls=\"ngg-p-play\" aria-selected=\"true\" data-k=\"play\">I want to play<\/button>\n<button type=\"button\" class=\"ngg-in__tab\" role=\"tab\" id=\"ngg-t-start\" aria-controls=\"ngg-p-start\" aria-selected=\"false\" tabindex=\"-1\" data-k=\"start\">I want to start<\/button>\n<button type=\"button\" class=\"ngg-in__tab\" role=\"tab\" id=\"ngg-t-group\" aria-controls=\"ngg-p-group\" aria-selected=\"false\" tabindex=\"-1\" data-k=\"group\">Coming with a group<\/button>\n<\/div>\n<div class=\"ngg-in__panel\" role=\"tabpanel\" id=\"ngg-p-play\" aria-labelledby=\"ngg-t-play\">\n<p class=\"ngg-x-hero__lead\">Ponds, mounds and a long round in nature. The course, driving range and practice areas are open \u2013 tee times daily 10:30\u201315:30. With a playing right, you play as much as you like at both Valgeranna and Rae.<\/p>\n<div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--main\" href=\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget&amp;source=club\" target=\"_blank\" rel=\"noopener\" data-ngg-cta=\"book\">Book a tee time<\/a><a class=\"ngg-x-btn ngg-x-btn--light\" href=\"https:\/\/www.wbg.ee\/en\/prices\/#playing-rights\" data-ngg-cta=\"offer_view\" data-ngg-val=\"manguoigus_2027\">Playing right 2027<\/a><\/div>\n<\/div>\n<div class=\"ngg-in__panel\" role=\"tabpanel\" id=\"ngg-p-start\" aria-labelledby=\"ngg-t-start\" hidden>\n<p class=\"ngg-x-hero__lead\">This year&#8217;s Green Card courses are over. People who register their interest hear about the 2027 courses first. You need no equipment or experience.<\/p>\n<ol class=\"ngg-in__steps\" aria-label=\"Your path into golf\"><li>Try golf<\/li><li>Take the Green Card course<\/li><li>Start playing<\/li><\/ol>\n<div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--main\" href=\"https:\/\/www.wbg.ee\/en\/for-beginners\/#Huvi\" data-ngg-cta=\"interest\">Register interest<\/a><a class=\"ngg-x-btn ngg-x-btn--light\" href=\"https:\/\/www.wbg.ee\/en\/for-beginners\/#Teekond\" data-ngg-cta=\"journey\">See the path<\/a><\/div>\n<\/div>\n<div class=\"ngg-in__panel\" role=\"tabpanel\" id=\"ngg-p-group\" aria-labelledby=\"ngg-t-group\" hidden>\n<p class=\"ngg-x-hero__lead\">A golf day with friends, colleagues or family. Golf, food in the clubhouse restaurant or on the terrace, and rooms. We plan the day together with you.<\/p>\n<div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--main\" href=\"https:\/\/www.wbg.ee\/en\/events\/\" data-ngg-cta=\"inquiry_view\">Request an offer<\/a><a class=\"ngg-x-btn ngg-x-btn--light\" href=\"https:\/\/www.wbg.ee\/en\/restaurant-white-beach-golf\/\" data-ngg-cta=\"restaurant\">Restaurant<\/a><\/div>\n<\/div>\n<div class=\"ngg-in__today\"><b>Today at Valgeranna<\/b><span data-today><button type=\"button\" class=\"ngg-in__chip\" data-bs-toggle=\"modal\" data-bs-target=\"#infoModal\" data-ngg-cta=\"info\">Opening hours<\/button><\/span><a class=\"ngg-in__chip\" href=\"#tana\" data-ngg-cta=\"today_more\">Times and prices<\/a><a class=\"ngg-in__chip\" href=\"#ngg-lv\" data-ngg-cta=\"weather\">Weather<\/a><button type=\"button\" class=\"ngg-in__chip\" data-bs-toggle=\"modal\" data-bs-target=\"#golfboxModal\" data-ngg-cta=\"golfbox\">GolfBox<\/button><\/div>\n<\/div>\n<\/section>\n<\/div>\n\n\n\n<style id=\"ngg-ss-css\">\n#ngg-ss{position:relative;z-index:6;display:flex;gap:18px;align-items:stretch;margin:0 0 22px;padding:16px;max-width:700px;border-radius:22px;background:rgba(11,29,58,.93);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);color:#fff;box-shadow:0 18px 40px rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.14);text-align:left;font-family:inherit;line-height:1.45}\n#ngg-ss *,#ngg-pt *{box-sizing:border-box}\n@media (min-width:900px){#ngg-ss{width:700px;max-width:calc(100vw - 200px)}}\n#ngg-ss .ngg-ss__g{position:relative;flex:0 0 132px;min-height:150px;border-radius:16px;overflow:hidden;cursor:pointer;border:0;padding:0;background:repeating-linear-gradient(135deg,#2f7d3f 0 14px,#378a48 14px 28px);color:#fff;font:inherit;text-align:center}\n#ngg-ss .ngg-ss__g:focus-visible{outline:3px solid #ffafea;outline-offset:2px}\n#ngg-ss .ngg-ss__hole{position:absolute;left:50%;top:38%;width:22px;height:12px;margin-left:-11px;border-radius:50%;background:#0d1f12;box-shadow:inset 0 3px 4px rgba(0,0,0,.6)}\n#ngg-ss .ngg-ss__pole{position:absolute;left:50%;top:calc(38% - 48px);width:2px;height:54px;background:#fff;border-radius:2px}\n#ngg-ss .ngg-ss__flag{position:absolute;left:calc(50% + 2px);top:calc(38% - 48px);width:26px;height:17px;background:#f39595;clip-path:polygon(0 0,100% 50%,0 100%);transform-origin:0 50%;animation:nggFlag 1.6s ease-in-out infinite}\n#ngg-ss .ngg-ss__ball{position:absolute;left:50%;bottom:30px;width:12px;height:12px;margin-left:-6px;border-radius:50%;background:#fff;box-shadow:0 2px 3px rgba(0,0,0,.35);animation:nggRoll 2.8s cubic-bezier(.2,.7,.3,1) infinite}\n#ngg-ss .ngg-ss__gl{position:absolute;left:0;right:0;bottom:8px;font-size:10.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase}\n@keyframes nggFlag{0%,100%{transform:scaleX(1) skewY(0)}50%{transform:scaleX(.82) skewY(6deg)}}\n@keyframes nggRoll{0%{transform:translateY(0) scale(1);opacity:1}55%{transform:translateY(-66px) scale(.9);opacity:1}70%{transform:translateY(-70px) scale(.4);opacity:0}100%{transform:translateY(0);opacity:0}}\n#ngg-ss .ngg-ss__b{flex:1 1 auto;min-width:0}\n#ngg-ss .ngg-ss__k{display:inline-block;font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:#ffafea;margin:0 0 6px}\n#ngg-ss .ngg-ss__t{display:block;font-size:23px;line-height:1.15;font-weight:800;letter-spacing:-.01em;margin:0 0 6px;color:#fff}\n#ngg-ss .ngg-ss__p{margin:0 0 10px;font-size:14.5px;color:rgba(255,255,255,.86)}\n#ngg-ss .ngg-ss__c{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 14px;padding:0;list-style:none}\n#ngg-ss .ngg-ss__c li{display:inline-flex;align-items:center;gap:7px;margin:0;padding:4px 10px;border-radius:999px;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.16);font-size:12.5px;font-weight:600;color:#fff}\n#ngg-ss .ngg-ss__c li:before{content:\"\";width:8px;height:8px;border-radius:50%;background:#f39595;flex:0 0 auto}\n#ngg-ss .ngg-ss__c li.is-on:before{background:#3ddc84;box-shadow:0 0 0 3px rgba(61,220,132,.25)}\n#ngg-ss .ngg-ss__f{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px}\n#ngg-ss .ngg-ss__a,#ngg-pt .ngg-pt__a{display:inline-flex;align-items:center;gap:8px;padding:11px 18px;border-radius:999px;background:#f39595;color:#0b1d3a!important;font-weight:800;font-size:13px;letter-spacing:.04em;text-transform:uppercase;text-decoration:none!important;border:0;cursor:pointer;font-family:inherit;transition:transform .15s ease}\n#ngg-ss .ngg-ss__a:hover,#ngg-pt .ngg-pt__a:hover{transform:translateY(-1px)}\n#ngg-ss .ngg-ss__a2,#ngg-pt .ngg-pt__a2{display:inline-flex;align-items:center;padding:10px 16px;border-radius:999px;background:transparent;color:#fff!important;border:1px solid rgba(255,255,255,.4);font-weight:800;font-size:12.5px;letter-spacing:.04em;text-transform:uppercase;text-decoration:none!important;cursor:pointer;font-family:inherit}\n@media (max-width:600px){#ngg-ss{flex-direction:column;gap:12px;padding:12px;border-radius:18px}#ngg-ss .ngg-ss__g{flex:0 0 auto;min-height:96px}#ngg-ss .ngg-ss__hole{top:52%}#ngg-ss .ngg-ss__pole,#ngg-ss .ngg-ss__flag{top:calc(52% - 48px)}#ngg-ss .ngg-ss__ball{display:none}#ngg-ss .ngg-ss__t{font-size:20px}}\n#ngg-pt{position:fixed;inset:0;z-index:2147483000;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(6,14,30,.78);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);font-family:inherit;color:#fff;opacity:0;transition:opacity .2s ease}\n#ngg-pt.is-in{opacity:1}\n#ngg-pt .ngg-pt__box{position:relative;width:100%;max-width:760px;max-height:100%;overflow:auto;border-radius:24px;background:#0b1d3a;box-shadow:0 30px 80px rgba(0,0,0,.5);padding:20px}\n#ngg-pt .ngg-pt__x{position:absolute;top:12px;right:12px;width:40px;height:40px;border-radius:50%;border:0;background:rgba(255,255,255,.12);color:#fff;font-size:22px;line-height:40px;cursor:pointer;z-index:3}\n#ngg-pt .ngg-pt__k{display:block;font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:#ffafea;margin:0 0 4px}\n#ngg-pt .ngg-pt__t{display:block;font-size:26px;line-height:1.15;font-weight:800;margin:0 48px 4px 0;color:#fff}\n#ngg-pt .ngg-pt__h{margin:0 0 12px;font-size:14px;color:rgba(255,255,255,.75)}\n#ngg-pt .ngg-pt__st{display:flex;justify-content:space-between;align-items:center;margin:0 0 8px;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.7)}\n#ngg-pt canvas.ngg-pt__cv{display:block;width:100%;border-radius:18px;touch-action:none;cursor:crosshair;background:#2f7d3f}\n#ngg-pt .ngg-pt__fx{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:2}\n#ngg-pt .ngg-pt__win{display:none;text-align:center;padding:18px 6px 4px}\n#ngg-pt.is-won .ngg-pt__win{display:block;animation:nggUp .5s ease both}\n#ngg-pt .ngg-pt__wt{display:block;font-size:30px;line-height:1.1;font-weight:800;margin:0 0 8px;color:#fff}\n#ngg-pt .ngg-pt__wp{max-width:560px;margin:0 auto 16px;font-size:15.5px;color:rgba(255,255,255,.88)}\n#ngg-pt .ngg-pt__wf{display:flex;flex-wrap:wrap;justify-content:center;gap:10px}\n#ngg-pt.is-won .ngg-pt__skip{display:none}\n#ngg-pt .ngg-pt__skip{background:none;border:0;color:rgba(255,255,255,.6);font:inherit;font-size:12.5px;text-decoration:underline;cursor:pointer;padding:6px 0 0}\n@keyframes nggUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}\n@media (max-width:600px){#ngg-pt{padding:8px}#ngg-pt .ngg-pt__box{padding:14px;border-radius:18px}#ngg-pt .ngg-pt__t{font-size:21px}#ngg-pt .ngg-pt__wt{font-size:24px}}\n@media (prefers-reduced-motion:reduce){#ngg-ss .ngg-ss__ball,#ngg-ss .ngg-ss__flag{animation:none}}\n<\/style>\n<script id=\"ngg-ss-js\">\n(function(){\nvar H=(location.hostname||'').replace(\/^www\\.\/,'');\nvar SITE=\/wbg\\.ee$\/.test(H)?'wbg':(\/raegolf\\.ee$\/.test(H)?'rae':'');\nif(!SITE){return;}\nvar RAE=(SITE==='rae');\nvar EN=\/^en\/i.test(document.documentElement.lang||'');\nvar NAME=RAE?'Rae Golf':'Valgeranna Golf';\nvar PLAY=RAE?(EN?'https:\/\/raegolf.ee\/en\/price-list\/#manguoigused':'https:\/\/raegolf.ee\/hinnakiri\/#manguoigused'):(EN?'https:\/\/www.wbg.ee\/en\/prices\/#playing-rights':'https:\/\/www.wbg.ee\/hinnakiri\/#manguoigused');\nvar L=EN?{\n k:RAE?'Season 2026 is over':'The course is open',\n t:RAE?'Thank you for a wonderful season!':'Tee times 10:30\u201315:30',\n p:RAE?'From 19 October both Nordic Golf Group courses \u2013 Rae and Valgeranna \u2013 are closed daily. In good weather we may open on weekends \u2013 we will announce it separately.':'The Valgeranna course, driving range and practice areas are open. Tee times daily 10:30\u201315:30. Caddiemaster and pro shop Mon\u2013Sun 10:00\u201313:00, restaurant Mon\u2013Fri 11:00\u201314:00.',\n chips:RAE?[['Main course closed',0],['Fortal academy course closed',0],['TrackMan range open',1],['Restaurant closed',0],['Caddiemaster closed',0]]:[['Course open \u00b7 tee times 10:30\u201315:30',1],['Range & practice areas open',1],['Caddiemaster & pro shop Mon\u2013Sun 10\u201313',1],['Restaurant Mon\u2013Fri 11\u201314',1]],\n putt:'Hit the last putt of the season',gl:'Last putt',play27:'Playing right 2027',\n mk:'Season 2026 \u00b7 the last hole',mt:'Hit the last putt of the season',mh:'Drag back from the ball (finger or mouse), aim and let go. Mind the break!',\n strokes:'Strokes',brk:'Break',skip:'Skip the game',close:'Close',again:'Putt again',share:'Share',\n w1:'Hole in one!',w2:'Two putts \u2013 a solid par!',wn:function(n){return n+' strokes \u2013 in is in!';},\n wp:'Thank you for being with us this season \u2013 every round, every competition and every early tee time made it special. The courses are going to sleep for the winter. See you in spring!',\n shareT:function(n){return 'I sank the last putt of the 2026 season at '+NAME+' in '+n+(n===1?' stroke':' strokes')+'!';},\n closed:'closed',open:'open',Closed:'Closed',\n notice:RAE?'From 19 October the course is closed daily. The range is open, the restaurant and caddiemaster are closed. In good weather we may open the course on weekends.':'The course, driving range and practice areas are open. Tee times 10:30\u201315:30. Caddiemaster and pro shop Mon\u2013Sun 10:00\u201313:00, restaurant Mon\u2013Fri 11:00\u201314:00.'\n}:{\n k:RAE?'Hooaeg 2026 on l\u00e4bi':'V\u00e4ljak on avatud',\n t:RAE?'Ait\u00e4h imelise hooaja eest!':'Tiiajad 10:30\u201315:30',\n p:RAE?'Alates 19. oktoobrist on m\u00f5lemad Nordic Golf Groupi v\u00e4ljakud \u2013 Rae ja Valgeranna \u2013 igap\u00e4evaselt suletud. Ilusate ilmade korral v\u00f5ime n\u00e4dalavahetuseti avada \u2013 anname sellest eraldi teada.':'Valgeranna v\u00e4ljak, driving range ja harjutusalad on avatud. Tiiajad iga p\u00e4ev 10:30\u201315:30. Caddiemaster ja pro shop E\u2013P 10:00\u201313:00, restoran E\u2013R 11:00\u201314:00.',\n chips:RAE?[['Peav\u00e4ljak suletud',0],['Fortal akadeemiav\u00e4ljak suletud',0],['TrackMan range avatud',1],['Restoran suletud',0],['Caddiemaster suletud',0]]:[['V\u00e4ljak avatud \u00b7 tiiajad 10:30\u201315:30',1],['Range ja harjutusalad avatud',1],['Caddiemaster ja pro shop E\u2013P 10\u201313',1],['Restoran E\u2013R 11\u201314',1]],\n putt:'L\u00f6\u00f6 hooaja viimane putt',gl:'Viimane putt',play27:'M\u00e4ngu\u00f5igus 2027',\n mk:'Hooaeg 2026 \u00b7 viimane auk',mt:'L\u00f6\u00f6 hooaja viimane putt',mh:'T\u00f5mba s\u00f5rme v\u00f5i hiirega pallist eemale, sihi ja lase lahti. Arvesta kallet!',\n strokes:'L\u00f6\u00f6ke',brk:'Kalle',skip:'J\u00e4ta m\u00e4ng vahele',close:'Sulge',again:'L\u00f6\u00f6 uuesti',share:'Jaga',\n w1:'Auk \u00fche l\u00f6\u00f6giga!',w2:'Kaks putti \u2013 kindel par!',wn:function(n){return n+' l\u00f6\u00f6ki \u2013 peaasi, et sees!';},\n wp:'Ait\u00e4h, et olid sel hooajal meiega \u2013 iga ring, iga v\u00f5istlus ja iga varahommikune stardiaeg tegi selle hooaja eriliseks. V\u00e4ljakud j\u00e4\u00e4vad n\u00fc\u00fcd talveunne. Kohtume kevadel!',\n shareT:function(n){return 'L\u00f5in '+NAME+'is hooaja 2026 viimase puti sisse '+n+(n===1?' l\u00f6\u00f6giga':' l\u00f6\u00f6giga')+'!';},\n closed:'suletud',open:'avatud',Closed:'Suletud',\n notice:RAE?'Alates 19. oktoobrist on v\u00e4ljak igap\u00e4evaselt suletud. Range on avatud, restoran ja caddiemaster on suletud. Ilusate ilmade korral v\u00f5ime v\u00e4ljaku n\u00e4dalavahetuseti avada.':'V\u00e4ljak, driving range ja harjutusalad on avatud. Tiiajad 10:30\u201315:30. Caddiemaster ja pro shop E\u2013P 10:00\u201313:00, restoran E\u2013R 11:00\u201314:00.'\n};\nfunction esc(s){return String(s).replace(\/[<>&\"]\/g,function(c){return {'<':'&lt;','>':'&gt;','&':'&amp;','\"':'&quot;'}[c];});}\nfunction track(ev){try{if(window.dataLayer){window.dataLayer.push({event:ev,ngg_site:SITE});}}catch(e){}}\n\n\/* ---------- 1. Banner ---------- *\/\nvar PAY='https:\/\/payment.lhv.ee\/lp\/u6ucgrmvx5';L.pay=EN?'Pay green fee 29 \u20ac':'Maksa green fee 29 \u20ac';\nfunction banner(){\n if(document.getElementById('ngg-ss')){return;}\n var host=document.querySelector('.ngg-bh__card')||document.querySelector('.ngg-x-hero');if(!host){return;}\n var tgt=host.querySelector('.ngg-bh__in, .ngg-x__in')||host;\n var el=document.createElement('div');el.id='ngg-ss';el.setAttribute('role','region');el.setAttribute('aria-label',L.t);\n var chips='';L.chips.forEach(function(c){chips+='<li'+(c[1]?' class=\"is-on\"':'')+'>'+esc(c[0])+'<\/li>';});\n el.innerHTML='<button type=\"button\" class=\"ngg-ss__g\" data-ngg-putt aria-label=\"'+esc(L.putt)+'\"><span class=\"ngg-ss__pole\"><\/span><span class=\"ngg-ss__flag\"><\/span><span class=\"ngg-ss__hole\"><\/span><span class=\"ngg-ss__ball\"><\/span><span class=\"ngg-ss__gl\">'+esc(L.gl)+'<\/span><\/button>'+\n '<div class=\"ngg-ss__b\"><span class=\"ngg-ss__k\">'+esc(L.k)+'<\/span><strong class=\"ngg-ss__t\">'+esc(L.t)+'<\/strong><p class=\"ngg-ss__p\">'+esc(L.p)+'<\/p><ul class=\"ngg-ss__c\">'+chips+'<\/ul>'+\n '<div class=\"ngg-ss__f\"><button type=\"button\" class=\"ngg-ss__a\" data-ngg-putt data-ngg-cta=\"season_putt_open\">'+esc(L.putt)+' \u2192<\/button><a class=\"ngg-ss__a2\" href=\"'+PLAY+'\" data-ngg-cta=\"season_end_play\">'+esc(L.play27)+'<\/a><\/div><\/div>';\n tgt.insertBefore(el,tgt.firstChild);\n [].forEach.call(el.querySelectorAll('[data-ngg-putt]'),function(b){b.addEventListener('click',function(){openGame();});});\n}\n\n\/* ---------- 2. Putting game ---------- *\/\nvar G=null;\nfunction openGame(){\n if(document.getElementById('ngg-pt')){return;}\n track('ngg_putt_open');\n var ov=document.createElement('div');ov.id='ngg-pt';ov.setAttribute('role','dialog');ov.setAttribute('aria-modal','true');ov.setAttribute('aria-label',L.mt);\n ov.innerHTML='<div class=\"ngg-pt__box\"><button type=\"button\" class=\"ngg-pt__x\" aria-label=\"'+esc(L.close)+'\">\u00d7<\/button>'+\n '<span class=\"ngg-pt__k\">'+esc(L.mk)+'<\/span><strong class=\"ngg-pt__t\">'+esc(L.mt)+'<\/strong><p class=\"ngg-pt__h\">'+esc(L.mh)+'<\/p>'+\n '<div class=\"ngg-pt__st\"><span>'+esc(L.strokes)+': <b data-s>0<\/b><\/span><span>'+esc(NAME)+'<\/span><\/div>'+\n '<div style=\"position:relative\"><canvas class=\"ngg-pt__cv\"><\/canvas><\/div>'+\n '<div style=\"text-align:center\"><button type=\"button\" class=\"ngg-pt__skip\">'+esc(L.skip)+'<\/button><\/div>'+\n '<div class=\"ngg-pt__win\"><strong class=\"ngg-pt__wt\"><\/strong><p class=\"ngg-pt__wp\">'+esc(L.wp)+'<\/p><div class=\"ngg-pt__wf\"><a class=\"ngg-pt__a\" href=\"'+PLAY+'\" data-ngg-cta=\"season_putt_play27\">'+esc(L.play27)+' \u2192<\/a><button type=\"button\" class=\"ngg-pt__a2\" data-again>'+esc(L.again)+'<\/button>'+(navigator.share?'<button type=\"button\" class=\"ngg-pt__a2\" data-share>'+esc(L.share)+'<\/button>':'')+'<\/div><\/div>'+\n '<canvas class=\"ngg-pt__fx\"><\/canvas><\/div>';\n document.body.appendChild(ov);\n var prevOverflow=document.documentElement.style.overflow;document.documentElement.style.overflow='hidden';\n requestAnimationFrame(function(){ov.classList.add('is-in');});\n var cv=ov.querySelector('.ngg-pt__cv'),fx=ov.querySelector('.ngg-pt__fx'),box=ov.querySelector('.ngg-pt__box');\n var ctx=cv.getContext('2d'),fctx=fx.getContext('2d');\n var sEl=ov.querySelector('[data-s]');\n var S={w:0,h:0,dpr:1,vert:false,ball:{x:0,y:0,vx:0,vy:0,r:7,s:1},hole:{x:0,y:0,r:12},slope:{x:0,y:0},strokes:0,aim:null,moving:false,sunk:false,sinkT:0,raf:0,t:0,parts:[],start:{x:0,y:0},alive:true};\n G=S;\n function sizeFx(){var hh=box.scrollHeight;fx.style.height=hh+'px';fx.width=Math.round(box.clientWidth*S.dpr);fx.height=Math.round(hh*S.dpr);}\n function layout(){\n  var w=cv.clientWidth||600;S.vert=w<520;var h=S.vert?Math.round(Math.min(w*1.25,window.innerHeight*0.55)):Math.round(w*0.56);\n  S.dpr=Math.min(window.devicePixelRatio||1,2);cv.width=Math.round(w*S.dpr);cv.height=Math.round(h*S.dpr);cv.style.height=h+'px';S.w=w;S.h=h;\n  sizeFx();\n  var u=Math.max(5,Math.min(w,h)\/48);S.ball.r=u;S.hole.r=u*1.75;\n }\n function reset(full){\n  layout();\n  if(S.vert){S.start={x:S.w*0.5,y:S.h*0.84};S.hole.x=S.w*(0.35+Math.random()*0.3);S.hole.y=S.h*0.2;}\n  else{S.start={x:S.w*0.14,y:S.h*0.5};S.hole.x=S.w*0.8;S.hole.y=S.h*(0.3+Math.random()*0.4);}\n  S.ball.x=S.start.x;S.ball.y=S.start.y;S.ball.vx=0;S.ball.vy=0;S.ball.s=1;\n  var a=Math.random()*Math.PI*2,m=0.012+Math.random()*0.02;S.slope={x:Math.cos(a)*m,y:Math.sin(a)*m};\n  S.strokes=0;sEl.textContent='0';S.sunk=false;S.moving=false;S.aim=null;S.sinkT=0;\n  if(full){ov.classList.remove('is-won');}\n }\n function pos(e){var r=cv.getBoundingClientRect();return {x:e.clientX-r.left,y:e.clientY-r.top};}\n cv.addEventListener('pointerdown',function(e){if(S.moving){return;}if(S.sunk){return;}S.aim={x0:pos(e).x,y0:pos(e).y,x:pos(e).x,y:pos(e).y};try{cv.setPointerCapture(e.pointerId);}catch(er){}e.preventDefault();});\n cv.addEventListener('pointermove',function(e){if(!S.aim){return;}var p=pos(e);S.aim.x=p.x;S.aim.y=p.y;});\n function release(){\n  if(!S.aim){return;}var dx=S.aim.x0-S.aim.x,dy=S.aim.y0-S.aim.y;S.aim=null;\n  var len=Math.sqrt(dx*dx+dy*dy);var maxD=Math.min(S.w,S.h)*0.45;if(len<6){return;}\n  var p=Math.min(len,maxD)\/maxD;var maxV=Math.min(S.w,S.h)*0.052;\n  S.ball.vx=dx\/len*p*maxV;S.ball.vy=dy\/len*p*maxV;S.moving=true;S.strokes++;sEl.textContent=String(S.strokes);\n }\n cv.addEventListener('pointerup',release);cv.addEventListener('pointercancel',function(){S.aim=null;});\n function win(){\n  S.sunk=true;track('ngg_putt_sunk');\n  var n=S.strokes;ov.querySelector('.ngg-pt__wt').textContent=(n===1?L.w1:(n===2?L.w2:L.wn(n)));\n  ov.classList.add('is-won');\n  sizeFx();\n  confetti();\n  setTimeout(function(){var w=ov.querySelector('.ngg-pt__win');if(w){if(w.scrollIntoView){w.scrollIntoView({behavior:'smooth',block:'nearest'});}}},350);\n }\n function confetti(){\n  var cols=['#f39595','#ffafea','#1a6bfc','#ffffff','#3ddc84','#ffd166'];\n  var W=fx.width\/S.dpr;var r=cv.getBoundingClientRect(),br=box.getBoundingClientRect();\n  var ox=S.hole.x+(r.left-br.left),oy=S.hole.y+(r.top-br.top)+box.scrollTop;\n  for(var i=0;i<160;i++){var a=-Math.PI\/2+(Math.random()-.5)*2.2,sp=4+Math.random()*9;S.parts.push({x:ox,y:oy,vx:Math.cos(a)*sp,vy:Math.sin(a)*sp,g:.18+Math.random()*.1,s:4+Math.random()*6,r:Math.random()*6,vr:(Math.random()-.5)*.4,c:cols[i%cols.length],life:140+Math.random()*80});}\n  for(var j=0;j<60;j++){S.parts.push({x:Math.random()*W,y:-20-Math.random()*200,vx:(Math.random()-.5)*2,vy:2+Math.random()*3,g:.05,s:4+Math.random()*5,r:Math.random()*6,vr:(Math.random()-.5)*.3,c:cols[j%cols.length],life:260});}\n }\n function step(){\n  var b=S.ball,h=S.hole;\n  if(S.moving){if(!S.sunk){\n   var sp=Math.sqrt(b.vx*b.vx+b.vy*b.vy);\n   if(sp>0.25){b.vx+=S.slope.x;b.vy+=S.slope.y;}\n   b.x+=b.vx;b.y+=b.vy;b.vx*=0.982;b.vy*=0.982;\n   var m=b.r+6;\n   if(b.x<m){b.x=m;b.vx=-b.vx*0.6;}if(b.x>S.w-m){b.x=S.w-m;b.vx=-b.vx*0.6;}\n   if(b.y<m){b.y=m;b.vy=-b.vy*0.6;}if(b.y>S.h-m){b.y=S.h-m;b.vy=-b.vy*0.6;}\n   var dx=h.x-b.x,dy=h.y-b.y,d=Math.sqrt(dx*dx+dy*dy);sp=Math.sqrt(b.vx*b.vx+b.vy*b.vy);\n   var cap=Math.min(S.w,S.h)*0.022;\n   if(d<h.r){\n    if(sp<cap){S.moving=false;S.sinkT=1;b.vx=0;b.vy=0;}\n    else{b.vx+=dx*0.03;b.vy+=dy*0.03;b.vx*=0.8;b.vy*=0.8;}\n   } else if(d<h.r*1.8){if(sp<cap){b.vx+=dx\/d*0.08;b.vy+=dy\/d*0.08;}}\n   if(S.moving){if(sp<0.06){b.vx=0;b.vy=0;S.moving=false;}}\n  }}\n  if(S.sinkT>0){S.sinkT+=1;b.x+=(h.x-b.x)*0.25;b.y+=(h.y-b.y)*0.25;b.s=Math.max(0,1-S.sinkT\/14);if(S.sinkT===16){win();}}\n }\n function drawGreen(){\n  var w=S.w,h=S.h;ctx.save();ctx.scale(S.dpr,S.dpr);\n  ctx.fillStyle='#24683a';ctx.fillRect(0,0,w,h);\n  var g=ctx.createRadialGradient(w*.5,h*.45,10,w*.5,h*.5,Math.max(w,h)*.7);g.addColorStop(0,'#46a05a');g.addColorStop(1,'#2e7f43');\n  ctx.fillStyle=g;rr(6,6,w-12,h-12,16);ctx.fill();\n  ctx.save();rr(6,6,w-12,h-12,16);ctx.clip();ctx.globalAlpha=.07;ctx.fillStyle='#ffffff';\n  var band=Math.max(18,Math.min(w,h)\/9);for(var i=-h;i<w+h;i+=band*2){ctx.beginPath();ctx.moveTo(i,0);ctx.lineTo(i+band,0);ctx.lineTo(i+band-h*.6,h);ctx.lineTo(i-h*.6,h);ctx.closePath();ctx.fill();}\n  ctx.restore();\n  return ctx;\n }\n function rr(x,y,w,h,r){ctx.beginPath();ctx.moveTo(x+r,y);ctx.arcTo(x+w,y,x+w,y+h,r);ctx.arcTo(x+w,y+h,x,y+h,r);ctx.arcTo(x,y+h,x,y,r);ctx.arcTo(x,y,x+w,y,r);ctx.closePath();}\n function draw(){\n  S.t++;var b=S.ball,h=S.hole;drawGreen();\n  ctx.fillStyle='rgba(0,0,0,.08)';ctx.beginPath();ctx.arc(h.x,h.y,h.r*2.2,0,Math.PI*2);ctx.fill();\n  ctx.fillStyle='#0d1f12';ctx.beginPath();ctx.ellipse(h.x,h.y,h.r,h.r*.8,0,0,Math.PI*2);ctx.fill();\n  ctx.strokeStyle='rgba(255,255,255,.55)';ctx.lineWidth=1.5;ctx.beginPath();ctx.ellipse(h.x,h.y,h.r,h.r*.8,0,0,Math.PI*2);ctx.stroke();\n  if(!S.sunk){\n   var ph=h.r*5.5,wave=Math.sin(S.t\/9)*3;\n   ctx.strokeStyle='#ffffff';ctx.lineWidth=2.2;ctx.beginPath();ctx.moveTo(h.x,h.y);ctx.lineTo(h.x,h.y-ph);ctx.stroke();\n   ctx.fillStyle='#f39595';ctx.beginPath();ctx.moveTo(h.x+1,h.y-ph);ctx.quadraticCurveTo(h.x+h.r*1.6,h.y-ph+wave,h.x+h.r*3,h.y-ph+h.r*.9+wave*.5);ctx.quadraticCurveTo(h.x+h.r*1.4,h.y-ph+h.r*1.4,h.x+1,h.y-ph+h.r*1.8);ctx.closePath();ctx.fill();\n  }\n  \/* break indicator *\/\n  var sx=S.w-46,sy=34,sl=Math.sqrt(S.slope.x*S.slope.x+S.slope.y*S.slope.y),ux=S.slope.x\/sl,uy=S.slope.y\/sl,al=10+sl*500;\n  ctx.fillStyle='rgba(11,29,58,.55)';ctx.beginPath();ctx.arc(sx,sy,24,0,Math.PI*2);ctx.fill();\n  ctx.strokeStyle='#ffafea';ctx.fillStyle='#ffafea';ctx.lineWidth=2.5;ctx.beginPath();ctx.moveTo(sx-ux*al\/2,sy-uy*al\/2);ctx.lineTo(sx+ux*al\/2,sy+uy*al\/2);ctx.stroke();\n  ctx.beginPath();ctx.moveTo(sx+ux*al\/2+ux*6,sy+uy*al\/2+uy*6);ctx.lineTo(sx+ux*al\/2-uy*5,sy+uy*al\/2+ux*5);ctx.lineTo(sx+ux*al\/2+uy*5,sy+uy*al\/2-ux*5);ctx.closePath();ctx.fill();\n  ctx.fillStyle='rgba(255,255,255,.85)';ctx.font='800 9px system-ui,sans-serif';ctx.textAlign='center';ctx.fillText(L.brk.toUpperCase(),sx,sy+38);\n  \/* aim *\/\n  if(S.aim){\n   var dx=S.aim.x0-S.aim.x,dy=S.aim.y0-S.aim.y,len=Math.sqrt(dx*dx+dy*dy),maxD=Math.min(S.w,S.h)*0.45,p=Math.min(len,maxD)\/maxD;\n   if(len>4){var ux2=dx\/len,uy2=dy\/len,ll=30+p*Math.min(S.w,S.h)*0.5;\n    ctx.setLineDash([4,7]);ctx.strokeStyle='rgba(255,255,255,.9)';ctx.lineWidth=2.5;ctx.beginPath();ctx.moveTo(b.x,b.y);ctx.lineTo(b.x+ux2*ll,b.y+uy2*ll);ctx.stroke();ctx.setLineDash([]);\n    var pw=70,px=b.x-pw\/2,py=b.y+b.r+12;if(py>S.h-16){py=b.y-b.r-20;}\n    ctx.fillStyle='rgba(11,29,58,.6)';rr(px,py,pw,7,4);ctx.fill();ctx.fillStyle=p>.85?'#f39595':'#ffffff';rr(px,py,pw*p,7,4);ctx.fill();\n   }\n  }\n  \/* ball *\/\n  if(b.s>0){\n   ctx.fillStyle='rgba(0,0,0,.25)';ctx.beginPath();ctx.ellipse(b.x+2,b.y+3,b.r*b.s,b.r*.7*b.s,0,0,Math.PI*2);ctx.fill();\n   var bg=ctx.createRadialGradient(b.x-b.r*.35,b.y-b.r*.35,1,b.x,b.y,b.r*b.s);bg.addColorStop(0,'#ffffff');bg.addColorStop(1,'#d9dde3');\n   ctx.fillStyle=bg;ctx.beginPath();ctx.arc(b.x,b.y,b.r*b.s,0,Math.PI*2);ctx.fill();\n   if(S.strokes===0){if(!S.aim){var pr=b.r*2+Math.sin(S.t\/10)*3;ctx.strokeStyle='rgba(255,255,255,.6)';ctx.lineWidth=2;ctx.beginPath();ctx.arc(b.x,b.y,pr,0,Math.PI*2);ctx.stroke();}}\n  }\n  ctx.restore();\n  \/* confetti *\/\n  var fw=fx.width\/S.dpr,fh=fx.height\/S.dpr;fctx.setTransform(S.dpr,0,0,S.dpr,0,0);fctx.clearRect(0,0,fw,fh);\n  S.parts=S.parts.filter(function(q){q.vy+=q.g;q.vx*=.99;q.x+=q.vx;q.y+=q.vy;q.r+=q.vr;q.life--;\n   fctx.save();fctx.translate(q.x,q.y);fctx.rotate(q.r);fctx.fillStyle=q.c;fctx.globalAlpha=Math.max(0,Math.min(1,q.life\/40));fctx.fillRect(-q.s\/2,-q.s\/4,q.s,q.s\/2);fctx.restore();\n   return q.life>0;});\n }\n function loop(){if(!S.alive){return;}step();draw();S.raf=requestAnimationFrame(loop);}\n function close(){S.alive=false;cancelAnimationFrame(S.raf);document.documentElement.style.overflow=prevOverflow;ov.classList.remove('is-in');document.removeEventListener('keydown',onKey);window.removeEventListener('resize',onResize);setTimeout(function(){if(ov.parentNode){ov.parentNode.removeChild(ov);}},200);G=null;var f=document.querySelector('#ngg-ss .ngg-ss__a');if(f){f.focus();}}\n function onKey(e){if(e.key==='Escape'){close();}}\n function onResize(){var keep=S.sunk;if(!S.moving){reset(false);if(keep){S.sunk=true;S.ball.s=0;}}}\n ov.querySelector('.ngg-pt__x').addEventListener('click',close);\n ov.addEventListener('click',function(e){if(e.target===ov){close();}});\n ov.querySelector('.ngg-pt__skip').addEventListener('click',function(){track('ngg_putt_skip');ov.querySelector('.ngg-pt__wt').textContent=L.t;ov.classList.add('is-won');S.sunk=true;S.ball.s=0;sizeFx();confetti();});\n ov.querySelector('[data-again]').addEventListener('click',function(){reset(true);});\n var shb=ov.querySelector('[data-share]');if(shb){shb.addEventListener('click',function(){try{navigator.share({title:L.t,text:L.shareT(S.strokes||1),url:location.origin+'\/'});}catch(e){}});}\n document.addEventListener('keydown',onKey);window.addEventListener('resize',onResize);\n reset(true);loop();\n setTimeout(function(){var x=ov.querySelector('.ngg-pt__x');if(x){x.focus();}},50);\n}\n\n\/* ---------- 3. Statuses & opening hours on this page ---------- *\/\nfunction setText(el,t){if(el){if(el.textContent!==t){el.textContent=t;}}}\nfunction raeHours(){\n [].forEach.call(document.querySelectorAll('.dot__item-left'),function(l){\n  var r=l.nextElementSibling;if(!r){return;}var tg=r.querySelector('strong')||r;var k=l.textContent.toLowerCase();\n  if(\/v\u00e4ljak|course|caddiemaster\/.test(k)){setText(tg,L.Closed);}\n });\n var ul=document.querySelector('.list-checks-wrap .list--checks');\n if(ul){[].forEach.call(ul.querySelectorAll('li'),function(li){\n  var b=li.querySelector('b'),sp=li.querySelector('span');var n=(b?b.textContent:li.textContent).toLowerCase();\n  var on=\/range\/.test(n);var off=\/peav\u00e4ljak|main course|akadeemia|academy|fortal|restoran|restaurant|jacoby|caddie\/.test(n);\n  if(!on){if(!off){return;}}\n  var txt=on?L.open:L.closed;\n  if(b){if(sp){setText(sp,txt);li.className=on?'is-open':'is-closed';li.setAttribute('title',txt);}}\n  else{setText(li,li.textContent.split(':')[0]+': '+txt);}\n });}\n}\nfunction wbgMin(){try{var p=new Intl.DateTimeFormat('en-GB',{timeZone:'Europe\/Tallinn',hour:'2-digit',minute:'2-digit',hourCycle:'h23'}).formatToParts(new Date()),o={};p.forEach(function(q){o[q.type]=q.value;});return parseInt(o.hour,10)*60+parseInt(o.minute,10);}catch(e){return -1;}}\nfunction wbgClub(){var m=wbgMin();return m>=600 ? 780>m : false;}\nfunction wbgOpen(){var m=wbgMin();return m>=630 ? 930>m : false;}\nfunction wbgResto(){try{var p=new Intl.DateTimeFormat('en-GB',{timeZone:'Europe\/Tallinn',weekday:'short',hour:'2-digit',minute:'2-digit',hourCycle:'h23'}).formatToParts(new Date()),o={};p.forEach(function(x){o[x.type]=x.value;});var m=parseInt(o.hour,10)*60+parseInt(o.minute,10);if(!\/Mon|Tue|Wed|Thu|Fri\/.test(o.weekday)){return false;}if(m<660){return false;}return m<840;}catch(e){return false;}}\nfunction wbgHours(){\n [].forEach.call(document.querySelectorAll('.gut-info-list .wp-block-columns'),function(row){\n  var ps=row.querySelectorAll('p');if(ps.length<2){return;}var k=ps[0].textContent.toLowerCase();\n  \n });\n [].forEach.call(document.querySelectorAll('footer p'),function(p){\n  if(p.getAttribute('data-ngg-ss')==='1'){return;}var t=p.textContent;\n  if(\/V\u00e4ljak on avatud R\u2013P\/.test(t)){if(\/caddiemaster\/i.test(t)){p.innerHTML='<span class=\"ngg-l-et\">V\u00e4ljak on avatud R\u2013P, tiiajad 10\u201317. Range on avatud.<\/span><span class=\"ngg-l-en\">The course is open Fri\u2013Sun, tee times 10\u201317. The range is open.<\/span><br><strong><span class=\"ngg-l-et\">Klubimaja ja caddiemaster<\/span><span class=\"ngg-l-en\">Clubhouse and caddiemaster<\/span><\/strong><br><span class=\"ngg-l-et\">suletud<\/span><span class=\"ngg-l-en\">closed<\/span>';p.setAttribute('data-ngg-ss','1');}}\n  else if(false&&\/11:00\/.test(t)){var col=p.closest('.wp-block-column');if(col){if(\/restoran|restaurant\/i.test(col.textContent)){p.innerHTML='<strong><span class=\"ngg-l-et\">Talvel suletud<\/span><span class=\"ngg-l-en\">Closed for winter<\/span><\/strong>';p.setAttribute('data-ngg-ss','1');}}}\n });\n var CO=wbgOpen();var CL=wbgClub();var RO=wbgResto();var TODAY='<span data-state=\"'+(CO?'open':'closed')+'\"><i>'+(EN?'Course':'V\u00e4ljak')+'<\/i> '+(CO?L.open:L.closed)+'<\/span><span data-state=\"open\"><i>Range<\/i> '+L.open+'<\/span><span data-state=\"'+(CL?'open':'closed')+'\"><i>'+(EN?'Clubhouse':'Klubimaja')+'<\/i> '+(CL?L.open:L.closed)+'<\/span><span data-state=\"'+(RO?'open':'closed')+'\"><i>'+(EN?'Restaurant':'Restoran')+'<\/i> '+(RO?L.open:L.closed)+'<\/span>';\n [].forEach.call(document.querySelectorAll('[data-today]'),function(el){\n  if(el.innerHTML!==TODAY){el.innerHTML=TODAY;}\n  if(el.getAttribute('data-ngg-ss')!=='1'){el.setAttribute('data-ngg-ss','1');if(window.MutationObserver){new MutationObserver(function(){if(el.innerHTML!==TODAY){el.innerHTML=TODAY;}}).observe(el,{childList:true,subtree:true,characterData:true});}}\n });\n}\nfunction lv(){if(window.NGGLV){if(window.NGGLV.setStatus){try{window.NGGLV.setStatus(SITE,{notice:{text:L.notice,level:'info'},course:(RAE||!wbgOpen())?{text:L.closed,open:false}:{text:L.open,open:true},range:{text:L.open,open:true},source:'NGG hooaja l\u00f5pp 19.10'});}catch(e){}}}}\nfunction apply(){try{banner();}catch(e){}try{if(RAE){raeHours();}else{wbgHours();}}catch(e){}try{lv();}catch(e){}}\nfunction run(){apply();setTimeout(apply,400);setTimeout(apply,1500);setTimeout(apply,4000);}\nif(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',run);}else{run();}\n})();\n<\/script>\n\n\n\n<style id=\"ngg-lv-css\">\n.ngg-lv-host--rel{position:relative}\n.ngg-lv-above{position:relative;z-index:2}\n.ngg-lv-above-z{z-index:2}\n.ngg-lv-fx{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;overflow:hidden}\n.ngg-lv-fx .ngg-lv-l,.ngg-lv-fx .ngg-lv-precip,.ngg-lv-fx .ngg-lv-photo{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;transition:opacity 1.2s ease,background-color 1.2s ease}\n.ngg-lv-bg{transition:filter 1.2s ease}\n.ngg-lv-fx-on .ngg-lv-bg,.ngg-lv-fx .ngg-lv-photo{filter:brightness(var(--lv-bri,1)) saturate(var(--lv-sat,1)) contrast(var(--lv-con,1))}\n.ngg-lv-fx .ngg-lv-photo{object-fit:cover;max-width:none;margin:0;border:0;border-radius:0}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-photo--on{opacity:1}\n.ngg-lv-fx .ngg-lv-warm{background:var(--lv-warm,#ffb070);mix-blend-mode:soft-light}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-warm{opacity:var(--lv-warm-a,0)}\n.ngg-lv-fx .ngg-lv-cool{background:var(--lv-cool,#0b1d3a);mix-blend-mode:multiply}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-cool{opacity:var(--lv-cool-a,0)}\n.ngg-lv-fx .ngg-lv-glow{background:radial-gradient(55% 60% at var(--lv-glow-x,80%) var(--lv-glow-y,20%),rgba(255,200,130,.9),rgba(255,160,90,.28) 42%,rgba(255,160,90,0) 72%);mix-blend-mode:screen}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-glow{opacity:var(--lv-glow-a,0)}\n.ngg-lv-fx .ngg-lv-spots{top:-8%;left:-8%;width:116%;height:116%;background:radial-gradient(16% 13% at 20% 34%,rgba(255,246,220,.55),rgba(255,246,220,0) 70%),radial-gradient(12% 10% at 58% 62%,rgba(255,242,206,.42),rgba(255,242,206,0) 70%),radial-gradient(20% 15% at 84% 26%,rgba(255,250,232,.5),rgba(255,250,232,0) 70%),radial-gradient(10% 9% at 40% 82%,rgba(255,244,214,.35),rgba(255,244,214,0) 70%);mix-blend-mode:screen;animation:ngg-lv-spots 28s ease-in-out infinite alternate}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-spots{opacity:var(--lv-spots-a,0)}\n.ngg-lv-fx .ngg-lv-clouds{width:200%;background-image:radial-gradient(34% 40% at 18% 40%,rgba(28,40,60,.5),rgba(28,40,60,.22) 45%,rgba(28,40,60,0) 75%),radial-gradient(28% 34% at 54% 72%,rgba(28,40,60,.42),rgba(28,40,60,.18) 45%,rgba(28,40,60,0) 75%),radial-gradient(38% 42% at 84% 32%,rgba(28,40,60,.48),rgba(28,40,60,.2) 45%,rgba(28,40,60,0) 75%);background-size:50% 100%;background-repeat:repeat-x;mix-blend-mode:multiply;animation:ngg-lv-drift var(--lv-drift,120s) linear infinite}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-clouds{opacity:var(--lv-shadow-a,0)}\n.ngg-lv-fx .ngg-lv-haze{background:linear-gradient(180deg,rgba(234,240,246,.9),rgba(234,240,246,.6) 55%,rgba(234,240,246,.4))}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-haze{opacity:var(--lv-haze-a,0)}\n.ngg-lv-fx .ngg-lv-scrim{background:radial-gradient(closest-side,rgba(11,29,58,.8),rgba(11,29,58,.45) 62%,rgba(11,29,58,0))}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-scrim{opacity:var(--lv-scrim-a,0)}\n.ngg-lv-fx-on .ngg-lv-fx .ngg-lv-precip{opacity:1}\n.ngg-lv-fx .ngg-lv-precip{-webkit-mask-image:linear-gradient(180deg,transparent 0,transparent 70px,#000 170px);mask-image:linear-gradient(180deg,transparent 0,transparent 70px,#000 170px)}\n.ngg-lv-fx .ngg-lv-hbadge{position:absolute;right:16px;max-width:calc(100% - 32px);padding:6px 12px;border-radius:999px;background:rgba(11,29,58,.66);color:#fff;font:600 13px\/1.25 \"Google Sans\",system-ui,-apple-system,\"Segoe UI\",sans-serif;letter-spacing:.02em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.ngg-lv-fx .ngg-lv-hbadge[hidden],.ngg-lv-fx .ngg-lv-hbadge--off{display:none}\n.ngg-lv-host.ngg-lv-paused .ngg-lv-fx .ngg-lv-l{animation-play-state:paused}\n.ngg-lv-host.ngg-lv-rm .ngg-lv-fx .ngg-lv-l{animation:none}\n@keyframes ngg-lv-drift{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}\n@keyframes ngg-lv-spots{from{transform:translate3d(-2.5%,1.5%,0)}to{transform:translate3d(2.5%,-1.5%,0)}}\n@media (prefers-reduced-motion:reduce){.ngg-lv-fx .ngg-lv-l{animation:none!important}.ngg-lv-fx .ngg-lv-l,.ngg-lv-bg{transition:none!important}}\n.ngg-lv.ngg-lv-sec{--lv-night:#0b1d3a;--lv-ink:#3c4b63;--lv-line:#cbd7db;--lv-coral:#f39595;--lv-sand:#f6f6f5;--lv-acc:#1f6fff;--lv-acc2:#ffafea;--lv-acc2-t:#ffe1f5;background:var(--lv-sand);color:var(--lv-night);font-family:\"Google Sans\",system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;padding:clamp(28px,5vw,64px) 0;min-height:var(--ngg-lv-reserve-m,1370px);display:flex;flex-direction:column;scroll-margin-top:90px}\n.ngg-lv.ngg-lv--wbg{--lv-sand:#f2ece2;--lv-acc:#073875;--lv-acc2:#aff4ed;--lv-acc2-t:#dcf9f5}\n.ngg-lv.ngg-lv-sec,.ngg-lv.ngg-lv-sec *{box-sizing:border-box}\n.ngg-lv .ngg-lv-wrap{flex:1 0 auto;display:flex;flex-direction:column;width:100%;max-width:var(--ngg-wide-max,1180px);margin:0 auto;padding-left:16px;padding-right:16px}\n.ngg-lv .ngg-lv-grid{flex:1 0 auto;display:grid;grid-template-columns:minmax(0,1fr);gap:16px}\n.ngg-lv .ngg-lv-card{background:#fff;border-radius:24px;padding:clamp(18px,2.6vw,32px);box-shadow:0 1px 0 var(--lv-line),0 18px 40px -24px rgba(11,29,58,.35);min-width:0}\n.ngg-lv .ngg-lv-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap}\n.ngg-lv .ngg-lv-k{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--lv-ink);margin:0 0 6px}\n.ngg-lv .ngg-lv-h{font-family:\"Bricolage Grotesque\",\"Google Sans\",system-ui,sans-serif;font-stretch:87.5%;font-weight:780;line-height:1.05;letter-spacing:-.01em;font-size:clamp(26px,3vw,36px);margin:0 0 14px;color:var(--lv-night);overflow-wrap:break-word;hyphens:auto}\n.ngg-lv .ngg-lv-fxbtn{display:inline-flex;align-items:center;gap:8px;min-height:36px;padding:4px 10px 4px 4px;border:1px solid var(--lv-line);border-radius:999px;background:#fff;color:var(--lv-ink);font-weight:600;font-size:13px;line-height:1.2;font-family:inherit;cursor:pointer}\n.ngg-lv .ngg-lv-fxdot{position:relative;width:34px;height:20px;border-radius:999px;background:var(--lv-line);transition:background .2s}\n.ngg-lv .ngg-lv-fxdot::after{content:\"\";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(11,29,58,.3);transition:transform .2s}\n.ngg-lv .ngg-lv-fxbtn[aria-checked=\"true\"] .ngg-lv-fxdot{background:var(--lv-acc)}\n.ngg-lv .ngg-lv-fxbtn[aria-checked=\"true\"] .ngg-lv-fxdot::after{transform:translateX(14px)}\n.ngg-lv .ngg-lv-seg{display:inline-flex;flex-wrap:wrap;gap:4px;padding:4px;border:1px solid var(--lv-line);border-radius:999px;background:#fff;max-width:100%}\n.ngg-lv .ngg-lv-segb{min-height:40px;padding:0 16px;border:0;border-radius:999px;background:transparent;color:var(--lv-night);font-weight:600;font-size:15px;line-height:1;font-family:inherit;cursor:pointer;white-space:nowrap}\n.ngg-lv .ngg-lv-segb:hover{background:#eef2f5}\n.ngg-lv .ngg-lv-segb[aria-pressed=\"true\"]{background:var(--lv-night);color:#fff}\n.ngg-lv .ngg-lv-segb[hidden]{display:none}\n.ngg-lv button:focus-visible,.ngg-lv a:focus-visible,.ngg-lv input:focus-visible,.ngg-lv select:focus-visible{outline:3px solid var(--lv-acc);outline-offset:3px}\n.ngg-lv .ngg-lv-copy{font-size:18px;line-height:1.4;margin:14px 0 6px;min-height:calc(1.4em * 2);color:var(--lv-night);max-width:44ch}\n.ngg-lv .ngg-lv-copy[hidden]{display:block;visibility:hidden}\n.ngg-lv .ngg-lv-main{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:10px 16px;align-items:center;margin:4px 0 8px}\n.ngg-lv .ngg-lv-big{display:flex;flex-direction:column;gap:6px;min-width:0}\n.ngg-lv .ngg-lv-temp{font-family:\"Bricolage Grotesque\",\"Google Sans\",system-ui,sans-serif;font-stretch:87.5%;font-weight:780;font-size:clamp(56px,7vw,76px);line-height:.95;letter-spacing:-.02em}\n.ngg-lv .ngg-lv-bigtxt{display:flex;flex-direction:column;gap:2px;min-height:44px}\n.ngg-lv .ngg-lv-cond{font-size:17px;font-weight:600;line-height:1.3}\n.ngg-lv .ngg-lv-feels-s{font-size:14px;color:var(--lv-ink);line-height:1.3}\n.ngg-lv .ngg-lv-flag{margin:0;min-width:0}\n.ngg-lv .ngg-lv-flaghold{width:100%;max-width:240px;aspect-ratio:200\/140;margin-left:auto}\n.ngg-lv .ngg-lv-flag-svg{display:block;width:100%;height:100%}\n.ngg-lv .ngg-lv-wind{grid-column:1\/-1;display:flex;align-items:flex-start;gap:8px;font-size:15px;line-height:1.35;color:var(--lv-night);min-height:41px}\n.ngg-lv .ngg-lv-arrow{flex:0 0 22px;width:22px;height:22px;color:var(--lv-acc);transition:transform .6s ease}\n.ngg-lv .ngg-lv-arrow svg{display:block}\n.ngg-lv .ngg-lv-arrow[hidden]{display:block;visibility:hidden}\n.ngg-lv .ngg-lv-detbtn{display:none}\n.ngg-lv .ngg-lv-det{margin:8px 0 0;padding:0;border-top:1px solid var(--lv-line)}\n.ngg-lv .ngg-lv-row{display:flex;justify-content:space-between;gap:12px;padding:10px 0;border-bottom:1px solid var(--lv-line);font-size:15px;line-height:1.35}\n.ngg-lv .ngg-lv-row[hidden]{display:none}\n.ngg-lv .ngg-lv-row dt{color:var(--lv-ink);margin:0;min-width:0}\n.ngg-lv .ngg-lv-row dd{margin:0;font-weight:600;text-align:right;min-width:0}\n.ngg-lv .ngg-lv-row--na dd{color:var(--lv-ink);font-weight:400}\n.ngg-lv .ngg-lv-row--closed dd{color:#a12a2a}\n.ngg-lv .ngg-lv-mini{display:inline-flex;align-items:flex-end;gap:3px;height:16px;vertical-align:-2px;margin-left:4px}\n.ngg-lv .ngg-lv-mini i{display:block;width:6px;height:100%;border-radius:2px;background:linear-gradient(to top,var(--lv-acc) var(--p,0%),#e1e8ed var(--p,0%))}\n.ngg-lv .ngg-lv-official{margin:12px 0 0;font-size:15px}\n.ngg-lv .ngg-lv-official[hidden]{display:none}\n.ngg-lv .ngg-lv-link{background:none;border:0;padding:0;font:inherit;color:var(--lv-acc);text-decoration:underline;text-underline-offset:3px;cursor:pointer}\n.ngg-lv .ngg-lv-upd{margin:12px 0 0;font-size:12.5px;line-height:1.45;color:var(--lv-ink);min-height:calc(1.45em * 2)}\n.ngg-lv .ngg-lv-upd a{color:inherit;text-decoration:underline;text-underline-offset:2px}\n.ngg-lv.ngg-lv-stale .ngg-lv-upd{color:#8a5a00}\n.ngg-lv .ngg-lv-notice{margin:0 0 16px;padding:12px 16px;border-radius:14px;font-size:16px;line-height:1.4;font-weight:600;background:#e2ecff;border:1px solid #b9cdf5}\n.ngg-lv .ngg-lv-notice--closed{background:#fde8e8;border-color:#f0b4b4;color:#6b1414}\n.ngg-lv .ngg-lv-notice[hidden]{display:none}\n.ngg-lv .ngg-lv-ctrls{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 18px}\n.ngg-lv .ngg-lv-slhead{display:flex;justify-content:space-between;align-items:baseline;gap:12px;margin-bottom:6px}\n.ngg-lv .ngg-lv-sllbl{font-size:14px;font-weight:700;color:var(--lv-ink);text-transform:uppercase;letter-spacing:.08em}\n.ngg-lv .ngg-lv-startout{font-family:\"Bricolage Grotesque\",\"Google Sans\",system-ui,sans-serif;font-stretch:87.5%;font-weight:780;font-size:30px;line-height:1}\n.ngg-lv .ngg-lv-strip{position:relative;height:76px;margin:6px 0 2px}\n.ngg-lv .ngg-lv-cell{position:absolute;bottom:0;width:12px;height:56px;transform:translateX(-50%);display:flex;align-items:flex-end;justify-content:center}\n.ngg-lv .ngg-lv-cbar{display:block;width:100%;border-radius:4px 4px 2px 2px;background:#d6e0e6;transition:background .2s}\n.ngg-lv .ngg-lv-cell--in .ngg-lv-cbar{background:var(--lv-acc)}\n.ngg-lv .ngg-lv-cell--sel .ngg-lv-cbar{background:var(--lv-night)}\n.ngg-lv .ngg-lv-cell--na .ngg-lv-cbar{background:repeating-linear-gradient(45deg,#e3e8ec 0 3px,#fff 3px 6px);height:100%!important}\n.ngg-lv .ngg-lv-cell::before{content:\"\";position:absolute;left:-1px;right:-1px;bottom:0;height:100%;border-radius:4px;background:transparent}\n.ngg-lv .ngg-lv-cell--in::before{background:rgba(31,111,255,.08)}\n.ngg-lv.ngg-lv--wbg .ngg-lv-cell--in::before{background:rgba(7,56,117,.08)}\n.ngg-lv .ngg-lv-ctemp{position:absolute;top:-18px;left:50%;transform:translateX(-50%);font-size:12px;font-weight:600;color:var(--lv-ink);white-space:nowrap}\n.ngg-lv .ngg-lv-sunset{position:absolute;bottom:0;width:0;height:72px;border-left:2px dashed #f0a35e;transform:translateX(-1px)}\n.ngg-lv .ngg-lv-sunset::after{content:\"\";position:absolute;top:-4px;left:-6px;width:10px;height:10px;border-radius:50%;background:#f0a35e}\n.ngg-lv .ngg-lv-range{-webkit-appearance:none;appearance:none;display:block;width:100%;height:32px;margin:0;background:transparent;cursor:pointer}\n.ngg-lv .ngg-lv-range:focus-visible{outline-offset:0;border-radius:999px}\n.ngg-lv .ngg-lv-range:disabled{cursor:not-allowed;opacity:.5}\n.ngg-lv .ngg-lv-range::-webkit-slider-runnable-track{height:6px;border-radius:999px;background:var(--lv-line)}\n.ngg-lv .ngg-lv-range::-moz-range-track{height:6px;border-radius:999px;background:var(--lv-line)}\n.ngg-lv .ngg-lv-range::-webkit-slider-thumb{-webkit-appearance:none;width:28px;height:28px;margin-top:-11px;border-radius:50%;background:var(--lv-night);border:4px solid #fff;box-shadow:0 1px 4px rgba(11,29,58,.45)}\n.ngg-lv .ngg-lv-range::-moz-range-thumb{width:20px;height:20px;border-radius:50%;background:var(--lv-night);border:4px solid #fff;box-shadow:0 1px 4px rgba(11,29,58,.45)}\n.ngg-lv .ngg-lv-ticks{position:relative;height:18px;font-size:12px;color:var(--lv-ink)}\n.ngg-lv .ngg-lv-tick{position:absolute;top:0;transform:translateX(-50%)}\n.ngg-lv .ngg-lv-badge{display:inline-flex;align-items:center;align-self:flex-start;height:30px;box-sizing:border-box;margin:14px 0 0;padding:0 12px;border-radius:999px;background:var(--lv-acc2-t);border:1px solid var(--lv-acc2);font-size:13px;font-weight:700;letter-spacing:.02em}\n.ngg-lv .ngg-lv-badge[hidden]{display:inline-flex;visibility:hidden}\n.ngg-lv .ngg-lv-read{margin:10px 0 0;min-height:236px}\n.ngg-lv .ngg-lv-rline{margin:0 0 6px;font-size:15.5px;line-height:1.4}\n.ngg-lv .ngg-lv-rline b{font-weight:700}\n.ngg-lv .ngg-lv-rline--lead{font-size:17px;font-weight:600;margin-bottom:10px}\n.ngg-lv .ngg-lv-rline--warn{color:#8a4a00}\n.ngg-lv .ngg-lv-rline--muted{font-size:13.5px;color:var(--lv-ink)}\n.ngg-lv .ngg-lv-btns{display:flex;flex-wrap:wrap;gap:10px;margin-top:14px;min-height:48px}\n.ngg-lv .ngg-lv-btn{display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:0 22px;border-radius:999px;font-weight:700;font-size:15px;line-height:1.1;font-family:inherit;letter-spacing:.04em;text-transform:uppercase;text-decoration:none;cursor:pointer;text-align:center;max-width:100%}\n.ngg-lv .ngg-lv-btn[hidden]{display:none}\n.ngg-lv .ngg-lv-btn--main{background:var(--lv-coral);color:var(--lv-night);border:2px solid var(--lv-coral)}\n.ngg-lv .ngg-lv-btn--main:hover{background:#ef8383;border-color:#ef8383}\n.ngg-lv .ngg-lv-btn--line{background:transparent;color:var(--lv-night);border:2px solid var(--lv-night)}\n.ngg-lv .ngg-lv-btn--line:hover{background:var(--lv-night);color:#fff}\n.ngg-lv .ngg-lv-note{margin:10px 0 0;font-size:13px;line-height:1.45;color:var(--lv-ink);min-height:calc(1.45em * 2)}\n.ngg-lv .ngg-lv-note[hidden]{display:block;visibility:hidden}\n.ngg-lv .ngg-lv-test{position:relative;align-self:flex-start;margin:-12px 0 12px 16px;z-index:5;display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:12px;background:var(--lv-night);color:#fff;font-size:13px;box-shadow:0 8px 24px rgba(0,0,0,.3);max-width:calc(100vw - 24px)}\n.ngg-lv .ngg-lv-test select{font:inherit;max-width:60vw;padding:4px;border-radius:6px}\n.ngg-lv[data-state=\"loading\"] .ngg-lv-temp,.ngg-lv[data-state=\"loading\"] .ngg-lv-det dd{color:#b9c4cc}\n.ngg-lv[data-state=\"error\"] .ngg-lv-main,.ngg-lv[data-state=\"error\"] .ngg-lv-det,.ngg-lv[data-state=\"error\"] .ngg-lv-detbtn,.ngg-lv[data-state=\"error\"] .ngg-lv-slide,.ngg-lv[data-state=\"error\"] .ngg-lv-badge,.ngg-lv[data-state=\"error\"] .ngg-lv-ctrls,.ngg-lv[data-state=\"error\"] .ngg-lv-note{display:none}\n.ngg-lv .ngg-lv-fallback{max-width:var(--ngg-wide-max,1180px);margin:0 auto;padding:0 16px}\n@media (min-width:760px){\n.ngg-lv .ngg-lv-wrap{padding-left:24px;padding-right:24px}\n.ngg-lv.ngg-lv-sec{min-height:var(--ngg-lv-reserve-t,1525px)}\n}\n@media (min-width:960px){\n.ngg-lv .ngg-lv-grid{grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:20px;align-items:stretch}\n.ngg-lv.ngg-lv-sec{min-height:var(--ngg-lv-reserve-d,880px)}\n}\n@media (max-width:759px){\n.ngg-lv .ngg-lv-main{grid-template-columns:minmax(0,1fr) minmax(0,150px)}\n.ngg-lv .ngg-lv-detbtn{display:inline-flex;align-items:center;min-height:44px;margin-top:6px;padding:0 16px;border:1px solid var(--lv-line);border-radius:999px;background:#fff;color:var(--lv-night);font-weight:600;font-size:14px;line-height:1;font-family:inherit;cursor:pointer}\n.ngg-lv .ngg-lv-det,.ngg-lv .ngg-lv-official,.ngg-lv .ngg-lv-upd{display:none}\n.ngg-lv.ngg-lv-open .ngg-lv-det{display:block}\n.ngg-lv.ngg-lv-open .ngg-lv-official:not([hidden]),.ngg-lv.ngg-lv-open .ngg-lv-upd{display:block}\n.ngg-lv .ngg-lv-copy{font-size:17px}\n.ngg-lv .ngg-lv-segb{padding:0 13px;font-size:14px}\n.ngg-lv .ngg-lv-cell{width:10px}\n.ngg-lv .ngg-lv-btn{width:100%}\n.ngg-lv .ngg-lv-read{min-height:282px}\n.ngg-lv[data-state=\"error\"] .ngg-lv-official:not([hidden]){display:block}\n}\n@media (prefers-reduced-motion:reduce){.ngg-lv .ngg-lv-arrow,.ngg-lv .ngg-lv-fxdot,.ngg-lv .ngg-lv-fxdot::after{transition:none}}\n.ngg-lv.ngg-lv-rm .ngg-lv-arrow{transition:none}\n<\/style>\n<section id=\"ngg-lv\" class=\"ngg-lv ngg-lv-sec ngg-lv--wbg\" data-ngg-lv data-site=\"valgeranna\" data-lang=\"en\" data-hero=\".ngg-in\" aria-label=\"On the course today\">\n<script type=\"application\/json\" class=\"ngg-lv-config\">{\"version\":\"1.1.0\",\"_doc\":\"Elav v\u00e4ljak \u2013 konfiguratsioon. V\u00e4ljad, mille juures on TO_VERIFY, vajavad kinnitust enne avaldamist. T\u00fchi (null) v\u00e4\u00e4rtus t\u00e4hendab: \u00e4ra n\u00e4ita \/ kasuta vaikimisi k\u00e4itumist.\",\"site\":\"valgeranna\",\"lang\":\"en\",\"heroSelector\":\".ngg-in\",\"bgSelector\":\".ngg-in__bgs\",\"contentSelector\":\".ngg-x-pill, .ngg-x-hero__t, .ngg-in__ask, .ngg-in__tabs, .ngg-in__panel, .ngg-in__today\",\"badgeTop\":\"clamp(84px, 13vh, 132px)\",\"bookingTarget\":\"_self\",\"provider\":{\"id\":\"met\",\"name\":\"MET Norway\",\"endpoint\":\"https:\/\/api.met.no\/weatherapi\/locationforecast\/2.0\/complete\",\"proxyEndpoint\":null,\"_proxyNote\":\"Kui serveripoolne vahem\u00e4luga proxy on olemas (sama JSON-vorming), pane selle URL siia. Proxy saab lisada User-Agenti ja If-Modified-Since p\u00e4ise; brauser seda teha ei saa.\",\"timeoutMs\":8000,\"minCacheMinutes\":10,\"defaultCacheMinutes\":30,\"staleAfterMinutes\":120,\"hideAfterMinutes\":240,\"licenseName\":\"CC BY 4.0\",\"licenseUrl\":\"https:\/\/creativecommons.org\/licenses\/by\/4.0\/\",\"sourceUrl\":\"https:\/\/api.met.no\/\"},\"courses\":{\"valgeranna\":{\"name\":\"Valgeranna Golf\",\"short\":\"Valgeranna\",\"lat\":58.39,\"lon\":24.3719,\"altitude\":null,\"coordsVerified\":true,\"TO_VERIFY\":\"KINNITATUD 11.10 (research.md p1): klubimaja Google Place 58.3899835\/24.3719459 (wbg.ee \/kontakt\/) = Chronogolf 58.39023\/24.371825. OSM v\u00e4ljaku keskpunkt 58.3947\/24.3832 (~0,9 km). altitude null.\",\"booking\":\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget&source=club\",\"hasRange\":true,\"rangeLink\":\"https:\/\/www.wbg.ee\/en\/prices\/#range\",\"_rangeLinkNote\":\"KINNITATUD: wbg.ee \/hinnakiri\/#range (EN \/en\/prices\/#range) on live'is olemas.\",\"statusLink\":{\"href\":null,\"modalTarget\":\"#infoModal\"},\"photos\":{\"default\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/03\/valgeranna_51499715609_o-2400x1349-1-2048x1151.jpg\",\"night\":null,\"_note\":\"Ainult Valgeranna fotod: 1193 p\u00e4ev, 4633 loojang, 1712 pehme \u00f5htu, 5791 pilves. \u00d6\u00f6 = 1712 tumendatud \u00f6\u00f6-tooniga (Valgeranna \u00f6\u00f6fotot pole). Rae fotosid ei kasutata.\",\"states\":{\"day\":{\"src\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/03\/valgeranna_51499715609_o-2400x1349-1-2048x1151.jpg\",\"position\":\"50% 50%\"},\"golden\":{\"src\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg\",\"position\":\"50% 50%\"},\"evening\":{\"src\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/05\/valgeranna_51499222653_o-1536x1534.jpg\",\"position\":\"50% 55%\"},\"overcast\":{\"src\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2025\/11\/490800000_1208955107905956_5354428887820793106_n-1536x1025.jpg\",\"position\":\"50% 45%\"},\"night\":{\"src\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/05\/valgeranna_51499222653_o-1536x1534.jpg\",\"position\":\"50% 55%\"}}}}},\"symbolMap\":{\"clearsky\":{\"sky\":\"clear\",\"precip\":\"none\"},\"fair\":{\"sky\":\"clear\",\"precip\":\"none\"},\"partlycloudy\":{\"sky\":\"partly\",\"precip\":\"none\"},\"cloudy\":{\"sky\":\"cloudy\",\"precip\":\"none\"},\"fog\":{\"sky\":\"fog\",\"precip\":\"none\"},\"rain\":{\"sky\":\"cloudy\",\"precip\":\"rain\"},\"sleet\":{\"sky\":\"cloudy\",\"precip\":\"sleet\"},\"snow\":{\"sky\":\"cloudy\",\"precip\":\"snow\"},\"lightIntensity\":0.45,\"normalIntensity\":0.75,\"heavyIntensity\":1,\"lightRainIs\":\"drizzle\",\"showersSky\":\"partly\"},\"phases\":{\"nightBelow\":-6,\"dawnBelow\":6,\"goldenBelow\":7},\"thresholds\":{\"windyMs\":6,\"windyGustMs\":10,\"strongWindMs\":10,\"strongGustMs\":14,\"thunderProb\":30},\"effects\":{\"enabledByDefault\":true,\"storageKey\":\"ngg-lv-fx\",\"intensity\":{\"grade\":1,\"spots\":1,\"clouds\":1,\"fog\":1,\"rain\":1,\"snow\":1,\"flag\":1},\"maxParticles\":220,\"dprCap\":1.5},\"activities\":{\"9\":{\"minutes\":135,\"showDaylight\":true,\"_note\":\"hinnanguline\"},\"18\":{\"minutes\":270,\"showDaylight\":true,\"_note\":\"hinnanguline\"},\"range\":{\"minutes\":60,\"showDaylight\":false,\"_note\":\"hinnanguline; p\u00e4evavalguse varu ei n\u00e4idata, sest range'i valgustus on kinnitamata\"}},\"defaultActivity\":\"18\",\"timeline\":{\"firstHour\":6,\"lastHour\":21,\"precipWindowHours\":3},\"status\":{\"valgeranna\":null},\"_statusShape\":\"{ notice: {text, level:'closed'|'info'} | null, course: {text, open:true|false|null} | null, range: {text, open:true|false|null} | null, source: 'Rae ACF \u201eT\u00e4na Raes\u201c' }. Ainult kinnitatud haldusallikast. Ilmast avatust EI j\u00e4reldata.\",\"statusSources\":{\"rae\":\"Rae ACF \u201eT\u00e4na Raes\u201c read ja Info aken (integreerija t\u00e4idab: NGGLV.setStatus('rae', {...}))\",\"valgeranna\":\"Valgeranna jaluse #infoModal (integreerija t\u00e4idab: NGGLV.setStatus('valgeranna', {...}))\"},\"texts\":{\"et\":{\"eyebrow\":\"Hetkeilma hinnang\",\"title\":\"T\u00e4na v\u00e4ljakul.\",\"courseLabel\":\"V\u00e4ljak\",\"feels\":\"Tajutav\",\"wind\":\"Tuul\",\"gusts\":\"Puhangud\",\"gustsUpTo\":\"puhangud kuni {v}\",\"windBlows\":\"puhub {dir}\",\"windCalm\":\"tuulevaikus\",\"windAria\":\"Tuul {v}, {gust}puhub {dir}. Nool n\u00e4itab, kuhu tuul puhub.\",\"precipNext\":\"Sademete t\u00f5en\u00e4osus j\u00e4rgmise {h} h jooksul\",\"precipUpTo\":\"kuni {v}\",\"precipAmount\":\"sademeid {v} mm\",\"sunset\":\"P\u00e4ike loojub\",\"sunrise\":\"P\u00e4ike t\u00f5useb\",\"statusCourse\":\"V\u00e4ljak\",\"statusRange\":\"Range\",\"official\":\"Ametlik v\u00e4ljakuinfo\",\"updated\":\"Uuendatud {t}\",\"source\":\"Prognoos: {src}\",\"stale\":\"andmed v\u00f5ivad olla vananenud\",\"modelNote\":\"Mudeli hinnang, mitte v\u00e4ljakul m\u00f5\u00f5detud. Foto on illustreeriv.\",\"detailsOpen\":\"N\u00e4ita detaile\",\"detailsClose\":\"Peida detailid\",\"fxOn\":\"Ilmaefektid sees\",\"fxOff\":\"Ilmaefektid v\u00e4ljas\",\"missing\":\"andmed puuduvad\",\"loading\":\"Laadin prognoosi \u2026\",\"error\":\"Ilmaandmed pole hetkel saadaval. Tiiaegu saad vaadata ja broneerida tavap\u00e4raselt.\",\"planTitle\":\"Millal t\u00e4na m\u00e4ngida?\",\"activityLabel\":\"Mida m\u00e4ngid?\",\"dayLabel\":\"P\u00e4ev\",\"today\":\"T\u00e4na\",\"tomorrow\":\"Homme\",\"startLabel\":\"Algusaeg\",\"startAria\":\"Algusaeg, kell {t}\",\"finish\":\"L\u00f5pp umbes {t}\",\"estimate\":\"hinnanguline\",\"durationNote\":\"Kestus on hinnanguline: {d}.\",\"daylightPlus\":\"P\u00e4ike loojub {t}. P\u00e4rast l\u00f5ppu j\u00e4\u00e4b p\u00e4evavalgust umbes {d}.\",\"daylightMinus\":\"P\u00e4ike loojub {t}. L\u00f5pp j\u00e4\u00e4b umbes {d} p\u00e4rast p\u00e4ikeseloojangut.\",\"daylightAfterDark\":\"P\u00e4ike on loojunud ({t}).\",\"forecastBadge\":\"Prognoos \u00b7 {d} {t}\",\"back\":\"Tagasi hetkeilma juurde\",\"ctaTee\":\"Vaata tiiaegu\",\"ctaRange\":\"Vaata range'i infot\",\"ctaNote\":\"Prognoos ei n\u00e4ita vabu tiiaegu. Vabad ajad n\u00e4ed broneerimiss\u00fcsteemis.\",\"noSlotsToday\":\"T\u00e4naseks pole prognoosis enam algusaegu. Vaata homset.\",\"windowTemp\":\"Temperatuur\",\"windowWind\":\"Tuul\",\"windowPrecip\":\"Sademete t\u00f5en\u00e4osus\",\"testMode\":\"Testre\u017eiim\",\"hole9\":\"9 rada\",\"hole18\":\"18 rada\",\"range\":\"Range\",\"dirs\":[\"p\u00f5hjast\",\"kirdest\",\"idast\",\"kagust\",\"l\u00f5unast\",\"edelast\",\"l\u00e4\u00e4nest\",\"loodest\"],\"wd\":[\"P\",\"E\",\"T\",\"K\",\"N\",\"R\",\"L\"],\"cond\":{\"clearsky\":\"Selge\",\"fair\":\"Peamiselt selge\",\"partlycloudy\":\"Vahelduv pilvisus\",\"cloudy\":\"Pilves\",\"fog\":\"Udu\",\"rain\":\"vihm\",\"sleet\":\"l\u00f6rts\",\"snow\":\"lumesadu\",\"rainshowers\":\"vihmahood\",\"sleetshowers\":\"l\u00f6rtsihood\",\"snowshowers\":\"lumehood\",\"light\":\"n\u00f5rk\",\"lightPl\":\"n\u00f5rgad\",\"heavy\":\"tugev\",\"heavyPl\":\"tugevad\",\"thunder\":\"ja \u00e4ike\"},\"autoTomorrow\":\"T\u00e4naseks pole prognoosis enam algusaegu. Siin on homne prognoos.\",\"planTitleTomorrow\":\"Millal homme m\u00e4ngida?\",\"autoTomorrowLight\":\"T\u00e4naseks ei j\u00f5ua valitud ringi enne p\u00e4ikeseloojangut l\u00f5petada. Siin on homne prognoos.\",\"stamp\":\"Kella {h} prognoos, koostatud {m}, laaditud {t}\",\"eyebrowDated\":\"{d} \u00b7 hetkeilma hinnang\"},\"en\":{\"eyebrow\":\"Current weather estimate\",\"title\":\"On the course today.\",\"courseLabel\":\"Course\",\"feels\":\"Feels like\",\"wind\":\"Wind\",\"gusts\":\"Gusts\",\"gustsUpTo\":\"gusts up to {v}\",\"windBlows\":\"from the {dir}\",\"windCalm\":\"calm\",\"windAria\":\"Wind {v}, {gust}blowing from the {dir}. The arrow shows where the wind is blowing.\",\"precipNext\":\"Chance of precipitation, next {h} h\",\"precipUpTo\":\"up to {v}\",\"precipAmount\":\"{v} mm of precipitation\",\"sunset\":\"Sunset\",\"sunrise\":\"Sunrise\",\"statusCourse\":\"Course\",\"statusRange\":\"Range\",\"official\":\"Official course info\",\"updated\":\"Updated {t}\",\"source\":\"Forecast: {src}\",\"stale\":\"data may be out of date\",\"modelNote\":\"Model estimate, not measured on the course. The photo is illustrative.\",\"detailsOpen\":\"Show details\",\"detailsClose\":\"Hide details\",\"fxOn\":\"Weather effects on\",\"fxOff\":\"Weather effects off\",\"missing\":\"no data\",\"loading\":\"Loading the forecast \u2026\",\"error\":\"Weather data is not available right now. You can still view and book tee times as usual.\",\"planTitle\":\"When to play today?\",\"activityLabel\":\"What are you playing?\",\"dayLabel\":\"Day\",\"today\":\"Today\",\"tomorrow\":\"Tomorrow\",\"startLabel\":\"Start time\",\"startAria\":\"Start time, {t}\",\"finish\":\"Finish around {t}\",\"estimate\":\"estimate\",\"durationNote\":\"The duration is an estimate: {d}.\",\"daylightPlus\":\"Sunset is at {t}. About {d} of daylight remains after you finish.\",\"daylightMinus\":\"Sunset is at {t}. You finish about {d} after sunset.\",\"daylightAfterDark\":\"The sun has set ({t}).\",\"forecastBadge\":\"Forecast \u00b7 {d} {t}\",\"back\":\"Back to current weather\",\"ctaTee\":\"See tee times\",\"ctaRange\":\"See range info\",\"ctaNote\":\"The forecast does not show free tee times. You will see them in the booking system.\",\"noSlotsToday\":\"No more start times in today's forecast. Check tomorrow.\",\"windowTemp\":\"Temperature\",\"windowWind\":\"Wind\",\"windowPrecip\":\"Chance of precipitation\",\"testMode\":\"Test mode\",\"hole9\":\"9 holes\",\"hole18\":\"18 holes\",\"range\":\"Range\",\"dirs\":[\"north\",\"northeast\",\"east\",\"southeast\",\"south\",\"southwest\",\"west\",\"northwest\"],\"wd\":[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"],\"cond\":{\"clearsky\":\"Clear\",\"fair\":\"Mostly clear\",\"partlycloudy\":\"Partly cloudy\",\"cloudy\":\"Cloudy\",\"fog\":\"Fog\",\"rain\":\"rain\",\"sleet\":\"sleet\",\"snow\":\"snow\",\"rainshowers\":\"rain showers\",\"sleetshowers\":\"sleet showers\",\"snowshowers\":\"snow showers\",\"light\":\"light\",\"lightPl\":\"light\",\"heavy\":\"heavy\",\"heavyPl\":\"heavy\",\"thunder\":\"and thunder\"},\"autoTomorrow\":\"No more start times in today's forecast. Here is tomorrow's forecast.\",\"planTitleTomorrow\":\"When to play tomorrow?\",\"autoTomorrowLight\":\"The selected round would not finish before sunset today. Here is tomorrow\u2019s forecast.\",\"stamp\":\"Forecast for {h}, issued {m}, loaded {t}\",\"eyebrowDated\":\"{d} \u00b7 current weather estimate\"}},\"copy\":{\"et\":{\"sunny\":[\"T\u00e4na v\u00f5iks kontorist varem lahkuda.\",\"P\u00e4ike on v\u00e4ljas. Sinu ring v\u00f5iks ka olla.\"],\"evening\":[\"P\u00e4ev saab l\u00e4bi. Trenn veel mitte.\",\"\u00d5htune valgus on v\u00e4ljakul parim.\"],\"morning\":[\"Hommik on vaikne. Hea aeg varajaseks ringiks.\"],\"cloudy\":[\"Pilves ja rahulik. Pall lendab sama h\u00e4sti.\",\"Pilved on \u00fcleval, m\u00e4ng k\u00e4ib all.\"],\"windy\":[\"T\u00e4na on ka tuulel m\u00e4nguplaan.\",\"Tuul m\u00e4ngib kaasa. Vali l\u00f6\u00f6gid targalt.\"],\"drizzle\":[\"V\u00e4ike vihm. Suured plaanid.\",\"Natuke niiske. V\u00f5ta vihmajope kaasa.\"],\"rain\":[\"Vihmane ilm. Vaata l\u00e4hitundide prognoosi.\"],\"rainEvening\":[\"Vihmane \u00f5htu. Vaata homset prognoosi.\"],\"fog\":[\"Udune ilm. Vaata enne tulekut prognoosi.\"],\"night\":[\"V\u00e4ljakul on pime. Vali homseks hea algusaeg.\"],\"snow\":[\"Prognoosis on lumi. Enne tulekut vaata ametlikku v\u00e4ljakuinfot.\"],\"strongwind\":[\"Prognoosis on tugevad tuulepuhangud. Enne tulekut vaata ametlikku v\u00e4ljakuinfot.\"],\"thunder\":[\"Prognoosis on \u00e4ike. Enne tulekut vaata ametlikku v\u00e4ljakuinfot.\"],\"neutral\":[\"Vaata tiiaegu ja planeeri oma ring.\"]},\"en\":{\"sunny\":[\"Today might be a day to leave the office early.\",\"The sun is out. Your round could be too.\"],\"evening\":[\"The workday is ending. Practice is not.\",\"Evening light is the best light on the course.\"],\"morning\":[\"A quiet morning. A good time for an early round.\"],\"cloudy\":[\"Cloudy and calm. The ball flies just as well.\",\"Clouds up high, the game down below.\"],\"windy\":[\"Today the wind has a game plan too.\",\"The wind is playing along. Choose your shots wisely.\"],\"drizzle\":[\"A little rain. Big plans.\",\"A bit damp. Bring a rain jacket.\"],\"rain\":[\"Rainy weather. Check the forecast for the next hours.\"],\"rainEvening\":[\"A rainy evening. Check the forecast for tomorrow.\"],\"fog\":[\"Foggy weather. Check the forecast before you come.\"],\"night\":[\"It's dark on the course. Pick a good start time for tomorrow.\"],\"snow\":[\"Snow is in the forecast. Check the official course info before you come.\"],\"strongwind\":[\"Strong gusts are in the forecast. Check the official course info before you come.\"],\"thunder\":[\"Thunder is in the forecast. Check the official course info before you come.\"],\"neutral\":[\"See tee times and plan your round.\"]}},\"copyOverrides\":{},\"playfulBuckets\":[\"sunny\",\"evening\",\"morning\",\"cloudy\",\"windy\",\"drizzle\"],\"fullFxWhen\":\".ngg-in__bg.is-on[data-k=\\\"play\\\"]\",\"bookingDateHash\":false,\"_bookingDateHashNote\":\"Chronogolf ei dokumenteeri kuup\u00e4eva parameetrit. Brauseris 11.10 n\u00e4htud '#?date=YYYY-MM-DD' t\u00f6\u00f6tab, kuid on dokumenteerimata \u2013 l\u00fclita true ainult omaniku n\u00f5usolekul. Kellaaega ei edastata.\",\"_fullFxWhenNote\":\"Valikuline selektor hero sees. Kui see EI leia elementi (nt WBG sakk n\u00e4itab inimeste fotot), j\u00e4\u00e4b alles ainult toon: pole valguslaike, pilvevarje ega sademeid. WBG: .ngg-in__bg.is-on[data-k=\\\"play\\\"]\",\"layout\":null,\"courseSwitch\":false,\"statusRows\":true,\"planSelector\":null,\"courseLink\":null,\"_layoutNote\":\"layout:'bar' = kompaktne T\u00e4na-kaart (hero all, ametlikud read + jalus); courseSwitch:false = ainult koduv\u00e4ljak (teise v\u00e4ljaku ilma\/fotot pole); statusRows:false = V\u00e4ljak\/Range read peidetud, kui ametlikud read on samas kaardis kiipidena; planSelector = eraldi sektsioon \u201eMillal t\u00e4na m\u00e4ngida?\u201c jaoks; courseLink = {et:{href,text},en:{href,text}} lihtlink teisele v\u00e4ljakule.\"}<\/script>\n<div class=\"ngg-lv-fallback\"><a class=\"ngg-lv-btn ngg-lv-btn--main\" href=\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget&amp;source=club\">See tee times<\/a><\/div>\n<\/section>\n<script id=\"ngg-lv-js\">\n\/* Elav v\u00e4ljak (ngg-lv) v1.2.0 \u2013 Rae Golf ja Valgeranna Golf. Plain JS, no libraries.\nRules for WordPress inline use: this file must not contain the double-ampersand operator or any raw ampersand character.\nURLs are joined with AMP = String.fromCharCode(38). *\/\n(function () {\n'use strict';\nvar W = window, D = document;\nif (W.NGGLV) { if (W.NGGLV.booted) { return; } }\nvar AMP = String.fromCharCode(38);\nvar TZ = 'Europe\/Tallinn';\nvar DEFAULTS = {\"version\":\"1.2.0\",\"_doc\":\"Elav v\u00e4ljak \u2013 konfiguratsioon. V\u00e4ljad, mille juures on TO_VERIFY, vajavad kinnitust enne avaldamist. T\u00fchi (null) v\u00e4\u00e4rtus t\u00e4hendab: \u00e4ra n\u00e4ita \/ kasuta vaikimisi k\u00e4itumist.\",\"site\":\"rae\",\"lang\":\"auto\",\"heroSelector\":\".ngg-x-hero\",\"bgSelector\":\".ngg-x-hero__bg\",\"contentSelector\":\".ngg-x-hero__t, .ngg-x-hero__lead, .ngg-x-hero__stats, .ngg-x-btns, .ngg-x-pill, h1, h2, p, a, button, ul, li\",\"badgeTop\":\"clamp(84px, 13vh, 132px)\",\"bookingTarget\":\"_self\",\"provider\":{\"id\":\"met\",\"name\":\"MET Norway\",\"endpoint\":\"https:\/\/api.met.no\/weatherapi\/locationforecast\/2.0\/complete\",\"proxyEndpoint\":null,\"_proxyNote\":\"Kui serveripoolne vahem\u00e4luga proxy on olemas (sama JSON-vorming), pane selle URL siia. Proxy saab lisada User-Agenti ja If-Modified-Since p\u00e4ise; brauser seda teha ei saa.\",\"timeoutMs\":8000,\"minCacheMinutes\":10,\"defaultCacheMinutes\":30,\"staleAfterMinutes\":120,\"hideAfterMinutes\":240,\"licenseName\":\"CC BY 4.0\",\"licenseUrl\":\"https:\/\/creativecommons.org\/licenses\/by\/4.0\/\",\"sourceUrl\":\"https:\/\/api.met.no\/\"},\"courses\":{\"rae\":{\"name\":\"Rae Golf\",\"short\":\"Rae\",\"lat\":59.3085,\"lon\":24.9736,\"altitude\":null,\"coordsVerified\":true,\"TO_VERIFY\":\"KINNITATUD 11.10 (research.md p1): raegolf.ee \/kontakt\/ ACF kaart 59.308546\/24.9736292 = OSM golf_course way 238789194 keskpunkt. Klubimaja (Chronogolf) 59.3079\/24.9759. altitude: kinnitatud allikat pole -\\u003e null.\",\"booking\":\"https:\/\/www.chronogolf.com\/club\/18975\/widget?medium=widget\\u0026source=club\",\"hasRange\":true,\"rangeLink\":\"https:\/\/raegolf.ee\/trackman-range\/\",\"statusLink\":{\"href\":null,\"modalTarget\":\"#dropdown-modal-2\",\"TO_VERIFY\":\"KINNITATUD: Rae Info aken #dropdown-modal-2 (Bootstrap 4: data-toggle\/data-target, mitte data-bs-*). Ametlikud read: ACF section-about (.section--about .list--checks li).\"},\"photos\":{\"default\":\"https:\/\/raegolf.ee\/static\/DJI_20250905171117_0026_D-1536x1152.jpg\",\"night\":\"https:\/\/raegolf.ee\/static\/IMG_0853-1536x2048.jpg\",\"nightPosition\":\"50% 70%\",\"_TO_VERIFY\":\"KINNITATUD (research.md p4): default = id 79366 Rae droon 2025 (p\u00e4ev, inimesteta); night = id 78597 valgustatud TrackMan range h\u00e4maruses 27.10.2025 (p\u00fcstine foto, k\u00e4rbi 50% 70%).\"}},\"valgeranna\":{\"name\":\"Valgeranna Golf\",\"short\":\"Valgeranna\",\"lat\":58.39,\"lon\":24.3719,\"altitude\":null,\"coordsVerified\":true,\"TO_VERIFY\":\"KINNITATUD 11.10 (research.md p1): klubimaja Google Place 58.3899835\/24.3719459 (wbg.ee \/kontakt\/) = Chronogolf 58.39023\/24.371825. OSM v\u00e4ljaku keskpunkt 58.3947\/24.3832 (~0,9 km). altitude null.\",\"booking\":\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget\\u0026source=club\",\"hasRange\":true,\"rangeLink\":\"https:\/\/www.wbg.ee\/hinnakiri\/#range\",\"_rangeLinkNote\":\"KINNITATUD: wbg.ee \/hinnakiri\/#range (EN \/en\/prices\/#range) on live'is olemas.\",\"statusLink\":{\"href\":null,\"modalTarget\":\"#infoModal\"},\"photos\":{\"default\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/03\/valgeranna_51499715609_o-2400x1349-1-2048x1151.jpg\",\"night\":null,\"_note\":\"default = id 1193 Valgeranna droon (p\u00e4ev, inimesteta). Valgustatud range'i \/ \u00f6\u00f6 fotot Valgeranna meedias ei ole -\\u003e night null.\"}}},\"symbolMap\":{\"clearsky\":{\"sky\":\"clear\",\"precip\":\"none\"},\"fair\":{\"sky\":\"clear\",\"precip\":\"none\"},\"partlycloudy\":{\"sky\":\"partly\",\"precip\":\"none\"},\"cloudy\":{\"sky\":\"cloudy\",\"precip\":\"none\"},\"fog\":{\"sky\":\"fog\",\"precip\":\"none\"},\"rain\":{\"sky\":\"cloudy\",\"precip\":\"rain\"},\"sleet\":{\"sky\":\"cloudy\",\"precip\":\"sleet\"},\"snow\":{\"sky\":\"cloudy\",\"precip\":\"snow\"},\"lightIntensity\":0.45,\"normalIntensity\":0.75,\"heavyIntensity\":1,\"lightRainIs\":\"drizzle\",\"showersSky\":\"partly\"},\"phases\":{\"nightBelow\":-6,\"dawnBelow\":6,\"goldenBelow\":7,\"nightPhotoBelow\":-4},\"thresholds\":{\"windyMs\":6,\"windyGustMs\":10,\"strongWindMs\":10,\"strongGustMs\":14,\"thunderProb\":30},\"effects\":{\"enabledByDefault\":true,\"storageKey\":\"ngg-lv-fx\",\"intensity\":{\"grade\":1,\"spots\":1,\"clouds\":1,\"fog\":1,\"rain\":1,\"snow\":1,\"flag\":1},\"maxParticles\":220,\"dprCap\":1.5,\"minBrightness\":0.85,\"maxCoolA\":0.18,\"maxShadowA\":0.35},\"activities\":{\"9\":{\"minutes\":135,\"showDaylight\":true,\"_note\":\"hinnanguline\"},\"18\":{\"minutes\":270,\"showDaylight\":true,\"_note\":\"hinnanguline\"},\"range\":{\"minutes\":60,\"showDaylight\":false,\"_note\":\"hinnanguline; p\u00e4evavalguse varu ei n\u00e4idata, sest range'i valgustus on kinnitamata\"}},\"defaultActivity\":\"18\",\"timeline\":{\"firstHour\":6,\"lastHour\":21,\"precipWindowHours\":3},\"status\":{\"rae\":null,\"valgeranna\":null},\"_statusShape\":\"{ notice: {text, level:'closed'|'info'} | null, course: {text, open:true|false|null} | null, range: {text, open:true|false|null} | null, source: 'Rae ACF \u201eT\u00e4na Raes\u201c' }. Ainult kinnitatud haldusallikast. Ilmast avatust EI j\u00e4reldata.\",\"statusSources\":{\"rae\":\"Rae ACF \u201eT\u00e4na Raes\u201c read ja Info aken (integreerija t\u00e4idab: NGGLV.setStatus('rae', {...}))\",\"valgeranna\":\"Valgeranna jaluse #infoModal (integreerija t\u00e4idab: NGGLV.setStatus('valgeranna', {...}))\"},\"texts\":{\"et\":{\"eyebrow\":\"Hetkeilma hinnang\",\"title\":\"T\u00e4na v\u00e4ljakul.\",\"courseLabel\":\"V\u00e4ljak\",\"feels\":\"Tajutav\",\"wind\":\"Tuul\",\"gusts\":\"Puhangud\",\"gustsUpTo\":\"puhangud kuni {v}\",\"windBlows\":\"puhub {dir}\",\"windCalm\":\"tuulevaikus\",\"windAria\":\"Tuul {v}, {gust}puhub {dir}. Nool n\u00e4itab, kuhu tuul puhub.\",\"precipNext\":\"Sademete t\u00f5en\u00e4osus j\u00e4rgmise {h} h jooksul\",\"precipUpTo\":\"kuni {v}\",\"precipAmount\":\"sademeid {v} mm\",\"sunset\":\"P\u00e4ike loojub\",\"sunrise\":\"P\u00e4ike t\u00f5useb\",\"statusCourse\":\"V\u00e4ljak\",\"statusRange\":\"Range\",\"official\":\"Ametlik v\u00e4ljakuinfo\",\"updated\":\"Uuendatud {t}\",\"source\":\"Prognoos: {src}\",\"stale\":\"andmed v\u00f5ivad olla vananenud\",\"modelNote\":\"Mudeli hinnang, mitte v\u00e4ljakul m\u00f5\u00f5detud. Foto on illustreeriv.\",\"detailsOpen\":\"N\u00e4ita detaile\",\"detailsClose\":\"Peida detailid\",\"fxOn\":\"Ilmaefektid sees\",\"fxOff\":\"Ilmaefektid v\u00e4ljas\",\"missing\":\"andmed puuduvad\",\"loading\":\"Laadin prognoosi \u2026\",\"error\":\"Ilmaandmed pole hetkel saadaval. Tiiaegu saad vaadata ja broneerida tavap\u00e4raselt.\",\"planTitle\":\"Millal t\u00e4na m\u00e4ngida?\",\"activityLabel\":\"Mida m\u00e4ngid?\",\"dayLabel\":\"P\u00e4ev\",\"today\":\"T\u00e4na\",\"tomorrow\":\"Homme\",\"startLabel\":\"Algusaeg\",\"startAria\":\"Algusaeg, kell {t}\",\"finish\":\"L\u00f5pp umbes {t}\",\"estimate\":\"hinnanguline\",\"durationNote\":\"Kestus on hinnanguline: {d}.\",\"daylightPlus\":\"P\u00e4ike loojub {t}. P\u00e4rast l\u00f5ppu j\u00e4\u00e4b p\u00e4evavalgust umbes {d}.\",\"daylightMinus\":\"P\u00e4ike loojub {t}. L\u00f5pp j\u00e4\u00e4b umbes {d} p\u00e4rast p\u00e4ikeseloojangut.\",\"daylightAfterDark\":\"P\u00e4ike on loojunud ({t}).\",\"forecastBadge\":\"Prognoos \u00b7 {d} {t}\",\"back\":\"Tagasi hetkeilma juurde\",\"ctaTee\":\"Vaata tiiaegu\",\"ctaRange\":\"Vaata range'i infot\",\"ctaNote\":\"Prognoos ei n\u00e4ita vabu tiiaegu. Vabad ajad n\u00e4ed broneerimiss\u00fcsteemis.\",\"noSlotsToday\":\"T\u00e4naseks pole prognoosis enam algusaegu. Vaata homset.\",\"windowTemp\":\"Temperatuur\",\"windowWind\":\"Tuul\",\"windowPrecip\":\"Sademete t\u00f5en\u00e4osus\",\"testMode\":\"Testre\u017eiim\",\"hole9\":\"9 rada\",\"hole18\":\"18 rada\",\"range\":\"Range\",\"dirs\":[\"p\u00f5hjast\",\"kirdest\",\"idast\",\"kagust\",\"l\u00f5unast\",\"edelast\",\"l\u00e4\u00e4nest\",\"loodest\"],\"wd\":[\"P\",\"E\",\"T\",\"K\",\"N\",\"R\",\"L\"],\"cond\":{\"clearsky\":\"Selge\",\"fair\":\"Peamiselt selge\",\"partlycloudy\":\"Vahelduv pilvisus\",\"cloudy\":\"Pilves\",\"fog\":\"Udu\",\"rain\":\"vihm\",\"sleet\":\"l\u00f6rts\",\"snow\":\"lumesadu\",\"rainshowers\":\"vihmahood\",\"sleetshowers\":\"l\u00f6rtsihood\",\"snowshowers\":\"lumehood\",\"light\":\"n\u00f5rk\",\"lightPl\":\"n\u00f5rgad\",\"heavy\":\"tugev\",\"heavyPl\":\"tugevad\",\"thunder\":\"ja \u00e4ike\"},\"autoTomorrow\":\"T\u00e4naseks pole prognoosis enam algusaegu. Siin on homne prognoos.\",\"planTitleTomorrow\":\"Millal homme m\u00e4ngida?\",\"autoTomorrowLight\":\"T\u00e4naseks ei j\u00f5ua valitud ringi enne p\u00e4ikeseloojangut l\u00f5petada. Siin on homne prognoos.\",\"stamp\":\"Kella {h} prognoos, koostatud {m}, laaditud {t}\",\"eyebrowDated\":\"{d} \u00b7 hetkeilma hinnang\"},\"en\":{\"eyebrow\":\"Current weather estimate\",\"title\":\"On the course today.\",\"courseLabel\":\"Course\",\"feels\":\"Feels like\",\"wind\":\"Wind\",\"gusts\":\"Gusts\",\"gustsUpTo\":\"gusts up to {v}\",\"windBlows\":\"from the {dir}\",\"windCalm\":\"calm\",\"windAria\":\"Wind {v}, {gust}blowing from the {dir}. The arrow shows where the wind is blowing.\",\"precipNext\":\"Chance of precipitation, next {h} h\",\"precipUpTo\":\"up to {v}\",\"precipAmount\":\"{v} mm of precipitation\",\"sunset\":\"Sunset\",\"sunrise\":\"Sunrise\",\"statusCourse\":\"Course\",\"statusRange\":\"Range\",\"official\":\"Official course info\",\"updated\":\"Updated {t}\",\"source\":\"Forecast: {src}\",\"stale\":\"data may be out of date\",\"modelNote\":\"Model estimate, not measured on the course. The photo is illustrative.\",\"detailsOpen\":\"Show details\",\"detailsClose\":\"Hide details\",\"fxOn\":\"Weather effects on\",\"fxOff\":\"Weather effects off\",\"missing\":\"no data\",\"loading\":\"Loading the forecast \u2026\",\"error\":\"Weather data is not available right now. You can still view and book tee times as usual.\",\"planTitle\":\"When to play today?\",\"activityLabel\":\"What are you playing?\",\"dayLabel\":\"Day\",\"today\":\"Today\",\"tomorrow\":\"Tomorrow\",\"startLabel\":\"Start time\",\"startAria\":\"Start time, {t}\",\"finish\":\"Finish around {t}\",\"estimate\":\"estimate\",\"durationNote\":\"The duration is an estimate: {d}.\",\"daylightPlus\":\"Sunset is at {t}. About {d} of daylight remains after you finish.\",\"daylightMinus\":\"Sunset is at {t}. You finish about {d} after sunset.\",\"daylightAfterDark\":\"The sun has set ({t}).\",\"forecastBadge\":\"Forecast \u00b7 {d} {t}\",\"back\":\"Back to current weather\",\"ctaTee\":\"See tee times\",\"ctaRange\":\"See range info\",\"ctaNote\":\"The forecast does not show free tee times. You will see them in the booking system.\",\"noSlotsToday\":\"No more start times in today's forecast. Check tomorrow.\",\"windowTemp\":\"Temperature\",\"windowWind\":\"Wind\",\"windowPrecip\":\"Chance of precipitation\",\"testMode\":\"Test mode\",\"hole9\":\"9 holes\",\"hole18\":\"18 holes\",\"range\":\"Range\",\"dirs\":[\"north\",\"northeast\",\"east\",\"southeast\",\"south\",\"southwest\",\"west\",\"northwest\"],\"wd\":[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"],\"cond\":{\"clearsky\":\"Clear\",\"fair\":\"Mostly clear\",\"partlycloudy\":\"Partly cloudy\",\"cloudy\":\"Cloudy\",\"fog\":\"Fog\",\"rain\":\"rain\",\"sleet\":\"sleet\",\"snow\":\"snow\",\"rainshowers\":\"rain showers\",\"sleetshowers\":\"sleet showers\",\"snowshowers\":\"snow showers\",\"light\":\"light\",\"lightPl\":\"light\",\"heavy\":\"heavy\",\"heavyPl\":\"heavy\",\"thunder\":\"and thunder\"},\"autoTomorrow\":\"No more start times in today's forecast. Here is tomorrow's forecast.\",\"planTitleTomorrow\":\"When to play tomorrow?\",\"autoTomorrowLight\":\"The selected round would not finish before sunset today. Here is tomorrow\u2019s forecast.\",\"stamp\":\"Forecast for {h}, issued {m}, loaded {t}\",\"eyebrowDated\":\"{d} \u00b7 current weather estimate\"}},\"copy\":{\"et\":{\"sunny\":[\"T\u00e4na v\u00f5iks kontorist varem lahkuda.\",\"P\u00e4ike on v\u00e4ljas. Sinu ring v\u00f5iks ka olla.\"],\"evening\":[\"P\u00e4ev saab l\u00e4bi. Trenn veel mitte.\",\"\u00d5htune valgus on v\u00e4ljakul parim.\"],\"morning\":[\"Hommik on vaikne. Esimene tiiaeg ootab.\"],\"cloudy\":[\"Pilves ja rahulik. Pall lendab sama h\u00e4sti.\",\"Pilved on \u00fcleval, m\u00e4ng k\u00e4ib all.\"],\"windy\":[\"T\u00e4na on ka tuulel m\u00e4nguplaan.\",\"Tuul m\u00e4ngib kaasa. Vali l\u00f6\u00f6gid targalt.\"],\"drizzle\":[\"V\u00e4ike vihm. Suured plaanid.\",\"Natuke niiske, aga m\u00e4ngitav.\"],\"rain\":[\"Vihmane ilm. Vaata l\u00e4hitundide prognoosi.\"],\"rainEvening\":[\"Vihmane \u00f5htu. Vaata homset prognoosi.\"],\"fog\":[\"Udune ilm. Vaata enne tulekut prognoosi.\"],\"night\":[\"\u00d5htu on k\u00e4es. Vali homseks hea algusaeg.\"],\"snow\":[\"Prognoosis on lumi. Enne tulekut vaata ametlikku v\u00e4ljakuinfot.\"],\"strongwind\":[\"Prognoosis on tugevad tuulepuhangud. Enne tulekut vaata ametlikku v\u00e4ljakuinfot.\"],\"thunder\":[\"Prognoosis on \u00e4ike. Enne tulekut vaata ametlikku v\u00e4ljakuinfot.\"],\"neutral\":[\"Vaata tiiaegu ja planeeri oma ring.\"]},\"en\":{\"sunny\":[\"Today might be a day to leave the office early.\",\"The sun is out. Your round could be too.\"],\"evening\":[\"The workday is ending. Practice is not.\",\"Evening light is the best light on the course.\"],\"morning\":[\"A quiet morning. The first tee time is waiting.\"],\"cloudy\":[\"Cloudy and calm. The ball flies just as well.\",\"Clouds up high, the game down below.\"],\"windy\":[\"Today the wind has a game plan too.\",\"The wind is playing along. Choose your shots wisely.\"],\"drizzle\":[\"A little rain. Big plans.\",\"A bit damp, but playable.\"],\"rain\":[\"Rainy weather. Check the forecast for the next hours.\"],\"rainEvening\":[\"A rainy evening. Check the forecast for tomorrow.\"],\"fog\":[\"Foggy weather. Check the forecast before you come.\"],\"night\":[\"Evening is here. Pick a good start time for tomorrow.\"],\"snow\":[\"Snow is in the forecast. Check the official course info before you come.\"],\"strongwind\":[\"Strong gusts are in the forecast. Check the official course info before you come.\"],\"thunder\":[\"Thunder is in the forecast. Check the official course info before you come.\"],\"neutral\":[\"See tee times and plan your round.\"]}},\"copyOverrides\":{\"rae\":{\"et\":{\"rain\":[\"Vihmane ilm. TrackMan range'il on 19 katusealust l\u00f6\u00f6gikohta.\"]},\"en\":{\"rain\":[\"Rainy weather. The TrackMan range has 19 covered bays.\"]}}},\"playfulBuckets\":[\"sunny\",\"evening\",\"morning\",\"cloudy\",\"windy\",\"drizzle\"],\"fullFxWhen\":null,\"bookingDateHash\":false,\"_bookingDateHashNote\":\"Chronogolf ei dokumenteeri kuup\u00e4eva parameetrit. Brauseris 11.10 n\u00e4htud '#?date=YYYY-MM-DD' t\u00f6\u00f6tab, kuid on dokumenteerimata \u2013 l\u00fclita true ainult omaniku n\u00f5usolekul. Kellaaega ei edastata.\",\"_fullFxWhenNote\":\"Valikuline selektor hero sees. Kui see EI leia elementi (nt WBG sakk n\u00e4itab inimeste fotot), j\u00e4\u00e4b alles ainult toon: pole valguslaike, pilvevarje ega sademeid. WBG: .ngg-in__bg.is-on[data-k=\\\"play\\\"]\",\"layout\":null,\"courseSwitch\":true,\"statusRows\":true,\"planSelector\":null,\"courseLink\":null,\"_layoutNote\":\"layout:'bar' = kompaktne T\u00e4na-kaart (hero all, ametlikud read + jalus); courseSwitch:false = ainult koduv\u00e4ljak (teise v\u00e4ljaku ilma\/fotot pole); statusRows:false = V\u00e4ljak\/Range read peidetud, kui ametlikud read on samas kaardis kiipidena; planSelector = eraldi sektsioon \u201eMillal t\u00e4na m\u00e4ngida?\u201c jaoks; courseLink = {et:{href,text},en:{href,text}} lihtlink teisele v\u00e4ljakule.\"};\nvar VERSION = '1.2.0';\n\/* ---------- small helpers ---------- *\/\nfunction isObj(v) { if (v === null) { return false; } return typeof v === 'object' ? !Array.isArray(v) : false; }\nfunction merge(a, b) {\nvar out = {}, k;\nfor (k in a) { if (Object.prototype.hasOwnProperty.call(a, k)) { out[k] = a[k]; } }\nfor (k in b) {\nif (!Object.prototype.hasOwnProperty.call(b, k)) { continue; }\nif (isObj(out[k])) { if (isObj(b[k])) { out[k] = merge(out[k], b[k]); continue; } }\nout[k] = b[k];\n}\nreturn out;\n}\nfunction num(v) { if (typeof v !== 'number') { return null; } return isFinite(v) ? v : null; }\nfunction clamp(v, a, b) { return v < a ? a : (v > b ? b : v); }\nfunction rad(d) { return d * Math.PI \/ 180; }\nfunction deg(r) { return r * 180 \/ Math.PI; }\nfunction fill(s, o) { return String(s).replace(\/\\{(\\w+)\\}\/g, function (m, k) { return o[k] === undefined ? '' : String(o[k]); }); }\nfunction pad2(n) { return (n < 10 ? '0' : '') + n; }\nfunction store(kind) { try { return kind === 's' ? W.sessionStorage : W.localStorage; } catch (e) { return null; } }\nfunction sget(key, kind) { try { var s = store(kind); if (!s) { return null; } var v = s.getItem(key); return v === null ? null : JSON.parse(v); } catch (e) { return null; } }\nfunction sset(key, val, kind) { try { var s = store(kind); if (s) { s.setItem(key, JSON.stringify(val)); } } catch (e) { \/* quota or blocked *\/ } }\nfunction h(tag, attrs, kids) {\nvar el = D.createElement(tag), k;\nif (attrs) {\nfor (k in attrs) {\nif (!Object.prototype.hasOwnProperty.call(attrs, k)) { continue; }\nvar v = attrs[k];\nif (v === null) { continue; }\nif (v === undefined) { continue; }\nif (k === 'text') { el.textContent = v; } else if (k === 'class') { el.className = v; } else { el.setAttribute(k, v); }\n}\n}\nif (kids) { for (var i = 0; i < kids.length; i++) { if (kids[i]) { el.appendChild(typeof kids[i] === 'string' ? D.createTextNode(kids[i]) : kids[i]); } } }\nreturn el;\n}\nvar SVGNS = 'http:\/\/www.w3.org\/2000\/svg';\nfunction s(tag, attrs) { var el = D.createElementNS(SVGNS, tag); for (var k in attrs) { if (Object.prototype.hasOwnProperty.call(attrs, k)) { el.setAttribute(k, attrs[k]); } } return el; }\nfunction qs(sel, root) { try { return (root || D).querySelector(sel); } catch (e) { return null; } }\nfunction qsa(sel, root) { try { return Array.prototype.slice.call((root || D).querySelectorAll(sel)); } catch (e) { return []; } }\nfunction push(site, comp, ev, val) {\ntry { W.dataLayer = W.dataLayer || []; W.dataLayer.push({ event: ev, ngg_site: site, ngg_component: comp, ngg_value: String(val) }); } catch (e) { \/* ignore *\/ }\n}\nfunction qp(name) {\ntry { return new URL(W.location.href).searchParams.get(name); } catch (e) { return null; }\n}\n\/* ---------- Europe\/Tallinn time (DST aware via Intl) ---------- *\/\nvar WDEN = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\nvar FMT = null;\nfunction tparts(ms) {\nif (!FMT) { FMT = new Intl.DateTimeFormat('en-GB', { timeZone: TZ, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', weekday: 'short', hourCycle: 'h23' }); }\nvar o = {};\nFMT.formatToParts(new Date(ms)).forEach(function (x) { o[x.type] = x.value; });\nreturn { y: +o.year, m: +o.month, d: +o.day, h: (+o.hour) % 24, mi: +o.minute, wd: WDEN.indexOf(o.weekday) };\n}\nfunction localToUtc(y, m, d, hh, mi) {\nvar guess = Date.UTC(y, m - 1, d, hh, mi);\nvar t = guess - 2 * 3600000;\nfor (var i = 0; i < 2; i++) {\nvar p = tparts(t);\nvar off = Date.UTC(p.y, p.m - 1, p.d, p.h, p.mi) - t;\nt = guess - off;\n}\nreturn t;\n}\nfunction addDays(p, n) { var dt = new Date(Date.UTC(p.y, p.m - 1, p.d + n, 12)); return { y: dt.getUTCFullYear(), m: dt.getUTCMonth() + 1, d: dt.getUTCDate(), wd: dt.getUTCDay() }; }\nfunction hhmm(ms) { var p = tparts(ms); return pad2(p.h) + ':' + pad2(p.mi); }\nfunction durTxt(min, lang) {\nmin = Math.round(Math.abs(min));\nvar hh = Math.floor(min \/ 60), mm = min % 60;\nif (hh === 0) { return mm + ' min'; }\nif (mm === 0) { return hh + ' h'; }\nreturn hh + ' h ' + mm + ' min';\n}\n\/* ---------- NOAA solar position (Solar Calculator spreadsheet formulas) ---------- *\/\nfunction jc(ms) { return (ms \/ 86400000 + 2440587.5 - 2451545) \/ 36525; }\nfunction solar(T) {\nvar L0 = (280.46646 + T * (36000.76983 + T * 0.0003032)) % 360;\nif (L0 < 0) { L0 += 360; }\nvar M = 357.52911 + T * (35999.05029 - 0.0001537 * T);\nvar e = 0.016708634 - T * (0.000042037 + 0.0000001267 * T);\nvar Mr = rad(M);\nvar C = Math.sin(Mr) * (1.914602 - T * (0.004817 + 0.000014 * T)) + Math.sin(2 * Mr) * (0.019993 - 0.000101 * T) + Math.sin(3 * Mr) * 0.000289;\nvar omega = 125.04 - 1934.136 * T;\nvar lambda = L0 + C - 0.00569 - 0.00478 * Math.sin(rad(omega));\nvar eps0 = 23 + (26 + (21.448 - T * (46.815 + T * (0.00059 - T * 0.001813))) \/ 60) \/ 60;\nvar eps = eps0 + 0.00256 * Math.cos(rad(omega));\nvar decl = deg(Math.asin(Math.sin(rad(eps)) * Math.sin(rad(lambda))));\nvar y = Math.tan(rad(eps \/ 2)); y = y * y;\nvar L0r = rad(L0);\nvar eot = 4 * deg(y * Math.sin(2 * L0r) - 2 * e * Math.sin(Mr) + 4 * e * y * Math.sin(Mr) * Math.cos(2 * L0r) - 0.5 * y * y * Math.sin(4 * L0r) - 1.25 * e * e * Math.sin(2 * Mr));\nreturn { decl: decl, eot: eot };\n}\nfunction sunElev(ms, lat, lon) {\nvar p = solar(jc(ms));\nvar utcMin = (((ms % 86400000) + 86400000) % 86400000) \/ 60000;\nvar tst = (utcMin + p.eot + 4 * lon) % 1440; if (tst < 0) { tst += 1440; }\nvar ha = tst \/ 4 - 180;\nvar cz = Math.sin(rad(lat)) * Math.sin(rad(p.decl)) + Math.cos(rad(lat)) * Math.cos(rad(p.decl)) * Math.cos(rad(ha));\nreturn 90 - deg(Math.acos(clamp(cz, -1, 1)));\n}\nfunction sunTimes(y, m, d, lat, lon) {\nvar base = Date.UTC(y, m - 1, d);\nfunction calc(kind) {\nvar t = base + 12 * 3600000 - lon \/ 15 * 3600000;\nfor (var i = 0; i < 3; i++) {\nvar p = solar(jc(t));\nvar noonMin = 720 - 4 * lon - p.eot;\nif (kind === 0) { t = base + noonMin * 60000; continue; }\nvar x = Math.cos(rad(90.833)) \/ (Math.cos(rad(lat)) * Math.cos(rad(p.decl))) - Math.tan(rad(lat)) * Math.tan(rad(p.decl));\nif (x > 1) { return null; }\nif (x < -1) { return null; }\nt = base + (noonMin + kind * 4 * deg(Math.acos(x))) * 60000;\n}\nreturn Math.round(t);\n}\nreturn { rise: calc(-1), set: calc(1), noon: calc(0) };\n}\nfunction sunForLocalDay(ms, c) { var p = tparts(ms); return sunTimes(p.y, p.m, p.d, c.lat, c.lon); }\n\/* ---------- apparent temperature (same rule as Yr FAQ) ----------\nT at most 10 C and wind above 1.33 m\/s: wind chill (JAG\/TI, Environment Canada), V in km\/h at 10 m:\nWC = 13.12 + 0.6215 T - 11.37 V^0.16 + 0.3965 T V^0.16\nT at least 26 C and RH at least 40 %: NOAA heat index (Rothfusz regression, computed in F).\nOtherwise: air temperature. Missing inputs give null, never 0. *\/\nfunction feelsLike(T, wind, rh) {\nif (T === null) { return null; }\nif (T <= 10) {\nif (wind === null) { return null; }\nif (wind > 1.33) {\nvar v = Math.pow(wind * 3.6, 0.16);\nreturn 13.12 + 0.6215 * T - 11.37 * v + 0.3965 * T * v;\n}\nreturn T;\n}\nif (T >= 26) {\nif (rh === null) { return null; }\nif (rh >= 40) {\nvar F = T * 9 \/ 5 + 32, R = rh;\nvar HI = -42.379 + 2.04901523 * F + 10.14333127 * R - 0.22475541 * F * R - 0.00683783 * F * F - 0.05481717 * R * R + 0.00122874 * F * F * R + 0.00085282 * F * R * R - 0.00000199 * F * F * R * R;\nreturn (HI - 32) * 5 \/ 9;\n}\n}\nreturn T;\n}\n\/* ---------- MET Norway Locationforecast 2.0 adapter ---------- *\/\nvar MET = {\nurl: function (cfg, c, base) {\nbase = base || cfg.provider.proxyEndpoint || cfg.provider.endpoint;\nvar lat = Math.floor(c.lat * 10000) \/ 10000, lon = Math.floor(c.lon * 10000) \/ 10000; \/* max 4 decimals per MET terms *\/\nvar u = base + (base.indexOf('?') === -1 ? '?' : AMP) + 'lat=' + lat.toFixed(4) + AMP + 'lon=' + lon.toFixed(4);\nif (num(c.altitude) !== null) { u += AMP + 'altitude=' + Math.round(c.altitude); }\nreturn u;\n},\n\/* proxy: one fixed point per course, chosen by c=<course key>; no lat\/lon *\/\nproxyUrl: function (base, key) {\nif (\/[?]c=\/.test(base)) { return base.replace(\/c=[A-Za-z0-9_-]*\/, 'c=' + key); }\nreturn base + (base.indexOf('?') === -1 ? '?' : AMP) + 'c=' + key;\n},\nurls: function (cfg, c, key) {\nvar out = [];\nvar off = sget('ngg-lv-proxy-off', 's');\nvar skip = typeof off === 'number' ? Date.now() < off : false;\nif (cfg.provider.proxyEndpoint) { if (!skip) { out.push({ via: 'proxy', url: MET.proxyUrl(cfg.provider.proxyEndpoint, key) }); } }\nif (cfg.provider.endpoint) { out.push({ via: 'met', url: MET.url(cfg, c, cfg.provider.endpoint) }); }\nreturn out;\n},\nparse: function (json) {\nvar props = json ? json.properties : null;\nif (!props) { throw new Error('bad payload'); }\nvar ts = props.timeseries || [];\nvar out = [];\nfor (var i = 0; i < ts.length; i++) {\nvar t = ts[i], data = t.data || {};\nvar det = (data.instant || {}).details || {};\nvar n1 = data.next_1_hours;\nif (!n1) { continue; } \/* hourly part only (about 60 h in the Nordic domain) *\/\nvar nd = n1.details || {};\nvar T = num(det.air_temperature), wind = num(det.wind_speed), rh = num(det.relative_humidity);\nvar apiFeels = num(det.apparent_air_temperature);\nout.push({\ntime: Date.parse(t.time),\ntemp: T,\nfeels: apiFeels !== null ? apiFeels : feelsLike(T, wind, rh),\nfeelsSrc: apiFeels !== null ? 'api' : 'calc',\nsymbol: n1.summary ? (n1.summary.symbol_code || null) : null,\ncloud: num(det.cloud_area_fraction),\nfog: num(det.fog_area_fraction),\nrh: rh,\nprecipProb: num(nd.probability_of_precipitation),\nthunderProb: num(nd.probability_of_thunder),\nprecipMm: num(nd.precipitation_amount),\nwind: wind,\ngust: num(det.wind_speed_of_gust),\ndirFrom: num(det.wind_from_direction)\n});\n}\nvar meta = props.meta || {};\nreturn { series: out, modelUpdated: meta.updated_at ? Date.parse(meta.updated_at) : null };\n}\n};\n\/* ---------- weather state model: three independent layers ---------- *\/\nfunction symbolInfo(code, cfg) {\nif (!code) { return null; }\nvar base = String(code).split('_')[0];\nvar thunder = base.indexOf('andthunder') !== -1;\nbase = base.replace('andthunder', '');\nvar inten = 'normal';\nif (base.indexOf('heavy') === 0) { inten = 'heavy'; base = base.slice(5); }\nelse if (base.indexOf('lights') === 0) {\n\/* MET keeps the typo lightssleetshowersandthunder and lightssnowshowersandthunder *\/\nif (base.indexOf('lightss') === 0) { base = base.slice(6); } else { base = base.slice(5); }\ninten = 'light';\n} else if (base.indexOf('light') === 0) { inten = 'light'; base = base.slice(5); }\nvar showers = base.indexOf('showers') !== -1;\nvar type = base.replace('showers', '');\nreturn { code: code, type: type, showers: showers, inten: inten, thunder: thunder, night: String(code).indexOf('_night') !== -1 };\n}\nfunction condText(code, T) {\nvar si = symbolInfo(code);\nif (!si) { return null; }\nvar C = T.cond;\nif (C[si.type] !== undefined) { if (['clearsky', 'fair', 'partlycloudy', 'cloudy', 'fog'].indexOf(si.type) !== -1) { return C[si.type]; } }\nvar word = C[si.type + (si.showers ? 'showers' : '')] || C[si.type] || si.type;\nvar pre = '';\nif (si.inten === 'light') { pre = (si.showers ? C.lightPl : C.light) + ' '; }\nif (si.inten === 'heavy') { pre = (si.showers ? C.heavyPl : C.heavy) + ' '; }\nvar txt = pre + word + (si.thunder ? ' ' + C.thunder : '');\nreturn txt.charAt(0).toUpperCase() + txt.slice(1);\n}\nfunction weatherState(entry, ms, course, cfg) {\nvar sm = cfg.symbolMap, th = cfg.thresholds, ph = cfg.phases;\nvar elev = sunElev(ms, course.lat, course.lon);\nvar st = sunForLocalDay(ms, course);\nvar morning = st.noon ? ms < st.noon : tparts(ms).h < 12;\nvar phase = 'day';\nif (elev < ph.nightBelow) { phase = 'night'; }\nelse if (morning) { if (elev < ph.dawnBelow) { phase = 'dawn'; } }\nelse if (elev < 0) { phase = 'dusk'; }\nelse if (elev < ph.goldenBelow) { phase = 'golden'; }\nvar r = { phase: phase, elev: elev, morning: morning, sky: null, precip: 'none', inten: 0, thunder: false, wind: null, gust: null, dirFrom: null, temp: null };\nif (!entry) { return r; }\nr.wind = entry.wind; r.gust = entry.gust; r.dirFrom = entry.dirFrom; r.temp = entry.temp;\nvar si = symbolInfo(entry.symbol, cfg);\nif (si) {\nvar m = sm[si.type];\nif (m) {\nr.sky = si.showers ? sm.showersSky : m.sky;\nr.precip = m.precip;\nif (r.precip !== 'none') {\nr.inten = si.inten === 'light' ? sm.lightIntensity : (si.inten === 'heavy' ? sm.heavyIntensity : sm.normalIntensity);\nif (r.precip === 'rain') { if (si.inten === 'light') { r.precip = sm.lightRainIs; } }\n}\n}\nr.thunder = si.thunder;\n} else if (entry.cloud !== null) {\nr.sky = entry.cloud < 20 ? 'clear' : (entry.cloud < 70 ? 'partly' : 'cloudy');\n}\nif (entry.fog !== null) { if (entry.fog >= 50) { if (r.precip === 'none') { r.sky = 'fog'; } } }\nif (entry.thunderProb !== null) { if (entry.thunderProb >= th.thunderProb) { r.thunder = true; } }\nr.strong = false;\nif (r.thunder) { r.strong = true; }\nif (r.gust !== null) { if (r.gust >= th.strongGustMs) { r.strong = true; } }\nif (r.wind !== null) { if (r.wind >= th.strongWindMs) { r.strong = true; } }\nr.windy = false;\nif (r.wind !== null) { if (r.wind >= th.windyMs) { r.windy = true; } }\nif (r.gust !== null) { if (r.gust >= th.windyGustMs) { r.windy = true; } }\nreturn r;\n}\nfunction bucketOf(st) {\nif (!st) { return 'neutral'; }\nif (st.thunder) { return 'thunder'; }\nif (st.strong) { return 'strongwind'; }\nif (st.precip === 'snow') { return 'snow'; }\nvar evening = ['golden', 'dusk', 'night'].indexOf(st.phase) !== -1;\nif (st.precip === 'rain' || st.precip === 'sleet') { return evening ? 'rainEvening' : 'rain'; }\nif (st.phase === 'night') { return 'night'; }\nif (st.precip === 'drizzle') { return 'drizzle'; }\nif (st.sky === 'fog') { return 'fog'; }\nif (st.windy) { return 'windy'; }\nif (st.sky === null) { return 'neutral'; }\nif (evening) { if (st.sky !== 'cloudy') { return 'evening'; } }\nif (st.phase === 'dawn') { return 'morning'; }\nif (st.sky === 'cloudy') { return 'cloudy'; }\nreturn 'sunny';\n}\n\/* ---------- grading recipe (CSS variables) ---------- *\/\nfunction grade(st, k) {\nvar g = { bri: 1, sat: 1, con: 1, warm: '#ffb070', warmA: 0, cool: '#0b1d3a', coolA: 0, haze: 0, shadow: 0, spots: 0, glow: 0, glowX: '78%', glowY: '18%', scrim: 0.25, rain: 0, snow: 0, kind: 'none' };\nif (!st) { return g; }\nvar p = st.phase;\nif (p === 'day') { g.bri = 1.03; g.sat = 1.06; g.con = 1.02; }\nif (p === 'dawn') { g.warm = '#ffb27a'; g.warmA = 0.32; g.bri = 0.95; g.glow = 0.55; g.glowX = '16%'; g.glowY = '30%'; }\nif (p === 'golden') { g.warm = '#ff9a45'; g.warmA = 0.55; g.sat = 1.14; g.bri = 1.02; g.glow = 0.9; g.glowX = '84%'; g.glowY = '30%'; }\nif (p === 'dusk') { g.warm = '#ff9a7a'; g.warmA = 0.16; g.cool = '#3b3a78'; g.coolA = 0.16; g.bri = 0.92; g.sat = 0.95; g.glow = 0.3; g.glowX = '86%'; g.glowY = '40%'; g.scrim = 0.4; }\nif (p === 'night') { g.cool = '#0b1d3a'; g.coolA = 0.55; g.bri = 0.58; g.sat = 0.72; g.scrim = 0.5; }\nvar sky = st.sky;\nif (sky === 'clear') { g.sat += 0.05; g.bri += 0.02; if (p === 'day') { g.spots = 0.9; } if (p === 'golden') { g.spots = 0.6; } }\nif (sky === 'partly') { g.shadow = 0.32; if (p === 'day') { g.spots = 0.45; } }\nif (sky === 'cloudy') { g.sat -= 0.18; g.bri -= 0.07; g.con -= 0.04; g.shadow = 0.5; g.glow *= 0.35; g.warmA *= 0.5; if (g.coolA < 0.18) { g.cool = '#6f86a3'; g.coolA = 0.18; } }\nif (sky === 'fog') { g.scrim += 0.25; g.haze = 0.5; g.con -= 0.18; g.sat -= 0.3; g.glow *= 0.3; g.warmA *= 0.4; }\nif (st.precip === 'drizzle') { g.rain = 0.45; g.kind = 'rain'; g.bri -= 0.04; if (g.coolA < 0.14) { g.cool = '#6f86a3'; g.coolA = 0.14; } }\nif (st.precip === 'rain') { g.rain = st.inten; g.kind = 'rain'; g.bri -= 0.1; g.sat -= 0.12; g.spots = 0; if (g.coolA < 0.26) { g.cool = '#5d7896'; g.coolA = 0.26; } g.scrim += 0.08; }\nif (st.precip === 'sleet') { g.rain = st.inten * 0.8; g.snow = st.inten * 0.4; g.kind = 'sleet'; g.bri -= 0.08; g.sat -= 0.2; g.spots = 0; if (g.coolA < 0.24) { g.cool = '#7d93ad'; g.coolA = 0.24; } }\nif (st.precip === 'snow') { g.snow = st.inten; g.kind = 'snow'; g.bri += 0.03; g.sat -= 0.32; g.haze = Math.max(g.haze, 0.16); g.scrim += 0.2; g.spots = 0; g.warmA *= 0.5; }\nif (st.precip !== 'none') { g.spots = 0; g.glow *= 0.4; }\nvar I = k || {};\nfunction mix(v, base, f) { return base + (v - base) * (f === undefined ? 1 : f); }\ng.bri = mix(g.bri, 1, I.grade); g.sat = mix(g.sat, 1, I.grade); g.con = mix(g.con, 1, I.grade);\ng.warmA *= (I.grade === undefined ? 1 : I.grade); g.coolA *= (I.grade === undefined ? 1 : I.grade);\ng.spots *= (I.spots === undefined ? 1 : I.spots); g.glow *= (I.spots === undefined ? 1 : I.spots);\ng.shadow *= (I.clouds === undefined ? 1 : I.clouds); g.haze *= (I.fog === undefined ? 1 : I.fog);\ng.rain *= (I.rain === undefined ? 1 : I.rain); g.snow *= (I.snow === undefined ? 1 : I.snow);\nreturn g;\n}\n\/* ---------- precipitation canvas ---------- *\/\nfunction Precip(canvas, cfg) {\nthis.c = canvas; this.ctx = canvas.getContext('2d'); this.cfg = cfg;\nthis.p = []; this.kind = 'none'; this.rain = 0; this.snow = 0; this.wx = 0; this.w = 0; this.h = 0; this.mask = null; this.safe = null; this.dpr = 1;\n}\nPrecip.prototype.resize = function (w, h, safe) {\nvar dpr = Math.min(W.devicePixelRatio || 1, this.cfg.effects.dprCap || 1.5);\nthis.dpr = dpr; this.w = w; this.h = h; this.safe = safe;\nthis.c.width = Math.max(1, Math.round(w * dpr)); this.c.height = Math.max(1, Math.round(h * dpr));\nthis.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\nthis.mask = null;\nif (safe) {\nvar m = D.createElement('canvas'); m.width = this.c.width; m.height = this.c.height;\nvar mc = m.getContext('2d'); mc.setTransform(dpr, 0, 0, dpr, 0, 0);\nvar cx = safe.x + safe.w \/ 2, cy = safe.y + safe.h \/ 2, rx = safe.w \/ 2 * 1.45 + 40, ry = safe.h \/ 2 * 1.45 + 40;\nmc.save(); mc.translate(cx, cy); mc.scale(rx \/ ry, 1);\nvar gr = mc.createRadialGradient(0, 0, 0, 0, 0, ry);\ngr.addColorStop(0, 'rgba(0,0,0,1)'); gr.addColorStop(0.78, 'rgba(0,0,0,1)'); gr.addColorStop(1, 'rgba(0,0,0,0)');\nmc.fillStyle = gr; mc.beginPath(); mc.arc(0, 0, ry, 0, Math.PI * 2); mc.fill(); mc.restore();\n\/* hard rectangle on top so particles never touch text *\/\nmc.fillStyle = '#000'; mc.fillRect(safe.x - 12, safe.y - 12, safe.w + 24, safe.h + 24);\nthis.mask = m;\n}\nthis.seed();\n};\nPrecip.prototype.set = function (kind, rain, snow, wx) {\nvar changed = kind !== this.kind ? true : (Math.abs(rain - this.rain) > 0.05 ? true : Math.abs(snow - this.snow) > 0.05);\nthis.kind = kind; this.rain = rain; this.snow = snow; this.wx = wx;\nif (changed) { this.seed(); }\n};\nPrecip.prototype.seed = function () {\nvar area = this.w * this.h \/ 1e6, max = this.cfg.effects.maxParticles || 220;\nvar nr = Math.round(clamp(area * 260 * this.rain, 0, max));\nvar ns = Math.round(clamp(area * 220 * this.snow, 0, max * 0.7));\nthis.p = [];\nif (this.w) { this.ctx.clearRect(0, 0, this.w, this.h); }\nfor (var i = 0; i < nr; i++) { this.p.push(this.mk('r', true)); }\nfor (var j = 0; j < ns; j++) { this.p.push(this.mk('s', true)); }\n};\nPrecip.prototype.mk = function (t, anywhere) {\nvar drizzle = this.rain < 0.5;\nif (t === 'r') {\nreturn { t: 'r', x: Math.random() * (this.w + 80) - 40, y: anywhere ? Math.random() * this.h : -20 - Math.random() * 60, l: drizzle ? 6 + Math.random() * 6 : 12 + Math.random() * 12, v: drizzle ? 260 + Math.random() * 120 : 620 + Math.random() * 280, a: drizzle ? 0.22 + Math.random() * 0.18 : 0.28 + Math.random() * 0.22 };\n}\nreturn { t: 's', x: Math.random() * this.w, y: anywhere ? Math.random() * this.h : -6, r: 1.2 + Math.random() * 2, v: 16 + Math.random() * 24, ph: Math.random() * 6.28, a: 0.6 + Math.random() * 0.35 };\n};\nPrecip.prototype.step = function (dt, tsec) {\nvar ctx = this.ctx, w = this.w, h = this.h, wx = clamp(this.wx, -1, 1);\nctx.clearRect(0, 0, w, h);\nif (!this.p.length) { return; }\nctx.lineCap = 'round';\nctx.lineWidth = this.rain < 0.5 ? 0.8 : 1;\nctx.strokeStyle = 'rgba(226,236,248,1)';\nctx.fillStyle = 'rgba(255,255,255,1)';\nfor (var i = 0; i < this.p.length; i++) {\nvar q = this.p[i];\nif (q.t === 'r') {\nvar vx = wx * 0.28;\nq.y += q.v * dt; q.x += q.v * vx * dt;\nif (q.y > h + 20) { var n = this.mk('r', false); q.x = n.x; q.y = n.y; }\nctx.globalAlpha = q.a;\nctx.beginPath(); ctx.moveTo(q.x, q.y); ctx.lineTo(q.x - vx * q.l, q.y - q.l); ctx.stroke();\n} else {\nq.y += q.v * dt; q.x += (Math.sin(tsec * 0.8 + q.ph) * 10 + wx * 16) * dt;\nif (q.y > h + 6) { q.y = -6; q.x = Math.random() * w; }\nctx.globalAlpha = q.a;\nctx.beginPath(); ctx.arc(q.x, q.y, q.r, 0, 6.2832); ctx.fill();\n}\n}\nctx.globalAlpha = 1;\nif (this.mask) {\nctx.save(); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.globalCompositeOperation = 'destination-out'; ctx.drawImage(this.mask, 0, 0); ctx.restore();\n}\n};\n\/* ---------- golf flag (SVG) ---------- *\/\nfunction Flag(holder) {\nvar svg = s('svg', { viewBox: '0 0 200 140', class: 'ngg-lv-flag-svg', 'aria-hidden': 'true', focusable: 'false' });\nvar id = 'ngglv' + Math.floor(Math.random() * 1e6);\nvar defs = s('defs', {});\nvar sky = s('linearGradient', { id: id + 'sky', x1: '0', y1: '0', x2: '0', y2: '1' });\nthis.sk1 = s('stop', { offset: '0', 'stop-color': '#cfe3ff' }); this.sk2 = s('stop', { offset: '1', 'stop-color': '#f4f8ff' });\nsky.appendChild(this.sk1); sky.appendChild(this.sk2);\nvar grn = s('radialGradient', { id: id + 'grn', cx: '0.5', cy: '0.35', r: '0.7' });\nthis.g1 = s('stop', { offset: '0', 'stop-color': '#7fbf5a' }); this.g2 = s('stop', { offset: '1', 'stop-color': '#3f7f35' });\ngrn.appendChild(this.g1); grn.appendChild(this.g2);\nvar sheen = s('linearGradient', { id: id + 'sh', x1: '0', y1: '0', x2: '1', y2: '0' });\nsheen.appendChild(s('stop', { offset: '0', 'stop-color': '#fff', 'stop-opacity': '0' }));\nsheen.appendChild(s('stop', { offset: '0.5', 'stop-color': '#fff', 'stop-opacity': '0.55' }));\nsheen.appendChild(s('stop', { offset: '1', 'stop-color': '#fff', 'stop-opacity': '0' }));\nvar clip = s('clipPath', { id: id + 'cl' });\nclip.appendChild(s('ellipse', { cx: '100', cy: '112', rx: '90', ry: '21' }));\ndefs.appendChild(sky); defs.appendChild(grn); defs.appendChild(sheen); defs.appendChild(clip);\nsvg.appendChild(defs);\nthis.bg = s('rect', { x: '0', y: '0', width: '200', height: '140', rx: '18', fill: 'url(#' + id + 'sky)' });\nsvg.appendChild(this.bg);\nsvg.appendChild(s('ellipse', { cx: '100', cy: '114', rx: '96', ry: '24', fill: '#2f6a2b', opacity: '0.55' }));\nthis.green = s('ellipse', { cx: '100', cy: '112', rx: '90', ry: '21', fill: 'url(#' + id + 'grn)' });\nsvg.appendChild(this.green);\nvar cg = s('g', { 'clip-path': 'url(#' + id + 'cl)' });\nthis.snowCover = s('ellipse', { cx: '100', cy: '112', rx: '90', ry: '21', fill: '#f4f7fb', opacity: '0' });\nthis.sheen = s('rect', { x: '-60', y: '88', width: '60', height: '50', fill: 'url(#' + id + 'sh)', opacity: '0' });\ncg.appendChild(this.snowCover); cg.appendChild(this.sheen);\nthis.rings = [];\nfor (var i = 0; i < 5; i++) { var r = s('ellipse', { cx: '0', cy: '0', rx: '0', ry: '0', fill: 'none', stroke: '#e6f1ff', 'stroke-width': '0.9', opacity: '0' }); cg.appendChild(r); this.rings.push({ el: r, t: Math.random(), x: 40 + Math.random() * 120, y: 104 + Math.random() * 14 }); }\nsvg.appendChild(cg);\nthis.shadow = s('line', { x1: '100', y1: '112', x2: '128', y2: '120', stroke: '#1f3d1c', 'stroke-width': '2', 'stroke-linecap': 'round', opacity: '0.25' });\nsvg.appendChild(this.shadow);\nsvg.appendChild(s('ellipse', { cx: '100', cy: '112', rx: '7', ry: '2.6', fill: '#15200f' }));\nsvg.appendChild(s('line', { x1: '100', y1: '112', x2: '100', y2: '20', stroke: '#ffffff', 'stroke-width': '2.4', 'stroke-linecap': 'round' }));\nsvg.appendChild(s('circle', { cx: '100', cy: '19', r: '2.2', fill: '#ffffff' }));\nthis.flag = s('path', { d: '', fill: '#f39595', stroke: '#e07f7f', 'stroke-width': '0.6', 'stroke-linejoin': 'round' });\nsvg.appendChild(this.flag);\nthis.warm = s('rect', { x: '0', y: '0', width: '200', height: '140', rx: '18', fill: '#ff9d4d', opacity: '0', 'pointer-events': 'none' });\nsvg.appendChild(this.warm);\nholder.appendChild(svg);\nthis.svg = svg; this.wind = 0; this.dirTo = 90; this.mode = {}; this.t = 0;\nthis.draw(0);\n}\nFlag.prototype.setWeather = function (st, intensity) {\nthis.wind = st ? (st.wind === null ? 0 : st.wind) : 0;\nthis.gust = st ? (st.gust === null ? this.wind : st.gust) : 0;\nthis.dirTo = st ? (st.dirFrom === null ? null : (st.dirFrom + 180) % 360) : null;\nthis.k = intensity === undefined ? 1 : intensity;\nvar p = st ? st.phase : 'day';\nvar skies = { day: ['#cfe3ff', '#f4f8ff'], dawn: ['#ffd9c2', '#fff2e6'], golden: ['#ffc58f', '#ffeeda'], dusk: ['#8f86c9', '#f3b7a8'], night: ['#0b1d3a', '#24385e'] };\nvar sk = skies[p] || skies.day;\nif (st) { if (st.sky === 'cloudy' || st.sky === 'fog' || st.precip !== 'none') { if (p === 'day') { sk = ['#c9d3de', '#eef2f6']; } } }\nthis.sk1.setAttribute('stop-color', sk[0]); this.sk2.setAttribute('stop-color', sk[1]);\nvar night = p === 'night';\nthis.g1.setAttribute('stop-color', night ? '#2f5a3a' : '#7fbf5a'); this.g2.setAttribute('stop-color', night ? '#16301f' : '#3f7f35');\nthis.warm.setAttribute('opacity', p === 'golden' ? '0.22' : (p === 'dawn' ? '0.14' : (p === 'dusk' ? '0.1' : '0')));\nthis.sun = st ? (st.sky === 'clear' || st.sky === 'partly') : false;\nif (st) { if (st.precip !== 'none') { this.sun = false; } if (p === 'night') { this.sun = false; } }\nthis.rain = st ? (st.precip === 'rain' || st.precip === 'drizzle' || st.precip === 'sleet') : false;\nthis.snowCover.setAttribute('opacity', st ? (st.precip === 'snow' ? '0.75' : '0') : '0');\nthis.sheen.setAttribute('opacity', this.sun ? '1' : '0');\nvar sx = this.dirTo === null ? 1 : Math.sin(rad(this.dirTo));\nthis.dirSign = sx < 0 ? -1 : 1; this.fore = this.dirTo === null ? 0.8 : 0.6 + 0.4 * Math.abs(sx);\nthis.shadow.setAttribute('x2', p === 'golden' ? '60' : '128');\nthis.shadow.setAttribute('opacity', this.sun ? '0.28' : '0.08');\n};\nFlag.prototype.draw = function (tsec) {\nvar w = this.wind * (this.k === undefined ? 1 : this.k);\nvar L = 54 * (this.fore || 0.8), H = 26, n = 12;\nvar lift = clamp(w \/ 8, 0, 1);\n\/* hoist edge stays on the pole; the fly end droops in calm air (shear, not rotation) *\/\nvar droop = rad((1 - lift) * 68 + 3);\nvar gustF = this.gust > this.wind ? (1 + 0.25 * Math.sin(tsec * 0.9) * clamp((this.gust - this.wind) \/ 6, 0, 1)) : 1;\nvar amp = (0.5 + clamp(w, 0, 16) * 0.5) * gustF;\nvar freq = 0.3 + clamp(w, 0, 16) * 0.16;\nvar lam = 46;\nvar sg = this.dirSign || 1;\nvar ax = 100, ay = 21;\nvar cs = Math.cos(droop), tn = Math.sin(droop);\nfunction P(u, v) {\nvar f = u \/ L;\nvar wave = amp * f * Math.sin(6.2832 * (freq * tsec - u \/ lam));\nvar x = u * cs + Math.abs(wave) * 0.08 * L \/ 54;\nvar y = v + u * tn + wave;\nreturn (ax + sg * x).toFixed(2) + ' ' + (ay + y).toFixed(2);\n}\nvar top = [], bot = [], i;\nfor (i = 0; i <= n; i++) { top.push(P(L * i \/ n, 0)); }\nfor (i = n; i >= 0; i--) { bot.push(P(L * i \/ n, H)); }\nthis.flag.setAttribute('d', 'M' + top.join(' L') + ' L' + bot.join(' L') + ' Z');\nif (this.sun) { var sx = ((tsec \/ 9) % 1) * 300 - 80; this.sheen.setAttribute('x', sx.toFixed(1)); }\nfor (var j = 0; j < this.rings.length; j++) {\nvar r = this.rings[j];\nif (!this.rain) { r.el.setAttribute('opacity', '0'); continue; }\nvar tt = (tsec * 0.55 + r.t) % 1;\nif (tt < 0.02) { r.x = 30 + Math.random() * 140; r.y = 102 + Math.random() * 18; }\nr.el.setAttribute('cx', r.x.toFixed(1)); r.el.setAttribute('cy', r.y.toFixed(1));\nr.el.setAttribute('rx', (1 + tt * 9).toFixed(2)); r.el.setAttribute('ry', (0.4 + tt * 2.6).toFixed(2));\nr.el.setAttribute('opacity', ((1 - tt) * 0.85).toFixed(2));\n}\n};\nFlag.prototype.drawStatic = function () {\nthis.draw(1.3);\nif (this.rain) { for (var j = 0; j < this.rings.length; j++) { var r = this.rings[j]; var tt = 0.25 + j * 0.12; r.el.setAttribute('cx', (50 + j * 25).toFixed(1)); r.el.setAttribute('cy', (106 + (j % 3) * 4).toFixed(1)); r.el.setAttribute('rx', (1 + tt * 9).toFixed(2)); r.el.setAttribute('ry', (0.4 + tt * 2.6).toFixed(2)); r.el.setAttribute('opacity', '0.55'); } }\nif (this.sun) { this.sheen.setAttribute('x', '70'); }\n};\n\/* ---------- test fixtures (MET complete format) ---------- *\/\nvar VARIANT = ['clearsky', 'fair', 'partlycloudy', 'lightrainshowers', 'rainshowers', 'heavyrainshowers', 'lightsnowshowers', 'snowshowers', 'sleetshowers', 'rainshowersandthunder'];\nvar SCN = {\nsunny: function (lh, day) { return { T: 12 + 4 * Math.sin((lh - 8) \/ 12 * Math.PI), rh: 60, cloud: 8, wind: 3.2, gust: 6.1, dir: 205, code: day ? (lh > 14 ? 'partlycloudy' : 'fair') : 'clearsky', pop: day ? (lh > 14 ? 20 : 5) : 2, mm: 0 }; },\nrain: function (lh) { return { T: 8.5, rh: 94, cloud: 100, wind: 5.1, gust: 9.4, dir: 230, code: lh % 3 === 0 ? 'heavyrain' : 'rain', pop: 90, mm: 1.6 }; },\nrainEvening: function (lh, day) {\nif (day) { return { T: 10, rh: 75, cloud: 60, wind: 4, gust: 8, dir: 250, code: lh > 13 ? (lh < 16 ? 'lightrainshowers' : 'partlycloudy') : 'cloudy', pop: lh > 13 ? (lh < 16 ? 55 : 20) : 15, mm: lh > 13 ? (lh < 16 ? 0.3 : 0) : 0 }; }\nreturn { T: lh < 16 ? 11 : 9, rh: 88, cloud: lh < 16 ? 70 : 100, wind: 4.4, gust: 8.2, dir: 220, code: lh < 16 ? 'partlycloudy' : (lh < 17 ? 'lightrain' : 'rain'), pop: lh < 16 ? 25 : (lh < 17 ? 60 : 85), mm: lh < 16 ? 0 : (lh < 17 ? 0.2 : 1.1) };\n},\nwindy: function (lh) { return { T: 9, rh: 70, cloud: 90, wind: 8.6, gust: 13.1, dir: 245, code: 'cloudy', pop: 15, mm: 0 }; },\nstorm: function (lh) { return { T: 13, rh: 85, cloud: 100, wind: 11.2, gust: 18.5, dir: 260, code: 'rainshowersandthunder', pop: 80, mm: 2.2, thunder: 45 }; },\nnight: function (lh, day) { return { T: 4 + 3 * Math.sin((lh - 8) \/ 12 * Math.PI), rh: 80, cloud: 15, wind: 2.1, gust: 4.2, dir: 160, code: 'clearsky', pop: 0, mm: 0 }; },\nsnow: function (lh) { return { T: -1.5, rh: 92, cloud: 100, wind: 3.4, gust: 6.5, dir: 30, code: lh % 4 === 0 ? 'lightsnow' : 'snow', pop: 85, mm: 0.7 }; },\nfog: function (lh) { return { T: 6, rh: 99, cloud: 100, fog: lh < 11 ? 85 : 20, wind: 0.8, gust: 2.1, dir: 120, code: lh < 11 ? 'fog' : 'cloudy', pop: 10, mm: 0 }; },\ngolden: function (lh) { return { T: 11, rh: 70, cloud: 30, wind: 4.2, gust: 7.6, dir: 280, code: 'fair', pop: 5, mm: 0 }; },\ndusk: function (lh) { return { T: 10, rh: 82, cloud: 100, wind: 3, gust: 6.3, dir: 90, code: 'cloudy', pop: 15, mm: 0 }; }\n};\nvar FIXTURES = {\nsunny: { now: '13:00', label: 'P\u00e4ikeseline p\u00e4ev', scn: 'sunny' },\n'rain-evening': { now: '18:00', label: 'Vihmane \u00f5htu', scn: 'rainEvening' },\nwindy: { now: '12:00', label: 'Tuuline pilvine', scn: 'windy' },\nstorm: { now: '16:00', label: '\u00c4ike ja tugevad puhangud', scn: 'storm' },\nnight: { now: '22:30', label: '\u00d6\u00f6', scn: 'night' },\nsnow: { now: '11:00', label: 'Lumine', scn: 'snow' },\nfog: { now: '08:30', label: 'Udune hommik', scn: 'fog' },\ngolden: { now: '17:45', label: 'Kuldne tund', scn: 'golden' },\ndusk: { now: 'sunset+15', label: 'H\u00e4marik (p\u00e4ike \u22122\u2026\u22123\u00b0)', scn: 'dusk' },\n'dusk-late': { now: 'sunset+40', label: 'Hilinenud h\u00e4marik (p\u00e4ike alla \u22124\u00b0)', scn: 'dusk' },\nmissing: { now: '14:00', label: 'Puuduvad andmed', scn: 'sunny', missing: true },\nerror: { now: '13:00', label: 'API t\u00f5rge', error: true },\nsplit: { now: '13:00', label: 'Rae vs Valgeranna erinev ilm', scn: 'sunny', perCourse: { valgeranna: 'rain' } },\ntomorrow: { now: '15:00', label: 'Homne algusaeg', scn: 'sunny', day: 1, slot: 10 }\n};\nfunction fixturePayload(fx, courseKey, course, nowMs) {\nvar scn = SCN[(fx.perCourse ? fx.perCourse[courseKey] : null) || fx.scn];\nvar start = Math.floor(nowMs \/ 3600000) * 3600000;\nvar today = tparts(nowMs);\nvar ts = [];\nfor (var i = 0; i < 64; i++) {\nvar t = start + i * 3600000, lp = tparts(t);\nvar dayOff = (lp.d === today.d) ? 0 : 1;\nvar w = scn(lp.h, dayOff);\nvar elev = sunElev(t + 1800000, course.lat, course.lon);\nvar code = w.code + (VARIANT.indexOf(w.code) !== -1 ? (elev > 0 ? '_day' : '_night') : '');\nvar inst = { air_pressure_at_sea_level: 1012, air_temperature: Math.round(w.T * 10) \/ 10, cloud_area_fraction: w.cloud, relative_humidity: w.rh, wind_from_direction: w.dir, wind_speed: w.wind, wind_speed_of_gust: w.gust, fog_area_fraction: w.fog === undefined ? 0 : w.fog, dew_point_temperature: w.T - 3 };\nvar n1 = { summary: { symbol_code: code }, details: { precipitation_amount: w.mm, precipitation_amount_min: 0, precipitation_amount_max: w.mm * 1.5, probability_of_precipitation: w.pop, probability_of_thunder: w.thunder === undefined ? 0 : w.thunder } };\nif (fx.missing) {\ndelete inst.wind_speed_of_gust; delete n1.details.probability_of_precipitation; delete n1.details.probability_of_thunder;\nif (i < 2) { delete inst.air_temperature; delete inst.wind_speed; delete inst.wind_from_direction; delete n1.summary; }\n}\nts.push({ time: new Date(t).toISOString().replace('.000', ''), data: { instant: { details: inst }, next_1_hours: n1, next_6_hours: { summary: { symbol_code: code }, details: { precipitation_amount: w.mm * 6 } } } });\n}\nfor (var j = 1; j < 5; j++) { var t6 = start + (64 + j * 6) * 3600000; ts.push({ time: new Date(t6).toISOString().replace('.000', ''), data: { instant: { details: { air_temperature: 8, wind_speed: 3, wind_from_direction: 200, cloud_area_fraction: 50, relative_humidity: 70 } }, next_6_hours: { summary: { symbol_code: 'cloudy' }, details: { precipitation_amount: 0 } } } }); }\nreturn { type: 'Feature', geometry: { type: 'Point', coordinates: [course.lon, course.lat, 30] }, properties: { meta: { updated_at: new Date(start - 1800000).toISOString(), units: {} }, timeseries: ts } };\n}\n\/* ---------- the component ---------- *\/\nvar INST = [];\nfunction Live(mount) {\nvar self = this;\nthis.mount = mount;\nvar cj = qs('script.ngg-lv-config', mount) || qs('script[type=\"application\/json\"]', mount);\nvar user = {};\nif (cj) { try { user = JSON.parse(cj.textContent); } catch (e) { user = {}; } }\nthis.cfg = merge(DEFAULTS, user);\nvar cfg = this.cfg;\nif (mount.getAttribute('data-site')) { cfg.site = mount.getAttribute('data-site'); }\n\/* single-course mode: the other course (its weather and photos) is not reachable at all *\/\nif (cfg.courseSwitch === false) { if (cfg.courses[cfg.site]) { var only = {}; only[cfg.site] = cfg.courses[cfg.site]; cfg.courses = only; } }\nvar lang = cfg.lang;\nif (lang === 'auto') { lang = (mount.getAttribute('data-lang') || D.documentElement.lang || 'et').slice(0, 2).toLowerCase(); }\nthis.lang = cfg.texts[lang] ? lang : 'et';\nthis.T = cfg.texts[this.lang];\nthis.siteName = cfg.site === 'rae' ? 'rae' : 'valgeranna';\nthis.st = { course: cfg.courses[cfg.site] ? cfg.site : Object.keys(cfg.courses)[0], data: {}, activity: cfg.defaultActivity || '18', day: 0, slot: 0, preview: false, detailsOpen: false, heroVis: true, panelVis: true, docVis: !D.hidden, loading: false };\nvar fxSaved = sget(cfg.effects.storageKey, 'l');\nthis.fxOn = fxSaved === null ? cfg.effects.enabledByDefault !== false : fxSaved === true;\nthis.reduced = false;\ntry { this.mq = W.matchMedia('(prefers-reduced-motion: reduce)'); this.reduced = this.mq.matches; } catch (e) { this.mq = null; }\n\/* test mode: only for logged-in admins or WP preview *\/\nthis.test = null;\nvar tq = qp('ngg-ilm-test');\nif (tq) {\nvar allowed = D.body.classList.contains('logged-in') ? true : qp('preview') === 'true';\nif (allowed) { this.test = tq; }\n}\nthis.nowOffset = 0;\n\/* endpoint override for failure tests, same gate as test mode *\/\nvar ep = qp('ngg-ilm-endpoint');\nif (ep) { if (D.body.classList.contains('logged-in') ? true : qp('preview') === 'true') { cfg.provider = merge(cfg.provider, { endpoint: ep, proxyEndpoint: null }); this.epOverride = true; } }\nthis.hero = qs(mount.getAttribute('data-hero') || cfg.heroSelector);\nthis.buildPanel();\nif (this.hero) { this.buildFx(); }\nthis.observe();\nif (this.test) { this.buildTestBar(); this.applyFixture(this.test === '1' ? 'sunny' : this.test); }\nelse { this.load(this.st.course); }\nthis.tick = W.setInterval(function () { self.onTick(); }, 60000);\nINST.push(this);\n}\nvar P = Live.prototype;\nP.now = function () { return Date.now() + this.nowOffset; };\nP.course = function () { return this.cfg.courses[this.st.course]; };\n\/* data-state lives on the mount and, when the planner is placed elsewhere, on its host too *\/\nP.setState = function (s) {\nthis.mount.setAttribute('data-state', s);\nif (this.planHost) { this.planHost.setAttribute('data-state', s); }\n};\n\/* ----- panel DOM ----- *\/\nP.buildPanel = function () {\nvar self = this, T = this.T, cfg = this.cfg;\nvar m = this.mount;\nm.classList.add('ngg-lv', 'ngg-lv-sec', 'ngg-lv--' + (cfg.site === 'rae' ? 'rae' : 'wbg'));\nm.setAttribute('data-state', 'loading');\nvar bar = cfg.layout === 'bar';\nif (bar) { m.classList.add('ngg-lv--bar'); }\nvar keep = qs('.ngg-lv-fallback', m);\nif (keep) { keep.parentNode.removeChild(keep); }\nvar wrap = h('div', { class: 'ngg-lv-wrap' });\nthis.el = {};\nvar E = this.el;\nE.notice = h('div', { class: 'ngg-lv-notice', role: 'status', hidden: '' });\nwrap.appendChild(E.notice);\nvar grid = h('div', { class: 'ngg-lv-grid' });\n\/* T\u00e4na v\u00e4ljakul *\/\nvar now = h('article', { class: 'ngg-lv-card ngg-lv-now', 'aria-labelledby': 'ngg-lv-h-now' });\nvar head = h('div', { class: 'ngg-lv-head' });\nE.eyebrow = h('p', { class: 'ngg-lv-k', text: T.eyebrow });\nE.h = h('h2', { class: 'ngg-lv-h', id: 'ngg-lv-h-now', text: T.title });\nhead.appendChild(h('div', { class: 'ngg-lv-headtxt' }, [E.eyebrow, E.h]));\nE.fx = h('button', { type: 'button', class: 'ngg-lv-fxbtn', role: 'switch', 'aria-checked': this.fxOn ? 'true' : 'false' }, [h('span', { class: 'ngg-lv-fxdot', 'aria-hidden': 'true' }), h('span', { class: 'ngg-lv-fxlbl', text: this.fxOn ? T.fxOn : T.fxOff })]);\nE.fx.addEventListener('click', function () { self.setFx(!self.fxOn); });\nif (!bar) { head.appendChild(E.fx); }\nnow.appendChild(head);\nvar keys = Object.keys(cfg.courses);\nE.courseBtns = {};\n\/* course switch only when more than one course is configured (courseSwitch:false keeps the home course only) *\/\nif (keys.length > 1) {\nE.courseSeg = h('div', { class: 'ngg-lv-seg', role: 'group', 'aria-label': T.courseLabel });\nkeys.forEach(function (k) {\nvar b = h('button', { type: 'button', class: 'ngg-lv-segb', 'aria-pressed': k === self.st.course ? 'true' : 'false', 'data-k': k, text: cfg.courses[k].short });\nb.addEventListener('click', function () { self.setCourse(k); });\nE.courseBtns[k] = b; E.courseSeg.appendChild(b);\n});\nnow.appendChild(E.courseSeg);\n}\nE.copy = h('p', { class: 'ngg-lv-copy', 'aria-live': 'polite' });\nnow.appendChild(E.copy);\nvar main = h('div', { class: 'ngg-lv-main' });\nE.temp = h('span', { class: 'ngg-lv-temp', text: '\u2013\u00b0' });\nE.cond = h('span', { class: 'ngg-lv-cond', text: T.loading });\nE.feelsS = h('span', { class: 'ngg-lv-feels-s' });\nmain.appendChild(h('div', { class: 'ngg-lv-big' }, [E.temp, h('span', { class: 'ngg-lv-bigtxt' }, [E.cond, E.feelsS])]));\nvar flagBox = h('div', { class: 'ngg-lv-flag' });\nE.flagHold = h('div', { class: 'ngg-lv-flaghold' });\nflagBox.appendChild(E.flagHold);\nE.windBox = h('div', { class: 'ngg-lv-wind', role: 'img', 'aria-label': '' });\nE.arrow = h('span', { class: 'ngg-lv-arrow', 'aria-hidden': 'true' });\nE.arrow.innerHTML = '<svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"11\" fill=\"none\" stroke=\"currentColor\" stroke-opacity=\".28\"\/><path d=\"M12 4 L16.5 13 H13.2 V20 H10.8 V13 H7.5 Z\" fill=\"currentColor\"\/><\/svg>';\nE.windTxt = h('span', { class: 'ngg-lv-windtxt', 'aria-hidden': 'true' });\nE.windBox.appendChild(E.arrow); E.windBox.appendChild(E.windTxt);\nmain.appendChild(flagBox);\nmain.appendChild(E.windBox);\nnow.appendChild(main);\nthis.flag = new Flag(E.flagHold);\nE.detBtn = h('button', { type: 'button', class: 'ngg-lv-detbtn', 'aria-expanded': 'false', 'aria-controls': 'ngg-lv-det', text: T.detailsOpen });\nE.detBtn.addEventListener('click', function () { self.toggleDetails(); });\nnow.appendChild(E.detBtn);\nE.det = h('dl', { class: 'ngg-lv-det', id: 'ngg-lv-det' });\nfunction row(key, label) { var dt = h('dt', { text: label }), dd = h('dd', {}); var r = h('div', { class: 'ngg-lv-row ngg-lv-row--' + key }, [dt, dd]); E.det.appendChild(r); return { row: r, dt: dt, dd: dd }; }\nE.rFeels = row('feels', T.feels);\nE.rWind = row('wind', T.wind);\nE.rGust = row('gust', T.gusts);\nE.rPrecip = row('precip', fill(T.precipNext, { h: cfg.timeline.precipWindowHours }));\nE.rSun = row('sun', T.sunset);\nE.rCourse = row('course', T.statusCourse);\nE.rRange = row('range', T.statusRange);\nE.rCourse.row.hidden = true; E.rRange.row.hidden = true;\nnow.appendChild(E.det);\nE.official = h('p', { class: 'ngg-lv-official' });\nE.upd = h('p', { class: 'ngg-lv-upd' });\nvar pm = cfg.planSelector ? qs(cfg.planSelector) : null;\nif (bar) {\n\/* compact card: official status slot (filled by the integrator), then one footer line *\/\nE.statusSlot = h('div', { class: 'ngg-lv-status' });\nnow.appendChild(E.statusSlot);\nvar foot = h('div', { class: 'ngg-lv-foot' });\nvar links = h('p', { class: 'ngg-lv-links' });\nE.official = h('span', { class: 'ngg-lv-official' });\nlinks.appendChild(E.official);\nif (pm) { if (pm.id) { links.appendChild(h('a', { class: 'ngg-lv-link ngg-lv-planlink', href: '#' + pm.id, text: T.planTitle + ' \u2192' })); } }\nvar cl = cfg.courseLink ? (cfg.courseLink[this.lang] || null) : null;\nif (cl) { if (cl.href) { links.appendChild(h('a', { class: 'ngg-lv-link ngg-lv-xlink', href: cl.href, text: cl.text || cl.href })); } }\nlinks.appendChild(E.fx);\nfoot.appendChild(E.upd); foot.appendChild(links);\nnow.appendChild(foot);\n} else {\nnow.appendChild(E.official);\nnow.appendChild(E.upd);\n}\ngrid.appendChild(now);\n\/* Millal t\u00e4na m\u00e4ngida? *\/\nvar plan = h('article', { class: 'ngg-lv-card ngg-lv-plan', 'aria-labelledby': 'ngg-lv-h-plan' });\nE.planH = h('h2', { class: 'ngg-lv-h', id: 'ngg-lv-h-plan', text: T.planTitle });\nplan.appendChild(E.planH);\nvar ctr = h('div', { class: 'ngg-lv-ctrls' });\nE.actSeg = h('div', { class: 'ngg-lv-seg', role: 'group', 'aria-label': T.activityLabel });\nE.actBtns = {};\n[['9', T.hole9], ['18', T.hole18], ['range', T.range]].forEach(function (a) {\nvar b = h('button', { type: 'button', class: 'ngg-lv-segb', 'aria-pressed': a[0] === self.st.activity ? 'true' : 'false', text: a[1] });\nb.addEventListener('click', function () { self.setActivity(a[0]); });\nE.actBtns[a[0]] = b; E.actSeg.appendChild(b);\n});\nE.daySeg = h('div', { class: 'ngg-lv-seg', role: 'group', 'aria-label': T.dayLabel });\nE.dayBtns = [];\n[T.today, T.tomorrow].forEach(function (lbl, i) {\nvar b = h('button', { type: 'button', class: 'ngg-lv-segb', 'aria-pressed': i === 0 ? 'true' : 'false', text: lbl });\nb.addEventListener('click', function () { self.setDay(i); });\nE.dayBtns.push(b); E.daySeg.appendChild(b);\n});\nctr.appendChild(E.actSeg); ctr.appendChild(E.daySeg);\nplan.appendChild(ctr);\nvar sl = h('div', { class: 'ngg-lv-slide' });\nE.startOut = h('output', { class: 'ngg-lv-startout', 'for': 'ngg-lv-range', text: '\u2013' });\nsl.appendChild(h('div', { class: 'ngg-lv-slhead' }, [h('label', { 'for': 'ngg-lv-range', class: 'ngg-lv-sllbl', text: T.startLabel }), E.startOut]));\nE.strip = h('div', { class: 'ngg-lv-strip', 'aria-hidden': 'true' });\nsl.appendChild(E.strip);\nE.range = h('input', { type: 'range', id: 'ngg-lv-range', class: 'ngg-lv-range', min: '0', max: '0', step: '1', value: '0' });\nE.range.addEventListener('input', function () { self.setSlot(+E.range.value, true); });\nE.range.addEventListener('change', function () { push(self.siteName, 'elav-valjak', 'ngg_select', 'start-' + E.startOut.textContent); });\nsl.appendChild(E.range);\nE.ticks = h('div', { class: 'ngg-lv-ticks', 'aria-hidden': 'true' });\nsl.appendChild(E.ticks);\nplan.appendChild(sl);\nE.badge = h('p', { class: 'ngg-lv-badge', hidden: '' });\nplan.appendChild(E.badge);\nE.read = h('div', { class: 'ngg-lv-read', 'aria-live': 'polite' });\nplan.appendChild(E.read);\nvar btns = h('div', { class: 'ngg-lv-btns' });\nE.cta = h('a', { class: 'ngg-lv-btn ngg-lv-btn--main', href: this.course().booking, target: cfg.bookingTarget || '_self', text: T.ctaTee });\nE.cta.addEventListener('click', function () { push(self.siteName, 'elav-valjak', 'ngg_cta', self.st.activity === 'range' ? 'range-info' : 'tee-times-' + self.st.course); });\nE.back = h('button', { type: 'button', class: 'ngg-lv-btn ngg-lv-btn--line', hidden: '', text: T.back });\nE.back.addEventListener('click', function () { self.backToNow(); });\nbtns.appendChild(E.cta); btns.appendChild(E.back);\nplan.appendChild(btns);\nE.ctaNote = h('p', { class: 'ngg-lv-note', text: T.ctaNote });\nplan.appendChild(E.ctaNote);\nif (pm) {\n\/* planner in its own section further down the page *\/\nthis.planHost = pm;\npm.classList.add('ngg-lv', 'ngg-lv-planhost', 'ngg-lv--' + (cfg.site === 'rae' ? 'rae' : 'wbg'));\npm.setAttribute('data-state', 'loading');\nvar pf = qs('.ngg-lv-fallback', pm);\nif (pf) { pf.parentNode.removeChild(pf); }\npm.appendChild(plan);\n} else { grid.appendChild(plan); }\nwrap.appendChild(grid);\nm.appendChild(wrap);\n};\n\/* ----- hero effect layers ----- *\/\nP.buildFx = function () {\nvar hero = this.hero, cfg = this.cfg;\nhero.classList.add('ngg-lv-host');\ntry { if (W.getComputedStyle(hero).position === 'static') { hero.classList.add('ngg-lv-host--rel'); } } catch (e) { \/* ignore *\/ }\nthis.bg = qs(this.mount.getAttribute('data-bg') || cfg.bgSelector, hero);\nif (this.bg) { this.bg.classList.add('ngg-lv-bg'); }\nvar fx = h('div', { class: 'ngg-lv-fx', 'aria-hidden': 'true' });\nthis.fxEl = fx;\nthis.photo = h('img', { class: 'ngg-lv-photo', alt: '', decoding: 'async' });\nfx.appendChild(this.photo);\n['warm', 'cool', 'glow', 'spots', 'clouds', 'haze', 'scrim'].forEach(function (n) { fx.appendChild(h('div', { class: 'ngg-lv-l ngg-lv-' + n })); });\nthis.canvas = h('canvas', { class: 'ngg-lv-precip' });\nfx.appendChild(this.canvas);\nthis.hbadge = h('span', { class: 'ngg-lv-hbadge', hidden: '' });\nthis.hbadge.style.top = cfg.badgeTop;\nfx.appendChild(this.hbadge);\nif (this.bg) {\nif (this.bg.parentNode === hero) { hero.insertBefore(fx, this.bg.nextSibling); } else { hero.insertBefore(fx, hero.firstChild); }\n} else { hero.insertBefore(fx, hero.firstChild); }\n\/* keep hero content above the effect layers *\/\nArray.prototype.forEach.call(hero.children, function (ch) {\nif (ch === fx) { return; }\nif (ch.classList.contains('ngg-lv-bg')) { return; }\nif (ch.tagName === 'IMG') { return; }\ntry { var cs = W.getComputedStyle(ch); if (cs.position === 'static') { ch.classList.add('ngg-lv-above'); } else if (cs.zIndex === 'auto') { ch.classList.add('ngg-lv-above-z'); } } catch (e) { \/* ignore *\/ }\n});\nthis.precip = new Precip(this.canvas, cfg);\nthis.layout();\nthis.applyFxClass();\n};\nP.safeRect = function () {\nif (!this.hero) { return null; }\nvar hr = this.hero.getBoundingClientRect();\nvar els = qsa(this.cfg.contentSelector, this.hero);\nvar x1 = Infinity, y1 = Infinity, x2 = -Infinity, y2 = -Infinity, any = false;\nfor (var i = 0; i < els.length; i++) {\nvar e = els[i];\nif (this.fxEl.contains(e)) { continue; }\nvar r = e.getBoundingClientRect();\nif (r.width < 2) { continue; }\nif (r.height < 2) { continue; }\nif (r.bottom < hr.top) { continue; }\nif (r.top > hr.bottom) { continue; }\nany = true;\nx1 = Math.min(x1, r.left); y1 = Math.min(y1, r.top); x2 = Math.max(x2, r.right); y2 = Math.max(y2, r.bottom);\n}\nif (!any) { return null; }\nreturn { x: x1 - hr.left - 16, y: y1 - hr.top - 16, w: x2 - x1 + 32, h: y2 - y1 + 32 };\n};\nP.layout = function () {\nif (!this.hero) { return; }\nvar r = this.hero.getBoundingClientRect();\nvar safe = this.safeRect();\nthis.safe = safe;\nvar sc = qs('.ngg-lv-scrim', this.fxEl);\nif (sc) {\nif (safe) { sc.style.left = (safe.x - 40) + 'px'; sc.style.top = (safe.y - 40) + 'px'; sc.style.width = (safe.w + 80) + 'px'; sc.style.height = (safe.h + 80) + 'px'; sc.hidden = false; }\nelse { sc.hidden = true; }\n}\nthis.precip.resize(r.width, r.height, safe);\nthis.placeBadge();\nif (this.reduced) { this.renderStatic(); }\n};\nP.placeBadge = function () {\nvar b = this.hbadge;\nif (!b) { return; }\nif (b.hidden) { return; }\nb.classList.remove('ngg-lv-hbadge--off');\nif (!this.safe) { return; }\nvar hr = this.hero.getBoundingClientRect(), br = b.getBoundingClientRect();\nvar x = br.left - hr.left, y = br.top - hr.top, s0 = this.safe;\nvar overlap = !(x + br.width < s0.x || x > s0.x + s0.w || y + br.height < s0.y || y > s0.y + s0.h);\nif (overlap) { b.classList.add('ngg-lv-hbadge--off'); }\n};\nP.applyFxClass = function () {\nvar on = this.fxOn;\nif (this.mount.getAttribute('data-state') === 'error') { on = false; }\nif (this.hero) {\nthis.hero.classList.toggle('ngg-lv-fx-on', on);\nthis.hero.classList.toggle('ngg-lv-rm', this.reduced);\n}\nthis.mount.classList.toggle('ngg-lv-rm', this.reduced);\nthis.mount.classList.toggle('ngg-lv-fxoff', !this.fxOn);\n};\n\/* ----- observers, pause and resume ----- *\/\nP.observe = function () {\nvar self = this;\nif ('IntersectionObserver' in W) {\nvar io = new IntersectionObserver(function (ents) {\nents.forEach(function (en) {\nif (en.target === self.hero) { self.st.heroVis = en.isIntersecting; }\nif (en.target === self.el.flagHold) { self.st.panelVis = en.isIntersecting; }\n});\nself.loopCheck();\n}, { threshold: 0 });\nif (this.hero) { io.observe(this.hero); }\nio.observe(this.el.flagHold);\nthis.io = io;\n}\nD.addEventListener('visibilitychange', function () { self.st.docVis = !D.hidden; self.loopCheck(); if (!D.hidden) { self.onTick(); } });\nif (this.mq) {\nvar onMq = function () { self.reduced = self.mq.matches; self.applyFxClass(); self.loopCheck(); self.renderStatic(); };\nif (this.mq.addEventListener) { this.mq.addEventListener('change', onMq); } else if (this.mq.addListener) { this.mq.addListener(onMq); }\n}\nvar rt = null;\nvar onResize = function () { W.clearTimeout(rt); rt = W.setTimeout(function () { self.layout(); self.renderStrip(); }, 150); };\nif ('ResizeObserver' in W) { if (this.hero) { this.ro = new ResizeObserver(onResize); this.ro.observe(this.hero); } }\nW.addEventListener('resize', onResize);\nW.addEventListener('load', onResize);\nif (this.cfg.fullFxWhen) {\nif ('MutationObserver' in W) {\nif (this.hero) {\nvar mt = null;\nthis.mo = new MutationObserver(function () { W.clearTimeout(mt); mt = W.setTimeout(function () { if (self.mount.getAttribute('data-state') === 'ready') { self.renderAtmos(); } }, 60); });\nthis.mo.observe(this.bg || this.hero, { attributes: true, subtree: true, attributeFilter: ['class'] });\n}\n}\n}\n};\nP.running = function () {\nif (this.reduced) { return false; }\nif (!this.fxOn) { return false; }\nif (!this.st.docVis) { return false; }\nif (this.mount.getAttribute('data-state') !== 'ready') { return false; }\nreturn this.st.heroVis ? true : this.st.panelVis;\n};\nP.loopCheck = function () {\nvar self = this;\nvar paused = !this.st.docVis ? true : !this.st.heroVis;\nif (this.hero) { this.hero.classList.toggle('ngg-lv-paused', paused); }\nthis.mount.classList.toggle('ngg-lv-paused', !this.st.docVis ? true : !this.st.panelVis);\nif (this.running()) {\nif (!this.raf) {\nthis.last = 0;\nvar frame = function (ts) {\nif (!self.running()) { self.raf = 0; return; }\nvar dt = self.last ? Math.min(0.05, (ts - self.last) \/ 1000) : 0.016;\nself.last = ts;\nvar tsec = ts \/ 1000;\nif (self.st.heroVis) { if (self.precip) { if (self.precip.p.length) { self.precip.step(dt, tsec); } } }\nif (self.st.panelVis) { self.flag.draw(tsec); }\nself.raf = W.requestAnimationFrame(frame);\n};\nthis.raf = W.requestAnimationFrame(frame);\n}\n} else if (this.raf) { W.cancelAnimationFrame(this.raf); this.raf = 0; }\nif (!this.running()) { this.renderStatic(); }\n};\nP.renderStatic = function () {\nif (this.flag) { this.flag.drawStatic(); }\nif (this.precip) {\nif (this.reduced) { this.precip.step(0, 0); }\nif (!this.fxOn) { this.precip.ctx.clearRect(0, 0, this.precip.w, this.precip.h); }\n}\n};\n\/* ----- data loading with cache ----- *\/\nP.cacheKey = function (k) { return 'ngg-lv:v1:' + k + (this.epOverride ? ':ep' : ''); };\nP.load = function (k, force) {\nvar self = this, cfg = this.cfg, c = cfg.courses[k];\nvar now = this.now();\nvar cached = sget(this.cacheKey(k), 'l') || sget(this.cacheKey(k), 's');\nif (cached) { if (!force) { if (cached.expires > now) { this.useData(k, cached, false); return; } } }\nif (!c.coordsVerified) {\nvar adminish = D.body.classList.contains('logged-in') ? true : qp('preview') === 'true';\nif (!adminish) { this.fail(k, 'coords-unverified'); return; }\n}\nif (this.st.loading) { return; }\nthis.st.loading = true;\n\/* server proxy first (identifies itself to MET and caches), the direct MET call stays as a fallback *\/\nvar urls = MET.urls(cfg, c, k);\nvar staleProxy = null;\nif (!urls.length) { self.st.loading = false; if (cached) { this.useData(k, cached, true); } else { this.fail(k, 'no-endpoint'); } return; }\nvar attempt = function (i) {\nvar ctl = ('AbortController' in W) ? new AbortController() : null;\nvar to = W.setTimeout(function () { if (ctl) { ctl.abort(); } }, cfg.provider.timeoutMs || 8000);\nvar hdrExp = null, hdrLm = null;\n\/* simple GET, no custom headers (MET does not support preflight); the browser sends Origin itself *\/\nW.fetch(urls[i].url, { mode: 'cors', credentials: 'omit', signal: ctl ? ctl.signal : undefined })\n.then(function (r) {\nif (!r.ok) { throw new Error('HTTP ' + r.status); }\nhdrExp = r.headers.get('Expires'); hdrLm = r.headers.get('Last-Modified');\nreturn r.json();\n})\n.then(function (json) {\nW.clearTimeout(to);\nvar parsed = MET.parse(json);\nif (!parsed.series.length) { throw new Error('empty series'); }\nvar n = self.now();\nvar exp = hdrExp ? Date.parse(hdrExp) : NaN;\nvar got = n;\nif (urls[i].via === 'proxy') {\n\/* the proxy says when it last reached MET and when its copy expires *\/\n\/* age_s is server-side, so it does not depend on the visitor's clock *\/\nvar ag = num(json.age_s);\nvar pf = json.fetched ? Date.parse(json.fetched) : NaN;\nif (ag !== null) { got = n - ag * 1000; } else if (isFinite(pf)) { got = Math.min(n, pf); }\nvar pe = json.expires ? Date.parse(json.expires) : NaN;\nif (isFinite(pe)) { exp = pe; }\n}\nif (!isFinite(exp)) { exp = n + (cfg.provider.defaultCacheMinutes || 30) * 60000; }\nexp = Math.max(exp, n + (cfg.provider.minCacheMinutes || 10) * 60000);\nvar rec = { fetchedAt: got, expires: exp, lastModified: hdrLm, modelUpdated: parsed.modelUpdated, series: parsed.series, via: urls[i].via };\nif (urls[i].via === 'proxy') { if (json.stale === true) { staleProxy = rec; throw new Error('proxy stale'); } }\nself.st.loading = false;\nsset(self.cacheKey(k), rec, 'l');\nself.mount.setAttribute('data-src', urls[i].via);\nself.useData(k, rec, false);\n})\n.catch(function (err) {\nW.clearTimeout(to);\n\/* after a proxy failure the proxy is skipped for 15 min in this browser session *\/\nif (urls[i].via === 'proxy') { if (!staleProxy) { sset('ngg-lv-proxy-off', Date.now() + 15 * 60000, 's'); } }\nif (i + 1 < urls.length) { attempt(i + 1); return; }\nself.st.loading = false;\nvar back = staleProxy || cached;\nif (staleProxy) { if (cached) { if (cached.fetchedAt > staleProxy.fetchedAt) { back = cached; } } }\nif (back) { self.useData(k, back, true); } else { self.fail(k, String(err)); }\n});\n};\nattempt(0);\n};\nP.useData = function (k, rec, fetchFailed) {\nvar cfg = this.cfg, now = this.now();\nvar age = (now - rec.fetchedAt) \/ 60000;\nif (age > (cfg.provider.hideAfterMinutes || 240)) { this.fail(k, 'too-old'); return; }\nvar cur = this.entryAt(rec.series, now);\nif (!cur) { this.fail(k, 'no-current-hour'); return; }\nrec.stale = age > (cfg.provider.staleAfterMinutes || 120) ? true : (fetchFailed ? age > 60 : false);\nthis.st.data[k] = rec;\nif (k !== this.st.course) { return; }\nthis.setState('ready');\nthis.applyFxClass();\nif (!this.planInit) { this.planInit = true; this.st.day = 0; }\nthis.renderAll(true);\n};\nP.fail = function (k, why) {\nthis.st.data[k] = { error: why };\nif (k !== this.st.course) { return; }\nthis.setState('error');\nthis.mount.setAttribute('data-reason', why);\nthis.applyFxClass();\nthis.renderError();\nthis.loopCheck();\n};\nP.entryAt = function (series, ms) {\nif (!series) { return null; }\nfor (var i = 0; i < series.length; i++) { if (series[i].time <= ms) { if (ms < series[i].time + 3600000) { return series[i]; } } }\nreturn null;\n};\n\/* ----- rendering ----- *\/\nP.fmtTemp = function (v) { if (v === null) { return null; } var r = Math.round(v); return (r < 0 ? '\u2212' + Math.abs(r) : String(r)) + '\u00b0'; };\nP.fmtMs = function (v) { if (v === null) { return null; } var r = Math.round(v * 10) \/ 10; var t = (r >= 10 ? String(Math.round(r)) : r.toFixed(1)); return (this.lang === 'et' ? t.replace('.', ',') : t) + '\u00a0m\/s'; };\nP.dirName = function (d) { if (d === null) { return null; } return this.T.dirs[Math.round(((d % 360) + 360) % 360 \/ 45) % 8]; };\nP.dateLbl = function (ms) { var p = tparts(ms); var wd = this.T.wd[p.wd]; return wd + ' ' + p.d + '.' + p.m; };\nP.renderAll = function (resetSlot) {\nvar rec = this.st.data[this.st.course];\nif (!rec) { return; }\nif (rec.error) { return; }\nthis.renderNow();\nthis.buildSlots(resetSlot);\nthis.renderStrip();\nthis.renderRead();\nthis.renderAtmos();\nthis.loopCheck();\n};\nP.renderNow = function () {\nvar T = this.T, E = this.el, cfg = this.cfg, c = this.course(), rec = this.st.data[this.st.course];\nvar now = this.now(), cur = this.entryAt(rec.series, now);\nvar st = weatherState(cur, now, c, cfg);\nthis.liveState = st;\nvar miss = T.missing;\nvar tt = this.fmtTemp(cur.temp);\nE.temp.textContent = tt === null ? '\u2013\u00b0' : tt;\nE.temp.setAttribute('aria-label', tt === null ? T.missing : tt);\nvar cond = condText(cur.symbol, T);\nE.cond.textContent = cond === null ? '' : cond;\nvar fl = this.fmtTemp(cur.feels);\nE.feelsS.textContent = fl === null ? '' : T.feels + ' ' + fl;\nE.rFeels.dd.textContent = fl === null ? miss : fl;\nE.rFeels.row.classList.toggle('ngg-lv-row--na', fl === null);\n\/* wind *\/\nvar ws = this.fmtMs(cur.wind), gs = this.fmtMs(cur.gust), dn = this.dirName(cur.dirFrom);\nvar wtxt;\nif (ws === null) { wtxt = T.wind + ': ' + miss; }\nelse if (cur.wind < 0.5) { wtxt = T.wind + ' ' + ws + ', ' + T.windCalm; }\nelse { wtxt = T.wind + ' ' + ws + (dn === null ? '' : ', ' + fill(T.windBlows, { dir: dn })); }\nE.windTxt.textContent = wtxt + (gs === null ? '' : ' (' + fill(T.gustsUpTo, { v: gs }) + ')');\nE.windBox.setAttribute('aria-label', ws === null ? T.wind + ': ' + miss : fill(T.windAria, { v: ws, gust: gs === null ? '' : fill(T.gustsUpTo, { v: gs }) + ', ', dir: dn === null ? miss : dn }));\nif (cur.dirFrom === null) { E.arrow.hidden = true; } else { E.arrow.hidden = false; E.arrow.style.transform = 'rotate(' + ((cur.dirFrom + 180) % 360) + 'deg)'; }\nE.rWind.dd.textContent = ws === null ? miss : ws + (dn === null ? '' : ', ' + fill(T.windBlows, { dir: dn }));\nE.rGust.dd.textContent = gs === null ? miss : gs;\nE.rGust.row.classList.toggle('ngg-lv-row--na', gs === null);\n\/* precipitation, next hours *\/\nvar hrs = cfg.timeline.precipWindowHours || 3, maxP = null, sumMm = null, bars = [];\nfor (var i = 0; i < hrs; i++) {\nvar e = this.entryAt(rec.series, cur.time + i * 3600000);\nif (!e) { continue; }\nif (e.precipProb !== null) { maxP = maxP === null ? e.precipProb : Math.max(maxP, e.precipProb); }\nif (e.precipMm !== null) { sumMm = (sumMm === null ? 0 : sumMm) + e.precipMm; }\nbars.push(e);\n}\nE.rPrecip.dd.textContent = '';\nif (maxP !== null) {\nE.rPrecip.dt.textContent = fill(T.precipNext, { h: hrs });\nvar mini = h('span', { class: 'ngg-lv-mini', 'aria-hidden': 'true' });\nbars.forEach(function (b) { var bi = h('i', {}); bi.style.setProperty('--p', (b.precipProb === null ? 0 : b.precipProb) + '%'); mini.appendChild(bi); });\nE.rPrecip.dd.appendChild(D.createTextNode(fill(T.precipUpTo, { v: Math.round(maxP) + '%' }) + ' '));\nE.rPrecip.dd.appendChild(mini);\nE.rPrecip.row.classList.remove('ngg-lv-row--na');\n} else if (sumMm !== null) {\n\/* fallback when probability is missing: forecast amount *\/\nE.rPrecip.dt.textContent = fill(T.precipNext, { h: hrs });\nvar mmTxt = (Math.round(sumMm * 10) \/ 10).toFixed(1); if (this.lang === 'et') { mmTxt = mmTxt.replace('.', ','); }\nE.rPrecip.dd.textContent = fill(T.precipAmount, { v: mmTxt });\nE.rPrecip.row.classList.remove('ngg-lv-row--na');\n} else { E.rPrecip.dd.textContent = miss; E.rPrecip.row.classList.add('ngg-lv-row--na'); }\n\/* sun *\/\nvar sun = sunForLocalDay(now, c);\nif (sun.set !== null) {\nif (now < sun.set) { E.rSun.dt.textContent = T.sunset; E.rSun.dd.textContent = hhmm(sun.set); }\nelse { var tm = sunForLocalDay(now + 86400000, c); E.rSun.dt.textContent = T.sunrise; E.rSun.dd.textContent = tm.rise === null ? miss : hhmm(tm.rise); }\n}\nif (sun.rise !== null) { if (now < sun.rise) { E.rSun.dt.textContent = T.sunrise; E.rSun.dd.textContent = hhmm(sun.rise); } }\nthis.renderStatus();\n\/* updated line *\/\nif (cfg.layout === 'bar') { if (T.eyebrowDated) { E.eyebrow.textContent = fill(T.eyebrowDated, { d: this.dateLbl(now) }); } }\nE.upd.textContent = '';\n\/* timestamps: which forecast hour is shown, when MET issued it, when this page loaded it *\/\nvar stamp = T.stamp ? fill(T.stamp, { h: hhmm(cur.time), m: rec.modelUpdated ? hhmm(rec.modelUpdated) : '\u2013', t: hhmm(rec.fetchedAt) }) : fill(T.updated, { t: hhmm(rec.fetchedAt) });\nE.upd.appendChild(D.createTextNode(stamp + (rec.stale ? ' (' + T.stale + ')' : '') + ' \u00b7 '));\nE.upd.appendChild(D.createTextNode(fill(T.source, { src: '' })));\nvar a = h('a', { href: cfg.provider.sourceUrl, rel: 'noopener', text: cfg.provider.name });\nE.upd.appendChild(a);\nE.upd.appendChild(D.createTextNode(' (' + cfg.provider.licenseName + '). ' + T.modelNote));\nthis.mount.classList.toggle('ngg-lv-stale', !!rec.stale);\nthis.renderCopy(st);\nthis.flag.setWeather(st, cfg.effects.intensity.flag);\nif (!this.running()) { this.flag.drawStatic(); }\n};\nP.renderStatus = function () {\nvar T = this.T, E = this.el, cfg = this.cfg, k = this.st.course;\nvar S = cfg.status ? cfg.status[k] : null;\nfunction put(r, obj) {\nif (!obj) { r.row.hidden = true; return; }\nr.row.hidden = false; r.dd.textContent = obj.text || '';\nr.row.classList.toggle('ngg-lv-row--closed', obj.open === false);\n}\nvar rowsOn = cfg.statusRows !== false;\nput(E.rCourse, rowsOn ? (S ? S.course : null) : null);\nput(E.rRange, rowsOn ? (S ? S.range : null) : null);\nif (!this.course().hasRange) { E.rRange.row.hidden = true; }\n\/* notice: highest priority *\/\nif (S) { if (S.notice) { if (S.notice.text) { E.notice.hidden = false; E.notice.textContent = S.notice.text; E.notice.className = 'ngg-lv-notice ngg-lv-notice--' + (S.notice.level || 'info'); } else { E.notice.hidden = true; } } else { E.notice.hidden = true; } } else { E.notice.hidden = true; }\n\/* official info link *\/\nE.official.textContent = '';\nvar sl = this.course().statusLink || {};\nvar link = null;\nif (sl.modalTarget) { if (qs(sl.modalTarget)) { link = h('button', { type: 'button', class: 'ngg-lv-link', 'data-toggle': 'modal', 'data-target': sl.modalTarget, 'data-bs-toggle': 'modal', 'data-bs-target': sl.modalTarget, text: T.official }); } }\nif (!link) { if (sl.href) { link = h('a', { class: 'ngg-lv-link', href: sl.href, text: T.official }); } }\nif (link) { E.official.appendChild(link); E.official.hidden = false; } else { E.official.hidden = true; }\n};\nP.renderCopy = function (st) {\nvar cfg = this.cfg, k = this.st.course, lang = this.lang, E = this.el;\nvar S = cfg.status ? cfg.status[k] : null;\n\/* priority 1: official notice is shown in the notice bar; copy steps back to neutral *\/\nif (S) {\nif (S.notice) { if (S.notice.text) { E.copy.textContent = ''; E.copy.hidden = true; return; } }\n\/* priority 2: service status text *\/\nvar svc = S.course || S.range;\nif (svc) { if (svc.open === false) { E.copy.hidden = false; E.copy.textContent = svc.text; return; } }\n}\nE.copy.hidden = false;\nvar bucket = bucketOf(st);\nvar key = 'ngg-lv-copy:' + k + ':' + lang;\nvar prev = sget(key, 's');\nif (prev) { if (prev.b === bucket) { E.copy.textContent = prev.t; E.copy.setAttribute('data-bucket', bucket); return; } }\nvar ov = cfg.copyOverrides ? cfg.copyOverrides[k] : null;\nvar list = null;\nif (ov) { if (ov[lang]) { if (ov[lang][bucket]) { list = ov[lang][bucket]; } } }\nif (!list) { list = (cfg.copy[lang] || {})[bucket] || (cfg.copy[lang] || {}).neutral || ['']; }\nvar p = tparts(this.now());\nvar doy = Math.floor((Date.UTC(p.y, p.m - 1, p.d) - Date.UTC(p.y, 0, 1)) \/ 86400000);\nvar t = list[doy % list.length];\nE.copy.textContent = t; E.copy.setAttribute('data-bucket', bucket);\nsset(key, { b: bucket, t: t }, 's');\n};\n\/* ----- timeline ----- *\/\nP.slotsFor = function (day) {\nvar rec = this.st.data[this.st.course], cfg = this.cfg, now = this.now();\nvar tp = tparts(now);\nvar dp = day === 0 ? tp : addDays(tp, 1);\nvar slots = [];\nfor (var hh = cfg.timeline.firstHour; hh <= cfg.timeline.lastHour; hh++) {\nvar ms = localToUtc(dp.y, dp.m, dp.d, hh, 0);\nif (day === 0) { if (ms + 3600000 <= now) { continue; } }\nvar e = this.entryAt(rec.series, ms);\nif (!e) { continue; }\nslots.push({ ms: ms, startMs: day === 0 ? Math.max(ms, Math.floor(now \/ 60000) * 60000) : ms, e: e, hour: hh });\n}\nreturn { slots: slots, dp: dp };\n};\nP.buildSlots = function (reset) {\nvar cfg = this.cfg;\nvar wasAuto = this.autoDay;\nif (wasAuto) { if (!this.st.touched) { this.st.day = 0; } }\nvar r = this.slotsFor(this.st.day);\nthis.autoDay = false; this.autoReason = null;\n\/* no start times left today (late evening), or no 9\/18-hole round ends before sunset:\nshow tomorrow without treating it as a preview. The visitor can still pick \"Today\". *\/\nif (this.st.day === 0) {\nif (!this.st.touched) {\nvar noLight = false;\nvar act0 = cfg.activities[this.st.activity];\nif (r.slots.length) {\nif (act0) { if (act0.showDaylight) {\nvar c0 = this.course(), sun0 = sunTimes(r.dp.y, r.dp.m, r.dp.d, c0.lat, c0.lon);\nif (sun0.set !== null) {\nnoLight = true;\nfor (var q = 0; q < r.slots.length; q++) { if (r.slots[q].startMs + act0.minutes * 60000 <= sun0.set) { noLight = false; break; } }\n}\n} }\n}\nif (noLight ? true : !r.slots.length) {\nvar r2 = this.slotsFor(1);\nif (r2.slots.length) {\nr = r2; this.st.day = 1; this.autoDay = true; this.autoReason = noLight ? 'light' : 'late';\nif (!wasAuto) { reset = true; }\n}\n}\n}\n}\nif (wasAuto) { if (!this.autoDay) { reset = true; } }\nvar dsel = this.st.day;\nthis.el.dayBtns.forEach(function (b, j) { b.setAttribute('aria-pressed', j === dsel ? 'true' : 'false'); });\nvar slots = r.slots, dp = r.dp;\nthis.slots = slots;\nthis.dayParts = dp;\nvar E = this.el;\nE.range.max = String(Math.max(0, slots.length - 1));\nE.range.disabled = slots.length < 2;\nif (reset) {\nthis.st.slot = 0;\nif (this.st.day === 1) {\n\/* tomorrow starts at the first hour after sunrise *\/\nvar c = this.course(), sun = sunTimes(dp.y, dp.m, dp.d, c.lat, c.lon);\nif (sun.rise !== null) { for (var i = 0; i < slots.length; i++) { if (slots[i].ms >= sun.rise) { this.st.slot = i; break; } } }\n}\n}\nif (this.st.slot > slots.length - 1) { this.st.slot = Math.max(0, slots.length - 1); }\nE.range.value = String(this.st.slot);\n};\nP.renderStrip = function () {\nvar E = this.el, slots = this.slots || [], self = this;\nE.strip.textContent = ''; E.ticks.textContent = '';\nif (!slots.length) { return; }\nvar n = slots.length;\nvar act = this.cfg.activities[this.st.activity];\nvar span = Math.ceil(act.minutes \/ 60);\nvar c = this.course();\nvar sun = sunTimes(this.dayParts.y, this.dayParts.m, this.dayParts.d, c.lat, c.lon);\nvar tickEvery = n > 12 ? 3 : (n > 6 ? 2 : 1);\nslots.forEach(function (sl, i) {\nvar pos = n === 1 ? 0.5 : i \/ (n - 1);\nvar cell = h('span', { class: 'ngg-lv-cell' });\ncell.style.left = 'calc(14px + (100% - 28px) * ' + pos.toFixed(4) + ')';\nvar bar = h('i', { class: 'ngg-lv-cbar' });\nvar pp = sl.e.precipProb;\nif (pp === null) { if (sl.e.precipMm !== null) { pp = clamp(sl.e.precipMm * 40, 0, 100); } }\nbar.style.height = (pp === null ? 0 : Math.max(4, pp)) + '%';\nif (pp === null) { cell.classList.add('ngg-lv-cell--na'); }\ncell.appendChild(bar);\nif (i >= self.st.slot) { if (i < self.st.slot + span) { cell.classList.add('ngg-lv-cell--in'); } }\nif (i === self.st.slot) { cell.classList.add('ngg-lv-cell--sel'); }\nvar t = self.fmtTemp(sl.e.temp);\nif (i % tickEvery === 0) { cell.appendChild(h('b', { class: 'ngg-lv-ctemp', text: t === null ? '' : t })); }\nE.strip.appendChild(cell);\nif (i % tickEvery === 0) { var tk = h('span', { class: 'ngg-lv-tick', text: pad2(sl.hour) }); tk.style.left = cell.style.left; E.ticks.appendChild(tk); }\n});\nif (sun.set !== null) {\nvar first = slots[0].ms, last = slots[n - 1].ms;\nif (sun.set > first) {\nif (sun.set < last + 3600000) {\nvar f = n === 1 ? 0.5 : (sun.set - first) \/ (last - first);\nvar mk = h('span', { class: 'ngg-lv-sunset', title: this.T.sunset + ' ' + hhmm(sun.set) });\nmk.style.left = 'calc(14px + (100% - 28px) * ' + clamp(f, 0, 1.05).toFixed(4) + ')';\nE.strip.appendChild(mk);\n}\n}\n}\n};\nP.renderRead = function () {\nvar T = this.T, E = this.el, cfg = this.cfg, self = this;\nvar slots = this.slots || [];\nE.read.textContent = '';\nvar c = this.course();\nvar act = cfg.activities[this.st.activity];\n\/* CTA *\/\nif (this.st.activity === 'range') {\nif (c.rangeLink) { E.cta.href = c.rangeLink; E.cta.textContent = T.ctaRange; E.cta.hidden = false; }\nelse { E.cta.href = c.booking; E.cta.textContent = T.ctaTee; }\n} else { E.cta.href = this.bookingHref(c); E.cta.textContent = T.ctaTee; E.cta.hidden = false; }\nE.ctaNote.hidden = this.st.activity === 'range';\nif (!slots.length) {\nE.startOut.textContent = '\u2013';\nE.read.appendChild(h('p', { class: 'ngg-lv-rline', text: T.noSlotsToday }));\nE.badge.hidden = true; this.setHeroBadge(null);\nreturn;\n}\nvar sl = slots[this.st.slot];\nvar startMs = sl.startMs;\nvar endMs = startMs + act.minutes * 60000;\nE.startOut.textContent = hhmm(startMs);\nvar win = [];\nfor (var t = sl.ms; t < endMs; t += 3600000) { var e = this.entryAt(this.st.data[this.st.course].series, t); if (e) { win.push(e); } }\nvar tmin = null, tmax = null, wmax = null, gmax = null, pmax = null, dir = null;\nwin.forEach(function (e) {\nif (e.temp !== null) { tmin = tmin === null ? e.temp : Math.min(tmin, e.temp); tmax = tmax === null ? e.temp : Math.max(tmax, e.temp); }\nif (e.wind !== null) { if (wmax === null ? true : e.wind > wmax) { wmax = e.wind; dir = e.dirFrom; } }\nif (e.gust !== null) { gmax = gmax === null ? e.gust : Math.max(gmax, e.gust); }\nif (e.precipProb !== null) { pmax = pmax === null ? e.precipProb : Math.max(pmax, e.precipProb); }\n});\nvar cond = condText(sl.e.symbol, T);\nE.range.setAttribute('aria-valuetext', fill(T.startAria, { t: hhmm(startMs) }) + (cond ? ', ' + cond : '') + (tmax === null ? '' : ', ' + this.fmtTemp(tmax)));\nvar miss = T.missing;\nfunction line(label, val, cls) { var p = h('p', { class: 'ngg-lv-rline' + (cls ? ' ' + cls : '') }); if (label) { p.appendChild(h('b', { text: label + ' ' })); } p.appendChild(D.createTextNode(val)); E.read.appendChild(p); return p; }\nif (E.planH) { E.planH.textContent = this.st.day === 1 ? (T.planTitleTomorrow || T.planTitle) : T.planTitle; }\nif (this.autoDay) { line(null, (this.autoReason === 'light' ? T.autoTomorrowLight : null) || T.autoTomorrow || T.noSlotsToday, 'ngg-lv-rline--muted'); }\nline(null, fill(T.finish, { t: hhmm(endMs) }) + ' (' + T.estimate + ')' + (cond ? ' \u00b7 ' + cond : ''), 'ngg-lv-rline--lead');\nvar tTxt = tmin === null ? miss : (Math.round(tmin) === Math.round(tmax) ? this.fmtTemp(tmin) : this.fmtTemp(tmin) + '\u2026' + this.fmtTemp(tmax));\nline(T.windowTemp, tTxt);\nvar dn = this.dirName(dir);\nline(T.windowWind, wmax === null ? miss : this.fmtMs(wmax) + (gmax === null ? '' : ', ' + fill(T.gustsUpTo, { v: this.fmtMs(gmax) })) + (dn === null ? '' : ', ' + fill(T.windBlows, { dir: dn })));\nline(T.windowPrecip, pmax === null ? miss : fill(T.precipUpTo, { v: Math.round(pmax) + '%' }));\nif (act.showDaylight) {\nvar sun = sunTimes(this.dayParts.y, this.dayParts.m, this.dayParts.d, c.lat, c.lon);\nif (sun.set !== null) {\nvar diff = (sun.set - endMs) \/ 60000;\nvar txt;\nif (startMs >= sun.set) { txt = fill(T.daylightAfterDark, { t: hhmm(sun.set) }); }\nelse if (diff >= 0) { txt = fill(T.daylightPlus, { t: hhmm(sun.set), d: durTxt(diff) }); }\nelse { txt = fill(T.daylightMinus, { t: hhmm(sun.set), d: durTxt(-diff) }); }\nline(null, txt.replace(\/\\.$\/, '') + ' (' + T.estimate + ').', diff < 0 ? 'ngg-lv-rline--warn' : '');\n}\n}\nif (!this.autoDay) { line(null, fill(T.durationNote, { d: durTxt(act.minutes) }), 'ngg-lv-rline--muted'); }\n\/* preview badge *\/\nvar isNow = this.st.day === 0 ? this.st.slot === 0 : false;\n\/* the hero previews a future hour only after the visitor has chosen one *\/\nthis.st.preview = isNow ? false : !!this.st.touched;\nE.back.hidden = isNow ? true : !this.st.touched;\nif (isNow) { E.badge.hidden = true; this.setHeroBadge(null); }\nelse {\nvar bt = fill(T.forecastBadge, { d: this.dateLbl(startMs), t: hhmm(startMs) });\nE.badge.hidden = false; E.badge.textContent = bt; this.setHeroBadge(this.st.preview ? bt : null);\n}\n};\nP.bookingHref = function (c) {\n\/* Chronogolf documents no date parameter. '#?date=YYYY-MM-DD' was seen to work in a browser (11.10.2026) but is undocumented,\nso it is used only when config bookingDateHash is true. A forecast time is never passed as a free tee time. *\/\nif (this.cfg.bookingDateHash !== true) { return c.booking; }\nvar dp = this.dayParts;\nif (!dp) { return c.booking; }\nreturn c.booking.split('#')[0] + '#?date=' + dp.y + '-' + pad2(dp.m) + '-' + pad2(dp.d);\n};\nP.setHeroBadge = function (txt) {\nif (!this.hbadge) { return; }\nvar show = txt ? this.fxOn : false;\nif (this.mount.getAttribute('data-state') !== 'ready') { show = false; }\nthis.hbadge.hidden = !show;\nif (show) { this.hbadge.textContent = txt; this.placeBadge(); }\n};\nP.renderAtmos = function () {\nif (!this.hero) { return; }\nvar cfg = this.cfg, c = this.course();\nvar st = this.liveState;\nif (this.st.preview) {\nvar sl = this.slots[this.st.slot];\nif (sl) { st = weatherState(sl.e, sl.startMs, c, cfg); }\n}\nvar homeCourse = this.st.course === cfg.site;\nvar photo = null, pos = null;\nvar ph = c.photos || {};\n\/* tone-only mode: e.g. a hero tab that shows people, not the course (config fullFxWhen) *\/\nvar full = true;\nif (cfg.fullFxWhen) { full = !!qs(cfg.fullFxWhen, this.hero); }\n\/* from civil dusk on (sun below phases.nightPhotoBelow, default -4 deg) the course's own night photo is used *\/\nvar npb = num(cfg.phases.nightPhotoBelow);\nvar nightish = false;\nif (st) { if (st.phase === 'night') { nightish = true; } else if (npb !== null) { if (st.elev < npb) { nightish = true; } } }\nif (nightish) { if (full) { photo = ph.night || null; pos = ph.nightPosition || null; } }\n\/* optional per-state photos of the same course (photos.states: day, golden, evening, overcast, night) *\/\nif (st) { if (full) { if (homeCourse) { if (ph.states) { if (!photo) {\nvar sk = 'day';\nif (nightish) { sk = 'night'; }\nelse if (st.phase === 'golden') { sk = 'golden'; }\nelse if (st.phase === 'dusk') { sk = 'evening'; }\nelse if (st.phase === 'dawn') { sk = 'golden'; }\nif (sk !== 'night') { if (st.sky === 'cloudy' || st.sky === 'fog' || st.precip !== 'none') { sk = 'overcast'; } }\nvar so = ph.states[sk] || null;\nif (so) { if (typeof so === 'string') { photo = so; } else { photo = so.src || null; pos = so.position || null; } }\n} } } } }\nif (!homeCourse) { if (!photo) { photo = ph['default'] || null; pos = ph.defaultPosition || null; } }\n\/* never show weather of one course on a photo of the other *\/\nif (!homeCourse) { if (!photo) { st = null; } }\nthis.setPhoto(photo, pos);\nvar g = grade(st, cfg.effects.intensity);\n\/* the photo must stay clearly visible in every phase; only the text-safe zone is darkened (scrim) *\/\nvar EF = cfg.effects;\nvar mb = num(EF.minBrightness), mc = num(EF.maxCoolA), mx = num(EF.maxShadowA);\nif (mb !== null) { g.bri = Math.max(g.bri, mb); g.sat = Math.max(g.sat, mb); g.con = Math.max(g.con, 0.94); }\nif (mc !== null) { g.coolA = Math.min(g.coolA, mc); }\nif (mx !== null) { g.shadow = Math.min(g.shadow, mx); }\nif (photo) { if (nightish) { g.bri = Math.max(g.bri, 0.97); g.sat = Math.max(g.sat, 0.92); g.coolA = Math.min(g.coolA, 0.06); g.warmA *= 0.4; g.glow = 0; g.spots = 0; } }\nthis.hero.setAttribute('data-lv-photo', photo ? (nightish ? 'night' : 'alt') : 'base');\nif (!full) { g.spots = 0; g.shadow = 0; g.rain = 0; g.snow = 0; g.kind = 'none'; g.haze *= 0.5; g.glow *= 0.5; }\nthis.hero.setAttribute('data-lv-mode', full ? 'full' : 'tone');\nvar hs = this.hero.style;\nhs.setProperty('--lv-bri', g.bri.toFixed(3)); hs.setProperty('--lv-sat', g.sat.toFixed(3)); hs.setProperty('--lv-con', g.con.toFixed(3));\nhs.setProperty('--lv-warm', g.warm); hs.setProperty('--lv-warm-a', g.warmA.toFixed(3));\nhs.setProperty('--lv-cool', g.cool); hs.setProperty('--lv-cool-a', g.coolA.toFixed(3));\nhs.setProperty('--lv-glow-a', g.glow.toFixed(3)); hs.setProperty('--lv-glow-x', g.glowX); hs.setProperty('--lv-glow-y', g.glowY);\nhs.setProperty('--lv-spots-a', g.spots.toFixed(3)); hs.setProperty('--lv-shadow-a', g.shadow.toFixed(3)); hs.setProperty('--lv-haze-a', g.haze.toFixed(3));\nhs.setProperty('--lv-scrim-a', g.scrim.toFixed(3));\nvar wind = st ? (st.wind === null ? 3 : st.wind) : 3;\nhs.setProperty('--lv-drift', Math.round(clamp(160 - wind * 9, 50, 160)) + 's');\nvar wx = 0;\nif (st) { if (st.dirFrom !== null) { if (st.wind !== null) { wx = Math.sin(rad((st.dirFrom + 180) % 360)) * clamp(st.wind \/ 10, 0, 1); } } }\nif (this.precip) { this.precip.set(g.kind, g.rain, g.snow, wx); }\nthis.hero.setAttribute('data-lv-phase', st ? st.phase : 'none');\nthis.hero.setAttribute('data-lv-sky', st ? (st.sky || 'none') : 'none');\nthis.hero.setAttribute('data-lv-precip', st ? st.precip : 'none');\nthis.loopCheck();\nif (this.reduced) { if (this.precip) { this.precip.step(0, 0); } }\n};\nP.setPhoto = function (src, pos) {\nvar im = this.photo;\nif (!im) { return; }\nim.style.objectPosition = pos || '50% 50%';\nif (!src) { im.classList.remove('ngg-lv-photo--on'); return; }\nif (im.getAttribute('src') === src) { if (im.complete) { im.classList.add('ngg-lv-photo--on'); } return; }\nim.classList.remove('ngg-lv-photo--on');\nim.onload = function () { im.classList.add('ngg-lv-photo--on'); };\nim.onerror = function () { im.classList.remove('ngg-lv-photo--on'); };\nim.src = src;\n};\nP.renderError = function () {\nvar T = this.T, E = this.el;\nE.temp.textContent = '\u2013\u00b0'; E.temp.setAttribute('aria-label', T.missing);\nE.cond.textContent = ''; E.feelsS.textContent = '';\nE.windTxt.textContent = ''; E.windBox.setAttribute('aria-label', T.missing); E.arrow.hidden = true;\nE.copy.hidden = false; E.copy.textContent = T.error;\nE.upd.textContent = '';\nthis.renderStatus();\nE.read.textContent = '';\nE.read.appendChild(h('p', { class: 'ngg-lv-rline', text: T.error }));\nE.strip.textContent = ''; E.ticks.textContent = '';\nE.range.disabled = true; E.startOut.textContent = '\u2013';\nE.badge.hidden = true; E.back.hidden = true;\nE.cta.href = this.course().booking; E.cta.textContent = T.ctaTee; E.cta.hidden = false;\nthis.setHeroBadge(null);\nthis.flag.setWeather(null, 0); this.flag.drawStatic();\nif (this.hero) {\nthis.setPhoto(null);\n['--lv-bri', '--lv-sat', '--lv-con'].forEach(function (k) { this.hero.style.setProperty(k, '1'); }, this);\nif (this.precip) { this.precip.set('none', 0, 0, 0); this.precip.ctx.clearRect(0, 0, this.precip.w, this.precip.h); }\nthis.hero.setAttribute('data-lv-phase', 'none');\n}\n};\n\/* ----- interactions ----- *\/\nP.setFx = function (on) {\nthis.fxOn = on;\nsset(this.cfg.effects.storageKey, on, 'l');\nthis.el.fx.setAttribute('aria-checked', on ? 'true' : 'false');\nthis.el.fx.querySelector('.ngg-lv-fxlbl').textContent = on ? this.T.fxOn : this.T.fxOff;\nthis.applyFxClass();\nif (this.st.data[this.st.course]) { if (!this.st.data[this.st.course].error) { this.renderRead(); this.renderAtmos(); } }\nthis.loopCheck();\nif (!on) { this.renderStatic(); }\npush(this.siteName, 'elav-valjak', 'ngg_select', on ? 'effects-on' : 'effects-off');\n};\nP.setCourse = function (k) {\nif (k === this.st.course) { return; }\nthis.st.course = k;\nvar self = this;\nObject.keys(this.el.courseBtns).forEach(function (kk) { self.el.courseBtns[kk].setAttribute('aria-pressed', kk === k ? 'true' : 'false'); });\nthis.el.actBtns.range.hidden = !this.course().hasRange;\nif (this.st.activity === 'range') { if (!this.course().hasRange) { this.setActivity(this.cfg.defaultActivity || '18'); } }\npush(this.siteName, 'elav-valjak', 'ngg_select', 'course-' + k);\nvar d = this.st.data[k];\nthis.planInit = false;\nthis.st.touched = false; this.st.day = 0;\nthis.el.dayBtns.forEach(function (b, j) { b.setAttribute('aria-pressed', j === 0 ? 'true' : 'false'); });\nif (this.test) { this.applyFixture(this.testName, true); return; }\nif (d) { if (d.error) { this.fail(k, d.error); return; } this.setState('ready'); this.applyFxClass(); this.renderAll(true); return; }\nthis.setState('loading');\nthis.el.cond.textContent = this.T.loading;\nthis.load(k);\n};\nP.setActivity = function (a) {\nthis.st.activity = a;\nvar self = this;\nObject.keys(this.el.actBtns).forEach(function (k) { self.el.actBtns[k].setAttribute('aria-pressed', k === a ? 'true' : 'false'); });\npush(this.siteName, 'elav-valjak', 'ngg_select', 'activity-' + a);\nif (this.mount.getAttribute('data-state') === 'ready') {\n\/* re-check the automatic \"tomorrow\" choice for the new activity (daylight differs for 9, 18 and range) *\/\nif (!this.st.touched) { this.buildSlots(false); }\nthis.renderStrip(); this.renderRead(); this.renderAtmos();\n} else { this.renderError(); }\n};\nP.setDay = function (i, auto) {\nthis.st.day = i;\nif (!auto) { this.st.touched = true; }\nvar self = this;\nthis.el.dayBtns.forEach(function (b, j) { b.setAttribute('aria-pressed', j === i ? 'true' : 'false'); });\npush(this.siteName, 'elav-valjak', 'ngg_select', i === 0 ? 'today' : 'tomorrow');\nif (this.mount.getAttribute('data-state') !== 'ready') { return; }\nthis.buildSlots(true);\nthis.renderStrip(); this.renderRead(); this.renderAtmos();\n};\nP.setSlot = function (i, fromInput) {\nthis.st.slot = i;\nthis.st.touched = true;\nif (!fromInput) { this.el.range.value = String(i); }\nvar self = this;\n\/* read-out and aria-valuetext synchronously, so keyboard and screen readers get the new value at once *\/\nthis.renderRead();\nif (this.slotRaf) { return; }\nthis.slotRaf = W.requestAnimationFrame(function () { self.slotRaf = 0; self.renderStrip(); if (self.fxOn) { self.renderAtmos(); } });\n};\nP.backToNow = function () {\nthis.st.touched = false;\nthis.setDay(0, true);\nthis.st.touched = false;\nthis.buildSlots(true);\nthis.renderStrip(); this.renderRead(); this.renderAtmos();\ntry { this.el.range.focus(); } catch (e) { \/* ignore *\/ }\n};\nP.toggleDetails = function () {\nvar o = !this.st.detailsOpen;\nthis.st.detailsOpen = o;\nthis.mount.classList.toggle('ngg-lv-open', o);\nthis.el.detBtn.setAttribute('aria-expanded', o ? 'true' : 'false');\nthis.el.detBtn.textContent = o ? this.T.detailsClose : this.T.detailsOpen;\n};\nP.onTick = function () {\nif (this.test) { return; }\nvar k = this.st.course, rec = this.st.data[k];\nif (!rec) { return; }\nif (rec.error) { return; }\nif (this.now() > rec.expires) { if (this.st.docVis) { this.load(k, true); return; } }\nvar cur = this.entryAt(rec.series, this.now());\nif (!cur) { this.fail(k, 'no-current-hour'); return; }\nthis.renderNow();\nif (!this.st.preview) { this.buildSlots(false); this.renderStrip(); this.renderRead(); this.renderAtmos(); }\n};\nP.reload = function (patch) {\nvar self = this;\nif (patch) { this.cfg = merge(this.cfg, patch); }\nObject.keys(this.cfg.courses).forEach(function (k) { try { W.localStorage.removeItem(self.cacheKey(k)); } catch (e) { \/* ignore *\/ } });\nthis.st.data = {}; this.test = null; this.nowOffset = 0; this.st.loading = false;\nthis.mount.removeAttribute('data-fixture');\nthis.setState('loading');\nthis.el.cond.textContent = this.T.loading;\nthis.load(this.st.course, true);\n};\nP.setStatus = function (k, obj) {\nthis.cfg.status = this.cfg.status || {};\nthis.cfg.status[k] = obj;\nif (k === this.st.course) {\nif (this.mount.getAttribute('data-state') === 'ready') { this.renderNow(); } else { this.renderStatus(); }\n}\n};\n\/* ----- test mode ----- *\/\nP.buildTestBar = function () {\nvar self = this;\nvar bar = h('div', { class: 'ngg-lv-test', role: 'region', 'aria-label': this.T.testMode });\nvar sel = h('select', { 'aria-label': this.T.testMode });\nObject.keys(FIXTURES).forEach(function (k) { var o = h('option', { value: k, text: FIXTURES[k].label + ' (' + k + ')' }); sel.appendChild(o); });\nsel.addEventListener('change', function () { self.applyFixture(sel.value); });\nbar.appendChild(h('b', { text: this.T.testMode + ' ' }));\nbar.appendChild(sel);\nthis.testSel = sel;\nthis.mount.insertBefore(bar, this.mount.firstChild);\n};\nP.applyFixture = function (name, keepCourse) {\nvar fx = FIXTURES[name] || FIXTURES.sunny;\nif (!FIXTURES[name]) { name = 'sunny'; }\nthis.testName = name;\nif (this.testSel) { this.testSel.value = name; }\nvar nq = qp('ngg-ilm-now') || fx.now;\nvar tp = tparts(Date.now());\nif (String(nq).indexOf('sunset') === 0) {\nvar c0 = this.course(), sn = sunTimes(tp.y, tp.m, tp.d, c0.lat, c0.lon);\nvar offm = parseInt(String(nq).slice(6), 10) || 0;\nthis.nowOffset = (sn.set === null ? Date.now() : sn.set + offm * 60000) - Date.now();\n} else {\nvar hm = nq.split(':');\nthis.nowOffset = localToUtc(tp.y, tp.m, tp.d, +hm[0], +(hm[1] || 0)) - Date.now();\n}\nthis.mount.setAttribute('data-fixture', name);\nvar k = this.st.course, c = this.course();\nif (!keepCourse) { this.st.data = {}; }\nthis.planInit = false;\ntry { W.sessionStorage.removeItem('ngg-lv-copy:' + k + ':' + this.lang); } catch (e) { \/* ignore *\/ }\nif (fx.error) { this.fail(k, 'fixture-error'); return; }\nvar now = this.now();\nvar parsed = MET.parse(fixturePayload(fx, k, c, now));\nvar rec = { fetchedAt: now - 4 * 60000, expires: now + 30 * 60000, modelUpdated: parsed.modelUpdated, series: parsed.series };\nthis.st.day = 0; this.st.touched = false; this.el.dayBtns.forEach(function (b, j) { b.setAttribute('aria-pressed', j === 0 ? 'true' : 'false'); });\nthis.useData(k, rec, false);\nif (fx.day) {\nthis.setDay(fx.day);\nvar self = this;\nvar idx = 0;\nthis.slots.forEach(function (s0, i) { if (s0.hour === fx.slot) { idx = i; } });\nthis.setSlot(idx, false);\nW.requestAnimationFrame(function () { self.renderStrip(); self.renderRead(); self.renderAtmos(); });\n}\n};\n\/* ---------- boot ---------- *\/\nfunction boot() {\nqsa('[data-ngg-lv]').forEach(function (m) {\nif (m.getAttribute('data-ngg-lv-ready')) { return; }\nm.setAttribute('data-ngg-lv-ready', '1');\ntry { new Live(m); } catch (e) { m.setAttribute('data-state', 'error'); if (W.console) { W.console.error('ngg-lv', e); } }\n});\n}\nW.NGGLV = {\nbooted: true,\nversion: VERSION,\ninstances: INST,\nsetStatus: function (k, obj) { INST.forEach(function (i) { i.setStatus(k, obj); }); },\nreload: function (patch) { INST.forEach(function (i) { i.reload(patch); }); },\n_t: { sunTimes: sunTimes, sunElev: sunElev, feelsLike: feelsLike, parse: MET.parse, url: MET.url, symbolInfo: symbolInfo, condText: condText, bucketOf: bucketOf, weatherState: weatherState, fixtures: FIXTURES, fixturePayload: fixturePayload, tparts: tparts, localToUtc: localToUtc }\n};\nif (D.readyState === 'loading') { D.addEventListener('DOMContentLoaded', boot); } else { boot(); }\n})();\n\n<\/script>\n<script id=\"ngg-lv-bridge\">\n(function(){\nfunction txt(e){return e?String(e.textContent||'').replace(\/\\s+\/g,' ').trim():'';}\nfunction low(s){return s?s.charAt(0).toLowerCase()+s.slice(1):s;}\nfunction read(){\nvar md=document.getElementById('infoModal');\nif(!md){return null;}\nvar out={notice:null,course:null,range:null,source:'Valgeranna #infoModal'};\n[].forEach.call(md.querySelectorAll('.wp-block-columns'),function(row){\nvar c=row.querySelectorAll('.wp-block-column');\nif(c.length<2){return;}\nvar name=txt(c[0]),val=txt(c[1]);\nif(!\/^(v\u00e4ljak|course)$\/i.test(name)){return;}\nif(!val){return;}\nvar o=null;\nif(\/suletud|closed\/i.test(val)){o=false;out.notice={text:name+': '+val,level:'closed'};}\nelse if(\/^(avatud|open)$\/i.test(val)){o=true;}\nout.course={text:low(val),open:o};\n});\nreturn out;\n}\nfunction run(){\nif(!window.NGGLV){return false;}\nvar st=read();\nif(!st){return false;}\nwindow.NGGLV.setStatus('valgeranna',st);\nreturn true;\n}\nfunction later(){run();setTimeout(run,400);setTimeout(run,1500);}\nif(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',later);}else{later();}\nwindow.addEventListener('load',later);\n})();\n<\/script>\n<style id=\"ngg-lv-integ\">#ngg-lv .ngg-lv-today{margin-top:16px;border-radius:24px;overflow:hidden;background:#fff;box-shadow:0 1px 0 #cbd7db}#ngg-lv.ngg-lv--wbg .ngg-lv-wrap{max-width:1320px}@media(min-width:768px){#ngg-lv.ngg-lv--wbg .ngg-lv-wrap{padding-left:max(12px,min(max(16px,5vw),724px - 50vw));padding-right:max(12px,min(max(16px,5vw),724px - 50vw))}}@media(min-width:1440px){#ngg-lv.ngg-lv--wbg .ngg-lv-wrap{max-width:calc(var(--ngg-wide-max,1480px) + 2*var(--ngg-wide-g,48px));padding-left:var(--ngg-wide-g,48px);padding-right:var(--ngg-wide-g,48px)}}@media(min-width:1200px){#ngg-lv.ngg-lv--wbg .ngg-lv-btns{margin-bottom:72px}}<\/style>\n\n\n\n<div class=\"ngg-x ngg-home\">\n<section class=\"ngg-x-sec ngg-x-sec--tight ngg-now\" data-ngg=\"home_offers\" aria-labelledby=\"ngg-now-h\">\n<div class=\"ngg-x__in\">\n<div class=\"ngg-x-head ngg-x-head--split\"><div><span class=\"ngg-x-k\">Now at Valgeranna<\/span><h2 class=\"ngg-x-h\" id=\"ngg-now-h\">The last weeks of the season.<\/h2><\/div><p class=\"ngg-x-lead\">Here are all current offers and their end dates.<\/p><\/div>\n<div class=\"ngg-now__grid\">\n<article class=\"ngg-x-card\" data-until=\"2026-10-10\"><span class=\"ngg-x-flag ngg-x-flag--blue\">Saturday 10.10<\/span><h3 class=\"ngg-x-h3\">Season final competition and party<\/h3><p>Valgeranna Golf Club members and candidate members are especially welcome. Breakfast at 10.30, shotgun start at 11.30.<\/p><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"https:\/\/www.wbg.ee\/news\/hooaja-lopuvoistlus-ja-lopupidu-10-oktoobril\/\" data-ngg-cta=\"offer_view\" data-ngg-val=\"lopuvoistlus\">See the programme<\/a><\/article>\n<article class=\"ngg-x-card\" data-until=\"2026-10-11\"><span class=\"ngg-x-flag\">Until Sun 11.10<\/span><h3 class=\"ngg-x-h3\">2=1 \u2013 play with a friend for one green fee<\/h3><p>You come as two, and one of you pays. It is for two players without a playing right, at Valgeranna and at Rae. It does not apply when you play with a voucher.<\/p><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget&amp;source=club\" data-ngg-cta=\"offer_view\" data-ngg-val=\"2for1\">Book a tee time<\/a><\/article>\n<article class=\"ngg-x-card\" data-until=\"2026-10-15\"><span class=\"ngg-x-flag\">Until Thu 15.10<\/span><h3 class=\"ngg-x-h3\">Swap vouchers for a playing right<\/h3><p>Use your unused green fee vouchers to pay for the 2027 playing right. On top of that, you get 1&nbsp;000 range balls from us.<\/p><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"https:\/\/raegolf.ee\/en\/vouchers-2027\/\" data-ngg-cta=\"offer_view\" data-ngg-val=\"voucherid\">Calculate your price<\/a><\/article>\n<\/div>\n<\/div>\n<\/section>\n<\/div>\n\n\n\n<div class=\"ngg-x ngg-home ngg-td\" data-site=\"valgeranna\">\n<style>\n.ngg-td .ngg-x-sec{scroll-margin-top:120px}\n.ngg-td__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin-top:28px}\n.ngg-td__c{background:#fff;border:1px solid #cbd7db;border-radius:20px;padding:24px;display:flex;flex-direction:column;gap:12px;min-width:0}\n.ngg-td__c .ngg-x-k{margin:0}\n.ngg-td__c .ngg-x-h3{margin:0}\n.ngg-td__st{display:flex;align-items:flex-start;gap:8px;margin:0;font-weight:700;color:#0b1d3a;line-height:1.4}\n.ngg-td__st::before{content:\"\";width:10px;height:10px;margin-top:.4em;border-radius:50%;background:#9aa8b5;flex:none}\n.ngg-td__st[data-state=\"open\"]::before{background:#1f8a5b}\n.ngg-td__st[data-state=\"closed\"]::before{background:#b8433f}\n.ngg-td__fee{list-style:none;margin:0;padding:0;display:grid;gap:6px}\n.ngg-td__fee li{display:flex;flex-wrap:wrap;justify-content:space-between;gap:4px 10px;padding:9px 12px;border-radius:12px;background:#f2ece2;color:#0b1d3a;font-size:15px;line-height:1.35}\n.ngg-td__fee li.is-today{background:#073875;color:#fff}\n.ngg-td__now{font-style:normal;font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;margin-left:8px;padding:2px 8px;border-radius:999px;background:#aff4ed;color:#0b1d3a}\n.ngg-td__s{margin:0;color:#3c4b63;font-size:15px;line-height:1.5}\n.ngg-td__c .ngg-x-btns{margin-top:auto;padding-top:6px}\n.ngg-td__more{display:flex;flex-wrap:wrap;gap:8px;margin-top:20px}\n.ngg-td__chip{display:inline-flex;align-items:center;min-height:44px;padding:0 18px;border-radius:999px;border:1px solid #cbd7db;background:#fff;color:#0b1d3a;font:700 14px\/1.2 \"Google Sans\",system-ui,sans-serif;text-decoration:none;cursor:pointer}\n.ngg-td__chip:hover{border-color:#073875;color:#073875}\n.ngg-td__chip:focus-visible,.ngg-td a:focus-visible{outline:3px solid #073875;outline-offset:3px}\n.ngg-in__today [data-today] span[data-state=\"open\"] i::after,.ngg-in__today [data-today] span[data-state=\"closed\"] i::after{content:\"\";display:inline-block;width:7px;height:7px;margin-left:6px;border-radius:50%;background:#7fe0b4;vertical-align:middle}\n.ngg-in__today [data-today] span[data-state=\"closed\"] i::after{background:#f39595}\n.ngg-td__st:empty{display:none}\n@media(max-width:900px){.ngg-td__grid{grid-template-columns:1fr}.ngg-td__c{padding:20px}}\n<\/style>\n<section class=\"ngg-x-sec ngg-x-sec--sand\" id=\"tana\" data-ngg=\"home_today\" aria-labelledby=\"ngg-td-h\">\n<div class=\"ngg-x__in\">\n<div class=\"ngg-x-head ngg-x-head--split\"><div><span class=\"ngg-x-k\">Today at Valgeranna<\/span><h2 class=\"ngg-x-h\" id=\"ngg-td-h\">What you can do today.<\/h2><\/div><p class=\"ngg-x-lead\"><span data-td-date><\/span>See what is open now and what opens next.<\/p><\/div>\n<div class=\"ngg-td__grid\">\n<article class=\"ngg-td__c\">\n<span class=\"ngg-x-k\">Course<\/span>\n<h3 class=\"ngg-x-h3\">Play a round.<\/h3>\n<p class=\"ngg-td__st\" data-td-st=\"course\">See the opening hours for the course status.<\/p>\n<ul class=\"ngg-td__fee\" aria-label=\"Green fee\">\n<li><span>Mon\u2013Sun<\/span><b>Tee times 10:30\u201315:30<\/b><\/li>\n<\/ul>\n<p class=\"ngg-td__s\">The course, driving range and practice areas are open daily, tee times 10:30\u201315:30. Caddiemaster and pro shop Mon\u2013Sun 10:00\u201313:00. Children up to 12 play free, ages 13\u201321 pay half price. You can see free tee times in the booking.<\/p>\n<div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--main\" href=\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget&amp;source=club\" target=\"_blank\" rel=\"noopener\" data-ngg-cta=\"book\" data-ngg-val=\"today\">Book a tee time<\/a><\/div>\n<\/article>\n<article class=\"ngg-td__c\">\n<span class=\"ngg-x-k\">Clubhouse and caddiemaster<\/span>\n<h3 class=\"ngg-x-h3\">Balls, rental and help.<\/h3>\n<p class=\"ngg-td__st\" data-td-st=\"club\">Clubhouse: see opening hours.<\/p>\n<p class=\"ngg-td__st\" data-td-st=\"cm\"><\/p>\n<p class=\"ngg-td__s\">Range balls 25 for 4&nbsp;\u20ac. Golf set rental 15&nbsp;\u20ac. Any questions? Call the caddiemaster.<\/p>\n<div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"tel:+3724429930\" data-ngg-cta=\"call_caddiemaster\">Call the caddiemaster<\/a><\/div>\n<\/article>\n<article class=\"ngg-td__c\">\n<span class=\"ngg-x-k\">Restaurant<\/span>\n<h3 class=\"ngg-x-h3\">Eat after your round.<\/h3>\n<p class=\"ngg-td__st\" data-td-st=\"resto\">Restaurant: see opening hours.<\/p>\n<p class=\"ngg-td__s\">Lunch in the clubhouse restaurant. Coming with a larger group? Let us know in advance.<\/p>\n<div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"https:\/\/www.wbg.ee\/en\/restaurant-white-beach-golf\/\" data-ngg-cta=\"restaurant\">See the restaurant<\/a><\/div>\n<\/article>\n<\/div>\n<div class=\"ngg-td__more\"><button type=\"button\" class=\"ngg-td__chip\" data-bs-toggle=\"modal\" data-bs-target=\"#infoModal\" data-ngg-cta=\"info\">All opening hours<\/button><a class=\"ngg-td__chip\" href=\"https:\/\/www.wbg.ee\/en\/treeningud\/\" data-ngg-cta=\"trainings\">Training<\/a><a class=\"ngg-td__chip\" href=\"https:\/\/www.wbg.ee\/en\/events\/\" data-ngg-cta=\"events\">Events<\/a><\/div>\n<\/div>\n<\/section>\n<script>\n(function(){\nvar ETD={E:1,T:2,K:3,N:4,R:5,L:6,P:7},END={mon:1,tue:2,wed:3,thu:4,fri:5,sat:6,sun:7};\nfunction dn(t){t=String(t).replace(\/[.,:]\/g,'');if(t.length===1){var u=t.toUpperCase();if(ETD[u])return ETD[u]}return END[t.slice(0,3).toLowerCase()]||0}\nfunction mi(h,m){return parseInt(h,10)*60+parseInt(m,10)}\nfunction hm(x){var h=Math.floor(x\/60),m=x%60;return (h<10?'0':'')+h+':'+(m<10?'0':'')+m}\nfunction cap(s){return s.charAt(0).toUpperCase()+s.slice(1)}\nvar EN=\/^en\/i.test(document.documentElement.lang||'');\nvar L=EN?{k:{course:'Course',club:'Clubhouse',cm:'Caddiemaster',resto:'Restaurant'},open:'open',closed:'closed',until:'open until',today:'opens today at',tomorrow:'opens tomorrow at',on:function(d){return 'opens on '+['','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'][d]+' at'},see:'see opening hours',now:'today',date:function(t){return 'Today is '+['','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'][t.d]+', '+t.day+' '+['','January','February','March','April','May','June','July','August','September','October','November','December'][t.mon]+'. '}}:{k:{course:'V\u00e4ljak',club:'Klubimaja',cm:'Caddiemaster',resto:'Restoran'},open:'avatud',closed:'suletud',until:'avatud kuni',today:'avab t\u00e4na kell',tomorrow:'avab homme kell',on:function(d){return 'avab '+['','esmasp\u00e4eval','teisip\u00e4eval','kolmap\u00e4eval','neljap\u00e4eval','reedel','laup\u00e4eval','p\u00fchap\u00e4eval'][d]+' kell'},see:'vaata lahtiolekuaegu',now:'t\u00e4na',date:function(t){return 'T\u00e4na on '+['','esmasp\u00e4ev','teisip\u00e4ev','kolmap\u00e4ev','neljap\u00e4ev','reede','laup\u00e4ev','p\u00fchap\u00e4ev'][t.d]+', '+t.day+'.'+(t.mon<10?'0':'')+t.mon+'. '}};\nfunction sched(ls){var s={state:null,days:{}};ls.forEach(function(x){x=x.replace(\/\\s*[\\u2013\\u2014-]\\s*\/g,'-').trim();var m;\nif(\/^(avatud|open)$\/i.test(x)){s.state='open';return}\nif(\/^(suletud|closed)$\/i.test(x)){s.state='closed';return}\nm=x.match(\/^(\\d{1,2})[:.](\\d{2})-(\\d{1,2})[:.](\\d{2})$\/);\nif(m){for(var d=1;d<8;d++)s.days[d]=[mi(m[1],m[2]),mi(m[3],m[4])];return}\nm=x.match(\/^([^\\s\\d-]+)-([^\\s\\d-]+)\\s+(\\d{1,2})[:.](\\d{2})-(\\d{1,2})[:.](\\d{2})$\/);\nif(m){var a=dn(m[1]),b=dn(m[2]);if(a){if(b){var d2=a;for(var i=0;i<7;i++){s.days[d2]=[mi(m[3],m[4]),mi(m[5],m[6])];if(d2===b)break;d2=d2%7+1}}}return}\nm=x.match(\/^([^\\s\\d-]+)\\s+(\\d{1,2})[:.](\\d{2})-(\\d{1,2})[:.](\\d{2})$\/);\nif(m){var a2=dn(m[1]);if(a2)s.days[a2]=[mi(m[2],m[3]),mi(m[4],m[5])]}\n});return s}\nfunction nowT(){var p=new Intl.DateTimeFormat('en-GB',{timeZone:'Europe\/Tallinn',weekday:'short',day:'numeric',month:'numeric',hour:'2-digit',minute:'2-digit',hourCycle:'h23'}).formatToParts(new Date()),o={};p.forEach(function(x){o[x.type]=x.value});return {d:dn(o.weekday),m:mi(o.hour,o.minute)%1440,day:parseInt(o.day,10),mon:parseInt(o.month,10)}}\nfunction stat(s,t){if(s.state)return {st:s.state,tx:s.state==='open'?L.open:L.closed};var td=s.days[t.d];\nif(td){if(t.m<td[0])return {st:'closed',tx:L.closed+' \\u00b7 '+L.today+' '+hm(td[0])};if(t.m<td[1])return {st:'open',tx:L.until+' '+hm(td[1])}}\nfor(var i=1;i<8;i++){var d=(t.d-1+i)%7+1,x=s.days[d];if(x)return {st:'closed',tx:L.closed+' \\u00b7 '+(i===1?L.tomorrow:L.on(d))+' '+hm(x[0])}}\nreturn {st:'',tx:L.see}}\nfunction info(){var md=document.getElementById('infoModal'),r={};if(!md)return r;[].forEach.call(md.querySelectorAll('.wp-block-columns'),function(row){var c=row.querySelectorAll('.wp-block-column');if(c.length<2)return;var k=c[0].textContent.trim(),cl=c[1].cloneNode(true);[].forEach.call(cl.querySelectorAll('br'),function(b){b.parentNode.replaceChild(document.createTextNode('\\n'),b)});[].forEach.call(cl.querySelectorAll('p,div'),function(p){p.appendChild(document.createTextNode('\\n'))});var ls=cl.textContent.replace(\/\\u00a0\/g,' ').split(\/\\n+\/).map(function(x){return x.trim()}).filter(Boolean);if(k)if(ls.length)r[k]=sched(ls)});return r}\nfunction render(){var I=info(),t=nowT(),keys=['course','club','resto'];\nvar hero=document.querySelector('.ngg-in__today [data-today]');\nif(hero){var fr=document.createDocumentFragment(),n=0;keys.forEach(function(k){var nm=L.k[k];if(!I[nm])return;n++;var s=document.createElement('span'),i=document.createElement('i'),r=stat(I[nm],t);i.textContent=nm;s.appendChild(i);s.appendChild(document.createTextNode(' '+r.tx));if(r.st)s.setAttribute('data-state',r.st);fr.appendChild(s)});if(n){while(hero.firstChild)hero.removeChild(hero.firstChild);hero.appendChild(fr)}}\n[].forEach.call(document.querySelectorAll('[data-td-st]'),function(el){var nm=L.k[el.getAttribute('data-td-st')];if(!I[nm])return;var r=stat(I[nm],t);el.textContent=nm+': '+r.tx;if(r.st)el.setAttribute('data-state',r.st)});\n[].forEach.call(document.querySelectorAll('[data-td-date]'),function(el){el.textContent=L.date(t)});\n[].forEach.call(document.querySelectorAll('.ngg-td [data-days]'),function(li){var p=li.getAttribute('data-days').split('-'),a=+p[0],b=+p[1],on=false;if(t.d>=a){if(t.d<=b)on=true}li.classList.toggle('is-today',on);var tg=li.querySelector('.ngg-td__now');if(on){if(!tg){tg=document.createElement('em');tg.className='ngg-td__now';tg.textContent=L.now;li.firstElementChild.appendChild(tg)}}else{if(tg)tg.parentNode.removeChild(tg)}})}\nfunction go(){render();setInterval(render,60000)}\nif(document.readyState==='loading')document.addEventListener('DOMContentLoaded',go);else go();\n})();\n<\/script>\n<\/div>\n\n\n\n<div class=\"ngg-p ngg-p--home\">\n<section class=\"ngg-p__sec\" id=\"miks-valgeranna\">\n<p class=\"ngg-p__eyebrow\">Why Valgeranna Golf<\/p>\n<h2 class=\"ngg-p__h\">5 reasons to play at Valgeranna.<\/h2>\n<div class=\"ngg-p__reasons\">\n<a class=\"ngg-p__reason\" href=\"https:\/\/www.wbg.ee\/en\/prices\/#playing-rights\"><b>One playing right, two courses<\/b><span>With a playing right, you play as much as you like at Valgeranna and at Rae.<\/span><\/a>\n<a class=\"ngg-p__reason\" href=\"https:\/\/www.wbg.ee\/en\/golfers\/\"><b>A Kosti Kuronen course<\/b><span>A full-length course designed by Kosti Kuronen, opened in 2004. Every hole is different.<\/span><\/a>\n<a class=\"ngg-p__reason\" href=\"https:\/\/www.wbg.ee\/en\/golfers\/#Rajad\"><b>The Audru river and ponds<\/b><span>The river winds along the course. Ponds, a canal and mounds keep the game interesting.<\/span><\/a>\n<a class=\"ngg-p__reason\" href=\"https:\/\/www.wbg.ee\/en\/golfers\/#Rajad\"><b>Pine forest edges<\/b><span>Several holes run along the edge of a pine forest.<\/span><\/a>\n<a class=\"ngg-p__reason\" href=\"https:\/\/www.wbg.ee\/en\/restaurant-white-beach-golf\/\"><b>Restaurant and terrace<\/b><span>The clubhouse restaurant and outdoor terrace \u2013 for your event, too.<\/span><\/a>\n<\/div>\n<div class=\"ngg-p__row\"><a class=\"ngg-p__btn ngg-p__btn--main\" href=\"https:\/\/www.wbg.ee\/en\/prices\/#playing-rights\">Choose a playing right<\/a><a class=\"ngg-p__btn\" href=\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget&amp;source=club\" target=\"_blank\" rel=\"noopener\">Book a tee time<\/a><\/div>\n<\/section>\n<\/div>\n\n\n\n<div class=\"ngg-x ngg-home ngg-home--low\">\n<section class=\"ngg-x-sec ngg-kk\" id=\"kaks-koduvaljakut\" data-ngg=\"kaks_koduvaljakut\" aria-labelledby=\"ngg-kk-h\"><style>.ngg-kk{--acc:#073875;--rp:#ffafea;--vd:#aff4ed;background:#0b1d3a!important;color:#fff;overflow:hidden;position:relative}.ngg-kk .ngg-x-k{color:#cbd7db!important}.ngg-kk h2.ngg-x-h{color:#fff!important;max-width:12ch}.ngg-kk .ngg-x-lead{color:#cfd9e2!important}.ngg-kk__grid{display:grid;gap:clamp(24px,4vw,64px);align-items:center}@media(min-width:960px){.ngg-kk__grid{grid-template-columns:1fr 1.15fr}}.ngg-kk__card{position:relative;width:min(100%,380px);aspect-ratio:1.586;border-radius:22px;padding:22px;margin:6px 0 26px;background:#13284d;border:1px solid rgba(255,255,255,.18);box-shadow:0 24px 60px rgba(0,0,0,.35);display:flex;flex-direction:column;justify-content:space-between;transform:rotate(-3deg);transition:transform .4s ease}.ngg-kk__card:hover{transform:rotate(0)}.ngg-kk__card::after{content:\"\";position:absolute;right:-40px;top:-40px;width:180px;height:180px;border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.10) 2px,transparent 2.5px) 0 0\/14px 14px;opacity:.6;pointer-events:none}.ngg-kk__lock{display:block;width:78%;aspect-ratio:9.085;background:url(https:\/\/raegolf.ee\/static\/rae-valgeranna-lockup-must.svg) left center\/contain no-repeat;filter:brightness(0) invert(1)}.ngg-kk__card b{display:block;font-family:\"Bricolage Grotesque\",system-ui,sans-serif;font-stretch:87.5%;font-weight:800;font-size:30px;letter-spacing:-.03em;line-height:1}.ngg-kk__card small{display:block;font-size:13px;color:#cfd9e2;margin-top:6px}.ngg-kk__card i{font-style:normal;font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.7)}.ngg-kk__map{position:relative;aspect-ratio:600\/380;width:100%}.ngg-kk__map svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.ngg-kk__land{fill:#16305a;stroke:rgba(203,215,219,.45);stroke-width:1}.ngg-kk__arc{fill:none;stroke:#fff;stroke-width:2.5;stroke-dasharray:6 8;animation:nggKk 1.6s linear infinite}@keyframes nggKk{to{stroke-dashoffset:-28}}.ngg-kk__lbl{font:700 13px \"Google Sans\",system-ui,sans-serif;fill:#fff;letter-spacing:.06em;text-transform:uppercase}.ngg-kk__pin{position:absolute;transform:translate(-50%,-50%);appearance:none;-webkit-appearance:none;border:0;background:none;padding:0;cursor:pointer;display:flex;align-items:center;gap:10px;color:#fff;text-align:left}.ngg-kk__pin span.d{position:relative;width:22px;height:22px;border-radius:50%;flex:0 0 auto;box-shadow:0 0 0 6px rgba(255,255,255,.12)}.ngg-kk__pin span.d::after{content:\"\";position:absolute;inset:-10px;border-radius:50%;border:2px solid currentColor;opacity:.5;animation:nggPulse 2.2s ease-out infinite}@keyframes nggPulse{from{transform:scale(.6);opacity:.7}to{transform:scale(1.4);opacity:0}}.ngg-kk__pin--rae span.d{background:var(--rp);color:var(--rp)}.ngg-kk__pin--vg span.d{background:var(--vd);color:var(--vd)}.ngg-kk__pin b{display:block;font:800 18px\/1.1 \"Bricolage Grotesque\",system-ui,sans-serif;font-stretch:87.5%;letter-spacing:-.02em}.ngg-kk__pin small{display:block;font-size:12px;color:#cfd9e2;margin-top:2px}.ngg-kk__pin:focus-visible{outline:3px solid #fff;outline-offset:6px;border-radius:12px}.ngg-kk__pin[aria-expanded=true] span.d{box-shadow:0 0 0 8px rgba(255,255,255,.3)}.ngg-kk__pin--rae{left:48.9%;top:15%}.ngg-kk__pin--vg{left:40.35%;top:60.2%;flex-direction:row-reverse;text-align:right}.ngg-kk__pin--vg span.t{position:absolute;right:34px;z-index:3;white-space:nowrap}.ngg-kk__pin--rae span.t{position:absolute;left:34px;white-space:nowrap}.ngg-kk__map:has(.ngg-kk__pop:not([hidden])){margin-bottom:200px}.ngg-kk__pop{position:absolute;left:0;right:0;top:calc(100% + 16px);bottom:auto;width:auto;max-width:560px;margin-left:auto;display:grid;grid-template-columns:130px 1fr;background:#fff;color:#0b1d3a;border-radius:20px;overflow:hidden;box-shadow:0 20px 50px rgba(0,0,0,.35);animation:nggUp .35s ease both;z-index:2}.ngg-kk__pop[hidden]{display:none}.ngg-kk__pop img{display:block;width:100%!important;height:100%!important;min-height:150px;max-width:none!important;object-fit:cover}.ngg-kk__pop div{padding:14px 40px 16px 16px}.ngg-kk__pop p{font-size:14px;line-height:1.45;color:#3c4b63!important;margin:0 0 10px!important}.ngg-kk__pop .ngg-x-btns{gap:6px}.ngg-kk__pop .ngg-x-btn{min-height:40px;padding:0 14px;font-size:12px}.ngg-kk__x{position:absolute;top:8px;right:8px;width:30px;height:30px;border-radius:50%;border:1px solid #cbd7db;background:#fff;color:#0b1d3a;font:700 16px\/28px system-ui;cursor:pointer;padding:0}@keyframes nggUp{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}.ngg-kk__hint{position:absolute;left:0;bottom:0;font-size:13px;color:#cfd9e2}.ngg-kk__cols{display:grid;gap:12px;margin-top:clamp(28px,4vw,56px)}@media(min-width:900px){.ngg-kk__cols{grid-template-columns:1fr 1.15fr 1fr;align-items:stretch}}.ngg-kk__col{border-radius:24px;padding:22px 22px 20px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.16);transition:border-color .3s ease,background .3s ease}.ngg-kk__col h3{font:800 22px\/1.1 \"Bricolage Grotesque\",system-ui,sans-serif!important;font-stretch:87.5%;letter-spacing:-.02em;color:#fff!important;margin:0 0 12px!important;display:flex;align-items:center;gap:10px}.ngg-kk__col h3::before{content:\"\";width:12px;height:12px;border-radius:50%;flex:0 0 auto}.ngg-kk__col--rae h3::before{background:var(--rp)}.ngg-kk__col--vg h3::before{background:var(--vd)}.ngg-kk__col--both{background:#fff;border-color:#fff}.ngg-kk__col--both h3{color:#0b1d3a!important}.ngg-kk__col--both h3::before{background:linear-gradient(90deg,var(--rp) 50%,var(--vd) 50%)}.ngg-kk__col ul{list-style:none;margin:0 0 12px;padding:0;display:grid;gap:8px}.ngg-kk__col li{list-style:none;position:relative;padding-left:22px;font-size:15px;line-height:1.45;color:#dbe5ee}.ngg-kk__col li::before{content:\"\";position:absolute;left:2px;top:.5em;width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,.5)}.ngg-kk__col--both li{color:#0b1d3a;font-weight:500}.ngg-kk__col--both li::before{background:#f39595}.ngg-kk__col a{color:#fff!important;font-weight:700;font-size:14px;text-decoration:underline;text-underline-offset:3px}.ngg-kk__col.is-on{border-color:#fff;background:rgba(255,255,255,.12)}@media(max-width:600px){.ngg-kk__pin b{font-size:15px}.ngg-kk__pin small{display:none}.ngg-kk__pop{grid-template-columns:100px 1fr}.ngg-kk__map:has(.ngg-kk__pop:not([hidden])){margin-bottom:230px}.ngg-kk__map{margin-bottom:8px}.ngg-kk__hint{position:static;display:block;margin-top:6px}}.ngg-kk__info{margin:16px 0 0!important;font-size:14px!important;line-height:1.5!important;color:#cfd9e2!important}.ngg-kk__info b{color:#fff;font-weight:700}@media(prefers-reduced-motion:reduce){.ngg-kk__arc,.ngg-kk__pin span.d::after{animation:none}.ngg-kk__card{transform:none}}<\/style><div class=\"ngg-x__in\"><div class=\"ngg-kk__grid\"><div><span class=\"ngg-x-k\">Nordic Golf Group<\/span><h2 class=\"ngg-x-h\" id=\"ngg-kk-h\">Your two home courses.<\/h2><p class=\"ngg-x-lead\">Nordic Golf Group brings together Rae Golf and Valgeranna Golf. Two different courses, one playing right. Select a course on the map to see what is shared and what is unique.<\/p><div class=\"ngg-kk__card\" aria-hidden=\"true\"><span class=\"ngg-kk__lock\"><\/span><div><b>Playing right 2027<\/b><small>42 holes \u00b7 2 courses<\/small><\/div><i>Part of Nordic Golf Group<\/i><\/div><div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--main\" href=\"https:\/\/www.wbg.ee\/en\/prices\/#playing-rights\" data-ngg-cta=\"offer_view\" data-ngg-val=\"manguoigus_2027\">Choose a playing right<\/a><a class=\"ngg-x-btn ngg-x-btn--light\" href=\"https:\/\/www.wbg.ee\/en\/one-playing-right-two-courses\/\" data-ngg-cta=\"two_courses\">What is valid where<\/a><\/div><\/div><div class=\"ngg-kk__map\"><svg viewBox=\"0 0 600 380\" aria-hidden=\"true\" focusable=\"false\"><path class=\"ngg-kk__land\" d=\"M508.4,369.4L506.2,370L493.7,367.7L480.3,361.1L474.2,355.9L468.5,356.2L461.1,359.4L435.9,368.9L429.5,366.8L414.8,357.4L407.5,347.3L391.2,326.8L389.9,321.9L387.7,318.1L370.1,312.9L363.7,305.4L358.3,304.2L350.6,300.5L329.9,284.5L324.8,282.7L323.5,285.7L324.1,289.4L322.8,291.8L320,291.5L315.5,285.7L309.7,280.4L291.9,290.3L285.5,292.9L280,293.5L251.9,306.3L243.3,313.2L239.8,312.6L240.4,306L252.3,273.1L254.5,247.1L258.6,243.3L259.9,239.8L258,231.3L245.9,226L241.1,226.9L236.6,235.7L232.1,242.2L221.3,246.3L212,239.5L190.6,230.1L184.9,218.1L183.6,205.7L172.4,193.9L167.6,179.7L169.5,169.9L179.7,163.4L182.6,157.8L169.8,158.6L167,157.2L166.3,152.1L160.6,134.8L165.7,128L167.9,121.4L163.8,115.7L165.1,109.1L168.3,102.5L166.3,87.5L179.1,79.4L191.9,73.6L218.4,70.6L215.8,56.7L226.7,56.1L244.9,39.2L262.8,42.2L289,30.7L339.1,30.7L346.2,24L344.9,17.3L344.9,10L354.5,12.1L370.1,10.9L429.5,24.9L443.9,24.9L464,39.2L474.9,43.1L507.1,43.1L556.3,49.5L566.2,39.8L567.2,37.1L571.6,42.5L577.7,51.3L579.3,56.4L577.4,59.2L571.3,61.9L570,64.3L567.5,68.8L560.5,69.7L557,73L552.5,87.8L544.5,112.1L532.4,130.6L522.8,140.8L518.3,148.5L515.7,157.8L515.1,167L524.4,217.8L524.4,226.9L522.1,236L520.5,245.7L521.8,253.9L527.9,267.9L534.3,288.6L536.8,301.9L541.3,306.9L545.5,310.3L546.4,312.6L546.1,315L544.2,317.6L525.3,324.5L522.8,330.3L520.9,336.9L512.9,346.4L510.3,355.4L508.7,365.7ZM88.4,185.9L94.8,190.1L100.5,188.9L106.3,185.9L119.1,188.6L148.4,209.5L151,215.1L133.8,217.5L129.6,224L125.5,228.4L120.7,229.8L112,238.6L100.9,247.1L98.3,252.1L77.9,251.2L66.7,254.4L57.4,264.1L53.9,282.2L47.2,296.4L40.5,301.6L33.5,302.5L31.6,297L32.5,291.8L47.2,271.7L50.4,265L43,262L36.7,255L23.2,246.8L20.7,240.4L23.9,239.8L27.1,237.8L30.6,232.2L32.2,226L21.3,207.2L27.1,204.2L33.8,204.8L40.8,210.4L48.5,203.9L52,203.1L57.4,205.4L62.9,193L75.6,188.9L82,185ZM115.6,150.9L108.2,159.2L104.1,156L101.8,151.8L92.2,171.1L81.7,174.4L75.6,170.5L76.3,163.4L70.2,144.7L60.9,139L48.2,138.7L38.6,130.9L74.7,125.6L78.5,116.6L85.8,107L91.3,106.1L96.1,108.2L96.7,115.7L98,118.7L114.3,122.6L120.7,134.8L123.2,149.7ZM152.9,198L145.6,199.8L128,187.7L132.2,179.7L137,176.4L152,181.5L153.9,193.9Z\"\/><path class=\"ngg-kk__arc\" d=\"M293.6,57.1 Q372,150 242.1,228.7\"\/><text class=\"ngg-kk__lbl\" x=\"326\" y=\"150\">one playing right<\/text><\/svg><button type=\"button\" class=\"ngg-kk__pin ngg-kk__pin--rae\" data-k=\"rae\" aria-expanded=\"false\" aria-controls=\"ngg-kk-pop-rae\"><span class=\"d\"><\/span><span class=\"t\"><b>Rae Golf<\/b><small>Near Tallinn \u00b7 18 + 6 holes<\/small><\/span><\/button><button type=\"button\" class=\"ngg-kk__pin ngg-kk__pin--vg\" data-k=\"vg\" aria-expanded=\"false\" aria-controls=\"ngg-kk-pop-vg\"><span class=\"d\"><\/span><span class=\"t\"><b>Valgeranna Golf<\/b><small>P\u00e4rnu County \u00b7 18 holes<\/small><\/span><\/button><span class=\"ngg-kk__hint\">Select a course on the map<\/span><div class=\"ngg-kk__pop\" id=\"ngg-kk-pop-rae\" role=\"region\" aria-label=\"Rae Golf\" hidden><button type=\"button\" class=\"ngg-kk__x\" aria-label=\"Close\">\u00d7<\/button><img src=\"https:\/\/raegolf.ee\/static\/rae-2026-aerofoto-rada-22-600x450.jpg\" alt=\"\" decoding=\"async\" loading=\"lazy\"><div><p>The golf centre closest to Tallinn. Practise, train and play in one evening.<\/p><div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"https:\/\/www.chronogolf.com\/club\/18975\/widget?medium=widget&amp;source=club\" target=\"_blank\" rel=\"noopener\" data-ngg-cta=\"book\" data-ngg-val=\"rae\">Book a tee time<\/a><a class=\"ngg-x-btn\" href=\"https:\/\/raegolf.ee\/en\/golf-course\/\" data-ngg-cta=\"course_view\" data-ngg-val=\"rae\">Rae course<\/a><\/div><\/div><\/div><div class=\"ngg-kk__pop\" id=\"ngg-kk-pop-vg\" role=\"region\" aria-label=\"Valgeranna Golf\" hidden><button type=\"button\" class=\"ngg-kk__x\" aria-label=\"Close\">\u00d7<\/button><img src=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-768x432.jpg\" alt=\"\" decoding=\"async\" loading=\"lazy\"><div><p>18 holes by the Audru river. Ponds, mounds and a long round in nature.<\/p><div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget&amp;source=club\" target=\"_blank\" rel=\"noopener\" data-ngg-cta=\"book\" data-ngg-val=\"valgeranna\">Book a tee time<\/a><a class=\"ngg-x-btn\" href=\"https:\/\/www.wbg.ee\/en\/golfers\/\" data-ngg-cta=\"course_view\" data-ngg-val=\"valgeranna\">Valgeranna course<\/a><\/div><\/div><\/div><\/div><\/div><div class=\"ngg-kk__cols\"><div class=\"ngg-kk__col ngg-kk__col--rae\"><h3>Only at Rae<\/h3><ul><li>TrackMan range with 19 covered bays<\/li><li>6-hole Fortal academy course<\/li><li>The golf centre closest to Tallinn \u2013 a round or practice in one evening<\/li><\/ul><a href=\"https:\/\/raegolf.ee\/en\/golf-course\/\">Rae course<\/a><\/div><div class=\"ngg-kk__col ngg-kk__col--both\"><h3>Shared on both courses<\/h3><ul><li>Playing right 2027 \u2013 unlimited play all season<\/li><li>Shared green fee vouchers \u2013 share with a friend<\/li><li>Green Card courses and training for kids and adults<\/li><li>Clubhouse restaurant and terrace<\/li><li>Booking in Chronogolf<\/li><\/ul><\/div><div class=\"ngg-kk__col ngg-kk__col--vg\"><h3>Only at Valgeranna<\/h3><ul><li>18 holes by the Audru river<\/li><li>Ponds, mounds and pine forest edges<\/li><li>A long round in nature \u2013 every hole is different<\/li><li>Free candidate membership after the Green Card<\/li><\/ul><a href=\"https:\/\/www.wbg.ee\/en\/golfers\/\">Valgeranna course<\/a><\/div><\/div><p class=\"ngg-kk__info\"><b>Practical info:<\/b> Both clubhouses have a sauna.<\/p><\/div><\/section><script>(function(){function run(){var root=document.querySelector(\".ngg-kk\");if(!root)return;function track(ev,p){try{window.dataLayer=window.dataLayer||[];var o={event:\"ngg_\"+ev,ngg_site:\"valgeranna\",ngg_component:\"kaks_koduvaljakut_en\"};for(var k in p)o[k]=p[k];window.dataLayer.push(o)}catch(e){}}var pins=[].slice.call(root.querySelectorAll(\".ngg-kk__pin\")),started=false;function close(){pins.forEach(function(p){p.setAttribute(\"aria-expanded\",\"false\");var d=document.getElementById(p.getAttribute(\"aria-controls\"));if(d)d.hidden=true});[].forEach.call(root.querySelectorAll(\".ngg-kk__col\"),function(c){c.classList.remove(\"is-on\")})}pins.forEach(function(p){p.addEventListener(\"click\",function(){var open=p.getAttribute(\"aria-expanded\")===\"true\";close();if(!open){p.setAttribute(\"aria-expanded\",\"true\");var d=document.getElementById(p.getAttribute(\"aria-controls\"));if(d)d.hidden=false;var c=root.querySelector(\".ngg-kk__col--\"+p.getAttribute(\"data-k\"));if(c)c.classList.add(\"is-on\");if(!started){started=true;track(\"start\",{})}track(\"select\",{ngg_value:p.getAttribute(\"data-k\")})}})});[].forEach.call(root.querySelectorAll(\".ngg-kk__x\"),function(b){b.addEventListener(\"click\",function(){var id=b.parentNode.id;close();var p=root.querySelector(\"[aria-controls=\"+id+\"]\");if(p)p.focus()})});root.addEventListener(\"keydown\",function(e){if(e.key===\"Escape\")close()});root.addEventListener(\"click\",function(e){var a=e.target.closest(\"[data-ngg-cta]\");if(a)if(!a.closest(\".ngg-home\"))track(\"cta\",{ngg_cta:a.getAttribute(\"data-ngg-cta\"),ngg_value:a.getAttribute(\"data-ngg-val\")||\"\"})})}if(document.readyState===\"loading\")document.addEventListener(\"DOMContentLoaded\",run);else run()})();<\/script>\n<section class=\"ngg-x-sec ngg-ev\" data-ngg=\"home_events\" aria-labelledby=\"ngg-ev-h\">\n<div class=\"ngg-x__in\">\n<div class=\"ngg-x-head ngg-x-head--split\"><div><span class=\"ngg-x-k\">Clubhouse<\/span><h2 class=\"ngg-x-h\" id=\"ngg-ev-h\">Golf is only half the day.<\/h2><\/div><p class=\"ngg-x-lead\">The clubhouse has a restaurant, a hall and an outdoor terrace. Come and eat with us even if you don't play golf.<\/p><\/div>\n<div class=\"ngg-ev__grid\">\n<article class=\"ngg-ev__card\"><figure class=\"ngg-x-photo\"><img src=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-sampanjagolf-sobrad-15-1536x1028.jpg\" srcset=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-sampanjagolf-sobrad-15-768x514.jpg 768w, https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-sampanjagolf-sobrad-15-1024x686.jpg 1024w, https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-sampanjagolf-sobrad-15-1536x1028.jpg 1536w, https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-sampanjagolf-sobrad-15.jpg 2048w\" sizes=\"auto, (min-width: 900px) 50vw, 100vw\" width=\"1536\" height=\"1028\" alt=\"Four friends with glasses of champagne on the Valgeranna course\" style=\"object-position:50% 30%\" loading=\"lazy\" decoding=\"async\"><\/figure><div class=\"ngg-ev__body\"><span class=\"ngg-x-k\">For companies and friends<\/span><h3 class=\"ngg-x-h3\">An event with golf<\/h3><p>A golf taster, food and rooms from one place. Tell us how many people are coming and what you would like. We will send you a personal offer.<\/p><div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"https:\/\/www.wbg.ee\/en\/events\/\" data-ngg-cta=\"inquiry_view\">See events<\/a><\/div><\/div><\/article>\n<article class=\"ngg-ev__card\"><figure class=\"ngg-x-photo\"><img src=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-terrass-restoran-19-1536x1028.jpg\" srcset=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-terrass-restoran-19-768x514.jpg 768w, https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-terrass-restoran-19-1024x686.jpg 1024w, https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-terrass-restoran-19-1536x1028.jpg 1536w, https:\/\/www.wbg.ee\/wp-content\/uploads\/2026\/10\/valgeranna-2026-terrass-restoran-19.jpg 2048w\" sizes=\"auto, (min-width: 900px) 50vw, 100vw\" width=\"1536\" height=\"1028\" alt=\"Guests on the Valgeranna restaurant terrace\" style=\"object-position:60% 40%\" loading=\"lazy\" decoding=\"async\"><\/figure><div class=\"ngg-ev__body\"><span class=\"ngg-x-k\">Restaurant<\/span><h3 class=\"ngg-x-h3\">A meal after the round<\/h3><p>Lunch for golfers, guests and passers-by. In summer, the outdoor terrace is open. Coming as a group? Let us know in advance.<\/p><span class=\"ngg-ev__hours\" data-hours=\"Restaurant\">Opening hours in the info window<\/span><div class=\"ngg-x-btns\"><a class=\"ngg-x-btn ngg-x-btn--dark\" href=\"https:\/\/www.wbg.ee\/en\/restaurant-white-beach-golf\/\" data-ngg-cta=\"restaurant\">See the restaurant<\/a><\/div><\/div><\/article>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"ngg-x-sec ngg-x-sec--dark ngg-nl\" id=\"Uudiskiri\" data-ngg=\"home_newsletter\" aria-labelledby=\"ngg-nl-h\">\n<div class=\"ngg-x__in ngg-nl__grid\">\n<div><span class=\"ngg-x-k\">Newsletter<\/span><h2 class=\"ngg-x-h\" id=\"ngg-nl-h\">Hear about new courses first.<\/h2><p class=\"ngg-x-lead\">Green Card course dates, competitions and seasonal offers, straight to your inbox.<\/p><\/div>\n<div><script>(function() {\n\twindow.mc4wp = window.mc4wp || {\n\t\tlisteners: [],\n\t\tforms: {\n\t\t\ton: function(evt, cb) {\n\t\t\t\twindow.mc4wp.listeners.push(\n\t\t\t\t\t{\n\t\t\t\t\t\tevent   : evt,\n\t\t\t\t\t\tcallback: cb\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n})();\n<\/script><!-- Mailchimp for WordPress v4.10.9 - https:\/\/wordpress.org\/plugins\/mailchimp-for-wp\/ --><form id=\"mc4wp-form-1\" class=\"mc4wp-form mc4wp-form-116\" method=\"post\" data-id=\"116\" data-name=\"Uudiskirja vorm\" ><div class=\"mc4wp-form-fields\"><div id=\"newsletter_form\">\r\n\t<input type=\"email\" name=\"EMAIL\" placeholder=\"Enter an e-mail\" required=\"\">\r\n\t<input type=\"submit\" value=\"Join\">\r\n<\/div><\/div><label style=\"display: none !important;\">Leave this field empty if you're human: <input type=\"text\" name=\"_mc4wp_honeypot\" value=\"\" tabindex=\"-1\" autocomplete=\"off\" \/><\/label><input type=\"hidden\" name=\"_mc4wp_timestamp\" value=\"1794702186\" \/><input type=\"hidden\" name=\"_mc4wp_form_id\" value=\"116\" \/><input type=\"hidden\" name=\"_mc4wp_form_element_id\" value=\"mc4wp-form-1\" \/><div class=\"mc4wp-response\"><\/div><\/form><!-- \/ Mailchimp for WordPress Plugin --><\/div>\n<\/div>\n<\/section>\n<section class=\"ngg-x-sec ngg-x-sec--tight ngg-sp\" aria-labelledby=\"ngg-sp-h\">\n<div class=\"ngg-x__in\">\n<span class=\"ngg-x-k\">Our partners<\/span><h2 class=\"ngg-x-h\" id=\"ngg-sp-h\" style=\"font-size:clamp(28px,3.4vw,44px)\">Thank you, partners.<\/h2>\n<ul class=\"ngg-sp__grid\"><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-linus-medical.png\" alt=\"Linus Medical\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-vdisain.png\" alt=\"vDisain\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-belief.png\" alt=\"Belief\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-vitamin-well.png\" alt=\"Vitamin Well\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-stalla.png\" alt=\"Stalla\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-kastor-gaas.png\" alt=\"Kastor Gaas\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-aesti.png\" alt=\"Aesti\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-junimperium.png\" alt=\"Junimperium\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-fortal.png\" alt=\"Fortal\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-tanni-kauplus.png\" alt=\"Tanni kauplus\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-europark.png\" alt=\"Europark\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-innopol-group.png\" alt=\"Innopol Group\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-motohobi.png\" alt=\"Motohobi\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-moobel1.png\" alt=\"M\u00f6\u00f6bel1\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-myfitness.png\" alt=\"MyFitness\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-unibet.png\" alt=\"Unibet\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-saku-olletehas.png\" alt=\"Saku \u00d5lletehas\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-jacoby.png\" alt=\"JACOBY\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-ballzy.png\" alt=\"Ballzy\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-bo-golf.png\" alt=\"BoGolf\" loading=\"lazy\" decoding=\"async\"><\/li><li><img src=\"https:\/\/raegolf.ee\/static\/toetaja-2026-nyimage.png\" alt=\"NY Image\" loading=\"lazy\" decoding=\"async\"><\/li><\/ul>\n<\/div>\n<\/section>\n<script>\n(function(){function nggRun(){var root=document;if(!document.querySelector('.ngg-home'))return;\nfunction track(ev,p){try{window.dataLayer=window.dataLayer||[];var o={event:'ngg_'+ev,ngg_site:'valgeranna',ngg_page:'home_en'};for(var k in p)o[k]=p[k];window.dataLayer.push(o)}catch(e){}}\nvar tabs=[].slice.call(root.querySelectorAll('.ngg-in__tab')),started=false;\nfunction loadImgs(){[].forEach.call(root.querySelectorAll('.ngg-in__bg[data-src]'),function(i){i.src=i.getAttribute('data-src');i.removeAttribute('data-src')})}\nfunction sel(k,focus){tabs.forEach(function(t){var on=t.getAttribute('data-k')===k;t.setAttribute('aria-selected',on?'true':'false');t.tabIndex=on?0:-1;var p=document.getElementById(t.getAttribute('aria-controls'));if(p){p.hidden=!on;if(on){p.classList.remove('is-in');void p.offsetWidth;p.classList.add('is-in')}}if(on){if(focus)t.focus()}});[].forEach.call(root.querySelectorAll('.ngg-in__bg'),function(i){i.classList.toggle('is-on',i.getAttribute('data-k')===k)})}\nfunction pick(t,focus){loadImgs();if(!started){started=true;track('start',{ngg_component:'home_entry'})}sel(t.getAttribute('data-k'),focus);track('select',{ngg_component:'home_entry',ngg_value:t.getAttribute('data-k')})}\ntabs.forEach(function(t,ix){t.addEventListener('click',function(){pick(t)});t.addEventListener('pointerenter',loadImgs);t.addEventListener('focus',loadImgs);t.addEventListener('keydown',function(e){var n=null,L=tabs.length;if(e.key==='ArrowRight'||e.key==='ArrowDown')n=tabs[(ix+1)%L];if(e.key==='ArrowLeft'||e.key==='ArrowUp')n=tabs[(ix-1+L)%L];if(e.key==='Home')n=tabs[0];if(e.key==='End')n=tabs[L-1];if(n){e.preventDefault();pick(n,true)}})});\nwindow.addEventListener('load',function(){setTimeout(loadImgs,2500)});\nroot.addEventListener('click',function(e){var a=e.target.closest('.ngg-home [data-ngg-cta]');if(!a)return;var c=a.closest('[data-ngg]');track('cta',{ngg_component:c?c.getAttribute('data-ngg'):'home',ngg_cta:a.getAttribute('data-ngg-cta'),ngg_value:a.getAttribute('data-ngg-val')||''})});\nvar now=new Date(),today=new Intl.DateTimeFormat('en-CA',{timeZone:'Europe\/Tallinn',year:'numeric',month:'2-digit',day:'2-digit'}).format(now);\n[].forEach.call(root.querySelectorAll('[data-until]'),function(c){if(c.getAttribute('data-until')<today)c.parentNode.removeChild(c)});\nvar g=root.querySelector('.ngg-now__grid');if(g){if(!g.children.length){var s=root.querySelector('.ngg-now');s.parentNode.removeChild(s)}}\nvar wd={Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6,Sun:7}[new Intl.DateTimeFormat('en-US',{timeZone:'Europe\/Tallinn',weekday:'short'}).format(now)],D={Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6,Sun:7,E:1,T:2,K:3,N:4,R:5,L:6,P:7};\nfunction line(ls){for(var i=0;i<ls.length;i++){var m=ls[i].match(\/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun|E|T|K|N|R|L|P)\\s*[\u2013-]\\s*(Mon|Tue|Wed|Thu|Fri|Sat|Sun|E|T|K|N|R|L|P)\\s+(.+)$\/);if(m){if(wd>=D[m[1]]){if(wd<=D[m[2]])return m[3]}}else{var m2=ls[i].match(\/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun|E|T|K|N|R|L|P)\\s+(\\d.+)$\/);if(m2){if(D[m2[1]]===wd)return m2[2]}else if(ls.length===1)return ls[0]}}return null}\nfunction nk(t){var l=t.toLowerCase();if(l.indexOf('restor')>-1)return 'Restaurant';if(l.indexOf('restaur')>-1)return 'Restaurant';if(l.indexOf('club')>-1)return 'Clubhouse';if(l.indexOf('klubi')>-1)return 'Clubhouse';if(l.indexOf('caddie')>-1)return 'Caddiemaster';if(l.indexOf('course')>-1)return 'Course';if(l.indexOf('v\u00e4ljak')>-1)return 'Course';return t}\nfunction nv(v){return v.replace(\/\\s*[\u2013-]\\s*\/g,'\u2013').replace(\/^(Open|Avatud)$\/i,'open').replace(\/^(Closed|Suletud)$\/i,'closed')}\nfunction fill(){var info={},md=document.getElementById('infoModal');if(!md)return 0;\n[].forEach.call(md.querySelectorAll('.wp-block-columns'),function(r){var c=r.querySelectorAll('.wp-block-column');if(c.length<2)return;var k=nk(c[0].textContent.replace(\/\\s+\/g,' ').trim()),ls=c[1].innerHTML.replace(\/<br\\s*\\\/?>\/gi,'\\n').replace(\/<\\\/p>\/gi,'\\n').replace(\/<[^>]+>\/g,'').replace(\/&nbsp;\/g,' ').split(\/\\n+\/).map(function(s){return s.trim()}).filter(Boolean),v=line(ls);if(k){if(v){if(!info[k])info[k]=nv(v)}}});\nvar n=0,out=root.querySelector('[data-today-old]');if(out){var fr=document.createDocumentFragment();['Course','Clubhouse','Restaurant'].forEach(function(k){if(!info[k])return;n++;var s=document.createElement('span'),i=document.createElement('i');i.textContent=k;s.appendChild(i);s.appendChild(document.createTextNode(' '+info[k]));fr.appendChild(s)});if(n){while(out.firstChild)out.removeChild(out.firstChild);out.appendChild(fr)}}\n[].forEach.call(root.querySelectorAll('[data-hours]'),function(el){var k=el.getAttribute('data-hours');if(info[k])el.textContent='Today '+info[k]});return n}\nif(!fill()){window.addEventListener('load',fill)}\n}if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',nggRun);else nggRun();})();\n<\/script>\n<\/div>\n<nav class=\"ngg-mbar\" aria-label=\"Quick actions\">\n<a class=\"ngg-mbar__a ngg-mbar__a--book\" href=\"https:\/\/www.chronogolf.com\/club\/19133\/widget?medium=widget&amp;source=club\" target=\"_blank\" rel=\"noopener\">Book a tee time<\/a>\n<a class=\"ngg-mbar__a ngg-mbar__a--buy\" href=\"https:\/\/www.wbg.ee\/en\/prices\/#playing-rights\">Buy a playing right<\/a>\n<\/nav>\n\n\n\n<style id=\"ngg-l-wide\">\n\/* NGG-L-WIDE-0910 (agent L): laiad ekraanid samamoodi nagu Raes. Tokenid tulevad globaalsest CSS-ist, siin on varuv\u00e4\u00e4rtused. *\/\n@media(min-width:1440px){\n.ngg-home .ngg-x__in{max-width:calc(var(--ngg-wide-max,1480px) + 2*var(--ngg-wide-g,48px));padding-left:var(--ngg-wide-g,48px);padding-right:var(--ngg-wide-g,48px)}\n.ngg-now__grid,.ngg-duo__grid,.ngg-ev__grid,.ngg-td__grid,.ngg-nw__grid,.ngg-kk__cols{gap:var(--ngg-wide-gap,24px)}\n.ngg-sp__grid{gap:clamp(12px,1vw,20px)}\n.ngg-td__c{padding:var(--ngg-wide-pad,32px);gap:14px}\n.ngg-duo__card{padding:clamp(36px,2.4vw,52px)}\n.ngg-nw__c{padding:16px;gap:18px}\n.ngg-nw__c--big{padding:18px}\n.ngg-kk__col{padding:clamp(26px,1.8vw,36px)}\n.ngg-kk__col h3{font-size:clamp(22px,1.4vw,28px)}\n.ngg-kk__col li{font-size:16px}\n}\n<\/style>\n","protected":false},"excerpt":{"rendered":"<p>Valgeranna Golf \u00b7 P\u00e4rnu County 18 holes by the river. What would you like to do? I want to play I want to start Coming with a group Ponds,<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":43,"comment_status":"closed","ping_status":"closed","template":"home-template.php","meta":{"_acf_changed":false,"inline_featured_image":false,"_uag_custom_page_level_css":"","footnotes":""},"class_list":["post-61","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Home | Valgeranna Golf<\/title>\n<meta name=\"description\" content=\"Valgeranna Golf is the first 18-hole golf course in P\u00e4rnu County, by the Audru River. Play, train, start with a Green Card and enjoy the clubhouse restaurant.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wbg.ee\/en\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Home | Valgeranna Golf\" \/>\n<meta property=\"og:description\" content=\"Valgeranna Golf is the first 18-hole golf course in P\u00e4rnu County, by the Audru River. Play, train, start with a Green Card and enjoy the clubhouse restaurant.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wbg.ee\/en\/\" \/>\n<meta property=\"og:site_name\" content=\"Valgeranna Golf\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-26T10:25:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wbg.ee\/en\/\",\"url\":\"https:\/\/www.wbg.ee\/en\/\",\"name\":\"Home | Valgeranna Golf\",\"isPartOf\":{\"@id\":\"https:\/\/www.wbg.ee\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.wbg.ee\/en\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.wbg.ee\/en\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg\",\"datePublished\":\"2021-12-28T16:16:28+00:00\",\"dateModified\":\"2026-10-26T10:25:06+00:00\",\"description\":\"Valgeranna Golf is the first 18-hole golf course in P\u00e4rnu County, by the Audru River. Play, train, start with a Green Card and enjoy the clubhouse restaurant.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.wbg.ee\/en\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wbg.ee\/en\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.wbg.ee\/en\/#primaryimage\",\"url\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg\",\"contentUrl\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wbg.ee\/en\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.wbg.ee\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Home\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wbg.ee\/#website\",\"url\":\"https:\/\/www.wbg.ee\/\",\"name\":\"Valgeranna Golf\",\"description\":\"Parim tunne on olla m\u00e4ngus\",\"publisher\":{\"@id\":\"https:\/\/www.wbg.ee\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wbg.ee\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.wbg.ee\/#organization\",\"name\":\"Valgeranna Golf\",\"url\":\"https:\/\/www.wbg.ee\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.wbg.ee\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/02\/logo.png\",\"contentUrl\":\"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/02\/logo.png\",\"width\":882,\"height\":154,\"caption\":\"Valgeranna Golf\"},\"image\":{\"@id\":\"https:\/\/www.wbg.ee\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Home | Valgeranna Golf","description":"Valgeranna Golf is the first 18-hole golf course in P\u00e4rnu County, by the Audru River. Play, train, start with a Green Card and enjoy the clubhouse restaurant.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wbg.ee\/en\/","og_locale":"en_US","og_type":"article","og_title":"Home | Valgeranna Golf","og_description":"Valgeranna Golf is the first 18-hole golf course in P\u00e4rnu County, by the Audru River. Play, train, start with a Green Card and enjoy the clubhouse restaurant.","og_url":"https:\/\/www.wbg.ee\/en\/","og_site_name":"Valgeranna Golf","article_modified_time":"2026-10-26T10:25:06+00:00","og_image":[{"url":"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg","type":"","width":"","height":""}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wbg.ee\/en\/","url":"https:\/\/www.wbg.ee\/en\/","name":"Home | Valgeranna Golf","isPartOf":{"@id":"https:\/\/www.wbg.ee\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.wbg.ee\/en\/#primaryimage"},"image":{"@id":"https:\/\/www.wbg.ee\/en\/#primaryimage"},"thumbnailUrl":"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg","datePublished":"2021-12-28T16:16:28+00:00","dateModified":"2026-10-26T10:25:06+00:00","description":"Valgeranna Golf is the first 18-hole golf course in P\u00e4rnu County, by the Audru River. Play, train, start with a Green Card and enjoy the clubhouse restaurant.","breadcrumb":{"@id":"https:\/\/www.wbg.ee\/en\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wbg.ee\/en\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.wbg.ee\/en\/#primaryimage","url":"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg","contentUrl":"https:\/\/www.wbg.ee\/wp-content\/uploads\/2024\/05\/valgeranna_51498997876_o-2048x1151.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/www.wbg.ee\/en\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.wbg.ee\/en\/"},{"@type":"ListItem","position":2,"name":"Home"}]},{"@type":"WebSite","@id":"https:\/\/www.wbg.ee\/#website","url":"https:\/\/www.wbg.ee\/","name":"Valgeranna Golf","description":"Parim tunne on olla m\u00e4ngus","publisher":{"@id":"https:\/\/www.wbg.ee\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wbg.ee\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.wbg.ee\/#organization","name":"Valgeranna Golf","url":"https:\/\/www.wbg.ee\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.wbg.ee\/#\/schema\/logo\/image\/","url":"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/02\/logo.png","contentUrl":"https:\/\/www.wbg.ee\/wp-content\/uploads\/2022\/02\/logo.png","width":882,"height":154,"caption":"Valgeranna Golf"},"image":{"@id":"https:\/\/www.wbg.ee\/#\/schema\/logo\/image\/"}}]}},"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"gform-image-choice-sm":false,"gform-image-choice-md":false,"gform-image-choice-lg":false},"uagb_author_info":{"display_name":"admin","author_link":"https:\/\/www.wbg.ee\/en\/author\/admin\/"},"uagb_comment_info":0,"uagb_excerpt":"Valgeranna Golf \u00b7 P\u00e4rnu County 18 holes by the river. What would you like to do? I want to play I want to start Coming with a group Ponds,","_links":{"self":[{"href":"https:\/\/www.wbg.ee\/en\/wp-json\/wp\/v2\/pages\/61","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wbg.ee\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.wbg.ee\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.wbg.ee\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wbg.ee\/en\/wp-json\/wp\/v2\/comments?post=61"}],"version-history":[{"count":28,"href":"https:\/\/www.wbg.ee\/en\/wp-json\/wp\/v2\/pages\/61\/revisions"}],"predecessor-version":[{"id":6561,"href":"https:\/\/www.wbg.ee\/en\/wp-json\/wp\/v2\/pages\/61\/revisions\/6561"}],"wp:attachment":[{"href":"https:\/\/www.wbg.ee\/en\/wp-json\/wp\/v2\/media?parent=61"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}