start-vibing-stacks 1.9.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ui.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Start Vibing Stacks — Terminal UI
3
3
  */
4
4
  import chalk from 'chalk';
5
- const VERSION = '1.9.1';
5
+ const VERSION = '2.0.0';
6
6
  const gradient = (text) => {
7
7
  const colors = [chalk.hex('#FF6B6B'), chalk.hex('#FF8E53'), chalk.hex('#FFBD2E'), chalk.hex('#48BB78'), chalk.hex('#4299E1'), chalk.hex('#9F7AEA')];
8
8
  return text.split('').map((c, i) => colors[i % colors.length](c)).join('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "start-vibing-stacks",
3
- "version": "1.9.1",
3
+ "version": "2.0.0",
4
4
  "description": "AI-powered multi-stack dev workflow for Claude Code. Supports PHP, Node.js, Python and more.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,273 @@
1
+ # Preline UI — Component & Theme System for TailwindCSS 4
2
+
3
+ **ALWAYS invoke when using Preline components, creating themes, or customizing design tokens.**
4
+
5
+ ## What is Preline
6
+
7
+ Preline is a **semantic token-based design system** built on TailwindCSS. It provides:
8
+ - 220+ CSS tokens for full UI consistency
9
+ - Pre-built components (navbar, sidebar, card, dropdown, overlay, etc.)
10
+ - Theme generator for custom color schemes
11
+ - Light + dark mode via `data-theme` + `.dark`
12
+
13
+ ## Installation (Laravel + Inertia)
14
+
15
+ ```bash
16
+ npm install preline
17
+ ```
18
+
19
+ ```js
20
+ // vite.config.js
21
+ export default defineConfig({
22
+ plugins: [
23
+ laravel({ input: ['resources/css/app.css', 'resources/js/app.tsx'] }),
24
+ ],
25
+ });
26
+ ```
27
+
28
+ ```css
29
+ /* resources/css/app.css */
30
+ @import "tailwindcss";
31
+ @import "preline/themes/theme.css";
32
+ ```
33
+
34
+ ```tsx
35
+ // resources/js/app.tsx — init Preline after Inertia navigation
36
+ import { router } from '@inertiajs/react';
37
+
38
+ router.on('navigate', () => {
39
+ // Re-init Preline components after SPA navigation
40
+ setTimeout(() => {
41
+ import('preline/preline').then(({ HSStaticMethods }) => {
42
+ HSStaticMethods.autoInit();
43
+ });
44
+ }, 100);
45
+ });
46
+ ```
47
+
48
+ ## Token Architecture
49
+
50
+ ```
51
+ Layer 1 — Tailwind primitives: var(--color-blue-600)
52
+ Layer 2 — Preline semantic: --primary: var(--color-blue-600)
53
+ Layer 3 — Component tokens: --navbar-nav-hover: var(--color-gray-100)
54
+ Layer 4 — Usage in HTML: className="bg-primary text-primary-foreground"
55
+ ```
56
+
57
+ ### Core Token Groups
58
+
59
+ | Group | Example Tokens | Purpose |
60
+ |---|---|---|
61
+ | **Background** | `--background`, `--background-1`, `--background-2` | App surfaces |
62
+ | **Foreground** | `--foreground`, `--foreground-inverse` | Text colors |
63
+ | **Primary** | `--primary`, `--primary-hover`, `--primary-foreground`, `--primary-50`→`950` | Brand/action color |
64
+ | **Secondary** | `--secondary`, `--secondary-hover`, `--secondary-foreground` | Secondary emphasis |
65
+ | **Muted** | `--muted`, `--muted-foreground`, `--muted-foreground-1`, `--muted-foreground-2` | Subdued elements |
66
+ | **Destructive** | `--destructive`, `--destructive-hover`, `--destructive-foreground` | Danger actions |
67
+ | **Border** | `--border`, `--border-line-1`→`8` | Border scale (light→dark) |
68
+ | **Surface** | `--surface`, `--surface-1`→`5`, `--surface-foreground` | Elevated layers |
69
+ | **Layer** | `--layer`, `--layer-hover`, `--layer-foreground` | Stacked elements |
70
+
71
+ ### Component Token Groups
72
+
73
+ | Component | Tokens | Notes |
74
+ |---|---|---|
75
+ | **Navbar** | `--navbar`, `--navbar-line`, `--navbar-nav-*` | 3 variants (base, `-1`, `-2`) |
76
+ | **Sidebar** | `--sidebar`, `--sidebar-line`, `--sidebar-nav-*` | 3 variants (base, `-1`, `-2`) |
77
+ | **Card** | `--card`, `--card-line`, `--card-divider`, `--card-header`, `--card-footer` | |
78
+ | **Dropdown** | `--dropdown`, `--dropdown-item-*` | hover, focus, active states |
79
+ | **Select** | `--select`, `--select-item-*` | Same state pattern |
80
+ | **Overlay** | `--overlay`, `--overlay-line`, `--overlay-header`, `--overlay-footer` | Modals |
81
+ | **Tooltip** | `--tooltip`, `--tooltip-foreground`, `--tooltip-line` | |
82
+ | **Popover** | `--popover`, `--popover-line` | |
83
+ | **Scrollbar** | `--scrollbar-track`, `--scrollbar-thumb` | + inverse variants |
84
+
85
+ ## Creating Custom Themes
86
+
87
+ ### Theme File Structure (MUST follow order)
88
+
89
+ ```css
90
+ /* 1. Import base theme */
91
+ @import "./theme.css";
92
+
93
+ /* 2. Theme scoping block — custom palettes ONLY */
94
+ @theme theme-brand inline {
95
+ --color-brand-50: oklch(98% 0.003 250);
96
+ --color-brand-100: oklch(95% 0.01 250);
97
+ --color-brand-200: oklch(88% 0.03 250);
98
+ --color-brand-300: oklch(78% 0.06 250);
99
+ --color-brand-400: oklch(68% 0.10 250);
100
+ --color-brand-500: oklch(58% 0.14 250);
101
+ --color-brand-600: oklch(50% 0.15 250);
102
+ --color-brand-700: oklch(42% 0.13 250);
103
+ --color-brand-800: oklch(35% 0.10 250);
104
+ --color-brand-900: oklch(28% 0.08 250);
105
+ --color-brand-950: oklch(20% 0.05 250);
106
+ }
107
+
108
+ /* 3. Light mode — semantic token overrides */
109
+ :root[data-theme="theme-brand"],
110
+ [data-theme="theme-brand"] {
111
+ --background: var(--color-white);
112
+ --foreground: var(--color-gray-800);
113
+
114
+ --primary: var(--color-brand-600);
115
+ --primary-foreground: var(--color-white);
116
+ --primary-hover: var(--color-brand-700);
117
+ --primary-focus: var(--color-brand-700);
118
+ --primary-active: var(--color-brand-700);
119
+
120
+ /* ... all 220+ tokens as needed */
121
+ }
122
+
123
+ /* 4. Dark mode */
124
+ [data-theme="theme-brand"].dark {
125
+ --background: var(--color-neutral-800);
126
+ --foreground: var(--color-neutral-200);
127
+
128
+ --primary: var(--color-brand-500);
129
+ --primary-foreground: var(--color-white);
130
+ --primary-hover: var(--color-brand-600);
131
+
132
+ /* ... dark overrides */
133
+ }
134
+ ```
135
+
136
+ ### Activation
137
+
138
+ ```html
139
+ <html data-theme="theme-brand">
140
+ <!-- Or with dark mode: -->
141
+ <html data-theme="theme-brand" class="dark">
142
+ ```
143
+
144
+ ```tsx
145
+ // React theme switcher
146
+ function ThemeToggle() {
147
+ const [dark, setDark] = useState(false);
148
+ return (
149
+ <button onClick={() => {
150
+ document.documentElement.classList.toggle('dark');
151
+ setDark(!dark);
152
+ }}>
153
+ {dark ? '☀️' : '🌙'}
154
+ </button>
155
+ );
156
+ }
157
+ ```
158
+
159
+ ## Using Components with React (Inertia)
160
+
161
+ ### Navbar
162
+
163
+ ```tsx
164
+ <nav className="bg-navbar border-b border-navbar-line">
165
+ <div className="max-w-7xl mx-auto px-4 flex items-center justify-between h-16">
166
+ <Link href="/" className="text-foreground font-bold text-lg">Brand</Link>
167
+ <div className="flex items-center gap-1">
168
+ <Link href="/dashboard"
169
+ className="px-3 py-2 rounded-lg text-navbar-nav-foreground hover:bg-navbar-nav-hover transition-colors">
170
+ Dashboard
171
+ </Link>
172
+ <Link href="/leads"
173
+ className="px-3 py-2 rounded-lg text-navbar-nav-foreground hover:bg-navbar-nav-hover transition-colors">
174
+ Leads
175
+ </Link>
176
+ </div>
177
+ </div>
178
+ </nav>
179
+ ```
180
+
181
+ ### Card
182
+
183
+ ```tsx
184
+ <div className="bg-card border border-card-line rounded-xl overflow-hidden">
185
+ <div className="bg-card-header px-6 py-4 border-b border-card-divider">
186
+ <h3 className="text-foreground font-semibold">Title</h3>
187
+ </div>
188
+ <div className="px-6 py-4">
189
+ <p className="text-muted-foreground">Content</p>
190
+ </div>
191
+ <div className="bg-card-footer px-6 py-3 border-t border-card-divider">
192
+ <button className="bg-primary text-primary-foreground px-4 py-2 rounded-lg hover:bg-primary-hover transition-colors">
193
+ Action
194
+ </button>
195
+ </div>
196
+ </div>
197
+ ```
198
+
199
+ ### Sidebar
200
+
201
+ ```tsx
202
+ <aside className="w-64 bg-sidebar border-r border-sidebar-line h-screen">
203
+ <nav className="p-4 space-y-1">
204
+ {navItems.map(item => (
205
+ <Link key={item.href} href={item.href}
206
+ className={`flex items-center gap-3 px-3 py-2 rounded-lg transition-colors
207
+ ${isActive(item.href)
208
+ ? 'bg-sidebar-nav-active text-primary font-medium'
209
+ : 'text-sidebar-nav-foreground hover:bg-sidebar-nav-hover'}`}>
210
+ {item.icon}
211
+ {item.label}
212
+ </Link>
213
+ ))}
214
+ </nav>
215
+ </aside>
216
+ ```
217
+
218
+ ### Dropdown (with Preline JS)
219
+
220
+ ```tsx
221
+ <div className="hs-dropdown relative">
222
+ <button className="hs-dropdown-toggle px-4 py-2 bg-layer border border-layer-line rounded-lg text-layer-foreground hover:bg-layer-hover">
223
+ Options ▾
224
+ </button>
225
+ <div className="hs-dropdown-menu hidden bg-dropdown border border-dropdown-line rounded-lg shadow-lg mt-1 p-1 min-w-48">
226
+ <button className="w-full text-left px-3 py-2 rounded-md text-dropdown-item-foreground hover:bg-dropdown-item-hover">
227
+ Edit
228
+ </button>
229
+ <div className="border-t border-dropdown-divider my-1" />
230
+ <button className="w-full text-left px-3 py-2 rounded-md text-destructive hover:bg-dropdown-item-hover">
231
+ Delete
232
+ </button>
233
+ </div>
234
+ </div>
235
+ ```
236
+
237
+ ## Theme Generator (CLI)
238
+
239
+ ```bash
240
+ # Generate theme from config
241
+ npx preline-theme-generator /tmp/config.json ./resources/css/themes/brand.css
242
+
243
+ # Config format:
244
+ {
245
+ "name": "brand",
246
+ "hue": 250,
247
+ "style": "professional",
248
+ "useCustomDarkGray": true,
249
+ "tailwindGray": "neutral"
250
+ }
251
+ ```
252
+
253
+ ## Chart Tokens (Apexcharts)
254
+
255
+ ```css
256
+ /* Charts require HEX for gradients — no oklch! */
257
+ --chart-colors-primary-hex: #2563eb;
258
+ --chart-colors-chart-1-hex: #8b5cf6;
259
+ --chart-colors-chart-2-hex: #06b6d4;
260
+ ```
261
+
262
+ ## FORBIDDEN
263
+
264
+ | ❌ Don't | ✅ Do |
265
+ |---|---|
266
+ | Modify `theme.css` (base) | Create separate theme file |
267
+ | Put tokens inside `@theme` block | Tokens in selector blocks only |
268
+ | Use raw colors (`bg-blue-500`) | Use semantic tokens (`bg-primary`) |
269
+ | `oklch()` in chart `-hex` tokens | Use hex format for charts |
270
+ | Force HTML class changes | Theme activation via `data-theme` only |
271
+ | Invent token names | Follow Preline's naming system |
272
+ | `@apply` for component styles | React components with token classes |
273
+ | Skip `HSStaticMethods.autoInit()` | Always re-init after Inertia navigation |
@@ -1,94 +1,273 @@
1
- # Tailwind PatternsUtility-First CSS
1
+ # TailwindCSS 4CSS-First Design System
2
2
 
3
- **ALWAYS invoke when writing Tailwind CSS classes.**
3
+ **ALWAYS invoke when writing Tailwind classes, theming, or responsive layouts.**
4
4
 
5
- ## Mobile-First Breakpoints
5
+ ## What Changed (v3 → v4)
6
6
 
7
- ```
8
- sm: 640px → md: 768px → lg: 1024px → xl: 1280px → 2xl: 1536px
7
+ | v3 (Legacy) | v4 (Current) |
8
+ |---|---|
9
+ | `tailwind.config.js` | CSS `@theme` directive |
10
+ | PostCSS plugin | Oxide engine (10x faster) |
11
+ | `@tailwind base/components/utilities` | `@import "tailwindcss"` |
12
+ | Colors in JS config | Colors as CSS variables |
13
+ | `@apply` everywhere | Components > `@apply` |
14
+
15
+ ## Setup (v4)
16
+
17
+ ```css
18
+ /* resources/css/app.css (Laravel + Inertia) */
19
+ @import "tailwindcss";
20
+
21
+ @theme {
22
+ /* ─── Semantic Colors (OKLCH for perceptual uniformity) ─── */
23
+ --color-primary: oklch(0.55 0.15 250);
24
+ --color-primary-foreground: oklch(0.98 0 0);
25
+ --color-secondary: oklch(0.75 0.05 250);
26
+ --color-secondary-foreground: oklch(0.15 0 0);
27
+ --color-destructive: oklch(0.55 0.2 25);
28
+ --color-destructive-foreground: oklch(0.98 0 0);
29
+
30
+ --color-background: oklch(0.99 0 0);
31
+ --color-foreground: oklch(0.15 0 0);
32
+ --color-muted: oklch(0.95 0.01 250);
33
+ --color-muted-foreground: oklch(0.45 0.02 250);
34
+ --color-border: oklch(0.90 0.01 250);
35
+ --color-ring: oklch(0.55 0.15 250);
36
+
37
+ --color-surface: oklch(0.98 0 0);
38
+ --color-surface-raised: oklch(1 0 0);
39
+
40
+ /* ─── Typography ─── */
41
+ --font-sans: 'Inter', system-ui, sans-serif;
42
+ --font-mono: 'JetBrains Mono', monospace;
43
+
44
+ /* ─── Spacing ─── */
45
+ --spacing-page: 1rem;
46
+
47
+ /* ─── Border Radius ─── */
48
+ --radius-sm: 0.375rem;
49
+ --radius-md: 0.5rem;
50
+ --radius-lg: 0.75rem;
51
+ --radius-xl: 1rem;
52
+
53
+ /* ─── Shadows ─── */
54
+ --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.05);
55
+ --shadow-md: 0 4px 6px oklch(0 0 0 / 0.07);
56
+ --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.1);
57
+
58
+ /* ─── Animations ─── */
59
+ --animate-fade-in: fade-in 0.2s ease-out;
60
+ --animate-slide-up: slide-up 0.3s ease-out;
61
+ --animate-slide-down: slide-down 0.3s ease-out;
62
+ }
63
+
64
+ /* ─── Dark Mode Override ─── */
65
+ @theme dark {
66
+ --color-background: oklch(0.13 0.01 250);
67
+ --color-foreground: oklch(0.95 0 0);
68
+ --color-surface: oklch(0.17 0.01 250);
69
+ --color-surface-raised: oklch(0.21 0.01 250);
70
+ --color-muted: oklch(0.22 0.02 250);
71
+ --color-muted-foreground: oklch(0.65 0.02 250);
72
+ --color-border: oklch(0.28 0.02 250);
73
+ }
74
+
75
+ /* ─── Keyframes ─── */
76
+ @keyframes fade-in {
77
+ from { opacity: 0; }
78
+ to { opacity: 1; }
79
+ }
80
+ @keyframes slide-up {
81
+ from { opacity: 0; transform: translateY(8px); }
82
+ to { opacity: 1; transform: translateY(0); }
83
+ }
84
+ @keyframes slide-down {
85
+ from { opacity: 0; transform: translateY(-8px); }
86
+ to { opacity: 1; transform: translateY(0); }
87
+ }
9
88
  ```
10
89
 
11
- ```tsx
12
- <div className="w-full md:w-1/2 lg:w-1/3 xl:w-1/4">
13
- {/* Mobile: full → Tablet: half → Desktop: third → Large: quarter */}
14
- </div>
90
+ ## Color Token Architecture
91
+
15
92
  ```
93
+ Layer 1 — Primitive: oklch(0.55 0.15 250) (raw values)
94
+ Layer 2 — Semantic: --color-primary (purpose-based)
95
+ Layer 3 — Component: className="bg-primary" (usage in JSX)
16
96
 
17
- ## Layout Patterns
97
+ Usage in Tailwind classes:
98
+ bg-primary text-primary-foreground
99
+ bg-destructive text-destructive-foreground
100
+ bg-muted text-muted-foreground
101
+ bg-surface border-border
102
+ ```
18
103
 
