import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { X, ChevronRight, ChevronLeft, Sparkles } from 'lucide-react'; import AnimatedCharacter from '@/components/AnimatedCharacter'; import { cn } from '@/lib/utils'; const STEPS = [ { title: 'Welcome to ReplicaLab', content: 'Watch AI agents negotiate how to replicate scientific experiments under real-world constraints.', character: null as string | null, highlight: null as string | null, }, { title: 'Meet Dr. Elara — The Scientist', content: 'She proposes experiment protocols, adjusting sample size, technique, duration, and equipment to match the original paper.', character: 'scientist', highlight: 'scientist', }, { title: 'Meet Takuma — The Lab Manager', content: 'He checks budgets, equipment availability, reagent stocks, and scheduling conflicts. If something doesn\'t work, he suggests alternatives.', character: 'lab_manager', highlight: 'lab_manager', }, { title: 'Meet Judge Aldric', content: 'After negotiations end, the Judge scores the final protocol on Rigor, Feasibility, and Fidelity using a deterministic rubric.', character: 'judge', highlight: 'judge', }, { title: 'How to Play', content: 'Choose a scenario and difficulty, then click "Start Episode". Use "Step" to advance rounds, or enable Auto-Play to watch it unfold. Try the Protocol Editor to craft your own actions!', character: null, highlight: null, }, { title: 'Keyboard Shortcuts', content: 'Press Space to step, R to restart, A for auto-play, E to toggle the editor, and ? for the full shortcut list. You\'re ready!', character: null, highlight: null, }, ]; const STORAGE_KEY = 'replicalab-onboarded'; export function useOnboarding() { const [show, setShow] = useState(false); useEffect(() => { try { if (!localStorage.getItem(STORAGE_KEY)) { setShow(true); } } catch { // ignore } }, []); function dismiss() { setShow(false); try { localStorage.setItem(STORAGE_KEY, '1'); } catch { // ignore } } function reset() { setShow(true); try { localStorage.removeItem(STORAGE_KEY); } catch { // ignore } } return { showOnboarding: show, dismissOnboarding: dismiss, resetOnboarding: reset }; } interface OnboardingProps { show: boolean; onDismiss: () => void; } export default function Onboarding({ show, onDismiss }: OnboardingProps) { const [step, setStep] = useState(0); if (!show) return null; const current = STEPS[step]; const isLast = step === STEPS.length - 1; return ( {/* Skip button */} {/* Step indicator */}
{STEPS.map((_, i) => (
))}
{/* Character */} {current.character ? (
) : (
)}

{current.title}

{current.content}

{/* Navigation */}
{isLast ? ( ) : ( )}
); }