diff --git a/site/docs/02-fundamentals/04-cameras.mdx b/site/docs/02-fundamentals/04-cameras.mdx
index 944748d3e..6082217ba 100644
--- a/site/docs/02-fundamentals/04-cameras.mdx
+++ b/site/docs/02-fundamentals/04-cameras.mdx
@@ -95,7 +95,7 @@ in-game effects.
"Lerp" is short for [Linear Interpolation](http://en.wikipedia.org/wiki/Linear_interpolation)
and it enables the camera focus to move smoothly between two points using timing functions.
-Use [[Camera.move]] to ease to a specific point using a provided [[EasingFunction]].
+Use [[Camera.move]] to ease to a specific point using a provided [[Util.EasingFunction|EasingFunction]].
```typescript
export interface EasingFunction {
diff --git a/site/docs/05-entity-component-system/05-entity-component-system.mdx b/site/docs/05-entity-component-system/05-entity-component-system.mdx
index 13a3338d9..42e4b1025 100644
--- a/site/docs/05-entity-component-system/05-entity-component-system.mdx
+++ b/site/docs/05-entity-component-system/05-entity-component-system.mdx
@@ -26,7 +26,7 @@ pieces live and can interact together. Each [[Scene]] in Excalibur contains an E
Inside an ECS [[World]] there is an [[EntityManager]], [[QueryManager]], and [[SystemManager]] that handle all the details.
-- [[EntityManager]] - Manages all the entities known by the world, it is an [[Observer]] of entity component changes over time.
+- [[EntityManager]] - Manages all the entities known by the world, it is an [[Util.Observer|Observer]] of entity component changes over time.
- [[QueryManager]] - Manages all the entity queries, a [[Query]] allows a search of all known entities by a set of component types.
- [[SystemManager]] - Manages all the systems known by the world, it updates a [[System]] in priority order (low to high) and gives them a set of entities that match types.
diff --git a/site/docs/10-physics/08-colliders.mdx b/site/docs/10-physics/08-colliders.mdx
index f5c47dadb..0d8927888 100644
--- a/site/docs/10-physics/08-colliders.mdx
+++ b/site/docs/10-physics/08-colliders.mdx
@@ -7,7 +7,7 @@ section: Physics
Colliders are abstractions over geometry in Excalibur, they implement the [[Collider]] interface and know how
to detect intersecions with other colliders, test ray casts, check point containment, etc. Related but not the same are [bodies](/docs/bodies) which are abstractions over the collision response
-Colliders attached to an [[Entity]] will have a [[Entity.owner]] populated.
+Colliders attached to an [[Entity]] will have a [[Component.owner|owner]] populated.
:::note
diff --git a/site/docs/11-input/10.3-pointer.mdx b/site/docs/11-input/10.3-pointer.mdx
index a9ccf3745..a191d081c 100644
--- a/site/docs/11-input/10.3-pointer.mdx
+++ b/site/docs/11-input/10.3-pointer.mdx
@@ -1,162 +1,196 @@
---
-title: Pointers
+title: Mouse and Touch
slug: /pointers
section: Input
---
-## Mouse and Touch
+```twoslash include ex
+///
+declare const engine: ex.Engine;
+```
+
+Excalibur handles mouse and touch input by abstracting event handling into a [[Engine.input|engine.input.pointers]] API that closely follows the [W3C Pointer Events](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events) spec. Excalibur normalizes both mouse and touch events to a single [[Input.PointerEvent|PointerEvent]]
+that your game can subscribe to and handle.
-Excalibur handles mouse and touch input using a [[Pointers]] API that closely follows the [W3C Pointer Events](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events) spec. Excalibur normalizes mouse and touch events to a [[PointerEvent]]
-that your game can subscribe to and handle ([[Engine.input|engine.input.pointers]]`).
+## The Primary Pointer
-There is always at least one [[Pointer]] available ([[Pointers.primary]]) and
+There is always at least one [[PointerAbstraction|Pointer]] available ([[Input.PointerEventReceiver.primary|engine.input.pointers.primary]]) and
you can request multiple pointers to support multi-touch scenarios.
-Since [[Pointers.primary]] normalizes both mouse and touch events, your game
+```ts twoslash
+// @include: ex
+// ---cut---
+engine.input.pointers.primary;
+```
+
+Since a pointer normalizes both mouse and touch events, your game
automatically supports touch for the primary pointer by default. When
you handle the events, you can customize what your game does based on the type
of pointer, if applicable.
-:::note
+## Handling Pointer Events Globally
+
+You can subscribe (or unsubscribe) to pointer events multiple ways using the [[Input.PointerEventReceiver.on|on]], [[Input.PointerEventReceiver.once|once]], or [[Input.PointerEventReceiver.off|off]] methods. Each method takes two arguments: the event name and the handler.
-For performance reasons,
+```ts twoslash
+// @include: ex
+// @noErrors
+// ---cut---
-
+engine.input.pointers.primary.o
+// ^|
-actors do not automatically capture pointer events
-
+```
-until they are opted-in
+You can subscribe to the primary pointer, all pointers, or a specific pointer.
-
+```ts twoslash
+// @include: ex
+// ---cut---
-.
+// Subscribe to the primary pointer
+engine.input.pointers.primary.on;
+// ^?
-
+// Subscribe to a specific pointer (multi-touch)
+engine.input.pointers.at(1).on;
+// ^?
-:::
+// Subscribe to all pointers (advanced)
+engine.input.pointers.on;
+// ^?
+```
-### Pointer Events
+### Event Names
-You can subscribe to pointer events through `engine.input.pointers.on`. A [[PointerEvent]] object is
-passed to your handler which offers information about the pointer input being received.
+The event name is a string and can be one of the following:
- `down` - When a pointer is pressed down (any mouse button or finger press)
- `up` - When a pointer is lifted
- `move` - When a pointer moves (be wary of performance issues when subscribing to this)
- `cancel` - When a pointer event is canceled for some reason
+- `wheel` - When a mousewheel is activated (trackpad scroll or mouse wheel)
+
+### Event Handlers
-```js
+A [[Input.PointerEvent|PointerEvent]] object (or in the case of `wheel`, a [[Input.WheelEvent|WheelEvent]]) is
+passed to your handler which offers information about the pointer input being received.
+
+```ts twoslash
+// @include: ex
+// ---cut---
+
+// Subscribe to the primary pointer
engine.input.pointers.primary.on('down', function (evt) {});
+// ^?
engine.input.pointers.primary.on('up', function (evt) {});
engine.input.pointers.primary.on('move', function (evt) {});
engine.input.pointers.primary.on('cancel', function (evt) {});
-```
-
-#### Wheel Event
-
-You can also subscribe to the mouse wheel event through `engine.input.pointers.on`. A [[WheelEvent]]
-object is passed to your handler which offers information about the wheel event being received.
-
-- `wheel` - When a mousewheel is activated (trackpad scroll or mouse wheel)
-
-```js
+engine.input.pointers.primary.on('wheel', function (evt) {});
+// ^?
+
+// Subscribe to a specific pointer (multi-touch)
+engine.input.pointers.at(1).on('down', function (evt) {});
+engine.input.pointers.at(1).on('up', function (evt) {});
+engine.input.pointers.at(1).on('move', function (evt) {});
+engine.input.pointers.at(1).on('cancel', function (evt) {});
+engine.input.pointers.at(1).on('wheel', function (evt) {});
+
+// Subscribe to all pointers (advanced)
+engine.input.pointers.on('down', function (evt) {});
+engine.input.pointers.on('up', function (evt) {});
+engine.input.pointers.on('move', function (evt) {});
+engine.input.pointers.on('cancel', function (evt) {});
engine.input.pointers.on('wheel', function (evt) {});
```
-### Last position querying
+### Querying the Last Position
-If you don't wish to subscribe to events, you can also access the [[Pointer.lastPagePos]], [[Pointer.lastScreenPos]]
-or [[Pointer.lastWorldPos]] coordinates ([[Vector]]) on the pointer you're targeting.
+If you don't wish to subscribe to events, you can also access the [[PointerAbstraction.lastPagePos]], [[PointerAbstraction.lastScreenPos]]
+or [[PointerAbstraction.lastWorldPos]] coordinates ([[Vector]]) on the pointer you're targeting.
-```js
+```ts twoslash
+// @include: ex
+// ---cut---
engine.input.pointers.primary.lastPagePos;
engine.input.pointers.primary.lastScreenPos;
engine.input.pointers.primary.lastWorldPos;
```
-Note that the value may be `null` if the Pointer was not active the last frame.
-
-### Pointer scope (window vs. canvas)
+:::note
+The value may be `null` if the Pointer was not active the last frame.
+:::
-You have the option to handle _all_ pointer events in the browser by setting
-[[EngineOptions.pointerScope]] to [[PointerScope.Document]]. If this is enabled,
+### Scoping Events to Canvas vs. Document
-Excalibur will handle every pointer event in the browser. This is useful for handling
-complex input and having control over every interaction.
+You can customize how pointer events are handled by setting the [[EngineOptions.pointerScope]] option when creating a new [[Engine]] instance, like this:
-You can also use [[PointerScope.Canvas]] to only scope event handling to the game
-canvas. This is useful if you don't care about events that occur outside the game.
+```ts twoslash
+// @noErrors
+///
+// ---cut---
+const game = new ex.Engine({
+ pointerScope: ex.Input.PointerScope.C
+// ^|
+});
+```
-One real-world example is dragging and gestures. Sometimes a player will drag their
-finger outside your game and then into it, expecting it to work. If [[PointerScope]]
-is set to [[PointerScope.Canvas|Canvas]] this will not work. If it is set to
-[[PointerScope.Document|Document]], it will.
+The default scope is [[Input.PointerScope.Canvas|PointerScope.Canvas]]. For many games, this works really well. It scopes event handling to the game canvas.
-### Responding to input
+This is useful if you don't care about events that occur outside the game.
-The primary pointer can be a mouse, stylus, or single finger touch event. You
-can inspect what type of pointer it is from the [[PointerEvent]] handled.
+You also have the option to handle _all_ pointer events in the browser window by using [[Input.PointerScope.Document|PointerScope.Document]], like this:
-```js
-engine.input.pointers.primary.on('down', function (pe) {
- if (pe.pointerType === ex.Input.PointerType.Mouse) {
- ex.Logger.getInstance().info('Mouse event:', pe);
- } else if (pe.pointerType === ex.Input.PointerType.Touch) {
- ex.Logger.getInstance().info('Touch event:', pe);
- }
+```ts twoslash
+// @noErrors
+///
+// ---cut---
+const game = new ex.Engine({
+ pointerScope: ex.Input.PointerScope.D
+// ^|
});
```
-### Multiple Pointers (Multi-Touch)
+This is useful for handling complex input and having control over every interaction.
-When there is more than one pointer detected on the screen,
-this is considered multi-touch. For example, pressing one finger,
-then another, will create two pointers. If you lift a finger,
-the first one remains and the second one disappears.
+:::note When to Use Document Scope
-You can handle multi-touch by subscribing to however many pointers
-you would like to support. If a pointer doesn't yet exist, it will
-be created. You do not need to check if a pointer exists. If it does
-exist, it will propagate events, otherwise it will remain idle.
+One real-world example is dragging and gestures. Sometimes a player will drag their
+finger outside your game and then into it, expecting it to work. If [[Input.PointerScope|PointerScope]]
+is set to [[Input.PointerScope.Canvas|Canvas]] this will not work. If it is set to
+[[Input.PointerScope.Document|Document]], it will.
-Excalibur does not impose a limit to the amount of pointers you can
-subscribe to, so by all means, support all 10 fingers.
+:::
-_Note:_ There is no way to identify touches after they happen; you can only
-know that there are _n_ touches on the screen at once.
+:::info What about HTML elements?
+`PointerScope.Canvas` does not affect handling native HTML events like `click`, `mouseover`, `mouseout`, etc. on any HTML-based UI. It only applies to pointer events that are targeted to the HTML `