# Film / Analog Aesthetic

Warmth in a digital world. This aesthetic uses grain, color grading, and imperfection to evoke film photography and analog video. It's the antidote to sterile, hyper-clean AI-generated content.

## Critical Self-Assessment

**Why this deserves a template:**
- ✅ Counter-trend to "too perfect" digital content
- ✅ Strong use cases (lifestyle, food, travel, storytelling, indie brands)
- ✅ Achievable in Remotion (overlays, filters, color grading)
- ✅ Fills the "warm/organic" gap in our toolkit
- ✅ Timeless appeal (film look never goes out of style)

**When NOT to use:**
- Tech/SaaS products (too soft)
- Gaming/esports (needs energy)
- Corporate/enterprise (too casual)
- Anything requiring "cutting edge" feeling

---

## Core Elements

### 1. Film Grain
The signature texture. Organic noise that breathes life into footage.

```tsx
const FilmGrain = ({ 
  intensity = 0.08,
  frame,
  fps = 30,
}: {
  intensity?: number;
  frame: number;
  fps?: number;
}) => {
  // Change grain every few frames for "film" feel
  const grainFrame = Math.floor(frame / 2) * 2; // Update every 2 frames
  
  return (
    <div
      style={{
        position: 'absolute',
        inset: 0,
        opacity: intensity,
        mixBlendMode: 'overlay',
        pointerEvents: 'none',
        backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='grain'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' seed='${grainFrame}'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23grain)'/%3E%3C/svg%3E")`,
      }}
    />
  );
};
```

### 2. Vignette
Darkened edges that focus attention to the center.

```tsx
const Vignette = ({ 
  intensity = 0.4,
  size = 50, // Percentage from center where vignette starts
}: {
  intensity?: number;
  size?: number;
}) => (
  <div
    style={{
      position: 'absolute',
      inset: 0,
      background: `radial-gradient(
        ellipse at center,
        transparent ${size}%,
        rgba(0, 0, 0, ${intensity}) 100%
      )`,
      pointerEvents: 'none',
    }}
  />
);
```

### 3. Color Grading Presets
Film stocks have distinctive color signatures.

```tsx
// Apply via CSS filter + overlay combinations
const colorGrades = {
  // Kodak Portra - Warm, slightly desaturated, creamy highlights
  portra: {
    filter: 'saturate(0.9) contrast(1.05) brightness(1.02)',
    overlay: 'linear-gradient(rgba(255, 235, 205, 0.1), rgba(255, 220, 180, 0.05))',
  },
  
  // Fuji Pro 400H - Cooler shadows, pastel greens
  fujiPro: {
    filter: 'saturate(0.85) contrast(1.1) hue-rotate(-5deg)',
    overlay: 'linear-gradient(rgba(200, 220, 210, 0.08), rgba(180, 200, 190, 0.05))',
  },
  
  // Cinestill 800T - Tungsten, teal shadows, halation
  cinestill: {
    filter: 'saturate(1.1) contrast(1.15)',
    overlay: 'linear-gradient(rgba(0, 80, 100, 0.1), rgba(20, 60, 80, 0.08))',
  },
  
  // Kodak Gold - Warm, saturated, nostalgic
  kodakGold: {
    filter: 'saturate(1.2) contrast(1.1) sepia(0.15)',
    overlay: 'linear-gradient(rgba(255, 200, 100, 0.1), rgba(255, 180, 80, 0.08))',
  },
  
  // Black & White - Classic monochrome
  bw: {
    filter: 'grayscale(1) contrast(1.15) brightness(1.05)',
    overlay: 'none',
  },
};

