// AI walkthrough — animated multi-scene video showing the Thraxel AI Hub in action // Auto-cycles between scenes; user can also click chapter markers to jump. const { useState: useStateAI, useEffect: useEffectAI, useRef: useRefAI, useMemo: useMemoAI } = React; const SCENES = [ { id:'replace', title:'Replace 12+ softwares', dur: 6500 }, { id:'voice', title:'AI voice answers your business', dur: 6500 }, { id:'avatar', title:'On-brand AI avatars', dur: 6500 }, { id:'booking', title:'Booking on autopilot', dur: 6500 }, { id:'leadmap', title:'God\u2019s-eye lead map', dur: 7000 }, ]; function useSceneCycle(scenes){ const [i, setI] = useStateAI(0); const [paused, setPaused] = useStateAI(false); const [progress, setProgress] = useStateAI(0); // 0..1 within scene const startRef = useRefAI(performance.now()); useEffectAI(()=>{ let raf; const tick = ()=>{ if (!paused){ const elapsed = performance.now() - startRef.current; const dur = scenes[i].dur; const p = Math.min(1, elapsed / dur); setProgress(p); if (p >= 1){ setI((i+1) % scenes.length); startRef.current = performance.now(); } } raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return ()=> cancelAnimationFrame(raf); }, [i, paused]); const goto = (idx)=>{ setI(idx); startRef.current = performance.now(); setProgress(0); }; return { i, progress, paused, setPaused, goto }; } // ---------- SCENE 1: Replace 12+ softwares ---------- function SceneReplace({ progress }){ const apps = [ { name:'QuickBooks', color:'#2CA01C', mark:'qb' }, { name:'HubSpot', color:'#FF7A59', mark:'hs' }, { name:'ServiceTitan',color:'#FFB200',mark:'st' }, { name:'Jobber', color:'#1E73BE', mark:'jb' }, { name:'Stripe', color:'#635BFF', mark:'st2' }, { name:'Gmail', color:'#EA4335', mark:'gm' }, { name:'Twilio', color:'#F22F46', mark:'tw' }, { name:'Calendly', color:'#006BFF', mark:'cl' }, { name:'Slack', color:'#4A154B', mark:'sl' }, { name:'Mailchimp', color:'#FFE01B', mark:'mc' }, { name:'Zendesk', color:'#03363D', mark:'zd' }, { name:'Asana', color:'#F06A6A', mark:'as' }, ]; // Phase 0-0.5: apps fly in around perimeter // Phase 0.5-0.75: red sweep eliminates them // Phase 0.75-1: THRAXEL hub pulses with $ savings counter const eliminated = progress > 0.55; const finalPhase = progress > 0.78; const sweepX = (progress - 0.55) / 0.2; // 0..1 during sweep return (
{/* perimeter apps */} {apps.map((a, idx)=>{ const ang = (idx / apps.length) * Math.PI * 2 - Math.PI/2; const r = 36; const x = 50 + Math.cos(ang)*r; const y = 50 + Math.sin(ang)*r; const flyIn = Math.min(1, progress*3 - idx*0.04); const op = eliminated ? Math.max(0, 1 - sweepX*1.4 - idx*0.05) : Math.max(0, flyIn); const scale = eliminated ? 0.6 + (1-Math.max(0,1-sweepX))*0 : 0.4 + 0.6*Math.max(0,flyIn); const xOff = eliminated ? (idx%2?-1:1) * sweepX * 200 : 0; return (
{a.name}
{eliminated && ( )}
); })} {/* red sweep wave */} {progress > 0.5 && progress < 0.78 && (
)} {/* central THRAXEL hub */}
THRAXEL
AI HUB
{/* savings stat */} {finalPhase && (
↓ ${Math.floor(2400 + (progress-0.78)*4000)}/mo SAVED
)}
); } // ---------- SCENE 2: AI Voice ---------- function SceneVoice({ progress }){ // Phase 0-0.3: phone rings/incoming call // Phase 0.3-0.7: AI voice waveform + caller transcript // Phase 0.7-1: actions fire — calendar block created, lead saved const showCall = progress > 0.05; const showWave = progress > 0.25; const showTranscript = progress > 0.32; const showActions = progress > 0.7; const wavePhase = progress * 14; const transcript = [ { who:'CALLER', text:'"Hey, looking for a quote on permanent lights."', t:0.34 }, { who:'RANDY', text:'"Got it. What city are you in?"', t:0.46 }, { who:'CALLER', text:'"Cranberry Township."', t:0.56 }, { who:'RANDY', text:'"Perfect — that\'s in our route. Single story or two?"', t:0.66 }, ]; return (
{/* top: incoming call card */}
{/* pulse ring */}
● INCOMING · AI ANSWERED
+1 (724) 555-0188
00:0{Math.floor(progress*5)}
{/* waveform */}
{Array.from({length:48}).map((_,i)=>{ const h = 6 + Math.abs(Math.sin(i*0.5 + wavePhase))*30 * (1 - Math.abs((i-24)/30)); return
24-wavePhase*4 ? 'var(--thraxel-red)':'#2a2a2e',borderRadius:2,transition:'height 0.05s'}}/>; })}
{/* transcript */}
{transcript.map((t,i)=>{ const visible = showTranscript && progress > t.t; return (
{t.who}
{t.text}
); })}
{/* actions row */}
{[ {label:'LEAD CREATED',color:'#3aff7a'}, {label:'CALLBACK SCHEDULED',color:'#FFB347'}, {label:'QUOTE PREP QUEUED',color:'var(--thraxel-red)'}, ].map(a=>(
✓ {a.label}
))}
); } // ---------- SCENE 3: Avatar ---------- function SceneAvatar({ progress }){ // Phase 0-0.4: avatar generates in (skeletal -> filled portrait) // Phase 0.4-0.8: avatar speaks; controls show ("voice", "tone", "video reply") // Phase 0.8-1: video reply preview generated const generated = progress > 0.35; const showControls = progress > 0.42; const showOutput = progress > 0.78; return (
{/* avatar window */}
{/* synthetic portrait silhouette */} {/* shoulders */} {/* neck */} {/* head */} {/* hair */} {/* eyes */} {/* mouth — animated when speaking */} {generated && ( )} {/* generation scan line */} {!generated && ( )} {/* polygon mesh on generation */} {!generated && ( )}
{generated ? '● LIVE · AVATAR_RANDY_01' : '○ GENERATING…'}
{/* status badge */}
FOR YOUR BUSINESS
{/* right side: controls + output */}
AVATAR FOR YOUR BUSINESS
{[ ['VOICE','Western PA · Warm'], ['TONE','Friendly · Direct'], ['CHANNEL','SMS · Email · Video'], ['LANGUAGE','EN · ES'], ].map(([l,v])=>(
{l}
{v}
))}
{/* output: video reply preview */}
VIDEO REPLY · GENERATED
"Hey Sarah — saw your inquiry…"
0:24
); } // ---------- SCENE 4: Booking ---------- function SceneBooking({ progress }){ // Phase 0-0.3: calendar grid renders // Phase 0.3-0.6: AI suggests slot, confirms via SMS // Phase 0.6-1: booking confirmed; deposit captured const showCal = progress > 0.05; const showSuggested = progress > 0.32; const showSMS = progress > 0.5; const showConfirm = progress > 0.78; // 5-day x 4-row grid const days = ['MON','TUE','WED','THU','FRI']; const rows = ['9A','11A','1P','3P']; // mark booked vs available const grid = [ ['B','A','B','A','B'], ['B','A','A','B','A'], ['A','S','B','A','A'], // S = AI suggested slot at TUE 1P ['B','B','A','A','B'], ]; return (
{/* calendar */}
WEEK OF APR 14
TECH · AJ
{days.map(d=>(
{d}
))} {rows.map((r,ri)=>(
{r}
{grid[ri].map((c,ci)=>{ const isSuggested = c==='S'; const isBooked = c==='B'; const pulse = isSuggested && showSuggested; const becomesBooked = isSuggested && showConfirm; return (
{becomesBooked ? '✓ BOOKED' : (isBooked ? '·' : (pulse ? 'AI ↗' : ''))}
); })}
))}
{/* SMS conversation */}
SMS · CARRIE J.
{[ { who:'me', text:'Tue Apr 15, 1–3 PM works for the walkthrough?', t:0.55 }, { who:'them',text:'Yes! Perfect.', t:0.66 }, { who:'me', text:'Booked. $150 deposit holds the slot.', t:0.74 }, { who:'them',text:'Sending now 👍', t:0.85 }, ].map((m,i)=>{ const visible = progress > m.t; return (
{m.text}
); })}
{/* deposit captured */}
● DEPOSIT CAPTURED
$150.00
); } // ---------- SCENE 5: God's-eye Lead Map ---------- function SceneLeadMap({ progress }){ // Phase 0-0.25: map fades in with HQ pin pulsing // Phase 0.25-0.7: red dots pop into existence across PA/OH/WV/MD/NY (leads streaming in) // Phase 0.5-1: live events panel populates one at a time on the right // Phase 0.8-1: stats counters tick up // Pre-seeded lead positions across the abstract map (percent coords inside the SVG box) const leads = useMemoAI(()=> { const seeds = []; // Cluster heavy in PA (center) for (let i=0;i<14;i++) seeds.push({ x: 42 + Math.random()*28, y: 30 + Math.random()*22, t: 0.25 + Math.random()*0.4 }); // Ohio left for (let i=0;i<5;i++) seeds.push({ x: 18 + Math.random()*18, y: 32 + Math.random()*22, t: 0.30 + Math.random()*0.4 }); // NY top for (let i=0;i<5;i++) seeds.push({ x: 28 + Math.random()*46, y: 14 + Math.random()*12, t: 0.35 + Math.random()*0.35 }); // WV for (let i=0;i<4;i++) seeds.push({ x: 36 + Math.random()*28, y: 60 + Math.random()*16, t: 0.40 + Math.random()*0.3 }); // MD for (let i=0;i<3;i++) seeds.push({ x: 60 + Math.random()*22, y: 56 + Math.random()*12, t: 0.45 + Math.random()*0.3 }); return seeds; },[]); const events = [ { label:'New Lead', value:'724-555-0188 · Cranberry Twp', color:'#3aff7a', t:0.40 }, { label:'Quote Sent', value:'PDF · 4-zone · $4,820', color:'#3aff7a', t:0.50 }, { label:'Booked', value:'Tue 4/14 · 9-11am · Tech: AJ', color:'#FFB347', t:0.60 }, { label:'Review Filed', value:'★★★★★ · Google · auto-replied', color:'#3aff7a', t:0.70 }, { label:'Scrape Match', value:'12 new permits · Butler Co.', color:'#1a4dcf', t:0.80 }, ]; const statT = (progress - 0.78) / 0.22; const tickT = Math.max(0, Math.min(1, statT)); const stats = [ { l:'LEADS / 30D', v: Math.floor(1847 * tickT).toLocaleString() }, { l:'PERMITS WATCHED', v: Math.floor(12402 * tickT).toLocaleString() }, { l:'CLOSE RATE', v: `${Math.floor(38 * tickT)}%` }, { l:'REGIONS', v: Math.floor(5 * tickT) }, ]; return (
{/* top header — like the dashboard chrome */}
0.05?1:0,transition:'opacity 0.3s'}}> OPS · LIVE WPA · OHIO · WV · MD · NY
{/* main row: map + events */}
{/* map */}
{/* state polys */} {/* HQ */} HQ · 16037 {/* lead dots — pop in based on their .t threshold */} {leads.map((d,idx)=>{ const visible = progress > d.t; const justPopped = progress > d.t && progress < d.t + 0.05; return (
); })} {/* stats strip — bottom-left */}
0.7?1:0, transform:`translateY(${progress>0.7?0:8}px)`,transition:'opacity 0.4s, transform 0.4s', }}> {stats.map(s=>(
{s.l}
{s.v}
))}
{/* events feed */}
● LIVE EVENTS
{events.map((e,i)=>{ const visible = progress > e.t; return (
{e.label}
{e.value}
); })}
); } // ---------- Main walkthrough player ---------- function AIWalkthrough(){ const { i, progress, paused, setPaused, goto } = useSceneCycle(SCENES); const SceneEl = [SceneReplace, SceneVoice, SceneAvatar, SceneBooking, SceneLeadMap][i]; return (
setPaused(true)} onMouseLeave={()=>setPaused(false)} > {/* film-like vignette */}
{/* top status bar */}
● THRAXEL AI HUB · WALKTHROUGH
{String(i+1).padStart(2,'0')} / {String(SCENES.length).padStart(2,'0')}
{/* the active scene */}
{/* bottom: title + chapters + progress */}
{SCENES[i].title}
{paused && (
❚❚ PAUSED
)}
{/* chapter progress segments */}
{SCENES.map((s,idx)=>{ const filled = idx < i ? 1 : (idx === i ? progress : 0); const isActive = idx === i; return ( ); })}
{/* corner mini-meta — gives a "captured live" feel */}
REC · 1080p
); } Object.assign(window, { AIWalkthrough });