<!-- source-hash: e691658139dcf0e352222348aeae0a32 -->
Self-contained React component that combines SEO metadata editing fields with a live social media (Open Graph) card preview, used across blog posts, case studies, and product releases in the Flamingo/OpenFrame platform.

## Key Components

### `SEOEditorPreview` (default export)
The main component rendering a two-panel layout:
- **Editor fields** — SEO title, description, keywords, and OG image upload
- **Live OG card preview** — real-time social media card simulation

### `SEOEditorPreviewProps` interface
| Prop | Type | Description |
|------|------|-------------|
| `seoTitle` / `seoDescription` / `seoKeywords` / `ogImageUrl` | `string` | Controlled SEO field values |
| `title` / `summary` / `featuredImage` | `string` | Auto-populate fallback sources |
| `onSeo*Change` / `onOgImageUrlChange` | `(value: string) => void` | Change handlers per field |
| `onOgImageUpload` | `(file: File) => Promise<string>` | Optional parent-provided upload handler |
| `aiConfidenceSeo*` | `number` (optional) | AI confidence scores shown via `ConfidenceBadge` |
| `domain` | `string` | Preview domain label (default: `'openmsp.ai'`) |
| `disabled` | `boolean` | Disables all inputs |

### Internal State
- `imageError` — falls back to placeholder when OG image fails to load
- `isUploading` — shows `Loader2` spinner during file upload
- `fileInputRef` — ref to hidden `<input type="file">` for programmatic click

## Usage Example

```typescript
<SEOEditorPreview
  seoTitle={post.seoTitle}
  seoDescription={post.seoDescription}
  seoKeywords={post.seoKeywords}
  ogImageUrl={post.ogImageUrl}
  title={post.title}
  summary={post.summary}
  featuredImage={post.featuredImage}
  onSeoTitleChange={(v) => updatePost({ seoTitle: v })}
  onSeoDescriptionChange={(v) => updatePost({ seoDescription: v })}
  onSeoKeywordsChange={(v) => updatePost({ seoKeywords: v })}
  onOgImageUrlChange={(v) => updatePost({ ogImageUrl: v })}
  onOgImageUpload={async (file) => {
    const { url } = await uploadAsset(file);
    return url;
  }}
  aiConfidenceSeoTitle={0.92}
  domain="flamingo.run"
/>
```

> All SEO fields accept empty strings (never `undefined`). When a field is empty, the component automatically falls back to `title`, `summary`, or `featuredImage` props, showing an "Auto-populated" hint label beneath the input.