/* global React, NAV_LINKS, Magnetic, Star, Glyph */ const { useState:useStateH, useEffect:useEffectH, useRef:useRefH } = React; /* ---------- Gold particle field (canvas) ---------- */ function ParticleField({ density=0.00009, color='212,175,55', dark=true }){ const ref = useRefH(null); useEffectH(()=>{ const cv = ref.current; if(!cv) return; const ctx = cv.getContext('2d'); let w,h,parts=[],raf, dpr=Math.min(2,window.devicePixelRatio||1); const make=()=>{ const n=Math.max(26,Math.floor(w*h*density)); parts=Array.from({length:n},()=>({ x:Math.random()*w, y:Math.random()*h, r:Math.random()*1.6+0.4, vy:-(Math.random()*0.28+0.05), vx:(Math.random()-0.5)*0.12, a:Math.random()*0.6+0.15, tw:Math.random()*Math.PI*2, })); }; const resize=()=>{ w=cv.clientWidth; h=cv.clientHeight; cv.width=w*dpr; cv.height=h*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); make(); }; const draw=()=>{ ctx.clearRect(0,0,w,h); for(const p of parts){ p.x+=p.vx; p.y+=p.vy; p.tw+=0.02; if(p.y<-4){p.y=h+4;p.x=Math.random()*w;} if(p.x<-4)p.x=w+4; if(p.x>w+4)p.x=-4; const a=p.a*(0.55+0.45*Math.sin(p.tw)); ctx.beginPath(); ctx.fillStyle=`rgba(${color},${a})`; ctx.shadowBlur=6; ctx.shadowColor=`rgba(${color},${a*0.8})`; ctx.arc(p.x,p.y,p.r,0,7); ctx.fill(); } raf=requestAnimationFrame(draw); }; resize(); draw(); window.addEventListener('resize',resize); return ()=>{cancelAnimationFrame(raf); window.removeEventListener('resize',resize);}; },[]); return React.createElement('canvas',{ref, className:'particle-field', style:{position:'absolute',inset:0,width:'100%',height:'100%',pointerEvents:'none'}}); } /* ---------- Navigation ---------- */ function Nav(){ const [scrolled,setScrolled]=useStateH(false); const [open,setOpen]=useStateH(false); const [platformsOpen,setPlatformsOpen]=useStateH(false); useEffectH(()=>{ const on=()=>setScrolled(window.scrollY>40); on(); window.addEventListener('scroll',on,{passive:true}); return ()=>window.removeEventListener('scroll',on); },[]); const go=(id)=>(e)=>{e.preventDefault();const el=document.getElementById(id);if(el)window.scrollTo({top:el.offsetTop-10,behavior:'smooth'});setOpen(false);}; const onContact=(e)=>{e.preventDefault(); setOpen(false); window.openContact('AETHERCORE LABS');}; const onJoin=(e)=>{e.preventDefault(); setOpen(false); window.goDashboard();}; const map={'Mission':'mission','Platforms':'ecosystem','Precision Medicine':'journey','Future':'future','Research':'research','Careers':'careers'}; return React.createElement('header',{className:`nav ${scrolled?'is-scrolled':''}`}, React.createElement('div',{className:'nav-inner'}, React.createElement('a',{href:'#',className:'brand',onClick:go('top')}, React.createElement(LogoMark,null), React.createElement('span',{className:'brand-txt'},'AETHERCORE',React.createElement('em',null,'LABS')) ), React.createElement('nav',{className:'nav-links'}, NAV_LINKS.map(l=>l==='Platforms' ? React.createElement('div',{className:'nav-dropdown',key:l, onMouseEnter:()=>setPlatformsOpen(true),onMouseLeave:()=>setPlatformsOpen(false)}, React.createElement('a',{href:'#ecosystem',onClick:go('ecosystem'), 'aria-haspopup':'true','aria-expanded':platformsOpen},'Platforms'), React.createElement('div',{className:`nav-dropdown-menu ${platformsOpen?'open':''}`}, PLATFORMS.map(p=>React.createElement('a',{key:p.id,href:`platforms/${p.id}.html`},p.name)), React.createElement('span',{className:'nav-dropdown-rule'}), React.createElement('a',{href:'value-proposition.html',className:'nav-dropdown-value'},'Value Proposition') ) ) : React.createElement('a',{key:l,href:'#',onClick:go(map[l])},l)) ), React.createElement('div',{className:'nav-cta'}, React.createElement('a',{href:'#',className:'nav-contact',onClick:onContact},'Contact'), React.createElement(Magnetic,{strength:0.4}, React.createElement('button',{className:'btn btn-gold nav-join',onClick:onJoin},'Join Now') ), React.createElement('button',{className:'nav-burger',onClick:()=>setOpen(o=>!o),'aria-label':'Menu'}, React.createElement('span',null),React.createElement('span',null),React.createElement('span',null)) ) ), React.createElement('div',{className:`nav-mobile ${open?'open':''}`}, NAV_LINKS.map(l=>l==='Platforms' ? React.createElement('div',{className:'nav-mobile-group',key:l}, React.createElement('button',{className:'nav-mobile-platform-toggle', onClick:()=>setPlatformsOpen(v=>!v)},'Platforms ',platformsOpen?'\u2212':'+'), React.createElement('div',{className:`nav-mobile-platforms ${platformsOpen?'open':''}`}, PLATFORMS.map(p=>React.createElement('a',{key:p.id,href:`platforms/${p.id}.html`},p.name)), React.createElement('a',{href:'value-proposition.html'},'Value Proposition'))) : React.createElement('a',{key:l,href:'#',onClick:go(map[l])},l)), React.createElement('a',{href:'#',onClick:onContact},'Contact'), React.createElement('a',{href:'#',onClick:onJoin,style:{color:'var(--gold-deep)',fontWeight:600}},'Join Now') ) ); } function LogoMark(){ return React.createElement('span',{className:'logo-mark'}, React.createElement('svg',{viewBox:'0 0 48 40',fill:'none'}, React.createElement('path',{d:'M6 34 18 8l6 14',stroke:'currentColor',strokeWidth:2,strokeLinecap:'round',strokeLinejoin:'round'}), React.createElement('path',{d:'M40 13a13 13 0 1 0 0 18',stroke:'currentColor',strokeWidth:2,strokeLinecap:'round'}), React.createElement('path',{d:'M33 19c.4 2.6 1.9 4.1 4.5 4.5-2.6.4-4.1 1.9-4.5 4.5-.4-2.6-1.9-4.1-4.5-4.5 2.6-.4 4.1-1.9 4.5-4.5z',fill:'var(--gold)',stroke:'none'}) ) ); } /* ---------- Hero with boomerang carve video ---------- */ function Hero(){ const videoRef=useRefH(null); const canvasRef=useRefH(null); const layerRef=useRefH(null); const [ready,setReady]=useStateH(false); const framesRef=useRefH([]); const [mounted,setMounted]=useStateH(false); useEffectH(()=>{ const t=setTimeout(()=>setMounted(true),60); return ()=>clearTimeout(t); },[]); // capture frames -> boomerang useEffectH(()=>{ const video=videoRef.current; if(!video) return; let capturing=true, lastT=-1, raf, fallbackTimer; const MAXW=900; const frames=[]; const fallbackLoop=()=>{ capturing=false; try{video.loop=true;video.play().catch(()=>{});}catch(e){} }; fallbackTimer=setTimeout(()=>{ if(!ready && frames.length<6) fallbackLoop(); },9000); const cap=()=>{ if(!capturing) return; if(video.readyState>=2 && video.currentTime!==lastT){ lastT=video.currentTime; const s=Math.min(1,MAXW/(video.videoWidth||MAXW)); const cw=Math.round((video.videoWidth||MAXW)*s), ch=Math.round((video.videoHeight||MAXW)*s); const c=document.createElement('canvas'); c.width=cw;c.height=ch; try{ c.getContext('2d').drawImage(video,0,0,cw,ch); frames.push(c);}catch(e){} } if('requestVideoFrameCallback' in video) video.requestVideoFrameCallback(cap); else raf=requestAnimationFrame(cap); }; const onEnded=()=>{ if(frames.length>8){ capturing=false; framesRef.current=frames; clearTimeout(fallbackTimer); setReady(true); } else { fallbackLoop(); } }; const onMeta=()=>{ video.play().catch(()=>{}); cap(); }; video.addEventListener('loadedmetadata',onMeta); video.addEventListener('ended',onEnded); if(video.readyState>=1) onMeta(); return ()=>{ capturing=false; cancelAnimationFrame(raf); clearTimeout(fallbackTimer); video.removeEventListener('loadedmetadata',onMeta); video.removeEventListener('ended',onEnded); }; },[]); // boomerang render useEffectH(()=>{ if(!ready) return; const cv=canvasRef.current; const frames=framesRef.current; if(!cv||!frames.length) return; cv.width=frames[0].width; cv.height=frames[0].height; const ctx=cv.getContext('2d'); let i=0,dir=1,last=performance.now(),raf; const interval=1000/30; const render=(now)=>{ if(now-last>=interval){ last=now; ctx.drawImage(frames[i],0,0); i+=dir; if(i>=frames.length-1){i=frames.length-1;dir=-1;} else if(i<=0){i=0;dir=1;} } raf=requestAnimationFrame(render); }; raf=requestAnimationFrame(render); return ()=>cancelAnimationFrame(raf); },[ready]); // parallax on the media layer useEffectH(()=>{ let tx=0,ty=0,cx=0,cy=0,raf; const onMove=(e)=>{ const X=(e.clientX/window.innerWidth-0.5), Y=(e.clientY/window.innerHeight-0.5); tx=X*22; ty=Y*16; }; const onScroll=()=>{}; const loop=()=>{ cx+=(tx-cx)*0.06; cy+=(ty-cy)*0.06; if(layerRef.current) layerRef.current.style.transform=`scale(1.1) translate(${cx}px,${cy}px)`; raf=requestAnimationFrame(loop); }; window.addEventListener('mousemove',onMove); loop(); return ()=>{ cancelAnimationFrame(raf); window.removeEventListener('mousemove',onMove); }; },[]); // scroll-fade hero content useEffectH(()=>{ const el=document.getElementById('hero-content'); const on=()=>{ const y=window.scrollY; if(el){ el.style.opacity=String(Math.max(0,1-y/520)); el.style.transform=`translateY(${y*0.18}px)`; } }; window.addEventListener('scroll',on,{passive:true}); return ()=>window.removeEventListener('scroll',on); },[]); const m=mounted?'in':''; return React.createElement('section',{className:'hero',id:'top'}, React.createElement('div',{className:'hero-media',ref:layerRef}, React.createElement('video',{ref:videoRef,src:'assets/hero-carve.mp4',muted:true,playsInline:true,preload:'auto', style:{display:ready?'none':'block'},className:'hero-video'}), React.createElement('canvas',{ref:canvasRef,className:'hero-video',style:{display:ready?'block':'none'}}) ), React.createElement('div',{className:'hero-veil'}), React.createElement(ParticleField,null), React.createElement('div',{className:'hero-frame'}), React.createElement('div',{className:'hero-content',id:'hero-content'}, React.createElement('div',{className:`hero-kick ${m}`}, React.createElement(Star,{size:12}), React.createElement('span',null,'AETHERCORE LABS'), React.createElement(Star,{size:12}) ), React.createElement('h1',{className:`hero-title display ${m}`}, React.createElement('span',{className:'l1'},'Building the Future of'), React.createElement('span',{className:'l2 gild italic'},'Biological Intelligence') ), React.createElement('p',{className:`hero-sub ${m}`}, 'The operating system for biology.'), React.createElement('div',{className:`hero-btns ${m}`}, React.createElement(Magnetic,{strength:0.4}, React.createElement('button',{className:'btn btn-gold',onClick:()=>window.goDashboard()},'Join AetherCore', React.createElement(Glyph,{name:'arrow',className:'arr',width:16,height:16}))), React.createElement(Magnetic,{strength:0.4}, React.createElement('button',{className:'btn btn-dark',onClick:()=>{const el=document.getElementById('ecosystem');el&&window.scrollTo({top:el.offsetTop,behavior:'smooth'});}},'Explore Platform')) ) ), React.createElement('div',{className:`hero-scroll ${m}`}, React.createElement('span',null,'Scroll'), React.createElement('span',{className:'hero-scroll-line'}) ) ); } Object.assign(window,{ Nav, Hero, ParticleField, LogoMark });