File size: 7,477 Bytes
df4a1a2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563ed2b
df4a1a2
 
 
 
 
 
 
 
 
 
 
 
 
 
563ed2b
df4a1a2
 
 
 
 
 
 
563ed2b
 
 
df4a1a2
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import { useEffect, useRef, useState } from "react";
import { useAnimate } from "motion/react";
import { twMerge } from "tailwind-merge";
import { clsx } from "clsx";

function cn(...inputs) {
  return twMerge(clsx(inputs));
}

export const FedoraSVG = ({ className }) => (
  <svg viewBox="0 0 100 60" className={cn("w-full h-full drop-shadow-[0_8px_16px_rgba(0,0,0,0.6)]", className)} xmlns="http://www.w3.org/2000/svg">
    <path d="M 28 40 L 35 15 C 37 5, 45 5, 50 10 C 55 15, 63 5, 65 10 C 70 15, 72 30, 72 40 Z" fill="#5c4033" stroke="#2a1b14" strokeWidth="2" strokeLinejoin="round" />
    <path d="M 28 40 L 31 30 Q 52 38 69 30 L 72 40 Q 52 45 28 40 Z" fill="#111111" />
    <path d="M 4 45 C 4 45, 25 35, 50 42 C 75 48, 96 38, 96 38 C 96 38, 90 50, 50 50 C 15 50, 4 45, 4 45 Z" fill="#463025" stroke="#2a1b14" strokeWidth="2" strokeLinejoin="round"/>
  </svg>
);

// Custom Geometric SVGs
const LetterA = ({ className, ...props }) => (
  <svg viewBox="0 0 100 100" className={cn("inline-block w-[0.8em] h-[1em]", className)} {...props} fill="currentColor">
    <rect x="10" y="10" width="20" height="80" />
    <rect x="70" y="10" width="20" height="80" />
    <rect x="10" y="10" width="80" height="20" />
    <rect x="10" y="45" width="80" height="20" />
  </svg>
);

const LetterP = ({ className, ...props }) => (
  <svg viewBox="0 0 100 100" className={cn("inline-block w-[0.8em] h-[1em]", className)} {...props} fill="currentColor">
    <rect x="10" y="10" width="20" height="80" />
    <rect x="70" y="10" width="20" height="55" />
    <rect x="10" y="10" width="80" height="20" />
    <rect x="10" y="45" width="80" height="20" />
  </svg>
);

const LetterD = ({ className, ...props }) => (
  <svg viewBox="0 0 100 100" className={cn("inline-block w-[0.8em] h-[1em]", className)} {...props} fill="currentColor">
    <rect x="10" y="10" width="20" height="80" />
    <rect x="70" y="10" width="20" height="80" />
    <rect x="10" y="10" width="80" height="20" />
    <rect x="10" y="70" width="80" height="20" />
  </svg>
);

const LetterF = ({ className, ...props }) => (
  <svg viewBox="0 0 100 100" className={cn("inline-block w-[0.8em] h-[1em]", className)} {...props} fill="currentColor">
    <rect x="10" y="10" width="20" height="80" />
    <rect x="10" y="10" width="80" height="20" />
    <rect x="10" y="45" width="60" height="20" />
  </svg>
);