const ColorGrade = ({ 
  grade,
  children,
}: {
  grade: keyof typeof colorGrades;
  children: React.ReactNode;
}) => (
  <div style={{ position: 'relative' }}>
    <div style={{ filter: colorGrades[grade].filter }}>
      {children}
    </div>
    {colorGrades[grade].overlay !== 'none' && (
      <div style={{
        position: 'absolute',
        inset: 0,
        background: colorGrades[grade].overlay,
        mixBlendMode: 'overlay',
        pointerEvents: 'none',
      }} />
    )}
  </div>
);
```

### 4. Light Leaks
Organic light bleeding into the frame.

```tsx
const LightLeak = ({ 
  color = '#ff6b35',
  position = 'top-right',
  intensity = 0.3,
  frame,
}: {
  color?: string;
  position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
  intensity?: number;
  frame: number;
}) => {
  const positions = {
    'top-left': { top: '-20%', left: '-20%' },
    'top-right': { top: '-20%', right: '-20%' },
    'bottom-left': { bottom: '-20%', left: '-20%' },
    'bottom-right': { bottom: '-20%', right: '-20%' },
  };
  
  // Subtle breathing animation
  const breathe = 1 + Math.sin(frame * 0.03) * 0.1;
  
  return (
    <div
      style={{
        position: 'absolute',
        ...positions[position],
        width: '80%',
        height: '80%',
        background: `radial-gradient(ellipse, ${color}${Math.round(intensity * 255).toString(16).padStart(2, '0')}, transparent 70%)`,
        transform: `scale(${breathe})`,
        mixBlendMode: 'screen',
        pointerEvents: 'none',
      }}
    />
  );
};
```

### 5. Frame Scratches / Dust
Subtle imperfections that add authenticity.

```tsx
const FilmDust = ({ frame }: { frame: number }) => {
  // Generate deterministic "random" dust positions
  const dustParticles = Array.from({ length: 15 }, (_, i) => {
    const seed = Math.sin(i * 1000 + Math.floor(frame / 3)) * 10000;
    return {
      x: (seed % 100),
      y: ((seed * 7) % 100),
      size: 1 + (seed % 3),
      opacity: 0.1 + (seed % 0.3),
    };
  });
  
  return (
    <svg
      style={{
        position: 'absolute',
        inset: 0,
        width: '100%',
        height: '100%',
        pointerEvents: 'none',
      }}
    >
      {dustParticles.map((dust, i) => (
        <circle
          key={i}
          cx={`${dust.x}%`}
          cy={`${dust.y}%`}
          r={dust.size}
          fill={`rgba(255, 255, 255, ${dust.opacity})`}
        />
      ))}
    </svg>
  );
};
```

---

## Color Palette Guidance

Film aesthetic favors **muted, warm** tones.

| Tone | Hex Range | Usage |
|------|-----------|-------|
| Cream/Off-white | #faf7f2 - #f5efe6 | Backgrounds, text |
| Warm Shadow | #2d2a24 - #3d3830 | Dark areas |
| Faded Black | #1a1816 | Near-black (not pure) |
| Amber | #d4a574 - #c9956c | Warm highlights |
| Dusty Rose | #c9a99e - #b8968b | Accent |
| Sage | #a8b5a0 - #8fa086 | Cool accent |

**Key Rule:** Avoid pure colors (#ff0000, #00ff00). Everything is slightly muted/desaturated.

```tsx
// ❌ Too digital
const bad = '#ff0000';

