/* global React */
const { useEffect, useRef, useState, useMemo } = React;
/* ============== Reveal-on-scroll hook ============== */
function useReveal() {
useEffect(() => {
const els = document.querySelectorAll('.reveal, .word');
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => {
if (e.isIntersecting) {
e.target.classList.add('in');
io.unobserve(e.target);
}
});
}, { threshold: 0.1, rootMargin: '0px 0px -5% 0px' });
els.forEach((el) => io.observe(el));
return () => io.disconnect();
}, []);
}
/* ============== Type helpers ============== */
function SplitWords({ text, children, className = '', delayBase = 0 }) {
let raw = text;
if (raw == null) {
const arr = React.Children.toArray(children);
raw = arr.map((c) => typeof c === 'string' || typeof c === 'number' ? String(c) : '').join('');
}
const words = String(raw).split(' ').filter(Boolean);
return (
{words.map((w, i) =>
{w}
)}
);
}
/* ============== Nav ============== */
function Nav() {
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const f = () => setScrolled(window.scrollY > 40);
window.addEventListener('scroll', f, { passive: true });
f();
return () => window.removeEventListener('scroll', f);
}, []);
return (
);
}
/* ============== Background Helpers ============== */
function MasterGrid() {
return
;
}
/* ============== Record Player (YouTube) ============== */
function RecordPlayer() {
const [player, setPlayer] = useState(null);
const [isPlaying, setIsPlaying] = useState(false);
const [isMuted, setIsMuted] = useState(false);
const [isReady, setIsReady] = useState(false);
useEffect(() => {
const initPlayer = () => {
// Avoid initializing multiple times
if (document.getElementById('yt-player-container').innerHTML !== '') return;
const ytPlayer = new window.YT.Player('yt-player-container', {
height: '0',
width: '0',
videoId: 'MYW0TgV67RE', // Work Music for Serious Grind _ Stay Aligned
playerVars: {
autoplay: 1,
controls: 0,
disablekb: 1,
fs: 0,
rel: 0,
showinfo: 0,
iv_load_policy: 3
},
events: {
onReady: (event) => {
setIsReady(true);
setPlayer(event.target);
event.target.playVideo();
},
onStateChange: (event) => {
if (event.data === window.YT.PlayerState.PLAYING) {
setIsPlaying(true);
} else {
setIsPlaying(false);
}
}
}
});
};
if (!window.YT) {
const tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.onYouTubeIframeAPIReady = initPlayer;
} else if (window.YT && window.YT.Player) {
initPlayer();
} else {
const prev = window.onYouTubeIframeAPIReady;
window.onYouTubeIframeAPIReady = () => {
if (prev) prev();
initPlayer();
}
}
}, []);
// Hack for strict browsers: Force play on any first interaction (scroll, click, etc)
const hasAutoPlayed = useRef(false);
useEffect(() => {
if (!player || hasAutoPlayed.current) return;
const forcePlay = () => {
if (!hasAutoPlayed.current && player.getPlayerState && player.getPlayerState() !== window.YT.PlayerState.PLAYING) {
player.playVideo();
hasAutoPlayed.current = true;
}
window.removeEventListener('click', forcePlay);
window.removeEventListener('scroll', forcePlay);
window.removeEventListener('touchstart', forcePlay);
window.removeEventListener('keydown', forcePlay);
};
window.addEventListener('click', forcePlay, { passive: true });
window.addEventListener('scroll', forcePlay, { passive: true });
window.addEventListener('touchstart', forcePlay, { passive: true });
window.addEventListener('keydown', forcePlay, { passive: true });
return () => {
window.removeEventListener('click', forcePlay);
window.removeEventListener('scroll', forcePlay);
window.removeEventListener('touchstart', forcePlay);
window.removeEventListener('keydown', forcePlay);
};
}, [player]);
const togglePlay = () => {
if (!player) return;
if (isPlaying) {
player.pauseVideo();
} else {
player.playVideo();
}
};
const toggleMute = (e) => {
e.stopPropagation();
if (!player) return;
if (isMuted) {
player.unMute();
setIsMuted(false);
} else {
player.mute();
setIsMuted(true);
}
};
const spinState = isPlaying ? 'running' : 'paused';
return (
{/* Background grid / tech texture */}
{/* Nodal Processor Visuals (Rotates slightly) */}
{/* Outer Ring 1 */}
{/* Outer Ring 2 (dashed) */}
{/* Inner Ring */}
{/* PCB Traces (SVG lines) */}
{/* Central cross */}
{/* Diagonal nodes */}
{/* Orbiting Data Packet (Orb) on the dashed ring */}
{/* Central Core (Static) */}
{/* Red Dot (Nothing OS style) */}
{/* Mute button icon overlaid if muted */}
{isMuted && (
✕
)}
{/* Floating Status Texts (Dot-Matrix) */}
{isReady ? (
isPlaying ? (
<>
[BATAJ_CORE.STREAMING.AUDIO:ACTIVE]
// BPM_SYNC: 120
>
) : (
<>
[BATAJ_CORE.STATUS:LOCKED]
// AUDIO:MUTED
>
)
) : (
[INITIALIZING_CORE...]
)}
);
}
/* ============== Hero ============== */
function Hero() {
return (
[SYS_STATUS: ONLINE]
v2.0.0-rc
Diseñamos y construimos aplicaciones web a medida. Estética premium, stack moderno, código limpio. Listas para operar.
);
}
/* ============== Manifesto ============== */
function Manifesto() {
const pillars = [
{ n: '01', t: 'Identidad', d: 'Tipografía, ritmo y tono diseñados desde cero.' },
{ n: '02', t: 'Sistema', d: 'Componentes escalables, sin deuda visual.' },
{ n: '03', t: 'Operativo', d: 'Entregamos software que ya factura.' },
{ n: '04', t: 'Stack', d: 'React, Node, Postgres. Sin vendor lock-in.' }
];
return (
// MANIFESTO
/ 04 Principios
No vendemostecnología.
Vendemos productos terminados. Con estética. Con identidad. Listos para entrar al mercado el lunes.
{pillars.map((p, i) => (
{p.n}
{p.t}
{p.d}
))}
);
}
/* ============== Products header ============== */
function ProductsIntro() {
return (
/ PRODUCTOS
Cada productoun universo.
Desde una agenda profesional hasta un dashboard de inteligencia comercial. Mismo estudio. Cuatro lenguajes visuales.
);
}
/* ============== Process ============== */
function Process() {
const steps = [
{ n: '01', t: 'Brief', d: 'Entendemos el negocio. No el ticket.', tag: '1 sem' },
{ n: '02', t: 'Sistema', d: 'Identidad, tokens y voz. Antes de codear.', tag: '2-3 sem' },
{ n: '03', t: 'Build', d: 'Sprints quincenales, deploy continuo.', tag: '6-12 sem' },
{ n: '04', t: 'Launch', d: 'Entregamos operativo. Cobranza, métricas.', tag: 'Día 1' }
];
return (
/ PROCESO
De cero a producto.En semanas.
{steps.map((s, i) =>
{s.n}
{s.tag}
{s.t}
{s.d}
)}
);
}
/* ============== Stats strip ============== */
function Stats() {
const stats = [
{ v: '4', l: 'PRODUCTOS EN PRODUCCIÓN' },
{ v: '100%', l: 'DISEÑO + DEV INTEGRADO' },
{ v: '<12w', l: 'TIEMPO AL PRIMER LAUNCH' },
{ v: '0', l: 'PLANTILLAS REUTILIZADAS' }
];
return (
);
}
/* ============== CTA / Footer ============== */
function CTAFooter() {
return (
);
}
/* Expose */
Object.assign(window, {
useReveal, SplitWords, Nav, Hero, Manifesto, ProductsIntro, Process, Stats, CTAFooter, MasterGrid
});