diff --git a/skills/uniwind/SKILL.md b/skills/uniwind/SKILL.md
index e6723cc8..f56c370d 100644
--- a/skills/uniwind/SKILL.md
+++ b/skills/uniwind/SKILL.md
@@ -11,7 +11,7 @@ description: >
cover NativeWind migration.
---
-# Uniwind — Complete Reference
+# Uniwind
> Uniwind 1.7.0+ / Uniwind Pro 1.2.1+ / Tailwind CSS v4 / React Native 0.81+ / Expo SDK 54+
@@ -38,2193 +38,27 @@ Uniwind brings Tailwind CSS v4 to React Native. All core React Native components
13. **Deduplicate with `cn()` when mixing custom CSS classes and Tailwind** — Uniwind does NOT auto-deduplicate. If a custom CSS class (`.card { padding: 16px }`) and a Tailwind utility (`p-6`) set the same property, both apply with unpredictable results. Always wrap with `cn('card', 'p-6')` when there's overlap.
14. **Important utilities are supported** — Tailwind important modifier works in classNames with `!` at the end: `bg-red-500!`, `active:bg-red-500!`, `ios:pt-12!`. Leading `!bg-red-500` syntax is deprecated. Important utilities override non-important utilities for the same style property, but inline `style` still overrides className.
-## Setup
+## Reference Routing
-### Installation
+Read only relevant bundled reference files under `references/` after identifying the user's task:
-```bash
-# or other package manager
-bun install uniwind tailwindcss
-```
+- Setup/config install issues: `references/setup.md`
+- React Native component className props, accent color props, or component examples: `references/component-bindings.md`
+- Third-party components, `withUniwind`, dynamic class names, `tailwind-variants`, `cn`, or important utilities: `references/styling-patterns.md`
+- Themes, CSS variables, `ScopedTheme`, `LayoutDirection`, color spaces, or runtime variable APIs: `references/theming.md`
+- Platform, data, state, responsive, or safe-area utilities: `references/variants-and-selectors.md`
+- CSS functions, custom CSS, `@utility`, `@theme`, fonts, or gradients: `references/css-and-utilities.md`
+- React Navigation, UI kits, support matrix, or unsupported classes: `references/integrations.md`
+- Uniwind Pro installation, animations, diagnostics, group variants, default styles, native insets, or theme transitions: `references/pro.md`
+- Broken styles, setup diagnostics, errors, cache issues, FAQ answers, MCP, or related skills: `references/troubleshooting.md`
-Requires **Tailwind CSS v4+**.
+## Workflow
-### global.css
-
-Create a CSS entry file:
-
-```css
-@import 'tailwindcss';
-@import 'uniwind';
-```
-
-Import in your **App component** (e.g., `App.tsx` or `app/_layout.tsx`), **NOT** in `index.ts`/`index.js` — importing there breaks hot reload:
-
-```tsx
-// app/_layout.tsx or App.tsx
-import './global.css';
-```
-
-The directory containing `global.css` is the app root — Tailwind scans for classNames starting from this directory.
-
-### Metro Configuration
-
-```js
-const { getDefaultConfig } = require('expo/metro-config');
-// Bare RN: const { getDefaultConfig } = require('@react-native/metro-config');
-const { withUniwindConfig } = require('uniwind/metro');
-
-const config = getDefaultConfig(__dirname);
-
-// withUniwindConfig MUST be the OUTERMOST wrapper
-module.exports = withUniwindConfig(config, {
- cssEntryFile: './global.css', // Required — relative path from project root
- polyfills: { rem: 16 }, // Optional — base rem value (default 16)
- extraThemes: ['ocean', 'sunset'], // Optional — custom themes beyond light/dark
- dtsFile: './uniwind-types.d.ts', // Optional — TypeScript types output path
- debug: true, // Optional — log unsupported CSS in dev
- isTV: false, // Optional — enable TV platform support
-});
-```
-
-For most flows, keep defaults, only provide `cssEntryFile`.
-
-Wrapper order — Uniwind must wrap everything else:
-
-```js
-// CORRECT
-module.exports = withUniwindConfig(withOtherConfig(config, opts), { cssEntryFile: './global.css' });
-
-// WRONG — Uniwind is NOT outermost
-module.exports = withOtherConfig(withUniwindConfig(config, { cssEntryFile: './global.css' }), opts);
-```
-
-### Vite Configuration (v1.2.0+)
-
-If user has storybook setup, add extra vite config:
-
-```ts
-import tailwindcss from '@tailwindcss/vite';
-import { uniwind } from 'uniwind/vite';
-import { defineConfig } from 'vite';
-
-export default defineConfig({
- plugins: [
- tailwindcss(),
- uniwind({
- cssEntryFile: './src/global.css',
- dtsFile: './src/uniwind-types.d.ts',
- }),
- ],
-});
-```
-
-### TypeScript
-
-Uniwind auto-generates a `.d.ts` file (default: `./uniwind-types.d.ts`) after running Metro. Place it in `src/` or `app/` for auto-inclusion, or add to `tsconfig.json`:
-
-```json
-{ "include": ["./uniwind-types.d.ts"] }
-```
-
-If user has some typescript errors related to classNames, just run metro server to build the d.ts file.
-
-### Expo Router Placement
-
-```text
-project/
-├── app/_layout.tsx ← import '../global.css' here
-├── components/
-├── global.css ← project root (best location)
-└── metro.config.js ← cssEntryFile: './global.css'
-```
-
-If `global.css` is in `app/` dir, add `@source` for sibling directories:
-
-```css
-@import 'tailwindcss';
-@import 'uniwind';
-@source '../components';
-```
-
-### Tailwind IntelliSense (VS Code / Cursor / Windsurf)
-
-```json
-{
- "tailwindCSS.classAttributes": [
- "class", "className", "headerClassName",
- "contentContainerClassName", "columnWrapperClassName",
- "endFillColorClassName", "imageClassName", "tintColorClassName",
- "ios_backgroundColorClassName", "thumbColorClassName",
- "trackColorOnClassName", "trackColorOffClassName",
- "selectionColorClassName", "cursorColorClassName",
- "underlineColorAndroidClassName", "placeholderTextColorClassName",
- "selectionHandleColorClassName", "colorsClassName",
- "progressBackgroundColorClassName", "titleColorClassName",
- "underlayColorClassName", "colorClassName",
- "backdropColorClassName", "backgroundColorClassName",
- "statusBarBackgroundColorClassName", "drawerBackgroundColorClassName",
- "ListFooterComponentClassName", "ListHeaderComponentClassName"
- ],
- "tailwindCSS.classFunctions": ["useResolveClassNames"]
-}
-```
-
-### Monorepo Support
-
-Add `@source` directives in `global.css` for packages outside the CSS entry file's directory:
-
-```css
-@import 'tailwindcss';
-@import 'uniwind';
-@source "../../packages/ui/src";
-@source "../../packages/shared/src";
-```
-
-Also needed for `node_modules` packages that contain Uniwind classes (e.g., shared UI libraries).
-
-## Component Bindings
-
-All core React Native components support `className` out of the box. Some have additional className props for sub-styles (like `contentContainerClassName`) and non-style color props (requiring `accent-` prefix).
-
-### Complete Reference
-
-**Legend**: Props marked with ⚡ require the `accent-` prefix. Props in parentheses are platform-specific.
-
-#### View
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-
-#### Text
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `selectionColorClassName` | `selectionColor` | ⚡ `accent-` |
-
-#### Pressable
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-
-Supports `active:`, `disabled:`, `focus:` state selectors.
-
-#### Image
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `tintColorClassName` | `tintColor` | ⚡ `accent-` |
-
-#### TextInput
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `cursorColorClassName` | `cursorColor` | ⚡ `accent-` |
-| `selectionColorClassName` | `selectionColor` | ⚡ `accent-` |
-| `placeholderTextColorClassName` | `placeholderTextColor` | ⚡ `accent-` |
-| `selectionHandleColorClassName` | `selectionHandleColor` | ⚡ `accent-` |
-| `underlineColorAndroidClassName` | `underlineColorAndroid` (Android) | ⚡ `accent-` |
-
-Supports `focus:`, `active:`, `disabled:` state selectors.
-
-#### ScrollView
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `contentContainerClassName` | `contentContainerStyle` | — |
-| `endFillColorClassName` | `endFillColor` | ⚡ `accent-` |
-
-#### FlatList
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `contentContainerClassName` | `contentContainerStyle` | — |
-| `columnWrapperClassName` | `columnWrapperStyle` | — |
-| `ListHeaderComponentClassName` | `ListHeaderComponentStyle` | — |
-| `ListFooterComponentClassName` | `ListFooterComponentStyle` | — |
-| `endFillColorClassName` | `endFillColor` | ⚡ `accent-` |
-
-#### SectionList
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `contentContainerClassName` | `contentContainerStyle` | — |
-| `ListHeaderComponentClassName` | `ListHeaderComponentStyle` | — |
-| `ListFooterComponentClassName` | `ListFooterComponentStyle` | — |
-| `endFillColorClassName` | `endFillColor` | ⚡ `accent-` |
-
-#### VirtualizedList
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `contentContainerClassName` | `contentContainerStyle` | — |
-| `ListHeaderComponentClassName` | `ListHeaderComponentStyle` | — |
-| `ListFooterComponentClassName` | `ListFooterComponentStyle` | — |
-| `endFillColorClassName` | `endFillColor` | ⚡ `accent-` |
-
-#### Switch
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `thumbColorClassName` | `thumbColor` | ⚡ `accent-` |
-| `trackColorOnClassName` | `trackColor.true` (on) | ⚡ `accent-` |
-| `trackColorOffClassName` | `trackColor.false` (off) | ⚡ `accent-` |
-| `ios_backgroundColorClassName` | `ios_backgroundColor` (iOS) | ⚡ `accent-` |
-
-Note: Switch does NOT support `className` (`className?: never` in types). Use only the color-specific className props above. Supports `disabled:` state selector.
-
-#### ActivityIndicator
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `colorClassName` | `color` | ⚡ `accent-` |
-
-#### Button
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `colorClassName` | `color` | ⚡ `accent-` |
-
-Note: Button does not support `className` (no `style` prop on RN Button).
-
-#### Modal
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `backdropColorClassName` | `backdropColor` | ⚡ `accent-` |
-
-#### RefreshControl
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `colorsClassName` | `colors` (Android) | ⚡ `accent-` |
-| `tintColorClassName` | `tintColor` (iOS) | ⚡ `accent-` |
-| `titleColorClassName` | `titleColor` (iOS) | ⚡ `accent-` |
-| `progressBackgroundColorClassName` | `progressBackgroundColor` (Android) | ⚡ `accent-` |
-
-#### ImageBackground
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `imageClassName` | `imageStyle` | — |
-| `tintColorClassName` | `tintColor` | ⚡ `accent-` |
-
-#### SafeAreaView
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-
-#### KeyboardAvoidingView
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `contentContainerClassName` | `contentContainerStyle` | — |
-
-#### InputAccessoryView
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `backgroundColorClassName` | `backgroundColor` | ⚡ `accent-` |
-
-#### TouchableHighlight
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-| `underlayColorClassName` | `underlayColor` | ⚡ `accent-` |
-
-Supports `active:`, `disabled:` state selectors.
-
-#### TouchableOpacity
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-
-Supports `active:`, `disabled:` state selectors.
-
-#### TouchableNativeFeedback
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-
-Supports `active:`, `disabled:` state selectors.
-
-#### TouchableWithoutFeedback
-
-| Prop | Maps to | Prefix |
-|------|---------|--------|
-| `className` | `style` | — |
-
-Supports `active:`, `disabled:` state selectors.
-
-### Usage Examples
-
-```tsx
-import { View, Text, Pressable, TextInput, ScrollView, FlatList, Switch, Image, ActivityIndicator, Modal, RefreshControl, Button } from 'react-native';
-
-// View — basic layout
-
- Title
-
-
-// Pressable — with press/focus states
-
- Press Me
-
-
-// TextInput — with focus state and accent- color props
-
-
-// ScrollView — with content container
-
- {/* content */}
-
-
-// FlatList — with all sub-style props
- }
-/>
-
-// Switch — no className support, use color-specific props only
-
-
-// Image — tint color
-
-
-// ActivityIndicator
-
-
-// Button — only colorClassName (no className)
-
-
-// Modal — backdrop color
-
- {/* content */}
-
-
-// RefreshControl — platform-specific color props
-
-
-// ImageBackground — separate image styling
-
- Overlay
-
-
-// KeyboardAvoidingView
-
-
-
-
-// InputAccessoryView
-
-
-
-
-// TouchableHighlight — underlay color
-
- Press Me
-
-```
-
-## The accent- Prefix Pattern
-
-React Native components have props like `color`, `tintColor`, `thumbColor` that are NOT part of the `style` object. To set these via Tailwind classes, use the `accent-` prefix with the corresponding `{propName}ClassName` prop:
-
-```tsx
-// color prop → colorClassName with accent- prefix
-
-
-
-// tintColor prop → tintColorClassName
-
-
-// thumbColor → thumbColorClassName
-
-
-// placeholderTextColor → placeholderTextColorClassName
-
-```
-
-**CRITICAL Rule**: `className` maps to the `style` prop — it handles layout, typography, backgrounds, borders, etc. But React Native has many color props that live OUTSIDE of `style` (like `color`, `tintColor`, `thumbColor`, `placeholderTextColor`). These require a separate `{propName}ClassName` prop with the `accent-` prefix. Without `accent-`, the class resolves to a style object — but these props expect a plain color string.
-
-```tsx
-// WRONG — className sets style, but ActivityIndicator's color is NOT a style prop
- // color will NOT be set
-
-// CORRECT — use the dedicated colorClassName prop with accent- prefix
- // color IS set to #3b82f6
-
-// WRONG — tintColor is not a style prop on Image
- // won't work
-
-// CORRECT
-
-```
-
-## Styling Third-Party Components
-
-### withUniwind (Recommended)
-
-Wrap once at module level, use with `className` everywhere:
-
-```tsx
-import { withUniwind } from 'uniwind';
-import { Image as ExpoImage } from 'expo-image';
-import { BlurView as RNBlurView } from 'expo-blur';
-import { LinearGradient as RNLinearGradient } from 'expo-linear-gradient';
-
-// Module-level wrapping (NEVER inside render functions)
-export const Image = withUniwind(ExpoImage);
-export const BlurView = withUniwind(RNBlurView);
-export const LinearGradient = withUniwind(RNLinearGradient);
-```
-
-`withUniwind` automatically maps:
-- `style` → `className`
-- `{name}Style` → `{name}ClassName`
-- `{name}Color` → `{name}ColorClassName` (with accent- prefix)
-
-For custom prop mappings:
-
-```tsx
-const StyledProgressBar = withUniwind(ProgressBar, {
- width: {
- fromClassName: 'widthClassName',
- styleProperty: 'width',
- },
-});
-```
-
-**Usage patterns:**
-
-- **Used in one file only** — define the wrapped component in that same file
-- **Used across multiple files** — wrap once in a shared module (e.g., `components/styled.ts`) and re-export
-
-```tsx
-// components/styled.ts
-import { withUniwind } from 'uniwind';
-import { Image as ExpoImage } from 'expo-image';
-export const Image = withUniwind(ExpoImage);
-
-// Then import everywhere:
-import { Image } from '@/components/styled';
-```
-
-**NEVER** call `withUniwind` on the same component in multiple files.
-
-**CRITICAL**: Do NOT use `withUniwind` on components from `react-native` or `react-native-reanimated`. These already have built-in `className` support:
-
-```tsx
-// WRONG — View already supports className natively
-const StyledView = withUniwind(View); // DO NOT DO THIS
-const StyledText = withUniwind(Text); // DO NOT DO THIS
-const StyledAnimatedView = withUniwind(Animated.View); // DO NOT DO THIS
-
-// CORRECT — only wrap third-party components
-const StyledExpoImage = withUniwind(ExpoImage); // expo-image
-const StyledBlurView = withUniwind(BlurView); // expo-blur
-const StyledMotiView = withUniwind(MotiView); // moti
-```
-
-### useResolveClassNames
-
-Converts Tailwind class strings to React Native style objects. Use for one-off cases or components that only accept `style`:
-
-```tsx
-import { useResolveClassNames } from 'uniwind';
-
-const headerStyle = useResolveClassNames('bg-primary p-4');
-const cardStyle = useResolveClassNames('bg-card dark:bg-card rounded-lg shadow-sm');
-
-// React Navigation screen options
-
-```
-
-### Comparison
-
-| Feature | withUniwind | useResolveClassNames |
-|---------|-------------|----------------------|
-| Setup | Once per component | Per usage |
-| Performance | Optimized | Slightly slower |
-| Best for | Reusable components | One-off, navigation config |
-| Syntax | `className="..."` | `style={...}` |
-
-## Dynamic ClassNames
-
-### NEVER do this (Tailwind scans at build time)
-
-```tsx
-// BROKEN — template literal with variable
-
-
-```
-
-### Correct patterns
-
-```tsx
-// Ternary with complete class names
-
-
-// Mapping object
-const colorMap = {
- primary: 'bg-blue-500 text-white',
- danger: 'bg-red-500 text-white',
- ghost: 'bg-transparent text-foreground',
-};
-
-
-// Array join for multiple conditions
-
-```
-
-## tailwind-variants (tv)
-
-For complex component styling with variants and compound variants:
-
-```tsx
-import { tv } from 'tailwind-variants';
-
-const button = tv({
- base: 'font-semibold rounded-lg px-4 py-2 items-center justify-center',
- variants: {
- color: {
- primary: 'bg-blue-500 text-white',
- secondary: 'bg-gray-500 text-white',
- danger: 'bg-red-500 text-white',
- ghost: 'bg-transparent text-foreground border border-border',
- },
- size: {
- sm: 'text-sm px-3 py-1.5',
- md: 'text-base px-4 py-2',
- lg: 'text-lg px-6 py-3',
- },
- disabled: {
- true: 'opacity-50',
- },
- },
- compoundVariants: [
- { color: 'primary', size: 'lg', class: 'bg-blue-600' },
- ],
- defaultVariants: { color: 'primary', size: 'md' },
-});
-
-
- Click
-
-```
-
-## cn Utility — Class Deduplication
-
-Uniwind does **NOT** auto-deduplicate conflicting classNames. This means if the same property appears in multiple classes, **both will be applied and the result is unpredictable**. This is especially critical when mixing custom CSS classes with Tailwind utilities.
-
-### Setup
-
-```bash
-npm install tailwind-merge clsx
-```
-
-```ts
-// lib/cn.ts
-import { type ClassValue, clsx } from 'clsx';
-import { twMerge } from 'tailwind-merge';
-
-export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs));
-}
-```
-
-### When cn Is Required
-
-1. **Merging className props** — component accepts external className that may conflict:
-
-```tsx
-import { cn } from '@/lib/cn';
-
-
-
-```
-
-2. **CRITICAL: Mixing custom CSS classes with Tailwind utilities** — if your custom CSS class sets a property that a Tailwind utility also sets, you MUST use `cn()` to deduplicate:
-
-```css
-/* global.css */
-.card {
- background-color: white;
- border-radius: 12px;
- padding: 16px;
-}
-```
-
-```tsx
-// WRONG — both .card (padding: 16px) and p-6 (padding: 24px) apply, result is unpredictable
-
-
-// CORRECT — cn deduplicates, p-6 wins over .card's padding
-
-```
-
-3. **tv() output combined with extra classes** — tv already handles its own variants, but if you add more classes on top:
-
-```tsx
-
-```
-
-### When cn Is NOT Needed
-
-- Static className with no conflicts: ``
-- Single custom CSS class with no overlapping Tailwind: `` (if card-shadow only sets box-shadow which no Tailwind class also sets)
-
-## Important Utilities and Style Specificity
-
-Uniwind supports Tailwind's important modifier (`!`) for utilities that must override another utility for the same style property.
-
-```tsx
-import { View, Pressable } from 'react-native';
-
-// bg-red-500! has higher priority than bg-blue-500
-;
-
-// Important utilities work with state and platform variants
-;
-;
-```
-
-Priority rules:
-- Important utility (`bg-red-500!`) overrides non-important utility (`bg-blue-500`) for the same property.
-- Important variants work normally: `active:bg-red-500!`, `ios:pt-12!`, `dark:text-white!`.
-- Inline `style` always wins, even over important className utilities: `` renders blue.
-- Use `!` sparingly. For reusable components and consumer overrides, prefer `cn()` with `tailwind-merge`.
-
-## Theming
-
-### Quick Setup (dark: prefix)
-
-Works immediately — no configuration needed:
-
-```tsx
-
- Themed
-
-```
-
-Best for small apps and prototyping. Does not scale to custom themes.
-
-### Scalable Setup (CSS Variables)
-
-Define in `global.css`, use everywhere without `dark:` prefix:
-
-```css
-@layer theme {
- :root {
- @variant light {
- --color-background: #ffffff;
- --color-foreground: #111827;
- --color-foreground-secondary: #6b7280;
- --color-card: #ffffff;
- --color-border: #e5e7eb;
- --color-muted: #9ca3af;
- --color-primary: #3b82f6;
- --color-danger: #ef4444;
- --color-success: #10b981;
- }
- @variant dark {
- --color-background: #000000;
- --color-foreground: #ffffff;
- --color-foreground-secondary: #9ca3af;
- --color-card: #1f2937;
- --color-border: #374151;
- --color-muted: #6b7280;
- --color-primary: #3b82f6;
- --color-danger: #ef4444;
- --color-success: #10b981;
- }
- }
-}
-```
-
-```tsx
-// Auto-adapts to current theme — no dark: prefix needed
-
- Title
- Subtitle
-
-```
-
-Variable naming: `--color-background` → `bg-background`, `text-background`.
-
-**Prefer CSS variables over explicit `dark:` variants** — they're cleaner, maintain easier, and work with custom themes automatically.
-
-### Custom Themes
-
-**Step 1** — Define in `global.css`:
-
-```css
-@layer theme {
- :root {
- @variant light { /* ... */ }
- @variant dark { /* ... */ }
- @variant ocean {
- --color-background: #0c4a6e;
- --color-foreground: #e0f2fe;
- --color-primary: #06b6d4;
- --color-card: #0e7490;
- --color-border: #155e75;
- /* Must define ALL the same variables as light/dark */
- }
- }
-}
-```
-
-**Step 2** — Register in `metro.config.js` (exclude `light`/`dark` — they're automatic):
-
-```js
-module.exports = withUniwindConfig(config, {
- cssEntryFile: './global.css',
- extraThemes: ['ocean'],
-});
-```
-
-Restart Metro after adding themes.
-
-**Step 3** — Use:
-
-```tsx
-Uniwind.setTheme('ocean');
-```
-
-### Theme API
-
-```tsx
-import { Uniwind, useUniwind } from 'uniwind';
-
-// Imperative (no re-render)
-Uniwind.setTheme('dark'); // Force dark
-Uniwind.setTheme('light'); // Force light
-Uniwind.setTheme('system'); // Follow device (re-enables adaptive themes)
-Uniwind.setTheme('ocean'); // Custom theme (must be in extraThemes)
-Uniwind.currentTheme; // Current theme name
-Uniwind.hasAdaptiveThemes; // true if following system
-
-// Reactive hook (re-renders on change)
-const { theme, hasAdaptiveThemes } = useUniwind();
-```
-
-`Uniwind.setTheme('light')` / `setTheme('dark')` also calls `Appearance.setColorScheme` to sync native components (Alert, Modal, system dialogs).
-
-By default Uniwind uses "system" theme - follows device color scheme. If user wants to override it, just
-call Uniwind.setTheme with desired theme. It can be done above the React component to avoid theme switching at runtime.
-
-### Theme Switcher Example
-
-```tsx
-import { View, Pressable, Text, ScrollView } from 'react-native';
-import { Uniwind, useUniwind } from 'uniwind';
-
-export const ThemeSwitcher = () => {
- const { theme, hasAdaptiveThemes } = useUniwind();
- const activeTheme = hasAdaptiveThemes ? 'system' : theme;
-
- const themes = [
- { name: 'light', label: 'Light' },
- { name: 'dark', label: 'Dark' },
- { name: 'system', label: 'System' },
- ];
-
- return (
-
-
- {themes.map((t) => (
- Uniwind.setTheme(t.name)}
- className={`px-4 py-3 rounded-lg items-center ${
- activeTheme === t.name ? 'bg-primary' : 'bg-card border border-border'
- }`}
- >
-
- {t.label}
-
-
- ))}
-
-
- );
-};
-```
-
-### ScopedTheme
-
-Apply a different theme to a subtree without changing the global theme:
-
-```tsx
-import { ScopedTheme } from 'uniwind';
-
-
-
-
-
- {/* Renders with dark theme */}
-
-
-
- {/* Renders with ocean theme */}
-
-
-```
-
-- Nearest `ScopedTheme` wins (nested scopes supported)
-- Hooks (`useUniwind`, `useResolveClassNames`, `useCSSVariable`) resolve against the nearest scoped theme
-- `withUniwind`-wrapped components inside the scope also resolve scoped theme values
-- Custom themes require registration in `extraThemes`
-
-### LayoutDirection (v1.8.0+)
-
-Scope RTL/LTR variants to a subtree without changing global device RTL state:
-
-```tsx
-import { LayoutDirection } from 'uniwind';
-
-
- Uses global RTL state
-
-
- Forced RTL subtree
-
-
-
- Forced LTR subtree
-
-
-```
-
-- Available from `uniwind@1.8.0`.
-- `rtl` prop: `true` forces RTL, `false` forces LTR.
-- Omit `rtl` to inherit parent `LayoutDirection`; outside any parent it falls back to global RTL state.
-- Nearest `LayoutDirection` wins (nested scopes supported).
-- Prefer `LayoutDirection` over inline `style={{ direction: 'rtl' }}` for `rtl:`/`ltr:` variant scoping.
-- Hooks (`useResolveClassNames`, `useCSSVariable`) and `withUniwind`-wrapped components inside the scope resolve against the nearest layout direction.
-
-### useCSSVariable
-
-Access CSS variable values in JavaScript:
-
-```tsx
-import { useCSSVariable } from 'uniwind';
-
-const primaryColor = useCSSVariable('--color-primary');
-const spacing = useCSSVariable('--spacing-4');
-
-// Multiple variables at once
-const [bg, fg] = useCSSVariable(['--color-background', '--color-foreground']) as [string, string]
-```
-
-Use for: animations, chart libraries, third-party component configs, calculations with design tokens.
-
-It's required to cast the result of `useCSSVariable` as it can return: string | number | undefined.
-Uniwind doesn't know if given variable exist and what type it is, so it returns union type.
-
-### getCSSVariable
-
-Read CSS variable values outside of React (event handlers, async callbacks, utility modules, worklets). Available in Uniwind 1.6.4+.
-
-```ts
-import { Uniwind } from 'uniwind';
-
-const primary = Uniwind.getCSSVariable('--color-primary');
-const [bg, fg] = Uniwind.getCSSVariable(['--color-background', '--color-foreground']) as [string, string];
-```
-
-Same value rules as `useCSSVariable` (variable must be used in a `className` or declared in `@theme static`). Same return type: `string | number | undefined`. Cast as needed.
-
-Not reactive — value is read once. For reactive values inside components use `useCSSVariable`. Use `getCSSVariable` for one-shot reads (onPress handlers, utility functions, native module configs).
-
-### Runtime CSS Variable Updates
-
-Update theme variables at runtime (e.g., user-selected brand colors or API-driven themes):
-
-```tsx
-Uniwind.updateCSSVariables('light', {
- '--color-primary': '#ff6600',
- '--color-background': '#fafafa',
-});
-```
-
-Updates are theme-specific and take effect immediately.
-
-### @theme static
-
-For JS-only values not used in classNames:
-
-```css
-@theme static {
- --chart-line-width: 2;
- --chart-dot-radius: 4;
- --animation-duration: 300;
-}
-```
-
-Access via `useCSSVariable('--chart-line-width')`. Use for: chart configs, animation durations, native module values.
-
-### OKLCH Colors support
-
-Perceptually uniform color format — wider gamut, consistent lightness:
-
-```css
-@layer theme {
- :root {
- @variant light {
- --color-primary: oklch(0.5 0.2 240);
- --color-background: oklch(1 0 0);
- }
- @variant dark {
- --color-primary: oklch(0.6 0.2 240);
- --color-background: oklch(0.13 0.004 17.69);
- }
- }
-}
-```
-
-### Display P3 Colors support
-
-Wide-gamut color format for devices that support the P3 color space (most modern iPhones and Macs). Uniwind parses `color(display-p3 ...)` values and converts them for native use:
-
-```css
-@layer theme {
- :root {
- @variant light {
- --color-primary: color(display-p3 0.2 0.4 1);
- --color-accent: color(display-p3 1 0.3 0.3);
- }
- @variant dark {
- --color-primary: color(display-p3 0.3 0.5 1);
- --color-accent: color(display-p3 1 0.4 0.4);
- }
- }
-}
-```
-
-## Platform Selectors
-
-Apply platform-specific styles directly in className:
-
-```tsx
-// Individual platforms
-
-
-// native: shorthand (iOS + Android)
-
-
-// TV platforms
-
-
-// Combine with other utilities
-
-```
-
-Platform variants in `@layer theme` for global values (use `@variant`, not `@media`):
-
-```css
-@layer theme {
- :root {
- @variant ios { --font-sans: 'SF Pro Text'; }
- @variant android { --font-sans: 'Roboto-Regular'; }
- @variant web { --font-sans: 'Inter'; }
- }
-}
-```
-
-**Prefer platform selectors over `Platform.select()`** — cleaner syntax, no imports needed.
-
-## Data Selectors
-
-Style based on prop values using `data-[prop=value]:utility`:
-
-```tsx
-// Boolean props
-
-
-// String props
-
-
-// Tabs pattern
-
- {route.title}
-
-
-// Toggle pattern
-
-
-
-```
-
-**Rules**:
-- Only equality selectors supported (`data-[prop=value]`)
-- No presence-only selectors (`data-[prop]` — not supported)
-- No `has-data-*` parent selectors (not supported in React Native)
-- Booleans match both boolean and string forms
-
-## Interactive States
-
-```tsx
-// active: — when pressed
-
- Press me
-
-
-// disabled: — when disabled prop is true
-
- Submit
-
-
-// focus: — keyboard/accessibility focus
-
-
-
- Focusable
-
-```
-
-Components with state support:
-- **Pressable**: `active:`, `disabled:`, `focus:`
-- **TextInput**: `active:`, `disabled:`, `focus:`
-- **Switch**: `disabled:`
-- **Text**: `active:`, `disabled:`
-- **TouchableOpacity / TouchableHighlight / TouchableNativeFeedback / TouchableWithoutFeedback**: `active:`, `disabled:`
-
-## Responsive Breakpoints
-
-Mobile-first — unprefixed styles apply to all sizes, prefixed styles apply at that breakpoint and above:
-
-| Prefix | Min Width | Typical Device |
-|--------|-----------|----------------|
-| (none) | 0px | All (mobile) |
-| `sm:` | 640px | Large phones |
-| `md:` | 768px | Tablets |
-| `lg:` | 1024px | Landscape tablets |
-| `xl:` | 1280px | Desktops |
-| `2xl:` | 1536px | Large desktops |
-
-```tsx
-// Responsive padding and typography
-
- Responsive
-
-
-// Responsive grid (1 col → 2 col → 3 col)
-
-
- Item
-
-
-
-// Responsive visibility
-
- Visible on tablet+
-
-
- Mobile only
-
-```
-
-Custom breakpoints:
-
-```css
-@theme {
- --breakpoint-xs: 480px;
- --breakpoint-tablet: 820px;
- --breakpoint-3xl: 1920px;
-}
-```
-
-Usage: `xs:p-2 tablet:p-4 3xl:p-8`
-
-**Design mobile-first** — start with base styles (no prefix), enhance with breakpoints:
-
-```tsx
-// CORRECT — mobile-first
-
-
-// WRONG — desktop-first (reversed order is confusing and fragile)
-
-```
-
-## Safe Area Utilities
-
-### Padding
-
-| Class | Description |
-|-------|-------------|
-| `p-safe` | All sides |
-| `pt-safe` / `pb-safe` / `pl-safe` / `pr-safe` | Individual sides |
-| `px-safe` / `py-safe` | Horizontal / vertical |
-
-### Margin
-
-| Class | Description |
-|-------|-------------|
-| `m-safe` | All sides |
-| `mt-safe` / `mb-safe` / `ml-safe` / `mr-safe` | Individual sides |
-| `mx-safe` / `my-safe` | Horizontal / vertical |
-
-### Positioning
-
-| Class | Description |
-|-------|-------------|
-| `inset-safe` | All sides |
-| `top-safe` / `bottom-safe` / `left-safe` / `right-safe` | Individual sides |
-| `x-safe` / `y-safe` | Horizontal / vertical inset |
-
-### Compound Variants
-
-| Pattern | Behavior | Example |
-|---------|----------|---------|
-| `{prop}-safe-or-{value}` | `Math.max(inset, value)` — ensures minimum spacing | `pt-safe-or-4` |
-| `{prop}-safe-offset-{value}` | `inset + value` — adds extra spacing on top of inset | `pb-safe-offset-4` |
-
-### Setup
-
-**Uniwind Free (default)** — requires `react-native-safe-area-context` to update insets.
-Wrap your App component in `SafeAreaProvider` and `SafeAreaListener` and call `Uniwind.updateInsets(insets)` in the `onChange` callback:
-
-```tsx
-import { SafeAreaProvider, SafeAreaListener } from 'react-native-safe-area-context';
-import { Uniwind } from 'uniwind';
-
-export default function App() {
- return (
-
- {
- Uniwind.updateInsets(insets);
- }}
- >
- {/* content */}
-
-
- );
-}
-```
-
-**Uniwind Pro** — automatic, no setup needed. Insets injected from native layer.
-
-## CSS Functions
-
-Uniwind provides CSS functions for device-aware and theme-aware styling. These can be used everywhere (custom CSS classes, `@utility`, etc.) — but NOT inside `@theme {}` (which only accepts static values). Use `@utility` to create reusable Tailwind-style utility classes:
-
-### hairlineWidth()
-
-Returns the thinnest line width displayable on the device. Use for subtle borders and dividers.
-
-```css
-@utility h-hairline { height: hairlineWidth(); }
-@utility border-hairline { border-width: hairlineWidth(); }
-@utility w-hairline { width: calc(hairlineWidth() * 10); }
-```
-
-```tsx
-
-
-```
-
-### fontScale(multiplier?)
-
-Multiplies a base value by the device's font scale accessibility setting. Ensures text respects user preferences for larger or smaller text.
-
-- **`fontScale()`** — uses multiplier 1 (device font scale × 1)
-- **`fontScale(0.9)`** — smaller scale
-- **`fontScale(1.2)`** — larger scale
-
-```css
-@utility text-sm-scaled { font-size: fontScale(0.9); }
-@utility text-base-scaled { font-size: fontScale(); }
-@utility text-lg-scaled { font-size: fontScale(1.2); }
-```
-
-```tsx
-Small accessible text
-Regular accessible text
-```
-
-### pixelRatio(multiplier?)
-
-Multiplies a value by the device's pixel ratio. Creates pixel-perfect designs that scale across screen densities.
-
-- **`pixelRatio()`** — uses multiplier 1 (device pixel ratio × 1)
-- **`pixelRatio(2)`** — double the pixel ratio
-
-```css
-@utility w-icon { width: pixelRatio(); }
-@utility w-avatar { width: pixelRatio(2); }
-```
-
-```tsx
-
-```
-
-### light-dark(lightValue, darkValue)
-
-Returns different values based on the current theme mode. Automatically adapts when the theme changes — no manual switching logic needed.
-
-- First parameter: value for light theme
-- Second parameter: value for dark theme
-
-```css
-@utility bg-adaptive { background-color: light-dark(#ffffff, #1f2937); }
-@utility text-adaptive { color: light-dark(#111827, #f9fafb); }
-@utility border-adaptive { border-color: light-dark(#e5e7eb, #374151); }
-```
-
-```tsx
-
- Adapts to light/dark theme
-
-```
-
-Also works in custom CSS classes (not just `@utility`):
-
-```css
-.adaptive-card {
- background-color: light-dark(#ffffff, #1f2937);
- color: light-dark(#111827, #f9fafb);
-}
-```
-
-## Custom CSS & Utilities
-
-### Custom CSS Classes
-
-Uniwind supports custom CSS class names defined in `global.css`. They are compiled at build time — no runtime overhead. Use them when you need styles that are hard to express as Tailwind utilities (e.g., complex box-shadow, multi-property bundles).
-
-```css
-/* global.css */
-.card-shadow {
- background-color: white;
- border-radius: 12px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-}
-
-.adaptive-surface {
- background-color: light-dark(#ffffff, #1f2937);
- color: light-dark(#111827, #f9fafb);
-}
-
-.container {
- flex: 1;
- width: 100%;
- max-width: 1200px;
-}
-```
-
-Apply via `className` just like any Tailwind class:
-
-```tsx
-
-```
-
-### Mixing Custom CSS with Tailwind
-
-You can combine custom CSS classes with Tailwind utilities in a single `className`:
-
-```tsx
-
- {title}
- {children}
-
-```
-
-**WARNING**: If a custom CSS class and a Tailwind utility set the **same property**, you **MUST** use `cn()` to deduplicate. Without `cn()`, both values apply and the result is unpredictable:
-
-```tsx
-// WRONG — .container sets flex:1, and flex-1 also sets flex:1 (harmless but wasteful)
-// WRONG — .container sets width:100%, and w-full also sets width:100% (redundant)
-// DANGEROUS — .card-shadow sets border-radius:12px, and rounded-2xl sets border-radius:16px — CONFLICT!
-
-
-// CORRECT — cn ensures rounded-2xl wins
-import { cn } from '@/lib/cn';
-
-```
-
-**Rule of thumb**: If your custom CSS class sets properties that might overlap with Tailwind utilities you'll also use, always wrap with `cn()`. See **cn Utility** section for full setup.
-
-### Guidelines for Custom CSS
-
-- Keep selectors flat — no deep nesting or child selectors
-- Prefer Tailwind utilities for simple, single-property styles
-- Use custom classes for complex or multi-property bundles that would be verbose in className
-- Use `light-dark()` for theme-aware custom classes
-- Custom classes are great for shared design tokens that don't fit Tailwind's naming (e.g., `.card`, `.chip`, `.badge-dot`)
-
-### Custom Utilities (@utility)
-
-The `@utility` directive creates utility classes that work exactly like built-in Tailwind classes. Three main use cases:
-
-#### 1. Variable-driven utilities (runtime-injected values)
-
-Create a utility whose value comes from a CSS variable injected at runtime via `updateCSSVariables`. Use `@theme static` to declare the variable so Uniwind tracks it even before it is updated:
-
-```css
-/* global.css */
-@theme static {
- --header-height: 0px;
-}
-
-@utility p-safe-header {
- padding-top: var(--header-height);
-}
-```
-
-Inject the real value at runtime (e.g., from react-navigation's layout event):
-
-```tsx
-import { Uniwind } from 'uniwind'
-
-// e.g., inside a navigation layout listener
-Uniwind.updateCSSVariables(Uniwind.currentTheme, {
- '--header-height': headerHeight,
-})
-```
-
-```tsx
-
-```
-
-#### 2. Brand-new utilities (no Tailwind equivalent)
-
-For styles that have no built-in Tailwind class:
-
-```css
-@utility h-hairline { height: hairlineWidth(); }
-@utility text-scaled { font-size: fontScale(); }
-@utility card-shadow {
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
-}
-```
-
-Usage like any Tailwind class: ``
-
-#### 3. Overriding existing Tailwind utilities
-
-Use `@utility` to completely replace what a built-in class does. Example: make `border` always use `--color-primary`:
-
-```css
-@utility border {
- border-width: 1px;
- border-style: solid;
- border-color: var(--color-primary);
-}
-```
-
-## @theme Directive
-
-Customize Tailwind design tokens in `global.css`:
-
-```css
-@theme {
- /* Colors */
- --color-primary: #3b82f6;
- --color-brand-500: #3b82f6;
- --color-brand-900: #1e3a8a;
-
- /* Typography */
- --font-sans: 'Roboto-Regular';
- --font-sans-medium: 'Roboto-Medium';
- --font-sans-bold: 'Roboto-Bold';
- --font-mono: 'FiraCode-Regular';
-
- /* Spacing & sizing */
- --text-base: 15px;
- --spacing-4: 16px;
- --radius-lg: 12px;
-
- /* Breakpoints */
- --breakpoint-tablet: 820px;
-}
-```
-
-Usage: `bg-brand-500`, `text-brand-900`, `font-sans`, `font-mono`, `rounded-lg`.
-
-## Fonts
-
-React Native requires a **single font** per family — no fallbacks:
-
-```css
-@theme {
- --font-sans: 'Roboto-Regular';
- --font-sans-bold: 'Roboto-Bold';
- --font-mono: 'FiraCode-Regular';
-}
-```
-
-Font name must **exactly match** the font file name (without extension).
-
-**Expo**: Configure fonts in `app.json` with the `expo-font` plugin, then reference in CSS.
-
-**Bare RN**: Use `react-native-asset` to link fonts, same CSS config.
-
-**Platform-specific fonts** (use `@variant`, not `@media`):
-
-```css
-@layer theme {
- :root {
- @variant ios { --font-sans: 'SF Pro Text'; }
- @variant android { --font-sans: 'Roboto-Regular'; }
- @variant web { --font-sans: 'system-ui'; }
- }
-}
-```
-
-## Gradients
-
-Built-in support — no extra dependencies:
-
-```tsx
-
- Gradient
-
-```
-
-For `expo-linear-gradient`, you can wrap it with `withUniwind` for className-based layout and styling (padding, border-radius, flex, etc.), but the `colors` prop is an array that cannot be resolved via className — it must be provided explicitly. Use `useCSSVariable` to get theme-aware colors:
-
-```tsx
-import { useCSSVariable } from 'uniwind';
-import { withUniwind } from 'uniwind';
-import { LinearGradient as RNLinearGradient } from 'expo-linear-gradient';
-
-const LinearGradient = withUniwind(RNLinearGradient);
-
-function GradientCard() {
- // useCSSVariable returns string | number | undefined
- const primary = useCSSVariable('--color-primary');
- const secondary = useCSSVariable('--color-secondary');
-
- // Guard against undefined — LinearGradient.colors requires valid ColorValues
- if (!primary || !secondary) {
- return null;
- }
-
- return (
-
- Themed gradient
-
- );
-}
-```
-
-Alternatively, export a wrapped component from a shared module for reuse:
-
-```tsx
-// components/styled.ts
-import { withUniwind } from 'uniwind';
-import { LinearGradient as RNLinearGradient } from 'expo-linear-gradient';
-
-export const LinearGradient = withUniwind(RNLinearGradient);
-```
-
-```tsx
-// usage — className handles layout, colors still passed manually
-import { LinearGradient } from '@/components/styled';
-
-
- Static gradient
-
-```
-
-## React Navigation Integration
-
-Use `useResolveClassNames` for screen options that only accept `style` objects:
-
-```tsx
-import { useResolveClassNames } from 'uniwind';
-
-function Layout() {
- const headerStyle = useResolveClassNames('bg-background');
- const headerTitleStyle = useResolveClassNames('text-foreground font-bold');
-
- return (
-
- );
-}
-```
-
-Keep React Navigation's `` if already in use — it manages navigation-specific theming.
-
-## UI Kit Compatibility
-
-- **HeroUI Native**: Works with Uniwind. Uses `tailwind-variants` (tv) internally. Apply `className` directly on HeroUI components. **Bun users**: Bun uses symlinks for `node_modules`, which can cause Tailwind's Oxide scanner to miss library classes in production builds. Fix: use the resolved path in `@source` and hoist the package:
- ```css
- @source "../../node_modules/heroui-native/lib";
- ```
- ```ini
- # .npmrc
- public-hoist-pattern[]=heroui-native
- ```
-- **react-native-reusables**: Compatible.
-- **Gluestack v4.1+**: Compatible.
-- **Lucide React Native**: Use `withUniwind(LucideIcon)` with `colorClassName="accent-blue-500"` for icon color. Works for all Lucide icons.
-- **@shopify/flash-list**: Use `withUniwind(FlashList)` for `className` and `contentContainerClassName` support. Note: `withUniwind` loses generic type params on `ref` — cast manually if needed.
-
-Use semantic color tokens (`bg-primary`, `text-foreground`) for theme consistency across UI kits.
-
-## Supported vs Unsupported Classes
-
-React Native uses the Yoga layout engine. Key differences from web CSS:
-- **No CSS cascade/inheritance** — styles don't inherit from parents
-- **Flexbox by default** — all views use flexbox with `flexDirection: 'column'`
-- **Limited CSS properties** — no floats, grid, pseudo-elements
-
-### Built-in Extra Utilities
-
-Uniwind provides additional utility classes for React Native features not covered by standard Tailwind:
-
-| Class | Effect |
-|-------|--------|
-| `border-continuous` | Sets `borderCurve: 'continuous'` — smooth, superellipse corners (iOS) |
-| `border-circular` | Sets `borderCurve: 'circular'` — standard circular corners (iOS default) |
-
-```tsx
-// Smooth iOS-style rounded corners (like SwiftUI's .continuous)
-
- Smooth corners
-
-```
-
-### Supported (all standard Tailwind)
-
-Layout, spacing, sizing, typography, colors, borders, effects, flexbox, positioning, transforms, interactive states.
-
-### Unsupported (web-specific, silently ignored)
-
-- `hover:` `visited:` — use Pressable `active:` instead
-- `before:` `after:` `placeholder:` — pseudo-elements
-- `float-*` `clear-*` `columns-*`
-- `print:` `screen:`
-- `break-before-*` `break-after-*` `break-inside-*`
-
-## Uniwind Pro
-
-Paid upgrade with 100% API compatibility. Built on a 2nd-generation C++ engine for apps that demand the best performance. Graduated pricing (billed annually): **$99/seat** (1-3), **$49** (4-6), **$29** (7-15), **$1** (16+). Pricing and licensing: [https://uniwind.dev/pricing](https://uniwind.dev/pricing)
-
-### Pricing & Licensing
-
-- **Graduated per-seat pricing** (billed annually, VAT excluded unless applicable): $99 for seats 1-3, $49 for 4-6, $29 for 7-15, $1 for 16+
-- **Individual License**: Personal Pro license per engineer
-- **Team License**: Single key management — add or remove members instantly
-- **CI/CD License**: Full support for automated and headless build environments
-- **Enterprise**: Custom plans available (contact support@uniwind.dev)
-- **Priority Support**: Critical issues resolved with priority response times
-
-### Overview
-
-- **C++ style engine**: Forged on the 2nd-gen Unistyles C++ engine. Injects styles directly into the ShadowTree without triggering React re-renders — a direct, optimized highway between classNames and the native layer
-- **Performance**: Benchmarked at ~55ms (vs StyleSheet 49ms, traditional Uniwind 81ms, NativeWind 197ms) — near-native speed
-- **55+ className props** update without re-renders across 20 components (all component bindings listed above)
-- **Reanimated animations**: `animate-*` and `transition-*` via className (Reanimated v4)
-- **Native insets & runtime values**: Automatic safe area injection, device rotation, and font size updates — no `SafeAreaListener` setup needed
-- **Theme transitions**: Native animated transitions when switching themes (fade, slide, circle mask)
-- **Group variants**: Tailwind `group-active:*` / `group-focus:*` propagate parent interaction state through the C++ shadow tree with zero re-renders
-- **Default styles**: Experimental `1.2.0+` feature for styling default React Native components from CSS selectors like `View { ... }` and `Text { ... }`
-- **Priority support**: Don't let technical hurdles slow your team down
-
-Package: `"uniwind": "npm:uniwind-pro@latest"` in `package.json`.
-
-### Installation
-
-1. Set dependency alias in `package.json`:
- ```json
- { "dependencies": { "uniwind": "npm:uniwind-pro@latest" } }
- ```
-
-2. Install peer dependencies:
- ```bash
- npm install react-native-nitro-modules react-native-reanimated react-native-worklets
- ```
-
-3. Authenticate: `npx uniwind-pro` (interactive — select "Login with GitHub")
-
-4. Add Babel plugin — APPEND `react-native-worklets/plugin` to your existing `plugins` array. Do NOT replace your presets (keep `babel-preset-expo` for Expo, or your bare-RN preset):
- ```js
- // babel.config.js
- module.exports = {
- // your existing presets and config — leave untouched
- plugins: [
- // ...other plugins
- 'react-native-worklets/plugin',
- ],
- };
- ```
- If you already use Reanimated, you may already have the worklets plugin configured.
-
-5. Whitelist postinstall if needed:
- - **bun**: Add `"trustedDependencies": ["uniwind"]` to `package.json`
- - **yarn v2+**: Configure in `.yarnrc.yml`
- - **pnpm**: `pnpm config set enable-pre-post-scripts true`
-
-6. Rebuild native app:
- ```bash
- npx expo prebuild --clean && npx expo run:ios
- ```
-
-Pro does **NOT** work with Expo Go. Requires native rebuild.
-
-**Verify installation**: Check for native modules (`.cpp`, `.mm` files) in `node_modules/uniwind`.
-
-### Reanimated Animations (Requires Reanimated v4.0.0+)
-
-```tsx
-
-
-
-
-
-// Loading spinner
-
-```
-
-Custom keyframe animations beyond Tailwind defaults:
-
-| Class | Description |
-|-------|-------------|
-| `animate-wiggle` | Rotational wiggle |
-| `animate-shake` | Horizontal shake |
-| `animate-flash` | Opacity flash on/off |
-| `animate-rubber-band` | Elastic scale stretch |
-| `animate-swing` | Pendulum swing |
-| `animate-tada` | Scale + rotate attention seeker |
-| `animate-heartbeat` | Double-pulse heartbeat |
-| `animate-jello` | Rotational jello wobble |
-| `animate-float` | Gentle vertical float |
-| `animate-breathe` | Subtle breathing scale |
-| `animate-tilt` | Alternating tilt rotation |
-| `animate-glitch` | Rapid horizontal jitter |
-
-Components auto-swap to Animated versions when animation classes detected:
-
-| Component | Animated Version |
-|-----------|------------------|
-| `View` | `Animated.View` |
-| `Text` | `Animated.Text` |
-| `Image` | `Animated.Image` |
-| `ImageBackground` | `Animated.ImageBackground` |
-| `ScrollView` | `Animated.ScrollView` |
-| `FlatList` | `Animated.FlatList` |
-| `TextInput` | `Animated.TextInput` |
-| `Pressable` | `Animated.Pressable` |
-
-### Entering & Exiting Animations
-
-Drive Reanimated's entering/exiting animations via className — no Reanimated imports needed. Components auto-upgrade when `uw-*` classes are detected.
-
-```tsx
-// Bounce in, bounce out
-{visible && }
-
-// Fade in slowly (1000ms)
-{visible && }
-```
-
-**Entering presets**: `uw-entering-fade-in` `uw-entering-fade-in-right` `uw-entering-fade-in-left` `uw-entering-fade-in-up` `uw-entering-fade-in-down` `uw-entering-slide-in-right` `uw-entering-slide-in-left` `uw-entering-slide-in-up` `uw-entering-slide-in-down` `uw-entering-zoom-in` `uw-entering-zoom-in-rotate` `uw-entering-zoom-in-left` `uw-entering-zoom-in-right` `uw-entering-zoom-in-up` `uw-entering-zoom-in-down` `uw-entering-zoom-in-easy-up` `uw-entering-zoom-in-easy-down` `uw-entering-bounce-in` `uw-entering-bounce-in-down` `uw-entering-bounce-in-up` `uw-entering-bounce-in-left` `uw-entering-bounce-in-right` `uw-entering-flip-in-x-up` `uw-entering-flip-in-x-down` `uw-entering-flip-in-y-left` `uw-entering-flip-in-y-right` `uw-entering-flip-in-easy-x` `uw-entering-flip-in-easy-y` `uw-entering-stretch-in-x` `uw-entering-stretch-in-y` `uw-entering-rotate-in-down-left` `uw-entering-rotate-in-down-right` `uw-entering-rotate-in-up-left` `uw-entering-rotate-in-up-right` `uw-entering-roll-in-left` `uw-entering-roll-in-right` `uw-entering-pinwheel-in` `uw-entering-light-speed-in-right` `uw-entering-light-speed-in-left`
-
-**Exiting presets**: `uw-exiting-fade-out` `uw-exiting-fade-out-right` `uw-exiting-fade-out-left` `uw-exiting-fade-out-up` `uw-exiting-fade-out-down` `uw-exiting-slide-out-right` `uw-exiting-slide-out-left` `uw-exiting-slide-out-up` `uw-exiting-slide-out-down` `uw-exiting-zoom-out` `uw-exiting-zoom-out-rotate` `uw-exiting-zoom-out-left` `uw-exiting-zoom-out-right` `uw-exiting-zoom-out-up` `uw-exiting-zoom-out-down` `uw-exiting-zoom-out-easy-up` `uw-exiting-zoom-out-easy-down` `uw-exiting-bounce-out` `uw-exiting-bounce-out-down` `uw-exiting-bounce-out-up` `uw-exiting-bounce-out-left` `uw-exiting-bounce-out-right` `uw-exiting-flip-out-x-up` `uw-exiting-flip-out-x-down` `uw-exiting-flip-out-y-left` `uw-exiting-flip-out-y-right` `uw-exiting-flip-out-easy-x` `uw-exiting-flip-out-easy-y` `uw-exiting-stretch-out-x` `uw-exiting-stretch-out-y` `uw-exiting-rotate-out-down-left` `uw-exiting-rotate-out-down-right` `uw-exiting-rotate-out-up-left` `uw-exiting-rotate-out-up-right` `uw-exiting-roll-out-left` `uw-exiting-roll-out-right` `uw-exiting-pinwheel-out` `uw-exiting-light-speed-out-right` `uw-exiting-light-speed-out-left`
-
-**Animation modifiers** (pattern: `uw-{entering|exiting|layout}-{modifier}`):
-- Duration: `uw-{type}-duration-75` `uw-{type}-duration-100` ... `uw-{type}-duration-1000` or arbitrary `uw-{type}-duration-{ms}`
-- Delay: `uw-{type}-delay-75` ... `uw-{type}-delay-1000` or arbitrary `uw-{type}-delay-{ms}`
-- Easing: `uw-{type}-ease-linear` `uw-{type}-ease-in` `uw-{type}-ease-out` `uw-{type}-ease-in-out` `uw-{type}-ease-bounce`
-- Spring: `uw-{type}-springify` `uw-{type}-damping-{value}` `uw-{type}-stiffness-{value}` `uw-{type}-mass-{value}`
-
-### Layout Transitions
-
-Animate position/size changes when siblings are added or removed:
-
-```tsx
-
- {items.map(item => (
-
- ))}
-
-```
-
-| Class | Description |
-|-------|-------------|
-| `uw-layout-linear-transition` | Smooth linear repositioning |
-| `uw-layout-fading-transition` | Fade during repositioning |
-| `uw-layout-jumping-transition` | Bouncy jump to new position |
-| `uw-layout-curved-transition` | Curved path repositioning |
-| `uw-layout-sequenced-transition` | Sequenced repositioning |
-| `uw-layout-entry-exit-transition` | Combined entry/exit during layout |
-
-### Transitions
-
-Smooth property changes when className or state changes:
-
-```tsx
-// Color transition on press
-
-
-// Opacity transition
-
-
-// Transform transition
-
-
-// All properties
-
- Animated Button
-
-```
-
-| Class | Properties |
-|-------|------------|
-| `transition-none` | No transition |
-| `transition-all` | All properties |
-| `transition-colors` | Background, border, text colors |
-| `transition-opacity` | Opacity |
-| `transition-shadow` | Box shadow |
-| `transition-transform` | Scale, rotate, translate |
-
-Duration: `duration-75` `duration-100` `duration-150` `duration-200` `duration-300` `duration-500` `duration-700` `duration-1000`
-
-Easing: `ease-linear` `ease-in` `ease-out` `ease-in-out`
-
-Delay: `delay-75` `delay-100` `delay-150` `delay-200` `delay-300` `delay-500` `delay-700` `delay-1000`
-
-### Using Reanimated Directly
-
-Still works with Uniwind classes:
-
-```tsx
-import Animated, { FadeIn, FlipInXUp, LinearTransition } from 'react-native-reanimated';
-
-
- Fading in
-
-
- (
-
- {item}
-
- )}
-/>
-```
-
-### Shadow Tree Updates
-
-No code changes needed — props connect directly to C++ engine, eliminating re-renders automatically.
-
-### Shadow Tree Diagnostics
-
-Development-only API to observe what the C++ engine is doing — when components register/unregister with the shadow tree and how styles flow through it. Import from `uniwind/diagnostics`:
-
-```tsx
-import { enableDiagnostics } from 'uniwind/diagnostics';
-
-enableDiagnostics({
- reportMounts: true, // log when components register with the shadow tree
- reportUnmounts: true, // log when components unregister
- reportUpdates: true, // log style updates with property-level detail
-});
-```
-
-All three options default to `false` — enable only what you need (logging everything on a complex screen gets noisy). Update logs are grouped into 🔥 C++ updates (applied via the shadow tree) and ✨ Native updates (props set directly on native views) — both happen with zero React re-renders.
-
-Use for: debugging theme switches (`reportUpdates`), detecting memory leaks (mount/unmount counts should return to zero when navigating away), and verifying zero re-renders.
-
-Platform support: full diagnostics on iOS and Android. On Web, `enableDiagnostics` is a no-op stub that produces no output.
-
-### Group Variants
-
-Tailwind `group` variants propagate parent interaction state to descendants through the C++ shadow tree. No re-renders, no context providers.
-
-```tsx
-// Basic group — descendants react to parent press
-
- Press the card
-
-
-
-// Named groups — descendants pick which ancestor to follow
-
-
-
- Nested groups
-
-
-
-```
-
-**Supported variants**: `group-active:*` (press), `group-focus:*` (focus). Named variants: `group-active/{name}:*`, `group-focus/{name}:*`.
-
-**Supported group parents**: `Pressable` (press + focus), `Text` (press — requires `onPress`, even empty). `TouchableOpacity`, `TouchableHighlight`, `TouchableWithoutFeedback`, and `TextInput` do **not** act as group parents — wrap in a `Pressable` marked `group`.
-
-**Not supported**: `group-hover:*` (no pointer hover on native), `group-disabled:*` (parsed but no shadow tree trigger), arbitrary `group-[.selector]:*` variants, implicit `in-*` variants.
-
-### Default Styles (Pro 1.2.0+, Experimental)
-
-Default styles let Pro users define baseline styles for built-in React Native components directly in CSS. They are disabled by default and require an experimental flag.
-
-```js
-// metro.config.js
-module.exports = withUniwindConfig(config, {
- cssEntryFile: './global.css',
- experimental: {
- defaultStyles: true,
- },
-});
-```
-
-```css
-/* global.css */
-View {
- border-color: var(--color-primary);
-}
-
-Text {
- font-family: Inter;
- font-size: 16px;
-}
-```
-
-Effect: every `View` gets `border-color: var(--color-primary)`, every `Text` gets `font-family: Inter` and `font-size: 16px`, unless more specific styles override them.
-
-Rules:
-- Available only in Uniwind Pro `1.2.0+`
-- Disabled by default; enable `experimental.defaultStyles: true`
-- Experimental; may not work for every use case and may change in future releases
-- Use React Native component names as selectors, not HTML tags
-- Treat as baseline styles; direct `className` styles can override them
-
-Supported component selectors: `ActivityIndicator`, `FlatList`, `Image`, `ImageBackground`, `InputAccessoryView`, `KeyboardAvoidingView`, `Modal`, `Pressable`, `RefreshControl`, `SafeAreaView`, `ScrollView`, `SectionList`, `Switch`, `Text`, `TextInput`, `TouchableHighlight`, `TouchableNativeFeedback`, `TouchableOpacity`, `TouchableWithoutFeedback`, `View`, `VirtualizedList`.
-
-### Suspense Support
-
-Components inside React `Suspense` boundaries are handled correctly. While a subtree is suspended, Uniwind keeps the C++ shadow entries alive so theme updates and runtime changes (dark mode, orientation, etc.) still reach suspended nodes. When the tree unsuspends, styles are already up to date — no flash of stale theme.
-
-### Native Insets
-
-Remove `SafeAreaListener` setup — insets injected from native layer:
-
-```tsx
-// With Pro — just use safe area classes directly
-{/* content */}
-```
-
-### Theme Transitions (Pro)
-
-Native animated transitions when switching themes. Supported on iOS, Android, and Web.
-
-```tsx
-import { Uniwind, ThemeTransitionPreset } from 'uniwind';
-
-// Fade transition
-Uniwind.setTheme('dark', { preset: ThemeTransitionPreset.Fade });
-
-// Slide transitions
-Uniwind.setTheme('dark', { preset: ThemeTransitionPreset.SlideRightToLeft });
-Uniwind.setTheme('light', { preset: ThemeTransitionPreset.SlideLeftToRight });
-
-// Circle mask transitions (expand from a corner or center)
-Uniwind.setTheme('ocean', { preset: ThemeTransitionPreset.CircleCenter });
-
-// Blur transitions
-Uniwind.setTheme('dark', { preset: ThemeTransitionPreset.Blur });
-Uniwind.setTheme('dark', { preset: ThemeTransitionPreset.BlurRightToLeft });
-
-// No animation
-Uniwind.setTheme('light');
-```
-
-Available presets:
-
-| Preset | Effect |
-|--------|--------|
-| `ThemeTransitionPreset.None` | Instant switch, no animation |
-| `ThemeTransitionPreset.Fade` | Crossfade between themes |
-| `ThemeTransitionPreset.SlideRightToLeft` | Slide new theme in from right |
-| `ThemeTransitionPreset.SlideLeftToRight` | Slide new theme in from left |
-| `ThemeTransitionPreset.CircleTopRight` | Circle mask expanding from top-right |
-| `ThemeTransitionPreset.CircleTopLeft` | Circle mask expanding from top-left |
-| `ThemeTransitionPreset.CircleBottomRight` | Circle mask expanding from bottom-right |
-| `ThemeTransitionPreset.CircleBottomLeft` | Circle mask expanding from bottom-left |
-| `ThemeTransitionPreset.CircleCenter` | Circle mask expanding from center |
-| `ThemeTransitionPreset.Blur` | Blur out animation |
-| `ThemeTransitionPreset.BlurRightToLeft` | Directional blur from right to left |
-| `ThemeTransitionPreset.BlurLeftToRight` | Directional blur from left to right |
-
-## Setup Diagnostics
-
-When styles aren't working, check in this order:
-
-### 1. package.json
-- `"uniwind"` (or `"uniwind-pro"`) in dependencies
-- `"tailwindcss"` at v4+ (`^4.0.0`)
-- For Pro: `react-native-nitro-modules`, `react-native-reanimated`, `react-native-worklets`
-
-### 2. metro.config.js
-- `withUniwindConfig` imported from `'uniwind/metro'`
-- `withUniwindConfig` is the **outermost** wrapper
-- `cssEntryFile` is a **relative path string** (e.g., `'./global.css'`)
-- No `path.resolve()` or absolute paths
-- For Pro default styles: `experimental.defaultStyles: true` is set
-
-### 3. global.css
-- Contains `@import 'tailwindcss';` AND `@import 'uniwind';`
-- Imported in `App.tsx` or root layout, **NOT** in `index.ts`/`index.js`
-- Location determines app root for Tailwind scanning
-
-### 4. babel.config.js (Pro only)
-- `'react-native-worklets/plugin'` in plugins array
-
-### 5. TypeScript
-- `uniwind-types.d.ts` exists (generated after running Metro)
-- Included in `tsconfig.json` or placed in `src/`/`app/` dir
-
-### 6. Build
-- Metro server restarted after config changes
-- Metro cache cleared (`npx expo start --clear` or `npx react-native start --reset-cache`)
-- Native rebuild done (if Pro or after dependency changes)
-
-## Troubleshooting
-
-| Symptom | Cause | Fix |
-|---------|-------|-----|
-| Styles not applying | Missing imports in global.css | Add `@import 'tailwindcss'; @import 'uniwind';` |
-| Styles not applying | global.css imported in index.js | Move import to App.tsx or `_layout.tsx` |
-| Classes not detected | global.css in nested dir, components elsewhere | Add `@source '../components'` in global.css |
-| TypeScript errors on className | Missing types file | Run Metro to generate `uniwind-types.d.ts` |
-| `withUniwindConfig is not a function` | Wrong import | Use `require('uniwind/metro')` not `require('uniwind')` |
-| Hot reload full-reloads | global.css imported in wrong file | Move to App.tsx or root layout |
-| `cssEntryFile` error / Metro crash | Absolute path used | Use relative: `'./global.css'` |
-| `withUniwindConfig` not outermost | Another wrapper wraps Uniwind | Swap order so Uniwind is outermost |
-| Dark theme not working | Missing `@variant dark` | Define dark variant in `@layer theme` |
-| Custom theme not appearing | Not registered in metro config | Add to `extraThemes` array, restart Metro |
-| Fonts not loading | Font name mismatch | CSS font name must match file name exactly (no extension) |
-| `rem` values too large/small | Wrong base rem | Set `polyfills: { rem: 14 }` for NativeWind compat |
-| Unsupported CSS warning | Web-specific CSS used | Enable `debug: true` to identify; remove unsupported properties |
-| `Failed to serialize javascript object` | Complex CSS, circular refs, or stale cache | Clear caches: `watchman watch-del-all; rm -rf node_modules/.cache; npx expo start --clear`. Also check if docs/markdown files containing CSS classes are in the scan path (see below) |
-| `Failed to serialize javascript object` from llms-full.txt or docs | Docs/markdown files with CSS classes in project dir get scanned by Tailwind | Move `.md` files with CSS examples outside the project root, or add to `.gitignore` so Tailwind's scanner skips them |
-| `unstable_enablePackageExports` conflict | App disables package exports | Use selective resolver for Uniwind and culori |
-| Classes from monorepo package missing | Not included in Tailwind scan | Add `@source '../../packages/ui'` in global.css |
-| Classes from `node_modules` library missing in production (bun) | Bun uses symlinks; Tailwind's Oxide scanner can't follow them | Use resolved path: `@source "../../node_modules/heroui-native/lib"` and add `public-hoist-pattern[]=heroui-native` to `.npmrc` |
-| `active:` not working with `withUniwind` | `withUniwind` does NOT support interactive state selectors | Only core RN `Pressable`/`TextInput`/`Switch` support `active:`/`focus:`/`disabled:`. Third-party pressables wrapped with `withUniwind` won't get states |
-| `withUniwind` custom mapping overrides `className`+`style` merging | When manual mapping is provided, `style` prop is not merged | Use auto mapping (no second arg) for `className`+`style` merge. For manual mapping + `className`, double-wrap: `withUniwind(withUniwind(Comp), { mapping })` |
-| `withUniwind` loses generic types on `ref` (e.g., `FlashList`) | TypeScript limitation with HOCs | Cast the ref manually: `ref={scrollRef as any}` |
-| Platform-specific fonts: `@theme` block error | `@media ios/android` inside `@theme {}` | Use `@layer theme { :root { @variant ios { ... } } }` instead — `@theme` only accepts custom properties, and platform selection uses `@variant` not `@media` |
-| `Uniwind.setTheme('system')` crash on Android (RN 0.82+) | RN 0.82 changed Appearance API | Update to latest Uniwind (fixed). Avoid `setTheme('system')` on older Uniwind + RN 0.82+ |
-| Styles flash/disappear on initial load (Android) | `SafeAreaListener` fires before component listeners mount | Fixed in recent versions. If persists, ensure Uniwind is latest |
-| `useTVEventHandler` is undefined | Uniwind module replacement interferes with tvOS exports | Fixed in v1.2.1+. Update Uniwind |
-| `@layer theme` variables not rendering on web | Bug with RNW + Expo SDK 55 | Fixed in v1.4.1+. Update Uniwind |
-| `updateCSSVariables` wrong theme at app start | Calling for multiple themes back-to-back; last call wins on first render | Call `updateCSSVariables` for the current theme last. After initial load, order doesn't matter |
-| Pro: animations not working | Missing Babel plugin | Add `react-native-worklets/plugin` to babel.config.js |
-| Pro: module not found | No native rebuild | Run `npx expo prebuild --clean` then `npx expo run:ios` |
-| Pro: postinstall failed | Package manager blocks scripts | Add to `trustedDependencies` (bun) or configure yarn/pnpm |
-| Pro: auth expired | Login session expired (180-day lifetime) | Run `npx uniwind-pro`, re-login |
-| Pro: download limit reached | Monthly download limit hit | Check Pro dashboard, limits reset monthly |
-| Pro: `Uniwind.updateInsets` called unnecessarily | Pro injects insets natively | `Uniwind.updateInsets` is a no-op in Pro. Remove `SafeAreaListener` setup when using Pro |
-| Pro: theme transition crash | Missing `ThemeTransitionPreset` import or calling before app is ready | Import from `'uniwind'`. Ensure the app has fully mounted before calling `setTheme` with a transition |
-| Pro: default component styles not applying | Feature disabled or unsupported selector | Use Uniwind Pro 1.2.0+, enable `experimental.defaultStyles: true`, restart Metro, and use supported RN component selectors like `View` or `Text` |
-
-### unstable_enablePackageExports Selective Resolver
-
-If your app disables `unstable_enablePackageExports` (common in crypto apps), use a selective resolver:
-
-```js
-config.resolver.unstable_enablePackageExports = false;
-config.resolver.resolveRequest = (context, moduleName, platform) => {
- if (['uniwind', 'culori'].some((prefix) => moduleName.startsWith(prefix))) {
- return context.resolveRequest(
- { ...context, unstable_enablePackageExports: true },
- moduleName,
- platform
- );
- }
- return context.resolveRequest(context, moduleName, platform);
-};
-```
-
-## FAQ
-
-**Where to put global.css in Expo Router?**
-Project root. Import in `app/_layout.tsx`. If placed in `app/`, add `@source` for sibling dirs.
-
-**Does Uniwind work with Expo Go?**
-Free: Yes. Pro: No — requires native rebuild (development builds).
-
-**Can I use tailwind.config.js?**
-No. Uniwind uses Tailwind v4 — all config via `@theme` in `global.css`.
-
-**How to access CSS variables in JS?**
-Inside components: `useCSSVariable('--color-primary')` (reactive). Outside React: `Uniwind.getCSSVariable('--color-primary')` (one-shot, 1.6.4+). For variables not used in classNames, define with `@theme static`.
-
-**Can I use Platform.select()?**
-Yes, but prefer platform selectors (`ios:pt-12 android:pt-6`) — cleaner, no imports.
-
-**Next.js support?**
-Not officially supported. Community plugin: `uniwind-plugin-next`. For Next.js, use standard Tailwind CSS.
-
-**Vite support?**
-Yes, since v1.2.0. Use `uniwind/vite` plugin alongside `@tailwindcss/vite`.
-
-**Full app reloads on CSS changes?**
-Metro can't hot-reload files with many providers. Move `global.css` import deeper in the component tree.
-
-**Style specificity?**
-Important utilities like `bg-red-500!` override non-important utilities for the same property and work with variants (`active:bg-red-500!`, `ios:pt-12!`). Inline `style` always overrides `className`, even important utilities. Use `className` for static styles, inline only for truly dynamic values. Use `cn()` from tailwind-merge for component libraries where classNames may conflict.
-
-**How do I include custom fonts?**
-Load font files (Expo: `expo-font` plugin in `app.json`; Bare RN: `react-native-asset`), then map in CSS: `@theme { --font-sans: 'Roboto-Regular'; }`. Font name must exactly match the file name. See the **Fonts** section above.
-
-**How can I style based on prop values?**
-Use data selectors: `data-[selected=true]:ring-2`. Only equality checks supported. See the **Data Selectors** section above.
-
-**How can I use gradients?**
-Built-in: `bg-gradient-to-r from-red-500 to-green-500`. Also supports angle-based (`bg-linear-90`) and arbitrary values (`bg-linear-[45deg,#f00_0%,#00f_100%]`). See the **Gradients** section above.
-
-**How does className deduplication work?**
-Uniwind does NOT auto-deduplicate conflicting classNames. Use `tailwind-merge` with a `cn()` utility. See the **cn Utility** section above.
-
-**How to debug 'Failed to serialize javascript object'?**
-Clear caches: `watchman watch-del-all; rm -rf node_modules/.cache; npx expo start --clear`. Enable `debug: true` in metro config to identify the problematic CSS pattern. See the **Troubleshooting** table above.
-
-**How do I enable safe area classNames?**
-Free: Install `react-native-safe-area-context`, wrap root with `SafeAreaListener`, call `Uniwind.updateInsets(insets)`. Pro: Automatic — no setup. Then use `pt-safe`, `pb-safe`, etc. See the **Safe Area Utilities** section above.
-
-**What UI kits work well with Uniwind?**
-**React Native Reusables** (shadcn philosophy, copy-paste components) and **HeroUI Native** (complete library, optimized for Uniwind). Any library works via `withUniwind` wrapper. See the **UI Kit Compatibility** section above.
-
-**Can I scope a theme to a single component?**
-Yes, use `ScopedTheme`: ``. It forces a theme for the subtree without changing the global theme. See the **Theming** section.
-
-**Does `active:` work with `react-native-gesture-handler` Pressable?**
-No. `withUniwind` does NOT support interactive state selectors (`active:`, `focus:`, `disabled:`). Only core RN `Pressable`, `TextInput`, and `Switch` support them. For RNGH components, use `onPressIn`/`onPressOut` with state.
-
-**Can I customize the default `border` color?**
-Yes — use `@utility border` to override the class entirely:
-```css
-@utility border {
- border-width: 1px;
- border-style: solid;
- border-color: var(--color-primary);
-}
-```
-This completely replaces the built-in `border` behavior, so re-declare any properties you still need. Alternatively, use `border border-gray-300` explicitly or define `--color-border` in `@theme` and use `border-border`.
-
-**Can I use platform-specific fonts in `@theme {}`?**
-No. `@theme {}` only accepts custom properties. Use `@layer theme { :root { @variant ios { --font-sans: '...'; } } }` instead. Note: use `@variant` (not `@media`) for platform selection in CSS.
-
-**Does Uniwind work with ESM metro config (`metro.config.mjs` or `metro.config.ts`)?**
-Yes since v1.3.0+. If you hit `Class extends value is not a constructor`, update Uniwind or use CommonJS `metro.config.js`.
-
-**Classes from `node_modules` work in dev but not production (bun)?**
-Bun symlinks packages. Tailwind's Oxide scanner can't follow them. Use resolved `@source` paths and hoist the package. See **UI Kit Compatibility** for details.
-
-**How to clear all caches when debugging?**
-`watchman watch-del-all 2>/dev/null; rm -rf node_modules/.cache && npx expo start --clear`. This clears Watchman, Babel/bundler caches, and Expo internal cache.
-
-## MCP Server
-
-Uniwind provides an official MCP server for AI-assisted development. If the user's environment supports MCP, recommend setting it up: [https://docs.uniwind.dev/mcp](https://docs.uniwind.dev/mcp)
+1. Identify whether user needs setup, styling, theming, variants, integrations, Pro, or troubleshooting help.
+2. Read the matching reference file before giving detailed guidance or editing code.
+3. Apply the Critical Rules above even if the selected reference omits them.
+4. Do not guess Uniwind APIs. If unsure, verify against official docs: https://docs.uniwind.dev/llms-full.txt
## Related Skills
-**NativeWind → Uniwind migration**: Use the `migrate-nativewind-to-uniwind` skill for migrating from NativeWind. It handles package removal, config migration, Tailwind v4 upgrade, `cssInterop` removal, theme conversion, and all breaking changes. It is tested and production-ready.
-
-**IMPORTANT**: Do NOT guess Uniwind APIs. If you are unsure about any Uniwind API, hook, component, or configuration option, fetch and verify against the official docs: [https://docs.uniwind.dev/llms-full.txt](https://docs.uniwind.dev/llms-full.txt)
+NativeWind migration is intentionally separate. Use the `migrate-nativewind-to-uniwind` skill when the user wants to migrate from NativeWind.
diff --git a/skills/uniwind/references/component-bindings.md b/skills/uniwind/references/component-bindings.md
new file mode 100644
index 00000000..94e2b7cc
--- /dev/null
+++ b/skills/uniwind/references/component-bindings.md
@@ -0,0 +1,338 @@
+## Component Bindings
+
+All core React Native components support `className` out of the box. Some have additional className props for sub-styles (like `contentContainerClassName`) and non-style color props (requiring `accent-` prefix).
+
+### Complete Reference
+
+**Legend**: Props marked with ⚡ require the `accent-` prefix. Props in parentheses are platform-specific.
+
+#### View
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+
+#### Text
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `selectionColorClassName` | `selectionColor` | ⚡ `accent-` |
+
+#### Pressable
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+
+Supports `active:`, `disabled:`, `focus:` state selectors.
+
+#### Image
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `tintColorClassName` | `tintColor` | ⚡ `accent-` |
+
+#### TextInput
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `cursorColorClassName` | `cursorColor` | ⚡ `accent-` |
+| `selectionColorClassName` | `selectionColor` | ⚡ `accent-` |
+| `placeholderTextColorClassName` | `placeholderTextColor` | ⚡ `accent-` |
+| `selectionHandleColorClassName` | `selectionHandleColor` | ⚡ `accent-` |
+| `underlineColorAndroidClassName` | `underlineColorAndroid` (Android) | ⚡ `accent-` |
+
+Supports `focus:`, `active:`, `disabled:` state selectors.
+
+#### ScrollView
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `contentContainerClassName` | `contentContainerStyle` | — |
+| `endFillColorClassName` | `endFillColor` | ⚡ `accent-` |
+
+#### FlatList
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `contentContainerClassName` | `contentContainerStyle` | — |
+| `columnWrapperClassName` | `columnWrapperStyle` | — |
+| `ListHeaderComponentClassName` | `ListHeaderComponentStyle` | — |
+| `ListFooterComponentClassName` | `ListFooterComponentStyle` | — |
+| `endFillColorClassName` | `endFillColor` | ⚡ `accent-` |
+
+#### SectionList
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `contentContainerClassName` | `contentContainerStyle` | — |
+| `ListHeaderComponentClassName` | `ListHeaderComponentStyle` | — |
+| `ListFooterComponentClassName` | `ListFooterComponentStyle` | — |
+| `endFillColorClassName` | `endFillColor` | ⚡ `accent-` |
+
+#### VirtualizedList
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `contentContainerClassName` | `contentContainerStyle` | — |
+| `ListHeaderComponentClassName` | `ListHeaderComponentStyle` | — |
+| `ListFooterComponentClassName` | `ListFooterComponentStyle` | — |
+| `endFillColorClassName` | `endFillColor` | ⚡ `accent-` |
+
+#### Switch
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `thumbColorClassName` | `thumbColor` | ⚡ `accent-` |
+| `trackColorOnClassName` | `trackColor.true` (on) | ⚡ `accent-` |
+| `trackColorOffClassName` | `trackColor.false` (off) | ⚡ `accent-` |
+| `ios_backgroundColorClassName` | `ios_backgroundColor` (iOS) | ⚡ `accent-` |
+
+Note: Switch does NOT support `className` (`className?: never` in types). Use only the color-specific className props above. Supports `disabled:` state selector.
+
+#### ActivityIndicator
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `colorClassName` | `color` | ⚡ `accent-` |
+
+#### Button
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `colorClassName` | `color` | ⚡ `accent-` |
+
+Note: Button does not support `className` (no `style` prop on RN Button).
+
+#### Modal
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `backdropColorClassName` | `backdropColor` | ⚡ `accent-` |
+
+#### RefreshControl
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `colorsClassName` | `colors` (Android) | ⚡ `accent-` |
+| `tintColorClassName` | `tintColor` (iOS) | ⚡ `accent-` |
+| `titleColorClassName` | `titleColor` (iOS) | ⚡ `accent-` |
+| `progressBackgroundColorClassName` | `progressBackgroundColor` (Android) | ⚡ `accent-` |
+
+#### ImageBackground
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `imageClassName` | `imageStyle` | — |
+| `tintColorClassName` | `tintColor` | ⚡ `accent-` |
+
+#### SafeAreaView
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+
+#### KeyboardAvoidingView
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `contentContainerClassName` | `contentContainerStyle` | — |
+
+#### InputAccessoryView
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `backgroundColorClassName` | `backgroundColor` | ⚡ `accent-` |
+
+#### TouchableHighlight
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+| `underlayColorClassName` | `underlayColor` | ⚡ `accent-` |
+
+Supports `active:`, `disabled:` state selectors.
+
+#### TouchableOpacity
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+
+Supports `active:`, `disabled:` state selectors.
+
+#### TouchableNativeFeedback
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+
+Supports `active:`, `disabled:` state selectors.
+
+#### TouchableWithoutFeedback
+
+| Prop | Maps to | Prefix |
+|------|---------|--------|
+| `className` | `style` | — |
+
+Supports `active:`, `disabled:` state selectors.
+
+### Usage Examples
+
+```tsx
+import { View, Text, Pressable, TextInput, ScrollView, FlatList, Switch, Image, ActivityIndicator, Modal, RefreshControl, Button } from 'react-native';
+
+// View — basic layout
+
+ Title
+
+
+// Pressable — with press/focus states
+
+ Press Me
+
+
+// TextInput — with focus state and accent- color props
+
+
+// ScrollView — with content container
+
+ {/* content */}
+
+
+// FlatList — with all sub-style props
+ }
+/>
+
+// Switch — no className support, use color-specific props only
+
+
+// Image — tint color
+
+
+// ActivityIndicator
+
+
+// Button — only colorClassName (no className)
+
+
+// Modal — backdrop color
+
+ {/* content */}
+
+
+// RefreshControl — platform-specific color props
+
+
+// ImageBackground — separate image styling
+
+ Overlay
+
+
+// KeyboardAvoidingView
+
+
+
+
+// InputAccessoryView
+
+
+
+
+// TouchableHighlight — underlay color
+
+ Press Me
+
+```
+
+## The accent- Prefix Pattern
+
+React Native components have props like `color`, `tintColor`, `thumbColor` that are NOT part of the `style` object. To set these via Tailwind classes, use the `accent-` prefix with the corresponding `{propName}ClassName` prop:
+
+```tsx
+// color prop → colorClassName with accent- prefix
+
+
+
+// tintColor prop → tintColorClassName
+
+
+// thumbColor → thumbColorClassName
+
+
+// placeholderTextColor → placeholderTextColorClassName
+
+```
+
+**CRITICAL Rule**: `className` maps to the `style` prop — it handles layout, typography, backgrounds, borders, etc. But React Native has many color props that live OUTSIDE of `style` (like `color`, `tintColor`, `thumbColor`, `placeholderTextColor`). These require a separate `{propName}ClassName` prop with the `accent-` prefix. Without `accent-`, the class resolves to a style object — but these props expect a plain color string.
+
+```tsx
+// WRONG — className sets style, but ActivityIndicator's color is NOT a style prop
+ // color will NOT be set
+
+// CORRECT — use the dedicated colorClassName prop with accent- prefix
+ // color IS set to #3b82f6
+
+// WRONG — tintColor is not a style prop on Image
+ // won't work
+
+// CORRECT
+
+```
diff --git a/skills/uniwind/references/css-and-utilities.md b/skills/uniwind/references/css-and-utilities.md
new file mode 100644
index 00000000..e6f88d5f
--- /dev/null
+++ b/skills/uniwind/references/css-and-utilities.md
@@ -0,0 +1,325 @@
+## CSS Functions
+
+Uniwind provides CSS functions for device-aware and theme-aware styling. These can be used everywhere (custom CSS classes, `@utility`, etc.) — but NOT inside `@theme {}` (which only accepts static values). Use `@utility` to create reusable Tailwind-style utility classes:
+
+### hairlineWidth()
+
+Returns the thinnest line width displayable on the device. Use for subtle borders and dividers.
+
+```css
+@utility h-hairline { height: hairlineWidth(); }
+@utility border-hairline { border-width: hairlineWidth(); }
+@utility w-hairline { width: calc(hairlineWidth() * 10); }
+```
+
+```tsx
+
+
+```
+
+### fontScale(multiplier?)
+
+Multiplies a base value by the device's font scale accessibility setting. Ensures text respects user preferences for larger or smaller text.
+
+- **`fontScale()`** — uses multiplier 1 (device font scale × 1)
+- **`fontScale(0.9)`** — smaller scale
+- **`fontScale(1.2)`** — larger scale
+
+```css
+@utility text-sm-scaled { font-size: fontScale(0.9); }
+@utility text-base-scaled { font-size: fontScale(); }
+@utility text-lg-scaled { font-size: fontScale(1.2); }
+```
+
+```tsx
+Small accessible text
+Regular accessible text
+```
+
+### pixelRatio(multiplier?)
+
+Multiplies a value by the device's pixel ratio. Creates pixel-perfect designs that scale across screen densities.
+
+- **`pixelRatio()`** — uses multiplier 1 (device pixel ratio × 1)
+- **`pixelRatio(2)`** — double the pixel ratio
+
+```css
+@utility w-icon { width: pixelRatio(); }
+@utility w-avatar { width: pixelRatio(2); }
+```
+
+```tsx
+
+```
+
+### light-dark(lightValue, darkValue)
+
+Returns different values based on the current theme mode. Automatically adapts when the theme changes — no manual switching logic needed.
+
+- First parameter: value for light theme
+- Second parameter: value for dark theme
+
+```css
+@utility bg-adaptive { background-color: light-dark(#ffffff, #1f2937); }
+@utility text-adaptive { color: light-dark(#111827, #f9fafb); }
+@utility border-adaptive { border-color: light-dark(#e5e7eb, #374151); }
+```
+
+```tsx
+
+ Adapts to light/dark theme
+
+```
+
+Also works in custom CSS classes (not just `@utility`):
+
+```css
+.adaptive-card {
+ background-color: light-dark(#ffffff, #1f2937);
+ color: light-dark(#111827, #f9fafb);
+}
+```
+
+## Custom CSS & Utilities
+
+### Custom CSS Classes
+
+Uniwind supports custom CSS class names defined in `global.css`. They are compiled at build time — no runtime overhead. Use them when you need styles that are hard to express as Tailwind utilities (e.g., complex box-shadow, multi-property bundles).
+
+```css
+/* global.css */
+.card-shadow {
+ background-color: white;
+ border-radius: 12px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+}
+
+.adaptive-surface {
+ background-color: light-dark(#ffffff, #1f2937);
+ color: light-dark(#111827, #f9fafb);
+}
+
+.container {
+ flex: 1;
+ width: 100%;
+ max-width: 1200px;
+}
+```
+
+Apply via `className` just like any Tailwind class:
+
+```tsx
+
+```
+
+### Mixing Custom CSS with Tailwind
+
+You can combine custom CSS classes with Tailwind utilities in a single `className`:
+
+```tsx
+
+ {title}
+ {children}
+
+```
+
+**WARNING**: If a custom CSS class and a Tailwind utility set the **same property**, you **MUST** use `cn()` to deduplicate. Without `cn()`, both values apply and the result is unpredictable:
+
+```tsx
+// WRONG — .container sets flex:1, and flex-1 also sets flex:1 (harmless but wasteful)
+// WRONG — .container sets width:100%, and w-full also sets width:100% (redundant)
+// DANGEROUS — .card-shadow sets border-radius:12px, and rounded-2xl sets border-radius:16px — CONFLICT!
+
+
+// CORRECT — cn ensures rounded-2xl wins
+import { cn } from '@/lib/cn';
+
+```
+
+**Rule of thumb**: If your custom CSS class sets properties that might overlap with Tailwind utilities you'll also use, always wrap with `cn()`. See **cn Utility** section for full setup.
+
+### Guidelines for Custom CSS
+
+- Keep selectors flat — no deep nesting or child selectors
+- Prefer Tailwind utilities for simple, single-property styles
+- Use custom classes for complex or multi-property bundles that would be verbose in className
+- Use `light-dark()` for theme-aware custom classes
+- Custom classes are great for shared design tokens that don't fit Tailwind's naming (e.g., `.card`, `.chip`, `.badge-dot`)
+
+### Custom Utilities (@utility)
+
+The `@utility` directive creates utility classes that work exactly like built-in Tailwind classes. Three main use cases:
+
+#### 1. Variable-driven utilities (runtime-injected values)
+
+Create a utility whose value comes from a CSS variable injected at runtime via `updateCSSVariables`. Use `@theme static` to declare the variable so Uniwind tracks it even before it is updated:
+
+```css
+/* global.css */
+@theme static {
+ --header-height: 0px;
+}
+
+@utility p-safe-header {
+ padding-top: var(--header-height);
+}
+```
+
+Inject the real value at runtime (e.g., from react-navigation's layout event):
+
+```tsx
+import { Uniwind } from 'uniwind'
+
+// e.g., inside a navigation layout listener
+Uniwind.updateCSSVariables(Uniwind.currentTheme, {
+ '--header-height': headerHeight,
+})
+```
+
+```tsx
+
+```
+
+#### 2. Brand-new utilities (no Tailwind equivalent)
+
+For styles that have no built-in Tailwind class:
+
+```css
+@utility h-hairline { height: hairlineWidth(); }
+@utility text-scaled { font-size: fontScale(); }
+@utility card-shadow {
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+}
+```
+
+Usage like any Tailwind class: ``
+
+#### 3. Overriding existing Tailwind utilities
+
+Use `@utility` to completely replace what a built-in class does. Example: make `border` always use `--color-primary`:
+
+```css
+@utility border {
+ border-width: 1px;
+ border-style: solid;
+ border-color: var(--color-primary);
+}
+```
+
+## @theme Directive
+
+Customize Tailwind design tokens in `global.css`:
+
+```css
+@theme {
+ /* Colors */
+ --color-primary: #3b82f6;
+ --color-brand-500: #3b82f6;
+ --color-brand-900: #1e3a8a;
+
+ /* Typography */
+ --font-sans: 'Roboto-Regular';
+ --font-sans-medium: 'Roboto-Medium';
+ --font-sans-bold: 'Roboto-Bold';
+ --font-mono: 'FiraCode-Regular';
+
+ /* Spacing & sizing */
+ --text-base: 15px;
+ --spacing-4: 16px;
+ --radius-lg: 12px;
+
+ /* Breakpoints */
+ --breakpoint-tablet: 820px;
+}
+```
+
+Usage: `bg-brand-500`, `text-brand-900`, `font-sans`, `font-mono`, `rounded-lg`.
+
+## Fonts
+
+React Native requires a **single font** per family — no fallbacks:
+
+```css
+@theme {
+ --font-sans: 'Roboto-Regular';
+ --font-sans-bold: 'Roboto-Bold';
+ --font-mono: 'FiraCode-Regular';
+}
+```
+
+Font name must **exactly match** the font file name (without extension).
+
+**Expo**: Configure fonts in `app.json` with the `expo-font` plugin, then reference in CSS.
+
+**Bare RN**: Use `react-native-asset` to link fonts, same CSS config.
+
+**Platform-specific fonts** (use `@variant`, not `@media`):
+
+```css
+@layer theme {
+ :root {
+ @variant ios { --font-sans: 'SF Pro Text'; }
+ @variant android { --font-sans: 'Roboto-Regular'; }
+ @variant web { --font-sans: 'system-ui'; }
+ }
+}
+```
+
+## Gradients
+
+Built-in support — no extra dependencies:
+
+```tsx
+
+ Gradient
+
+```
+
+For `expo-linear-gradient`, you can wrap it with `withUniwind` for className-based layout and styling (padding, border-radius, flex, etc.), but the `colors` prop is an array that cannot be resolved via className — it must be provided explicitly. Use `useCSSVariable` to get theme-aware colors:
+
+```tsx
+import { useCSSVariable } from 'uniwind';
+import { withUniwind } from 'uniwind';
+import { LinearGradient as RNLinearGradient } from 'expo-linear-gradient';
+
+const LinearGradient = withUniwind(RNLinearGradient);
+
+function GradientCard() {
+ // useCSSVariable returns string | number | undefined
+ const primary = useCSSVariable('--color-primary');
+ const secondary = useCSSVariable('--color-secondary');
+
+ // Guard against undefined — LinearGradient.colors requires valid ColorValues
+ if (!primary || !secondary) {
+ return null;
+ }
+
+ return (
+
+ Themed gradient
+
+ );
+}
+```
+
+Alternatively, export a wrapped component from a shared module for reuse:
+
+```tsx
+// components/styled.ts
+import { withUniwind } from 'uniwind';
+import { LinearGradient as RNLinearGradient } from 'expo-linear-gradient';
+
+export const LinearGradient = withUniwind(RNLinearGradient);
+```
+
+```tsx
+// usage — className handles layout, colors still passed manually
+import { LinearGradient } from '@/components/styled';
+
+
+ Static gradient
+
+```
diff --git a/skills/uniwind/references/integrations.md b/skills/uniwind/references/integrations.md
new file mode 100644
index 00000000..d88b75be
--- /dev/null
+++ b/skills/uniwind/references/integrations.md
@@ -0,0 +1,75 @@
+## React Navigation Integration
+
+Use `useResolveClassNames` for screen options that only accept `style` objects:
+
+```tsx
+import { useResolveClassNames } from 'uniwind';
+
+function Layout() {
+ const headerStyle = useResolveClassNames('bg-background');
+ const headerTitleStyle = useResolveClassNames('text-foreground font-bold');
+
+ return (
+
+ );
+}
+```
+
+Keep React Navigation's `` if already in use — it manages navigation-specific theming.
+
+## UI Kit Compatibility
+
+- **HeroUI Native**: Works with Uniwind. Uses `tailwind-variants` (tv) internally. Apply `className` directly on HeroUI components. **Bun users**: Bun uses symlinks for `node_modules`, which can cause Tailwind's Oxide scanner to miss library classes in production builds. Fix: use the resolved path in `@source` and hoist the package:
+ ```css
+ @source "../../node_modules/heroui-native/lib";
+ ```
+ ```ini
+ # .npmrc
+ public-hoist-pattern[]=heroui-native
+ ```
+- **react-native-reusables**: Compatible.
+- **Gluestack v4.1+**: Compatible.
+- **Lucide React Native**: Use `withUniwind(LucideIcon)` with `colorClassName="accent-blue-500"` for icon color. Works for all Lucide icons.
+- **@shopify/flash-list**: Use `withUniwind(FlashList)` for `className` and `contentContainerClassName` support. Note: `withUniwind` loses generic type params on `ref` — cast manually if needed.
+
+Use semantic color tokens (`bg-primary`, `text-foreground`) for theme consistency across UI kits.
+
+## Supported vs Unsupported Classes
+
+React Native uses the Yoga layout engine. Key differences from web CSS:
+- **No CSS cascade/inheritance** — styles don't inherit from parents
+- **Flexbox by default** — all views use flexbox with `flexDirection: 'column'`
+- **Limited CSS properties** — no floats, grid, pseudo-elements
+
+### Built-in Extra Utilities
+
+Uniwind provides additional utility classes for React Native features not covered by standard Tailwind:
+
+| Class | Effect |
+|-------|--------|
+| `border-continuous` | Sets `borderCurve: 'continuous'` — smooth, superellipse corners (iOS) |
+| `border-circular` | Sets `borderCurve: 'circular'` — standard circular corners (iOS default) |
+
+```tsx
+// Smooth iOS-style rounded corners (like SwiftUI's .continuous)
+
+ Smooth corners
+
+```
+
+### Supported (all standard Tailwind)
+
+Layout, spacing, sizing, typography, colors, borders, effects, flexbox, positioning, transforms, interactive states.
+
+### Unsupported (web-specific, silently ignored)
+
+- `hover:` `visited:` — use Pressable `active:` instead
+- `before:` `after:` `placeholder:` — pseudo-elements
+- `float-*` `clear-*` `columns-*`
+- `print:` `screen:`
+- `break-before-*` `break-after-*` `break-inside-*`
diff --git a/skills/uniwind/references/pro.md b/skills/uniwind/references/pro.md
new file mode 100644
index 00000000..b3ebe7d7
--- /dev/null
+++ b/skills/uniwind/references/pro.md
@@ -0,0 +1,354 @@
+## Uniwind Pro
+
+Paid upgrade with 100% API compatibility. Built on a 2nd-generation C++ engine for apps that demand the best performance. Graduated pricing (billed annually): **$99/seat** (1-3), **$49** (4-6), **$29** (7-15), **$1** (16+). Pricing and licensing: [https://uniwind.dev/pricing](https://uniwind.dev/pricing)
+
+### Pricing & Licensing
+
+- **Graduated per-seat pricing** (billed annually, VAT excluded unless applicable): $99 for seats 1-3, $49 for 4-6, $29 for 7-15, $1 for 16+
+- **Individual License**: Personal Pro license per engineer
+- **Team License**: Single key management — add or remove members instantly
+- **CI/CD License**: Full support for automated and headless build environments
+- **Enterprise**: Custom plans available (contact support@uniwind.dev)
+- **Priority Support**: Critical issues resolved with priority response times
+
+### Overview
+
+- **C++ style engine**: Forged on the 2nd-gen Unistyles C++ engine. Injects styles directly into the ShadowTree without triggering React re-renders — a direct, optimized highway between classNames and the native layer
+- **Performance**: Benchmarked at ~55ms (vs StyleSheet 49ms, traditional Uniwind 81ms, NativeWind 197ms) — near-native speed
+- **55+ className props** update without re-renders across 20 components (all component bindings listed above)
+- **Reanimated animations**: `animate-*` and `transition-*` via className (Reanimated v4)
+- **Native insets & runtime values**: Automatic safe area injection, device rotation, and font size updates — no `SafeAreaListener` setup needed
+- **Theme transitions**: Native animated transitions when switching themes (fade, slide, circle mask)
+- **Group variants**: Tailwind `group-active:*` / `group-focus:*` propagate parent interaction state through the C++ shadow tree with zero re-renders
+- **Default styles**: Experimental `1.2.0+` feature for styling default React Native components from CSS selectors like `View { ... }` and `Text { ... }`
+- **Priority support**: Don't let technical hurdles slow your team down
+
+Package: `"uniwind": "npm:uniwind-pro@latest"` in `package.json`.
+
+### Installation
+
+1. Set dependency alias in `package.json`:
+ ```json
+ { "dependencies": { "uniwind": "npm:uniwind-pro@latest" } }
+ ```
+
+2. Install peer dependencies:
+ ```bash
+ npm install react-native-nitro-modules react-native-reanimated react-native-worklets
+ ```
+
+3. Authenticate: `npx uniwind-pro` (interactive — select "Login with GitHub")
+
+4. Add Babel plugin — APPEND `react-native-worklets/plugin` to your existing `plugins` array. Do NOT replace your presets (keep `babel-preset-expo` for Expo, or your bare-RN preset):
+ ```js
+ // babel.config.js
+ module.exports = {
+ // your existing presets and config — leave untouched
+ plugins: [
+ // ...other plugins
+ 'react-native-worklets/plugin',
+ ],
+ };
+ ```
+ If you already use Reanimated, you may already have the worklets plugin configured.
+
+5. Whitelist postinstall if needed:
+ - **bun**: Add `"trustedDependencies": ["uniwind"]` to `package.json`
+ - **yarn v2+**: Configure in `.yarnrc.yml`
+ - **pnpm**: `pnpm config set enable-pre-post-scripts true`
+
+6. Rebuild native app:
+ ```bash
+ npx expo prebuild --clean && npx expo run:ios
+ ```
+
+Pro does **NOT** work with Expo Go. Requires native rebuild.
+
+**Verify installation**: Check for native modules (`.cpp`, `.mm` files) in `node_modules/uniwind`.
+
+### Reanimated Animations (Requires Reanimated v4.0.0+)
+
+```tsx
+
+
+
+
+
+// Loading spinner
+
+```
+
+Custom keyframe animations beyond Tailwind defaults:
+
+| Class | Description |
+|-------|-------------|
+| `animate-wiggle` | Rotational wiggle |
+| `animate-shake` | Horizontal shake |
+| `animate-flash` | Opacity flash on/off |
+| `animate-rubber-band` | Elastic scale stretch |
+| `animate-swing` | Pendulum swing |
+| `animate-tada` | Scale + rotate attention seeker |
+| `animate-heartbeat` | Double-pulse heartbeat |
+| `animate-jello` | Rotational jello wobble |
+| `animate-float` | Gentle vertical float |
+| `animate-breathe` | Subtle breathing scale |
+| `animate-tilt` | Alternating tilt rotation |
+| `animate-glitch` | Rapid horizontal jitter |
+
+Components auto-swap to Animated versions when animation classes detected:
+
+| Component | Animated Version |
+|-----------|------------------|
+| `View` | `Animated.View` |
+| `Text` | `Animated.Text` |
+| `Image` | `Animated.Image` |
+| `ImageBackground` | `Animated.ImageBackground` |
+| `ScrollView` | `Animated.ScrollView` |
+| `FlatList` | `Animated.FlatList` |
+| `TextInput` | `Animated.TextInput` |
+| `Pressable` | `Animated.Pressable` |
+
+### Entering & Exiting Animations
+
+Drive Reanimated's entering/exiting animations via className — no Reanimated imports needed. Components auto-upgrade when `uw-*` classes are detected.
+
+```tsx
+// Bounce in, bounce out
+{visible && }
+
+// Fade in slowly (1000ms)
+{visible && }
+```
+
+**Entering presets**: `uw-entering-fade-in` `uw-entering-fade-in-right` `uw-entering-fade-in-left` `uw-entering-fade-in-up` `uw-entering-fade-in-down` `uw-entering-slide-in-right` `uw-entering-slide-in-left` `uw-entering-slide-in-up` `uw-entering-slide-in-down` `uw-entering-zoom-in` `uw-entering-zoom-in-rotate` `uw-entering-zoom-in-left` `uw-entering-zoom-in-right` `uw-entering-zoom-in-up` `uw-entering-zoom-in-down` `uw-entering-zoom-in-easy-up` `uw-entering-zoom-in-easy-down` `uw-entering-bounce-in` `uw-entering-bounce-in-down` `uw-entering-bounce-in-up` `uw-entering-bounce-in-left` `uw-entering-bounce-in-right` `uw-entering-flip-in-x-up` `uw-entering-flip-in-x-down` `uw-entering-flip-in-y-left` `uw-entering-flip-in-y-right` `uw-entering-flip-in-easy-x` `uw-entering-flip-in-easy-y` `uw-entering-stretch-in-x` `uw-entering-stretch-in-y` `uw-entering-rotate-in-down-left` `uw-entering-rotate-in-down-right` `uw-entering-rotate-in-up-left` `uw-entering-rotate-in-up-right` `uw-entering-roll-in-left` `uw-entering-roll-in-right` `uw-entering-pinwheel-in` `uw-entering-light-speed-in-right` `uw-entering-light-speed-in-left`
+
+**Exiting presets**: `uw-exiting-fade-out` `uw-exiting-fade-out-right` `uw-exiting-fade-out-left` `uw-exiting-fade-out-up` `uw-exiting-fade-out-down` `uw-exiting-slide-out-right` `uw-exiting-slide-out-left` `uw-exiting-slide-out-up` `uw-exiting-slide-out-down` `uw-exiting-zoom-out` `uw-exiting-zoom-out-rotate` `uw-exiting-zoom-out-left` `uw-exiting-zoom-out-right` `uw-exiting-zoom-out-up` `uw-exiting-zoom-out-down` `uw-exiting-zoom-out-easy-up` `uw-exiting-zoom-out-easy-down` `uw-exiting-bounce-out` `uw-exiting-bounce-out-down` `uw-exiting-bounce-out-up` `uw-exiting-bounce-out-left` `uw-exiting-bounce-out-right` `uw-exiting-flip-out-x-up` `uw-exiting-flip-out-x-down` `uw-exiting-flip-out-y-left` `uw-exiting-flip-out-y-right` `uw-exiting-flip-out-easy-x` `uw-exiting-flip-out-easy-y` `uw-exiting-stretch-out-x` `uw-exiting-stretch-out-y` `uw-exiting-rotate-out-down-left` `uw-exiting-rotate-out-down-right` `uw-exiting-rotate-out-up-left` `uw-exiting-rotate-out-up-right` `uw-exiting-roll-out-left` `uw-exiting-roll-out-right` `uw-exiting-pinwheel-out` `uw-exiting-light-speed-out-right` `uw-exiting-light-speed-out-left`
+
+**Animation modifiers** (pattern: `uw-{entering|exiting|layout}-{modifier}`):
+- Duration: `uw-{type}-duration-75` `uw-{type}-duration-100` ... `uw-{type}-duration-1000` or arbitrary `uw-{type}-duration-{ms}`
+- Delay: `uw-{type}-delay-75` ... `uw-{type}-delay-1000` or arbitrary `uw-{type}-delay-{ms}`
+- Easing: `uw-{type}-ease-linear` `uw-{type}-ease-in` `uw-{type}-ease-out` `uw-{type}-ease-in-out` `uw-{type}-ease-bounce`
+- Spring: `uw-{type}-springify` `uw-{type}-damping-{value}` `uw-{type}-stiffness-{value}` `uw-{type}-mass-{value}`
+
+### Layout Transitions
+
+Animate position/size changes when siblings are added or removed:
+
+```tsx
+
+ {items.map(item => (
+
+ ))}
+
+```
+
+| Class | Description |
+|-------|-------------|
+| `uw-layout-linear-transition` | Smooth linear repositioning |
+| `uw-layout-fading-transition` | Fade during repositioning |
+| `uw-layout-jumping-transition` | Bouncy jump to new position |
+| `uw-layout-curved-transition` | Curved path repositioning |
+| `uw-layout-sequenced-transition` | Sequenced repositioning |
+| `uw-layout-entry-exit-transition` | Combined entry/exit during layout |
+
+### Transitions
+
+Smooth property changes when className or state changes:
+
+```tsx
+// Color transition on press
+
+
+// Opacity transition
+
+
+// Transform transition
+
+
+// All properties
+
+ Animated Button
+
+```
+
+| Class | Properties |
+|-------|------------|
+| `transition-none` | No transition |
+| `transition-all` | All properties |
+| `transition-colors` | Background, border, text colors |
+| `transition-opacity` | Opacity |
+| `transition-shadow` | Box shadow |
+| `transition-transform` | Scale, rotate, translate |
+
+Duration: `duration-75` `duration-100` `duration-150` `duration-200` `duration-300` `duration-500` `duration-700` `duration-1000`
+
+Easing: `ease-linear` `ease-in` `ease-out` `ease-in-out`
+
+Delay: `delay-75` `delay-100` `delay-150` `delay-200` `delay-300` `delay-500` `delay-700` `delay-1000`
+
+### Using Reanimated Directly
+
+Still works with Uniwind classes:
+
+```tsx
+import Animated, { FadeIn, FlipInXUp, LinearTransition } from 'react-native-reanimated';
+
+
+ Fading in
+
+
+ (
+
+ {item}
+
+ )}
+/>
+```
+
+### Shadow Tree Updates
+
+No code changes needed — props connect directly to C++ engine, eliminating re-renders automatically.
+
+### Shadow Tree Diagnostics
+
+Development-only API to observe what the C++ engine is doing — when components register/unregister with the shadow tree and how styles flow through it. Import from `uniwind/diagnostics`:
+
+```tsx
+import { enableDiagnostics } from 'uniwind/diagnostics';
+
+enableDiagnostics({
+ reportMounts: true, // log when components register with the shadow tree
+ reportUnmounts: true, // log when components unregister
+ reportUpdates: true, // log style updates with property-level detail
+});
+```
+
+All three options default to `false` — enable only what you need (logging everything on a complex screen gets noisy). Update logs are grouped into 🔥 C++ updates (applied via the shadow tree) and ✨ Native updates (props set directly on native views) — both happen with zero React re-renders.
+
+Use for: debugging theme switches (`reportUpdates`), detecting memory leaks (mount/unmount counts should return to zero when navigating away), and verifying zero re-renders.
+
+Platform support: full diagnostics on iOS and Android. On Web, `enableDiagnostics` is a no-op stub that produces no output.
+
+### Group Variants
+
+Tailwind `group` variants propagate parent interaction state to descendants through the C++ shadow tree. No re-renders, no context providers.
+
+```tsx
+// Basic group — descendants react to parent press
+
+ Press the card
+
+
+
+// Named groups — descendants pick which ancestor to follow
+
+
+
+ Nested groups
+
+
+
+```
+
+**Supported variants**: `group-active:*` (press), `group-focus:*` (focus). Named variants: `group-active/{name}:*`, `group-focus/{name}:*`.
+
+**Supported group parents**: `Pressable` (press + focus), `Text` (press — requires `onPress`, even empty). `TouchableOpacity`, `TouchableHighlight`, `TouchableWithoutFeedback`, and `TextInput` do **not** act as group parents — wrap in a `Pressable` marked `group`.
+
+**Not supported**: `group-hover:*` (no pointer hover on native), `group-disabled:*` (parsed but no shadow tree trigger), arbitrary `group-[.selector]:*` variants, implicit `in-*` variants.
+
+### Default Styles (Pro 1.2.0+, Experimental)
+
+Default styles let Pro users define baseline styles for built-in React Native components directly in CSS. They are disabled by default and require an experimental flag.
+
+```js
+// metro.config.js
+module.exports = withUniwindConfig(config, {
+ cssEntryFile: './global.css',
+ experimental: {
+ defaultStyles: true,
+ },
+});
+```
+
+```css
+/* global.css */
+View {
+ border-color: var(--color-primary);
+}
+
+Text {
+ font-family: Inter;
+ font-size: 16px;
+}
+```
+
+Effect: every `View` gets `border-color: var(--color-primary)`, every `Text` gets `font-family: Inter` and `font-size: 16px`, unless more specific styles override them.
+
+Rules:
+- Available only in Uniwind Pro `1.2.0+`
+- Disabled by default; enable `experimental.defaultStyles: true`
+- Experimental; may not work for every use case and may change in future releases
+- Use React Native component names as selectors, not HTML tags
+- Treat as baseline styles; direct `className` styles can override them
+
+Supported component selectors: `ActivityIndicator`, `FlatList`, `Image`, `ImageBackground`, `InputAccessoryView`, `KeyboardAvoidingView`, `Modal`, `Pressable`, `RefreshControl`, `SafeAreaView`, `ScrollView`, `SectionList`, `Switch`, `Text`, `TextInput`, `TouchableHighlight`, `TouchableNativeFeedback`, `TouchableOpacity`, `TouchableWithoutFeedback`, `View`, `VirtualizedList`.
+
+### Suspense Support
+
+Components inside React `Suspense` boundaries are handled correctly. While a subtree is suspended, Uniwind keeps the C++ shadow entries alive so theme updates and runtime changes (dark mode, orientation, etc.) still reach suspended nodes. When the tree unsuspends, styles are already up to date — no flash of stale theme.
+
+### Native Insets
+
+Remove `SafeAreaListener` setup — insets injected from native layer:
+
+```tsx
+// With Pro — just use safe area classes directly
+{/* content */}
+```
+
+### Theme Transitions (Pro)
+
+Native animated transitions when switching themes. Supported on iOS, Android, and Web.
+
+```tsx
+import { Uniwind, ThemeTransitionPreset } from 'uniwind';
+
+// Fade transition
+Uniwind.setTheme('dark', { preset: ThemeTransitionPreset.Fade });
+
+// Slide transitions
+Uniwind.setTheme('dark', { preset: ThemeTransitionPreset.SlideRightToLeft });
+Uniwind.setTheme('light', { preset: ThemeTransitionPreset.SlideLeftToRight });
+
+// Circle mask transitions (expand from a corner or center)
+Uniwind.setTheme('ocean', { preset: ThemeTransitionPreset.CircleCenter });
+
+// Blur transitions
+Uniwind.setTheme('dark', { preset: ThemeTransitionPreset.Blur });
+Uniwind.setTheme('dark', { preset: ThemeTransitionPreset.BlurRightToLeft });
+
+// No animation
+Uniwind.setTheme('light');
+```
+
+Available presets:
+
+| Preset | Effect |
+|--------|--------|
+| `ThemeTransitionPreset.None` | Instant switch, no animation |
+| `ThemeTransitionPreset.Fade` | Crossfade between themes |
+| `ThemeTransitionPreset.SlideRightToLeft` | Slide new theme in from right |
+| `ThemeTransitionPreset.SlideLeftToRight` | Slide new theme in from left |
+| `ThemeTransitionPreset.CircleTopRight` | Circle mask expanding from top-right |
+| `ThemeTransitionPreset.CircleTopLeft` | Circle mask expanding from top-left |
+| `ThemeTransitionPreset.CircleBottomRight` | Circle mask expanding from bottom-right |
+| `ThemeTransitionPreset.CircleBottomLeft` | Circle mask expanding from bottom-left |
+| `ThemeTransitionPreset.CircleCenter` | Circle mask expanding from center |
+| `ThemeTransitionPreset.Blur` | Blur out animation |
+| `ThemeTransitionPreset.BlurRightToLeft` | Directional blur from right to left |
+| `ThemeTransitionPreset.BlurLeftToRight` | Directional blur from left to right |
diff --git a/skills/uniwind/references/setup.md b/skills/uniwind/references/setup.md
new file mode 100644
index 00000000..17fd149a
--- /dev/null
+++ b/skills/uniwind/references/setup.md
@@ -0,0 +1,144 @@
+## Setup
+
+### Installation
+
+```bash
+# or other package manager
+bun install uniwind tailwindcss
+```
+
+Requires **Tailwind CSS v4+**.
+
+### global.css
+
+Create a CSS entry file:
+
+```css
+@import 'tailwindcss';
+@import 'uniwind';
+```
+
+Import in your **App component** (e.g., `App.tsx` or `app/_layout.tsx`), **NOT** in `index.ts`/`index.js` — importing there breaks hot reload:
+
+```tsx
+// app/_layout.tsx or App.tsx
+import './global.css';
+```
+
+The directory containing `global.css` is the app root — Tailwind scans for classNames starting from this directory.
+
+### Metro Configuration
+
+```js
+const { getDefaultConfig } = require('expo/metro-config');
+// Bare RN: const { getDefaultConfig } = require('@react-native/metro-config');
+const { withUniwindConfig } = require('uniwind/metro');
+
+const config = getDefaultConfig(__dirname);
+
+// withUniwindConfig MUST be the OUTERMOST wrapper
+module.exports = withUniwindConfig(config, {
+ cssEntryFile: './global.css', // Required — relative path from project root
+ polyfills: { rem: 16 }, // Optional — base rem value (default 16)
+ extraThemes: ['ocean', 'sunset'], // Optional — custom themes beyond light/dark
+ dtsFile: './uniwind-types.d.ts', // Optional — TypeScript types output path
+ debug: true, // Optional — log unsupported CSS in dev
+ isTV: false, // Optional — enable TV platform support
+});
+```
+
+For most flows, keep defaults, only provide `cssEntryFile`.
+
+Wrapper order — Uniwind must wrap everything else:
+
+```js
+// CORRECT
+module.exports = withUniwindConfig(withOtherConfig(config, opts), { cssEntryFile: './global.css' });
+
+// WRONG — Uniwind is NOT outermost
+module.exports = withOtherConfig(withUniwindConfig(config, { cssEntryFile: './global.css' }), opts);
+```
+
+### Vite Configuration (v1.2.0+)
+
+If user has storybook setup, add extra vite config:
+
+```ts
+import tailwindcss from '@tailwindcss/vite';
+import { uniwind } from 'uniwind/vite';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [
+ tailwindcss(),
+ uniwind({
+ cssEntryFile: './src/global.css',
+ dtsFile: './src/uniwind-types.d.ts',
+ }),
+ ],
+});
+```
+
+### TypeScript
+
+Uniwind auto-generates a `.d.ts` file (default: `./uniwind-types.d.ts`) after running Metro. Place it in `src/` or `app/` for auto-inclusion, or add to `tsconfig.json`:
+
+```json
+{ "include": ["./uniwind-types.d.ts"] }
+```
+
+If user has some typescript errors related to classNames, just run metro server to build the d.ts file.
+
+### Expo Router Placement
+
+```text
+project/
+├── app/_layout.tsx ← import '../global.css' here
+├── components/
+├── global.css ← project root (best location)
+└── metro.config.js ← cssEntryFile: './global.css'
+```
+
+If `global.css` is in `app/` dir, add `@source` for sibling directories:
+
+```css
+@import 'tailwindcss';
+@import 'uniwind';
+@source '../components';
+```
+
+### Tailwind IntelliSense (VS Code / Cursor / Windsurf)
+
+```json
+{
+ "tailwindCSS.classAttributes": [
+ "class", "className", "headerClassName",
+ "contentContainerClassName", "columnWrapperClassName",
+ "endFillColorClassName", "imageClassName", "tintColorClassName",
+ "ios_backgroundColorClassName", "thumbColorClassName",
+ "trackColorOnClassName", "trackColorOffClassName",
+ "selectionColorClassName", "cursorColorClassName",
+ "underlineColorAndroidClassName", "placeholderTextColorClassName",
+ "selectionHandleColorClassName", "colorsClassName",
+ "progressBackgroundColorClassName", "titleColorClassName",
+ "underlayColorClassName", "colorClassName",
+ "backdropColorClassName", "backgroundColorClassName",
+ "statusBarBackgroundColorClassName", "drawerBackgroundColorClassName",
+ "ListFooterComponentClassName", "ListHeaderComponentClassName"
+ ],
+ "tailwindCSS.classFunctions": ["useResolveClassNames"]
+}
+```
+
+### Monorepo Support
+
+Add `@source` directives in `global.css` for packages outside the CSS entry file's directory:
+
+```css
+@import 'tailwindcss';
+@import 'uniwind';
+@source "../../packages/ui/src";
+@source "../../packages/shared/src";
+```
+
+Also needed for `node_modules` packages that contain Uniwind classes (e.g., shared UI libraries).
diff --git a/skills/uniwind/references/styling-patterns.md b/skills/uniwind/references/styling-patterns.md
new file mode 100644
index 00000000..385d8466
--- /dev/null
+++ b/skills/uniwind/references/styling-patterns.md
@@ -0,0 +1,237 @@
+## Styling Third-Party Components
+
+### withUniwind (Recommended)
+
+Wrap once at module level, use with `className` everywhere:
+
+```tsx
+import { withUniwind } from 'uniwind';
+import { Image as ExpoImage } from 'expo-image';
+import { BlurView as RNBlurView } from 'expo-blur';
+import { LinearGradient as RNLinearGradient } from 'expo-linear-gradient';
+
+// Module-level wrapping (NEVER inside render functions)
+export const Image = withUniwind(ExpoImage);
+export const BlurView = withUniwind(RNBlurView);
+export const LinearGradient = withUniwind(RNLinearGradient);
+```
+
+`withUniwind` automatically maps:
+- `style` → `className`
+- `{name}Style` → `{name}ClassName`
+- `{name}Color` → `{name}ColorClassName` (with accent- prefix)
+
+For custom prop mappings:
+
+```tsx
+const StyledProgressBar = withUniwind(ProgressBar, {
+ width: {
+ fromClassName: 'widthClassName',
+ styleProperty: 'width',
+ },
+});
+```
+
+**Usage patterns:**
+
+- **Used in one file only** — define the wrapped component in that same file
+- **Used across multiple files** — wrap once in a shared module (e.g., `components/styled.ts`) and re-export
+
+```tsx
+// components/styled.ts
+import { withUniwind } from 'uniwind';
+import { Image as ExpoImage } from 'expo-image';
+export const Image = withUniwind(ExpoImage);
+
+// Then import everywhere:
+import { Image } from '@/components/styled';
+```
+
+**NEVER** call `withUniwind` on the same component in multiple files.
+
+**CRITICAL**: Do NOT use `withUniwind` on components from `react-native` or `react-native-reanimated`. These already have built-in `className` support:
+
+```tsx
+// WRONG — View already supports className natively
+const StyledView = withUniwind(View); // DO NOT DO THIS
+const StyledText = withUniwind(Text); // DO NOT DO THIS
+const StyledAnimatedView = withUniwind(Animated.View); // DO NOT DO THIS
+
+// CORRECT — only wrap third-party components
+const StyledExpoImage = withUniwind(ExpoImage); // expo-image
+const StyledBlurView = withUniwind(BlurView); // expo-blur
+const StyledMotiView = withUniwind(MotiView); // moti
+```
+
+### useResolveClassNames
+
+Converts Tailwind class strings to React Native style objects. Use for one-off cases or components that only accept `style`:
+
+```tsx
+import { useResolveClassNames } from 'uniwind';
+
+const headerStyle = useResolveClassNames('bg-primary p-4');
+const cardStyle = useResolveClassNames('bg-card dark:bg-card rounded-lg shadow-sm');
+
+// React Navigation screen options
+
+```
+
+### Comparison
+
+| Feature | withUniwind | useResolveClassNames |
+|---------|-------------|----------------------|
+| Setup | Once per component | Per usage |
+| Performance | Optimized | Slightly slower |
+| Best for | Reusable components | One-off, navigation config |
+| Syntax | `className="..."` | `style={...}` |
+
+## Dynamic ClassNames
+
+### NEVER do this (Tailwind scans at build time)
+
+```tsx
+// BROKEN — template literal with variable
+
+
+```
+
+### Correct patterns
+
+```tsx
+// Ternary with complete class names
+
+
+// Mapping object
+const colorMap = {
+ primary: 'bg-blue-500 text-white',
+ danger: 'bg-red-500 text-white',
+ ghost: 'bg-transparent text-foreground',
+};
+
+
+// Array join for multiple conditions
+
+```
+
+## tailwind-variants (tv)
+
+For complex component styling with variants and compound variants:
+
+```tsx
+import { tv } from 'tailwind-variants';
+
+const button = tv({
+ base: 'font-semibold rounded-lg px-4 py-2 items-center justify-center',
+ variants: {
+ color: {
+ primary: 'bg-blue-500 text-white',
+ secondary: 'bg-gray-500 text-white',
+ danger: 'bg-red-500 text-white',
+ ghost: 'bg-transparent text-foreground border border-border',
+ },
+ size: {
+ sm: 'text-sm px-3 py-1.5',
+ md: 'text-base px-4 py-2',
+ lg: 'text-lg px-6 py-3',
+ },
+ disabled: {
+ true: 'opacity-50',
+ },
+ },
+ compoundVariants: [
+ { color: 'primary', size: 'lg', class: 'bg-blue-600' },
+ ],
+ defaultVariants: { color: 'primary', size: 'md' },
+});
+
+
+ Click
+
+```
+
+## cn Utility — Class Deduplication
+
+Uniwind does **NOT** auto-deduplicate conflicting classNames. This means if the same property appears in multiple classes, **both will be applied and the result is unpredictable**. This is especially critical when mixing custom CSS classes with Tailwind utilities.
+
+### Setup
+
+```bash
+npm install tailwind-merge clsx
+```
+
+```ts
+// lib/cn.ts
+import { type ClassValue, clsx } from 'clsx';
+import { twMerge } from 'tailwind-merge';
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
+```
+
+### When cn Is Required
+
+1. **Merging className props** — component accepts external className that may conflict:
+
+```tsx
+import { cn } from '@/lib/cn';
+
+
+
+```
+
+2. **CRITICAL: Mixing custom CSS classes with Tailwind utilities** — if your custom CSS class sets a property that a Tailwind utility also sets, you MUST use `cn()` to deduplicate:
+
+```css
+/* global.css */
+.card {
+ background-color: white;
+ border-radius: 12px;
+ padding: 16px;
+}
+```
+
+```tsx
+// WRONG — both .card (padding: 16px) and p-6 (padding: 24px) apply, result is unpredictable
+
+
+// CORRECT — cn deduplicates, p-6 wins over .card's padding
+
+```
+
+3. **tv() output combined with extra classes** — tv already handles its own variants, but if you add more classes on top:
+
+```tsx
+
+```
+
+### When cn Is NOT Needed
+
+- Static className with no conflicts: ``
+- Single custom CSS class with no overlapping Tailwind: `` (if card-shadow only sets box-shadow which no Tailwind class also sets)
+
+## Important Utilities and Style Specificity
+
+Uniwind supports Tailwind's important modifier (`!`) for utilities that must override another utility for the same style property.
+
+```tsx
+import { View, Pressable } from 'react-native';
+
+// bg-red-500! has higher priority than bg-blue-500
+;
+
+// Important utilities work with state and platform variants
+;
+;
+```
+
+Priority rules:
+- Important utility (`bg-red-500!`) overrides non-important utility (`bg-blue-500`) for the same property.
+- Important variants work normally: `active:bg-red-500!`, `ios:pt-12!`, `dark:text-white!`.
+- Inline `style` always wins, even over important className utilities: `` renders blue.
+- Use `!` sparingly. For reusable components and consumer overrides, prefer `cn()` with `tailwind-merge`.
diff --git a/skills/uniwind/references/theming.md b/skills/uniwind/references/theming.md
new file mode 100644
index 00000000..190a5363
--- /dev/null
+++ b/skills/uniwind/references/theming.md
@@ -0,0 +1,309 @@
+## Theming
+
+### Quick Setup (dark: prefix)
+
+Works immediately — no configuration needed:
+
+```tsx
+
+ Themed
+
+```
+
+Best for small apps and prototyping. Does not scale to custom themes.
+
+### Scalable Setup (CSS Variables)
+
+Define in `global.css`, use everywhere without `dark:` prefix:
+
+```css
+@layer theme {
+ :root {
+ @variant light {
+ --color-background: #ffffff;
+ --color-foreground: #111827;
+ --color-foreground-secondary: #6b7280;
+ --color-card: #ffffff;
+ --color-border: #e5e7eb;
+ --color-muted: #9ca3af;
+ --color-primary: #3b82f6;
+ --color-danger: #ef4444;
+ --color-success: #10b981;
+ }
+ @variant dark {
+ --color-background: #000000;
+ --color-foreground: #ffffff;
+ --color-foreground-secondary: #9ca3af;
+ --color-card: #1f2937;
+ --color-border: #374151;
+ --color-muted: #6b7280;
+ --color-primary: #3b82f6;
+ --color-danger: #ef4444;
+ --color-success: #10b981;
+ }
+ }
+}
+```
+
+```tsx
+// Auto-adapts to current theme — no dark: prefix needed
+
+ Title
+ Subtitle
+
+```
+
+Variable naming: `--color-background` → `bg-background`, `text-background`.
+
+**Prefer CSS variables over explicit `dark:` variants** — they're cleaner, maintain easier, and work with custom themes automatically.
+
+### Custom Themes
+
+**Step 1** — Define in `global.css`:
+
+```css
+@layer theme {
+ :root {
+ @variant light { /* ... */ }
+ @variant dark { /* ... */ }
+ @variant ocean {
+ --color-background: #0c4a6e;
+ --color-foreground: #e0f2fe;
+ --color-primary: #06b6d4;
+ --color-card: #0e7490;
+ --color-border: #155e75;
+ /* Must define ALL the same variables as light/dark */
+ }
+ }
+}
+```
+
+**Step 2** — Register in `metro.config.js` (exclude `light`/`dark` — they're automatic):
+
+```js
+module.exports = withUniwindConfig(config, {
+ cssEntryFile: './global.css',
+ extraThemes: ['ocean'],
+});
+```
+
+Restart Metro after adding themes.
+
+**Step 3** — Use:
+
+```tsx
+Uniwind.setTheme('ocean');
+```
+
+### Theme API
+
+```tsx
+import { Uniwind, useUniwind } from 'uniwind';
+
+// Imperative (no re-render)
+Uniwind.setTheme('dark'); // Force dark
+Uniwind.setTheme('light'); // Force light
+Uniwind.setTheme('system'); // Follow device (re-enables adaptive themes)
+Uniwind.setTheme('ocean'); // Custom theme (must be in extraThemes)
+Uniwind.currentTheme; // Current theme name
+Uniwind.hasAdaptiveThemes; // true if following system
+
+// Reactive hook (re-renders on change)
+const { theme, hasAdaptiveThemes } = useUniwind();
+```
+
+`Uniwind.setTheme('light')` / `setTheme('dark')` also calls `Appearance.setColorScheme` to sync native components (Alert, Modal, system dialogs).
+
+By default Uniwind uses "system" theme - follows device color scheme. If user wants to override it, just
+call Uniwind.setTheme with desired theme. It can be done above the React component to avoid theme switching at runtime.
+
+### Theme Switcher Example
+
+```tsx
+import { View, Pressable, Text, ScrollView } from 'react-native';
+import { Uniwind, useUniwind } from 'uniwind';
+
+export const ThemeSwitcher = () => {
+ const { theme, hasAdaptiveThemes } = useUniwind();
+ const activeTheme = hasAdaptiveThemes ? 'system' : theme;
+
+ const themes = [
+ { name: 'light', label: 'Light' },
+ { name: 'dark', label: 'Dark' },
+ { name: 'system', label: 'System' },
+ ];
+
+ return (
+
+
+ {themes.map((t) => (
+ Uniwind.setTheme(t.name)}
+ className={`px-4 py-3 rounded-lg items-center ${
+ activeTheme === t.name ? 'bg-primary' : 'bg-card border border-border'
+ }`}
+ >
+
+ {t.label}
+
+
+ ))}
+
+
+ );
+};
+```
+
+### ScopedTheme
+
+Apply a different theme to a subtree without changing the global theme:
+
+```tsx
+import { ScopedTheme } from 'uniwind';
+
+
+
+
+
+ {/* Renders with dark theme */}
+
+
+
+ {/* Renders with ocean theme */}
+
+
+```
+
+- Nearest `ScopedTheme` wins (nested scopes supported)
+- Hooks (`useUniwind`, `useResolveClassNames`, `useCSSVariable`) resolve against the nearest scoped theme
+- `withUniwind`-wrapped components inside the scope also resolve scoped theme values
+- Custom themes require registration in `extraThemes`
+
+### LayoutDirection (v1.8.0+)
+
+Scope RTL/LTR variants to a subtree without changing global device RTL state:
+
+```tsx
+import { LayoutDirection } from 'uniwind';
+
+
+ Uses global RTL state
+
+
+ Forced RTL subtree
+
+
+
+ Forced LTR subtree
+
+
+```
+
+- Available from `uniwind@1.8.0`.
+- `rtl` prop: `true` forces RTL, `false` forces LTR.
+- Omit `rtl` to inherit parent `LayoutDirection`; outside any parent it falls back to global RTL state.
+- Nearest `LayoutDirection` wins (nested scopes supported).
+- Prefer `LayoutDirection` over inline `style={{ direction: 'rtl' }}` for `rtl:`/`ltr:` variant scoping.
+- Hooks (`useResolveClassNames`, `useCSSVariable`) and `withUniwind`-wrapped components inside the scope resolve against the nearest layout direction.
+
+### useCSSVariable
+
+Access CSS variable values in JavaScript:
+
+```tsx
+import { useCSSVariable } from 'uniwind';
+
+const primaryColor = useCSSVariable('--color-primary');
+const spacing = useCSSVariable('--spacing-4');
+
+// Multiple variables at once
+const [bg, fg] = useCSSVariable(['--color-background', '--color-foreground']) as [string, string]
+```
+
+Use for: animations, chart libraries, third-party component configs, calculations with design tokens.
+
+It's required to cast the result of `useCSSVariable` as it can return: string | number | undefined.
+Uniwind doesn't know if given variable exist and what type it is, so it returns union type.
+
+### getCSSVariable
+
+Read CSS variable values outside of React (event handlers, async callbacks, utility modules, worklets). Available in Uniwind 1.6.4+.
+
+```ts
+import { Uniwind } from 'uniwind';
+
+const primary = Uniwind.getCSSVariable('--color-primary');
+const [bg, fg] = Uniwind.getCSSVariable(['--color-background', '--color-foreground']) as [string, string];
+```
+
+Same value rules as `useCSSVariable` (variable must be used in a `className` or declared in `@theme static`). Same return type: `string | number | undefined`. Cast as needed.
+
+Not reactive — value is read once. For reactive values inside components use `useCSSVariable`. Use `getCSSVariable` for one-shot reads (onPress handlers, utility functions, native module configs).
+
+### Runtime CSS Variable Updates
+
+Update theme variables at runtime (e.g., user-selected brand colors or API-driven themes):
+
+```tsx
+Uniwind.updateCSSVariables('light', {
+ '--color-primary': '#ff6600',
+ '--color-background': '#fafafa',
+});
+```
+
+Updates are theme-specific and take effect immediately.
+
+### @theme static
+
+For JS-only values not used in classNames:
+
+```css
+@theme static {
+ --chart-line-width: 2;
+ --chart-dot-radius: 4;
+ --animation-duration: 300;
+}
+```
+
+Access via `useCSSVariable('--chart-line-width')`. Use for: chart configs, animation durations, native module values.
+
+### OKLCH Colors support
+
+Perceptually uniform color format — wider gamut, consistent lightness:
+
+```css
+@layer theme {
+ :root {
+ @variant light {
+ --color-primary: oklch(0.5 0.2 240);
+ --color-background: oklch(1 0 0);
+ }
+ @variant dark {
+ --color-primary: oklch(0.6 0.2 240);
+ --color-background: oklch(0.13 0.004 17.69);
+ }
+ }
+}
+```
+
+### Display P3 Colors support
+
+Wide-gamut color format for devices that support the P3 color space (most modern iPhones and Macs). Uniwind parses `color(display-p3 ...)` values and converts them for native use:
+
+```css
+@layer theme {
+ :root {
+ @variant light {
+ --color-primary: color(display-p3 0.2 0.4 1);
+ --color-accent: color(display-p3 1 0.3 0.3);
+ }
+ @variant dark {
+ --color-primary: color(display-p3 0.3 0.5 1);
+ --color-accent: color(display-p3 1 0.4 0.4);
+ }
+ }
+}
+```
diff --git a/skills/uniwind/references/troubleshooting.md b/skills/uniwind/references/troubleshooting.md
new file mode 100644
index 00000000..8c96bbc2
--- /dev/null
+++ b/skills/uniwind/references/troubleshooting.md
@@ -0,0 +1,179 @@
+## Setup Diagnostics
+
+When styles aren't working, check in this order:
+
+### 1. package.json
+- `"uniwind"` (or `"uniwind-pro"`) in dependencies
+- `"tailwindcss"` at v4+ (`^4.0.0`)
+- For Pro: `react-native-nitro-modules`, `react-native-reanimated`, `react-native-worklets`
+
+### 2. metro.config.js
+- `withUniwindConfig` imported from `'uniwind/metro'`
+- `withUniwindConfig` is the **outermost** wrapper
+- `cssEntryFile` is a **relative path string** (e.g., `'./global.css'`)
+- No `path.resolve()` or absolute paths
+- For Pro default styles: `experimental.defaultStyles: true` is set
+
+### 3. global.css
+- Contains `@import 'tailwindcss';` AND `@import 'uniwind';`
+- Imported in `App.tsx` or root layout, **NOT** in `index.ts`/`index.js`
+- Location determines app root for Tailwind scanning
+
+### 4. babel.config.js (Pro only)
+- `'react-native-worklets/plugin'` in plugins array
+
+### 5. TypeScript
+- `uniwind-types.d.ts` exists (generated after running Metro)
+- Included in `tsconfig.json` or placed in `src/`/`app/` dir
+
+### 6. Build
+- Metro server restarted after config changes
+- Metro cache cleared (`npx expo start --clear` or `npx react-native start --reset-cache`)
+- Native rebuild done (if Pro or after dependency changes)
+
+## Troubleshooting
+
+| Symptom | Cause | Fix |
+|---------|-------|-----|
+| Styles not applying | Missing imports in global.css | Add `@import 'tailwindcss'; @import 'uniwind';` |
+| Styles not applying | global.css imported in index.js | Move import to App.tsx or `_layout.tsx` |
+| Classes not detected | global.css in nested dir, components elsewhere | Add `@source '../components'` in global.css |
+| TypeScript errors on className | Missing types file | Run Metro to generate `uniwind-types.d.ts` |
+| `withUniwindConfig is not a function` | Wrong import | Use `require('uniwind/metro')` not `require('uniwind')` |
+| Hot reload full-reloads | global.css imported in wrong file | Move to App.tsx or root layout |
+| `cssEntryFile` error / Metro crash | Absolute path used | Use relative: `'./global.css'` |
+| `withUniwindConfig` not outermost | Another wrapper wraps Uniwind | Swap order so Uniwind is outermost |
+| Dark theme not working | Missing `@variant dark` | Define dark variant in `@layer theme` |
+| Custom theme not appearing | Not registered in metro config | Add to `extraThemes` array, restart Metro |
+| Fonts not loading | Font name mismatch | CSS font name must match file name exactly (no extension) |
+| `rem` values too large/small | Wrong base rem | Set `polyfills: { rem: 14 }` for NativeWind compat |
+| Unsupported CSS warning | Web-specific CSS used | Enable `debug: true` to identify; remove unsupported properties |
+| `Failed to serialize javascript object` | Complex CSS, circular refs, or stale cache | Clear caches: `watchman watch-del-all; rm -rf node_modules/.cache; npx expo start --clear`. Also check if docs/markdown files containing CSS classes are in the scan path (see below) |
+| `Failed to serialize javascript object` from llms-full.txt or docs | Docs/markdown files with CSS classes in project dir get scanned by Tailwind | Move `.md` files with CSS examples outside the project root, or add to `.gitignore` so Tailwind's scanner skips them |
+| `unstable_enablePackageExports` conflict | App disables package exports | Use selective resolver for Uniwind and culori |
+| Classes from monorepo package missing | Not included in Tailwind scan | Add `@source '../../packages/ui'` in global.css |
+| Classes from `node_modules` library missing in production (bun) | Bun uses symlinks; Tailwind's Oxide scanner can't follow them | Use resolved path: `@source "../../node_modules/heroui-native/lib"` and add `public-hoist-pattern[]=heroui-native` to `.npmrc` |
+| `active:` not working with `withUniwind` | `withUniwind` does NOT support interactive state selectors | Only core RN `Pressable`/`TextInput`/`Switch` support `active:`/`focus:`/`disabled:`. Third-party pressables wrapped with `withUniwind` won't get states |
+| `withUniwind` custom mapping overrides `className`+`style` merging | When manual mapping is provided, `style` prop is not merged | Use auto mapping (no second arg) for `className`+`style` merge. For manual mapping + `className`, double-wrap: `withUniwind(withUniwind(Comp), { mapping })` |
+| `withUniwind` loses generic types on `ref` (e.g., `FlashList`) | TypeScript limitation with HOCs | Cast the ref manually: `ref={scrollRef as any}` |
+| Platform-specific fonts: `@theme` block error | `@media ios/android` inside `@theme {}` | Use `@layer theme { :root { @variant ios { ... } } }` instead — `@theme` only accepts custom properties, and platform selection uses `@variant` not `@media` |
+| `Uniwind.setTheme('system')` crash on Android (RN 0.82+) | RN 0.82 changed Appearance API | Update to latest Uniwind (fixed). Avoid `setTheme('system')` on older Uniwind + RN 0.82+ |
+| Styles flash/disappear on initial load (Android) | `SafeAreaListener` fires before component listeners mount | Fixed in recent versions. If persists, ensure Uniwind is latest |
+| `useTVEventHandler` is undefined | Uniwind module replacement interferes with tvOS exports | Fixed in v1.2.1+. Update Uniwind |
+| `@layer theme` variables not rendering on web | Bug with RNW + Expo SDK 55 | Fixed in v1.4.1+. Update Uniwind |
+| `updateCSSVariables` wrong theme at app start | Calling for multiple themes back-to-back; last call wins on first render | Call `updateCSSVariables` for the current theme last. After initial load, order doesn't matter |
+| Pro: animations not working | Missing Babel plugin | Add `react-native-worklets/plugin` to babel.config.js |
+| Pro: module not found | No native rebuild | Run `npx expo prebuild --clean` then `npx expo run:ios` |
+| Pro: postinstall failed | Package manager blocks scripts | Add to `trustedDependencies` (bun) or configure yarn/pnpm |
+| Pro: auth expired | Login session expired (180-day lifetime) | Run `npx uniwind-pro`, re-login |
+| Pro: download limit reached | Monthly download limit hit | Check Pro dashboard, limits reset monthly |
+| Pro: `Uniwind.updateInsets` called unnecessarily | Pro injects insets natively | `Uniwind.updateInsets` is a no-op in Pro. Remove `SafeAreaListener` setup when using Pro |
+| Pro: theme transition crash | Missing `ThemeTransitionPreset` import or calling before app is ready | Import from `'uniwind'`. Ensure the app has fully mounted before calling `setTheme` with a transition |
+| Pro: default component styles not applying | Feature disabled or unsupported selector | Use Uniwind Pro 1.2.0+, enable `experimental.defaultStyles: true`, restart Metro, and use supported RN component selectors like `View` or `Text` |
+
+### unstable_enablePackageExports Selective Resolver
+
+If your app disables `unstable_enablePackageExports` (common in crypto apps), use a selective resolver:
+
+```js
+config.resolver.unstable_enablePackageExports = false;
+config.resolver.resolveRequest = (context, moduleName, platform) => {
+ if (['uniwind', 'culori'].some((prefix) => moduleName.startsWith(prefix))) {
+ return context.resolveRequest(
+ { ...context, unstable_enablePackageExports: true },
+ moduleName,
+ platform
+ );
+ }
+ return context.resolveRequest(context, moduleName, platform);
+};
+```
+
+## FAQ
+
+**Where to put global.css in Expo Router?**
+Project root. Import in `app/_layout.tsx`. If placed in `app/`, add `@source` for sibling dirs.
+
+**Does Uniwind work with Expo Go?**
+Free: Yes. Pro: No — requires native rebuild (development builds).
+
+**Can I use tailwind.config.js?**
+No. Uniwind uses Tailwind v4 — all config via `@theme` in `global.css`.
+
+**How to access CSS variables in JS?**
+Inside components: `useCSSVariable('--color-primary')` (reactive). Outside React: `Uniwind.getCSSVariable('--color-primary')` (one-shot, 1.6.4+). For variables not used in classNames, define with `@theme static`.
+
+**Can I use Platform.select()?**
+Yes, but prefer platform selectors (`ios:pt-12 android:pt-6`) — cleaner, no imports.
+
+**Next.js support?**
+Not officially supported. Community plugin: `uniwind-plugin-next`. For Next.js, use standard Tailwind CSS.
+
+**Vite support?**
+Yes, since v1.2.0. Use `uniwind/vite` plugin alongside `@tailwindcss/vite`.
+
+**Full app reloads on CSS changes?**
+Metro can't hot-reload files with many providers. Move `global.css` import deeper in the component tree.
+
+**Style specificity?**
+Important utilities like `bg-red-500!` override non-important utilities for the same property and work with variants (`active:bg-red-500!`, `ios:pt-12!`). Inline `style` always overrides `className`, even important utilities. Use `className` for static styles, inline only for truly dynamic values. Use `cn()` from tailwind-merge for component libraries where classNames may conflict.
+
+**How do I include custom fonts?**
+Load font files (Expo: `expo-font` plugin in `app.json`; Bare RN: `react-native-asset`), then map in CSS: `@theme { --font-sans: 'Roboto-Regular'; }`. Font name must exactly match the file name. See [Fonts](./css-and-utilities.md#fonts).
+
+**How can I style based on prop values?**
+Use data selectors: `data-[selected=true]:ring-2`. Only equality checks supported. See [Data Selectors](./variants-and-selectors.md#data-selectors).
+
+**How can I use gradients?**
+Built-in: `bg-gradient-to-r from-red-500 to-green-500`. Also supports angle-based (`bg-linear-90`) and arbitrary values (`bg-linear-[45deg,#f00_0%,#00f_100%]`). See [Gradients](./css-and-utilities.md#gradients).
+
+**How does className deduplication work?**
+Uniwind does NOT auto-deduplicate conflicting classNames. Use `tailwind-merge` with a `cn()` utility. See [cn Utility](./styling-patterns.md#cn-utility--class-deduplication).
+
+**How to debug 'Failed to serialize javascript object'?**
+Clear caches: `watchman watch-del-all; rm -rf node_modules/.cache; npx expo start --clear`. Enable `debug: true` in metro config to identify the problematic CSS pattern. See [Troubleshooting](#troubleshooting).
+
+**How do I enable safe area classNames?**
+Free: Install `react-native-safe-area-context`, wrap root with `SafeAreaListener`, call `Uniwind.updateInsets(insets)`. Pro: Automatic — no setup. Then use `pt-safe`, `pb-safe`, etc. See [Safe Area Utilities](./variants-and-selectors.md#safe-area-utilities).
+
+**What UI kits work well with Uniwind?**
+**React Native Reusables** (shadcn philosophy, copy-paste components) and **HeroUI Native** (complete library, optimized for Uniwind). Any library works via `withUniwind` wrapper. See [UI Kit Compatibility](./integrations.md#ui-kit-compatibility).
+
+**Can I scope a theme to a single component?**
+Yes, use `ScopedTheme`: ``. It forces a theme for the subtree without changing the global theme. See [Theming](./theming.md#theming).
+
+**Does `active:` work with `react-native-gesture-handler` Pressable?**
+No. `withUniwind` does NOT support interactive state selectors (`active:`, `focus:`, `disabled:`). Only core RN `Pressable`, `TextInput`, and `Switch` support them. For RNGH components, use `onPressIn`/`onPressOut` with state.
+
+**Can I customize the default `border` color?**
+Yes — use `@utility border` to override the class entirely:
+```css
+@utility border {
+ border-width: 1px;
+ border-style: solid;
+ border-color: var(--color-primary);
+}
+```
+This completely replaces the built-in `border` behavior, so re-declare any properties you still need. Alternatively, use `border border-gray-300` explicitly or define `--color-border` in `@theme` and use `border-border`.
+
+**Can I use platform-specific fonts in `@theme {}`?**
+No. `@theme {}` only accepts custom properties. Use `@layer theme { :root { @variant ios { --font-sans: '...'; } } }` instead. Note: use `@variant` (not `@media`) for platform selection in CSS.
+
+**Does Uniwind work with ESM metro config (`metro.config.mjs` or `metro.config.ts`)?**
+Yes since v1.3.0+. If you hit `Class extends value is not a constructor`, update Uniwind or use CommonJS `metro.config.js`.
+
+**Classes from `node_modules` work in dev but not production (bun)?**
+Bun symlinks packages. Tailwind's Oxide scanner can't follow them. Use resolved `@source` paths and hoist the package. See [UI Kit Compatibility](./integrations.md#ui-kit-compatibility) for details.
+
+**How to clear all caches when debugging?**
+`watchman watch-del-all 2>/dev/null; rm -rf node_modules/.cache && npx expo start --clear`. This clears Watchman, Babel/bundler caches, and Expo internal cache.
+
+## MCP Server
+
+Uniwind provides an official MCP server for AI-assisted development. If the user's environment supports MCP, recommend setting it up: [https://docs.uniwind.dev/mcp](https://docs.uniwind.dev/mcp)
+
+## Related Skills
+
+**NativeWind → Uniwind migration**: Use the `migrate-nativewind-to-uniwind` skill for migrating from NativeWind. It handles package removal, config migration, Tailwind v4 upgrade, `cssInterop` removal, theme conversion, and all breaking changes. It is tested and production-ready.
+
+**IMPORTANT**: Do NOT guess Uniwind APIs. If you are unsure about any Uniwind API, hook, component, or configuration option, fetch and verify against the official docs: [https://docs.uniwind.dev/llms-full.txt](https://docs.uniwind.dev/llms-full.txt)
diff --git a/skills/uniwind/references/variants-and-selectors.md b/skills/uniwind/references/variants-and-selectors.md
new file mode 100644
index 00000000..3a61b0b5
--- /dev/null
+++ b/skills/uniwind/references/variants-and-selectors.md
@@ -0,0 +1,221 @@
+## Platform Selectors
+
+Apply platform-specific styles directly in className:
+
+```tsx
+// Individual platforms
+
+
+// native: shorthand (iOS + Android)
+
+
+// TV platforms
+
+
+// Combine with other utilities
+
+```
+
+Platform variants in `@layer theme` for global values (use `@variant`, not `@media`):
+
+```css
+@layer theme {
+ :root {
+ @variant ios { --font-sans: 'SF Pro Text'; }
+ @variant android { --font-sans: 'Roboto-Regular'; }
+ @variant web { --font-sans: 'Inter'; }
+ }
+}
+```
+
+**Prefer platform selectors over `Platform.select()`** — cleaner syntax, no imports needed.
+
+## Data Selectors
+
+Style based on prop values using `data-[prop=value]:utility`:
+
+```tsx
+// Boolean props
+
+
+// String props
+
+
+// Tabs pattern
+
+ {route.title}
+
+
+// Toggle pattern
+
+
+
+```
+
+**Rules**:
+- Only equality selectors supported (`data-[prop=value]`)
+- No presence-only selectors (`data-[prop]` — not supported)
+- No `has-data-*` parent selectors (not supported in React Native)
+- Booleans match both boolean and string forms
+
+## Interactive States
+
+```tsx
+// active: — when pressed
+
+ Press me
+
+
+// disabled: — when disabled prop is true
+
+ Submit
+
+
+// focus: — keyboard/accessibility focus
+
+
+
+ Focusable
+
+```
+
+Components with state support:
+- **Pressable**: `active:`, `disabled:`, `focus:`
+- **TextInput**: `active:`, `disabled:`, `focus:`
+- **Switch**: `disabled:`
+- **Text**: `active:`, `disabled:`
+- **TouchableOpacity / TouchableHighlight / TouchableNativeFeedback / TouchableWithoutFeedback**: `active:`, `disabled:`
+
+## Responsive Breakpoints
+
+Mobile-first — unprefixed styles apply to all sizes, prefixed styles apply at that breakpoint and above:
+
+| Prefix | Min Width | Typical Device |
+|--------|-----------|----------------|
+| (none) | 0px | All (mobile) |
+| `sm:` | 640px | Large phones |
+| `md:` | 768px | Tablets |
+| `lg:` | 1024px | Landscape tablets |
+| `xl:` | 1280px | Desktops |
+| `2xl:` | 1536px | Large desktops |
+
+```tsx
+// Responsive padding and typography
+
+ Responsive
+
+
+// Responsive grid (1 col → 2 col → 3 col)
+
+
+ Item
+
+
+
+// Responsive visibility
+
+ Visible on tablet+
+
+
+ Mobile only
+
+```
+
+Custom breakpoints:
+
+```css
+@theme {
+ --breakpoint-xs: 480px;
+ --breakpoint-tablet: 820px;
+ --breakpoint-3xl: 1920px;
+}
+```
+
+Usage: `xs:p-2 tablet:p-4 3xl:p-8`
+
+**Design mobile-first** — start with base styles (no prefix), enhance with breakpoints:
+
+```tsx
+// CORRECT — mobile-first
+
+
+// WRONG — desktop-first (reversed order is confusing and fragile)
+
+```
+
+## Safe Area Utilities
+
+### Padding
+
+| Class | Description |
+|-------|-------------|
+| `p-safe` | All sides |
+| `pt-safe` / `pb-safe` / `pl-safe` / `pr-safe` | Individual sides |
+| `px-safe` / `py-safe` | Horizontal / vertical |
+
+### Margin
+
+| Class | Description |
+|-------|-------------|
+| `m-safe` | All sides |
+| `mt-safe` / `mb-safe` / `ml-safe` / `mr-safe` | Individual sides |
+| `mx-safe` / `my-safe` | Horizontal / vertical |
+
+### Positioning
+
+| Class | Description |
+|-------|-------------|
+| `inset-safe` | All sides |
+| `top-safe` / `bottom-safe` / `left-safe` / `right-safe` | Individual sides |
+| `x-safe` / `y-safe` | Horizontal / vertical inset |
+
+### Compound Variants
+
+| Pattern | Behavior | Example |
+|---------|----------|---------|
+| `{prop}-safe-or-{value}` | `Math.max(inset, value)` — ensures minimum spacing | `pt-safe-or-4` |
+| `{prop}-safe-offset-{value}` | `inset + value` — adds extra spacing on top of inset | `pb-safe-offset-4` |
+
+### Setup
+
+**Uniwind Free (default)** — requires `react-native-safe-area-context` to update insets.
+Wrap your App component in `SafeAreaProvider` and `SafeAreaListener` and call `Uniwind.updateInsets(insets)` in the `onChange` callback:
+
+```tsx
+import { SafeAreaProvider, SafeAreaListener } from 'react-native-safe-area-context';
+import { Uniwind } from 'uniwind';
+
+export default function App() {
+ return (
+
+ {
+ Uniwind.updateInsets(insets);
+ }}
+ >
+ {/* content */}
+
+
+ );
+}
+```
+
+**Uniwind Pro** — automatic, no setup needed. Insets injected from native layer.