// Data Mirai — Landing page const { useState, useEffect, useRef, useMemo, useCallback } = React; // ─── Scroll Reveal ────────────────────────────────────────────────────────── function useReveal(deps) { useEffect(() => { const els = document.querySelectorAll('.reveal:not(.in)'); if (!els.length) return; const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add('in'); observer.unobserve(entry.target); } }); }, { threshold: 0.1, rootMargin: '0px 0px -60px 0px' }); els.forEach((el) => observer.observe(el)); return () => observer.disconnect(); }, deps); } // ─── Typed Pitch ──────────────────────────────────────────────────────────── function TypedPitch({ pre, strong, post, end }) { const [typed, setTyped] = useState(0); useEffect(() => { if (typed < strong.length) { const t = setTimeout(() => setTyped(typed + 1), 40 + Math.random() * 30); return () => clearTimeout(t); } }, [typed, strong]); const done = typed >= strong.length; return (

{pre}{' '} {strong.slice(0, typed)}{!done && } {post}{end}

); } // ─── Hero Orbit ───────────────────────────────────────────────────────────── function OrbitChip({ x, y, kind, children, big, small, agent }) { const left = (x / 560) * 100; const top = (y / 560) * 100; const palette = { core: { c: '#fff', bg: 'linear-gradient(135deg, rgba(234,88,12,0.25), rgba(147,51,234,0.35))', border: 'rgba(255,255,255,0.18)' }, trigger: { c: 'var(--c-trigger)', bg: 'rgba(22,163,74,0.12)', border: 'rgba(22,163,74,0.35)' }, logic: { c: 'var(--c-logic)', bg: 'rgba(37,99,235,0.12)', border: 'rgba(37,99,235,0.35)' }, ai: { c: 'var(--c-ai)', bg: 'rgba(147,51,234,0.12)', border: 'rgba(147,51,234,0.35)' }, data: { c: 'var(--c-data)', bg: 'rgba(234,88,12,0.12)', border: 'rgba(234,88,12,0.35)' }, agent: { c: 'var(--c-agent)', bg: 'rgba(245,158,11,0.12)', border: 'rgba(245,158,11,0.35)' }, output: { c: 'var(--c-output)', bg: 'rgba(236,72,153,0.12)', border: 'rgba(236,72,153,0.35)' }, }; const p = palette[kind] || palette.core; const style = { position: 'absolute', left: `${left}%`, top: `${top}%`, transform: 'translate(-50%, -50%)', background: p.bg, color: p.c, border: `1px solid ${p.border}`, backdropFilter: 'blur(14px)', borderRadius: big ? '14px' : '10px', padding: big ? '14px 18px' : (small ? '5px 9px' : '7px 11px'), fontFamily: 'var(--font-mono)', fontSize: big ? '12px' : (small ? '10px' : '11px'), letterSpacing: '0.04em', whiteSpace: 'nowrap', boxShadow: big ? '0 20px 60px -20px rgba(147, 51, 234, 0.6), 0 0 0 4px rgba(167,139,250,0.05)' : `0 0 20px ${p.c}33, 0 0 0 1px ${p.border}`, zIndex: big ? 5 : (agent ? 4 : 3), minWidth: big ? '120px' : 'auto', textAlign: big ? 'center' : 'left', lineHeight: big ? '1.2' : '1.3', }; return (
{kind !== 'core' && ( )} {children}
); } function HeroOrbit({ t }) { const wrapRef = useRef(null); const [time, setTime] = useState(0); useEffect(() => { let raf, start = performance.now(); const loop = (now) => { setTime((now - start) / 1000); raf = requestAnimationFrame(loop); }; raf = requestAnimationFrame(loop); return () => cancelAnimationFrame(raf); }, []); const S = 560, cx = S / 2, cy = S / 2; const agentR = 140, planetR = 215; // Deterministic star field (like tucania-engine) const stars = useMemo(() => Array.from({ length: 110 }, (_, i) => ({ x: (i * 137.5 + 23) % S, y: (i * 89.7 + 17) % S, r: 0.3 + (i % 5) * 0.25, op: 0.08 + (i % 7) * 0.05, })), []); const COLORS = { agent: '#f59e0b', output: '#ec4899', logic: '#2563eb', ai: '#9333ea', data: '#ea580c', trigger: '#16a34a' }; const agentDefs = [ { name: t.orbit.n1, kind: 'agent', color: COLORS.agent }, { name: t.orbit.n2, kind: 'output', color: COLORS.output }, { name: t.orbit.n3, kind: 'logic', color: COLORS.logic }, { name: t.orbit.n4, kind: 'ai', color: COLORS.ai }, ]; const planetDefs = [ { name: t.orbit.p1, kind: 'data', color: COLORS.data }, { name: t.orbit.p2, kind: 'trigger', color: COLORS.trigger }, { name: t.orbit.p3, kind: 'data', color: COLORS.data }, { name: t.orbit.p4, kind: 'output', color: COLORS.output }, ]; const agents = agentDefs.map((a, i) => { const angle = (Math.PI * 2 * i) / 4 + Math.PI * 0.25 + time * 0.06; return { ...a, x: cx + Math.cos(angle) * agentR, y: cy + Math.sin(angle) * agentR }; }); const planets = planetDefs.map((p, i) => { const angle = (Math.PI * 2 * i) / 4 + time * 0.035; return { ...p, x: cx + Math.cos(angle) * planetR, y: cy + Math.sin(angle) * planetR }; }); return (
{/* Nebula glow */}
{/* Star field */} {stars.map((s, i) => )} {/* Twinkling stars */} {[0, 15, 33, 52, 71, 88].map((idx) => { const s = stars[idx]; return ; })} {/* Orbit rings */} {/* Agent ↔ center dashed lines */} {agents.map((a, i) => ( ))} {/* Agent ↔ planet bezier curves */} {agents.map((a, ai) => { const p = planets[ai % planets.length]; const mx = (a.x + p.x) / 2 + (cx - (a.x + p.x) / 2) * 0.4; const my = (a.y + p.y) / 2 + (cy - (a.y + p.y) / 2) * 0.4; return ; })} {/* Traveling pulses — agent to center */} {agents.map((a, i) => { const f = ((time * 0.45) + i * 0.25) % 1; const px = cx + (a.x - cx) * f, py = cy + (a.y - cy) * f; return ( ); })} {/* Traveling dots — agent to planet bezier */} {agents.map((a, ai) => { const p = planets[ai % planets.length]; const f = ((time * 0.3) + ai * 0.4) % 1; const mx = (a.x + p.x) / 2 + (cx - (a.x + p.x) / 2) * 0.4; const my = (a.y + p.y) / 2 + (cy - (a.y + p.y) / 2) * 0.4; const t1 = 1 - f; const bx = t1*t1*a.x + 2*t1*f*mx + f*f*p.x; const by = t1*t1*a.y + 2*t1*f*my + f*f*p.y; return ; })} {/* Core — glow + body + pulse ring */} {(() => { const pr = 48 + Math.sin(time * 1.6) * 10; const po = 0.15 * Math.max(0, Math.cos(time * 1.6)); return ; })()} {/* Agent glow halos + pulse rings */} {agents.map((a, i) => { const pr = 20 + Math.sin(time * 2.5 + i * 1.5) * 9; const po = 0.35 * Math.max(0, Math.cos(time * 2.5 + i * 1.5)); return ( ); })} {/* Planet glow halos */} {planets.map((p, i) => ( ))} {/* HTML glass chips */}
{t.orbit.core.split('\n').map((s,i) =>
{s}
)}
{agents.map((a) => {a.name})} {planets.map((p) => {p.name})}
); } // ─── Graph Demo ───────────────────────────────────────────────────────────── function kindColor(k) { return { trigger: '#16a34a', logic: '#2563eb', ai: '#9333ea', data: '#ea580c', agent: '#f59e0b', output: '#ec4899', }[k] || '#a78bfa'; } function getLogMessage(node) { const msgs = { trigger: 'lead received · acme.co · n=1', data: 'enriched 1 contact · 42 fields · 230ms', logic: 'icp_score=83 · qualified=true', ai: 'generated email · 142 tokens · $0.0008', agent: 'astronaut Sales picked up · tools loaded', output: 'draft → gmail · scheduled 09:30 PT', }; return msgs[node.k] || 'tick'; } function GraphDemo({ t }) { const [running, setRunning] = useState(true); const [activeIdx, setActiveIdx] = useState(0); const [logs, setLogs] = useState([]); const timerRef = useRef(null); const nodes = t.demo.nodes; const positions = [ { x: 30, y: 60 }, { x: 200, y: 30 }, { x: 200, y: 200 }, { x: 380, y: 60 }, { x: 380, y: 230 }, { x: 560, y: 150 }, ]; const edges = [ [0, 1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 5], ]; useEffect(() => { if (!running) return; timerRef.current = setInterval(() => { setActiveIdx((i) => { const next = (i + 1) % nodes.length; const now = new Date(); const ts = `${String(now.getHours()).padStart(2,'0')}:${String(now.getMinutes()).padStart(2,'0')}:${String(now.getSeconds()).padStart(2,'0')}`; setLogs((prev) => { const node = nodes[next]; const newLog = { t: ts, tag: `[${node.k}]`, msg: getLogMessage(node) }; return [newLog, ...prev].slice(0, 18); }); return next; }); }, 1200); return () => clearInterval(timerRef.current); }, [running, nodes]); useEffect(() => { const now = new Date(); const ts = `${String(now.getHours()).padStart(2,'0')}:${String(now.getMinutes()).padStart(2,'0')}:${String(now.getSeconds()).padStart(2,'0')}`; setLogs([ { t: ts, tag: '[boot]', msg: 'engine v0.42.0 booted · 6 nodes · MIT', ok: true }, { t: ts, tag: '[wsk]', msg: 'subscribed to @webhook/leads', ok: true }, ]); }, []); const step = () => { setActiveIdx((i) => (i + 1) % nodes.length); }; return (
datamirai.app — {t.demo.crumb}

