PageSourceSearch

https://centgen.ai/js/home-product-demos.js

js centgen.ai collected 2026-09-28 06:14:22 UTC 10,860 bytes, 344 lines download raw bytes

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.