(()=>{function f(n){var r,i,e=Array.prototype.slice.call(document.querySelectorAll(".progress-circle path"));function t(){i=0,e=document.documentElement,t=window.pageYOffset||e.scrollTop||0;var e,t,o=1-((e=(e.scrollHeight||0)-window.innerHeight)<=0||(t=t/e)<0?0:1 .wp-block-columns"),t=document.querySelector(".sidebar-col .is-sticky");e&&t&&s.create({trigger:e,pin:t,start:"top 10px",end:function(){return"+="+(e.offsetHeight-t.offsetHeight)},pinSpacing:!1,invalidateOnRefresh:!0})}})})})();; (function () { "use strict"; if (typeof window === "undefined") return; if (!window.LNS_DATA || !LNS_DATA.endpoint) return; function debounce(fn, wait) { var t; return function () { var ctx = this, args = arguments; clearTimeout(t); t = setTimeout(function () { fn.apply(ctx, args); }, wait); }; } function escapeHtml(str) { return String(str).replace(/[&<>"']/g, function (m) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[m]; }); } function buildAdvancedSearchUrl(q) { var base = window.location.origin + '/'; return base + '?s=' + encodeURIComponent(String(q || '').trim()); } function renderAdvancedButton(q) { var query = String(q || '').trim(); if (!query) return ''; var url = buildAdvancedSearchUrl(query); return ( '
' + '' + 'Advanced search' + '' + '
' ); } function renderItems(items, showExcerpt) { var html = ''; return html; } function renderGrouped(container, groups, query, showExcerpt) { if (!groups || !groups.length) { container.innerHTML = '
No results' + (query ? ' for “' + escapeHtml(query) + '”' : '') + '.
' + renderAdvancedButton(query); return; } var html = ''; for (var g = 0; g < groups.length; g++) { var group = groups[g] || {}; var label = group.label ? String(group.label) : ''; var items = group.items || []; if (!items.length) continue; html += '
'; html += '
' + escapeHtml(label) + '
'; html += renderItems(items, showExcerpt); html += '
'; } if (!html) { container.innerHTML = '
No results' + (query ? ' for “' + escapeHtml(query) + '”' : '') + '.
' + renderAdvancedButton(query); return; } container.innerHTML = html + renderAdvancedButton(query); } /* --------------------------------------------------------------------- */ /* Toggle UI: .show-search opens/closes .search-in */ /* Adds/removes .lns-open when open/closed */ /* --------------------------------------------------------------------- */ function setupToggle(root) { // root = .search-in var btn = root.querySelector('.show-search'); var wrap = root.querySelector('.lns-wrap'); if (!btn || !wrap) return; var input = wrap.querySelector('.lns-input'); var results = wrap.querySelector('.lns-results'); function isOpen() { return !root.classList.contains('lns-collapsed'); } function open() { root.classList.remove('lns-collapsed'); root.classList.add('lns-open'); // ✅ requested btn.setAttribute('aria-expanded', 'true'); if (input && input.focus) input.focus(); if (results && !results.innerHTML) { results.innerHTML = '
Start typing to search…
'; } } function close() { root.classList.add('lns-collapsed'); root.classList.remove('lns-open'); // ✅ requested btn.setAttribute('aria-expanded', 'false'); } btn.addEventListener('click', function (e) { e.preventDefault(); if (isOpen()) close(); else open(); }); // ESC closes when open root.addEventListener('keydown', function (e) { var key = e.key || e.keyCode; if ((key === 'Escape' || key === 'Esc' || key === 27) && isOpen()) { close(); if (btn && btn.focus) btn.focus(); } }); // Click outside closes (only when open) document.addEventListener('mousedown', function (e) { if (!isOpen()) return; if (!root.contains(e.target)) close(); }); // Optional: open when input receives focus (keyboard users) if (input) { input.addEventListener('focus', function () { if (!isOpen()) open(); }); } } /* --------------------------------------------------------------------- */ /* Search attach */ /* --------------------------------------------------------------------- */ function attachSearch(el) { // el = .lns-wrap var input = el.querySelector('.lns-input'); var results = el.querySelector('.lns-results'); if (!input || !results) return; var min = parseInt(el.getAttribute('data-min') || '2', 10); var perPage = parseInt(el.getAttribute('data-per-page') || '12', 10); var types = (el.getAttribute('data-types') || 'post,page'); var showExcerpt = el.getAttribute('data-show-excerpt') === '1'; if (!results.innerHTML) { results.innerHTML = '
Start typing to search…
'; } var doSearch = debounce(function () { var q = (input.value || '').trim(); if (q.length < min) { results.innerHTML = '
Keep typing…
'; return; } try { var url = new URL(LNS_DATA.endpoint, window.location.origin); url.searchParams.set('q', q); url.searchParams.set('types', types); url.searchParams.set('per_page', String(perPage)); var headers = {}; if (LNS_DATA.nonce) headers['X-WP-Nonce'] = LNS_DATA.nonce; fetch(url.toString(), { headers: headers, credentials: 'same-origin' }) .then(function (res) { if (!res.ok) throw new Error('HTTP ' + res.status); return res.json(); }) .then(function (data) { var groups = (data && data.groups) ? data.groups : null; if (groups && groups.length) { renderGrouped(results, groups, q, showExcerpt); return; } // Fallback if API returns only items (older PHP). var items = (data && data.items) || []; if (!items.length) { results.innerHTML = '
No results' + (q ? ' for “' + escapeHtml(q) + '”' : '') + '.
' + renderAdvancedButton(q); return; } results.innerHTML = renderItems(items, showExcerpt) + renderAdvancedButton(q); }) .catch(function () { results.innerHTML = '
Error loading results.
'; }); } catch (e) { results.innerHTML = '
Error loading results.
'; } }, 250); input.addEventListener('input', doSearch); } document.addEventListener('DOMContentLoaded', function () { // Toggle behavior (adds .lns-open when open) var roots = document.querySelectorAll('.search-in'); for (var r = 0; r < roots.length; r++) { setupToggle(roots[r]); } // Live search var nodes = document.querySelectorAll('.lns-wrap'); for (var i = 0; i < nodes.length; i++) attachSearch(nodes[i]); }); })(); // ======================== // Header, scroll helpers, menus, masonry // ======================== (function () { 'use strict'; // --- Helpers (scoped to this IIFE) --- const throttle = (fn, wait = 100) => { let last = 0; let pending = null; return function (...args) { const now = Date.now(); const remaining = wait - (now - last); if (!last || remaining <= 0) { last = now; fn.apply(this, args); } else if (!pending) { pending = setTimeout(() => { last = Date.now(); pending = null; fn.apply(this, args); }, remaining); } }; }; const smoothScrollToY = (y) => { try { window.scrollTo({ top: y, behavior: 'smooth' }); } catch (e) { // Older browsers window.scrollTo(0, y); } }; const onElementReady = (selector, cb) => { const el = document.querySelector(selector); if (el) { cb(el); return; } const mo = new MutationObserver(() => { const found = document.querySelector(selector); if (found) { mo.disconnect(); cb(found); } }); mo.observe(document.documentElement, { childList: true, subtree: true }); }; document.addEventListener('DOMContentLoaded', () => { // ------------------------------ // 1) .nolink/.no-link menu items & .load-more-btn as inert anchors // ------------------------------ const initNoLink = () => { const noLinkAnchors = document.querySelectorAll( '.nolink > a, .no-link > a' ); noLinkAnchors.forEach((a) => { a.setAttribute('aria-disabled', 'true'); if (!a.hasAttribute('tabindex')) { a.setAttribute('tabindex', '0'); } }); // Delegated click: prevent navigation but keep semantics document.addEventListener('click', (e) => { const inertLink = e.target.closest( '.nolink > a, .no-link > a, .load-more-btn a' ); if (!inertLink) return; e.preventDefault(); }); }; initNoLink(); // ------------------------------ // 2) Header scroll state & Back-to-top visibility // ------------------------------ const header = document.querySelector('header.wp-block-template-part'); const backToTop = document.querySelector('.back-to-top'); const updateOnScroll = throttle(() => { const y = window.scrollY || document.documentElement.scrollTop || 0; if (header) { header.classList.toggle('scroll-header', y > 120); } if (backToTop) { backToTop.classList.toggle('show', y > 600); } }, 100); updateOnScroll(); window.addEventListener('scroll', updateOnScroll, { passive: true }); // ------------------------------ // 3) Back button (delegated) // ------------------------------ document.addEventListener('click', (e) => { const a = e.target.closest('.back-btn a'); if (!a) return; e.preventDefault(); window.history.back(); }); // ------------------------------ // 4) Back-to-top click // ------------------------------ if (backToTop) { backToTop.addEventListener('click', (e) => { e.preventDefault(); smoothScrollToY(0); }); } // ------------------------------ // 5) Section scroll links with offset (.scroll-to a[href*="#"]) // ------------------------------ document.addEventListener('click', (e) => { const link = e.target.closest('.scroll-to a[href*="#"]'); if (!link) return; const href = link.getAttribute('href') || ''; const id = href.split('#')[1]; if (!id) return; const target = document.getElementById(id) || document.querySelector(`[name="${CSS.escape(id)}"]`); if (!target) return; e.preventDefault(); const rect = target.getBoundingClientRect(); const absoluteTop = rect.top + window.pageYOffset; const y = absoluteTop - 120; // offset for fixed header smoothScrollToY(y); }); // ------------------------------ // 6) Mobile menu toggle (.av-nav-toggle) // ------------------------------ (function initMobileMenu() { onElementReady('.av-nav-toggle', (toggleBtn) => { const SHOW_SEARCH_SEL = '.show-search'; const WRAP_CLASS = 'search-in'; const DISABLED_CLASS = 'is-disabled'; const setButtonDisabled = (el, disabled) => { const isButton = el.tagName === 'BUTTON' || el.getAttribute('role') === 'button'; if (isButton && 'disabled' in el) { el.disabled = disabled; } else { el.setAttribute('aria-disabled', String(disabled)); el.classList.toggle(DISABLED_CLASS, disabled); el.style.pointerEvents = disabled ? 'none' : ''; if (disabled) { if (!el.hasAttribute('data-prev-tabindex')) { el.setAttribute( 'data-prev-tabindex', el.getAttribute('tabindex') ?? '' ); } el.setAttribute('tabindex', '-1'); } else if (el.hasAttribute('data-prev-tabindex')) { const prev = el.getAttribute('data-prev-tabindex'); if (prev === '') { el.removeAttribute('tabindex'); } else { el.setAttribute('tabindex', prev); } el.removeAttribute('data-prev-tabindex'); } } }; const setWrapperDisabled = (wrap, disabled) => { if (!wrap) return; wrap.setAttribute('aria-disabled', String(disabled)); wrap.classList.toggle(DISABLED_CLASS, disabled); wrap.style.pointerEvents = disabled ? 'none' : ''; }; const applyDisabledFromBody = () => { const active = document.body.classList.contains('side-menu-opened'); const buttons = document.querySelectorAll(SHOW_SEARCH_SEL); buttons.forEach((btn) => { setButtonDisabled(btn, active); const wrap = btn.closest(`.${WRAP_CLASS}`); setWrapperDisabled(wrap, active); }); }; const isOpen = () => document.body.classList.contains('side-menu-opened'); const openMenu = () => { document.body.classList.add('side-menu-opened'); toggleBtn.classList.add('activated'); applyDisabledFromBody(); }; const closeMenu = () => { if (!isOpen()) return; document.body.classList.remove('side-menu-opened'); toggleBtn.classList.remove('activated'); applyDisabledFromBody(); }; applyDisabledFromBody(); toggleBtn.addEventListener('click', () => { if (isOpen()) { closeMenu(); } else { openMenu(); } // Original hidden-menu-item toggler requestAnimationFrame(() => { requestAnimationFrame(() => { document .querySelectorAll('.av-dropdown-toggle--mobile') .forEach((btn) => { if (btn.dataset._bound === '1') return; btn.dataset._bound = '1'; btn.addEventListener('click', () => { const hiddenItems = document.querySelectorAll( '.hidden-menu-item' ); if (hiddenItems.length) { hiddenItems.forEach((li) => li.classList.remove( 'hidden-menu-item' ) ); } else { document .querySelectorAll( '#av-mobile-wrap > ul > .menu-item' ) .forEach((li) => { const itsButton = li.querySelector( 'button' ) === btn; if (!itsButton) { li.classList.add( 'hidden-menu-item' ); } }); } }); }); }); }); }); // ESC closes document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { closeMenu(); } }); // Stay in sync if some other script toggles body class const bodyClassObserver = new MutationObserver( (mutations) => { for (const m of mutations) { if (m.attributeName === 'class') { applyDisabledFromBody(); break; } } } ); bodyClassObserver.observe(document.body, { attributes: true, attributeFilter: ['class'], }); }); })(); // ------------------------------ // 7) Mobile submenu accordion (.av-mobile) // ------------------------------ (function () { const findSubmenuForButton = (btn) => { const li = btn.closest('li'); if (!li) return null; const submenu = li.querySelector(':scope > ul.sub-menu'); if (submenu) return submenu; let n = btn.nextElementSibling; while (n) { if (n.matches && n.matches('ul.sub-menu')) return n; if (n.tagName === 'LI') break; n = n.nextElementSibling; } return null; }; const setClosed = (li) => { if (!li) return; li.classList.remove('is-open'); const btn = li.querySelector( ':scope > .av-dropdown-toggle--mobile[data-av-sub-toggle="true"]' ); const submenu = li.querySelector(':scope > ul.sub-menu'); if (btn) btn.setAttribute('aria-expanded', 'false'); if (submenu && !submenu.hasAttribute('hidden')) { submenu.setAttribute('hidden', ''); } }; const setOpen = (li) => { if (!li) return; li.classList.add('is-open'); const btn = li.querySelector( ':scope > .av-dropdown-toggle--mobile[data-av-sub-toggle="true"]' ); const submenu = li.querySelector(':scope > ul.sub-menu'); if (btn) btn.setAttribute('aria-expanded', 'true'); if (submenu && submenu.hasAttribute('hidden')) { submenu.removeAttribute('hidden'); } }; const onToggleClick = (e) => { const btn = e.currentTarget; const li = btn.closest('li'); if (!li) return; const submenu = findSubmenuForButton(btn); if (!submenu) return; const isOpen = btn.getAttribute('aria-expanded') === 'true'; if (isOpen) { setClosed(li); return; } const parentUL = li.parentElement; if (parentUL) { const openSiblings = parentUL.querySelectorAll(':scope > li.is-open'); openSiblings.forEach((sib) => { if (sib !== li) setClosed(sib); }); } setOpen(li); }; const bindMobileToggles = (root) => { const container = root || document; const buttons = container.querySelectorAll( '.av-mobile .av-dropdown-toggle--mobile[data-av-sub-toggle="true"]' ); buttons.forEach((btn) => { btn.removeEventListener('click', onToggleClick); btn.addEventListener('click', onToggleClick); }); }; if (document.readyState === 'loading') { document.addEventListener( 'DOMContentLoaded', () => bindMobileToggles(), { once: true } ); } else { bindMobileToggles(); } document.addEventListener('click', (e) => { const t = e.target.closest('[data-av-toggle]'); if (t) { setTimeout(() => bindMobileToggles(), 0); } }); })(); // ------------------------------ // 8) WP navigation submenu toggles (.wp-block-navigation-submenu__toggle) // One handler: toggles submenu + hides other items. // ------------------------------ document.addEventListener('click', (e) => { const toggle = e.target.closest('.wp-block-navigation-submenu__toggle'); if (!toggle) return; e.preventDefault(); const menuItem = toggle.closest('.wp-block-navigation-item'); const submenu = toggle.nextElementSibling || menuItem?.querySelector(':scope > .wp-block-navigation__submenu'); const isExpanded = toggle.getAttribute('aria-expanded') === 'true'; const nextExpanded = !isExpanded; toggle.setAttribute('aria-expanded', String(nextExpanded)); if (submenu) submenu.classList.toggle('active', nextExpanded); const allMenuItems = document.querySelectorAll( '.wp-block-navigation__responsive-container-content > ul > .wp-block-navigation-item' ); allMenuItems.forEach((item) => { if (!item.contains(toggle)) { item.classList.toggle('hidden-menu-item', nextExpanded); } }); }); // ------------------------------ // 9) .scroll-to-next links // ------------------------------ const nextLinks = document.querySelectorAll('.scroll-to-next a'); if (nextLinks.length) { nextLinks.forEach((link) => { link.addEventListener('click', (e) => { e.preventDefault(); const href = link.getAttribute('href') || ''; const id = href.startsWith('#') ? href.slice(1) : href; if (!id) return; const targetSection = document.getElementById(id); if (!targetSection) return; targetSection.scrollIntoView({ behavior: 'smooth' }); // Remove hash without reload history.pushState(null, '', ' '); }); }); } // ------------------------------ // 10) Masonry-style columns on blog/archive pages // ------------------------------ const body = document.body; if (body.classList.contains('archive') && body.classList.contains('post-type-archive-alumni-spotlights')) { return; } if ( body.classList.contains('page-template-blog-page') || body.classList.contains('archive') || body.classList.contains('term-papers') ) { let originalPosts = null; const getColumnsCount = () => { const width = window.innerWidth; if (width < 599) return 1; if (width < 1024) return 2; return 3; }; const createMasonryGrid = () => { const container = document.querySelector( 'ul.wp-block-post-template' ); if (!container) return; const columnsCount = getColumnsCount(); if (!originalPosts) { originalPosts = Array.from( container.querySelectorAll('li.wp-block-post') ); } if (!originalPosts.length) return; container.innerHTML = ''; const columns = []; for (let i = 0; i < columnsCount; i++) { const col = document.createElement('div'); col.classList.add('masonry-column'); const inner = document.createElement('div'); inner.classList.add('masonry-inner'); col.appendChild(inner); container.appendChild(col); columns.push(inner); } originalPosts.forEach((post, index) => { const colIndex = index % columnsCount; columns[colIndex].appendChild(post); }); }; const debounce = (fn, wait) => { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => fn.apply(this, args), wait); }; }; createMasonryGrid(); window.addEventListener( 'resize', debounce(createMasonryGrid, 150), { passive: true } ); } }); })(); // ======================== // Responsive menu behavior (desktop vs mobile regions) // ======================== (function () { 'use strict'; function initDinsmoreMenus(rootSelector) { const root = document.querySelector(rootSelector || '.av-responsive-menu'); if (!root) return; const cssBp = getComputedStyle(document.documentElement) .getPropertyValue('--av-bp') .trim(); const bp = cssBp && cssBp.endsWith('px') ? parseInt(cssBp, 10) : parseInt(root.getAttribute('data-breakpoint') || '992', 10); document.documentElement.style.setProperty('--av-bp', `${bp}px`); document.documentElement.classList.add('js-av-dropdowns'); const desktopRegion = root.querySelector('.av-desktop'); const mobileRegion = root.querySelector('.av-mobile'); const toggles = Array.prototype.slice.call( root.querySelectorAll('[data-av-toggle], .av-nav-toggle') ); const drawers = toggles.map((btn) => { const resolveTargetId = (b) => { return ( b.getAttribute('data-av-toggle') || b.getAttribute('aria-controls') || ((h) => (h && h.startsWith('#') ? h.slice(1) : null))( b.getAttribute('href') ) ); }; const id = resolveTargetId(btn); const list = id ? document.getElementById(id) : null; const wrap = id ? document.getElementById(`${id}-wrap`) || (list ? list.closest('.av-mobile-wrap') : null) : null; if (btn && !btn.hasAttribute('aria-expanded')) { btn.setAttribute('aria-expanded', 'false'); } if (wrap) wrap.hidden = true; if (list) list.hidden = true; return { btn, id, wrap, list }; }); const mq = window.matchMedia(`(min-width:${bp}px)`); const isDesktop = () => mq.matches; const setRegionState = (el, hidden) => { if (!el) return; el.setAttribute('aria-hidden', hidden ? 'true' : 'false'); if (hidden) { el.setAttribute('inert', ''); } else { el.removeAttribute('inert'); } }; const applyViewportState = () => { const desktop = isDesktop(); setRegionState(desktopRegion, !desktop); setRegionState(mobileRegion, desktop); drawers.forEach((d) => { if (!d.btn) return; d.btn.setAttribute('aria-expanded', 'false'); if (d.wrap) d.wrap.hidden = true; if (d.list) d.list.hidden = true; }); }; if (document.readyState === 'loading') { document.addEventListener( 'DOMContentLoaded', applyViewportState, { once: true } ); } else { applyViewportState(); } if (mq.addEventListener) { mq.addEventListener('change', applyViewportState); } else if (mq.addListener) { mq.addListener(applyViewportState); } // Mobile drawer drawers.forEach((d) => { const { btn, wrap, list } = d; if (!btn || !wrap || !list) return; btn.addEventListener('click', (e) => { if (btn.tagName === 'A') e.preventDefault(); e.stopPropagation(); const open = btn.getAttribute('aria-expanded') === 'true'; btn.setAttribute('aria-expanded', String(!open)); wrap.hidden = open; list.hidden = open; }); document.addEventListener('keydown', (e) => { if (e.key !== 'Escape') return; if (btn.getAttribute('aria-expanded') !== 'true') return; btn.setAttribute('aria-expanded', 'false'); wrap.hidden = true; list.hidden = true; btn.focus({ preventScroll: true }); }); document.addEventListener('click', (e) => { if (btn.getAttribute('aria-expanded') !== 'true') return; if (wrap.contains(e.target) || btn.contains(e.target)) return; btn.setAttribute('aria-expanded', 'false'); wrap.hidden = true; list.hidden = true; }); }); // Desktop dropdowns const roots = [ root.querySelector('.av-nav--top .menu--top'), root.querySelector('.av-nav--primary .menu--primary'), ].filter(Boolean); if (!roots.length) return; const OPEN = 'is-open'; const timers = new WeakMap(); const openDelay = 60; const closeDelay = 180; const hasSub = (li) => !!li && !!li.querySelector(':scope > .sub-menu'); const clearT = (node) => { const t = timers.get(node); if (t) { clearTimeout(t); timers.delete(node); } }; // ARIA prep roots.forEach((r) => { r.querySelectorAll('li.menu-item-has-children').forEach((li) => { li.dataset.dropdownParent = 'true'; li.dataset.state = 'closed'; const trigger = li.querySelector(':scope > a'); const panel = li.querySelector(':scope > .sub-menu'); const btn = li.querySelector(':scope > .av-dropdown-toggle'); if (trigger) { trigger.dataset.dropdownTrigger = 'true'; trigger.setAttribute('aria-haspopup', 'menu'); trigger.setAttribute('aria-expanded', 'false'); } if (panel) { panel.dataset.dropdownPanel = 'true'; if (!panel.id) { const base = li.id || `menu-item-${Math.random().toString(36).slice(2)}`; panel.id = `submenu-${base}`; } } if (btn) { btn.setAttribute('aria-expanded', 'false'); btn.dataset.dropdownToggle = 'true'; if (panel) btn.setAttribute('aria-controls', panel.id); } }); }); const setOpen = (li, on) => { if (!li) return; li.classList.toggle(OPEN, !!on); li.dataset.state = on ? 'open' : 'closed'; const a = li.querySelector(':scope > a[data-dropdown-trigger]'); if (a) a.setAttribute('aria-expanded', on ? 'true' : 'false'); const b = li.querySelector(':scope > .av-dropdown-toggle'); if (b) b.setAttribute('aria-expanded', on ? 'true' : 'false'); if (on) { const p = li.parentElement; if (p) { p.querySelectorAll(`:scope > li.${OPEN}`).forEach((s) => { if (s !== li) setOpen(s, false); }); } } else { li.querySelectorAll(`li.${OPEN}`).forEach((n) => { setOpen(n, false); }); } }; roots.forEach((rootMenu) => { rootMenu.addEventListener( 'pointerenter', (e) => { if (!isDesktop()) return; const submenu = e.target.closest('.sub-menu'); const li = submenu ? submenu.parentElement : e.target.closest('li.menu-item-has-children'); if (!li || !rootMenu.contains(li) || !hasSub(li)) return; clearT(li); timers.set( li, setTimeout(() => setOpen(li, true), openDelay) ); }, true ); rootMenu.addEventListener( 'pointerleave', (e) => { if (!isDesktop()) return; const submenu = e.target.closest('.sub-menu'); const li = submenu ? submenu.parentElement : e.target.closest('li.menu-item-has-children'); if (!li || !rootMenu.contains(li) || !hasSub(li)) return; const to = e.relatedTarget; if (to && li.contains(to)) return; clearT(li); timers.set( li, setTimeout(() => setOpen(li, false), closeDelay) ); }, true ); rootMenu.addEventListener('click', (e) => { if (!isDesktop()) return; const btn = e.target.closest('button.av-dropdown-toggle'); if (btn) { e.preventDefault(); e.stopPropagation(); const li = btn.parentElement; setOpen(li, !li.classList.contains(OPEN)); return; } const a = e.target.closest('a[data-dropdown-trigger]'); if (!a) return; const li2 = a.parentElement; if ( !li2 || !li2.classList.contains('menu-item-has-children') ) { return; } if (!li2.classList.contains(OPEN)) { e.preventDefault(); setOpen(li2, true); } }); rootMenu.addEventListener('focusin', (e) => { if (!isDesktop()) return; const li = e.target.closest('li.menu-item-has-children'); if (li && rootMenu.contains(li)) setOpen(li, true); }); rootMenu.addEventListener('focusout', () => { if (!isDesktop()) return; setTimeout(() => { const active = document.activeElement; rootMenu.querySelectorAll(`li.${OPEN}`).forEach((openLi) => { if (!openLi.contains(active)) setOpen(openLi, false); }); }, 0); }); }); const closeAll = () => { roots.forEach((r) => { r.querySelectorAll(`li.${OPEN}`).forEach((li) => setOpen(li, false) ); }); drawers.forEach((d) => { if (!d.wrap || !d.list) return; d.wrap.hidden = true; d.list.hidden = true; if (d.btn) d.btn.setAttribute('aria-expanded', 'false'); }); }; if (mq.addEventListener) mq.addEventListener('change', closeAll); else if (mq.addListener) mq.addListener(closeAll); } if (document.readyState === 'loading') { document.addEventListener( 'DOMContentLoaded', () => initDinsmoreMenus('.av-responsive-menu'), { once: true } ); } else { initDinsmoreMenus('.av-responsive-menu'); } // ======================== // Tablet touch “no-hover” patch // - Blocks hover events on touch devices in desktop breakpoint // - Keeps your current click behavior: 1st tap opens, 2nd tap navigates // - closes open dropdowns when tapping outside // ======================== //start function getBp(root) { const cssBp = getComputedStyle(document.documentElement) .getPropertyValue('--av-bp') .trim(); if (cssBp && cssBp.endsWith('px')) { const n = parseInt(cssBp, 10); if (!Number.isNaN(n)) return n; } const attr = root && root.getAttribute('data-breakpoint'); const n2 = parseInt(attr || '992', 10); return Number.isNaN(n2) ? 992 : n2; } function isTouchDesktop(root) { const bp = getBp(root); const desktopMq = window.matchMedia(`(min-width:${bp}px)`); if (!desktopMq.matches) return false; const noHover = window.matchMedia('(hover: none)').matches; const coarse = window.matchMedia('(pointer: coarse)').matches; return noHover || coarse; } function closeAllDropdowns(root) { if (!root) return; const openLis = root.querySelectorAll( '.av-nav--top li.is-open, .av-nav--primary li.is-open' ); openLis.forEach((li) => { li.classList.remove('is-open'); li.dataset.state = 'closed'; const a = li.querySelector(':scope > a[data-dropdown-trigger]'); if (a) a.setAttribute('aria-expanded', 'false'); const b = li.querySelector(':scope > .av-dropdown-toggle'); if (b) b.setAttribute('aria-expanded', 'false'); }); } function init() { const root = document.querySelector('.av-responsive-menu'); if (!root) return; const blockHoverIfTouchDesktop = (e) => { if (!isTouchDesktop(root)) return; const inDesktopNav = e.target && e.target.closest ? e.target.closest('.av-nav--top, .av-nav--primary') : null; if (!inDesktopNav) return; e.stopPropagation(); }; document.addEventListener('pointerenter', blockHoverIfTouchDesktop, true); document.addEventListener('pointerleave', blockHoverIfTouchDesktop, true); const onOutsideTap = (e) => { if (!isTouchDesktop(root)) return; if (root.contains(e.target)) return; closeAllDropdowns(root); }; if (window.PointerEvent) { document.addEventListener('pointerdown', onOutsideTap, { passive: true }); } else { document.addEventListener('touchstart', onOutsideTap, { passive: true }); } const bp = getBp(root); const desktopMq = window.matchMedia(`(min-width:${bp}px)`); const onBpChange = () => closeAllDropdowns(root); if (desktopMq.addEventListener) desktopMq.addEventListener('change', onBpChange); else if (desktopMq.addListener) desktopMq.addListener(onBpChange); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init, { once: true }); } else { init(); } //end })(); /** * Windows Touch Desktop dropdown patch (strong override) * - Desktop breakpoint only * - Windows + touch only * - Uses pointerdown (capture) + suppresses ensuing click to prevent "open then close" * - Parent link: 1st tap opens, 2nd tap navigates * - Arrow button: opens/closes on 1st tap */ (function () { 'use strict'; function getBp(root) { var cssBp = getComputedStyle(document.documentElement) .getPropertyValue('--av-bp') .trim(); if (cssBp && cssBp.endsWith('px')) { var n = parseInt(cssBp, 10); if (!Number.isNaN(n)) return n; } var attr = root && root.getAttribute('data-breakpoint'); var n2 = parseInt(attr || '992', 10); return Number.isNaN(n2) ? 992 : n2; } function isWindowsPlatform() { if (navigator.userAgentData && typeof navigator.userAgentData.platform === 'string') { return navigator.userAgentData.platform.toLowerCase().indexOf('windows') !== -1; } var p = (navigator.platform || '').toLowerCase(); if (p.indexOf('win') !== -1) return true; var ua = (navigator.userAgent || '').toLowerCase(); return ua.indexOf('windows') !== -1; } function isWindowsTouchDesktop(root) { if (!isWindowsPlatform()) return false; var bp = getBp(root); var desktopMq = window.matchMedia('(min-width:' + bp + 'px)'); if (!desktopMq.matches) return false; var noHover = window.matchMedia('(hover: none)').matches; var coarse = window.matchMedia('(pointer: coarse)').matches; var touchPoints = typeof navigator.maxTouchPoints === 'number' ? navigator.maxTouchPoints : 0; return noHover || coarse || touchPoints > 0; } function findNavContainer(target) { return target && target.closest ? target.closest('.av-nav--top, .av-nav--primary') : null; } function findParentLi(target) { return target && target.closest ? target.closest( '.av-nav--top li[data-dropdown-parent="true"], .av-nav--primary li[data-dropdown-parent="true"], ' + '.av-nav--top li.menu-item-has-children, .av-nav--primary li.menu-item-has-children' ) : null; } function setLiState(li, isOpen) { if (!li) return; if (isOpen) { li.classList.add('is-open'); li.dataset.state = 'open'; } else { li.classList.remove('is-open'); li.dataset.state = 'closed'; delete li.dataset.dsArmed; } var a = li.querySelector(':scope > a[data-dropdown-trigger]'); if (a) a.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); var b = li.querySelector(':scope > .av-dropdown-toggle, :scope > button[data-dropdown-toggle]'); if (b) b.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); } function closeSiblings(li) { if (!li || !li.parentElement) return; var siblings = li.parentElement.querySelectorAll(':scope > li.is-open'); siblings.forEach(function (sib) { if (sib !== li) setLiState(sib, false); }); } function initWindowsTouchPatch() { var root = document.querySelector('.av-responsive-menu'); if (!root) return; if (!isWindowsTouchDesktop(root)) return; // Block synthetic mouse events right after touch var ignoreMouseUntil = 0; function shouldIgnorePointer(e) { if (!e) return false; if (e.pointerType === 'touch') { ignoreMouseUntil = Date.now() + 650; return false; } if (e.pointerType === 'mouse' && Date.now() < ignoreMouseUntil) return true; return false; } // Click suppression token (per tap) var suppressNextClickUntil = 0; function suppressThisTap() { suppressNextClickUntil = Date.now() + 800; } // 1) pointerdown capture: handle toggles BEFORE existing code root.addEventListener( 'pointerdown', function (e) { if (!isWindowsTouchDesktop(root)) return; if (shouldIgnorePointer(e)) return; var nav = findNavContainer(e.target); if (!nav) return; var btn = e.target && e.target.closest ? e.target.closest('.av-dropdown-toggle, button[data-dropdown-toggle]') : null; var link = e.target && e.target.closest ? e.target.closest('a[data-dropdown-trigger]') : null; // Arrow button: always toggle on first tap if (btn) { var liBtn = findParentLi(btn); if (!liBtn) return; e.preventDefault(); e.stopPropagation(); if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation(); var isOpenBtn = liBtn.classList.contains('is-open') || liBtn.dataset.state === 'open'; if (!isOpenBtn) closeSiblings(liBtn); setLiState(liBtn, !isOpenBtn); // Prevent "open then close" from other click handlers suppressThisTap(); return; } // Parent link: 1st tap opens, 2nd tap navigates if (link) { var liLink = findParentLi(link); if (!liLink) return; var isOpenLink = liLink.classList.contains('is-open') || liLink.dataset.state === 'open'; var armed = liLink.dataset.dsArmed === '1'; // Closed => open only if (!isOpenLink) { e.preventDefault(); e.stopPropagation(); if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation(); closeSiblings(liLink); setLiState(liLink, true); liLink.dataset.dsArmed = '1'; suppressThisTap(); return; } // Open: // If armed => allow navigation on second tap, but keep other handlers from toggling it. if (armed) { // Do NOT preventDefault here (we want to navigate). // But we *do* stop propagation to avoid other handlers closing before nav. e.stopPropagation(); if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation(); return; } // Open but not armed (opened by something else): arm it, and suppress click once. e.preventDefault(); e.stopPropagation(); if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation(); liLink.dataset.dsArmed = '1'; suppressThisTap(); } }, true ); // 2) click capture: suppress the click that follows our pointerdown handling root.addEventListener( 'click', function (e) { if (!isWindowsTouchDesktop(root)) return; // If we just handled the tap on pointerdown, swallow click so other menu JS can't "undo" it. if (Date.now() < suppressNextClickUntil) { e.preventDefault(); e.stopPropagation(); if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation(); } }, true ); // 3) Outside tap closes document.addEventListener( 'pointerdown', function (e) { if (!isWindowsTouchDesktop(root)) return; if (!e || root.contains(e.target)) return; var openLis = root.querySelectorAll('.av-nav--top li.is-open, .av-nav--primary li.is-open'); openLis.forEach(function (li) { setLiState(li, false); }); }, { passive: true } ); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initWindowsTouchPatch, { once: true }); } else { initWindowsTouchPatch(); } })(); // ======================== // Safari detection + "latest" sliders + chips slider // ======================== (function () { 'use strict'; function isSafariDesktop() { const ua = navigator.userAgent; return /Safari/.test(ua) && !/(Chrome|Chromium|Edg|OPR|Brave|Vivaldi)/.test(ua); } function isSafariIOS() { const ua = navigator.userAgent; const isiOS = /iP(hone|ad|od)/.test(ua); return isiOS && /Safari/.test(ua) && !/(CriOS|FxiOS|EdgiOS|OPiOS)/.test(ua); } function isSafari() { return isSafariDesktop() || isSafariIOS(); } if (isSafari()) { document.documentElement.classList.add('is-safari'); if (isSafariIOS()) document.documentElement.classList.add('is-safari-ios'); if (isSafariDesktop()) document.documentElement.classList.add('is-safari-macos'); } document.addEventListener('DOMContentLoaded', () => { if (isSafari()) { document.body.classList.add('is-safari'); if (isSafariIOS()) document.body.classList.add('is-safari-ios'); if (isSafariDesktop()) document.body.classList.add('is-safari-macos'); } const aVselector = '.featured-office-block .wp-block-post-featured-image > p'; const firstMatch = document.querySelector(aVselector); if (!firstMatch) return; document.querySelectorAll(aVselector).forEach((p) => p.remove()); }); // ---------- IIFE #1: .latest-sections slider ---------- (function () { const BP_ON = 1024; const GAP_TAB = 30; const GAP_MOB = 20; const PEEK_TAB = 60; const PEEK_MOB = 40; const EASE_MS = 400; const THRESH_FR = 0.12; const REDUCED = matchMedia('(prefers-reduced-motion: reduce)').matches; const clamp = (n, a, b) => Math.min(Math.max(n, a), b); const blocks = document.querySelectorAll('.latest-sections'); if (!blocks.length) return; blocks.forEach(bootstrapCards); let rTO1; addEventListener( 'resize', () => { clearTimeout(rTO1); rTO1 = setTimeout(() => blocks.forEach(bootstrapCards), 120); }, { passive: true } ); function bootstrapCards(root) { const cols = root.querySelector('.wp-block-columns'); if (!cols) return; const active = innerWidth <= BP_ON; const inited = root.dataset.cardsInit === '1'; if (active && !inited) initCards(root, cols); else if (!active && inited) destroyCards(root); else if (active && inited) { const idx = root._cards && typeof root._cards.uiIndex === 'number' ? root._cards.uiIndex : 0; layoutCards(root); goToCard(root, idx, true); } } function initCards(root, cols) { root.dataset.cardsInit = '1'; const slides = Array.from(cols.querySelectorAll('.latest-unit')); if (!slides.length) { root.dataset.cardsInit = '0'; return; } const viewport = document.createElement('div'); viewport.className = 'ls-viewport'; viewport.style.overflow = 'hidden'; viewport.style.position = 'relative'; viewport.style.touchAction = 'pan-y'; const track = document.createElement('div'); track.className = 'ls-track'; track.style.display = 'flex'; track.style.willChange = 'transform'; track.style.transition = REDUCED ? 'none' : `transform ${EASE_MS}ms ease`; viewport.appendChild(track); cols.parentNode.insertBefore(viewport, cols); slides.forEach((s) => { s.classList.add('ls-slide'); s.style.flex = '0 0 auto'; s.style.maxWidth = 'none'; track.appendChild(s); }); cols.style.display = 'none'; const dots = document.createElement('div'); dots.className = 'ls-dots'; dots.setAttribute('role', 'tablist'); slides.forEach((_, i) => { const b = document.createElement('button'); b.className = 'ls-dot'; b.type = 'button'; b.setAttribute('role', 'tab'); b.setAttribute('aria-label', `Go to slide ${i + 1}`); dots.appendChild(b); }); root.appendChild(dots); viewport.setAttribute('aria-roledescription', 'carousel'); viewport.setAttribute('aria-label', 'Latest items'); slides.forEach((s, i) => { s.setAttribute('role', 'group'); s.setAttribute('aria-roledescription', 'slide'); s.setAttribute('aria-label', `Slide ${i + 1} of ${slides.length}`); }); const st = { uiIndex: 0, count: slides.length, els: { root, cols, viewport, track, slides, dots }, moved: false, dragging: false, justDragged: false, gap: 0, peek: 0, slideW: 0, step: 0, maxTranslate: 0, }; root._cards = st; const dotBtns = Array.from(dots.children); st.els.dotHandlers = dotBtns.map((_, i) => () => goToCard(root, i)); dotBtns.forEach((btn, i) => btn.addEventListener('click', st.els.dotHandlers[i]) ); st.onKey = (e) => { if (e.key === 'ArrowLeft') { e.preventDefault(); goToCard(root, st.uiIndex - 1); } if (e.key === 'ArrowRight') { e.preventDefault(); goToCard(root, st.uiIndex + 1); } }; viewport.tabIndex = 0; viewport.addEventListener('keydown', st.onKey); const onDown = (x) => { st.dragging = true; st.moved = false; st.justDragged = false; st.startX = x; st.curX = x; track.style.transition = 'none'; }; const onMove = (x) => { if (!st.dragging) return; st.curX = x; const dx = x - st.startX; if (Math.abs(dx) > 3) st.moved = true; const baseX = clamp(st.uiIndex * st.step, 0, st.maxTranslate); const raw = baseX - dx; const clampX = clamp(raw, 0, st.maxTranslate); track.style.transform = `translateX(${-clampX}px)`; }; const onUp = () => { if (!st.dragging) return; const dx = st.curX - st.startX; st.dragging = false; track.style.transition = REDUCED ? 'none' : `transform ${EASE_MS}ms ease`; const threshold = Math.max(40, st.step * THRESH_FR); if (dx > threshold) goToCard(root, st.uiIndex - 1); else if (dx < -threshold) goToCard(root, st.uiIndex + 1); else goToCard(root, st.uiIndex); if (st.moved) st.justDragged = true; }; st.pointerHandlers = { down: (e) => { viewport.setPointerCapture(e.pointerId); onDown(e.clientX); }, move: (e) => { if (st.dragging) onMove(e.clientX); }, up: () => onUp(), cancel: () => onUp(), }; viewport.addEventListener('pointerdown', st.pointerHandlers.down); viewport.addEventListener('pointermove', st.pointerHandlers.move, { passive: true, }); viewport.addEventListener('pointerup', st.pointerHandlers.up); viewport.addEventListener( 'pointercancel', st.pointerHandlers.cancel ); st.onClickCapture = (e) => { if (st.justDragged) { e.preventDefault(); e.stopPropagation(); st.justDragged = false; } }; viewport.addEventListener('click', st.onClickCapture, true); layoutCards(root); goToCard(root, 0, true); st.ro = new ResizeObserver(() => { layoutCards(root); goToCard(root, st.uiIndex, true); }); st.ro.observe(viewport); } function layoutCards(root) { const st = root._cards; if (!st) return; const { viewport, track, slides } = st.els; const isMobile = innerWidth <= 767; st.gap = isMobile ? GAP_MOB : GAP_TAB; st.peek = isMobile ? PEEK_MOB : PEEK_TAB; if (st.count <= 1) st.peek = 0; const vw = viewport.clientWidth; st.slideW = Math.max(0, vw - st.peek); const w = Math.floor(st.slideW); track.style.gap = `${st.gap}px`; slides.forEach((s) => { s.style.width = `${w}px`; }); st.step = Math.floor(st.slideW + st.gap); const contentW = st.count * st.slideW + (st.count - 1) * st.gap; const viewportW = st.slideW + st.peek; st.maxTranslate = Math.max(0, Math.ceil(contentW - viewportW)); } function goToCard(root, uiIndex, immediate) { const st = root._cards; if (!st) return; const { track, dots } = st.els; st.uiIndex = Math.min(Math.max(uiIndex, 0), st.count - 1); const rawX = st.uiIndex * st.step; const x = Math.min(rawX, st.maxTranslate); if (immediate || REDUCED) track.style.transition = 'none'; track.style.transform = `translateX(${-x}px)`; if (immediate || REDUCED) { track.getBoundingClientRect(); if (!REDUCED) { track.style.transition = `transform ${EASE_MS}ms ease`; } } Array.from(dots.children).forEach((b, i) => { if (i === st.uiIndex) { b.setAttribute('aria-selected', 'true'); b.tabIndex = 0; } else { b.removeAttribute('aria-selected'); b.tabIndex = -1; } }); } function destroyCards(root) { const st = root._cards; if (!st) return; const { viewport, track, cols, slides, dots } = st.els; if (st.ro) st.ro.disconnect(); if (st.onKey) viewport.removeEventListener('keydown', st.onKey); if (st.pointerHandlers) { viewport.removeEventListener( 'pointerdown', st.pointerHandlers.down ); viewport.removeEventListener( 'pointermove', st.pointerHandlers.move ); viewport.removeEventListener( 'pointerup', st.pointerHandlers.up ); viewport.removeEventListener( 'pointercancel', st.pointerHandlers.cancel ); } if (st.onClickCapture) { viewport.removeEventListener('click', st.onClickCapture, true); } const btns = Array.from(dots.children); if (st.els.dotHandlers) { btns.forEach((btn, i) => btn.removeEventListener('click', st.els.dotHandlers[i]) ); } slides.forEach((s) => { s.classList.remove('ls-slide'); s.style.width = ''; s.style.flex = ''; s.style.maxWidth = ''; cols.appendChild(s); }); if (viewport && viewport.parentNode) { viewport.parentNode.removeChild(viewport); } if (dots && dots.parentNode) { dots.parentNode.removeChild(dots); } cols.style.display = ''; delete root._cards; root.dataset.cardsInit = '0'; } })(); // ---------- IIFE #2: .turns-into-slider-xs chips slider ---------- (function () { const BP_ON = 992; // match your SCSS breakpoint (< 992px) const EASE_MS = 300; const REDUCED = matchMedia('(prefers-reduced-motion: reduce)').matches; const getTranslateX = (el) => { const t = getComputedStyle(el).transform; if (!t || t === 'none') return 0; if (typeof DOMMatrix !== 'undefined') { const m = new DOMMatrix(t); return m.m41 || 0; } if (typeof WebKitCSSMatrix !== 'undefined') { const m = new WebKitCSSMatrix(t); return m.m41 || 0; } const m2d = t.match(/matrix\([^,]+,[^,]+,[^,]+,[^,]+,(-?\d+\.?\d*),/); if (m2d && m2d[1]) return parseFloat(m2d[1]) || 0; const m3d = t.match(/matrix3d\((?:[^,]+,){12}(-?\d+\.?\d*)/); if (m3d && m3d[1]) return parseFloat(m3d[1]) || 0; return 0; }; const shells = document.querySelectorAll('.turns-into-slider-xs'); if (!shells.length) return; shells.forEach(bootstrap); let rTO; addEventListener('resize', () => { clearTimeout(rTO); rTO = setTimeout(() => { document.querySelectorAll('.turns-into-slider-xs').forEach(bootstrap); }, 120); }, { passive: true }); function bootstrap(shell) { const active = innerWidth <= BP_ON; const inited = shell.dataset.chipsInit === '1'; if (inited) destroy(shell); if (active) init(shell); } function init(shell) { shell.dataset.chipsInit = '1'; const viewport = document.createElement('div'); viewport.className = 'chips-viewport'; viewport.style.overflow = 'hidden'; viewport.style.position = 'relative'; viewport.style.touchAction = 'pan-y'; const track = document.createElement('div'); track.className = 'chips-track'; track.style.display = 'flex'; track.style.alignItems = 'stretch'; track.style.willChange = 'transform'; track.style.transform = 'translateX(0px)'; track.style.transition = REDUCED ? 'none' : `transform ${EASE_MS}ms ease`; const items = Array.from(shell.children); shell.parentNode.insertBefore(viewport, shell); viewport.appendChild(track); items.forEach((el) => { el.style.flex = '0 0 auto'; track.appendChild(el); }); shell.style.display = 'none'; const st = { shell, viewport, track, items, dragging: false, moved: false, justDragged: false, startX: 0, curX: 0, baseX: 0, maxTranslate: 0, ro: null, }; shell._chips = st; const onPointerDown = (e) => { st.dragging = true; st.moved = false; st.justDragged = false; st.startX = e.clientX; st.curX = e.clientX; st.baseX = getTranslateX(track); track.style.transition = 'none'; viewport.setPointerCapture(e.pointerId); }; const onPointerMove = (e) => { if (!st.dragging) return; st.curX = e.clientX; const dx = st.curX - st.startX; if (Math.abs(dx) > 3) st.moved = true; let next = st.baseX + dx; // Clamp between 0 and -maxTranslate next = Math.min(0, Math.max(next, -st.maxTranslate)); track.style.transform = `translateX(${next}px)`; }; const onPointerUp = () => { if (!st.dragging) return; st.dragging = false; snapToNearest(st); if (st.moved) st.justDragged = true; }; viewport.addEventListener('pointerdown', onPointerDown); viewport.addEventListener('pointermove', onPointerMove, { passive: true }); viewport.addEventListener('pointerup', onPointerUp); viewport.addEventListener('pointercancel', onPointerUp); st.pointerHandlers = { onPointerDown, onPointerMove, onPointerUp }; const onClickCap = (e) => { if (st.justDragged) { e.preventDefault(); e.stopPropagation(); st.justDragged = false; } }; viewport.addEventListener('click', onClickCap, true); st.onClickCap = onClickCap; layout(shell); const ro = new ResizeObserver(() => layout(shell)); ro.observe(viewport); st.ro = ro; } function layout(shell) { const st = shell._chips; if (!st) return; const { viewport, track } = st; // Includes item widths, flex gaps, padding, borders — everything. const total = track.scrollWidth; const vw = viewport.clientWidth; st.maxTranslate = Math.max(0, Math.ceil(total - vw)); const cur = getTranslateX(track); const clamped = Math.min(0, Math.max(cur, -st.maxTranslate)); track.style.transition = REDUCED ? 'none' : `transform ${EASE_MS}ms ease`; track.style.transform = `translateX(${clamped}px)`; } function snapToNearest(st) { const { track, items, maxTranslate } = st; if (!items.length) return; const curX = getTranslateX(track); const targets = [0, -maxTranslate]; items.forEach((el) => targets.push(-el.offsetLeft)); let target = targets[0]; let bestDist = Math.abs(curX - target); for (let i = 1; i < targets.length; i++) { const d = Math.abs(curX - targets[i]); if (d < bestDist) { bestDist = d; target = targets[i]; } } target = Math.min(0, Math.max(target, -maxTranslate)); track.style.transition = REDUCED ? 'none' : `transform ${EASE_MS}ms ease`; track.style.transform = `translateX(${target}px)`; } function destroy(shell) { const st = shell._chips; if (!st) return; const { viewport, track, items } = st; if (st.ro) st.ro.disconnect(); if (st.pointerHandlers) { viewport.removeEventListener('pointerdown', st.pointerHandlers.onPointerDown); viewport.removeEventListener('pointermove', st.pointerHandlers.onPointerMove); viewport.removeEventListener('pointerup', st.pointerHandlers.onPointerUp); viewport.removeEventListener('pointercancel', st.pointerHandlers.onPointerUp); } if (st.onClickCap) viewport.removeEventListener('click', st.onClickCap, true); items.forEach((el) => { el.style.flex = ''; shell.appendChild(el); }); if (viewport && viewport.parentNode) { viewport.parentNode.removeChild(viewport); } shell.style.display = ''; delete shell._chips; shell.dataset.chipsInit = '0'; } })(); })(); // ======================== // Viewport debugger (DEV only): enable via // ======================== (function () { 'use strict'; function showViewPortSize(display) { if (!display) return; const box = document.createElement('div'); box.id = 'viewportsize'; box.style.zIndex = '9999'; box.style.position = 'fixed'; box.style.bottom = '30px'; box.style.left = '0'; box.style.color = '#fff'; box.style.background = '#000'; box.style.padding = '10px'; box.style.fontFamily = 'monospace'; box.style.fontSize = '12px'; box.style.pointerEvents = 'none'; const updateSize = () => { const height = window.innerHeight; const width = window.innerWidth; box.innerHTML = `Height: ${height}
Width: ${width}`; }; updateSize(); document.body.appendChild(box); window.addEventListener('resize', updateSize); } document.addEventListener('DOMContentLoaded', () => { const debugFlag = document.documentElement.dataset.debugViewport === '1'; showViewPortSize(debugFlag); }); })(); // ======================== // Person tabs, LinkedIn, vCard width sync, tile cleanup // ======================== (function () { 'use strict'; const artInitPersonTabs = (root = document) => { const wrap = root.querySelector('.js-person-tabs'); if (!wrap || wrap.__artTabsBound) return; wrap.__artTabsBound = true; const onToggle = (e) => { const details = e.target; if ( !(details instanceof HTMLDetailsElement) || !details.classList.contains('person-section-details') ) return; if (details.open) { details.classList.add('tab-open'); details.classList.remove('tab-close'); } else { details.classList.remove('tab-open'); details.classList.add('tab-close'); } }; wrap.addEventListener('toggle', onToggle, true); }; if (document.readyState === 'loading') { document.addEventListener( 'DOMContentLoaded', () => artInitPersonTabs(), { once: true } ); } else { artInitPersonTabs(); } const artInit = () => { const linkedIns = document.querySelectorAll('.ds-linkedin'); if (linkedIns.length) { linkedIns.forEach((el) => el.classList.add('ln-loaded')); } const email = document.querySelector('.person-email'); const vcard = document.querySelector('.download-vcard'); if (!email || !vcard) return; const syncWidth = () => { const w = email.getBoundingClientRect().width - 26; vcard.style.width = `${Math.max(0, Math.floor(w))}px`; }; syncWidth(); if ('ResizeObserver' in window) { const ro = new ResizeObserver(() => { requestAnimationFrame(syncWidth); }); ro.observe(email); } window.addEventListener('resize', syncWidth, { passive: true }); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', artInit, { once: true }); } else { artInit(); } function art_init() { const hasPerson = document.querySelector('.person-tile'); const hasPl = document.querySelector('.pl-item'); if (!hasPerson && !hasPl) return; const nodes = document.querySelectorAll( '.person-tile > p, .pl-item > p' ); if (!nodes.length) return; nodes.forEach((p) => { if (p && p.parentNode) p.parentNode.removeChild(p); }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', art_init, { once: true }); } else { art_init(); } })(); // ======================== // External links + Swiper industry slider // ======================== (function () { 'use strict'; function markExternalLinks() { const links = document.querySelectorAll('a[href]'); const currentHost = window.location.hostname.replace(/^www\./, ''); const currentOrigin = window.location.origin; links.forEach((link) => { const href = link.getAttribute('href'); if ( !href || href.charAt(0) === '#' || href.indexOf('mailto:') === 0 || href.indexOf('tel:') === 0 || href.indexOf('javascript:') === 0 ) { return; } let url; try { url = new URL(href, currentOrigin); } catch (e) { return; } const linkHost = url.hostname.replace(/^www\./, ''); if (!['http:', 'https:'].includes(url.protocol)) return; if (linkHost && linkHost !== currentHost) { link.setAttribute('target', '_blank'); const rel = (link.getAttribute('rel') || '') .split(/\s+/) .filter(Boolean); if (!rel.includes('noopener')) rel.push('noopener'); if (!rel.includes('noreferrer')) rel.push('noreferrer'); link.setAttribute('rel', rel.join(' ')); } }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', markExternalLinks, { once: true, }); } else { markExternalLinks(); } // Swiper: industry featured slider function dsInitIndustryFeaturedSlider() { if (typeof window.Swiper === 'undefined') { return; } const sliders = document.querySelectorAll( '.ifs-slider.swiper[data-ifs-slider="1"]' ); if (!sliders.length) return; sliders.forEach((sliderEl) => { if (sliderEl.dataset.swiperInitialized === '1') return; sliderEl.dataset.swiperInitialized = '1'; const paginationEl = sliderEl.querySelector('.swiper-pagination'); const outer = sliderEl.closest('.industry-related-wrap'); let desktopSlides = 4; if ( outer && outer.classList.contains( 'industry-related-wrap--no-resources' ) && outer.classList.contains('industry-related-wrap--no-faqs') ) { desktopSlides = 2; } /* eslint-disable no-new */ new window.Swiper(sliderEl, { loop: true, speed: 700, spaceBetween: 50, autoplay: { delay: 8000, disableOnInteraction: false, }, slidesPerView: 1, slidesPerGroup: 1, centeredSlides: false, pagination: { el: paginationEl || null, clickable: true, }, breakpoints: { 0: { slidesPerView: 1, }, 768: { slidesPerView: 2, }, 1024: { slidesPerView: desktopSlides, }, }, a11y: { enabled: true, }, }); /* eslint-enable no-new */ }); } if (document.readyState === 'loading') { document.addEventListener( 'DOMContentLoaded', dsInitIndustryFeaturedSlider, { once: true } ); } else { dsInitIndustryFeaturedSlider(); } document.addEventListener('facetwp-loaded', dsInitIndustryFeaturedSlider); })(); /* one-word-paras.js */ /* few-words-paras.js */ (function () { 'use strict'; function countWords(text) { if (window.Intl && Intl.Segmenter) { const seg = new Intl.Segmenter(undefined, { granularity: 'word' }); let n = 0; for (const s of seg.segment(text)) if (s.isWordLike) n++; return n; } const m = text.replace(/\u00A0/g, ' ').match(/\b[\p{L}\p{N}’'-]+\b/gu); return m ? m.length : 0; } function tagShortParagraphs(root) { const scope = root || document; const paras = scope.querySelectorAll('.office-leadership .wp-block-heading, .pattern-linked-box p, .office-team-cta .wp-block-heading'); for (let i = 0; i < paras.length; i++) { const p = paras[i]; const text = (p.textContent || '').trim(); if (!text) continue; const wc = countWords(text); // shared class for 1–2 words if (wc <= 2) { p.classList.add('is-few-words'); if (wc === 1) p.classList.add('is-one-word'); if (wc === 2) p.classList.add('is-two-words'); } } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function () { tagShortParagraphs(); }, { once: true }); } else { tagShortParagraphs(); } const STORAGE_KEY = "ds_last_service_parent"; const qs = (sel, root = document) => root.querySelector(sel); // --- 1) Remember the last parent service the user clicked from --- document.addEventListener("click", (event) => { const link = event.target.closest("a.js-service-child-link"); if (!link) return; const parentId = link.getAttribute("data-parent-service-id"); if (!parentId) return; try { window.sessionStorage.setItem(STORAGE_KEY, String(parentId)); // console.log("[ds] stored parent", parentId); } catch (err) { // ignore storage errors } }); // --- 2) On service single, override the parent crumb if we have context --- document.addEventListener("DOMContentLoaded", () => { const nav = qs(".ds-breadcrumbs.ds-breadcrumbs--services"); if (!nav) return; const parentsJson = nav.getAttribute("data-service-parents"); if (!parentsJson) { // console.log("[ds] no data-service-parents on nav"); return; } let parents; try { parents = JSON.parse(parentsJson); } catch (err) { // console.warn("[ds] failed to parse parents JSON", err); return; } if (!parents || typeof parents !== "object") { return; } let storedParentId = null; try { storedParentId = window.sessionStorage.getItem(STORAGE_KEY); } catch (err) { storedParentId = null; } if (!storedParentId) { // console.log("[ds] no stored parent id"); return; } // Keys from PHP JSON will be strings const keyStr = String(storedParentId); const keyInt = parseInt(storedParentId, 10); let parentInfo = parents[keyStr]; if (!parentInfo && Number.isFinite(keyInt)) { parentInfo = parents[String(keyInt)]; } if (!parentInfo) { // console.log("[ds] stored parent not found in map", storedParentId, parents); return; } const parentLink = nav.querySelector(".ds-breadcrumbs-parent--services"); // If there is no parent link at all, we could insert one, but for now just bail. if (!parentLink) { // console.log("[ds] no .ds-breadcrumbs-parent--services link to override"); return; } if (parentInfo.url) { parentLink.setAttribute("href", parentInfo.url); } if (parentInfo.title) { parentLink.textContent = parentInfo.title; } }); if (!document.querySelector(".ds-search-reveal-btn")) return; document.addEventListener("click", (e) => { const btn = e.target.closest(".ds-search-reveal-btn"); if (!btn) return; e.preventDefault(); const section = btn.closest(".search-section"); if (!section) return; // First click: reveal hidden items if (!btn.dataset.revealed) { section.querySelectorAll(".ds-search-hidden-item").forEach((el) => { el.classList.remove("ds-search-hidden-item"); }); btn.dataset.revealed = "1"; const needsViewAll = btn.dataset.needsViewAll === "1"; if (needsViewAll) { btn.textContent = btn.getAttribute("data-view-all-label") || "View all results"; } else { // remove entire button area const buttonWrap = btn.closest(".wp-block-buttons") || btn.closest(".wp-block-button"); if (buttonWrap) { buttonWrap.remove(); } else { btn.remove(); } } return; } // Second click: go to view-all page (only if needed) if (btn.dataset.needsViewAll !== "1") return; const url = btn.getAttribute("data-view-all-url"); if (url) window.location.assign(url); }); })(); // ---------- IIFE #3: .lfs-serv-ind-slider — INFINITE LOOP + DOTS + VIP-ROBUST DRAG ---------- (function () { 'use strict'; const LFS_SELECTOR = '.lfs-serv-ind-slider'; const LFS_MIN_COUNT_TO_SLIDE = 4; // Breakpoints: desktop=3, <=1023=2, <=767=1 const LFS_BP_TAB = 1080; const LFS_BP_MOB = 599; const LFS_GAP_DESK = 40; const LFS_GAP_TAB = 30; const LFS_GAP_MOB = 20; const LFS_EASE_MS = 400; const LFS_THRESH_FR = 0.12; const LFS_REDUCED = matchMedia('(prefers-reduced-motion: reduce)').matches; // Autoplay const LFS_AUTOPLAY_MS = 4500; const LFS_AUTOPLAY_RESUME_DELAY = 1200; const clamp = (n, a, b) => Math.min(Math.max(n, a), b); const getPerView = () => { if (innerWidth <= LFS_BP_MOB) return 2; if (innerWidth <= LFS_BP_TAB) return 2; return 3; }; const getGap = () => { if (innerWidth <= LFS_BP_MOB) return LFS_GAP_MOB; if (innerWidth <= LFS_BP_TAB) return LFS_GAP_TAB; return LFS_GAP_DESK; }; function scanAndInit(rootNode) { const scope = rootNode && rootNode.nodeType === 1 ? rootNode : document; const roots = scope.querySelectorAll ? scope.querySelectorAll(LFS_SELECTOR) : document.querySelectorAll(LFS_SELECTOR); if (!roots.length) return; roots.forEach((root) => { if (root.dataset.lfsInit === '1' && root._lfs) { rebuildForBreakpoint(root); return; } const items = Array.from(root.children).filter((n) => n && n.nodeType === 1); if (items.length < LFS_MIN_COUNT_TO_SLIDE) return; init(root, items); }); } function init(root, originalItems) { root.dataset.lfsInit = '1'; const viewport = document.createElement('div'); viewport.className = 'lfs-viewport'; viewport.style.overflow = 'hidden'; viewport.style.position = 'relative'; viewport.style.width = '100%'; viewport.style.touchAction = 'pan-y'; viewport.style.setProperty('user-select', 'none', 'important'); viewport.style.setProperty('-webkit-user-select', 'none', 'important'); const track = document.createElement('div'); track.className = 'lfs-track'; track.style.setProperty('display', 'flex', 'important'); track.style.setProperty('flex-wrap', 'nowrap', 'important'); track.style.setProperty('flex-direction', 'row', 'important'); track.style.setProperty('align-items', 'center', 'important'); track.style.setProperty('user-select', 'none', 'important'); track.style.setProperty('-webkit-user-select', 'none', 'important'); track.style.willChange = 'transform'; track.style.transform = 'translateX(0px)'; track.style.transition = LFS_REDUCED ? 'none' : `transform ${LFS_EASE_MS}ms ease`; viewport.appendChild(track); root.parentNode.insertBefore(viewport, root); // Hide original wrapper root.style.display = 'none'; // Dots const dots = document.createElement('div'); dots.className = 'lfs-dots'; dots.setAttribute('role', 'tablist'); viewport.parentNode.insertBefore(dots, viewport.nextSibling); const st = { uiIndex: 0, // real slide index loopIndex: 0, // index in track (includes clones) realCount: originalItems.length, perView: getPerView(), gap: 0, slideW: 0, step: 0, dragging: false, moved: false, justDragged: false, startX: 0, startY: 0, curX: 0, curY: 0, lockAxis: null, // null | 'x' | 'y' baseLoopIndex: 0, activePointerId: null, _autoTimer: null, _autoResumeTimer: null, els: { root, viewport, track, dots }, realItems: originalItems, allItems: [], dotBtns: [], dotHandlers: [], }; root._lfs = st; viewport.setAttribute('aria-roledescription', 'carousel'); viewport.setAttribute('aria-label', 'Slider'); viewport.tabIndex = 0; buildTrackAndDots(st); // Pause autoplay on hover/focus viewport.addEventListener('mouseenter', () => stopAutoplay(st)); viewport.addEventListener('mouseleave', () => scheduleAutoplayResume(st)); viewport.addEventListener('focusin', () => stopAutoplay(st)); viewport.addEventListener('focusout', () => scheduleAutoplayResume(st)); // Keyboard st.onKey = (e) => { if (e.key === 'ArrowLeft') { e.preventDefault(); stopAutoplay(st); moveBy(st, -1); scheduleAutoplayResume(st); } if (e.key === 'ArrowRight') { e.preventDefault(); stopAutoplay(st); moveBy(st, 1); scheduleAutoplayResume(st); } }; viewport.addEventListener('keydown', st.onKey); // Robust drag (window capture) bindDrag(st); // Prevent clicks after drag st.onClickCapture = (e) => { if (st.justDragged) { e.preventDefault(); e.stopPropagation(); st.justDragged = false; } }; viewport.addEventListener('click', st.onClickCapture, true); // Resize observer st.ro = new ResizeObserver(() => rebuildForBreakpoint(root)); st.ro.observe(viewport); ensureAutoplay(st); } function rebuildForBreakpoint(root) { const st = root._lfs; if (!st) return; const nextPerView = getPerView(); if (nextPerView === st.perView) { layout(st); snapToLoopIndex(st, st.loopIndex, true); updateDots(st); ensureAutoplay(st); return; } const keepRealIndex = st.uiIndex; stopAutoplay(st); st.perView = nextPerView; buildTrackAndDots(st); st.uiIndex = clamp(keepRealIndex, 0, st.realCount - 1); st.loopIndex = st.uiIndex + st.perView; layout(st); snapToLoopIndex(st, st.loopIndex, true); updateDots(st); ensureAutoplay(st); } function buildTrackAndDots(st) { const { track, dots } = st.els; // Clear track while (track.firstChild) track.removeChild(track.firstChild); // Clear dots and handlers if (st.dotBtns.length && st.dotHandlers.length) { st.dotBtns.forEach((btn, i) => btn.removeEventListener('click', st.dotHandlers[i])); } while (dots.firstChild) dots.removeChild(dots.firstChild); st.dotBtns = []; st.dotHandlers = []; const real = st.realItems; const cloneN = Math.min(st.perView, st.realCount); const leftClones = []; const rightClones = []; for (let i = st.realCount - cloneN; i < st.realCount; i++) { const c = real[i].cloneNode(true); c.classList.add('lfs-clone'); leftClones.push(c); } real.forEach((el) => { el.classList.add('lfs-slide'); el.style.setProperty('flex', '0 0 auto', 'important'); el.style.setProperty('max-width', 'none', 'important'); // Disable native dragging/selecting inside slides (VIP prod often differs here) el.style.setProperty('user-select', 'none', 'important'); el.style.setProperty('-webkit-user-select', 'none', 'important'); el.querySelectorAll('img').forEach((img) => { img.setAttribute('draggable', 'false'); img.style.setProperty('-webkit-user-drag', 'none', 'important'); img.style.setProperty('user-drag', 'none', 'important'); img.style.setProperty('pointer-events', 'none', 'important'); // drag handled by viewport/window }); }); for (let i = 0; i < cloneN; i++) { const c = real[i].cloneNode(true); c.classList.add('lfs-clone'); // Ensure clones also disable native drag c.querySelectorAll('img').forEach((img) => { img.setAttribute('draggable', 'false'); img.style.setProperty('-webkit-user-drag', 'none', 'important'); img.style.setProperty('user-drag', 'none', 'important'); img.style.setProperty('pointer-events', 'none', 'important'); }); rightClones.push(c); } st.allItems = [...leftClones, ...real, ...rightClones]; st.allItems.forEach((el) => { el.style.setProperty('flex', '0 0 auto', 'important'); el.style.setProperty('max-width', 'none', 'important'); track.appendChild(el); }); // Dots for (let i = 0; i < st.realCount; i++) { const b = document.createElement('button'); b.className = 'lfs-dot'; b.type = 'button'; b.setAttribute('role', 'tab'); b.setAttribute('aria-label', `Go to slide ${i + 1}`); b.tabIndex = i === 0 ? 0 : -1; dots.appendChild(b); const handler = () => { stopAutoplay(st); goToRealIndex(st, i); scheduleAutoplayResume(st); }; b.addEventListener('click', handler); st.dotBtns.push(b); st.dotHandlers.push(handler); } st.uiIndex = clamp(st.uiIndex, 0, st.realCount - 1); st.loopIndex = st.uiIndex + st.perView; layout(st); snapToLoopIndex(st, st.loopIndex, true); updateDots(st); dots.style.display = st.realCount > st.perView ? '' : 'none'; } function layout(st) { const { viewport, track } = st.els; st.gap = getGap(); const vw = viewport.clientWidth; const per = Math.max(1, st.perView); const slideW = (vw - st.gap * (per - 1)) / per; st.slideW = Math.max(0, slideW); const w = Math.floor(st.slideW); track.style.gap = `${st.gap}px`; st.allItems.forEach((el) => { el.style.width = `${w}px`; }); st.step = Math.floor(st.slideW + st.gap); } function snapToLoopIndex(st, loopIndex, immediate) { st.loopIndex = loopIndex; const x = st.loopIndex * st.step; if (immediate || LFS_REDUCED) st.els.track.style.transition = 'none'; st.els.track.style.transform = `translateX(${-x}px)`; if (immediate || LFS_REDUCED) { st.els.track.getBoundingClientRect(); if (!LFS_REDUCED) st.els.track.style.transition = `transform ${LFS_EASE_MS}ms ease`; } } function moveBy(st, delta) { st.uiIndex = (st.uiIndex + delta + st.realCount) % st.realCount; updateDots(st); const targetLoop = st.loopIndex + delta; snapToLoopIndex(st, targetLoop, false); if (LFS_REDUCED) normalizeIfNeeded(st); else { const onEnd = () => { st.els.track.removeEventListener('transitionend', onEnd); normalizeIfNeeded(st); }; st.els.track.addEventListener('transitionend', onEnd); } } function normalizeIfNeeded(st) { const minRealLoop = st.perView; const maxRealLoop = st.perView + st.realCount - 1; if (st.loopIndex < minRealLoop) { st.loopIndex = st.loopIndex + st.realCount; snapToLoopIndex(st, st.loopIndex, true); } else if (st.loopIndex > maxRealLoop) { st.loopIndex = st.loopIndex - st.realCount; snapToLoopIndex(st, st.loopIndex, true); } } function goToRealIndex(st, targetRealIndex) { targetRealIndex = clamp(targetRealIndex, 0, st.realCount - 1); const cur = st.uiIndex; let delta = targetRealIndex - cur; const half = st.realCount / 2; if (delta > half) delta -= st.realCount; else if (delta < -half) delta += st.realCount; st.uiIndex = targetRealIndex; updateDots(st); const targetLoop = st.loopIndex + delta; snapToLoopIndex(st, targetLoop, false); if (LFS_REDUCED) normalizeIfNeeded(st); else { const onEnd = () => { st.els.track.removeEventListener('transitionend', onEnd); normalizeIfNeeded(st); }; st.els.track.addEventListener('transitionend', onEnd); } } function updateDots(st) { const dots = st.dotBtns; if (!dots || !dots.length) return; dots.forEach((b, i) => { if (i === st.uiIndex) { b.classList.add('is-active'); b.setAttribute('aria-selected', 'true'); b.tabIndex = 0; } else { b.classList.remove('is-active'); b.removeAttribute('aria-selected'); b.tabIndex = -1; } }); } // ------------------------------------------------------------ // VIP-ROBUST DRAG: start on viewport, move/up on WINDOW (capture) // ------------------------------------------------------------ function bindDrag(st) { const { viewport, track } = st.els; const endDrag = () => { if (!st.dragging) return; st.dragging = false; st.activePointerId = null; track.style.transition = LFS_REDUCED ? 'none' : `transform ${LFS_EASE_MS}ms ease`; const dx = st.curX - st.startX; const threshold = Math.max(40, st.step * LFS_THRESH_FR); if (st.lockAxis === 'x') { if (dx > threshold) moveBy(st, -1); else if (dx < -threshold) moveBy(st, 1); else snapToLoopIndex(st, st.loopIndex, false); if (st.moved) st.justDragged = true; } else { // User was scrolling vertically -> snap back snapToLoopIndex(st, st.loopIndex, false); } st.lockAxis = null; window.removeEventListener('pointermove', onWinMove, true); window.removeEventListener('pointerup', onWinUp, true); window.removeEventListener('pointercancel', onWinUp, true); scheduleAutoplayResume(st); }; const onWinMove = (e) => { // ignore other pointers if we captured one if (st.activePointerId !== null && e.pointerId !== st.activePointerId) return; // stop “hover drag” if mouse is no longer pressed if (e.pointerType === 'mouse' && st.dragging && e.buttons === 0) { endDrag(); return; } st.curX = e.clientX; st.curY = e.clientY; const dx = st.curX - st.startX; const dy = st.curY - st.startY; // Decide axis lock if (!st.lockAxis) { if (Math.abs(dx) > 6 || Math.abs(dy) > 6) { st.lockAxis = Math.abs(dx) > Math.abs(dy) ? 'x' : 'y'; } } if (st.lockAxis === 'x') { // critical on VIP: stop native drag/selection/scroll while horizontal e.preventDefault(); if (Math.abs(dx) > 3) st.moved = true; const baseX = st.baseLoopIndex * st.step; const raw = baseX - dx; track.style.transform = `translateX(${-raw}px)`; } }; const onWinUp = () => endDrag(); const onDown = (e) => { // primary mouse only if (e.pointerType === 'mouse' && e.button !== 0) return; stopAutoplay(st); st.dragging = true; st.moved = false; st.justDragged = false; st.lockAxis = null; st.activePointerId = typeof e.pointerId === 'number' ? e.pointerId : null; st.startX = e.clientX; st.startY = e.clientY; st.curX = e.clientX; st.curY = e.clientY; st.baseLoopIndex = st.loopIndex; // stop native image dragging on VIP prod e.preventDefault(); track.style.transition = 'none'; // Listen on WINDOW capture so nothing can block our drag window.addEventListener('pointermove', onWinMove, { capture: true, passive: false }); window.addEventListener('pointerup', onWinUp, true); window.addEventListener('pointercancel', onWinUp, true); }; // bind on viewport capture to beat overlays viewport.addEventListener('pointerdown', onDown, true); // extra safety: if pointer leaves / capture lost, end viewport.addEventListener('lostpointercapture', endDrag); viewport.addEventListener('pointerleave', endDrag); // store for reference st._dragHandlers = { onDown, onWinMove, onWinUp, endDrag }; } // ------------------------------------------------------------ // Autoplay // ------------------------------------------------------------ function stopAutoplay(st) { if (st._autoTimer) { clearInterval(st._autoTimer); st._autoTimer = null; } if (st._autoResumeTimer) { clearTimeout(st._autoResumeTimer); st._autoResumeTimer = null; } } function startAutoplay(st) { stopAutoplay(st); if (LFS_REDUCED) return; if (st.realCount <= st.perView) return; st._autoTimer = setInterval(() => moveBy(st, 1), LFS_AUTOPLAY_MS); } function scheduleAutoplayResume(st) { stopAutoplay(st); if (LFS_REDUCED) return; st._autoResumeTimer = setTimeout(() => startAutoplay(st), LFS_AUTOPLAY_RESUME_DELAY); } function ensureAutoplay(st) { if (st.realCount <= st.perView) { stopAutoplay(st); return; } if (!st._autoTimer && !st.dragging) startAutoplay(st); } // ------------------------------------------------------------ // Run // ------------------------------------------------------------ const run = () => scanAndInit(document); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', run); } else { run(); } addEventListener('load', run, { once: true, passive: true }); document.addEventListener('facetwp-loaded', run); let resizeTO; addEventListener( 'resize', () => { clearTimeout(resizeTO); resizeTO = setTimeout(run, 120); }, { passive: true } ); const mo = new MutationObserver((mutations) => { for (const m of mutations) { for (const node of m.addedNodes) { if (!node || node.nodeType !== 1) continue; if (node.matches && node.matches(LFS_SELECTOR)) { scanAndInit(node.parentNode || document); return; } if (node.querySelector && node.querySelector(LFS_SELECTOR)) { scanAndInit(node); return; } } } }); mo.observe(document.documentElement, { childList: true, subtree: true }); //dsd advisors check const TARGET_PATH = '/services/dsd-advisors/'; const normalizePath = (path) => { if (!path) return '/'; let p = path; // Ensure leading slash if (!p.startsWith('/')) p = `/${p}`; // Ensure exactly one trailing slash p = p.replace(/\/+$/, ''); return `${p}/`; }; document.addEventListener('DOMContentLoaded', () => { const target = normalizePath(TARGET_PATH); // Scope it if you want, e.g. '.entry-content a[href]' const links = document.querySelectorAll('a[href]'); for (const a of links) { const href = a.getAttribute('href'); if (!href) continue; // Skip non-nav types if (href.startsWith('#') || href.startsWith('mailto:') || href.startsWith('tel:')) continue; let url; try { url = new URL(href, window.location.origin); } catch { continue; } if (normalizePath(url.pathname) === target) { a.target = '_blank'; // Security best practice for new tab a.rel = 'noopener noreferrer'; } } }); })(); document.addEventListener('DOMContentLoaded', () => { const selector = '.single-offices figure.wp-block-post-featured-image > p'; const nodes = document.querySelectorAll(selector); if (!nodes.length) return; nodes.forEach((node) => node.remove()); }); ; (()=>{let s=new Set(["pager","sort","per_page","reset"]),n={lastAction:null,lastFacetName:null,lastFocused:null},a=(e,t)=>(t||document).querySelector(e),r=(e,t)=>Array.prototype.slice.call((t||document).querySelectorAll(e)),t=e=>{let t=a("#facetwp-announcer");t&&(t.textContent="",setTimeout(()=>{t.textContent=e},10))},o=t=>{var e=a("#results");e&&e.setAttribute("aria-busy",t?"true":"false"),r(".fwp-reset-all-fields, .facetwp-reset, .fwp-clear-facet").forEach(e=>{e.disabled=!!t,e.setAttribute("aria-disabled",t?"true":"false")})},l=()=>{r(".facetwp-facet").forEach(t=>{if(!t.querySelector(".fwp-clear-facet")){var a,r=t.getAttribute("data-type")||"";if(!s.has(r)){let e=t.getAttribute("data-name")||"";e&&((r=document.createElement("button")).type="button",r.className="fwp-clear-facet",r.setAttribute("data-facet",e),r.setAttribute("aria-label",`Clear ${e} filter`),r.setAttribute("aria-controls","results"),(a=document.createElement("span")).className="btn-label",a.textContent="Clear",r.appendChild(a),r.addEventListener("click",()=>{n.lastAction="reset-facet",n.lastFacetName=e,n.lastFocused=document.activeElement,window.FWP&&"function"==typeof window.FWP.reset&&window.FWP.reset(e)}),t.appendChild(r))}}})},c=e=>!(!window.FWP||!window.FWP.facets)&&(e=window.FWP.facets[e],Array.isArray(e)||"string"==typeof e?0{if(window.FWP&&window.FWP.facets){var e,t=window.FWP.facets;for(e in t)if(Object.prototype.hasOwnProperty.call(t,e)){var a=t[e];if(Array.isArray(a)&&a.length)return!0;if("string"==typeof a&&a.length)return!0;if(a&&"object"==typeof a&&Object.keys(a).length)return!0}}return!1},d=()=>{if(e())return!0;var t=r('.facetwp-facet[data-type="search"] .facetwp-search');for(let e=0;e{r(".facetwp-facet").forEach(e=>{var t,a=e.querySelector(".fwp-clear-facet");a&&(t=e.getAttribute("data-name")||"",e=e.getAttribute("data-type")||"",e=!s.has(e)&&t&&c(t),a.style.display=e?"":"none",a.classList.toggle("has-value",!!e),e?a.removeAttribute("tabindex"):a.setAttribute("tabindex","-1"))});var e,t=a(".fwp-reset-all-fields");t&&(e=d(),t.style.display=e?"":"none",t.classList.toggle("has-active-facets",!!e),!e)&&document.activeElement===t&&(e=t.getAttribute("data-focus-target")||"#results-top",t=a(e))&&t.focus()},u=()=>{r('.facetwp-facet[data-type="search"] .facetwp-search').forEach(e=>{"1"!==e.dataset.clearBound&&(e.dataset.clearBound="1",e.addEventListener("input",()=>{i()}))})},f=()=>{r(".fwp-reset-all-fields").forEach(e=>{var t,a;e.hasAttribute("aria-controls")||e.setAttribute("aria-controls","results"),e.querySelector(".btn-label")||(t=(e.textContent||"").trim()||"Clear all filters",e.textContent="",(a=document.createElement("span")).className="btn-label",a.textContent=t,e.appendChild(a))})},p=()=>{r(".fwp-reset-all-fields").forEach(e=>{"1"!==e.dataset.bound&&(e.dataset.bound="1",e.addEventListener("click",()=>{n.lastAction="reset-all",n.lastFocused=document.activeElement,window.FWP&&"function"==typeof window.FWP.reset&&window.FWP.reset()}))}),r(".facetwp-reset").forEach(e=>{"1"!==e.dataset.bound&&(e.dataset.bound="1",e.addEventListener("click",()=>{n.lastAction="reset-all",n.lastFocused=document.activeElement}))})};document.addEventListener("DOMContentLoaded",()=>{l(),f(),p(),u(),i()}),document.addEventListener("facetwp-refresh",()=>{o(!0)}),document.addEventListener("facetwp-loaded",()=>{var e;o(!1),l(),f(),p(),u(),i(),"reset-all"===n.lastAction?(t("All filters cleared. Showing updated results."),e=(e=a(".fwp-reset-all-fields"))&&e.getAttribute("data-focus-target")||"#results-top",(e=a(e)||a("#results"))&&e.focus()):"reset-facet"===n.lastAction&&(t(`${n.lastFacetName||"Filter"} cleared. Showing updated results.`),(e=a(`.facetwp-facet[data-name="${n.lastFacetName||""}"]`))?(a('select, input, button, a, [tabindex="0"]',e)||e).focus():n.lastFocused&&n.lastFocused.focus()),n.lastAction=null,n.lastFacetName=null,n.lastFocused=null})})(),(()=>{let a=e=>!(!window.FWP||!window.FWP.facets||!(e=e.getAttribute("data-name")||""))&&(e=window.FWP.facets[e],Array.isArray(e)||"string"==typeof e?0{var t=e.querySelector("select, .facetwp-dropdown");if(!t)return!1;if(t.multiple){for(let e=0;e{var t=a(e)||r(e);e.classList.toggle("has-value",!!t)},e=()=>{var t=document.querySelectorAll('.facetwp-facet[data-type="dropdown"], .facetwp-facet[data-type="fselect"]');for(let e=0;e{if("1"!==r.dataset.pmBound){r.dataset.pmBound="1";var e=r.querySelector("select, .facetwp-dropdown");e&&(e.addEventListener("focus",()=>{r.classList.add("is-open")}),e.addEventListener("blur",()=>{r.classList.remove("is-open")}),e.addEventListener("change",()=>{s(r)}));let a=r.querySelector(".fs-wrap");a&&(r.classList.toggle("is-open",a.classList.contains("fs-open")),new MutationObserver(t=>{for(let e=0;e{s(r)})),s(r)}})(t[e])};document.addEventListener("DOMContentLoaded",e),document.addEventListener("facetwp-loaded",()=>{e();var t=document.querySelectorAll('.facetwp-facet[data-type="dropdown"], .facetwp-facet[data-type="fselect"]');for(let e=0;e{let r=(e,t,a)=>{e&&e.addEventListener(t,a)},s=(e,t)=>{if(e&&"function"==typeof e.closest)return e.closest(t);let a=e;for(;a&&1===a.nodeType;){if(a.matches(t))return a;a=a.parentElement}return null},n=(e,t,a)=>{if(e.setAttribute("aria-expanded",String(a)),a)t.hidden=!1,t.classList.add("is-open");else{t.classList.remove("is-open");let e=()=>{t.hidden=!0,t.removeEventListener("transitionend",e)};t.addEventListener("transitionend",e),setTimeout(()=>{t.hidden=!0},320)}e=s(t,".people-search-wrap");e&&e.classList.toggle("adv-search-open",!!a)},o=e=>{var t=e.getAttribute("aria-controls");let a=t&&document.getElementById(t);a&&(t=!("true"===e.getAttribute("aria-expanded")),n(e,a,t),t?setTimeout(()=>{var e=a.querySelector('input,select,textarea,button,[tabindex="0"],[contenteditable="true"]');e?e.focus():0<=a.tabIndex&&a.focus()},20):e.focus())},e=t=>{var e,a;t&&"1"!==t.dataset.advBound&&(t.dataset.advBound="1",a=(a=t.getAttribute("aria-controls"))&&document.getElementById(a))&&(e="true"===t.getAttribute("aria-expanded"),a.hidden=!e,a.classList.toggle("is-open",e),(a=s(a,".people-search-wrap"))&&a.classList.toggle("adv-search-open",e),"a"===t.tagName.toLowerCase()&&t.setAttribute("role","button"),r(t,"click",e=>{"a"===t.tagName.toLowerCase()&&e.preventDefault(),o(t)}),r(t,"keydown",e=>{"a"!==t.tagName.toLowerCase()||" "!==e.key&&"Enter"!==e.key||(e.preventDefault(),o(t))}))},t=(document.addEventListener("DOMContentLoaded",()=>{Array.prototype.slice.call(document.querySelectorAll(".adv-search, #adv-search")).forEach(e)}),!1);document.addEventListener("click",function(e){e.target.closest(".facetwp-pager")&&(e.target.closest("a")||e.target.closest("button")||e.target.closest("[data-page]")||e.target.closest(".facetwp-page"))&&(t=!0)},!0),document.addEventListener("facetwp-loaded",function(){var e;window.FWP&&window.FWP.loaded&&t&&(t=!1,document.querySelector(".facetwp-pager"))&&((e=document.querySelector(".careers-filter"))?(e=e.getBoundingClientRect().top+(window.pageYOffset||document.documentElement.scrollTop||0)-200,window.scrollTo({top:Math.max(0,e),behavior:"smooth"})):window.scrollTo({top:0,behavior:"smooth"}))})})();;