19
- ### Flexbox
20
- ```tsx
21
- // Center
22
- <div className="flex items-center justify-center h-screen" />
104
+ ## Mobile-First Responsive
23
105
 
24
- // Responsive direction
25
- <div className="flex flex-col md:flex-row gap-4" />
106
+ ```
107
+ Breakpoints (min-width):
108
+ (none) → 0px Mobile base
109
+ sm: → 640px Large phone
110
+ md: → 768px Tablet
111
+ lg: → 1024px Laptop
112
+ xl: → 1280px Desktop
113
+ 2xl: → 1536px Large desktop
26
114
  ```
27
115
 
28
- ### Grid
29
116
  ```tsx
30
- // Responsive grid
31
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" />
117
+ {/* Mobile: stack → Tablet: 2 cols → Desktop: 3 cols */}
118
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
32
119
 
33
- // Auto-fit
34
- <div className="grid grid-cols-[repeat(auto-fit,minmax(300px,1fr))] gap-4" />
120
+ {/* Mobile: full width → Desktop: sidebar layout */}
121
+ <div className="flex flex-col lg:flex-row gap-6">
122
+ <aside className="w-full lg:w-64 shrink-0">Sidebar</aside>
123
+ <main className="flex-1">Content</main>
124
+ </div>
35
125
  ```
36
126
 
37
- ## Dark Mode
127
+ ## Container Queries (v4 Native)
38
128
 
39
129
  ```tsx