{t.demo.panels.nodes}

{['trigger','logic','ai','data','agent','output'].map((k) => (
{k}
))}
{edges.map(([a, b], i) => { const pa = positions[a]; const pb = positions[b]; const x1 = pa.x + 70, y1 = pa.y + 24; const x2 = pb.x, y2 = pb.y + 24; const mx = (x1 + x2) / 2; const path = `M ${x1} ${y1} C ${mx} ${y1}, ${mx} ${y2}, ${x2} ${y2}`; const isActive = activeIdx === b && running; return ( {isActive && ( )} ); })} {nodes.map((n, i) => { const p = positions[i]; const active = activeIdx === i; return (
{n.k}
{n.l}
{n.m}
); })}

{t.demo.panels.kpis}

{t.demo.kpi.map((k, i) => (
{k.v}
{k.k}
))}

{t.demo.panels.logs}

{logs.map((l, i) => (
{l.t} {l.tag} {l.msg}
))}
); } // ─── Shift Arrow ──────────────────────────────────────────────────────────── function ShiftArrow({ label }) { return (
{label}
); } // ─── Step Illustrations ───────────────────────────────────────────────────── function StepIllu({ n }) { if (n === 0) { return ( {[ { x: 12, y: 18, w: 70, h: 36, c: 'var(--c-trigger)', l: 'trigger' }, { x: 100, y: 14, w: 70, h: 32, c: 'var(--c-logic)', l: 'logic' }, { x: 100, y: 50, w: 70, h: 22, c: 'var(--c-data)', l: 'data' }, { x: 190, y: 30, w: 78, h: 32, c: 'var(--c-output)', l: 'output' }, ].map((b, i) => ( {b.l} ))} ); } if (n === 1) { return ( agent {[ { x: 60, y: 24, l: 'CRM', c: 'var(--c-data)' }, { x: 60, y: 60, l: 'PG', c: 'var(--c-logic)' }, { x: 220, y: 24, l: 'API', c: 'var(--c-output)' }, { x: 220, y: 60, l: 'S3', c: 'var(--c-agent)' }, ].map((p, i) => ( {p.l} ))} ); } return ( {[18, 28, 14, 36, 22, 40, 30, 48, 34, 52, 42, 60].map((h, i) => ( ))} runs / hr ↑ +34% ); } // ─── Particles ────────────────────────────────────────────────────────────── function Particles({ count }) { const particles = useMemo(() => { return Array.from({ length: count }, () => ({ left: Math.random() * 100, top: 60 + Math.random() * 40, delay: Math.random() * 12, duration: 8 + Math.random() * 10, size: 1 + Math.random() * 2, })); }, [count]); return (
{particles.map((p, i) => ( ))}
); } // ─── NavBar ───────────────────────────────────────────────────────────────── function NavBar({ t, lang, theme, toggleLang, toggleTheme }) { const [menuOpen, setMenuOpen] = useState(false); useEffect(() => { document.body.style.overflow = menuOpen ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; }, [menuOpen]); return ( <> {/* Desktop nav — floating glass bar */} {/* Mobile trigger — floating pill top-left */} {/* Mobile fullscreen overlay */}
未来 Data Mirai
setMenuOpen(false)}>{t.nav.product} setMenuOpen(false)}>{t.nav.how} setMenuOpen(false)}>{t.nav.paths}
setMenuOpen(false)}>{t.nav.cta}
); } // ─── Catalog ──────────────────────────────────────────────────────────────── function Catalog({ t }) { const [active, setActive] = useState('all'); const items = t.catalog.items; const visible = active === 'all' ? items : items.filter((it) => it.cat === active); return (
{t.catalog.tag}

