diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..e5f874b
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,71 @@
+# Wind UI — Tailwind-Inspired Flutter Styling Framework
+
+Utility-first Flutter UI plugin. Translates `className` strings (Tailwind syntax) into Flutter widget trees via modular parsing architecture.
+
+**Dart:** >=3.4.0 · **Flutter:** >=3.27.0
+
+## Architecture
+
+```
+lib/src/
+├── widgets/ # 20 W-prefix widgets (WDiv, WText, WButton, WSvg, WDynamic...)
+├── parser/
+│ ├── wind_parser.dart # Orchestrator — routes tokens to 17 parsers
+│ ├── wind_style.dart # Immutable style value object (parse output)
+│ ├── wind_context.dart # Theme + breakpoint + brightness + platform + states
+│ └── parsers/ # 17 domain parsers (bg, border, flex, text, shadow...)
+├── theme/
+│ ├── wind_theme.dart # WindTheme widget + WindThemeController
+│ ├── wind_theme_data.dart # Config: colors, screens, spacing, fonts
+│ └── defaults/ # 16 default token scales
+├── dynamic/ # WDynamic — JSON → widget tree (server-driven UI)
+├── state/ # WindAnchorStateProvider (hover/focus/press via InheritedWidget)
+└── utils/ # Extensions, helpers, color utils, logger
+```
+
+**Data flow:** `className` → WindParser.parse() → 17 parsers (first-match-wins) → WindStyle → Widget.build()
+
+**Cache key:** className + breakpoint + brightness + platform + sorted states
+
+## Key Conventions
+
+- All widgets use `W` prefix: `WDiv`, `WButton`, `WText`, `WFormInput`, `WSvg`
+- `className` is the primary styling API — takes precedence over explicit style properties
+- `child` XOR `children` — never both
+- Last class wins — later classes override earlier ones for same property
+- Spacing scale: N * 4px (`p-4` = 16px, `gap-2` = 8px)
+- Arbitrary values: bracket syntax `w-[200px]`, `text-[#FF0000]`
+- TDD — failing test first, red-green-refactor
+- Zero tolerance — linter zero warnings, no suppressions
+
+## Key Gotchas
+
+| Mistake | Fix |
+|---------|-----|
+| `className: 'flex-wrap'` | Use `wrap gap-2` — flex-wrap is a no-op |
+| `WDiv(child: x, children: [...])` | `child` XOR `children`, never both |
+| `overflow-y-auto` without `scrollPrimary: true` | Add it for iOS tap-to-top |
+| `w-full` inside Row/flex-row | Use `flex-1` — w-full causes overflow |
+| No `dark:` variant on colors | **Always** pair: `bg-white dark:bg-gray-800` |
+| `WIcon(Icons.settings)` | Use `Icons.settings_outlined` — outlined only |
+| className typo | Fails silently — parser ignores unknown tokens |
+| `h-full` inside scrollable parent | Use `min-h-screen` — h-full = infinite height error |
+| Forgetting `WindParser.clearCache()` in tests | Cache persists between tests |
+
+## Post-Change Checklist
+
+After ANY source code change, sync before committing:
+
+1. **`doc/`** — Update relevant documentation files
+2. **`skills/wind-ui/`** — Update SKILL.md and references if API/widget changes
+3. **`example/lib/pages/`** — Update or create demo pages
+4. **`CHANGELOG.md`** — Add entry under `[Unreleased]`
+5. **`README.md`** — Update if new widgets, features, or API changes
+
+## Parser Development
+
+1. Find parser in `lib/src/parser/parsers/` (or create new one implementing `WindParserInterface`)
+2. Add property to `WindStyle` if needed (immutable — use `copyWith`)
+3. Write failing test first in `test/parser/parsers/{name}_parser_test.dart`
+4. Implement in parser
+5. Run post-change checklist
diff --git a/.github/instructions/docs.instructions.md b/.github/instructions/docs.instructions.md
new file mode 100644
index 0000000..5ae8705
--- /dev/null
+++ b/.github/instructions/docs.instructions.md
@@ -0,0 +1,28 @@
+---
+name: 'Documentation Conventions'
+description: 'Formatting rules for Wind framework documentation files in doc/'
+applyTo: 'doc/**/*.md'
+---
+
+# Documentation Domain
+
+- One `#` title per file — widget name or concept name. One-line description immediately after
+- Table of Contents with `[Section Name](#section-name)` links after description
+- `` for live demos
+- Section anchors: `` before each `##` heading
+- Code blocks always use `dart` language specifier
+- Props table format — left-aligned columns, backtick all code:
+ ```
+ | Prop | Type | Default | Description |
+ |:-----|:-----|:--------|:------------|
+ | `className` | `String?` | `null` | Wind utility classes. |
+ ```
+- Required props show `**Required**` in Default column
+- Constructor section shows full signature with defaults
+- Heading hierarchy: `#` page title → `##` main sections → `###` subsections. Never skip levels
+- x-preview `path` matches `example/lib/pages/{path}.dart` without extension
+- x-preview `size`: `sm` (compact), `md` (standard), `lg` (full-width)
+- Keep code examples short, realistic, and copy-pasteable
+- Related docs at bottom: `- [Widget Name](../widgets/widget-name.md)`
+- Do NOT restructure sections that haven't changed — preserve existing format exactly
+- When adding new sections, match the style of adjacent sections in the same file
diff --git a/.github/instructions/example-pages.instructions.md b/.github/instructions/example-pages.instructions.md
new file mode 100644
index 0000000..37caff1
--- /dev/null
+++ b/.github/instructions/example-pages.instructions.md
@@ -0,0 +1,22 @@
+---
+name: 'Example Page Conventions'
+description: 'Structure and patterns for Wind framework demo pages in example/lib/pages/'
+applyTo: 'example/lib/pages/**/*.dart'
+---
+
+# Example Pages Domain
+
+- File name: `{feature_name}.dart` (snake_case). Class: `{FeatureName}ExamplePage`
+- Extend `StatefulWidget` for interactive demos (state toggles, counters, loading simulation)
+- Root widget: `WDiv(className: 'w-full h-full overflow-y-auto p-4', child: ...)` — always scrollable
+- Content wrapper: `WDiv(className: 'flex flex-col gap-6', children: [_buildHeader(), ...sections])`
+- Header: gradient WDiv with title (text-lg font-bold text-white) + description (text-sm)
+- Use `_buildSection({title, description, children})` helper for consistent section layout
+- Section title: `text-lg font-semibold text-gray-900 dark:text-white`
+- Section description: `text-sm text-gray-600 dark:text-gray-400 mb-4`
+- Always include dark mode variants in all className strings
+- Show multiple variants of the component: basic, styled, states (hover, disabled, loading), responsive
+- Include interactive state demos: `setState(() => _isLoading = !_isLoading)`
+- Use realistic content — names, emails, descriptions — not "Lorem ipsum"
+- Each page demonstrates ONE widget or concept thoroughly, not multiple
+- These pages are referenced by `doc/` via `` — keep file paths stable
diff --git a/.github/instructions/parsers.instructions.md b/.github/instructions/parsers.instructions.md
new file mode 100644
index 0000000..e47ce26
--- /dev/null
+++ b/.github/instructions/parsers.instructions.md
@@ -0,0 +1,22 @@
+---
+name: 'Parser Conventions'
+description: 'Implementation patterns for Wind className parsers'
+applyTo: 'lib/src/parser/**/*.dart'
+---
+
+# Parser Domain
+
+- Every parser implements `WindParserInterface` with exactly two methods: `canParse()` and `parse()`
+- `canParse()` must be O(1) — use `startsWith()` or pre-compiled `static final RegExp`. No heavy logic
+- `parse()` iterates classes in **reverse** (last class wins semantics). Forward iteration is a bug
+- Return `styles.copyWith(...)` from parse() — never return null, never mutate input
+- If `classes == null`, return `styles` unchanged immediately
+- Use named RegExp capture groups: `(?p|pt|pr|pb|pl|px|py)` — not positional groups
+- Prefix stripping (`hover:`, `dark:`, `md:`) happens in WindParser before delegation — parsers never see prefixes
+- First-match-wins routing: WindParser checks `canParse()` across all parsers — first `true` wins. Order matters
+- One parser per file in `parsers/`. File name matches domain: `padding_parser.dart`, `border_parser.dart`
+- Register new parsers in `WindParser._parserMap` — key is descriptive string, value is const instance
+- `WindStyle` is immutable — properties are nullable. Merge with existing: `pTop ?? styles.padding?.top ?? 0`
+- Theme value resolution via `context.theme.getSpacing()`, `context.theme.getColor()` — never hardcode values
+- Arbitrary values use `[...]` bracket syntax: `p-[10px]`, `bg-[#FF5733]`. Parse brackets before theme lookup
+- Cache key = className + breakpoint + brightness + platform + sorted states. Call `WindParser.clearCache()` in tests
diff --git a/.github/instructions/tests.instructions.md b/.github/instructions/tests.instructions.md
new file mode 100644
index 0000000..b65d689
--- /dev/null
+++ b/.github/instructions/tests.instructions.md
@@ -0,0 +1,21 @@
+---
+name: 'Testing Conventions'
+description: 'Test structure, helpers, and patterns for Wind framework tests'
+applyTo: 'test/**/*.dart'
+---
+
+# Testing Domain
+
+- Test structure mirrors `lib/src/` exactly: `test/parser/parsers/`, `test/widgets/`, `test/theme/`, `test/dynamic/`
+- Every Wind widget test needs `wrapWithTheme()` helper — wraps in `MaterialApp > WindTheme > Scaffold`
+- Parser tests use `createTestContext()` helper with named params: `brightness`, `activeBreakpoint`, `isHovering`, etc.
+- Always `WindParser.clearCache()` in `setUp()` — cache persists between tests and causes false positives
+- Use `group()` for logical grouping by feature, `testWidgets()` for widget tests, `test()` for pure logic
+- Always `await tester.pumpWidget()`, `await tester.tap()`, `await tester.pump()` — missing await = flaky test
+- Use `pumpAndSettle()` only for animations, `pump()` for single-frame rebuilds
+- Parser tests: initialize parser + context in `setUp()` with `late` keyword
+- Widget tests: test behavior (taps, state changes), not implementation details
+- Expect patterns: `findsOneWidget`, `findsNothing`, `findsWidgets`, `isTrue`, `isA()`
+- Test both theme-scale values (`p-4`) and arbitrary values (`p-[10px]`) for parser coverage
+- Test dark mode: pass `brightness: Brightness.dark` to `createTestContext()`
+- Test edge cases: null classes, empty string, conflicting classes (last wins), unknown tokens (ignored)
diff --git a/.github/instructions/widgets.instructions.md b/.github/instructions/widgets.instructions.md
new file mode 100644
index 0000000..c7fae72
--- /dev/null
+++ b/.github/instructions/widgets.instructions.md
@@ -0,0 +1,22 @@
+---
+name: 'Widget Conventions'
+description: 'W-prefix widget hierarchy, constructor patterns, and state handling'
+applyTo: 'lib/src/widgets/**/*.dart'
+---
+
+# Widget Domain
+
+- All widgets use `W` prefix: `WDiv`, `WButton`, `WText`, `WFormInput`, `WSvg`
+- Form-integrated variants: `WForm{Feature}` (WFormInput, WFormSelect, WFormCheckbox, WFormDatePicker)
+- Always `const` constructor with `super.key` first, required params next, optional last, trailing commas
+- One class per file named after the widget: `w_button.dart` → `WButton` + `_WButtonState`
+- `className` is the primary styling API — it takes precedence over any explicit style properties
+- Widget build flow: parse className → detect displayType (flex/grid/block) → build minimal widget tree
+- Use `WindParser.parse(className, WindContext.of(context), states: states)` — always with context
+- WAnchor is required for `hover:`, `focus:`, `active:` states — WDiv auto-wraps if these prefixes detected
+- `child` XOR `children` — never both. `child` for single content, `children` for flex/grid layouts
+- Loading state (`isLoading: true`) disables all callbacks and activates `loading:` prefixed classes
+- Disabled state (`disabled: true`) activates `disabled:` prefixed classes
+- Custom states via `Set? states` parameter — used with matching prefixes like `selected:`, `active:`
+- Never hardcode colors or sizes — resolve through className or theme
+- DartDoc: `/// **The Utility-First [Name]**` header, then `### Supported Features:` and `### Example Usage:` sections
diff --git a/.github/scripts/sync-cc-to-copilot.sh b/.github/scripts/sync-cc-to-copilot.sh
new file mode 100755
index 0000000..0fcf005
--- /dev/null
+++ b/.github/scripts/sync-cc-to-copilot.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# Sync Claude Code rules (.claude/rules/) → GitHub Copilot instructions (.github/instructions/)
+# Run from project root: bash .github/scripts/sync-cc-to-copilot.sh
+
+set -euo pipefail
+
+RULES_DIR=".claude/rules"
+INSTRUCTIONS_DIR=".github/instructions"
+
+mkdir -p "$INSTRUCTIONS_DIR"
+
+for rule in "$RULES_DIR"/*.md; do
+ [ -f "$rule" ] || continue
+
+ name=$(basename "$rule" .md)
+ target="$INSTRUCTIONS_DIR/${name}.instructions.md"
+
+ # Extract path: from frontmatter
+ path_glob=$(sed -n '/^---$/,/^---$/{ /^path:/{ s/^path: *"*\(.*\)"*/\1/; p; } }' "$rule")
+
+ # Extract body (everything after second ---)
+ body=$(awk 'BEGIN{c=0} /^---$/{c++; next} c>=2{print}' "$rule")
+
+ # Generate human-readable name from filename
+ display_name=$(echo "$name" | sed 's/-/ /g; s/\b\(.\)/\u\1/g')
+
+ # Write Copilot instruction file
+ cat > "$target" <