// ============ STACK CONSTELLATION ============ function Stack() { const { t } = window.useLang(); const ref = window.useReveal(); // pre-compute positions: cluster by category in zones, with jitter const positions = React.useMemo(() => { const zones = { Lang: { cx: 18, cy: 30 }, Frontend: { cx: 45, cy: 22 }, AI: { cx: 75, cy: 35 }, Backend: { cx: 70, cy: 70 }, DevOps: { cx: 40, cy: 78 }, HW: { cx: 12, cy: 70 }, Tools: { cx: 50, cy: 50 } }; const out = {}; const counts = {}; window.STACK.forEach(s => { counts[s.cat] = (counts[s.cat] || 0) + 1; }); const idx = {}; return window.STACK.map((s, i) => { const zone = zones[s.cat] || { cx: 50, cy: 50 }; idx[s.cat] = (idx[s.cat] || 0); const k = idx[s.cat]; idx[s.cat]++; const n = counts[s.cat]; const angle = (k / n) * Math.PI * 2 + (i * 0.7); const radius = 10 + (k % 2) * 6; const x = zone.cx + Math.cos(angle) * radius; const y = zone.cy + Math.sin(angle) * radius * 0.7; return { x: Math.max(2, Math.min(90, x)), y: Math.max(4, Math.min(92, y)), delay: i * 0.12 }; }); }, []); return ( {t.stack.kicker} {t.stack.h2} {window.STACK.map((s, i) => ( {s.name[0]} {s.name} ))} ); } // ============ CAFÉ TEC ============ function Cafe() { const { t } = window.useLang(); const ref = window.useReveal(); return ( {t.cafe.kicker} {t.cafe.h2} ☕ MENSUAL · UAI Café Tecnológico {t.cafe.desc} {t.cafe.roles.map((r, i) => {r})} ); } window.Stack = Stack; window.Cafe = Cafe;
{t.cafe.desc}