1/* A Bridge to the Throne â Black Friday band (enhancement layer). 2 Inserts one section on the homepage after the Rhythm of Revenue book 3 band. Rules honoured, each learned the hard way on this ecosystem: 4 never reuse builder class names (find the anchor by its text), insert 5 only after hydration settles, and if the framework drops the node on a 6 re-render, put it back rather than assume it stays. */ 7(function () { 8 "use strict"; 9 10 // The Bridge to the Throne site. Swap this one line when the custom 11 // domain is acquired, re-hash the ?v= in index.html, re-zip. 12 var BTT_URL = "https://abridgetothethrone.com"; 13 14 var path = location.pathname.replace(/\/+$/, "") || "/"; 15 if (path !== "/" && !/\/index(\.html)?$/.test(path)) return; 16 17 var BAND_ID = "gtbtt-band"; 18 var attempts = 0; 19 20 function ownText(el) { 21 var t = ""; 22 for (var i = 0; i < el.childNodes.length; i++) { 23 if (el.childNodes[i].nodeType === 3) t += el.childNodes[i].textContent; 24 } 25 return t; 26 } 27 28 function findAnchor() { 29 // The ROR purple band: the ancestor of its copy whose parent is the 30 // page's section list (13 children on this page). Structural, no 31 // geometry, so viewport width cannot break it. 32 var probe = null; 33 var ps = document.querySelectorAll("p"); 34 for (var i = 0; i < ps.length; i++) { 35 if (/turned survival into strategy/.test(ps[i].textContent || "")) { probe = ps[i]; break; } 36 } 37 if (!probe) return null; 38 var el = probe; 39 while (el && el !== document.body) { 40 var pr = el.parentElement; 41 if (pr && pr.children.length >= 8) { 42 // confirm this really is the section list: testimonials lives here too 43 for (var k = 0; k < pr.children.length; k++) { 44 if (pr.children[k] !== el && /WHAT LEADERS AND COLLABORATORS SAY/i.test(pr.children[k].innerText || "")) { 45 return { host: el, parent: pr }; 46 } 47 } 48 } 49 el = pr; 50 } 51 return null; 52 } 53 54 function buildBand() { 55 var section = document.createElement("section"); 56 section.id = BAND_ID; 57 section.className = "gtbtt"; 58 section.innerHTML = 59 '<div class="gtbtt__inner">' + 60 '<div class="gtbtt__copy">' + 61 '<p class="gtbtt__eyebrow">The New Book · A Bridge to the Throne</p>' + 62 '<h3 class="gtbtt__headline gtbtt__headline--announce">Coming Soon on Black Friday.</h3>' + 63 '<p class="gtbtt__date">November 27, 2026</p>' + 64 '<p class="gtbtt__pullline">You have been crossing the bridge your entire life.</p>' + 65 '<p class="gtbtt__body">How to cross from purpose to legacy. A transformational journey through healing, discipline, character, courage, financial wisdom, service, and consciousness, built one decision at a time.</p>' + 66 '<form class="gtbtt__form" method="post" action="/api/notify" novalidate>' + 67 '<input class="gtbtt__email" type="email" name="email" placeholder="Your email" required autocomplete="email" aria-label="Your email">' + 68 '<input type="text" name="company" tabindex="-1" autocomplete="off" aria-hidden="true" style="position:absolute;left:-9999px;width:1px;height:1px;opacity:0">' + 69 '<button class="gtbtt__btn" type="submit">Notify Me First</button>' + 70 "</form>" + 71 '<p class="gtbtt__note">Release list only. One email when the book goes live.</p>' + 72 '<a class="gtbtt__link" href="' + BTT_URL + '" target="_blank" rel="noopener">Visit the Book Site â</a>' + 73 "</div>" + 74 '<div class="gtbtt__coverwrap">' + 75 '<a href="' + BTT_URL + '" target="_blank" rel="noopener" aria-label="Visit the A Bridge to the Throne site">' + 76 '<img class="gtbtt__cover" src="/assets/enhance/btt-cover.jpg" alt="A Bridge to the Throne by Dr. Glenn Toby, book cover" loading="lazy">' + 77 "</a>" + 78 "</div>" + 79 "</div>"; 80 81 // staggered entrance on the house grid (625ms beat, quarter offsets) 82 var stagger = 0; 83 [].slice.call(section.querySelectorAll(".gtbtt__eyebrow, .gtbtt__headline, .gtbtt__date, .gtbtt__pullline, .gtbtt__body, .gtbtt__form, .gtbtt__note, .gtbtt__link, .gtbtt__coverwrap")).forEac
83h(function (el) { 84 el.setAttribute("data-gtrv", ""); 85 el.style.transitionDelay = (stagger * 0.08).toFixed(2) + "s"; 86 stagger++; 87 }); 88 89 var form = section.querySelector("form"); 90 form.addEventListener("submit", function (ev) { 91 ev.preventDefault(); 92 var btn = form.querySelector("button"); 93 var msg = section.querySelector(".gtbtt__msg"); 94 if (!msg) { 95 msg = document.createElement("p"); 96 msg.className = "gtbtt__msg"; 97 form.insertAdjacentElement("afterend", msg); 98 } 99 msg.textContent = ""; 100 msg.className = "gtbtt__msg"; 101 var email = (form.elements.email.value || "").trim(); 102 if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { 103 msg.textContent = "Enter a valid email address."; 104 msg.className = "gtbtt__msg gtbtt__msg--err"; 105 return; 106 } 107 var original = btn.textContent; 108 btn.textContent = "Sendingâ¦"; 109 btn.disabled = true; 110 fetch("/api/notify", { 111 method: "POST", 112 headers: { "Content-Type": "application/json" }, 113 body: JSON.stringify({ email: email, company: form.elements.company.value || "" }) 114 }).then(function (res) { 115 return res.json().catch(function () { return { ok: false }; }).then(function (body) { 116 if (res.ok && body.ok) { 117 btn.textContent = "You are on the list."; 118 form.elements.email.value = ""; 119 setTimeout(function () { btn.textContent = original; btn.disabled = false; }, 6000); 120 } else { throw new Error("failed"); } 121 }); 122 }).catch(function () { 123 btn.textContent = original; 124 btn.disabled = false; 125 msg.textContent = "Could not send right now. Please try again shortly."; 126 msg.className = "gtbtt__msg gtbtt__msg--err"; 127 }); 128 }); 129 return section; 130 } 131 132 var band = null; 133 134 function bandPlacedRight() { 135 var b = document.getElementById(BAND_ID); 136 if (!b || !b.previousElementSibling) return false; 137 return /FROM BROOKLYN TO THE BOARDROOM/i.test( 138 (b.previousElementSibling.innerText || "").slice(0, 800)); 139 } 140 141 function ensureInserted() { 142 if (bandPlacedRight()) return true; 143 var anchor = findAnchor(); 144 if (!anchor) return false; 145 if (!band) band = buildBand(); 146 // insertAdjacentElement re-homes the node if it landed somewhere wrong 147 anchor.host.insertAdjacentElement("afterend", band); 148 return bandPlacedRight(); 149 } 150 151 function fallbackInsert() { 152 if (document.getElementById(BAND_ID)) return true; 153 var els = document.querySelectorAll("p, h2, h3, div"); 154 for (var i = 0; i < els.length; i++) { 155 if (/WHAT LEADERS AND COLLABORATORS SAY/i.test(els[i].innerText || "")) { 156 var el = els[i]; 157 while (el && el !== document.body) { 158 var pr = el.parentElement; 159 if (pr && pr.children.length >= 8) { 160 if (!band) band = buildBand(); 161 el.insertAdjacentElement("beforebegin", band); 162 return true; 163 } 164 el = pr; 165 } 166 } 167 } 168 return false; 169 } 170 171 function start() { 172 if (ensureInserted()) { 173 armReveals(); 174 armProgress(); 175 repairGalleryLinks(); 176 watch(); 177 return; 178 } 179 attempts++; 180 if (attempts < 30) { setTimeout(start, 400); return; } // hydration can be slow; keep probing 181 // primary anchor never resolved: presence beats perfection 182 if (fallbackInsert()) { 183 armReveals(); 184 armProgress(); 185 repairGalleryLinks(); 186 watch(); 187 } 188 } 189 190 var reduceMotion = false; 191 try { reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; } catch (e) {} 192 193 function armReveals() { 194 // fail-open: nothing is ever hidden unless the observer is live and the 195 // element is safely below the viewport; a missed callback can only mean 196 // "no animation", never "invisible content" 197 var els = [].slice.call(document.querySelectorAll("[data-gtrv]")); 198 if (!els.length) return; 199 if (reduceMotion || !("IntersectionObserver" in window)) return; 200 var io = new IntersectionObserver(function (entries) {
201 entries.forEach(function (entry) { 202 if (entry.isIntersecting) { 203 entry.target.classList.remove("gtrv-pre"); 204 entry.target.classList.add("gtrv-in"); 205 io.unobserve(entry.target); 206 } 207 }); 208 }, { threshold: 0.2 }); 209 els.forEach(function (el) { 210 var r = el.getBoundingClientRect(); 211 if (r.top > window.innerHeight * 1.05) { 212 el.classList.add("gtrv-pre"); 213 io.observe(el); 214 } 215 }); 216 // safety net: whatever is still pre-hidden after 8s becomes visible 217 setTimeout(function () { 218 els.forEach(function (el) { el.classList.remove("gtrv-pre"); el.classList.add("gtrv-in"); }); 219 }, 8000); 220 } 221 222 function armProgress() { 223 if (document.getElementById("gtbtt-progress")) return; 224 var bar = document.createElement("div"); 225 bar.id = "gtbtt-progress"; 226 bar.setAttribute("aria-hidden", "true"); 227 document.body.appendChild(bar); 228 var ticking = false; 229 function frame() { 230 ticking = false; 231 var doc = document.documentElement; 232 var max = (doc.scrollHeight - window.innerHeight) || 1; 233 var f = Math.min(1, Math.max(0, (window.scrollY || doc.scrollTop) / max)); 234 bar.style.transform = "scaleX(" + f.toFixed(4) + ")"; 235 } 236 window.addEventListener("scroll", function () { 237 if (!ticking) { ticking = true; requestAnimationFrame(frame); } 238 }, { passive: true }); 239 window.addEventListener("resize", frame); 240 frame(); 241 } 242 243 // --- gallery-door repair --------------------------------------------- 244 // The Arrangement's ART-room card (and three other spots) still point at 245 // the interim Adobe Express page. The King's Exhibition now lives at its 246 // own domain, so those anchors are repointed at runtime. Attribute-only 247 // mutation; the observer re-applies it if a re-render restores the old 248 // href. 249 var OLD_KE = "new.express.adobe.com"; 250 var NEW_KE = "https://thekingsexhibition.com"; 251 function repairGalleryLinks() { 252 var as = document.querySelectorAll('a[href*="' + OLD_KE + '"]'); 253 for (var i = 0; i < as.length; i++) as[i].setAttribute("href", NEW_KE); 254 return as.length; 255 } 256 257 function watch() { 258 // If a framework re-render drops the band, re-insert. Union semantics: 259 // never remove on our own. 260 var queued = false; 261 var mo = new MutationObserver(function () { 262 if (queued) return; 263 queued = true; 264 setTimeout(function () { 265 queued = false; 266 if (!bandPlacedRight()) ensureInserted(); 267 repairGalleryLinks(); 268 }, 250); 269 }); 270 mo.observe(document.body, { childList: true, subtree: true }); 271 } 272 273 if (document.readyState === "loading") { 274 document.addEventListener("DOMContentLoaded", function () { setTimeout(start, 250); }); 275 } else { 276 setTimeout(start, 250); 277 } 278})();
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.