{t.catalog.title}

{t.catalog.lede}

{t.catalog.filters.map((f) => ( ))}
{visible.map((it, i) => (
{it.dept}
{it.t}
{it.p}
{it.freq} {t.catalog.saves_label} {it.saves}
))}
{t.catalog.cta_more}
); } // ─── Waitlist ─────────────────────────────────────────────────────────────── const WAITLIST_URL = 'https://script.google.com/macros/s/AKfycbx5PcBDn5FW1ABt4HKMl0HTdMjUKsQP1TA4Z2JHnB6aNYRcKg3fm4VKb-wGlYFjdRCk/exec'; function useSessionData() { const start = useRef(Date.now()); const maxScroll = useRef(0); useEffect(() => { const onScroll = () => { const depth = Math.round((window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100); if (depth > maxScroll.current) maxScroll.current = depth; }; window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); return useCallback(() => { const params = new URLSearchParams(window.location.search); const w = window.innerWidth; return { referrer: document.referrer || 'direct', utm_source: params.get('utm_source') || '', utm_medium: params.get('utm_medium') || '', utm_campaign: params.get('utm_campaign') || '', device: w < 480 ? 'mobile' : w < 1024 ? 'tablet' : 'desktop', screen: `${window.screen.width}x${window.screen.height}`, browser_lang: navigator.language || '', timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || '', scroll_depth: maxScroll.current + '%', time_on_page: Math.round((Date.now() - start.current) / 1000), }; }, []); } function Waitlist({ t, lang }) { const [email, setEmail] = useState(''); const [hp, setHp] = useState(''); const [status, setStatus] = useState('idle'); const getSession = useSessionData(); const submit = (e) => { e.preventDefault(); if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return; setStatus('sending'); const payload = { email, lang, _hp: hp, ...getSession(), }; fetch(WAITLIST_URL, { method: 'POST', body: JSON.stringify(payload), }) .then(() => setStatus('done')) .catch(() => setStatus('done')); }; if (status === 'done') { return
{t.waitlist.success}
; } return (
setEmail(e.target.value)} required /> {/* Honeypot — invisible to humans, bots fill it */} setHp(e.target.value)} style={{position:'absolute',left:'-9999px',tabIndex:-1}} autoComplete="off" aria-hidden="true" />
); } // ─── App ──────────────────────────────────────────────────────────────────── function App() { const [lang, setLang] = useState('es'); const [theme, setTheme] = useState('dark'); const [langFade, setLangFade] = useState(false); const t = window.I18N[lang]; useEffect(() => { document.documentElement.setAttribute('data-theme', theme); }, [theme]); useReveal([lang]); const toggleLang = () => { setLangFade(true); setTimeout(() => { setLang(lang === 'es' ? 'en' : 'es'); }, 50); setTimeout(() => setLangFade(false), 360); }; return (
{/* Background */}
{/* NAV — floating glass, logo centered */} setTheme(theme === 'dark' ? 'light' : 'dark')} /> {/* HERO */}
{t.hero.eyebrow}

