# `style.md` Format Specification

A "style" in letmesee is a Markdown file with YAML frontmatter. It describes a complete photographic intent: how aggressive the transformation should be, what model to send it to, what prompt to use, what to never do.

A style is **portable** (one file, no dependencies), **legible** (any human can read it), and **forkable** (right-click → duplicate → edit). The marketplace is just a directory of these files.

## Anatomy

```markdown
---
# Identity
name: True Moment
slug: true-moment
author: letmesee
version: 1.0
license: bundled

# Taxonomy (see docs/prompt-taxonomy.md)
aggressiveness: 1        # 1 (subtle) – 5 (reimagining)
identity: strict         # strict | soft | reimagined
geometry: locked         # locked | adjusted | free
color: neutral           # neutral | graded | stylized
subject: as-shot         # as-shot | posed-adjusted | restaged
environment: cleaned     # cleaned | decluttered | replaced

# Targeting
best_for: [portraits, food, landscape, street, group]
avoid_for: []
preferred_model: gemini-2.5-flash-image
fallback_model: gpt-image-1
cost_estimate_usd: 0.003

# Marketplace metadata
tagline: "What was there, but with a kind eye."
category: "Conservative · True to the Moment"
preview_pairs:
  - { type: portrait, before: portrait-1.jpg, after: portrait-1-after.jpg }
  - { type: food,     before: food-1.jpg,     after: food-1-after.jpg }
  - { type: landscape, before: landscape-1.jpg, after: landscape-1-after.jpg }
---

# True Moment

One paragraph describing the style in human terms. Plain English.
What does it look like, what does it feel like, who is it for?

## What it does

Bulleted list of behavioral guarantees. The user reads this to know
what they're opting into.

- Removes lens dust, sensor specks, and ambient haze.
- Opens shadows by ≤ ⅓ stop.
- Warms color cast toward neutral, never past it.

## What it never does

Hard negative constraints. This is the trust contract.

- Never moves a subject's eyes, mouth, or hands.
- Never changes anyone's expression.
- Never adds or removes a person.
- Never replaces or extends the background.

## Prompt

The literal prompt sent to the model. May reference template
variables in `{curly_braces}` — the engine fills these in at capture
time from the source photo's metadata.

```
You are a careful retoucher. The attached photo was just shot
on an iPhone. Make minimal corrections only: …
```

## Negative prompt

For models that accept negatives (gpt-image, SDXL). For models that
don't (Gemini), this is appended to the main prompt as "Do not …"

```
artificial smoothing, plastic skin, changed expressions,
moved limbs, replaced backgrounds, added bokeh, …
```

## Template variables

| Variable | Resolved from | Example |
| --- | --- | --- |
| `{time_of_day}` | EXIF DateTime | "golden hour" |
| `{subject_count}` | On-device person detection | "2 people" |
| `{primary_subject}` | Heuristic (portrait/food/landscape/…) | "portrait" |
| `{user_location_type}` | Reverse geocode bucket (optional, off by default) | "urban" |
```

## Required fields

The engine refuses to load a style.md missing any of:

- `name`, `slug`, `version`
- `aggressiveness` (must be integer 1–5)
- `preferred_model`
- A `## Prompt` section with at least one non-whitespace line

Everything else is optional but strongly encouraged.

## Reserved slugs

The `letmesee` author namespace owns these slugs (bundled styles):
`true-moment`, `clean-light`, `magazine`, `golden-hour`, `film-archive`, `restage`, `wardrobe`, `dreamscape`.

User and third-party styles get a namespaced slug (`@username/style-name`).

## Versioning

Styles are versioned by semver. The engine pins the version the user *activated*; a marketplace update notifies the user but doesn't auto-upgrade — a style's behavior is part of the user's photographic identity, not something we change under them.
