diff --git a/.nx/version-plans/version-plan-1780940298971.md b/.nx/version-plans/version-plan-1780940298971.md
new file mode 100644
index 00000000000..c71c5c19e33
--- /dev/null
+++ b/.nx/version-plans/version-plan-1780940298971.md
@@ -0,0 +1,5 @@
+---
+gamut: minor
+---
+
+Update ai-skills with better setup instructions + DESIGN.md generation
diff --git a/packages/gamut/agent-tools/.claude-plugin/plugin.json b/packages/gamut/agent-tools/.claude-plugin/plugin.json
index 1061b0b02f3..28d0f3ec686 100644
--- a/packages/gamut/agent-tools/.claude-plugin/plugin.json
+++ b/packages/gamut/agent-tools/.claude-plugin/plugin.json
@@ -1,6 +1,6 @@
{
"name": "gamut-design-system",
- "version": "0.0.1",
+ "version": "0.0.2",
"description": "Gamut design system agent tools: skills and rules for AI-assisted development.",
"license": "MIT",
"keywords": ["codecademy", "gamut", "design-system", "agent-skills"]
diff --git a/packages/gamut/agent-tools/.cursor-plugin/plugin.json b/packages/gamut/agent-tools/.cursor-plugin/plugin.json
index daa7f1bfab6..075b1a75d1c 100644
--- a/packages/gamut/agent-tools/.cursor-plugin/plugin.json
+++ b/packages/gamut/agent-tools/.cursor-plugin/plugin.json
@@ -1,7 +1,7 @@
{
"name": "gamut-design-system",
"displayName": "Gamut Design System",
- "version": "0.0.1",
+ "version": "0.0.2",
"description": "Gamut design system agent tools: skills and rules for AI-assisted development.",
"keywords": ["codecademy", "gamut", "design-system", "agent-skills"]
}
diff --git a/packages/gamut/agent-tools/skills/gamut-buttons/SKILL.md b/packages/gamut/agent-tools/skills/gamut-buttons/SKILL.md
index 5f50aaec562..18a5e0825df 100644
--- a/packages/gamut/agent-tools/skills/gamut-buttons/SKILL.md
+++ b/packages/gamut/agent-tools/skills/gamut-buttons/SKILL.md
@@ -87,6 +87,60 @@ Hover, active, and disabled colors are handled by the component. Do not override
- `IconButton`: provide an accessible name via `tip` (used as `aria-label` when `aria-label` is omitted). See ToolTip / IconButton Storybook pages.
- `ButtonBase` is not exported from `@codecademy/gamut` (only the `ButtonBaseElements` type is). Prefer stock atoms; custom button styling belongs in Gamut itself or via `css` / `variant` from `gamut-styles`, not by importing `ButtonBase`.
+## Focus management — buttons with ToolTip
+
+`ToolTip` opens on **hover or focus** and closes when neither is active. The two rendering paths behave differently:
+
+- **Inline (default):** CSS-only via `:hover` and `:focus-within` on the wrapper. No JS involved; tooltip visibility tracks pointer and focus state automatically.
+- **Floating (`placement="floating"`):** JS-driven. Tracks hover (`mouseenter`/`mouseleave`) and focus (`focus`/`blur`) separately with a small delay on each. Escape key always closes the tooltip by calling `.blur()` on the trigger automatically.
+
+**When the tooltip lingers after a click:** This only occurs with `FloatingTip` when the button was **keyboard-focused before the click**. `FloatingTip` keeps an `isFocused` flag; while that flag is true, `mouseleave` does not close the tooltip. If the click action does not naturally move DOM focus elsewhere, the button stays focused and the tooltip stays open.
+
+Mouse-initiated clicks do not have this problem: `TargetContainer` has `onMouseDown={(e) => e.preventDefault()}` which prevents the button from gaining focus via mouse, so `isFocused` stays `false` and the tooltip closes when the pointer moves away.
+
+**Pattern — explicit blur when focus won't move naturally:**
+
+```tsx
+const handleClick = () => {
+ (document.activeElement as HTMLElement)?.blur();
+ openPanel();
+};
+
+;
+```
+
+Or with a ref:
+
+```tsx
+const ref = useRef(null);
+
+ {
+ ref.current?.blur();
+ openPanel();
+ }}
+/>;
+```
+
+**When to apply (floating placement, keyboard-triggered clicks only):**
+
+- Click opens a modal, drawer, or panel that does NOT auto-focus an element inside it
+- Click triggers an in-place state toggle (e.g. show/hide inline editor)
+- Click dispatches a mutation with no focus side-effect
+
+**When NOT needed:**
+
+- Click opens a modal with a proper focus trap — the trap moves focus automatically, blurring the button
+- Click navigates to a new route — component unmounts
+- Click reveals a `Popover` or `FloatingTip`-managed dropdown — focus is moved by that system
+- Tooltip uses the default inline (non-floating) placement — CSS handles visibility, no lingering issue
+- User pressed Escape — built-in `escapeKeyPressHandler` already calls `.blur()`
+
+Call `.blur()` synchronously before the action; this keeps tooltip dismissal atomic with the user interaction.
+
## Rules
- Use `FillButton` for primary actions and `StrokeButton` for secondary — do not use both at equal weight on the same screen.
diff --git a/packages/gamut/agent-tools/skills/gamut-datalist/SKILL.md b/packages/gamut/agent-tools/skills/gamut-datalist/SKILL.md
new file mode 100644
index 00000000000..83a1e3e35b5
--- /dev/null
+++ b/packages/gamut/agent-tools/skills/gamut-datalist/SKILL.md
@@ -0,0 +1,274 @@
+---
+name: gamut-datalist
+description: Use this skill when building a DataList for item-focused layouts with row expansion, row selection, or rich per-item content — including expandedContent, onRowSelect, onRowExpand, variant (default/card), useLocalQuery, and empty/loading states. Do not use for bulk data comparison tables (see gamut-datatable), or for small static lists (see gamut-list).
+---
+
+# Gamut DataList
+
+Item-focused list for managing, engaging with, and expanding individual rows. Use when users interact with items — opening details, selecting for bulk actions, or viewing expanded layouts — rather than scanning and comparing data across rows.
+
+Source: `@codecademy/gamut` — [DataList.tsx](https://github.com/Codecademy/gamut/blob/main/packages/gamut/src/DataList/DataList.tsx)
+
+See also: [`gamut-datatable`](../gamut-datatable/SKILL.md) — query-focused table for bulk data comparison. [`gamut-list`](../gamut-list/SKILL.md) — lower-level list primitives for fully custom layouts. [`gamut-accessibility`](../gamut-accessibility/SKILL.md) — ARIA and keyboard interaction.
+
+Storybook: [Organisms / Lists & Tables / DataList](https://gamut.codecademy.com/?path=/docs-organisms-lists-tables-datalist--docs)
+
+## Components
+
+```tsx
+import { DataList } from '@codecademy/gamut';
+import { useLocalQuery } from '@codecademy/gamut';
+```
+
+| Symbol | Role |
+| --------------- | ---------------------------------------------------------------------------------------- |
+| `DataList` | Root component; supports expansion, selection, and card/default variants |
+| `useLocalQuery` | Client-side hook for sort/filter state; spread its return value directly into `DataList` |
+
+## When to use DataList
+
+- Users **open, expand, or engage** with individual items (content libraries, assignment lists, course catalogs).
+- Rows need **expandable detail panels** with rich layouts.
+- Users need to **select rows** for bulk actions.
+- Items contain **icons, graphics, or complex layouts** rather than plain metrics.
+- Optional filtering or sorting across shared attributes is needed at the list level.
+
+**Do not use DataList when:**
+
+- The goal is to **compare data across rows** (scores, metrics, statuses in columns) → use [`DataTable`](../gamut-datatable/SKILL.md).
+- The list is small, static, and needs fully custom row layouts → use [`List`](../gamut-list/SKILL.md) directly.
+- You need a table with horizontal scrolling → use `DataTable` (DataList is not scrollable).
+
+## Design principles
+
+- **Engage with individual items**: design each row to support the action users take on it (open, launch, select, expand).
+- **Customize items with rich content**: icons, progress indicators, graphics, and other atoms are appropriate within rows.
+- **Keep item controls visible**: action controls should be on the right side of the row.
+- **Place lists inside main containers**: avoid overflow by placing DataList in appropriately sized parent layouts.
+- **Use DataTable for comparison-first designs**: if the design is primarily about scanning data between items, reach for DataTable instead.
+
+## Variants
+
+```tsx
+
+```
+
+| `variant` | Use for |
+| --------- | ---------------------------------------------------------------------------------- |
+| `default` | Standard bordered rows; best for most item-management layouts |
+| `card` | Rows with vertical gap; best for content that doesn't need to be visually adjacent |
+
+## Props
+
+| Prop | Type | Default | Notes |
+| ----------------------- | ------------------------------------------------------ | ------------------- | ------------------------------------------------------------------------ |
+| `id` | `string` | required | Unique ID for the list |
+| `idKey` | `keyof Row` | required | Row identifier — must be a `string \| number` field |
+| `rows` | `Row[]` | required | Data array |
+| `columns` | `ColumnConfig[]` | required | Column definitions |
+| `query` | `Query` | — | Current sort/filter state |
+| `onQueryChange` | `OnQueryChange` | — | Called when sort or filter changes |
+| `selected` | `Row[IdKey][]` | — | Array of selected row IDs |
+| `onRowSelect` | `RowStateChange<'select' \| 'select-all', Row[IdKey]>` | — | Called on row or select-all toggle |
+| `expanded` | `Row[IdKey][]` | — | Array of expanded row IDs |
+| `onRowExpand` | `RowStateChange<'expand', Row[IdKey]>` | — | Called when a row is expanded or collapsed |
+| `expandedContent` | `ExpandRow` | — | Render function for expanded row content; receives `{ row, onCollapse }` |
+| `variant` | `'default' \| 'card'` | `'default'` | Row visual style |
+| `header` | `boolean` | — | Whether to show a header row |
+| `hideSelectAll` | `boolean` | `false` | Hides the select-all checkbox in the header |
+| `loading` | `boolean` | `false` | Replaces row content with shimmer placeholders |
+| `spacing` | `'condensed' \| 'normal'` | `'condensed'` | Row padding |
+| `emptyMessage` | `ReactNode` | default empty state | Rendered when `rows` is empty |
+| `disableContainerQuery` | `boolean` | `false` | Falls back to media queries instead of container queries |
+
+> DataList always sets `scrollable={false}`. For a horizontally scrollable table, use `DataTable`.
+
+## ColumnConfig
+
+Identical to DataTable — see [`gamut-datatable`](../gamut-datatable/SKILL.md#columnconfig) for the full table.
+
+## Basic usage
+
+```tsx
+import { DataList, useLocalQuery } from '@codecademy/gamut';
+
+const columns = [
+ { key: 'title', header: 'Title', size: 'md', type: 'header', fill: true },
+ { key: 'status', header: 'Status', size: 'sm' },
+];
+
+const MyList = ({ data }) => {
+ const queryData = useLocalQuery({ idKey: 'id', rows: data, columns });
+
+ return ;
+};
+```
+
+## Expandable rows
+
+Pass `expandedContent`, `expanded`, and `onRowExpand` together. The `expandedContent` render function receives `{ row, onCollapse }` — call `onCollapse` from within the expanded panel to close it programmatically.
+
+```tsx
+const [expanded, setExpanded] = useState([]);
+
+const handleExpand = ({ type, payload: { rowId, toggle } }) => {
+ if (type === 'expand') {
+ setExpanded((prev) =>
+ toggle ? prev.filter((id) => id !== rowId) : [...prev, rowId]
+ );
+ }
+};
+
+