DATA MIRAI

{/* MIRAI — storytelling */}
未来
/ mi·rai /
{t.mirai.meaning}

{/* PROBLEMA */}
{t.problema.tag}

{t.problema.title}

{t.problema.lede}

{t.problema.stats.map((s, i) => (
{s.n}{s.u}
{s.l}
{s.ex}
))}
{/* SHIFT */}
{t.shift.tag}

{t.shift.title}

{t.shift.before.label}
    {t.shift.before.items.map((it, i) => (
  • {it}
  • ))}
{t.shift.after.label}
    {t.shift.after.items.map((it, i) => (
  • {it}
  • ))}
{/* COMMAND CENTER */}
{t.panel.tag}

{t.panel.title}

{t.panel.lede}

{t.panel.columns.you.title.toUpperCase()}
{t.panel.columns.you.big}
{t.panel.columns.you.title}
{t.panel.columns.you.sub}

{t.panel.columns.you.desc}

    {t.panel.columns.you.tags.map((tg, i) =>
  • {tg}
  • )}
{t.panel.columns.agents.title.toUpperCase()}
{t.panel.columns.agents.big}
{t.panel.columns.agents.title}
{t.panel.columns.agents.sub}

{t.panel.columns.agents.desc}

{t.panel.columns.agents.chips.map((c, i) => (
{c.name}
))}
{t.panel.columns.services.title.toUpperCase()}
{t.panel.columns.services.big}
{t.panel.columns.services.title}
{t.panel.columns.services.sub}

