/* Hero — IA que coloca negócios locais NO MAPA
Includes mouse parallax 3D scene with 3 characters */
function CharacterCard({ name, role, color, description, specialties, index, active, onHover, onLeave, mouseX, mouseY, parallaxAmt }) {
// Carousel offset relative to active
const offset = index - active;
// -2..+2 positions wrap
const wrapped = ((offset + 3) % 3); // 0,1,2
// map to slot: 0 = center, 1 = right, 2 = left
let slot;
if (wrapped === 0) slot = 'center';
else if (wrapped === 1) slot = 'right';
else slot = 'left';
const slotConfig = {
center: { x: 0, z: 80, ry: 0, scale: 1.0, opacity: 1, z2: 3 },
left: { x: -55, z: -40, ry: 18, scale: 0.72, opacity: 0.55, z2: 1 },
right: { x: 55, z: -40, ry: -18, scale: 0.72, opacity: 0.55, z2: 1 }
}[slot];
const isHover = active === index && onHover; // tooltip only on center
const tx = (mouseX * 6) * parallaxAmt + slotConfig.x * 1;
const ty = mouseY * 5 * parallaxAmt;
const rx = -mouseY * 4 * parallaxAmt;
return (
onHover && onHover(index)}
onMouseLeave={() => onLeave && onLeave()}
onClick={() => onHover && onHover(index)}
style={{
position: 'absolute',
top: '50%',
left: '50%',
width: '62%',
marginLeft: '-31%',
marginTop: '-31%',
transformStyle: 'preserve-3d',
transform: `translate3d(calc(${slotConfig.x}% + ${tx}px), ${ty}px, ${slotConfig.z}px) rotateY(${slotConfig.ry + mouseX * 6 * parallaxAmt}deg) rotateX(${rx}deg) scale(${slotConfig.scale})`,
transition: 'transform 1.1s cubic-bezier(.22,.85,.3,1), opacity .9s ease',
cursor: 'pointer',
zIndex: slotConfig.z2,
opacity: slotConfig.opacity
}}
>
{/* Glow halo */}
{/* Speech-bubble tooltip with specialties — only on center card */}
{slot === 'center' && (
{/* tail */}
{name}
{role}
{description}
Especialidades
{specialties.map(s => (
{s}
))}
)}
);
}
/* Character mascot — stylized abstract face with neon */
function CharacterMascot({ color, variant }) {
// 3 variants: builder (brackets), brain (circuit), radar (rings)
return (
);
}
function FloatingPins({ color, variant }) {
const pins = [
{ x: 12, y: 20, delay: 0 },
{ x: 82, y: 12, delay: 0.6 },
{ x: 88, y: 70, delay: 1.2 }
];
return (
{pins.map((p, i) => (
))}
);
}
function Hero() {
const sceneRef = React.useRef(null);
const [mouse, setMouse] = React.useState({ x: 0, y: 0 });
const [showDemo, setShowDemo] = React.useState(false);
const tweaks = window.__tweaks || { parallax: 1 };
React.useEffect(() => {
const onMove = (e) => {
if (!sceneRef.current) return;
const r = sceneRef.current.getBoundingClientRect();
const x = ((e.clientX - r.left) / r.width - 0.5) * 2; // -1..1
const y = ((e.clientY - r.top) / r.height - 0.5) * 2;
setMouse({ x, y });
};
const el = sceneRef.current;
if (el) el.addEventListener('mousemove', onMove);
return () => { if (el) el.removeEventListener('mousemove', onMove); };
}, []);
// Subscribe to tweak updates
const [, force] = React.useReducer(x => x + 1, 0);
React.useEffect(() => {
const handler = () => force();
window.addEventListener('codekid:tweak', handler);
return () => window.removeEventListener('codekid:tweak', handler);
}, []);
const parallaxAmt = (window.__tweaks?.parallax ?? 1);
const characters = [
{
name: 'CAIO', role: 'BUILDER', color: '#00E5FF',
description: 'O programador. Constrói soluções sólidas e escaláveis.',
specialties: ['Backend', 'APIs', 'Estrutura', 'Código Limpo']
},
{
name: 'CAUÊ', role: 'AI OPERATOR', color: '#7C3AED',
description: 'O automatizador. Constrói IA para escalar resultados.',
specialties: ['IA', 'Automação', 'Design', 'Experiência']
},
{
name: 'CAUÃ', role: 'HUNTER', color: '#00FFA3',
description: 'O explorador. Encontra negócios escondidos no mapa.',
specialties: ['Mapeamento', 'Dados', 'Radar', 'Inteligência']
}
];
// Convert color CSS vars to actual color for inline calc
const colorMap = {
'var(--cyan)': '#00E5FF',
'var(--purple)': '#7C3AED',
'var(--green)': '#00FFA3'
};
return (
{showDemo && setShowDemo(false)} />}
{/* LEFT: copy */}
null}>
Do mapa para a web. Do invisível para o digital.
IA que coloca
negócios locais
no mapa.
Seu negócio no Rio de Janeiro merece um site próprio. Conheça os
layouts e converse com a CodeKid sobre a presença digital da sua loja.
{['Primeira análise gratuita', 'Site no ar em até 48 horas úteis após aprovação e envio do conteúdo necessário', 'Sem fidelidade'].map(t => (
{t}
))}
{/* RIGHT: 3D carousel with 3 character cards */}
);
}
function HeroCarousel({ characters, sceneRef, mouse, parallaxAmt }) {
const [active, setActive] = React.useState(1); // start centered on Cauê
const [paused, setPaused] = React.useState(false);
// Auto-rotate every 4.5s
React.useEffect(() => {
if (paused) return;
const t = setInterval(() => setActive(a => (a + 1) % 3), 6500);
return () => clearInterval(t);
}, [paused]);
return (
setPaused(true)}
onMouseLeave={() => setPaused(false)}
>
{characters.map((c, i) => (
setActive(idx)}
onLeave={() => {}}
mouseX={mouse.x}
mouseY={mouse.y}
parallaxAmt={parallaxAmt}
/>
))}
{/* Dots indicator */}
{characters.map((c, i) => (
);
}
function BackgroundRadar() {
return (
);
}
function DemoModal({ onClose }) {
// fecha com ESC + trava o scroll da pagina enquanto aberto
React.useEffect(() => {
const onKey = (e) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', onKey);
const prevOverflow = document.body.style.overflow;
document.body.style.overflow = 'hidden';
return () => {
window.removeEventListener('keydown', onKey);
document.body.style.overflow = prevOverflow;
};
}, [onClose]);
return (
e.stopPropagation()} style={{
position: 'relative', width: '100%', maxWidth: 960
}}>
{/* botao fechar */}
);
}
window.Hero = Hero;
window.DemoModal = DemoModal;
/* Per-character themed background effect inside the photo frame */
function ThemeEffect({ variant, color }) {
if (variant === 0) return ;
if (variant === 1) return ;
return ;
}
/* CAIO — falling code characters */
function CodeRainEffect({ color }) {
const chars = '01>{};=+#';
const cols = React.useMemo(() => (
Array.from({ length: 10 }).map((_, i) => ({
x: i * 10 + Math.random() * 4,
delay: Math.random() * 4,
dur: 4 + Math.random() * 4,
str: Array.from({ length: 12 }).map(() => chars[Math.floor(Math.random() * chars.length)]).join('\n')
}))
), []);
return (
{cols.map((c, i) => (
{c.str}
))}
);
}
/* CAUÊ — neural network nodes */
function NeuralEffect({ color }) {
const nodes = React.useMemo(() => (
Array.from({ length: 14 }).map(() => ({
x: 6 + Math.random() * 88,
y: 6 + Math.random() * 88,
delay: Math.random() * 3
}))
), []);
const links = React.useMemo(() => {
const out = [];
for (let i = 0; i < nodes.length; i++) {
for (let j = i + 1; j < nodes.length; j++) {
const dx = nodes[i].x - nodes[j].x;
const dy = nodes[i].y - nodes[j].y;
if (dx*dx + dy*dy < 800) out.push({ a: i, b: j });
}
}
return out;
}, [nodes]);
return (
);
}
/* CAUÃ — radar concentric rings + sweep */
function RadarPulseEffect({ color }) {
const dots = React.useMemo(() => (
Array.from({ length: 18 }).map(() => ({
x: 8 + Math.random() * 84,
y: 8 + Math.random() * 84,
d: Math.random() * 3
}))
), []);
return (
);
}
/* Tactical corner brackets that match the character color */
function CornerBrackets({ color }) {
const sz = 16;
const brkStyle = {
position: 'absolute',
width: sz, height: sz,
borderColor: color,
borderStyle: 'solid',
pointerEvents: 'none',
zIndex: 3,
filter: `drop-shadow(0 0 6px ${color})`
};
return (
<>
>
);
}