/* PolHunter embed. One line on a mission site: plus, where a code may appear, elements with data-ph-slot="0" ... data-ph-slot="N-1". When a hunter arrives with ?ph= (their own, from their PolHunter board) the token is kept in sessionStorage for this tab, and after the mission's dwell the code is fetched from polhunter.com and rendered in ONE of the slots (which one is picked per hunter per day). The request carries this page's Origin; polhunter.com answers only for the mission's own host and only after the dwell. Anyone else loading this page sees nothing at all. */ (function () { var API = 'https://polhunter.com'; try { // the token arrives in the hash (#ph=) or, for older links, the query (?ph=); it is kept for this tab var h = new URLSearchParams((location.hash || '').replace(/^#/, '')), q = new URLSearchParams(location.search), t = h.get('ph') || q.get('ph'); if (t) { sessionStorage.setItem('ph.token', t); h.delete('ph'); q.delete('ph'); history.replaceState(null, '', location.pathname + (q.toString() ? '?' + q : '') + (h.toString() ? '#' + h : '')); } t = sessionStorage.getItem('ph.token'); if (!t) return; } catch (e) { return; } // slots: explicit [data-ph-slot="i"] elements, or the i-th match of data-selector (e.g. ".video-card" // on a training page, ".card" on a programs page), else a fixed badge in the corner var me = document.currentScript, slots = Number((me && me.getAttribute('data-slots')) || 1) || 1, sel = me && me.getAttribute('data-selector'); function slotEl(i) { var el = document.querySelector('[data-ph-slot="' + i + '"]'); if (el) return el; if (sel) { var all = document.querySelectorAll(sel); if (all.length) { var host = all[i % all.length]; var d0 = document.createElement('div'); d0.style.cssText = 'margin:10px 0'; host.appendChild(d0); return d0; } } var d = document.createElement('div'); d.setAttribute('data-ph-slot', String(i)); d.style.cssText = 'position:fixed;right:16px;bottom:16px;z-index:99999'; document.body.appendChild(d); return d; } function render(code, slot) { var el = slotEl(slot); el.innerHTML = ''; var box = document.createElement('div'); box.setAttribute('role', 'note'); // the code as six fixed cells on its own row: a short read is visible at a glance, nothing can wrap or clip // a single glyph away, and a tap copies it for the board (OPG saw 5 of 6 characters twice, 2026-09-20) box.style.cssText = 'display:inline-flex;flex-direction:column;align-items:flex-start;gap:8px;padding:12px 14px;border-radius:14px;background:linear-gradient(135deg,#1a0f3d,#2b1a63);color:#f1eefb;font:600 13px/1.2 system-ui,-apple-system,"Segoe UI",sans-serif;box-shadow:0 8px 30px rgba(130,71,229,.45),0 0 0 1px rgba(255,255,255,.08);letter-spacing:.02em;max-width:100%;cursor:pointer;-webkit-user-select:none;user-select:none'; var cells = code.split('').map(function (ch) { return '' + ch + ''; }).join(''); box.innerHTML = 'PolHunter code 6 characters, tap to copy' + cells + ''; box.setAttribute('title', 'Tap to copy ' + code); box.addEventListener('click', function () { var done = function () { var s = box.querySelector('span span'); if (s) s.textContent = 'copied, paste it on your board'; }; try { navigator.clipboard.writeText(code).then(done, done); } catch (e) { done(); } }); el.appendChild(box); } var tries = 0, pending = null, done = false; // phones freeze a background tab's timers: when the hunter comes back to this tab, ask right away document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible' && !done) { clearTimeout(pending); ask(); } }); function ask() { tries++; if (tries > 80 || done) return; fetch(API + '/api/embed/code?t=' + encodeURIComponent(t), { mode: 'cors', credentials: 'omit' }).then(function (r) { return r.json(); }).then(function (r) { if (r && r.code) { done = true; render(r.code, Number(r.slot) % slots); try { sessionStorage.removeItem('ph.token'); } catch (e) {} return; } if (r && r.wait) { pending = setTimeout(ask, Math.min(r.wait, 5) * 1000); return; } // expired / gone / wrong origin: say nothing }).catch(function () { pending = setTimeout(ask, 6000); }); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', ask); else ask(); })();