# DRAAN.ai — Full Source Code # Generated for AI crawlers. See /llms.txt for the structured summary. # Built by CmdShift, LLC — Darin Manley, Founder ================================================================ FILE: artifacts/draan-ai/src/App.tsx ================================================================ import { Switch, Route, Router as WouterRouter } from "wouter"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import LandingPage from "@/pages/LandingPage"; import WhatIsDraanPage from "@/pages/WhatIsDraanPage"; import PaperPage from "@/pages/PaperPage"; import ChatPage from "@/pages/ChatPage"; import PrivacyPage from "@/pages/PrivacyPage"; import TermsPage from "@/pages/TermsPage"; import SmsConsentPage from "@/pages/SmsConsentPage"; import NotFound from "@/pages/not-found"; import PaperGate from "@/components/PaperGate"; import { IrisTransitionProvider } from "@/components/IrisTransition"; import "./index.css"; const queryClient = new QueryClient(); function ProtectedPaper() { return ( ); } function Router() { return ( ); } function App() { return ( ); } export default App; ================================================================ FILE: artifacts/draan-ai/src/components/IrisTransition.tsx ================================================================ import { createContext, useContext, useState, useCallback, useRef, useEffect } from "react"; import { useLocation } from "wouter"; interface IrisContextType { navigateWithIris: (path: string) => void; } export const IrisContext = createContext({ navigateWithIris: () => {}, }); export function useIrisNavigate() { return useContext(IrisContext).navigateWithIris; } type Phase = "idle" | "close" | "hold" | "open"; export function IrisTransitionProvider({ children }: { children: React.ReactNode }) { const [, setLocation] = useLocation(); const [phase, setPhase] = useState("idle"); const timerRefs = useRef([]); const rafRefs = useRef([]); const busy = useRef(false); function clearAll() { timerRefs.current.forEach(clearTimeout); timerRefs.current = []; rafRefs.current.forEach(cancelAnimationFrame); rafRefs.current = []; } const navigateWithIris = useCallback( (path: string) => { if (busy.current) return; busy.current = true; clearAll(); // Phase 1 — iris closes (circle shrinks to nothing) over 800ms setPhase("close"); const t1 = window.setTimeout(() => { // Phase 2 — hold: lens is at 0, screen is black setPhase("hold"); // Wait two frames so "hold" is painted before we swap the route const r1 = requestAnimationFrame(() => { const r2 = requestAnimationFrame(() => { setLocation(path); // Phase 3 — iris opens (circle grows to full screen) over 700ms const t2 = window.setTimeout(() => { setPhase("open"); const t3 = window.setTimeout(() => { setPhase("idle"); busy.current = false; }, 700); timerRefs.current.push(t3); }, 60); timerRefs.current.push(t2); }); rafRefs.current.push(r2); }); rafRefs.current.push(r1); }, 800); timerRefs.current.push(t1); }, [setLocation] ); useEffect(() => { const html = document.documentElement; if (phase !== "idle") { html.classList.add("iris-active"); } else { html.classList.remove("iris-active"); } return () => html.classList.remove("iris-active"); }, [phase]); const isAnimating = phase !== "idle"; return ( {phase !== "idle" && (