diff --git a/docs.json b/docs.json
index 63bcc930..7dc0e7f4 100644
--- a/docs.json
+++ b/docs.json
@@ -494,6 +494,8 @@
"scripting/api-reference/interfaces/property-enum",
"scripting/api-reference/interfaces/property-list",
"scripting/api-reference/interfaces/property-view-model",
+ "scripting/api-reference/interfaces/transition",
+ "scripting/api-reference/interfaces/transition-child",
"scripting/api-reference/interfaces/transition-condition",
"scripting/api-reference/interfaces/trigger",
"scripting/api-reference/interfaces/view-model"
diff --git a/scripting/api-reference/interfaces/transition-child.mdx b/scripting/api-reference/interfaces/transition-child.mdx
new file mode 100644
index 00000000..0143a9ec
--- /dev/null
+++ b/scripting/api-reference/interfaces/transition-child.mdx
@@ -0,0 +1,37 @@
+---
+title: TransitionChild
+---
+
+A handle to one child (a nested artboard) of a Transition, valid only for
+the duration of the `draw` (and `changed`) call it is passed to. Draw it
+with `child:draw(renderer)`, wrapping the call in renderer state
+(save / modulateOpacity / transform / clipPath / restore) to author the
+transition effect.
+
+
+## Fields
+
+### `width`
+
+The child artboard's natural width, useful for slide/scale math.
+
+
+### `height`
+
+The child artboard's natural height.
+
+
+## Methods
+
+### `draw`
+
+{/* draw: (self: TransitionChild, renderer: Renderer) -> () */}
+
+```lua
+draw(renderer: Renderer) -> ()
+```
+
+
+Draw this child's content at the renderer's current transform.
+
+
diff --git a/scripting/api-reference/interfaces/transition.mdx b/scripting/api-reference/interfaces/transition.mdx
new file mode 100644
index 00000000..284fc49a
--- /dev/null
+++ b/scripting/api-reference/interfaces/transition.mdx
@@ -0,0 +1,87 @@
+---
+title: Transition
+---
+
+Renders the visual change between an outgoing ("from") and incoming ("to")
+child when a Transition's active child changes. The active child is chosen
+natively (and is data-bindable, Solo-style); the script owns only how the
+two children are composited. Declare any inputs you need (e.g. a director
+Artboard, numbers, curves) as ordinary script inputs and drive the effect
+however you like.
+
+For more information, see [Transition Scripts](/scripting/protocols/transition-scripts).
+
+
+## Fields
+
+### `managesTo`
+
+When false, the incoming ("to") child renders normally through the
+artboard draw loop and is passed as nil to draw; the script composites
+only the outgoing ("from") child (useful for "reveal" transitions where
+the new content is already on-stage). Defaults to true (the script
+composites both children). Read at the start of each transition, so it
+may be set in init or changed.
+
+
+## Methods
+
+### `init`
+
+{/* init: ((self: T, context: Context) -> boolean)? */}
+
+```lua
+init(self: T, context: Context) -> boolean
+```
+
+
+Called once when the transition is created.
+
+
+### `changed`
+
+{/* changed: ((self: T, from: TransitionChild?, to: TransitionChild?, direction: number) -> ())? */}
+
+```lua
+changed(self: T, from: TransitionChild?, to: TransitionChild?, direction: number) -> ()
+```
+
+
+Called when the active child changes. `from` is the outgoing child
+(nil on the first show); `to` is the incoming child. `direction` is 1
+when `to` is at a higher combined index than `from`, -1 when lower, and
+0 when unknown (e.g. the first show). Reset your progress clock / seek
+any input you drive here. Called again on interruption, where `from` is
+the previously-incoming child.
+
+
+### `advance`
+
+{/* advance: (self: T, seconds: number) -> boolean */}
+
+```lua
+advance(self: T, seconds: number) -> boolean
+```
+
+
+Called every frame while a transition is in flight. Advance your own
+progress (and any input you drive). Return true while running; return
+false to signal completion, after which the runtime retires the
+outgoing child and resumes drawing the active child normally.
+
+
+### `draw`
+
+{/* draw: (self: T, renderer: Renderer, from: TransitionChild?, to: TransitionChild?) -> () */}
+
+```lua
+draw(self: T, renderer: Renderer, from: TransitionChild?, to: TransitionChild?) -> ()
+```
+
+
+Composite the two children. Wrap each `child:draw(renderer)` in renderer
+state (save / modulateOpacity / transform / clipPath / restore) to
+author crossfade, slide, wipe, scale, and custom effects. Either child
+may be nil (see `managesTo`).
+
+
diff --git a/scripting/api-reference/renderer/renderer.mdx b/scripting/api-reference/renderer/renderer.mdx
index 0a6317e1..ca16ff26 100644
--- a/scripting/api-reference/renderer/renderer.mdx
+++ b/scripting/api-reference/renderer/renderer.mdx
@@ -202,3 +202,18 @@ end
```
+### `modulateOpacity`
+
+{/* function modulateOpacity(self, opacity: number): () */}
+
+```lua
+modulateOpacity(opacity: number) -> ()
+```
+
+
+Multiplies the opacity of subsequent draw calls by `opacity` (0..1).
+Stacks multiplicatively and is captured by save()/restore(), so the
+common pattern is: renderer:save(); renderer:modulateOpacity(a);
+... draw ...; renderer:restore().
+
+