1- import { useState , useEffect , useCallback } from 'react'
1+ import { useState , useEffect , useCallback , type CSSProperties } from 'react'
22import { MeshGradient } from '@paper-design/shaders-react'
3+
4+ // ─── Presentation Page (temporary, for video recording) ──────────────
5+
6+ function WordReveal ( { text, delay, isGradient } : { text : string ; delay : number ; isGradient ?: boolean } ) {
7+ const words = text . split ( ' ' )
8+ return (
9+ < >
10+ { words . map ( ( word , i ) => (
11+ < span key = { i } style = { {
12+ display : 'inline-block' , margin : '0 0.12em' ,
13+ opacity : 0 , filter : 'blur(8px)' , transform : 'translateY(30px) scale(0.85)' ,
14+ animation : `word-reveal 0.8s ease-out forwards` ,
15+ animationDelay : `${ delay + i * 150 } ms` ,
16+ ...( isGradient ? { background : 'linear-gradient(to bottom, white, rgba(255,255,255,0.4))' , WebkitBackgroundClip : 'text' , WebkitTextFillColor : 'transparent' } : { } ) ,
17+ } } >
18+ { word }
19+ </ span >
20+ ) ) }
21+ </ >
22+ )
23+ }
24+
25+ function PresentationPage ( ) {
26+ const [ logoVisible , setLogoVisible ] = useState ( false )
27+
28+ useEffect ( ( ) => {
29+ setTimeout ( ( ) => setLogoVisible ( true ) , 200 )
30+ } , [ ] )
31+
32+ return (
33+ < >
34+ < style > { `
35+ @keyframes word-reveal {
36+ 0% { opacity: 0; transform: translateY(30px) scale(0.85); filter: blur(8px); }
37+ 60% { opacity: 1; transform: translateY(8px) scale(0.97); filter: blur(1px); }
38+ 100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
39+ }
40+ @keyframes logo-reveal {
41+ 0% { opacity: 0; transform: scale(0.7); filter: blur(20px); }
42+ 50% { opacity: 0.8; transform: scale(1.02); filter: blur(3px); }
43+ 100% { opacity: 1; transform: scale(1); filter: blur(0); }
44+ }
45+ @keyframes line-grow {
46+ 0% { width: 0; opacity: 0; }
47+ 100% { width: 80px; opacity: 0.3; }
48+ }
49+ @keyframes dot-fade {
50+ 0% { opacity: 0; transform: scale(0); }
51+ 100% { opacity: 0.4; transform: scale(1); }
52+ }
53+ ` } </ style >
54+
55+ < MeshGradient
56+ className = "!fixed inset-0 w-full h-full z-0"
57+ style = { { position : 'fixed' } }
58+ colors = { [ '#000000' , '#1a1a1a' , '#333333' , '#ffffff' ] }
59+ speed = { 0.12 }
60+ />
61+ < div style = { { position : 'fixed' , inset : 0 , zIndex : 1 , opacity : 0.12 , pointerEvents : 'none' , mixBlendMode : 'overlay' as const , backgroundImage : `url("data:image/svg+xml,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='6' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")` , backgroundRepeat : 'repeat' , backgroundSize : '512px 512px' } } />
62+
63+ < div style = { { position : 'relative' , zIndex : 10 , minHeight : '100vh' , display : 'flex' , flexDirection : 'column' , alignItems : 'center' , justifyContent : 'center' , gap : 40 } } >
64+
65+ { /* Logo — blur-to-sharp reveal */ }
66+ < div style = { {
67+ opacity : logoVisible ? 1 : 0 ,
68+ transform : logoVisible ? 'scale(1)' : 'scale(0.7)' ,
69+ filter : logoVisible ? 'blur(0)' : 'blur(20px)' ,
70+ transition : 'all 1.4s cubic-bezier(0.16,1,0.3,1)' ,
71+ } } >
72+ < img src = "/logo2.svg" alt = "Triage" style = { { width : 200 , height : 200 } } />
73+ </ div >
74+
75+ { /* Decorative line */ }
76+ < div style = { { height : 1 , background : 'linear-gradient(90deg, transparent, rgba(203,213,225,0.3), transparent)' , animation : 'line-grow 1.5s ease-out forwards' , animationDelay : '1s' , width : 0 , opacity : 0 } } />
77+
78+ { /* Title — word-by-word blur reveal */ }
79+ < h1 style = { { fontSize : 'clamp(52px, 9vw, 80px)' , fontWeight : 800 , letterSpacing : '-0.02em' , textAlign : 'center' , lineHeight : 1.1 } } >
80+ < WordReveal text = "TRIAGE" delay = { 1000 } isGradient />
81+ </ h1 >
82+
83+ { /* Tagline — word-by-word, slightly delayed */ }
84+ < p style = { { fontSize : 'clamp(16px, 2.5vw, 22px)' , textAlign : 'center' , maxWidth : 500 , color : 'rgba(255,255,255,0.5)' , fontWeight : 300 , letterSpacing : '0.02em' } } >
85+ < WordReveal text = "Trust infrastructure for the agent economy" delay = { 1600 } />
86+ </ p >
87+
88+ { /* Three dots — appear last */ }
89+ < div style = { { display : 'flex' , gap : 12 , marginTop : 8 } } >
90+ { [ 0 , 1 , 2 ] . map ( i => (
91+ < div key = { i } style = { {
92+ width : 4 , height : 4 , borderRadius : '50%' , background : 'rgba(203,213,225,0.6)' ,
93+ opacity : 0 , transform : 'scale(0)' ,
94+ animation : 'dot-fade 0.5s ease-out forwards' ,
95+ animationDelay : `${ 3200 + i * 200 } ms` ,
96+ } } />
97+ ) ) }
98+ </ div >
99+ </ div >
100+ </ >
101+ )
102+ }
103+
3104import { IDKitRequestWidget , deviceLegacy } from '@worldcoin/idkit'
4105import type { IDKitRequestHookConfig , IDKitResult } from '@worldcoin/idkit'
5106
@@ -26,7 +127,24 @@ function CopyBtn({ text }: { text: string }) {
26127 )
27128}
28129
130+ function BgPage ( ) {
131+ return (
132+ < >
133+ < MeshGradient
134+ className = "!fixed inset-0 w-full h-full z-0"
135+ style = { { position : 'fixed' } }
136+ colors = { [ '#000000' , '#1a1a1a' , '#333333' , '#ffffff' ] }
137+ speed = { 0.12 }
138+ />
139+ < div style = { { position : 'fixed' , inset : 0 , zIndex : 1 , opacity : 0.12 , pointerEvents : 'none' , mixBlendMode : 'overlay' as const , backgroundImage : `url("data:image/svg+xml,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='6' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")` , backgroundRepeat : 'repeat' , backgroundSize : '512px 512px' } } />
140+ </ >
141+ )
142+ }
143+
29144export default function App ( ) {
145+ if ( window . location . pathname === '/bg' ) return < BgPage />
146+ if ( window . location . pathname === '/presentation' ) return < PresentationPage />
147+
30148 const [ verified , setVerified ] = useState ( false )
31149 const [ humanId , setHumanId ] = useState < string | null > ( null )
32150 const [ result , setResult ] = useState < { tier : string ; trustScore : number ; roast : string ; price : string } | null > ( null )
0 commit comments