# Manual Replication: Handling Non-Extractable Elements

## When to Use This Guide

Some visual elements **cannot be extracted from HTML/CSS**:

- JavaScript-powered animations
- Canvas/WebGL renders
- Scroll-triggered effects
- Complex hover transitions
- SVG animations
- Video backgrounds
- Particle effects

For these, you must **look at the screenshot and replicate manually**.

## The Process

### 1. Identify What's Non-Extractable

Signs that something needs manual replication:

- Element looks different in screenshot vs. HTML structure
- CSS shows simple styles but visual is complex
- Effect involves motion/time
- `<canvas>` or `<video>` elements present

### 2. Study the Screenshot

Look carefully at:

- **What is the visual effect?** (floating, pulsing, glowing, etc.)
- **What elements are involved?**
- **What colors and opacities are used?**
- **What's the timing/rhythm?**

### 3. Choose a Replication Strategy

| Original Effect | Replication Strategy |
|-----------------|---------------------|
| JS animation loop | CSS @keyframes animation |
| Scroll-triggered | Framer Motion + scroll events |
| Particle effects | CSS pseudo-elements or canvas |
| Complex transitions | CSS transitions + Tailwind states |
| Video background | `<video>` tag with autoplay loop |
| Gradient animation | CSS animation on background-position |

## Common Replications

### Floating Animation

```tsx
// Original: JS-powered floating effect
// Replication: CSS keyframes

<div className="animate-float">
  <img src="/assets/photo.png" />
</div>

// In globals.css:
@keyframes float {
  0%, 100% { transform: translateY(0px); }
  50% { transform: translateY(-20px); }
}
.animate-float {
  animation: float 3s ease-in-out infinite;
}
```

### Pulsing Glow

```tsx
// Original: JS-controlled opacity changes
// Replication: CSS animation

<div 
  className="absolute rounded-full animate-pulse-glow"
  style={{
    width: '400px',
    height: '400px',
    background: 'radial-gradient(circle, #ABE0FF 0%, transparent 70%)',
    filter: 'blur(60px)',
  }}
/>

// In globals.css:
@keyframes pulse-glow {
  0%, 100% { opacity: 0.4; transform: scale(1); }
  50% { opacity: 0.6; transform: scale(1.1); }
}
.animate-pulse-glow {
  animation: pulse-glow 4s ease-in-out infinite;
}
```

### Gradient Background Animation

```tsx
"use client";

export default function AnimatedGradient() {
  return (
    <div 
      className="absolute inset-0"
      style={{
        background: 'linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab)',
        backgroundSize: '400% 400%',
        animation: 'gradient 15s ease infinite',
      }}
    >
      <style jsx>{`
        @keyframes gradient {
          0% { background-position: 0% 50%; }
          50% { background-position: 100% 50%; }
          100% { background-position: 0% 50%; }
        }
      `}</style>
    </div>
  );
}
```

### Hover Card Lift

```tsx
// Original: JS mousemove tracking for 3D effect
// Replication: CSS transform on hover

<div className="
  transition-all duration-300 ease-out
  hover:-translate-y-2 
  hover:shadow-[0_20px_40px_rgba(0,0,0,0.15)]
">
  <img src="/assets/card.png" />
</div>
```

### Scroll-Triggered Fade In

```tsx
"use client";

import {motion} from 'framer-motion';

export default function FadeInSection({children}) {
  return (
    <motion.div
      initial={{opacity: 0, y: 30}}
      whileInView={{opacity: 1, y: 0}}
      viewport={{once: true, margin: "-100px"}}
      transition={{duration: 0.6, ease: "easeOut"}}
    >
      {children}
    </motion.div>
  );
}
```

### Typewriter Effect

```tsx
"use client";

import {useState, useEffect} from 'react';

export default function Typewriter({text, speed = 50}) {
  const [displayed, setDisplayed] = useState('');
  
  useEffect(() => {
    let i = 0;
    const timer = setInterval(() => {
      if (i < text.length) {
        setDisplayed(text.slice(0, i + 1));
        i++;
      } else {
        clearInterval(timer);
      }
    }, speed);
    return () => clearInterval(timer);
  }, [text, speed]);
  
  return <span>{displayed}<span className="animate-blink">|</span></span>;
}
```

### Parallax Background

```tsx
"use client";

import {useEffect, useState} from 'react';

export default function ParallaxBg({src}) {
  const [offset, setOffset] = useState(0);
  
  useEffect(() => {
    const handleScroll = () => setOffset(window.scrollY * 0.5);
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);
  
  return (
    <div 
      className="absolute inset-0 bg-cover bg-center"
      style={{
        backgroundImage: `url(${src})`,
        transform: `translateY(${offset}px)`,
      }}
    />
  );
}
```

## When Perfect Replication Isn't Possible

Sometimes the original effect is too complex to replicate exactly. In these cases:

1. **Capture the essence** - What feeling does the effect create?
2. **Use a simpler version** - A basic animation is better than nothing
3. **Document the limitation** - Note what couldn't be replicated

## Dependencies for Complex Animations

If using Framer Motion:
```bash
npm install framer-motion
```

If using GSAP:
```bash
npm install gsap
```

## Key Principle

> **The goal is visual parity, not code parity.**
> 
> If the clone looks the same as the original, it doesn't matter that you achieved it differently.
