1window.addEventListener("load", () => { 2 function showModal(type = 'enterprise', deviceType) { 3 const headings = { 4 enterprise: 'Enterprise-wide personalized A.I. mastery, at scale, customized for your organization.', 5 schools: "Personalized A.I. mastery for every student, customized for your school's priorities and values.", 6 communities: "Weave critical A.I. literacy into your community's culture and daily life." 7 }; 8 const blurbs = { 9 enterprise: '', 10 schools: "Launched December 2025. Set your school's priorities and values to adjust the insights and monitoring, create dedicated discussions and leaderboards, gain insights, and more. For schools that want to graduate A.I.-native students who not only know how to navigate the top tools, but know how to think far more critically and strategically about them too.", 11 communities: "Deploy AI literacy where your residents already are â in libraries, transit hubs, schools, and public spaces. Custom-branded for your city, with locally-themed challenges, leaderboards, and employer-recognized credentials that make learning visible and valuable." 12 }; 13 const heading = headings[type] || headings.enterprise; 14 const blurb = blurbs[type] || blurbs.enterprise; 15 const content = ` 16 <button class="util-close-modal x-btn"><span class="material-icons-round">close</span></button> 17 <div class="content"> 18 ${type !== 'earlyAccess' ? `<h2>${heading}</h2> 19 <p class="first">${blurb}</p> 20 <p>Get in touch to learn more, gain priority access, or discuss pricing.</p>` : `<p class="appText">Launched December 2025. Want early access?</p>`} 21 <div class="inputs-errors-ct"> 22 <select name="offering" class="ent-modal-select"> 23 <option value="" disabled selected>Which offering are you most interested in?</option> 24 ${type === 'schools' ? ` 25 <option value="ai-literacy-app">Critical AI Literacy App</option> 26 <option value="showyourlearning">ShowYourLearning (AI Cheating Solution)</option> 27 <option value="local-challenges">Local Challenges</option> 28 <option value="cognitive-defence">Cognitive Defence Features</option> 29 <option value="pd-sessions">Professional Development Sessions</option> 30 ` : type === 'communities' ? ` 31 <option value="local-challenge-deployment">Local Challenge Deployment</option> 32 <option value="custom-city-portal">Custom-Branded City Portal</option> 33 <option value="school-integration">School & Campus Integration</option> 34 <option value="community-ai-literacy">Community AI Literacy Program</option> 35 ` : ` 36 <option value="business-upgrade">Business Upgrade for AI</option> 37 <option value="it-stack-upgrade">IT Stack & Practices Upgrade for AI</option> 38 <option value="cybersecurity-upgrade">Cybersecurity Upgrade for AI</option> 39 <option value="ai-upskilling">AI Upskilling</option> 40 `} 41 </select> 42 <div class="inputs-ct"> 43 <input type="text" placeholder="Full name" name="name" /> 44 <input type="text" placeholder="LinkedIn URL" name="linked" /> 45 <input type="text" placeholder="[email protected]" name="emailContact" /> 46 <button type="button" class="util-small-btn submit-enterprise"><span class="material-icons-round">send</span></button> 47 </div> 48 </div> 49 </div> 50 `; 51 const { modalObject, modalContainer, modalMain } = util.insertModal(null, { 52 id: "ttaiEnterprise", 53 canClose: true, 54 withCloseBtn: false, 55 removeOnClose: true, 56 content, 57 }); 58 modalContainer.classList.add(type); 59 modalObject.show(); 60 61 const grecaptchaSiteKey = "6LcOWUsrAAAAALO0BJFuIj0nrxBe-trq9QPaPSCV"; 62 function executeRecaptcha(action) { 63 return new Promise((resolve, reject) => { 64 if (!window.grecaptcha || typeof window.grecaptcha.execute !== "function") { 65 return reject(new Error("reCAPTCHA not loaded yet.")); 66 } 67 try { 68 grecaptcha.ready(() => { 69 grecaptcha 70 .execute(grecaptchaSiteKey, { action }) 71 .then((token) => { 72 if (!token) { 73 return reject(new Error("reCAPTCHA token is empty.")); 74 } 75 resolve(token); 76 }) 77 .catch((err) => reject(err)); 78 }); 79 } catch (err) { 80 reject(err); 81 } 82 }); 83 } 84 85 const submitBtn = document.querySelector('#ttaiEnterprise .submit-enterprise'); 86 if(submitBtn) { 87 submitBtn.addEventListener('click', submitEnterprise) 88 } 89 function submitEnterprise() { 90 const fields = { 91 firstLast: document.querySelector('#ttaiEnterprise input[name="name"]'), 92 linked: document.querySelector('#ttaiEnterprise input[name="linked"]'), 93 emailContact: document.querySelector('#ttaiEnterprise input[name="emailContact"]'), 94 offering: document.querySelector('#ttaiEnterprise .ent-modal-select'), 95 } 96 97 const params = { 98 name: fields.firstLast ? fields.firstLast.value : '', 99 linkedInURL: fields.linked ? fields.linked.value : '', 100 emailContact: fields.emailContact ? fields.emailContact.value : '', 101 offering: fields.offering ? fields.offering.value : '', 102 type, 103 device: deviceType ? deviceType : '' 104 }; 105 106 let formCt = document.querySelector('#ttaiEnterprise .inputs-errors-ct'); 107 if(formCt) { 108 util.removeErrors(formCt); 109 } 110 submitBtn.disabled = true; 111 submitBtn.opacity = '0.5'; 112 submitBtn.insertAdjacentHTML('afterBegin', `<div class="util-spinner-ct"> 113 <div class="util-spinner " style="--spinner-color: 0, 0%, 0%" aria-hidden="true"></div> 114 <p class="util-sr-only">Loading...</p> 115 </div>`); 116 submitBtn.classList.add('loading'); 117 executeRecaptcha("contact") 118 .then((token) => { 119 params["g-recaptcha-response"] = token; 120 util.request({ 121 url: "/contact/ttaiLandingRequest.json", 122 method: "POST", 123 params, 124 success: function (response) { 125 const spinner = submitBtn.querySelector('.util-spinner-ct'); 126 spinner.remove(); 127 submitBtn.opacity = 1; 128 submitBtn.disabled = false;
129 submitBtn.classList.remove('loading'); 130 131 if(response.formErrors && Object.keys(response.formErrors) && Object.keys(response.formErrors).length) { 132 if(formCt) { 133 util.showErrors(response.formErrors, formCt, true, true); 134 } 135 } else { 136 const contentEl = modalMain.querySelector('.content'); 137 if(contentEl) { 138 contentEl.classList.add('thanks'); 139 contentEl.innerHTML = ` 140 <h2>Thanks for your interest!</h2> 141 <p>We'll be in touch soon.</p> 142 `; 143 }; 144 } 145 } 146 }); 147 }) 148 .catch((err) => { 149 const spinner = submitBtn.querySelector('.util-spinner-ct'); 150 if (spinner) { 151 spinner.remove(); 152 } 153 submitBtn.opacity = 1; 154 submitBtn.disabled = false; 155 submitBtn.classList.remove('loading'); 156 let errorMessage = "Oops.. something went wrong!"; 157 if (err.message && err.message.includes("reCAPTCHA")) { 158 errorMessage = "reCAPTCHA validation failed. Please try again."; 159 } 160 if(formCt) { 161 util.showErrors({ name: errorMessage }, formCt, true, true); 162 } 163 }); 164 } 165 } 166 167 const openBtns = document.querySelectorAll('.open-contact-modal'); 168 openBtns.forEach(btn => { 169 btn.addEventListener('click', () => showModal(btn.dataset ? btn.dataset.type : '', btn.dataset ? btn.dataset.device : '')); 170 }); 171 172 // FAQ Accordion 173 document.querySelectorAll('.ent-faq-trigger').forEach(trigger => { 174 trigger.addEventListener('click', () => { 175 const item = trigger.closest('.ent-faq-item'); 176 const isActive = item.classList.contains('active'); 177 document.querySelectorAll('.ent-faq-item.active').forEach(i => i.classList.remove('active')); 178 if (!isActive) item.classList.add('active'); 179 }); 180 }); 181 182 // Toggle buttons scroll to their respective section 183 function scrollToPanel(panelId) { 184 document.querySelectorAll('.ent-sticky-toggle-btn').forEach(btn => { 185 btn.classList.toggle('active', btn.dataset.panel === panelId); 186 }); 187 const target = document.getElementById('panel-' + panelId); 188 if (target) { 189 var offset = 0; 190 var nav = document.querySelector('.ent-nav'); 191 var sticky = document.getElementById('entStickyToggle'); 192 if (nav) offset += nav.offsetHeight; 193 if (sticky) offset += sticky.offsetHeight; 194 var top = target.getBoundingClientRect().top + window.pageYOffset - offset - 16; 195 window.scrollTo({ top: top, behavior: 'smooth' }); 196 } 197 } 198 199 document.querySelectorAll('.ent-sticky-toggle-btn').forEach(btn => { 200 btn.addEventListener('click', () => scrollToPanel(btn.dataset.panel)); 201 }); 202 203 // Hero CTA scroll buttons (AI Transformation / AI Upskilling) 204 document.querySelectorAll('.ent-toggle-scroll-btn').forEach(btn => { 205 btn.addEventListener('click', () => { 206 const panelId = btn.dataset.target; 207 scrollToPanel(panelId); 208 }); 209 }); 210 211 // Top nav audience toggle 212 document.querySelectorAll('.ent-nav-toggle-btn').forEach(btn => { 213 btn.addEventListener('click', () => { 214 document.querySelectorAll('.ent-nav-toggle-btn').forEach(b => b.classList.remove('active')); 215 btn.classList.add('active'); 216 }); 217 }); 218 219 // Mobile burger menu toggle 220 var mobileBurger = document.getElementById('entMobileBurger'); 221 var mobileMenu = document.getElementById('entMobileMenu'); 222 if (mobileBurger && mobileMenu) { 223 mobileBurger.addEventListener('click', function() { 224 mobileBurger.classList.toggle('open'); 225 mobileMenu.classList.toggle('open'); 226 }); 227 document.addEventListener('click', function(e) { 228 if (!mobileBurger.contains(e.target) && !mobileMenu.contains(e.target)) { 229 mobileBurger.classList.remove('open'); 230 mobileMenu.classList.remove('open'); 231 } 232 }); 233 } 234 235 // Communities page â pin sticky toggle when scrolled past its static position 236 if (document.querySelector('.com-page')) { 237 const stickyEl = document.getElementById('entStickyToggle'); 238 if (stickyEl) { 239 const sentinel = document.createElement('div'); 240 sentinel.style.height = '1px'; 241 stickyEl.parentNode.insertBefore(sentinel, stickyEl); 242 const observer = new IntersectionObserver(function(entries) { 243 // Only pin when sentinel scrolls above the viewport (going down) 244 stickyEl.classList.toggle('is-pinned', entries[0].boundingClientRect.top < 0); 245 }, { threshold: 0 }); 246 observer.observe(sentinel); 247 } 248 } 249 250 // Schools page â pin hero CTAs when scrolled past their static position 251 if (document.querySelector('.sch-page:not(.com-page)')) { 252 const heroCtas = document.querySelector('.sch-page .ent-hero-ctas'); 253 if (heroCtas) { 254 const sentinel = document.createElement('div'); 255 heroCtas.parentNode.insertBefore(sentinel, heroCtas); 256 const observer = new IntersectionObserver(function(entries) { 257 heroCtas.classList.toggle('is-pinned', !entries[0].isIntersecting); 258 }, { threshold: 0 }); 259 observer.observe(sentinel); 260 } 261 } 262 263 // App mockup carousel â fade left out, fade right in 264 const slides = document.querySelectorAll('.ent-app-slide'); 265 if (slides.length > 1) {
266 let current = 0; 267 setInterval(() => { 268 const prev = current; 269 current = (current + 1) % slides.length; 270 slides[prev].classList.add('leaving'); 271 slides[prev].classList.remove('active'); 272 slides[current].classList.add('active'); 273 setTimeout(() => slides[prev].classList.remove('leaving'), 600); 274 }, 3000); 275 } 276});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.