/*! Top10AI v3 nav: hydrates server-rendered markup (hooks: docs/v3-markup-contract.md). No dependencies. * Never navigates programmatically and never touches an affiliate anchor. */ (function () { 'use strict'; var doc = document; var root = doc.documentElement; root.classList.add('js'); var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (reduce) root.classList.add('t3-reduce'); var script = doc.currentScript; var routerSrc = (script && script.src ? script.src.replace(/nav\.v3\.js/, 'router.v3.js') : '/wp-content/uploads/top10ai-v2/v3/router.v3.js'); function $all(sel, ctx) { return Array.prototype.slice.call((ctx || doc).querySelectorAll(sel)); } function on(el, ev, fn, opt) { if (el) el.addEventListener(ev, fn, opt || false); } // header: menu (closes on a link, outside press, Esc or the router; Tab stays inside), language menu, Ctrl K hint var closeMenu = function () {}; function initHeader() { var header = doc.getElementById('site-header'); if (!header) return; var btn = header.querySelector('.t3-menu-btn'); var nav = header.querySelector('.t3-nav'); function setMenu(open, focusBtn) { header.classList.toggle('t3-nav-open', open); if (btn) btn.setAttribute('aria-expanded', open ? 'true' : 'false'); if (open && nav) { var first = nav.querySelector('a[href]'); if (first) first.focus(); } if (!open && focusBtn && btn) btn.focus(); } closeMenu = function (focusBtn) { if (header.classList.contains('t3-nav-open')) setMenu(false, focusBtn); }; on(btn, 'click', function () { setMenu(!header.classList.contains('t3-nav-open'), false); }); on(nav, 'click', function (e) { if (e.target.closest && e.target.closest('a[href]')) closeMenu(false); }); on(doc, 'pointerdown', function (e) { if (header.classList.contains('t3-nav-open') && (e.target === header || !header.contains(e.target))) closeMenu(false); }); var langs = $all('details.t3-lang', header); on(doc, 'click', function (e) { langs.forEach(function (d) { if (d.open && !d.contains(e.target)) d.open = false; }); }); on(doc, 'keydown', function (e) { if (e.key === 'Tab' && header.classList.contains('t3-nav-open')) { var f = $all('a[href],button,summary', header).filter(function (el) { return el.offsetWidth || el.offsetHeight; }); if (f.length) { var i = f.indexOf(doc.activeElement); if (e.shiftKey && i <= 0) { e.preventDefault(); f[f.length - 1].focus(); } else if (!e.shiftKey && (i === f.length - 1 || i < 0)) { e.preventDefault(); f[0].focus(); } } return; } if (e.key !== 'Escape') return; langs.forEach(function (d) { if (d.open) { d.open = false; var s = d.querySelector('summary'); if (s) s.focus(); } }); closeMenu(true); }); var apple = /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent || ''); if (!apple) $all('.t3-kbd').forEach(function (k) { if (k.textContent === '\u2318K') k.textContent = 'Ctrl K'; }); } // router (lazy). The host serves .js as text/plain and browsers refuse such a module, so it is fetched as text and // imported from a same-document blob: URL. Warmed on idle, focus and pointer-over; until it has loaded, router links // and forms are left to the browser (href / action = the Tool Finder; the input has no name), so no CTA is dead. var routerMod = null; var loading = null; function loadRouter() { if (routerMod) return Promise.resolve(routerMod); if (!loading) { loading = fetch(routerSrc, { credentials: 'same-origin' }).then(function (r) { if (!r.ok) throw new Error('router.v3.js ' + r.status); return r.text(); }).then(function (src) { return import(URL.createObjectURL(new Blob([src], { type: 'text/javascript' }))); }).then(function (m) { routerMod = m; return m; }, function (err) { loading = null; if (window.console) console.warn('t3 router failed to load', err); throw err; }); } return loading; } function data() { return window.__T10V3 || { tools: [], tasks: [] }; } function warm() { loadRouter().catch(function () {}); } function initRouter() { if ('requestIdleCallback' in window) window.requestIdleCallback(warm, { timeout: 4000 }); else setTimeout(warm, 2500); $all('.t3-router').forEach(function (r) { var form = r.querySelector('.t3-router-form'); on(r, 'focusin', function () { loadRouter().then(function (m) { m.mount(r, data()); }).catch(function () {}); }); on(form, 'submit', function (e) { if (r.__t3Router || !routerMod) return; e.preventDefault(); form.__t3Pending = true; routerMod.mount(r, data()); }); }); $all('[data-t3-router-open]').forEach(function (a) { on(a, 'pointerover', warm, { once: true }); on(a, 'click', function (e) { if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0 || !routerMod) return; e.preventDefault(); closeMenu(false); routerMod.open(data()); }); }); on(doc, 'keydown', function (e) { if ((e.metaKey || e.ctrlKey) && !e.altKey && (e.key === 'k' || e.key === 'K')) { e.preventDefault(); closeMenu(false); loadRouter().then(function (m) { m.open(data()); }).catch(function () {}); } }); } // motion: .t3-tok gets .in in view; .t3-loop pauses off-screen (animation-play-state via .t3-paused) function initMotion() { var items = $all('.t3-tok'); if (reduce || !('IntersectionObserver' in window)) { items.forEach(function (el) { el.classList.add('in'); }); } else { var io = new IntersectionObserver(function (entries) { entries.forEach(function (en) { if (en.isIntersecting) { en.target.classList.add('in'); io.unobserve(en.target); } }); }, { rootMargin: '0px 0px -8% 0px', threshold: 0.01 }); items.forEach(function (el) { io.observe(el); }); } var loops = $all('.t3-loop'); if (!loops.length) return; if (reduce) { loops.forEach(function (el) { el.classList.add('t3-paused'); }); return; } if (!('IntersectionObserver' in window)) return; var lo = new IntersectionObserver(function (entries) { entries.forEach(function (en) { en.target.classList.toggle('t3-paused', !en.isIntersecting); }); }); loops.forEach(function (el) { lo.observe(el); }); on(doc, 'visibilitychange', function () { loops.forEach(function (el) { el.style.animationPlayState = doc.hidden ? 'paused' : ''; }); }); } // tabs: panels visible without JS; hidden only once .t3-tabs-js is set function initTabs() { $all('[data-t3-tabs]').forEach(function (box) { var tabs = $all('[data-t3-tab]', box); var panels = $all('[data-t3-panel]', box); if (!tabs.length || !panels.length) return; function select(id, focus) { tabs.forEach(function (t) { var sel = t.getAttribute('data-t3-tab') === id; t.setAttribute('aria-selected', sel ? 'true' : 'false'); t.setAttribute('tabindex', sel ? '0' : '-1'); t.classList.toggle('is-active', sel); if (sel && focus) t.focus(); }); panels.forEach(function (p) { p.classList.toggle('is-active', p.getAttribute('data-t3-panel') === id); }); } var start = tabs.filter(function (t) { return t.getAttribute('aria-selected') === 'true'; })[0] || tabs[0]; box.classList.add('t3-tabs-js'); tabs.forEach(function (t, i) { t.setAttribute('role', 'tab'); on(t, 'click', function () { select(t.getAttribute('data-t3-tab'), false); }); on(t, 'keydown', function (e) { var dir = e.key === 'ArrowRight' ? 1 : e.key === 'ArrowLeft' ? -1 : 0; if (!dir) return; if (root.getAttribute('dir') === 'rtl' || doc.body.getAttribute('dir') === 'rtl') dir = -dir; e.preventDefault(); var n = tabs[(i + dir + tabs.length) % tabs.length]; select(n.getAttribute('data-t3-tab'), true); }); }); select(start.getAttribute('data-t3-tab'), false); }); } // row filter: [data-t3-filter=