{t.panel.columns.services.desc}

{t.panel.columns.services.chips.map((c, i) => (
{c.name}
))}
{/* CATALOG */} {/* COMO FUNCIONA */}
{t.como.tag}

{t.como.title}

{t.como.lede}

{t.como.steps.map((s, i) => (
STEP / {s.n}

{s.t}

{s.p}

))}
{/* LIVE DEMO */}
{t.demo.tag}

{t.demo.title}

{t.demo.lede}

{/* DOS CAMINOS */}
{t.paths.tag}

{t.paths.title}

{t.paths.lede}

{t.paths.os.tag}

{t.paths.os.h}

{t.paths.os.price_pre}{t.paths.os.price_post}

{t.paths.os.lede}

    {t.paths.os.features.map((f, i) =>
  • {f}
  • )}
{t.paths.cloud.tag}

{t.paths.cloud.h}

{t.paths.cloud.price_pre} $49{t.paths.cloud.price_post}

{t.paths.cloud.lede}

    {t.paths.cloud.features.map((f, i) =>
  • {f}
  • )}
{/* WAITLIST */}
未来

{t.waitlist.title}

{t.waitlist.lede}

{/* FOOTER */}
DATA未来 {t.footer.rights} {t.footer.made}
); } // ─── Mount ────────────────────────────────────────────────────────────────── const root = ReactDOM.createRoot(document.getElementById('root')); root.render();