40
- <div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
41
- <p className="text-gray-600 dark:text-gray-300">Adapts to theme</p>
130
+ {/* Parent defines container */}
131
+ <div className="@container">
132
+ {/* Children respond to PARENT width, not viewport */}
133
+ <div className="flex flex-col @md:flex-row @lg:grid @lg:grid-cols-3 gap-4">
134
+ <Card />
135
+ </div>
136
+ </div>
137
+
138
+ {/* Named containers for specificity */}
139
+ <div className="@container/card">
140
+ <h2 className="text-sm @md/card:text-lg">Title</h2>
42
141
  </div>
43
142
  ```
44
143
 
144
+ **Rule:** Use container queries for **reusable components** (cards, widgets). Use viewport breakpoints for **page-level layouts**.
145
+
45
146
  ## Component Patterns
46
147
 
47
- ### Card
148
+ ### Button
149
+
48
150
  ```tsx
49
- <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 border border-gray-200 dark:border-gray-700 hover:shadow-lg transition-shadow">
151
+ const buttonVariants = {
152
+ base: "inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed",
153
+ variant: {
154
+ primary: "bg-primary text-primary-foreground hover:bg-primary/90",
155
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
156
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
157
+ outline: "border border-border bg-transparent hover:bg-muted",
158
+ ghost: "hover:bg-muted",
159
+ },
160
+ size: {
161
+ sm: "h-8 px-3 text-sm",
162
+ md: "h-10 px-4 text-sm",
163
+ lg: "h-12 px-6 text-base",
164
+ },
165
+ };
50
166
  ```
51
167
 
52
- ### Button
168
+ ### Card
169
+
53
170
  ```tsx
