1(function () { 2 const desktopQuery = window.matchMedia("(min-width: 992px)"); 3 const mounted = new WeakSet(); 4 const observed = new WeakSet(); 5 let demoObserver = null; 6 let fiberController = null; 7 8 function demoTheme() { 9 return /^\/ja(?:\/|$)/.test(window.location.pathname) 10 ? "blue-white" 11 : "black-white"; 12 } 13 14 function isVisible(el) { 15 let node = el; 16 17 while (node && node !== document.body) { 18 if (window.getComputedStyle(node).display === "none") return false; 19 node = node.parentElement; 20 } 21 22 return true; 23 } 24 25 function mountDemo(target) { 26 if (mounted.has(target)) return; 27 if (!isVisible(target)) return; 28 29 const type = target.getAttribute("data-home-demo"); 30 const theme = demoTheme(); 31 32 if (type === "autosales" && window.AIAutosalesDemo) { 33 window.AIAutosalesDemo.mount(target, { 34 theme, 35 }); 36 mounted.add(target); 37 } 38 39 if (type === "esearch" && window.AISearchDemo) { 40 window.AISearchDemo.mount(target, { 41 theme, 42 delay: 180, 43 }); 44 mounted.add(target); 45 } 46 } 47 48 function observeDemos() { 49 const targets = document.querySelectorAll("[data-home-demo]"); 50 51 if (!("IntersectionObserver" in window)) { 52 targets.forEach((target) => { 53 const rect = target.getBoundingClientRect(); 54 const isNearViewport = 55 rect.top < window.innerHeight * 0.86 && rect.bottom > window.innerHeight * 0.14; 56 57 if (isNearViewport) mountDemo(target); 58 }); 59 return; 60 } 61 62 if (!demoObserver) { 63 demoObserver = new IntersectionObserver( 64 (entries) => { 65 entries.forEach((entry) => { 66 if (!entry.isIntersecting) return; 67 68 mountDemo(entry.target); 69 70 if (mounted.has(entry.target)) { 71 demoObserver.unobserve(entry.target); 72 } 73 }); 74 }, 75 { 76 threshold: 0.18, 77 rootMargin: "0px 0px -10% 0px", 78 } 79 ); 80 } 81 82 targets.forEach((target) => { 83 if (mounted.has(target) || observed.has(target)) return; 84 85 observed.add(target); 86 demoObserver.observe(target); 87 }); 88 } 89 90 function createFiber() { 91 const existing = document.querySelector(".home-fiber-flow"); 92 if (existing) return existing; 93 94 const fiber = document.createElement("div"); 95 fiber.className = "home-fiber-flow"; 96 fiber.innerHTML = ` 97 <svg aria-hidden="true" focusable="false"> 98 <defs> 99 <linearGradient id="homeFiberCoreGradient" x1="0%" y1="0%" x2="100%" y2="100%"> 100 <stop offset="0%" stop-color="#fff9d8"/> 101 <stop offset="28%" stop-color="#f9d982"/> 102 <stop offset="62%" stop-color="#f5b544"/> 103 <stop offset="100%" stop-color="#b77420"/> 104 </linearGradient> 105 <linearGradient id="homeFiberEnergyGradient" x1="0%" y1="0%" x2="100%" y2="100%"> 106 <stop offset="0%" stop-color="#ffffff" stop-opacity=".92"/> 107 <stop offset="18%" stop-color="#fff7c2"/> 108 <stop offset="52%" stop-color="#ffd86a"/> 109 <stop offset="82%" stop-color="#ffad32"/> 110 <stop offset="100%" stop-color="#fff2b2" stop-opacity=".36"/> 111 </linearGradient> 112 <filter id="homeFiberSoftGlow" x="-36%" y="-36%" width="172%" height="172%"> 113 <feGaussianBlur stdDeviation="3.6" result="blur"/> 114 <feMerge> 115 <feMergeNode in="blur"/> 116 <feMergeNode in="SourceGraphic"/> 117 </feMerge> 118 </filter> 119 </defs> 120 <path class="home-fiber-shadow" data-fiber-path pathLength="1"></path> 121 <path class="home-fiber-rail" data-fiber-path pathLength="1"></path> 122 <path class="home-fiber-core" data-fiber-path pathLength="1"></path> 123 <path class="home-fiber-energy" data-fiber-path pathLength="1"></path> 124 <path class="home-fiber-sheen" data-fiber-path pathLength="1"></path> 125 <g class="home-fiber-glints"> 126 <path class="home-fiber-glint" data-fiber-path pathLength="1"></path> 127 <path class="home-fiber-glint" data-fiber-path pathLength="1"></path> 128 <path class="home-fiber-glint" data-fiber-path pathLength="1"></path> 129 <path class="home-fiber-glint" data-fiber-path pathLength="1"></path> 130 <path class="home-fiber-glint" data-fiber-path pathLength="1"></path> 131 </g> 132 </svg> 133 `; 134 document.body.appendChild(fiber); 135 return fiber; 136 } 137
138 function pointFor(el, anchor) { 139 const rect = el.getBoundingClientRect(); 140 const centerX = rect.left + rect.width * 0.5; 141 142 if (anchor === "bottom") { 143 return { 144 x: centerX, 145 y: rect.bottom - 4, 146 }; 147 } 148 149 return { 150 x: centerX, 151 y: rect.top + 4, 152 }; 153 } 154 155 function clamp(value, min, max) { 156 return Math.max(min, Math.min(max, value)); 157 } 158 159 function easeInOut(value) { 160 return value * value * (3 - 2 * value); 161 } 162 163 function formatPoint(point) { 164 return { 165 x: Math.round(point.x * 10) / 10, 166 y: Math.round(point.y * 10) / 10, 167 }; 168 } 169 170 function fiberPath(start, end) { 171 const dx = end.x - start.x; 172 const dy = end.y - start.y; 173 const direction = dy >= 0 ? 1 : -1; 174 const distance = Math.max(1, Math.hypot(dx, dy)); 175 const verticalPull = clamp(Math.abs(dy) * 0.44, 96, 260) * direction; 176 const horizontalPull = clamp(Math.abs(dx) * 0.08 + distance * 0.025, 24, 88); 177 const side = dx >= 0 ? 1 : -1; 178 179 const c1 = { 180 x: start.x + dx * 0.16 + horizontalPull * side, 181 y: start.y + verticalPull, 182 }; 183 const c2 = { 184 x: end.x - dx * 0.18 - horizontalPull * side * 0.45, 185 y: end.y - verticalPull * 0.82, 186 }; 187 188 return `M ${start.x} ${start.y} C ${c1.x} ${c1.y}, ${c2.x} ${c2.y}, ${end.x} ${end.y}`; 189 } 190 191 function setDashSegment(path, tail, head, overscan) { 192 const start = clamp(tail - (overscan || 0), 0, 1); 193 const end = clamp(head + (overscan || 0) * 0.45, 0, 1); 194 const segment = Math.max(end - start, 0.001); 195 196 path.style.strokeDasharray = `${segment} 1`; 197 path.style.strokeDashoffset = `${-start}`; 198 path.style.opacity = segment > 0.004 ? "" : "0"; 199 } 200 201 function setPointDash(path, position, size, opacity) { 202 path.style.strokeDasharray = `${Math.max(size, 0.001)} 1`; 203 path.style.strokeDashoffset = `${-clamp(position, 0, 1)}`; 204 path.style.opacity = opacity; 205 } 206 207 function setupFiber() { 208 if (fiberController) { 209 fiberController.schedule(); 210 return; 211 } 212 213 const source = document.querySelector( 214 ".wrapper-desktop .home-demo-slot-autosales" 215 ); 216 const target = document.querySelector( 217 ".wrapper-desktop .home-demo-slot-esearch" 218 ); 219 220 if (!source || !target) return; 221 222 const fiber = createFiber(); 223 const allPaths = Array.from(fiber.querySelectorAll("[data-fiber-path]")); 224 const shadow = fiber.querySelector(".home-fiber-shadow"); 225 const rail = fiber.querySelector(".home-fiber-rail"); 226 const core = fiber.querySelector(".home-fiber-core"); 227 const energy = fiber.querySelector(".home-fiber-energy"); 228 const sheen = fiber.querySelector(".home-fiber-sheen"); 229 const glints = Array.from(fiber.querySelectorAll(".home-fiber-glint")); 230 231 let rafId = 0; 232 let lastPath = ""; 233 234 function renderFiber() { 235 rafId = 0; 236 237 if (!desktopQuery.matches || !isVisible(source) || !isVisible(target)) { 238 fiber.classList.remove("is-visible", "is-touching"); 239 return; 240 } 241 242 const viewportHeight = window.innerHeight || document.documentElement.clientHeight; 243 const viewportWidth = window.innerWidth || document.documentElement.clientWidth; 244 const start = formatPoint(pointFor(source, "bottom")); 245 const end = formatPoint(pointFor(target, "top")); 246 const path = fiberPath(start, end); 247 248 if (path !== lastPath) { 249 allPaths.forEach((item) => item.setAttribute("d", path)); 250 lastPath = path; 251 } 252 253 const startInside = 254 start.x > -80 && 255 start.x < viewportWidth + 80 && 256 start.y > 8 && 257 start.y < viewportHeight - 8; 258 const endInside = 259 end.x > -80 && 260 end.x < viewportWidth + 80 && 261 end.y > 8 && 262 end.y < viewportHeight - 8; 263 const hasRoom = end.y - start.y > 42; 264 265 const rawProgress = clamp( 266 (viewportHeight * 0.92 - end.y) / (viewportHeight * 0.46), 267 0, 268 1 269 ); 270 const progress = easeInOut(rawProgress); 271 const touchPoint = 0.78; 272 const head = clamp(progress / touchPoint, 0, 1); 273 const tail = progress <= touchPoint 274 ? 0 275 : clamp((progress - touchPoint) / (1 - touchPoint), 0, 1); 276 const segment = Math.max(head - tail, 0); 277 const visible = 278 startInside && endInside && hasRoom && segment > 0.008 && rawProgress > 0.002; 279 280 fiber.classList.toggle("is-visible", visible); 281 fiber.classList.toggle("is-touching", visible && head >= 0.998 && tail > 0.01); 282 283 if (!visible) { 284 allPaths.forEach((item) => { 285 item.style.opacity = "0"; 286 }); 287 return; 288 } 289 290 setDashSegment(shadow, tail, head, 0.014); 291 setDashSegment(rail, tail, head, 0.008); 292 setDashSegment(core, tail, head, 0); 293 294 const energyStart = Math.max(tail, head - Math.min(0.18, Math.max(segment * 0.42, 0.055))); 295 setDashSegment(energy, energyStart, head, 0.002); 296 297 const sheenStart = Math.max(tail, head - Math.min(0.075, Math.max(segment * 0.25, 0.025))); 298 setDashSegment(sheen, sheenStart, head, 0); 299 300 const glintSize = clamp(segment * 0.06, 0.008, 0.024);
301 glints.forEach((glint, index) => { 302 const lane = (index + 1) / (glints.length + 1); 303 const drift = (rawProgress * 1.65 + index * 0.19) % 1; 304 const position = tail + segment * ((lane * 0.72 + drift * 0.28) % 1); 305 const opacity = segment > 0.08 ? `${0.28 + (index % 3) * 0.16}` : "0"; 306 setPointDash(glint, position, glintSize, opacity); 307 }); 308 } 309 310 function schedule() { 311 if (rafId) return; 312 rafId = window.requestAnimationFrame(renderFiber); 313 } 314 315 fiberController = { schedule }; 316 317 renderFiber(); 318 window.addEventListener("scroll", schedule, { passive: true }); 319 window.addEventListener("resize", schedule); 320 321 if (desktopQuery.addEventListener) { 322 desktopQuery.addEventListener("change", schedule); 323 } else if (desktopQuery.addListener) { 324 desktopQuery.addListener(schedule); 325 } 326 } 327 328 function init() { 329 observeDemos(); 330 // setupFiber(); 331 332 window.addEventListener("resize", () => { 333 observeDemos(); 334 // setupFiber(); 335 }); 336 window.addEventListener("scroll", observeDemos, { passive: true }); 337 } 338 339 if (document.readyState === "loading") { 340 document.addEventListener("DOMContentLoaded", init); 341 } else { 342 init(); 343 } 344})();
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.