diff --git a/README.md b/README.md
index f96372f..19c0060 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,8 @@ Agents use each skill when the task matches the skill’s `description` (e.g.
| **gsap-core** | Core API: `gsap.to()` / `from()` / `fromTo()`, easing, duration, stagger, defaults |
| **gsap-timeline** | Timelines: sequencing, position parameter, labels, nesting, playback |
| **gsap-scrolltrigger** | ScrollTrigger: scroll-linked animations, pinning, scrub, triggers, refresh & cleanup |
+| **gsap-plugins** | Plugins: ScrollToPlugin, ScrollSmoother, Flip, Draggable, Inertia, Observer, SplitText, ScrambleText, SVG & physics plugins, CustomEase, EasePack, GSDevTools, etc. |
+| **gsap-utils** | gsap.utils: clamp, mapRange, normalize, interpolate, random, snap, toArray, selector, wrap, pipe, and other helpers |
| **gsap-react** | React: useGSAP hook, refs, `gsap.context()`, cleanup, SSR |
| **gsap-performance** | Performance: transforms over layout props, will-change, batching, ScrollTrigger tips |
@@ -46,6 +48,8 @@ gsap-skills/
gsap-core/ SKILL.md
gsap-timeline/ SKILL.md
gsap-scrolltrigger/ SKILL.md
+ gsap-plugins/ SKILL.md
+ gsap-utils/ SKILL.md
gsap-react/ SKILL.md
gsap-performance/ SKILL.md
```
diff --git a/skills/gsap-plugins/SKILL.md b/skills/gsap-plugins/SKILL.md
new file mode 100644
index 0000000..981bd16
--- /dev/null
+++ b/skills/gsap-plugins/SKILL.md
@@ -0,0 +1,235 @@
+---
+name: gsap-plugins
+description: Use GSAP plugins correctly — registration, ScrollToPlugin, ScrollSmoother, Flip, Draggable, Inertia, Observer, SplitText, ScrambleText, SVG and physics plugins, CustomEase, EasePack, CustomWiggle, CustomBounce, GSDevTools. Use when the user asks about a GSAP plugin, scroll-to, flip animations, draggable, SVG drawing, or plugin registration.
+license: MIT
+---
+
+# GSAP Plugins
+
+## When to Use This Skill
+
+Apply when using or reviewing code that uses GSAP plugins: registering plugins, scroll-to, flip/FLIP animations, draggable elements, SVG (DrawSVG, MorphSVG, MotionPath), text (SplitText, ScrambleText), physics, easing plugins (CustomEase, EasePack, CustomWiggle, CustomBounce), or GSDevTools. ScrollTrigger has its own skill (gsap-scrolltrigger).
+
+## Registering Plugins
+
+Register each plugin once so GSAP (and bundlers) know to include it. Use **gsap.registerPlugin()** with every plugin used in the project:
+
+```javascript
+import gsap from "gsap";
+import { ScrollToPlugin } from "gsap/ScrollToPlugin";
+import { Flip } from "gsap/Flip";
+import { Draggable } from "gsap/Draggable";
+
+gsap.registerPlugin(ScrollToPlugin, Flip, Draggable);
+```
+
+- Register before using the plugin in any tween or API call.
+- In React, register at top level or once in the app (e.g. before first useGSAP); do not register inside a component that re-renders. useGSAP is a plugin that needs to be registered before use.
+
+## Scroll
+
+### ScrollToPlugin
+
+Animates scroll position (window or a scrollable element). Use for “scroll to element” or “scroll to position” without ScrollTrigger.
+
+```javascript
+gsap.registerPlugin(ScrollToPlugin);
+
+gsap.to(window, { duration: 1, scrollTo: { y: 500 } });
+gsap.to(window, { duration: 1, scrollTo: { y: "#section", offsetY: 50 } });
+gsap.to(scrollContainer, { duration: 1, scrollTo: { x: "max" } });
+```
+
+- **scrollTo**: `{ x, y, element, offsetX, offsetY }`. Use `"max"` for maximum scroll. Element can be selector or numeric position.
+
+### ScrollSmoother
+
+Smooth scroll wrapper (smooths native scroll). Requires ScrollTrigger and a specific DOM structure (content wrapper + smooth wrapper). Use when smooth, momentum-style scroll is needed. See GSAP docs for setup; register after ScrollTrigger. DOM structure would look like:
+
+```html
+
+
+
+
+```
+
+## DOM / UI
+
+### Flip
+
+Capture state with `Flip.getState()`, then apply changes (e.g. layout or class changes), then use `Flip.from()` to animate from the previous state to the new state (FLIP: First, Last, Invert, Play). Use when animating between two layout states (lists, grids, expanded/collapsed).
+
+```javascript
+gsap.registerPlugin(Flip);
+
+const state = Flip.getState(".item");
+// change DOM (reorder, add/remove, change classes)
+Flip.from(state, { duration: 0.5, ease: "power2.inOut" });
+```
+
+- **Flip.getState()** — pass element(s) or selector; returns state object.
+- **Flip.from(state, vars)** — animate from that state to current layout. Options: `absolute`, `nested`, `scale`, `simple`, etc.
+
+#### More information
+
+https://gsap.com/docs/v3/Plugins/Flip
+
+### Draggable
+
+Makes elements draggable, spinnable, or throwable with mouse/touch. Use for sliders, cards, reorderable lists, or any drag interaction.
+
+```javascript
+gsap.registerPlugin(Draggable, InertiaPlugin);
+
+Draggable.create(".box", { type: "x,y", bounds: "#container", inertia: true });
+Draggable.create(".knob", { type: "rotation" });
+```
+
+- **type**: `"x"`, `"y"`, `"x,y"`, `"rotation"`, etc.
+- **bounds**: element or `{ minX, maxX, minY, maxY }`.
+- **inertia**: boolean; uses InertiaPlugin if true (requires InertiaPlugin registered).
+- Events: **onDragStart**, **onDrag**, **onDragEnd**, **onThrowUpdate**, **onThrowComplete**.
+
+### Inertia (InertiaPlugin)
+
+Works with Draggable for momentum after release, or track the inertia/velocity of any property of any object so that it can then seamlessly glide to a stop using a simple tween. Register with Draggable when using `inertia: true`:
+
+```javascript
+gsap.registerPlugin(Draggable, InertiaPlugin);
+Draggable.create(".box", { type: "x,y", inertia: true });
+```
+
+Or track velocity of a property:
+```javascript
+InertiaPlugin.track(".box", "x");
+```
+
+Then use `"auto"` to continue the current velocity and glide to a stop:
+
+```javascript
+gsap.to(obj, { inertia: { x: "auto" } });
+```
+
+### Observer
+
+Normalizes pointer and scroll input across devices. Use for swipe, scroll direction, or custom gesture logic without tying directly to scroll position like ScrollTrigger.
+
+```javascript
+gsap.registerPlugin(Observer);
+
+Observer.create({
+ target: "#area",
+ onUp: () => {},
+ onDown: () => {},
+ onLeft: () => {},
+ onRight: () => {},
+ tolerance: 10
+});
+```
+
+## Text
+
+### SplitText
+
+Splits text into chars, words, or lines for staggered or per-char animation. Use when animating text character-by-character or word-by-word. Restores original text on `revert()`; or let `gsap.context()` revert.
+
+### ScrambleText
+
+Animates text with a scramble/glitch effect. Use when revealing or transitioning text with a scramble.
+
+## SVG
+
+### DrawSVG (DrawSVGPlugin)
+
+Animates SVG stroke dash (draw/undraw strokes). Use when “drawing” or “erasing” SVG paths.
+
+```javascript
+gsap.registerPlugin(DrawSVGPlugin);
+
+gsap.fromTo("#path", { drawSVG: "0% 0%" }, { drawSVG: "0% 100%", duration: 1 });
+```
+
+### MorphSVG (MorphSVGPlugin)
+
+Morphs one SVG shape into another. Use when morphing paths (e.g. icon A → icon B). Uses path data; shapes do not need to have the same number of points; they're converted to cubic beziers internally and points are added as necessary.
+
+### MotionPath (MotionPathPlugin)
+
+Animates an element along an SVG path. Use when moving an object along a path (e.g. a curve or custom route).
+
+```javascript
+gsap.registerPlugin(MotionPathPlugin);
+
+gsap.to(".dot", {
+ duration: 2,
+ motionPath: { path: "#path", align: "#path", alignOrigin: [0.5, 0.5] }
+});
+```
+
+### MotionPathHelper
+
+Visual editor for MotionPath (alignment, offset). Use during development to tune path alignment.
+
+## Easing
+
+### CustomEase
+
+Custom easing curves (cubic-bezier or SVG path). Use when a built-in ease is not enough. Basic usage is covered in gsap-core; register when using:
+
+```javascript
+gsap.registerPlugin(CustomEase);
+const ease = CustomEase.create("name", ".17,.67,.83,.67");
+gsap.to(".el", { x: 100, ease: ease, duration: 1 });
+```
+
+### EasePack
+
+Adds more named eases (e.g. SlowMo, RoughEase, ExpoScaleEase). Register and use the ease names in tweens.
+
+### CustomWiggle
+
+Wiggle/shake easing. Use when a value should “wiggle” (multiple oscillations).
+
+### CustomBounce
+
+Bounce-style easing with configurable strength.
+
+## Physics
+
+### Physics2D (Physics2DPlugin)
+
+2D physics (velocity, angle, gravity). Use when animating with simple physics (e.g. projectiles, bouncing).
+
+### PhysicsProps (PhysicsPropsPlugin)
+
+Applies physics to property values. Use for physics-driven property animation.
+
+## Development
+
+### GSDevTools
+
+UI for scrubbing timelines, toggling animations, and debugging. Use during development only; do not ship. Register and create an instance with a timeline reference.
+
+```javascript
+gsap.registerPlugin(GSDevTools);
+GSDevTools.create({ animation: tl });
+```
+
+## Other
+
+### Pixi (PixiPlugin)
+
+Integrates GSAP with PixiJS for animating Pixi display objects. Register when animating Pixi objects with GSAP.
+
+## Do Not
+
+- Use a plugin in a tween or API without registering it first (**gsap.registerPlugin()**).
+- Ship GSDevTools or development-only plugins to production.
+
+### Learn More
+
+https://gsap.com/docs/v3/Plugins/
diff --git a/skills/gsap-utils/SKILL.md b/skills/gsap-utils/SKILL.md
new file mode 100644
index 0000000..ef5941b
--- /dev/null
+++ b/skills/gsap-utils/SKILL.md
@@ -0,0 +1,190 @@
+---
+name: gsap-utils
+description: Use gsap.utils for clamping, distribution, interpolation, mapping, random, snapping, arrays, and strings. Use when the user asks about gsap.utils, clamp, mapRange, random, snap, toArray, wrap, or helper utilities in GSAP.
+license: MIT
+---
+
+# gsap.utils
+
+## When to Use This Skill
+
+Apply when writing or reviewing code that uses **gsap.utils** for math, array/collection handling, unit parsing, or value mapping in animations (e.g. mapping scroll to a value, randomizing, snapping to a grid, or normalizing inputs).
+
+## Overview
+
+**gsap.utils** provides pure helpers; no need to register. Use in tween vars (e.g. function-based values), in ScrollTrigger or Observer callbacks, or in any JS that drives GSAP. All are on **gsap.utils** (e.g. `gsap.utils.clamp()`).
+
+## Clamping and Ranges
+
+### clamp(min, max, value)
+
+Constrains a value between min and max.
+
+```javascript
+gsap.utils.clamp(0, 100, 150); // 100
+gsap.utils.clamp(0, 100, -10); // 0
+```
+
+### mapRange(inMin, inMax, outMin, outMax, value)
+
+Maps a value from one range to another. Use when converting scroll position, progress (0–1), or input range to an animation range.
+
+```javascript
+gsap.utils.mapRange(0, 100, 0, 500, 50); // 250
+gsap.utils.mapRange(0, 1, 0, 360, 0.5); // 180 (progress to degrees)
+```
+
+### normalize(min, max, value)
+
+Returns a value normalized to 0–1 for the given range. Inverse of mapping when the target range is 0–1.
+
+```javascript
+gsap.utils.normalize(0, 100, 50); // 0.5
+gsap.utils.normalize(100, 300, 200); // 0.5
+```
+
+### interpolate(start, end, progress)
+
+Interpolates between two values at a given progress (0–1). Handles numbers, colors, and objects with matching keys.
+
+```javascript
+gsap.utils.interpolate(0, 100, 0.5); // 50
+gsap.utils.interpolate("#ff0000", "#0000ff", 0.5); // mid color
+gsap.utils.interpolate({ x: 0, y: 0 }, { x: 100, y: 50 }, 0.5); // { x: 50, y: 25 }
+```
+
+## Random and Snap
+
+### random(min, max, increment?)
+
+Returns a random number between min and max. Optional **increment** snaps to steps (e.g. `increment: 1` for integers).
+
+```javascript
+gsap.utils.random(10, 20); // e.g. 14.3
+gsap.utils.random(1, 10, 1); // integer 1–10
+gsap.utils.random(-100, 100, 10); // -100, -90, ..., 100
+```
+
+### snap(snapTo, value)
+
+Snaps a value to the nearest multiple of **snapTo**, or to the nearest value in an array of allowed values.
+
+```javascript
+gsap.utils.snap(10, 23); // 20
+gsap.utils.snap(0.25, 0.7); // 0.75
+gsap.utils.snap([0, 100, 200], 150); // 100 or 200 (nearest in array)
+```
+
+Use in tweens for grid or step-based animation:
+
+```javascript
+gsap.to(".x", { x: 200, snap: { x: 20 } });
+```
+
+### shuffle(array)
+
+Returns a new array with the same elements in random order. Use for randomizing order (e.g. stagger from "random" with a copy).
+
+```javascript
+gsap.utils.shuffle([1, 2, 3, 4]); // e.g. [3, 1, 4, 2]
+```
+
+### distribute(baseObject)
+
+Distributes values across a range (e.g. for positioning many elements). Returns a function that, given an index and total, returns a value in the range. See GSAP docs for **base**, **amount**, **from**, **grid**, etc.
+
+```javascript
+const dist = gsap.utils.distribute({ base: 0, amount: 100, from: "center" });
+dist(0, 5); // value for index 0 of 5
+dist(2, 5); // value for index 2 of 5
+```
+
+## Units and Parsing
+
+### getUnit(value)
+
+Returns the unit string of a value (e.g. `"px"`, `"%"`, `"deg"`). Use when normalizing or converting values.
+
+```javascript
+gsap.utils.getUnit("100px"); // "px"
+gsap.utils.getUnit("50%"); // "%"
+gsap.utils.getUnit(42); // "" (unitless)
+```
+
+### unitize(value, unit)
+
+Appends a unit to a number, or returns the value as-is if it already has a unit. Use when building CSS values or tween end values.
+
+```javascript
+gsap.utils.unitize(100, "px"); // "100px"
+gsap.utils.unitize("2rem", "px"); // "2rem" (unchanged)
+```
+
+### splitColor(color)
+
+Splits a color string into RGB components (0–255) or an array. Use when animating color components or building gradients.
+
+```javascript
+gsap.utils.splitColor("#ff0000"); // [255, 0, 0] or similar
+```
+
+## Arrays and Collections
+
+### selector(scope)
+
+Returns a scoped selector function that finds elements only within the given element (or ref). Use in components so selectors like `".box"` match only descendants of that component, not the whole document. Accepts a DOM element or a ref (e.g. React ref; handles `.current`).
+
+```javascript
+const q = gsap.utils.selector(containerRef);
+q(".box"); // array of .box elements inside container
+gsap.to(q(".circle"), { x: 100 });
+```
+
+### toArray(value, scope?)
+
+Converts a value to an array: selector string (scoped to element), NodeList, HTMLCollection, single element, or array. Use when passing mixed inputs to GSAP (e.g. targets) and a true array is needed.
+
+```javascript
+gsap.utils.toArray(".item"); // array of elements
+gsap.utils.toArray(".item", container); // scoped to container
+gsap.utils.toArray(nodeList); // [ ... ] from NodeList
+```
+
+### pipe(...functions)
+
+Composes functions: **pipe(f1, f2, f3)(value)** returns f3(f2(f1(value))). Use when applying a chain of transforms (e.g. normalize → mapRange → snap) in a tween or callback.
+
+```javascript
+const fn = gsap.utils.pipe(
+ (v) => gsap.utils.normalize(0, 100, v),
+ (v) => gsap.utils.snap(0.1, v)
+);
+fn(50); // normalized then snapped
+```
+
+### wrap(min, max, value)
+
+Wraps a value into the range min–max (inclusive min, exclusive max). Use for infinite scroll or cyclic values.
+
+```javascript
+gsap.utils.wrap(0, 360, 370); // 10
+gsap.utils.wrap(0, 360, -10); // 350
+```
+
+### wrapYoyo(min, max, value)
+
+Wraps value in range with a yoyo (bounces at ends). Use for back-and-forth within a range.
+
+```javascript
+gsap.utils.wrapYoyo(0, 100, 150); // 50 (bounces back)
+```
+
+## Do Not
+
+- Use **gsap.utils** for DOM queries when a simple selector or ref is enough; **toArray** is for when GSAP or your code needs a real array.
+- Assume **mapRange** / **normalize** handle units; they work on numbers. Use **getUnit** / **unitize** when units matter.
+- Override or rely on undocumented behavior; stick to the documented API.
+
+### Learn More
+
+https://gsap.com/docs/v3/HelperFunctions