54
- <button className="bg-primary text-primary-foreground px-4 py-2 rounded-md font-medium hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors">
171
+ <div className="bg-surface-raised rounded-lg border border-border shadow-sm p-6 hover:shadow-md transition-shadow">
172
+ <h3 className="text-lg font-semibold text-foreground">Title</h3>
173
+ <p className="mt-2 text-muted-foreground">Description</p>
174
+ </div>
55
175
  ```
56
176
 
57
177
  ### Input
178
+
58
179
  ```tsx
59
- <input className="w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-md text-gray-900 dark:text-white placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" />
180
+ <input className="w-full h-10 px-3 rounded-md border border-border bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent transition-colors" />
60
181
  ```
61
182
 
62
- ## Animations
183
+ ### Table (responsive)
63
184
 
64
185
  ```tsx
65
- <Loader className="h-5 w-5 animate-spin" /> // Spinner
66
- <div className="h-4 w-24 bg-gray-200 animate-pulse" /> // Skeleton
67
- ```
68
-
69
- ### Custom (tailwind.config.js)
70
- ```js
71
- animation: {
72
- 'fade-in': 'fadeIn 0.3s ease-in-out',
73
- 'slide-up': 'slideUp 0.3s ease-out',
74
- },
75
- keyframes: {
76
- fadeIn: { '0%': { opacity: '0' }, '100%': { opacity: '1' } },
77
- slideUp: { '0%': { transform: 'translateY(10px)', opacity: '0' }, '100%': { transform: 'translateY(0)', opacity: '1' } },
78
- }
186
+ {/* Mobile: card layout Desktop: table */}
187
+ <div className="hidden md:block">
188
+ <table className="w-full text-sm">
189
+ <thead className="border-b border-border">
190
+ <tr className="text-left text-muted-foreground">
191
+ <th className="p-3 font-medium">Name</th>
192
+ </tr>
193
+ </thead>
194
+ </table>
195
+ </div>
196
+ <div className="md:hidden space-y-3">
197
+ {/* Card layout for mobile */}
198
+ </div>
199
+ ```
200
+
201
+ ## Dark Mode
202
+
203
+ ```tsx
204
+ {/* Automatic with semantic tokens */}
205
+ <div className="bg-background text-foreground">
206
+ <p className="text-muted-foreground">Always adapts</p>
207
+ <div className="border-border bg-surface">Card</div>
208
+ </div>
209
+
210
+ {/* Toggle button */}
211
+ <button onClick={() => document.documentElement.classList.toggle('dark')}>
212
+ Toggle Theme
213
+ </button>
79
214
  ```
80
215
 
81
- ## Show/Hide Responsive
216
+ **Rule:** Use semantic tokens (`bg-background`, `text-foreground`) instead of explicit dark classes. The `@theme dark` block handles everything.
217
+
218
+ ## Show/Hide
82
219
 
83
220
  ```tsx
