# The effect stack

Effects are per-scope and ordered: **Clip**, **Layer**, **Group** and **Master**. See [Effect reference](effect-reference.md) for what each effect does.

## Scopes

The Inspector picker chooses Clip, Layer or Master. Open group FX from **Groups** or a group header.
Adding an effect or loading a preset changes only the captured target scope.

| Scope | What it processes |
|---|---|
| **Clip** | One clip's pixels |
| **Layer** | The composited result of that layer after its own transform |
| **Group** | The composite of its members, before the parent group or Master |
| **Master** | The canvas after layers and groups |

## Adding, naming and removing

> **The Effects tab's Add menu and the legacy Add effect menu offer different lists.**
>
> The **Effects** tab's **Add** menu offers **every available kind** — all 27 — labelled by name. Use that
> one. The Inspector's separate legacy shortcut offers only the original seven, and two of its entries
> (`Glow`, `Pixelate`) no longer match the effects' current names (`Bloom / Glow`, `Pixelate / Bit Crush`), so
> those two rows currently do nothing. See [Not verified](#not-verified) below.

A newly added instance:

- is named after its effect by default, renameable to 1–80 characters;
- starts enabled, at **Wet amount 1**, blend `Alpha`, with that effect's documented parameter defaults.

The panel shows `n/16` live. Select instances in the list, then use **Selected actions** to
enable, bypass, move, duplicate or remove the selection.

**Maximum 16 instances per scope.** Add is refused at 16; a preset with more than 16 is rejected
entirely.

## Selecting several effects

Selection belongs to one effect stack. It is separate from selecting clips in the matrix.

| Action | Result |
|---|---|
| Click an effect row | Select only that effect and set the range anchor |
| **⌘**-click a row | Toggle that effect in or out of the selection |
| **⇧**-click a row | Select the ordered range from the anchor to that effect |
| **⌘⇧**-click a row | Add that ordered range to the selection |
| Click a row's checkbox | Add or remove just that effect |
| **Clear selection** | Deselect everything without changing the stack |

Selected rows have checked boxes and a selected appearance. The panel reports **N selected**.
The row also exposes named accessibility actions to select only that effect, toggle its selection,
or extend the range to it.

The form below the list labels **Editing primary effect:** followed by its name. Its Enabled, name, Wet amount,
Blend, parameter and animation controls edit **only the primary effect**, even when several effects
are selected. Use **Selected actions** for batch changes.

### Selected actions

- **Enable selected** / **Bypass selected** changes all selected instances together.
- **Move selected up** / **Move selected down** moves each selected block one position while retaining
  the selected effects' relative order. If a selected effect is already at that boundary, the entire
  move is refused.
- **Duplicate selected** inserts each copy directly below its original and selects the copies.
  Copies have independent identities and retain the original parameters, animation, Wet amount and blend.
- **Remove selected** removes exactly those instances and leaves the selection empty.

Every changed batch creates **one Undo step**. Consecutive batches remain separate steps, including
when performed quickly. One Undo or Redo restores the entire batch; it clears transient selection.
A rejected operation or an unchanged enable/bypass operation preserves the stack and Undo/Redo history.

Duplication is refused unless the **whole selection** fits within 16 instances. Enabling or duplicating
an unavailable effect is refused for the complete selection; unavailable effects can still be bypassed
or removed. An opaque future-version stack must be replaced or cleared before editing.

Selection follows surviving instance identities after stack edits. Changing layers or the editing
session clears it; selection is not saved with the set. Clearing selection or deselecting the final
member stays empty. A delayed batch action is refused if its captured stack or selection has changed.

## Ordering

Array top to bottom: the first instance receives the input image, and each subsequent one receives the
previous result. **Duplicate selected** inserts each copy directly beneath its original.
Up/down moves selected blocks one position, preserving their relative order.

The complete processing order is:

```
clip source → clip transform → clip effects (top→bottom) → clip opacity
  → layer clip transition → layer transform → layer effects → composite with blend + opacity
    → optional group stages (inner group → parent: composite, transform, effects, opacity)
      → master transform → master effects → master opacity over black
```

## Bypass and Wet amount

Both are handled the same way in the render loop: **an instance that is disabled or whose Wet amount
is 0 is skipped entirely.** Rows read `On` or `Bypassed`.

Wet amount is the instance's own blend-opacity — it is not "dry/wet" in the plug-in sense:

| Situation | Result |
|---|---|
| Blend `Alpha`, Wet 1 | The processed image replaces the input |
| Blend `Alpha`, Wet < 1 | A dissolve between input and processed image, chosen so keyed-out pixels stay gone |
| Any other blend, Wet < 1 | The blend is evaluated, then alpha is re-mixed between original and processed coverage |

## Blend modes

Each instance chooses one of **exactly 22** blend modes:

`Alpha, Add, 50 Add, Subtract, 50 Subtract, Multiply, 50 Multiply, Screen, Darken, Lighten,
50 Lighten, Difference, 50 Difference, Difference I, Exclusion, Overlay, 50 Overlay, Hard Light, Burn,
50 Burn, Dodge, 50 Dodge`

This is a larger set than the 14 offered for **layer** blending. The two pickers are deliberately
different: `Chaser` and `Mask` exist in the model but are rejected for effect instances.

The `…50` modes have their own fader profile: they sweep background→midpoint across the *whole* fader,
whereas the other modes reach their midpoint at Wet 0.5 and full strength at Wet 1.

## Resetting

**Reset parameters** restores the effect's documented defaults **and** Wet amount 1, blend `Alpha`, and
deletes every animation driver on that instance. It is the fast way back to a known state.

## Effect presets

**Save preset…** / **Load preset…** in the Effects tab.

- Extension `.uvjfx`, default filename `Effect stack.uvjfx`.
- Stores the **validated ordered stack**: every instance's ID, name, kind, enabled flag, parameters,
  Wet amount, blend mode, animation drivers and its descriptor.
- Maximum 1 MiB.
- **Load replaces the entire stack of the current scope.** Validation at load: at most 16 instances,
  version 1, unique IDs, every instance valid, blend among the 22, every animation key a real field of
  that kind with ranges inside the field's own.
- **Clear stack** empties the current scope.
- Loading affects that scope only, including when opened for a group.

## Preserving work you cannot read

This is a deliberate design rule worth knowing: **foreign or future effect data is never silently
substituted.**

- An instance whose payload cannot be decoded here stays in place as *unavailable*, keeps its original
  JSON, and shows *"<name> is unavailable in this build. Its saved settings are retained; bypass or
  remove it to continue."*
- A preset written by a newer version becomes opaque with *"This effect preset needs a newer app
  version…"* rather than being half-loaded.

These guards preserve unrecognized effect payloads; they do not guarantee visually identical
results across arbitrary application versions.

## Not verified

- Whether the legacy Inspector Add-effect rows other than `Glow` and `Pixelate` still work. Only those two
  were confirmed to no longer match their effect's current display name, and whether that shortcut is still
  intended to exist is unresolved.

- Current group/cue/layout/reset implementation where applicable: `Sources/VJMac/ConsoleLayerGroups.swift`, `Sources/VJMac/ConsoleRenderer.swift`.