// ✅ Film-like
const good = '#c94a3a'; // Muted, warm red
```

---

## Typography

Film aesthetic pairs with **classic, editorial** typography.

**Serif (Preferred):**
- Playfair Display
- Cormorant Garamond
- Libre Baskerville
- EB Garamond

**Sans-Serif (Clean):**
- Lato
- Source Sans Pro
- Nunito (friendly)
- DM Sans

**Handwritten (Personal):**
- Caveat
- Kalam
- Permanent Marker

**Style Rules:**
- Generous letter-spacing (0.02-0.05em)
- Comfortable line-height (1.4-1.6)
- Avoid ultra-bold weights (feels too digital)
- Consider slight rotation (-1 to 1 deg) for handmade feel

---

## Animation Style

Film aesthetic uses **slow, organic** motion.

### Slow Fades
Longer durations than typical. Let moments breathe.

```tsx
// Standard: 15-20 frame fade
// Film aesthetic: 30-45 frame fade
const opacity = interpolate(
  frame,
  [startFrame, startFrame + 40],
  [0, 1],
  { extrapolateRight: 'clamp' }
);
```

### Gentle Movement
Subtle drifts, not snappy animations.

```tsx
// Slow drift effect
const drift = Math.sin(frame * 0.02) * 5; // Very slow, small movement
transform: `translateY(${drift}px)`;
```

### Ken Burns Effect
Classic documentary-style slow zoom/pan on images.

```tsx
const KenBurns = ({ 
  frame,
  duration = 150,
  startScale = 1,
  endScale = 1.1,
  children,
}: Props) => {
  const progress = frame / duration;
  const scale = interpolate(progress, [0, 1], [startScale, endScale]);
  
  return (
    <div style={{
      transform: `scale(${scale})`,
      transformOrigin: 'center center',
    }}>
      {children}
    </div>
  );
};
```

### Frame Rate Feel
Slightly lower frame rate (24fps) feels more "cinematic" than 30fps.

---

## Compositing Layers

Stack effects in this order (bottom to top):

```
1. Background/Content
2. Color Grade filter
3. Vignette
4. Light Leaks (blend mode: screen)
5. Film Grain (blend mode: overlay)
6. Dust/Scratches (optional)
```

```tsx
const FilmComposition = ({ children, frame }: Props) => (
  <div style={{ position: 'relative' }}>
    {/* Base content with color grade */}
    <ColorGrade grade="portra">
      {children}
    </ColorGrade>
    
    {/* Vignette */}
    <Vignette intensity={0.35} size={55} />
    
    {/* Light leak */}
    <LightLeak 
      color="#ff8c42" 
      position="top-right" 
      intensity={0.2}
      frame={frame}
    />
    
    {/* Grain (always on top) */}
    <FilmGrain intensity={0.06} frame={frame} fps={30} />
  </div>
);
```

---

## Audio Pairing

- **Music:** Acoustic, lo-fi, indie folk, soft electronic
- **SFX:** Organic sounds, soft transitions, analog tape hiss
- **Voiceover:** Warm, intimate, conversational tone

---

## Use Cases

✅ **Perfect for:**
- Lifestyle/fashion brands
- Food & beverage
- Travel content
- Wedding/event videos
- Indie music videos
- Personal storytelling
- Nostalgia marketing
- Artisan/handmade products

❌ **Avoid for:**
- Tech startups
- Gaming content
- Corporate B2B
- Anything needing "modern/digital" feel

---

## Common Mistakes

❌ **Too much grain** → Looks damaged, not artistic
✅ Keep grain subtle (0.04-0.10 opacity)

❌ **Over-saturated color grade** → Defeats the purpose
✅ Film colors are muted, not boosted

❌ **Sharp digital text** → Clashes with organic look
✅ Use serif fonts, slight blur, or texture

❌ **Fast animations** → Feels like digital content with grain overlay
✅ Slow everything down by 1.5-2x

❌ **Pure black/white** → Too digital
✅ Use off-black (#1a1816) and cream (#faf7f2)

---

## Quality Checklist

- [ ] Grain is present but not distracting
- [ ] Colors feel warm and slightly muted
- [ ] No pure black (#000) or pure white (#fff)
- [ ] Vignette draws eye to center
- [ ] Animations are slow and organic
- [ ] Typography feels editorial, not corporate
- [ ] Overall mood is warm and nostalgic
- [ ] Would this look good on a film camera? (mental test)

---

*Reference: Wes Anderson films, A24 trailers, Kinfolk magazine, vintage Polaroid, VSCO filters, 35mm film photography*
