/* embeddedTR — inline icon set (stroke, currentColor) + small helpers */
const { useState, useEffect, useRef } = React;
const Ic = ({ d, size = 22, sw = 1.6, fill = "none", children, ...p }) => (
);
const Icons = {
share: (p) => ,
article: (p) => ,
qa: (p) => ,
learn: (p) => ,
chip: (p) => ,
star: (p) => ,
fork: (p) => ,
arrow: (p) => ,
arrowUp: (p) => ,
check: (p) => ,
search: (p) => ,
menu: (p) => ,
close: (p) => ,
sun: (p) => ,
moon: (p) => ,
terminal:(p) => ,
github: (p) => ,
youtube: (p) => ,
play: (p) => ,
bolt: (p) => ,
book: (p) => ,
users: (p) => ,
};
/* reveal on scroll — scroll/rect based (robust even when IntersectionObserver
doesn't fire in hidden/preview iframes) */
function useReveal() {
const ref = useRef(null);
useEffect(() => {
const el = ref.current; if (!el) return;
const nodes = el.classList.contains("reveal") ? [el] : Array.from(el.querySelectorAll(".reveal"));
const check = () => {
const vh = window.innerHeight || 800;
let pending = false;
nodes.forEach((n) => {
if (n.classList.contains("in")) return;
const r = n.getBoundingClientRect();
if (r.top < vh * 0.94 && r.bottom > 0) n.classList.add("in");
else pending = true;
});
if (!pending) { window.removeEventListener("scroll", check); window.removeEventListener("resize", check); }
};
check();
const t1 = setTimeout(check, 200);
const t2 = setTimeout(check, 700);
window.addEventListener("scroll", check, { passive: true });
window.addEventListener("resize", check);
return () => { window.removeEventListener("scroll", check); window.removeEventListener("resize", check); clearTimeout(t1); clearTimeout(t2); };
}, []);
return ref;
}
/* count-up number — scroll/rect triggered with setTimeout safety */
function Counter({ to, suffix = "", dur = 1400 }) {
const [n, setN] = useState(0);
const ref = useRef(null);
useEffect(() => {
const el = ref.current; if (!el) return;
let raf, safety, started = false;
const run = () => {
if (started) return; started = true;
window.removeEventListener("scroll", check);
const t0 = performance.now();
const tick = (t) => {
const p = Math.min(1, (t - t0) / dur);
const e = 1 - Math.pow(1 - p, 3);
setN(Math.round(to * e));
if (p < 1) raf = requestAnimationFrame(tick);
};
raf = requestAnimationFrame(tick);
safety = setTimeout(() => setN(to), dur + 150); // guarantee final value
};
const check = () => {
const vh = window.innerHeight || 800;
const r = el.getBoundingClientRect();
if (r.top < vh * 0.9 && r.bottom > 0) run();
};
check();
const t1 = setTimeout(check, 300);
window.addEventListener("scroll", check, { passive: true });
return () => { window.removeEventListener("scroll", check); cancelAnimationFrame(raf); clearTimeout(safety); clearTimeout(t1); };
}, [to]);
return {n.toLocaleString("tr-TR")}{suffix};
}
/* animated oscilloscope trace — sine (default) or square ("blink") */
function Waveform({ h = 70, color, shape = "sine" }) {
const ref = useRef(null);
useEffect(() => {
const path = ref.current; if (!path) return;
let raf, ph = 0, reduce = matchMedia("(prefers-reduced-motion: reduce)").matches;
const W = 300;
const mod2 = (v) => ((Math.floor(v) % 2) + 2) % 2;
const draw = () => {
let d = "";
if (shape === "square") {
const period = 58, top = 7, bot = h - 7;
let prev = null;
for (let x = 0; x <= W; x += 1) {
const y = mod2(x / period + ph) === 0 ? top : bot;
if (prev === null) { d = "M" + x + " " + y; }
else if (y !== prev) { d += " L" + x + " " + prev + " L" + x + " " + y; }
else { d += " L" + x + " " + y; }
prev = y;
}
ph += 0.018;
} else {
for (let x = 0; x <= W; x += 4) {
const y = h / 2 + Math.sin(x / 18 + ph) * (h / 2 - 6) * Math.sin(x / 120 + ph / 3);
d += (x === 0 ? "M" : "L") + x + " " + y.toFixed(1) + " ";
}
ph += 0.06;
}
path.setAttribute("d", d);
if (!reduce) raf = requestAnimationFrame(draw);
};
draw();
return () => cancelAnimationFrame(raf);
}, [shape, h]);
return (
);
}
/* ---- Brand mark: vector circuit-tree badge (replaces the raster logo) ---- */
function BrandMark({ size = 40, className = "" }) {
const id = React.useMemo(() => "bm" + Math.random().toString(36).slice(2, 7), []);
return (
);
}
/* full lockup: mark + wordmark + online dot */
function BrandLockup({ size = 38, withDot = true }) {
return (
embeddedTR
{withDot && }
);
}
Object.assign(window, { Icons, useReveal, Counter, Waveform, BrandMark, BrandLockup });