84
221
  <div className="hidden lg:block">Desktop only</div>
85
- <div className="block lg:hidden">Mobile only</div>
222
+ <div className="lg:hidden">Mobile only</div>
86
223
  <span className="sr-only">Screen reader only</span>
87
224
  ```
88
225
 
226
+ ## Auto-fit Grid
227
+
228
+ ```tsx
229
+ {/* Cards that auto-wrap based on available space */}
230
+ <div className="grid grid-cols-[repeat(auto-fit,minmax(280px,1fr))] gap-4">
231
+ {items.map(item => <Card key={item.id} {...item} />)}
232
+ </div>
233
+ ```
234
+
235
+ ## Animations
236
+
237
+ ```tsx
238
+ <div className="animate-fade-in">Fades in on mount</div>
239
+ <div className="animate-slide-up">Slides up on mount</div>
240
+ <Loader className="h-5 w-5 animate-spin" />
241
+ <div className="h-4 w-24 bg-muted animate-pulse rounded" /> {/* Skeleton */}
242
+ ```
243
+
244
+ ## Spacing Consistency
245
+
246
+ ```
247
+ Use the 4px scale consistently:
248
+ gap-1 = 4px p-1 = 4px
249
+ gap-2 = 8px p-2 = 8px
250
+ gap-3 = 12px p-3 = 12px
251
+ gap-4 = 16px p-4 = 16px
252
+ gap-6 = 24px p-6 = 24px
253
+ gap-8 = 32px p-8 = 32px
254
+
255
+ Page padding: px-4 md:px-6 lg:px-8
256
+ Section gaps: space-y-6 md:space-y-8
257
+ Card padding: p-4 md:p-6
258
+ ```
259
+
89
260
  ## FORBIDDEN
90
261
 
91
- 1. **`!important`** fix specificity properly
92
- 2. **Arbitrary values when utilities exist** — use the scale
93
- 3. **Mixing raw CSS with Tailwind** stick to utilities
94
- 4. **Inconsistent spacing** follow the 4px scale (p-1=4px, p-2=8px, p-4=16px)
262
+ | Don't | Do |
263
+ |---|---|
264
+ | `tailwind.config.js` in v4 | `@theme` in CSS |
265
+ | `@apply` for everything | React components |
266
+ | `!important` | Fix specificity |
267
+ | `style={{ color: 'red' }}` | `text-destructive` |
268
+ | Arbitrary values for tokens | Define in `@theme` |
269
+ | `bg-white dark:bg-gray-900` | `bg-background` (semantic) |
270
+ | `@tailwind base` | `@import "tailwindcss"` (v4) |
271
+ | Dynamic class strings | Static complete strings (purge-safe) |
272
+ | `text-[#FF5733]` inline | `--color-accent` in `@theme` |
273
+ | Inconsistent spacing | Follow 4px scale |