export function LandingAnimation({ onComplete }) {
  const [scope, animate] = useAnimate();
  const aRef = useRef(null);
  const gentRef = useRef(null);
  const pRef = useRef(null);
  const dRef = useRef(null);
  const fRef = useRef(null);

  const [phase, setPhase] = useState(0);

  useEffect(() => {
    let active = true;

    const runSeq = async () => {
      // Wait for layout/fonts to mount
      await new Promise(r => setTimeout(r, 400));
      if (!active) return;

      const fedoraNode = document.getElementById("fedora");
      const aRect = aRef.current?.getBoundingClientRect();
      const fRect = fRef.current?.getBoundingClientRect();

      if (fedoraNode && aRect && fRect) {
        const targetRightX = fRect.right - aRect.left + 20;
        const startY = fRect.height * 0.4;

        // Snap Fedora directly to the right side of Agent PDF initially
        await animate(fedoraNode, { x: targetRightX, y: startY, rotate: 10 }, { duration: 0 });
        await animate(fedoraNode, { opacity: 1 }, { duration: 0.3 });

        await new Promise(r => setTimeout(r, 400));
        if (!active) return;

        // 1. Hat Boomerang to right (fly out further)
        await animate(fedoraNode, { x: targetRightX + aRect.width * 1.5, y: startY - aRect.height * 0.2, rotate: 30 }, { duration: 0.6, ease: "easeOut" });
        
        // 2. Hat loops back to lands perfectly on 'A' Base coordinates (0, 0)
        await animate(fedoraNode, { x: 5, y: -aRect.height * 0.05, rotate: -5, scale: 0.95 }, { duration: 0.7, ease: "backOut" });
        setPhase(1); // Hat landed

        await new Promise(r => setTimeout(r, 400));
        if (!active) return;

        // 3. 'gent' collapses
        if (gentRef.current) {
          const gentWidth = gentRef.current.offsetWidth;
          gentRef.current.style.width = `${gentWidth}px`;
          await animate(gentRef.current, { width: 0, opacity: 0, paddingRight: 0, marginLeft: 0 }, { duration: 0.6, ease: "backIn" });
          gentRef.current.style.display = 'none';
        }

        // Collapse spacer
        await animate("#spacer", { width: 0 }, { duration: 0.2 });

        // 4. P, D, F merge into A
        const currentARect2 = aRef.current?.getBoundingClientRect();
        
        const mergeLetter = async (ref, delay) => {
          if (!ref.current || !currentARect2) return;
          const rect = ref.current.getBoundingClientRect();
          const offsetX = currentARect2.left - rect.left;
          
          animate(ref.current, { x: offsetX, opacity: 0, filter: "blur(4px)" }, { duration: 0.5, delay });
        };

        mergeLetter(pRef, 0);
        mergeLetter(dRef, 0.15);
        await mergeLetter(fRef, 0.3);

        if (!active) return;

        // 5. Center the block! We slide #text-container.
        const scopeRect = scope.current?.getBoundingClientRect();
        const finalARect = aRef.current?.getBoundingClientRect();
        if (scopeRect && finalARect) {
            const aCenterX = finalARect.left + finalARect.width / 2;
            const scopeCenterX = scopeRect.left + scopeRect.width / 2;
            const offset = scopeCenterX - aCenterX;
            await animate("#text-container", { x: offset }, { duration: 0.8, ease: "easeInOut" });
        }

        setPhase(2); // Merge & Center complete

        // Notify parent that animation is complete
        if (onComplete) onComplete();
      }
    };
    runSeq();

    return () => { active = false; };
  }, [animate, onComplete, scope]);

  return (
    <div ref={scope} className="relative select-none flex items-center justify-center min-h-[300px] w-full mt-10">
      
      <div id="text-container" className="flex items-end text-[80px] md:text-[120px] font-black leading-none tracking-tighter text-slate-800 relative">
        
        {/* The 'A' and its child Fedora! */}
        <span ref={aRef} className={cn("relative z-20 flex transition-all duration-700 ease-in-out", phase >= 2 && "text-orange-500 drop-shadow-[0_0_20px_rgba(229,115,0,0.6)] px-2")}>
          <LetterA />
          {/* The Fedora securely contained within A, initially invisible */}
          <div 
            id="fedora"
            className="absolute bottom-[90%] left-[-8%] w-[1.3em] z-30 transform origin-bottom opacity-0"
          >
            <FedoraSVG />
          </div>
        </span>
        
        {/* 'gent' (Standard font for contrast) */}
        <span ref={gentRef} className="relative z-10 overflow-hidden text-slate-600 whitespace-nowrap pl-[0.05em] origin-left pb-2 text-[60px] md:text-[90px]" style={{ fontFamily: "ui-sans-serif, system-ui, sans-serif" }}>
          gent
        </span>
        
        {/* Space */}
        <span className="w-4 md:w-6 inline-block" id="spacer"></span>
        
        {/* P, D, F */}
        <span ref={pRef} className="relative z-10 text-slate-700 flex"><LetterP /></span>
        <span ref={dRef} className="relative z-10 text-slate-600 flex"><LetterD /></span>
        <span ref={fRef} className="relative z-10 text-slate-500 flex"><LetterF /></span>

      </div>
    </div>
  );
}