+```
+
+**Current status:** Already supported for colors via `alpha` modifier
+**Enhancement:** Generalize to custom modifiers via `modifiers` option
+
+**Implementation:**
+- Check if `matchUtilities` already handles modifiers (it likely does via `coerceValue()`)
+- If not, add modifier extraction before value coercion
+- Pass modifier to utility function as second parameter
+
+**Complexity:** Low - likely already implemented
+
+---
+
+### 4.5 Fallback Plugin System
+**File:** `src/lib/generateRules.js` (candidate rule matching, ~lines 350-450)
+
+**Goal:** Handle ambiguous arbitrary values by trying multiple plugins
+```html
+
+```
+
+**Implementation:**
+- When multiple plugins match a candidate, try generating rules with each
+- If one succeeds and others fail, use the successful one
+- If multiple succeed, use explicit precedence order
+
+**Complexity:** Medium - requires plugin ordering and error handling
+
+---
+
+### 4.6 `matchVariant` Sort Function
+**File:** `src/lib/setupContextUtils.js` (variant API, ~lines 380-450)
+
+**Goal:** Custom sort order for variants with arbitrary values
+```javascript
+matchVariant('min', (value) => `@media (min-width: ${value})`, {
+ sort: (a, z) => parseFloat(a.value) - parseFloat(z.value)
+})
+```
+
+**Check:** May already be implemented - verify in `setupContextUtils.js`
+**If not:** Add `sort` option handling to variant registration
+
+**Complexity:** Low if API exists, Medium if needs implementation
+
+---
+
+## Phase 5: Content Extraction Updates
+
+**File:** `src/lib/defaultExtractor.js` (lines 1-27)
+
+**Add patterns for new variants:**
+```javascript
+// Current patterns include arbitrary variants: /(\[&.*?\]:[^<>"'`\s]*)/
+// Add these:
+
+/(\baria-\[[^\]]+\]:[^<>"'`\s]*)/.source, // aria-[checked]:utility
+/(\bdata-\[[^\]]+\]:[^<>"'`\s]*)/.source, // data-[state=open]:utility
+/(\bsupports-\[[^\]]+\]:[^<>"'`\s]*)/.source, // supports-[display:grid]:utility
+/(\bmin-\[[^\]]+\]:[^<>"'`\s]*)/.source, // min-[768px]:utility
+/(\bmax-\[[^\]]+\]:[^<>"'`\s]*)/.source, // max-[1024px]:utility
+```
+
+**Testing:** Ensure extraction catches all new variant patterns in HTML/JSX/template files
+
+---
+
+## Phase 6: Testing Strategy
+
+### 6.1 Create Test File
+**File:** `tests/v3.2-features.test.js` (new file, ~300-400 lines)
+
+**Test structure:**
+```javascript
+describe('v3.2 utilities', () => {
+ test('break-keep utility', () => { ... })
+ test('collapse visibility', () => { ... })
+ test('fill-none and stroke-none', () => { ... })
+ test('baseline alignment utilities', () => { ... })
+ test('negative outline-offset', () => { ... })
+})
+
+describe('v3.2 variants', () => {
+ test('aria variants with predefined values', () => { ... })
+ test('aria variants with arbitrary values', () => { ... })
+ test('data variants with arbitrary values', () => { ... })
+ test('supports variant with feature queries', () => { ... })
+ test('min/max media query variants', () => { ... })
+})
+
+describe('v3.2 configuration', () => {
+ test('@config directive loads custom config', () => { ... })
+ test('relative content paths resolve correctly', () => { ... })
+ test('font-feature-settings in font-family', () => { ... })
+})
+```
+
+### 6.2 Update Existing Tests
+**Files:** `tests/*.test.js`
+- Ensure no regressions in existing v3.1 features
+- Run full test suite: `npm test`
+
+### 6.3 Integration Tests
+**Directory:** `integrations/`
+- Test with Webpack, Vite, Parcel, Rollup
+- Verify new variants work in real-world bundlers
+- Check that tarballs install correctly
+
+---
+
+## Phase 7: Documentation Updates
+
+### 7.1 Update CHANGELOG.md
+**File:** `CHANGELOG.md`
+
+**Add v3.2.0 section:**
+```markdown
+## [3.2.0] - 2026-01-XX
+
+### Added
+
+**New Utilities:**
+- `break-keep` - Prevent breaking within words (word-break: keep-all)
+- `collapse` - Collapse table rows/columns (visibility: collapse)
+- `fill-none` - No SVG fill (fill: none)
+- `stroke-none` - No SVG stroke (stroke: none)
+- `place-content-baseline`, `place-items-baseline`, `content-baseline` - Baseline alignment
+- Negative `outline-offset-*` values
+
+**New Variants:**
+- `aria-*` - Style based on ARIA attributes (aria-checked:, aria-[disabled]:)
+- `data-*` - Style based on data attributes (data-[state=open]:, data-[loading]:)
+- `supports-*` - CSS feature query variant (supports-[display:grid]:)
+- `min-*` / `max-*` - Arbitrary min/max-width media queries (min-[768px]:, max-[1024px]:)
+
+**Configuration:**
+- `@config` directive for per-file configuration
+- `relative: true` option for content paths relative to config file
+- Font feature settings support in `fontFamily` theme
+- Modifier support in `matchUtilities`
+- Fallback plugin system for ambiguous arbitrary values
+- Sort function for `matchVariant`
+
+### Changed
+- Updated version-specific build system to support v3.2.0
+- Enhanced extractor patterns for new variant types
+```
+
+### 7.2 Update README.md
+**File:** `README.md`
+
+**Update lines 22-56** - Change "What's New in v3.1" to "What's New in v3.2":
+- List all v3.2 utilities and variants
+- Provide usage examples
+- Explain new configuration options
+
+**Update lines 57-64** - Migration plan status:
+```markdown
+- **v3.1** - ✅ **DONE** - Arbitrary variants, new utilities, new variants
+- **v3.2** - ✅ **DONE** - ARIA/data variants, @supports, min/max queries, logical properties
+- **v3.4** - Modern CSS features (subgrid, :has(), text-wrap, size-* utilities)
+```
+
+### 7.3 Update CLAUDE.md
+**File:** `CLAUDE.md`
+
+**Lines 1-10:** Update version to v3.2.0
+**Lines 22-64:** Update feature list and implementation status
+
+---
+
+## Phase 8: Build & Package
+
+### 8.1 Build v3.2.0
+```bash
+npm run build
+```
+
+**Expected output:**
+- `lib/3.1.0/` - Preserved from previous build
+- `lib/3.2.0/` - New build output
+- `lib/*.js` - Symlinks updated to point to `3.2.0/`
+
+### 8.2 Package v3.2.0
+```bash
+npm run pack
+```
+
+**Expected output:**
+- `dist/3.1.0/tailwindcss-3.1.0.tgz` - Preserved
+- `dist/3.2.0/tailwindcss-3.2.0.tgz` - New tarball
+- `dist/tailwindcss-3.2.0.tgz` - Convenience copy
+
+### 8.3 Test Installation
+```bash
+cd /tmp
+mkdir test-v3.2
+cd test-v3.2
+npm init -y
+npm install /home/ktaylor/Projects/tailwindcss/dist/3.2.0/tailwindcss-3.2.0.tgz
+npx tailwindcss init
+```
+
+Create test HTML with v3.2 features and verify CSS generation.
+
+---
+
+## Phase 9: Version Control
+
+### 9.1 Commit Changes
+```bash
+git add .
+git commit -m "feat: Tailwind CSS v3.2.0 JavaScript-only fork
+
+- Add new utilities: break-keep, collapse, fill-none, stroke-none, baseline alignment, negative outline-offset
+- Add new variants: aria-*, data-*, supports-*, min-*, max-*
+- Add configuration features: @config directive, relative paths, font-feature-settings
+- Add comprehensive test suite for v3.2 features
+- Preserve v3.1.0 build artifacts alongside v3.2.0
+- Update documentation and changelog
+
+Adapted from Tailwind CSS v3.2 (official release) while maintaining JavaScript-only architecture (no Rust/Oxide dependencies)."
+```
+
+### 9.2 Create Git Tag
+```bash
+git tag -a v3.2.0 -m "Tailwind CSS v3.2.0 (JavaScript-only fork)"
+```
+
+### 9.3 Optional: Push to Remote
+```bash
+git push origin javascript-fork-v3.2.0
+git push origin v3.2.0
+```
+
+---
+
+## Critical Files Reference
+
+**Files to modify (in order of changes):**
+
+1. `package.json` - Version bump
+2. `src/corePlugins.js` - All utilities and variants (~300 lines of changes)
+3. `src/public/default-theme.js` - Add `aria` and `data` theme keys
+4. `src/lib/defaultExtractor.js` - Add extraction patterns for new variants
+5. `src/lib/expandTailwindAtRules.js` - Add `@config` directive support
+6. `src/lib/setupContextUtils.js` - Add relative path resolution
+7. `tests/v3.2-features.test.js` - Complete test suite (NEW FILE)
+8. `CHANGELOG.md` - Document v3.2.0 changes
+9. `README.md` - Update feature list and migration status
+10. `CLAUDE.md` - Update version and feature references
+
+**Files to preserve:**
+- `lib/3.1.0/*` - Keep all v3.1.0 build artifacts
+- `dist/3.1.0/*` - Keep v3.1.0 tarball
+
+---
+
+## Verification Checklist
+
+### Build Verification
+- [ ] `npm install` completes without errors
+- [ ] `npm run build` generates `lib/3.2.0/` directory
+- [ ] Symlinks in `lib/` point to `3.2.0/` files
+- [ ] `npm run pack` creates `dist/3.2.0/tailwindcss-3.2.0.tgz`
+- [ ] Tarball installs correctly in test project
+
+### Feature Verification
+- [ ] All new utilities generate correct CSS
+- [ ] `aria-*` variant works with predefined and arbitrary values
+- [ ] `data-*` variant works with arbitrary values
+- [ ] `supports-*` variant generates `@supports` queries
+- [ ] `min-*` / `max-*` variants generate media queries
+- [ ] Negative outline-offset values work
+- [ ] Baseline alignment utilities render correctly
+
+### Testing Verification
+- [ ] `npm test` passes all tests
+- [ ] New v3.2 test file has 100% coverage of new features
+- [ ] No regressions in v3.1 features
+- [ ] Integration tests pass with bundlers
+
+### Documentation Verification
+- [ ] CHANGELOG.md has complete v3.2.0 section
+- [ ] README.md reflects v3.2 features
+- [ ] CLAUDE.md updated with v3.2 patterns
+- [ ] Usage examples in README work correctly
+
+### End-to-End Verification
+1. Install tarball in fresh project
+2. Create `tailwind.config.js` with v3.2 features
+3. Create HTML with all new utilities and variants
+4. Run `npx tailwindcss -i input.css -o output.css`
+5. Verify generated CSS contains all expected rules
+6. Test in browser that styles apply correctly
+
+---
+
+## Estimated Implementation Order
+
+1. **Day 1: Simple Utilities** (2-3 hours)
+ - break-keep, collapse, fill-none, stroke-none
+ - Baseline alignment utilities
+ - Negative outline-offset
+
+2. **Day 2: ARIA/Data Variants** (3-4 hours)
+ - aria-* variant with theme
+ - data-* variant
+ - Extraction patterns
+ - Basic tests
+
+3. **Day 3: Media/Feature Variants** (4-5 hours)
+ - supports-* variant
+ - min-* / max-* variants
+ - Extraction patterns
+ - Complex tests
+
+4. **Day 4: Configuration Features** (4-6 hours)
+ - @config directive
+ - Relative paths
+ - Font feature settings
+ - matchUtilities enhancements
+
+5. **Day 5: Testing & Documentation** (3-4 hours)
+ - Comprehensive test suite
+ - Update all documentation
+ - Build and package
+ - End-to-end verification
+
+**Total Estimate:** 16-22 hours of focused development
+
+---
+
+## Notes & Considerations
+
+### Rust/Oxide Avoidance
+- All features implemented in pure JavaScript/TypeScript
+- No binary dependencies or native compilation
+- PostCSS-based processing throughout
+- Regex-based extraction (not state machines)
+
+### Backwards Compatibility
+- v3.1.0 artifacts preserved in `lib/3.1.0/`
+- Symlinks ensure existing projects continue working
+- No breaking changes to existing APIs
+
+### Performance Considerations
+- New variant extraction may slightly slow content scanning
+- Consider caching for `@supports` / `min-*` / `max-*` variants
+- Test with large projects to ensure acceptable performance
+
+### Future Migration Path
+- v3.3: Container queries, logical property enhancements
+- v3.4: Subgrid, :has(), text-wrap utilities
+- Each version preserves previous builds
+
+### Known Limitations
+- `matchVariant` sort function may not exist in v3.1 codebase (need to implement)
+- Complex `@supports` queries with nested parentheses need careful parsing
+- Min/max media queries need proper numeric sorting
+
+---
+
+## Quick Reference: v3.2 Features at a Glance
+
+### New Utilities (8)
+| Utility | CSS Property | Use Case |
+|---------|--------------|----------|
+| `break-keep` | `word-break: keep-all` | Keep words intact (CJK languages) |
+| `collapse` | `visibility: collapse` | Collapse table rows/columns |
+| `fill-none` | `fill: none` | No SVG fill |
+| `stroke-none` | `stroke: none` | No SVG stroke |
+| `place-content-baseline` | `place-content: baseline` | Grid/flex baseline alignment |
+| `place-items-baseline` | `place-items: baseline` | Grid/flex baseline alignment |
+| `content-baseline` | `align-content: baseline` | Baseline content alignment |
+| `-outline-offset-*` | `outline-offset: -Xpx` | Negative outline offset |
+
+### New Variants (4)
+| Variant | Selector Pattern | Example |
+|---------|------------------|---------|
+| `aria-*` | `[aria-{state}="..."]` | `aria-checked:bg-blue-500` |
+| `data-*` | `[data-{attr}="..."]` | `data-[state=open]:block` |
+| `supports-*` | `@supports (prop: val)` | `supports-[display:grid]:grid` |
+| `min-*/max-*` | `@media (min/max-width: X)` | `min-[768px]:flex` |
+
+### Configuration (6)
+| Feature | Purpose | Complexity |
+|---------|---------|------------|
+| `@config` directive | Per-file configuration | Moderate |
+| `relative: true` | Config-relative content paths | Low |
+| Font feature settings | Advanced typography | Low |
+| `matchUtilities` modifiers | Custom modifiers | Low (likely exists) |
+| Fallback plugins | Ambiguous value handling | Medium |
+| `matchVariant` sort | Custom variant ordering | Low-Medium |
diff --git a/MIGRATION-TO-V3.3.md b/MIGRATION-TO-V3.3.md
new file mode 100644
index 000000000000..510dc824853c
--- /dev/null
+++ b/MIGRATION-TO-V3.3.md
@@ -0,0 +1,926 @@
+# Migration Plan: Tailwind CSS v3.3.0 (JavaScript-only Fork)
+
+## Overview
+
+**Goal:** Create a complete JavaScript-only implementation of Tailwind CSS v3.3 features, forked from the current `javascript-fork-v3.2.0` branch.
+
+**Branch:** `javascript-fork-v3.3.0` (new branch from `javascript-fork-v3.2.0`)
+
+**Version:** 3.3.0
+
+**Strategy:** Preserve v3.2.0 artifacts, build v3.3.0 alongside them using the established version-specific build system.
+
+**Scope:** Complete v3.3 feature port including:
+- Extended color palette (950 shades)
+- Line-clamp utilities (from plugin)
+- Logical properties utilities
+- Enhanced gradient controls
+- Font-size line-height modifiers
+- New utility classes
+
+---
+
+## Phase 1: Branch Setup & Version Configuration
+
+### 1.1 Create New Branch
+```bash
+git checkout javascript-fork-v3.2.0
+git checkout -b javascript-fork-v3.3.0
+```
+
+### 1.2 Update Version Numbers
+**File:** `package.json`
+- Update `"version": "3.2.0"` → `"version": "3.3.0"`
+
+**File:** `README.md` (lines 1-3)
+- Update title from "3.2 (javaScript version)" to "3.3 (javaScript version)"
+- Update version reference to v3.3.0
+
+**File:** `CLAUDE.md` (lines 1-10)
+- Update version references to v3.3.0
+- Update feature list to reflect v3.3 additions
+
+### 1.3 Update Migration Status
+**File:** `README.md` (migration plan section)
+- Mark v3.3 as "✅ **DONE**" after completion
+- Update feature descriptions
+
+---
+
+## Phase 2: Extended Color Palette - 950 Shades
+
+All changes in: `src/public/colors.js` and `stubs/defaultConfig.stub.js`
+
+### 2.1 Add 950 Shade to All Colors
+**Location:** `src/public/colors.js`
+
+**Colors to update:**
+- `slate`, `gray`, `zinc`, `neutral`, `stone` (neutral grays)
+- `red`, `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`
+
+**Pattern for each color:**
+```javascript
+slate: {
+ 50: '#f8fafc',
+ 100: '#f1f5f9',
+ // ... existing shades
+ 900: '#0f172a',
+ 950: '#020617', // ADD THIS - darkest shade
+}
+```
+
+**950 Shade Values:**
+- Grays (slate/gray/zinc/neutral/stone): Act as "tinted black" - very dark with slight hue
+- Colors: Optimized for high contrast text and tinted control backgrounds
+- Use values from official Tailwind CSS v3.3 color palette
+
+### 2.2 Update Default Theme
+**Location:** `stubs/defaultConfig.stub.js`
+
+Ensure the extended color palette is exported and available in the default theme configuration.
+
+---
+
+## Phase 3: Line-Clamp Utilities (Built-in)
+
+**Goal:** Promote `@tailwindcss/line-clamp` plugin functionality into core
+
+### 3.1 Add Line-Clamp Plugin to Core
+**Location:** `src/corePlugins.js`
+
+**Implementation:**
+```javascript
+lineClamp: ({ matchUtilities, addUtilities, theme }) => {
+ // Add base utility for disabling line-clamp
+ addUtilities({
+ '.line-clamp-none': {
+ 'overflow': 'visible',
+ 'display': 'block',
+ '-webkit-box-orient': 'horizontal',
+ '-webkit-line-clamp': 'none',
+ },
+ })
+
+ // Add numbered line-clamp utilities
+ matchUtilities(
+ {
+ 'line-clamp': (value) => ({
+ 'overflow': 'hidden',
+ 'display': '-webkit-box',
+ '-webkit-box-orient': 'vertical',
+ '-webkit-line-clamp': `${value}`,
+ }),
+ },
+ { values: theme('lineClamp') }
+ )
+}
+```
+
+### 3.2 Add Theme Configuration
+**Location:** `stubs/defaultConfig.stub.js`
+
+```javascript
+lineClamp: {
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+}
+```
+
+**Usage examples:**
+- `line-clamp-1` - Truncate to 1 line
+- `line-clamp-3` - Truncate to 3 lines
+- `line-clamp-none` - Disable line clamping
+
+---
+
+## Phase 4: Logical Properties Utilities
+
+All changes in: `src/corePlugins.js`
+
+### 4.1 Add Logical Inset Properties
+**Location:** After existing `inset` plugin
+
+**Add new utilities:**
+```javascript
+insetInline: createUtilityPlugin('insetInline', [['inset-inline', ['inset-inline']]], {
+ supportsNegativeValues: true,
+}),
+insetInlineStart: createUtilityPlugin('insetInlineStart', [['inset-inline-start', ['inset-inline-start']]], {
+ supportsNegativeValues: true,
+}),
+insetInlineEnd: createUtilityPlugin('insetInlineEnd', [['inset-inline-end', ['inset-inline-end']]], {
+ supportsNegativeValues: true,
+}),
+insetBlock: createUtilityPlugin('insetBlock', [['inset-block', ['inset-block']]], {
+ supportsNegativeValues: true,
+}),
+insetBlockStart: createUtilityPlugin('insetBlockStart', [['inset-block-start', ['inset-block-start']]], {
+ supportsNegativeValues: true,
+}),
+insetBlockEnd: createUtilityPlugin('insetBlockEnd', [['inset-block-end', ['inset-block-end']]], {
+ supportsNegativeValues: true,
+}),
+```
+
+### 4.2 Add Logical Margin Properties
+**Location:** After existing `margin` plugin
+
+```javascript
+marginInline: createUtilityPlugin('marginInline', [
+ ['mx', ['margin-inline-start', 'margin-inline-end']], // Alias for existing mx
+ ['margin-inline', ['margin-inline']],
+], {
+ supportsNegativeValues: true,
+}),
+marginInlineStart: createUtilityPlugin('marginInlineStart', [
+ ['ms', ['margin-inline-start']],
+ ['margin-inline-start', ['margin-inline-start']],
+], {
+ supportsNegativeValues: true,
+}),
+marginInlineEnd: createUtilityPlugin('marginInlineEnd', [
+ ['me', ['margin-inline-end']],
+ ['margin-inline-end', ['margin-inline-end']],
+], {
+ supportsNegativeValues: true,
+}),
+marginBlock: createUtilityPlugin('marginBlock', [
+ ['my', ['margin-block-start', 'margin-block-end']], // Alias for existing my
+ ['margin-block', ['margin-block']],
+], {
+ supportsNegativeValues: true,
+}),
+marginBlockStart: createUtilityPlugin('marginBlockStart', [
+ ['mt', ['margin-block-start']], // Alias for existing mt
+ ['margin-block-start', ['margin-block-start']],
+], {
+ supportsNegativeValues: true,
+}),
+marginBlockEnd: createUtilityPlugin('marginBlockEnd', [
+ ['mb', ['margin-block-end']], // Alias for existing mb
+ ['margin-block-end', ['margin-block-end']],
+], {
+ supportsNegativeValues: true,
+}),
+```
+
+### 4.3 Add Logical Padding Properties
+**Location:** After existing `padding` plugin
+
+Similar structure to margin, with `padding-inline`, `padding-inline-start`, `padding-inline-end`, `padding-block`, `padding-block-start`, `padding-block-end`.
+
+Use shortcuts: `ps`, `pe` for padding-inline-start/end.
+
+### 4.4 Add Logical Border Radius Properties
+**Location:** After existing `borderRadius` plugin
+
+```javascript
+borderStartStartRadius: createUtilityPlugin('borderStartStartRadius', [
+ ['rounded-ss', ['border-start-start-radius']],
+]),
+borderStartEndRadius: createUtilityPlugin('borderStartEndRadius', [
+ ['rounded-se', ['border-start-end-radius']],
+]),
+borderEndStartRadius: createUtilityPlugin('borderEndStartRadius', [
+ ['rounded-es', ['border-end-start-radius']],
+]),
+borderEndEndRadius: createUtilityPlugin('borderEndEndRadius', [
+ ['rounded-ee', ['border-end-end-radius']],
+]),
+```
+
+### 4.5 Add Logical Scroll Properties
+**Location:** After existing scroll utilities
+
+- `scroll-margin-inline`, `scroll-margin-inline-start`, `scroll-margin-inline-end`
+- `scroll-margin-block`, `scroll-margin-block-start`, `scroll-margin-block-end`
+- `scroll-padding-inline`, `scroll-padding-inline-start`, `scroll-padding-inline-end`
+- `scroll-padding-block`, `scroll-padding-block-start`, `scroll-padding-block-end`
+
+---
+
+## Phase 5: Font-Size Line-Height Modifiers
+
+**Goal:** Allow setting line-height alongside font-size in a single utility
+
+### 5.1 Enhance fontSize Plugin
+**Location:** `src/corePlugins.js` - `fontSize` plugin (around line 1648)
+
+**Current implementation:** Already supports arrays like `['14px', '20px']`
+
+**Enhancement needed:** Support modifier syntax like `text-lg/8` where `/8` sets line-height
+
+**Implementation approach:**
+- Modify candidate parsing to detect `/` separator after font-size utility
+- Parse the modifier value (number, named value, arbitrary)
+- Apply line-height alongside font-size
+
+**Example usage:**
+- `text-lg/7` - Font size `lg` with line-height from spacing scale `7`
+- `text-base/loose` - Font size `base` with named line-height `loose`
+- `text-sm/[3rem]` - Font size `sm` with arbitrary line-height `3rem`
+
+**Note:** This may require changes to `src/lib/generateRules.js` to handle modifiers for utilities.
+
+---
+
+## Phase 6: Gradient Color Stop Positions
+
+**Goal:** Allow specifying exact positions for gradient color stops
+
+### 6.1 Add Gradient Position Utilities
+**Location:** `src/corePlugins.js`
+
+**Add new plugins:**
+```javascript
+gradientColorStopPositions: ({ matchUtilities, theme }) => {
+ matchUtilities(
+ {
+ from: (value) => ({
+ '--tw-gradient-from-position': value,
+ }),
+ via: (value) => ({
+ '--tw-gradient-via-position': value,
+ }),
+ to: (value) => ({
+ '--tw-gradient-to-position': value,
+ }),
+ },
+ {
+ values: theme('gradientColorStopPositions'),
+ type: ['length', 'percentage'],
+ }
+ )
+}
+```
+
+### 6.2 Update Gradient Rendering
+**Location:** `src/corePlugins.js` - `gradientColorStops` plugin
+
+Update gradient color stop generation to include position variables:
+```javascript
+'--tw-gradient-from': `${toColorValue(value)} var(--tw-gradient-from-position, 0%)`,
+'--tw-gradient-to': `${toColorValue(value)} var(--tw-gradient-to-position, 100%)`,
+'--tw-gradient-via': `${toColorValue(value)} var(--tw-gradient-via-position, 50%)`,
+```
+
+### 6.3 Add Theme Configuration
+**Location:** `stubs/defaultConfig.stub.js`
+
+```javascript
+gradientColorStopPositions: {
+ '0%': '0%',
+ '5%': '5%',
+ '10%': '10%',
+ // ... through 100%
+}
+```
+
+**Usage examples:**
+- `from-blue-500 from-10%` - Start gradient at 10%
+- `via-purple-500 via-60%` - Middle color at 60%
+- `to-pink-500 to-90%` - End gradient at 90%
+
+---
+
+## Phase 7: Additional New Utilities
+
+All changes in: `src/corePlugins.js`
+
+### 7.1 Hyphens Utilities
+```javascript
+hyphens: ({ addUtilities }) => {
+ addUtilities({
+ '.hyphens-none': { 'hyphens': 'none' },
+ '.hyphens-manual': { 'hyphens': 'manual' },
+ '.hyphens-auto': { 'hyphens': 'auto' },
+ })
+}
+```
+
+### 7.2 Caption-Side Utilities
+```javascript
+captionSide: ({ addUtilities }) => {
+ addUtilities({
+ '.caption-top': { 'caption-side': 'top' },
+ '.caption-bottom': { 'caption-side': 'bottom' },
+ })
+}
+```
+
+### 7.3 List-Style-Image Utilities
+```javascript
+listStyleImage: ({ matchUtilities, theme }) => {
+ matchUtilities(
+ {
+ 'list-image': (value) => ({ 'list-style-image': value }),
+ },
+ { values: theme('listStyleImage') }
+ )
+}
+```
+
+**Theme config:**
+```javascript
+listStyleImage: {
+ none: 'none',
+}
+```
+
+### 7.4 Whitespace Break-Spaces
+**Location:** Existing `whitespace` plugin
+
+**Add:**
+```javascript
+'.whitespace-break-spaces': { 'white-space': 'break-spaces' }
+```
+
+### 7.5 Justify Normal/Stretch
+**Location:** Existing `justifyContent` plugin
+
+**Add:**
+```javascript
+'.justify-normal': { 'justify-content': 'normal' },
+'.justify-stretch': { 'justify-content': 'stretch' },
+```
+
+### 7.6 Content Normal/Stretch
+**Location:** Existing `alignContent` plugin
+
+**Add:**
+```javascript
+'.content-normal': { 'align-content': 'normal' },
+'.content-stretch': { 'align-content': 'stretch' },
+```
+
+### 7.7 Delay-0 and Duration-0
+**Location:** Existing transition utilities
+
+Ensure `0` value is included in transition delay and duration themes.
+
+---
+
+## Phase 8: CSS Variable Arbitrary Values (Shorthand)
+
+**Goal:** Allow using CSS variables without `var()` wrapper in arbitrary values
+
+### 8.1 Update Arbitrary Value Parser
+**Location:** `src/util/isValidArbitraryValue.js` or value coercion in `src/lib/setupContextUtils.js`
+
+**Enhancement:**
+- Detect CSS variable patterns: `--my-variable`, `--tw-color`
+- Automatically wrap in `var()` when used as arbitrary values
+- Example: `bg-[--my-color]` → `background-color: var(--my-color)`
+
+**Implementation approach:**
+1. Check if arbitrary value starts with `--`
+2. If yes, wrap with `var(...)` before applying
+3. Maintain backwards compatibility with explicit `var(...)` syntax
+
+---
+
+## Phase 9: Font-Variation-Settings Support
+
+**Goal:** Default `font-variation-settings` for font families
+
+### 9.1 Enhance fontFamily Configuration
+**Location:** Already implemented in v3.2 via `fontFeatureSettings`
+
+**Extend to support `fontVariationSettings`:**
+```javascript
+fontFamily: {
+ sans: [
+ 'Inter var',
+ {
+ fontFeatureSettings: '"cv11", "ss01"',
+ fontVariationSettings: '"wght" 500', // NEW
+ },
+ ],
+}
+```
+
+### 9.2 Update fontFamily Plugin
+**Location:** `src/corePlugins.js` - `fontFamily` plugin (already modified in v3.2)
+
+**Add support for `fontVariationSettings`:**
+```javascript
+...(options.fontVariationSettings && {
+ 'font-variation-settings': options.fontVariationSettings,
+}),
+```
+
+---
+
+## Phase 10: ESM and TypeScript Config Support
+
+**Goal:** Support `tailwind.config.ts` and `tailwind.config.mjs` files
+
+### 10.1 Enhance Config Loader
+**Location:** `src/util/resolveConfigPath.js`
+
+**Add support for:**
+- `tailwind.config.ts`
+- `tailwind.config.mjs`
+- `tailwind.config.cts`
+
+**Implementation approach:**
+1. Update config file discovery to check for `.ts` and `.mjs` extensions
+2. Use appropriate loaders:
+ - For `.mjs`: Use native ESM import
+ - For `.ts`: Use `@swc/register` or `tsx` to transpile on-the-fly
+3. Fallback to existing `.js` and `.cjs` support
+
+### 10.2 Add Dependencies (if needed)
+**File:** `package.json`
+
+May need to add optional dependencies for TypeScript support:
+- `tsx` or similar TypeScript loader
+- Or rely on existing `@swc/register` dependency
+
+---
+
+## Phase 11: Behavioral Changes
+
+### 11.1 Update rtl/ltr Variants
+**Location:** `src/corePlugins.js` - variant plugins
+
+Remove any deprecation warnings for `rtl` and `ltr` variants (if present).
+
+### 11.2 Use inset Property
+**Location:** `src/corePlugins.js` - positioning utilities
+
+**Change:** Prefer `inset` property over individual `top/right/bottom/left`
+
+**Current utilities like `inset-0`:** Already use `inset` property (verify)
+
+### 11.3 Dark/RTL/LTR Variants DOM-Order Insensitive
+**Location:** `src/corePlugins.js` - variant implementations
+
+**Enhancement:** Use `:is()` or `:where()` selectors to make these variants work regardless of DOM order
+
+**Example:**
+```javascript
+// Instead of: .dark .dark\:bg-black
+// Generate: :is(.dark) .dark\:bg-black
+```
+
+### 11.4 Important Modifier with :is()
+**Location:** `src/lib/generateRules.js` - important handling
+
+Update important modifier to use `:is()` for specificity control.
+
+---
+
+## Phase 12: Content Extraction Updates
+
+**File:** `src/lib/defaultExtractor.js`
+
+### 12.1 Add Line-Height Modifier Pattern
+**Add pattern to extract:**
+- `text-lg/7`
+- `text-base/loose`
+- `text-sm/[3rem]`
+
+**New regex pattern:**
+```javascript
+/(text-[^\s:]+\/[^\s:]+)/.source, // Font-size with line-height modifier
+```
+
+### 12.2 Add Gradient Position Pattern
+**Add pattern to extract:**
+- `from-10%`
+- `via-50%`
+- `to-90%`
+
+**New regex pattern:**
+```javascript
+/(from|via|to)-\d+%/.source, // Gradient color stop positions
+```
+
+### 12.3 Add Logical Property Pattern
+**Ensure extraction of:**
+- `ms-4`, `me-8` (margin-inline)
+- `ps-2`, `pe-6` (padding-inline)
+- `rounded-ss`, `rounded-ee` (border-radius logical)
+
+Existing patterns should cover these, but verify.
+
+---
+
+## Phase 13: Testing Strategy
+
+### 13.1 Create Test File
+**File:** `tests/v3.3-features.test.js` (new file, ~500-600 lines)
+
+**Test structure:**
+```javascript
+describe('v3.3 extended color palette', () => {
+ test('950 shades for all colors', () => { ... })
+})
+
+describe('v3.3 line-clamp utilities', () => {
+ test('line-clamp-1 through line-clamp-6', () => { ... })
+ test('line-clamp-none disables clamping', () => { ... })
+})
+
+describe('v3.3 logical properties', () => {
+ test('logical inset properties', () => { ... })
+ test('logical margin properties', () => { ... })
+ test('logical padding properties', () => { ... })
+ test('logical border-radius properties', () => { ... })
+ test('logical scroll properties', () => { ... })
+})
+
+describe('v3.3 font-size line-height modifiers', () => {
+ test('text-lg/7 sets font-size and line-height', () => { ... })
+ test('arbitrary line-height modifiers', () => { ... })
+})
+
+describe('v3.3 gradient color stop positions', () => {
+ test('from-10% via-50% to-90%', () => { ... })
+})
+
+describe('v3.3 new utilities', () => {
+ test('hyphens utilities', () => { ... })
+ test('caption-side utilities', () => { ... })
+ test('list-style-image utilities', () => { ... })
+ test('whitespace-break-spaces', () => { ... })
+ test('justify-normal and justify-stretch', () => { ... })
+ test('content-normal and content-stretch', () => { ... })
+})
+
+describe('v3.3 CSS variable shorthand', () => {
+ test('bg-[--my-color] expands to var()', () => { ... })
+})
+
+describe('v3.3 font-variation-settings', () => {
+ test('fontVariationSettings in fontFamily config', () => { ... })
+})
+```
+
+### 13.2 Update Existing Tests
+- Ensure no regressions in v3.0, v3.1, v3.2 features
+- Run full test suite: `npm test`
+
+### 13.3 Integration Tests
+**Directory:** `integrations/`
+- Test with bundlers (Webpack, Vite, etc.)
+- Verify ESM/TypeScript config loading works
+
+---
+
+## Phase 14: Documentation Updates
+
+### 14.1 Update CHANGELOG.md
+**File:** `CHANGELOG.md`
+
+**Add v3.3.0 section:**
+```markdown
+## [3.3.0] - 2026-01-XX
+
+### Added
+
+**Extended Color Palette:**
+- Added 950 shade to all color scales for darker UI options
+- Optimized for high contrast text and tinted backgrounds
+
+**Line-Clamp (Built-in):**
+- `line-clamp-{n}` utilities (1-6)
+- `line-clamp-none` utility
+- Promoted from `@tailwindcss/line-clamp` plugin
+
+**Logical Properties:**
+- Inset: `inset-inline`, `inset-inline-start/end`, `inset-block`, `inset-block-start/end`
+- Margin: `ms`, `me`, `margin-inline-start/end`, `margin-block-start/end`
+- Padding: `ps`, `pe`, `padding-inline-start/end`, `padding-block-start/end`
+- Border-radius: `rounded-ss`, `rounded-se`, `rounded-es`, `rounded-ee`
+- Scroll: `scroll-m{s|e|b|t}`, `scroll-p{s|e|b|t}`
+
+**Font-Size Line-Height Modifiers:**
+- `text-{size}/{height}` syntax (e.g., `text-lg/7`)
+- Arbitrary line-heights (e.g., `text-sm/[3rem]`)
+
+**Gradient Color Stop Positions:**
+- `from-{position}`, `via-{position}`, `to-{position}` utilities
+- Fine-tune gradient transitions (e.g., `from-10% via-50% to-90%`)
+
+**New Utilities:**
+- `hyphens-{none|manual|auto}` - Control hyphenation
+- `caption-{top|bottom}` - Table caption position
+- `list-image-{value}` - Custom list item images
+- `whitespace-break-spaces` - CSS white-space value
+- `justify-normal`, `justify-stretch` - Additional justify-content values
+- `content-normal`, `content-stretch` - Additional align-content values
+- `delay-0`, `duration-0` - Zero-value transitions
+
+**Configuration:**
+- ESM config file support (`tailwind.config.mjs`)
+- TypeScript config file support (`tailwind.config.ts`)
+- `fontVariationSettings` support in `fontFamily` theme
+- CSS variable shorthand in arbitrary values (e.g., `bg-[--my-color]`)
+
+### Changed
+- `rtl` and `ltr` variants marked stable (no warnings)
+- Improved specificity handling with `:is()` selectors
+- Updated `dark`, `rtl`, and `ltr` variants to be DOM-order insensitive
+
+### Notes
+JavaScript-only implementation maintaining compatibility with v3.0-v3.2.
+No Rust/Oxide dependencies.
+```
+
+### 14.2 Update README.md
+**File:** `README.md`
+
+Update "What's New in v3.3" section with all features and examples.
+
+### 14.3 Update CLAUDE.md
+**File:** `CLAUDE.md`
+
+Update version and feature references to v3.3.0.
+
+---
+
+## Phase 15: Build & Package
+
+### 15.1 Build v3.3.0
+```bash
+npm run build
+```
+
+**Expected output:**
+- `lib/3.0.24/`, `lib/3.1.0/`, `lib/3.2.0/` - Preserved
+- `lib/3.3.0/` - New build output
+- `lib/*.js` - Symlinks updated to point to `3.3.0/`
+
+### 15.2 Package v3.3.0
+```bash
+npm run pack
+```
+
+**Expected output:**
+- Previous version tarballs preserved
+- `dist/3.3.0/tailwindcss-3.3.0.tgz` - New tarball
+- `dist/tailwindcss-3.3.0.tgz` - Convenience copy
+
+### 15.3 Test Installation
+```bash
+cd /tmp
+mkdir test-v3.3
+cd test-v3.3
+npm init -y
+npm install /home/ktaylor/Projects/tailwindcss/dist/3.3.0/tailwindcss-3.3.0.tgz
+npx tailwindcss init
+```
+
+Create test HTML/config with v3.3 features and verify CSS generation.
+
+---
+
+## Phase 16: Version Control
+
+### 16.1 Commit Changes
+```bash
+git add .
+git commit -m "feat: Tailwind CSS v3.3.0 JavaScript-only fork
+
+Complete v3.3 feature implementation:
+- Extended color palette with 950 shades
+- Line-clamp utilities (built-in)
+- Logical properties (inset, margin, padding, border-radius, scroll)
+- Font-size line-height modifiers
+- Gradient color stop positions
+- New utilities (hyphens, caption-side, list-style-image, etc.)
+- ESM/TypeScript config support
+- CSS variable shorthand
+- Font-variation-settings support
+
+Preserves v3.0.24, v3.1.0, v3.2.0 build artifacts alongside v3.3.0.
+JavaScript-only architecture maintained (no Rust/Oxide dependencies)."
+```
+
+### 16.2 Create Git Tag
+```bash
+git tag -a v3.3.0 -m "Tailwind CSS v3.3.0 (JavaScript-only fork)"
+```
+
+### 16.3 Push to Remote
+```bash
+git push origin javascript-fork-v3.3.0
+git push origin v3.3.0
+```
+
+---
+
+## Critical Files Reference
+
+**Files to modify (in order of changes):**
+
+1. `package.json` - Version bump
+2. `src/public/colors.js` - Add 950 shades to all colors
+3. `stubs/defaultConfig.stub.js` - Add lineClamp, gradientColorStopPositions themes
+4. `src/corePlugins.js` - Add all new utilities and logical properties (~500 lines of changes)
+5. `src/lib/defaultExtractor.js` - Add extraction patterns for new syntaxes
+6. `src/util/resolveConfigPath.js` - Add ESM/TS config support
+7. `src/util/isValidArbitraryValue.js` - Add CSS variable shorthand
+8. `tests/v3.3-features.test.js` - Complete test suite (NEW FILE)
+9. `CHANGELOG.md` - Document v3.3.0 changes
+10. `README.md` - Update feature list and migration status
+11. `CLAUDE.md` - Update version and feature references
+
+**Files to preserve:**
+- `lib/3.0.24/*`, `lib/3.1.0/*`, `lib/3.2.0/*` - Keep all previous build artifacts
+- `dist/3.0.24/*`, `dist/3.1.0/*`, `dist/3.2.0/*` - Keep previous tarballs
+
+---
+
+## Verification Checklist
+
+### Build Verification
+- [ ] `npm install` completes without errors
+- [ ] `npm run build` generates `lib/3.3.0/` directory
+- [ ] Symlinks in `lib/` point to `3.3.0/` files
+- [ ] `npm run pack` creates `dist/3.3.0/tailwindcss-3.3.0.tgz`
+- [ ] Tarball installs correctly in test project
+
+### Feature Verification - Colors
+- [ ] All colors have 950 shade
+- [ ] 950 shades render correctly in CSS
+- [ ] Existing color functionality preserved
+
+### Feature Verification - Line-Clamp
+- [ ] `line-clamp-1` through `line-clamp-6` work
+- [ ] `line-clamp-none` disables clamping
+- [ ] Multi-line text truncates correctly
+
+### Feature Verification - Logical Properties
+- [ ] Logical inset properties work
+- [ ] Logical margin properties (ms, me) work
+- [ ] Logical padding properties (ps, pe) work
+- [ ] Logical border-radius (rounded-ss, etc.) work
+- [ ] Logical scroll properties work
+- [ ] RTL layouts adapt correctly
+
+### Feature Verification - Font Modifiers
+- [ ] `text-lg/7` sets font-size and line-height
+- [ ] Arbitrary modifiers work (e.g., `text-sm/[3rem]`)
+- [ ] Named line-heights work (e.g., `text-base/loose`)
+
+### Feature Verification - Gradient Positions
+- [ ] `from-10%` sets gradient start position
+- [ ] `via-50%` sets middle color position
+- [ ] `to-90%` sets gradient end position
+- [ ] Gradients render with correct positions
+
+### Feature Verification - New Utilities
+- [ ] Hyphens utilities work
+- [ ] Caption-side utilities work
+- [ ] List-style-image utilities work
+- [ ] Whitespace-break-spaces works
+- [ ] Justify-normal/stretch work
+- [ ] Content-normal/stretch work
+
+### Feature Verification - Configuration
+- [ ] ESM config files load (`.mjs`)
+- [ ] TypeScript config files load (`.ts`)
+- [ ] CSS variable shorthand works (`bg-[--my-color]`)
+- [ ] fontVariationSettings in fontFamily works
+
+### Testing Verification
+- [ ] `npm test` passes all tests
+- [ ] New v3.3 test file has comprehensive coverage
+- [ ] No regressions in v3.0, v3.1, v3.2 features
+- [ ] Integration tests pass
+
+### Documentation Verification
+- [ ] CHANGELOG.md has complete v3.3.0 section
+- [ ] README.md reflects v3.3 features
+- [ ] CLAUDE.md updated with v3.3 patterns
+- [ ] Usage examples work correctly
+
+---
+
+## Estimated Implementation Order
+
+1. **Day 1: Colors & Line-Clamp** (3-4 hours)
+ - Add 950 shades to color palette
+ - Implement line-clamp utilities
+ - Basic tests
+
+2. **Day 2: Logical Properties Part 1** (4-5 hours)
+ - Logical inset properties
+ - Logical margin properties
+ - Logical padding properties
+ - Tests
+
+3. **Day 3: Logical Properties Part 2** (3-4 hours)
+ - Logical border-radius
+ - Logical scroll properties
+ - Tests
+
+4. **Day 4: Font Modifiers & Gradients** (4-5 hours)
+ - Font-size line-height modifiers
+ - Gradient color stop positions
+ - Tests
+
+5. **Day 5: New Utilities** (2-3 hours)
+ - Hyphens, caption-side, list-style-image
+ - Whitespace, justify, content utilities
+ - Tests
+
+6. **Day 6: Configuration Enhancements** (3-4 hours)
+ - ESM/TypeScript config support
+ - CSS variable shorthand
+ - Font-variation-settings
+ - Tests
+
+7. **Day 7: Testing & Documentation** (3-4 hours)
+ - Comprehensive test suite
+ - Update all documentation
+ - Build and package
+ - End-to-end verification
+
+**Total Estimate:** 22-29 hours of focused development
+
+---
+
+## Notes & Considerations
+
+### Rust/Oxide Avoidance
+- All features implemented in pure JavaScript/TypeScript
+- No binary dependencies or native compilation
+- PostCSS-based processing throughout
+- Config loading uses standard Node.js mechanisms
+
+### Backwards Compatibility
+- All v3.0.24, v3.1.0, v3.2.0 artifacts preserved
+- Symlinks ensure existing projects continue working
+- No breaking changes to existing APIs
+
+### Performance Considerations
+- Extended color palette adds minimal overhead
+- Logical properties are simple CSS output
+- Line-clamp uses standard CSS properties
+- Test with large projects to ensure acceptable performance
+
+### Future Migration Path
+- v3.4: Subgrid, :has(), text-wrap, size-* utilities
+- Each version preserves previous builds
+- Gradual feature adoption possible
+
+### Known Limitations
+- Font-size line-height modifiers may require significant parser changes
+- ESM/TypeScript config support depends on Node.js version and available loaders
+- Some logical properties may need browser polyfills for older browsers
+
+---
+
+## Reference Links
+
+- [Tailwind CSS v3.3 Official Blog Post](https://tailwindcss.com/blog/tailwindcss-v3-3)
+- [Tailwind CSS v3.3.0 GitHub Release](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.0)
+- [Line-Clamp Documentation](https://v3.tailwindcss.com/docs/line-clamp)
diff --git a/README.md b/README.md
index 2ffaaf89400a..c59179210413 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,12 @@
-
-
-
-
-
-
-
-
+
+ Saulwind CSS v3.4.0 (JavaScript-only Fork)
+
A utility-first CSS framework for rapidly building custom user interfaces.
+**Forked from** - TailwindCSS v3.0.24
+**JavaScript-only version** - No Rust/Oxide dependencies required.
+
@@ -18,20 +16,257 @@ A utility-first CSS framework for rapidly building custom user interfaces.
------
-## Documentation
+## About This Fork
+
+**Version:** 3.4.0 (JavaScript-only fork)
+
+This is a JavaScript-only fork of Tailwind CSS, originally based on version 3.0.24 - the last version before the Rust/Oxide engine was introduced. This fork maintains the pure JavaScript/TypeScript architecture without requiring Rust toolchain dependencies.
+
+**Note:** Tailwind CSS v4 is a complete rewrite in Rust with the Oxide engine. This fork focuses on the JavaScript implementation with modern v3.x features.
+
+### What's New in v3.4.0
+
+This version includes modern CSS features from Tailwind CSS v3.4, adapted for the JavaScript-only architecture:
+
+**Modern Viewport Units:**
+- `h-dvh`, `h-svh`, `h-lvh` - Dynamic/Small/Large viewport height units
+- `w-dvw`, `w-svw`, `w-lvw` - Dynamic/Small/Large viewport width units
+- Better mobile browser support with viewport units that account for dynamic UI (URL bars, etc.)
+
+**Size Utilities:**
+- `size-*` - Combined width and height utilities (e.g., `size-4` sets both `width: 1rem` and `height: 1rem`)
+- Supports all spacing values, fractions (`size-1/2`), and arbitrary values (`size-[200px]`)
+
+**:has() Pseudo-Class Variant:**
+- `has-[selector]:utility` - Style parents based on descendants
+- Examples: `has-[:checked]:bg-blue-500`, `has-[>a]:underline`, `has-[img]:p-4`
+- Modern contextual styling for parent elements
+
+**Text Wrapping:**
+- `text-balance` - Balance text across lines for better headlines
+- `text-pretty` - Better text wrapping avoiding orphans and widows
+- `text-wrap` / `text-nowrap` - Standard wrapping controls
+
+**CSS Subgrid:**
+- `grid-cols-subgrid` - Inherit parent grid columns
+- `grid-rows-subgrid` - Inherit parent grid rows
+
+**Accessibility:**
+- `forced-colors:` variant - Style for Windows High Contrast Mode
+
+**Example Usage:**
+```html
+
+
Full dynamic viewport height
+
Minimum small viewport height
+
+
+
Square 16x16
+
Full width and height
+
+
+
+ Checked parent changes
+
+
+
+
Balanced headline text
+
Pretty wrapped paragraph
+
+
+
+
+
+
High contrast border
+```
+
+### Version History
+
+This fork incrementally migrates features from Tailwind CSS releases while maintaining JavaScript-only architecture:
+
+- **v3.0.24** - ✅ **BASE** - Original JavaScript-only fork
+- **v3.1.0** - ✅ **DONE** - Arbitrary variants, new utilities, new variants
+- **v3.2.0** - ✅ **DONE** - ARIA/data variants, @supports, min/max queries, baseline alignment
+- **v3.3.0** - ✅ **DONE** - Extended colors (950 shades), line-clamp, logical properties
+- **v3.4.0** - ✅ **DONE** - Viewport units, size utilities, :has(), text-wrap, subgrid
+
+All versions are preserved in `lib/VERSION/` directories and available as tarballs in `dist/VERSION/`.
+
+See `CHANGELOG.md` for detailed release notes.
+
+### Installation and Building
+
+```bash
+# Install dependencies
+npm install
+
+# Build with version-specific folders
+npm run build
+
+# Create version-specific tarball
+npm run pack
+
+# Build and package together
+npm run build:pack
+
+# Legacy build (outputs to lib/ without versioning)
+npm run swcify
+```
+
+#### Version-Specific Build System
+
+This fork uses a version-specific build system that allows multiple versions to coexist:
+
+**Build Output:**
+- `lib/VERSION/` - Compiled code for each version (e.g., `lib/3.0.24/`)
+- `lib/*.js` - Symlinks to the latest version for backwards compatibility
+- `dist/VERSION/` - Packaged tarballs (e.g., `dist/3.0.24/tailwindcss-3.0.24.tgz`)
+- `dist/*.tgz` - Latest tarball copy at root for convenience
+
+**Benefits:**
+- Work on multiple versions simultaneously
+- Preserve old version artifacts when building new versions
+- Install specific versions from versioned tarballs
+- Backwards compatible with existing tooling via symlinks
+
+### Using in Your Project
+
+You can install this JavaScript-only fork directly from the pre-built tarballs in the `dist/` folder.
+
+#### Quick Start
+
+**1. Install from Tarball**
+
+```bash
+# Create a new project
+mkdir my-website
+cd my-website
+npm init -y
+
+# Install Tailwind CSS v3.4.0 from tarball
+# Option A: Clone this repo and install locally
+git clone https://github.com/YOUR_USERNAME/tailwindcss.git
+npm install ./tailwindcss/dist/3.4.0/tailwindcss-3.4.0.tgz
+
+**2. Create Tailwind Config**
+
+```bash
+npx tailwindcss init
+```
+
+This creates a `tailwind.config.js` file:
+
+```js
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ["./*.html", "./src/**/*.{html,js}"],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
+```
+
+**3. Create Your CSS File**
+
+Create `src/input.css`:
+
+```css
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+```
+
+**4. Build Your CSS**
+
+```bash
+# One-time build
+npx tailwindcss -i ./src/input.css -o ./dist/output.css
+
+# Watch mode for development
+npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch
+
+# Minified for production
+npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify
+```
+
+**5. Use in Your HTML**
+
+Create `index.html`:
+
+```html
+
+
+
+
+
+
My Tailwind Site
+
+
+
+
+
+ Hello Tailwind CSS v3.1!
+
+
+
+
+ Arbitrary variant example
+
+
+
+ Border spacing utility
+
+
+
+ New enabled variant
+
+
+
+
+```
+
+**6. Add Build Scripts to package.json**
+
+```json
+{
+ "scripts": {
+ "dev": "tailwindcss -i ./src/input.css -o ./dist/output.css --watch",
+ "build": "tailwindcss -i ./src/input.css -o ./dist/output.css --minify"
+ }
+}
+```
+
+Then run:
+```bash
+npm run dev # Development with watch mode
+npm run build # Production build
+```
+
+#### Advanced Configuration
-For full documentation, visit [tailwindcss.com](https://tailwindcss.com/).
+**Using with PostCSS:**
-## Community
+```bash
+npm install -D postcss postcss-cli autoprefixer
+```
-For help, discussion about best practices, or any other conversation that would benefit from being searchable:
+Create `postcss.config.js`:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+```js
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ }
+}
+```
-For casual chit-chat with others using the framework:
+### Simple method to use prebult tgz in your nodejs web site
-[Join the Tailwind CSS Discord Server](https://discord.gg/7NF8GNe)
+ See the file INSTALLING_CUSTOM_TAILWINDCSS_LOCALLY.md
-## Contributing
+## Contributing to Tailwind , Not Me
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md) **before submitting a pull request**.
diff --git a/crates/node/.turbo/turbo-build.log b/crates/node/.turbo/turbo-build.log
new file mode 100644
index 000000000000..c0bb8da470c4
--- /dev/null
+++ b/crates/node/.turbo/turbo-build.log
@@ -0,0 +1,37 @@
+
+
+> @tailwindcss/oxide@4.1.18 build /home/ktaylor/Projects/tailwindcss/crates/node
+> pnpm run build:platform && pnpm run build:wasm
+
+
+> @tailwindcss/oxide@4.1.18 build:platform /home/ktaylor/Projects/tailwindcss/crates/node
+> napi build --platform --release
+
+node:events:497
+ throw er; // Unhandled 'error' event
+ ^
+
+Error: spawn cargo ENOENT
+[90m at ChildProcess._handle.onexit (node:internal/child_process:285:19)[39m
+[90m at onErrorNT (node:internal/child_process:483:16)[39m
+[90m at process.processTicksAndRejections (node:internal/process/task_queues:90:21)[39m
+Emitted 'error' event on ChildProcess instance at:
+[90m at ChildProcess._handle.onexit (node:internal/child_process:291:12)[39m
+[90m at onErrorNT (node:internal/child_process:483:16)[39m
+[90m at process.processTicksAndRejections (node:internal/process/task_queues:90:21)[39m {
+ errno: [33m-2[39m,
+ code: [32m'ENOENT'[39m,
+ syscall: [32m'spawn cargo'[39m,
+ path: [32m'cargo'[39m,
+ spawnargs: [
+ [32m'metadata'[39m,
+ [32m'--manifest-path'[39m,
+ [32m'/home/ktaylor/Projects/tailwindcss/crates/node/Cargo.toml'[39m,
+ [32m'--format-version'[39m,
+ [32m'1'[39m
+ ]
+}
+
+Node.js v22.21.0
+[41m[30m ELIFECYCLE [39m[49m [31mCommand failed with exit code 1.[39m
+[41m[30m ELIFECYCLE [39m[49m [31mCommand failed with exit code 1.[39m
diff --git a/crates/node/node_modules/.bin/napi b/crates/node/node_modules/.bin/napi
new file mode 100755
index 000000000000..596f49b8dbf5
--- /dev/null
+++ b/crates/node/node_modules/.bin/napi
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/cli/dist/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/cli/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/cli/dist/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/cli/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../@napi-rs/cli/dist/cli.js" "$@"
+else
+ exec node "$basedir/../@napi-rs/cli/dist/cli.js" "$@"
+fi
diff --git a/crates/node/node_modules/.bin/napi-raw b/crates/node/node_modules/.bin/napi-raw
new file mode 100755
index 000000000000..0e26c5a5f8cc
--- /dev/null
+++ b/crates/node/node_modules/.bin/napi-raw
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/cli/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/cli/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../@napi-rs/cli/cli.mjs" "$@"
+else
+ exec node "$basedir/../@napi-rs/cli/cli.mjs" "$@"
+fi
diff --git a/crates/node/node_modules/@napi-rs/cli b/crates/node/node_modules/@napi-rs/cli
new file mode 120000
index 000000000000..7a19bb9838ed
--- /dev/null
+++ b/crates/node/node_modules/@napi-rs/cli
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@napi-rs+cli@3.4.1_@emnapi+runtime@1.7.1_@types+node@20.19.1_node-addon-api@8.3.0/node_modules/@napi-rs/cli
\ No newline at end of file
diff --git a/crates/node/node_modules/@napi-rs/wasm-runtime b/crates/node/node_modules/@napi-rs/wasm-runtime
new file mode 120000
index 000000000000..f8a977515280
--- /dev/null
+++ b/crates/node/node_modules/@napi-rs/wasm-runtime
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@napi-rs+wasm-runtime@1.1.1/node_modules/@napi-rs/wasm-runtime
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-android-arm64 b/crates/node/node_modules/@tailwindcss/oxide-android-arm64
new file mode 120000
index 000000000000..e99784d04eb1
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-android-arm64
@@ -0,0 +1 @@
+../../npm/android-arm64
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-darwin-arm64 b/crates/node/node_modules/@tailwindcss/oxide-darwin-arm64
new file mode 120000
index 000000000000..7b716d6ec9d4
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-darwin-arm64
@@ -0,0 +1 @@
+../../npm/darwin-arm64
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-darwin-x64 b/crates/node/node_modules/@tailwindcss/oxide-darwin-x64
new file mode 120000
index 000000000000..dcf0e3ed29b6
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-darwin-x64
@@ -0,0 +1 @@
+../../npm/darwin-x64
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-freebsd-x64 b/crates/node/node_modules/@tailwindcss/oxide-freebsd-x64
new file mode 120000
index 000000000000..a104c64fb512
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-freebsd-x64
@@ -0,0 +1 @@
+../../npm/freebsd-x64
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-linux-arm-gnueabihf b/crates/node/node_modules/@tailwindcss/oxide-linux-arm-gnueabihf
new file mode 120000
index 000000000000..d5a1e1e4d486
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-linux-arm-gnueabihf
@@ -0,0 +1 @@
+../../npm/linux-arm-gnueabihf
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-linux-arm64-gnu b/crates/node/node_modules/@tailwindcss/oxide-linux-arm64-gnu
new file mode 120000
index 000000000000..907267ddd492
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-linux-arm64-gnu
@@ -0,0 +1 @@
+../../npm/linux-arm64-gnu
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-linux-arm64-musl b/crates/node/node_modules/@tailwindcss/oxide-linux-arm64-musl
new file mode 120000
index 000000000000..f66cd312e4d3
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-linux-arm64-musl
@@ -0,0 +1 @@
+../../npm/linux-arm64-musl
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-linux-x64-gnu b/crates/node/node_modules/@tailwindcss/oxide-linux-x64-gnu
new file mode 120000
index 000000000000..e333a6f436d2
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-linux-x64-gnu
@@ -0,0 +1 @@
+../../npm/linux-x64-gnu
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-linux-x64-musl b/crates/node/node_modules/@tailwindcss/oxide-linux-x64-musl
new file mode 120000
index 000000000000..a913c73a9bb9
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-linux-x64-musl
@@ -0,0 +1 @@
+../../npm/linux-x64-musl
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-wasm32-wasi b/crates/node/node_modules/@tailwindcss/oxide-wasm32-wasi
new file mode 120000
index 000000000000..fad41a576cc2
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-wasm32-wasi
@@ -0,0 +1 @@
+../../npm/wasm32-wasi
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-win32-arm64-msvc b/crates/node/node_modules/@tailwindcss/oxide-win32-arm64-msvc
new file mode 120000
index 000000000000..a1205b6626de
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-win32-arm64-msvc
@@ -0,0 +1 @@
+../../npm/win32-arm64-msvc
\ No newline at end of file
diff --git a/crates/node/node_modules/@tailwindcss/oxide-win32-x64-msvc b/crates/node/node_modules/@tailwindcss/oxide-win32-x64-msvc
new file mode 120000
index 000000000000..459940909a98
--- /dev/null
+++ b/crates/node/node_modules/@tailwindcss/oxide-win32-x64-msvc
@@ -0,0 +1 @@
+../../npm/win32-x64-msvc
\ No newline at end of file
diff --git a/crates/node/node_modules/emnapi b/crates/node/node_modules/emnapi
new file mode 120000
index 000000000000..a6df13c2befe
--- /dev/null
+++ b/crates/node/node_modules/emnapi
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/emnapi@1.7.1_node-addon-api@8.3.0/node_modules/emnapi
\ No newline at end of file
diff --git a/crates/node/npm/wasm32-wasi/node_modules/@emnapi/core b/crates/node/npm/wasm32-wasi/node_modules/@emnapi/core
new file mode 120000
index 000000000000..18747b39d675
--- /dev/null
+++ b/crates/node/npm/wasm32-wasi/node_modules/@emnapi/core
@@ -0,0 +1 @@
+../../../../../../node_modules/.pnpm/@emnapi+core@1.7.1/node_modules/@emnapi/core
\ No newline at end of file
diff --git a/crates/node/npm/wasm32-wasi/node_modules/@emnapi/runtime b/crates/node/npm/wasm32-wasi/node_modules/@emnapi/runtime
new file mode 120000
index 000000000000..525ec571968b
--- /dev/null
+++ b/crates/node/npm/wasm32-wasi/node_modules/@emnapi/runtime
@@ -0,0 +1 @@
+../../../../../../node_modules/.pnpm/@emnapi+runtime@1.7.1/node_modules/@emnapi/runtime
\ No newline at end of file
diff --git a/crates/node/npm/wasm32-wasi/node_modules/@emnapi/wasi-threads b/crates/node/npm/wasm32-wasi/node_modules/@emnapi/wasi-threads
new file mode 120000
index 000000000000..44d77cebeb01
--- /dev/null
+++ b/crates/node/npm/wasm32-wasi/node_modules/@emnapi/wasi-threads
@@ -0,0 +1 @@
+../../../../../../node_modules/.pnpm/@emnapi+wasi-threads@1.1.0/node_modules/@emnapi/wasi-threads
\ No newline at end of file
diff --git a/crates/node/npm/wasm32-wasi/node_modules/@napi-rs/wasm-runtime b/crates/node/npm/wasm32-wasi/node_modules/@napi-rs/wasm-runtime
new file mode 120000
index 000000000000..4e55d7ac1610
--- /dev/null
+++ b/crates/node/npm/wasm32-wasi/node_modules/@napi-rs/wasm-runtime
@@ -0,0 +1 @@
+../../../../../../node_modules/.pnpm/@napi-rs+wasm-runtime@1.1.1/node_modules/@napi-rs/wasm-runtime
\ No newline at end of file
diff --git a/crates/node/npm/wasm32-wasi/node_modules/@tybys/wasm-util b/crates/node/npm/wasm32-wasi/node_modules/@tybys/wasm-util
new file mode 120000
index 000000000000..3dc061d66f70
--- /dev/null
+++ b/crates/node/npm/wasm32-wasi/node_modules/@tybys/wasm-util
@@ -0,0 +1 @@
+../../../../../../node_modules/.pnpm/@tybys+wasm-util@0.10.1/node_modules/@tybys/wasm-util
\ No newline at end of file
diff --git a/crates/node/npm/wasm32-wasi/node_modules/tslib b/crates/node/npm/wasm32-wasi/node_modules/tslib
new file mode 120000
index 000000000000..e011db0c2d8c
--- /dev/null
+++ b/crates/node/npm/wasm32-wasi/node_modules/tslib
@@ -0,0 +1 @@
+../../../../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib
\ No newline at end of file
diff --git a/dist/3.0.24/tailwindcss-3.0.24.tgz b/dist/3.0.24/tailwindcss-3.0.24.tgz
new file mode 100644
index 000000000000..51f578928a46
Binary files /dev/null and b/dist/3.0.24/tailwindcss-3.0.24.tgz differ
diff --git a/dist/3.1.0/tailwindcss-3.1.0.tgz b/dist/3.1.0/tailwindcss-3.1.0.tgz
new file mode 100644
index 000000000000..ed0a33a6456c
Binary files /dev/null and b/dist/3.1.0/tailwindcss-3.1.0.tgz differ
diff --git a/dist/3.2.0/tailwindcss-3.2.0.tgz b/dist/3.2.0/tailwindcss-3.2.0.tgz
new file mode 100644
index 000000000000..0c6b7ea6619c
Binary files /dev/null and b/dist/3.2.0/tailwindcss-3.2.0.tgz differ
diff --git a/dist/3.3.0/tailwindcss-3.3.0.tgz b/dist/3.3.0/tailwindcss-3.3.0.tgz
new file mode 100644
index 000000000000..676894685937
Binary files /dev/null and b/dist/3.3.0/tailwindcss-3.3.0.tgz differ
diff --git a/dist/3.4.0/tailwindcss-3.4.0.tgz b/dist/3.4.0/tailwindcss-3.4.0.tgz
new file mode 100644
index 000000000000..bf95a2487551
Binary files /dev/null and b/dist/3.4.0/tailwindcss-3.4.0.tgz differ
diff --git a/dist/tailwindcss-3.0.24.tgz b/dist/tailwindcss-3.0.24.tgz
new file mode 100644
index 000000000000..51f578928a46
Binary files /dev/null and b/dist/tailwindcss-3.0.24.tgz differ
diff --git a/dist/tailwindcss-3.1.0.tgz b/dist/tailwindcss-3.1.0.tgz
new file mode 100644
index 000000000000..ed0a33a6456c
Binary files /dev/null and b/dist/tailwindcss-3.1.0.tgz differ
diff --git a/dist/tailwindcss-3.2.0.tgz b/dist/tailwindcss-3.2.0.tgz
new file mode 100644
index 000000000000..0c6b7ea6619c
Binary files /dev/null and b/dist/tailwindcss-3.2.0.tgz differ
diff --git a/dist/tailwindcss-3.3.0.tgz b/dist/tailwindcss-3.3.0.tgz
new file mode 100644
index 000000000000..676894685937
Binary files /dev/null and b/dist/tailwindcss-3.3.0.tgz differ
diff --git a/dist/tailwindcss-3.4.0.tgz b/dist/tailwindcss-3.4.0.tgz
new file mode 100644
index 000000000000..bf95a2487551
Binary files /dev/null and b/dist/tailwindcss-3.4.0.tgz differ
diff --git a/package.json b/package.json
index 2e35a65bce02..f1ad44b60055 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "tailwindcss",
- "version": "3.0.24",
- "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
+ "version": "3.4.0",
+ "description": "A utility-first CSS framework for rapidly building custom user interfaces. (JavaScript-only v3.x fork)",
"license": "MIT",
"main": "lib/index.js",
"repository": "https://github.com/tailwindlabs/tailwindcss.git",
@@ -12,11 +12,14 @@
"tailwindcss": "lib/cli.js"
},
"scripts": {
+ "build": "node scripts/build-versioned.js",
+ "pack": "node scripts/pack-versioned.js",
+ "build:pack": "npm run build && npm run pack",
"preswcify": "npm run generate && rimraf lib",
"swcify": "swc src --out-dir lib --copy-files",
"postswcify": "esbuild lib/cli-peer-dependencies.js --bundle --platform=node --outfile=peers/index.js",
"rebuild-fixtures": "npm run swcify && node -r @swc/register scripts/rebuildFixtures.js",
- "prepublishOnly": "npm install --force && npm run swcify",
+ "prepublishOnly": "npm install --force && npm run build",
"style": "eslint .",
"pretest": "npm run generate",
"test": "jest",
@@ -30,7 +33,7 @@
"files": [
"src/*",
"cli/*",
- "lib/*",
+ "lib/**/*",
"peers/*",
"scripts/*.js",
"stubs/*.stub.js",
diff --git a/packages/@tailwindcss-browser/node_modules/.bin/listen b/packages/@tailwindcss-browser/node_modules/.bin/listen
new file mode 100755
index 000000000000..31ae336f810c
--- /dev/null
+++ b/packages/@tailwindcss-browser/node_modules/.bin/listen
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../listhen/bin/listhen.mjs" "$@"
+else
+ exec node "$basedir/../listhen/bin/listhen.mjs" "$@"
+fi
diff --git a/packages/@tailwindcss-browser/node_modules/.bin/listhen b/packages/@tailwindcss-browser/node_modules/.bin/listhen
new file mode 100755
index 000000000000..31ae336f810c
--- /dev/null
+++ b/packages/@tailwindcss-browser/node_modules/.bin/listhen
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/listhen@1.9.0/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../listhen/bin/listhen.mjs" "$@"
+else
+ exec node "$basedir/../listhen/bin/listhen.mjs" "$@"
+fi
diff --git a/packages/@tailwindcss-browser/node_modules/h3 b/packages/@tailwindcss-browser/node_modules/h3
new file mode 120000
index 000000000000..70572c21c421
--- /dev/null
+++ b/packages/@tailwindcss-browser/node_modules/h3
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/h3@1.15.4/node_modules/h3
\ No newline at end of file
diff --git a/packages/@tailwindcss-browser/node_modules/listhen b/packages/@tailwindcss-browser/node_modules/listhen
new file mode 120000
index 000000000000..d4727d87997a
--- /dev/null
+++ b/packages/@tailwindcss-browser/node_modules/listhen
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/listhen@1.9.0/node_modules/listhen
\ No newline at end of file
diff --git a/packages/@tailwindcss-browser/node_modules/tailwindcss b/packages/@tailwindcss-browser/node_modules/tailwindcss
new file mode 120000
index 000000000000..2a8d9bcfa1f8
--- /dev/null
+++ b/packages/@tailwindcss-browser/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../tailwindcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-cli/node_modules/@parcel/watcher b/packages/@tailwindcss-cli/node_modules/@parcel/watcher
new file mode 120000
index 000000000000..c8306156b7bd
--- /dev/null
+++ b/packages/@tailwindcss-cli/node_modules/@parcel/watcher
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@parcel+watcher@2.5.1_patch_hash=zs2vvlrje3h42xp5ed2v44fep4/node_modules/@parcel/watcher
\ No newline at end of file
diff --git a/packages/@tailwindcss-cli/node_modules/@tailwindcss/node b/packages/@tailwindcss-cli/node_modules/@tailwindcss/node
new file mode 120000
index 000000000000..e2b30f3393f6
--- /dev/null
+++ b/packages/@tailwindcss-cli/node_modules/@tailwindcss/node
@@ -0,0 +1 @@
+../../../@tailwindcss-node
\ No newline at end of file
diff --git a/packages/@tailwindcss-cli/node_modules/@tailwindcss/oxide b/packages/@tailwindcss-cli/node_modules/@tailwindcss/oxide
new file mode 120000
index 000000000000..271d98bbb754
--- /dev/null
+++ b/packages/@tailwindcss-cli/node_modules/@tailwindcss/oxide
@@ -0,0 +1 @@
+../../../../crates/node
\ No newline at end of file
diff --git a/packages/@tailwindcss-cli/node_modules/enhanced-resolve b/packages/@tailwindcss-cli/node_modules/enhanced-resolve
new file mode 120000
index 000000000000..6c52962108b3
--- /dev/null
+++ b/packages/@tailwindcss-cli/node_modules/enhanced-resolve
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/enhanced-resolve@5.18.4/node_modules/enhanced-resolve
\ No newline at end of file
diff --git a/packages/@tailwindcss-cli/node_modules/mri b/packages/@tailwindcss-cli/node_modules/mri
new file mode 120000
index 000000000000..0c3daa859ec7
--- /dev/null
+++ b/packages/@tailwindcss-cli/node_modules/mri
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/mri@1.2.0/node_modules/mri
\ No newline at end of file
diff --git a/packages/@tailwindcss-cli/node_modules/picocolors b/packages/@tailwindcss-cli/node_modules/picocolors
new file mode 120000
index 000000000000..d3825c765ec2
--- /dev/null
+++ b/packages/@tailwindcss-cli/node_modules/picocolors
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors
\ No newline at end of file
diff --git a/packages/@tailwindcss-cli/node_modules/tailwindcss b/packages/@tailwindcss-cli/node_modules/tailwindcss
new file mode 120000
index 000000000000..2a8d9bcfa1f8
--- /dev/null
+++ b/packages/@tailwindcss-cli/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../tailwindcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-node/node_modules/.bin/jiti b/packages/@tailwindcss-node/node_modules/.bin/jiti
new file mode 100755
index 000000000000..5d197b8d34df
--- /dev/null
+++ b/packages/@tailwindcss-node/node_modules/.bin/jiti
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../jiti/lib/jiti-cli.mjs" "$@"
+else
+ exec node "$basedir/../jiti/lib/jiti-cli.mjs" "$@"
+fi
diff --git a/packages/@tailwindcss-node/node_modules/@jridgewell/remapping b/packages/@tailwindcss-node/node_modules/@jridgewell/remapping
new file mode 120000
index 000000000000..e0821158f3bb
--- /dev/null
+++ b/packages/@tailwindcss-node/node_modules/@jridgewell/remapping
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@jridgewell+remapping@2.3.5/node_modules/@jridgewell/remapping
\ No newline at end of file
diff --git a/packages/@tailwindcss-node/node_modules/enhanced-resolve b/packages/@tailwindcss-node/node_modules/enhanced-resolve
new file mode 120000
index 000000000000..6c52962108b3
--- /dev/null
+++ b/packages/@tailwindcss-node/node_modules/enhanced-resolve
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/enhanced-resolve@5.18.4/node_modules/enhanced-resolve
\ No newline at end of file
diff --git a/packages/@tailwindcss-node/node_modules/jiti b/packages/@tailwindcss-node/node_modules/jiti
new file mode 120000
index 000000000000..6f442364344d
--- /dev/null
+++ b/packages/@tailwindcss-node/node_modules/jiti
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/jiti@2.6.1/node_modules/jiti
\ No newline at end of file
diff --git a/packages/@tailwindcss-node/node_modules/lightningcss b/packages/@tailwindcss-node/node_modules/lightningcss
new file mode 120000
index 000000000000..8a050f8099ba
--- /dev/null
+++ b/packages/@tailwindcss-node/node_modules/lightningcss
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihrooumyi5fm/node_modules/lightningcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-node/node_modules/magic-string b/packages/@tailwindcss-node/node_modules/magic-string
new file mode 120000
index 000000000000..257020126104
--- /dev/null
+++ b/packages/@tailwindcss-node/node_modules/magic-string
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string
\ No newline at end of file
diff --git a/packages/@tailwindcss-node/node_modules/source-map-js b/packages/@tailwindcss-node/node_modules/source-map-js
new file mode 120000
index 000000000000..b621b85ee992
--- /dev/null
+++ b/packages/@tailwindcss-node/node_modules/source-map-js
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/source-map-js@1.2.1/node_modules/source-map-js
\ No newline at end of file
diff --git a/packages/@tailwindcss-node/node_modules/tailwindcss b/packages/@tailwindcss-node/node_modules/tailwindcss
new file mode 120000
index 000000000000..2a8d9bcfa1f8
--- /dev/null
+++ b/packages/@tailwindcss-node/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../tailwindcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/@alloc/quick-lru b/packages/@tailwindcss-postcss/node_modules/@alloc/quick-lru
new file mode 120000
index 000000000000..e2a31623b9d0
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/@alloc/quick-lru
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@alloc+quick-lru@5.2.0/node_modules/@alloc/quick-lru
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/@tailwindcss/node b/packages/@tailwindcss-postcss/node_modules/@tailwindcss/node
new file mode 120000
index 000000000000..e2b30f3393f6
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/@tailwindcss/node
@@ -0,0 +1 @@
+../../../@tailwindcss-node
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/@tailwindcss/oxide b/packages/@tailwindcss-postcss/node_modules/@tailwindcss/oxide
new file mode 120000
index 000000000000..271d98bbb754
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/@tailwindcss/oxide
@@ -0,0 +1 @@
+../../../../crates/node
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/@types/node b/packages/@tailwindcss-postcss/node_modules/@types/node
new file mode 120000
index 000000000000..724e28768eb0
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/@types/node
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+node@20.19.1/node_modules/@types/node
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/@types/postcss-import b/packages/@tailwindcss-postcss/node_modules/@types/postcss-import
new file mode 120000
index 000000000000..0cf63a98cfa3
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/@types/postcss-import
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+postcss-import@14.0.3/node_modules/@types/postcss-import
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/dedent b/packages/@tailwindcss-postcss/node_modules/dedent
new file mode 120000
index 000000000000..ef95e91b113c
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/dedent
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/dedent@1.7.1/node_modules/dedent
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/internal-example-plugin b/packages/@tailwindcss-postcss/node_modules/internal-example-plugin
new file mode 120000
index 000000000000..ff96a0212510
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/internal-example-plugin
@@ -0,0 +1 @@
+../../internal-example-plugin
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/postcss b/packages/@tailwindcss-postcss/node_modules/postcss
new file mode 120000
index 000000000000..5144775e7fb6
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/postcss
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/postcss@8.4.41/node_modules/postcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/postcss-import b/packages/@tailwindcss-postcss/node_modules/postcss-import
new file mode 120000
index 000000000000..d663ef89b098
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/postcss-import
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/postcss-import@16.1.1_postcss@8.4.41/node_modules/postcss-import
\ No newline at end of file
diff --git a/packages/@tailwindcss-postcss/node_modules/tailwindcss b/packages/@tailwindcss-postcss/node_modules/tailwindcss
new file mode 120000
index 000000000000..2a8d9bcfa1f8
--- /dev/null
+++ b/packages/@tailwindcss-postcss/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../tailwindcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/.bin/bun b/packages/@tailwindcss-standalone/node_modules/.bin/bun
new file mode 100755
index 000000000000..0f5fa74b3146
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/.bin/bun
@@ -0,0 +1,14 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+"$basedir/../bun/bin/bun.exe" "$@"
+exit $?
diff --git a/packages/@tailwindcss-standalone/node_modules/.bin/bunx b/packages/@tailwindcss-standalone/node_modules/.bin/bunx
new file mode 100755
index 000000000000..8896c8000de3
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/.bin/bunx
@@ -0,0 +1,14 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+"$basedir/../bun/bin/bunx.exe" "$@"
+exit $?
diff --git a/packages/@tailwindcss-standalone/node_modules/.bin/detect-libc b/packages/@tailwindcss-standalone/node_modules/.bin/detect-libc
new file mode 100755
index 000000000000..8cece26eec84
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/.bin/detect-libc
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/detect-libc@1.0.3/node_modules/detect-libc/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/detect-libc@1.0.3/node_modules/detect-libc/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/detect-libc@1.0.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/detect-libc@1.0.3/node_modules/detect-libc/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/detect-libc@1.0.3/node_modules/detect-libc/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/detect-libc@1.0.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../detect-libc/bin/detect-libc.js" "$@"
+else
+ exec node "$basedir/../detect-libc/bin/detect-libc.js" "$@"
+fi
diff --git a/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-darwin-arm64 b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-darwin-arm64
new file mode 120000
index 000000000000..80c9aa3bbc11
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-darwin-arm64
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@parcel+watcher-darwin-arm64@2.5.1/node_modules/@parcel/watcher-darwin-arm64
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-darwin-x64 b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-darwin-x64
new file mode 120000
index 000000000000..8adc5a582a4e
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-darwin-x64
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@parcel+watcher-darwin-x64@2.5.1/node_modules/@parcel/watcher-darwin-x64
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-arm64-glibc b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-arm64-glibc
new file mode 120000
index 000000000000..edb65123e59e
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-arm64-glibc
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@parcel+watcher-linux-arm64-glibc@2.5.1/node_modules/@parcel/watcher-linux-arm64-glibc
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-arm64-musl b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-arm64-musl
new file mode 120000
index 000000000000..12e8bd541ff1
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-arm64-musl
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@parcel+watcher-linux-arm64-musl@2.5.1/node_modules/@parcel/watcher-linux-arm64-musl
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-x64-glibc b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-x64-glibc
new file mode 120000
index 000000000000..cf39c4f43f9f
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-x64-glibc
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@parcel+watcher-linux-x64-glibc@2.5.1/node_modules/@parcel/watcher-linux-x64-glibc
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-x64-musl b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-x64-musl
new file mode 120000
index 000000000000..01a51e8a403a
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-linux-x64-musl
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@parcel+watcher-linux-x64-musl@2.5.1/node_modules/@parcel/watcher-linux-x64-musl
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-win32-x64 b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-win32-x64
new file mode 120000
index 000000000000..661c923a3b3c
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@parcel/watcher-win32-x64
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@parcel+watcher-win32-x64@2.5.1/node_modules/@parcel/watcher-win32-x64
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@tailwindcss/aspect-ratio b/packages/@tailwindcss-standalone/node_modules/@tailwindcss/aspect-ratio
new file mode 120000
index 000000000000..6d52e506611d
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@tailwindcss/aspect-ratio
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@tailwindcss+aspect-ratio@0.4.2_tailwindcss@packages+tailwindcss/node_modules/@tailwindcss/aspect-ratio
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@tailwindcss/cli b/packages/@tailwindcss-standalone/node_modules/@tailwindcss/cli
new file mode 120000
index 000000000000..e229d9d4aaaa
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@tailwindcss/cli
@@ -0,0 +1 @@
+../../../@tailwindcss-cli
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@tailwindcss/forms b/packages/@tailwindcss-standalone/node_modules/@tailwindcss/forms
new file mode 120000
index 000000000000..cc7912aba204
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@tailwindcss/forms
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@tailwindcss+forms@0.5.11_tailwindcss@packages+tailwindcss/node_modules/@tailwindcss/forms
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@tailwindcss/typography b/packages/@tailwindcss-standalone/node_modules/@tailwindcss/typography
new file mode 120000
index 000000000000..749fd2a5eb03
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@tailwindcss/typography
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@tailwindcss+typography@0.5.19_tailwindcss@packages+tailwindcss/node_modules/@tailwindcss/typography
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/@types/bun b/packages/@tailwindcss-standalone/node_modules/@types/bun
new file mode 120000
index 000000000000..42c30fcabba4
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/@types/bun
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+bun@1.3.5/node_modules/@types/bun
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/bun b/packages/@tailwindcss-standalone/node_modules/bun
new file mode 120000
index 000000000000..7f0483f32075
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/bun
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/bun@1.3.5/node_modules/bun
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/detect-libc b/packages/@tailwindcss-standalone/node_modules/detect-libc
new file mode 120000
index 000000000000..e6531d69bcef
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/detect-libc
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/detect-libc@1.0.3/node_modules/detect-libc
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/enhanced-resolve b/packages/@tailwindcss-standalone/node_modules/enhanced-resolve
new file mode 120000
index 000000000000..6c52962108b3
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/enhanced-resolve
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/enhanced-resolve@5.18.4/node_modules/enhanced-resolve
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/lightningcss-darwin-arm64 b/packages/@tailwindcss-standalone/node_modules/lightningcss-darwin-arm64
new file mode 120000
index 000000000000..65ceb1799900
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/lightningcss-darwin-arm64
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss-darwin-arm64@1.30.2/node_modules/lightningcss-darwin-arm64
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/lightningcss-darwin-x64 b/packages/@tailwindcss-standalone/node_modules/lightningcss-darwin-x64
new file mode 120000
index 000000000000..b344085c0506
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/lightningcss-darwin-x64
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss-darwin-x64@1.30.2/node_modules/lightningcss-darwin-x64
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-arm64-gnu b/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-arm64-gnu
new file mode 120000
index 000000000000..39aaa167bc74
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-arm64-gnu
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss-linux-arm64-gnu@1.30.2/node_modules/lightningcss-linux-arm64-gnu
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-arm64-musl b/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-arm64-musl
new file mode 120000
index 000000000000..08aa8e54c5df
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-arm64-musl
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss-linux-arm64-musl@1.30.2/node_modules/lightningcss-linux-arm64-musl
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-x64-gnu b/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-x64-gnu
new file mode 120000
index 000000000000..ed6d295a4b58
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-x64-gnu
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss-linux-x64-gnu@1.30.2/node_modules/lightningcss-linux-x64-gnu
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-x64-musl b/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-x64-musl
new file mode 120000
index 000000000000..1c32b10f8b33
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/lightningcss-linux-x64-musl
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss-linux-x64-musl@1.30.2/node_modules/lightningcss-linux-x64-musl
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/lightningcss-win32-x64-msvc b/packages/@tailwindcss-standalone/node_modules/lightningcss-win32-x64-msvc
new file mode 120000
index 000000000000..3eaf6f9ab508
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/lightningcss-win32-x64-msvc
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss-win32-x64-msvc@1.30.2/node_modules/lightningcss-win32-x64-msvc
\ No newline at end of file
diff --git a/packages/@tailwindcss-standalone/node_modules/tailwindcss b/packages/@tailwindcss-standalone/node_modules/tailwindcss
new file mode 120000
index 000000000000..2a8d9bcfa1f8
--- /dev/null
+++ b/packages/@tailwindcss-standalone/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../tailwindcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/.bin/jiti b/packages/@tailwindcss-upgrade/node_modules/.bin/jiti
new file mode 100755
index 000000000000..5d197b8d34df
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/.bin/jiti
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/lib/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules/jiti/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/jiti@2.6.1/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../jiti/lib/jiti-cli.mjs" "$@"
+else
+ exec node "$basedir/../jiti/lib/jiti-cli.mjs" "$@"
+fi
diff --git a/packages/@tailwindcss-upgrade/node_modules/.bin/prettier b/packages/@tailwindcss-upgrade/node_modules/.bin/prettier
new file mode 100755
index 000000000000..16b34ac2a446
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/.bin/prettier
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/prettier@3.6.2/node_modules/prettier/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/prettier@3.6.2/node_modules/prettier/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/prettier@3.6.2/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/prettier@3.6.2/node_modules/prettier/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/prettier@3.6.2/node_modules/prettier/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/prettier@3.6.2/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../prettier/bin/prettier.cjs" "$@"
+else
+ exec node "$basedir/../prettier/bin/prettier.cjs" "$@"
+fi
diff --git a/packages/@tailwindcss-upgrade/node_modules/.bin/semver b/packages/@tailwindcss-upgrade/node_modules/.bin/semver
new file mode 100755
index 000000000000..2de3f247ae53
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/.bin/semver
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/semver@7.7.3/node_modules/semver/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/semver@7.7.3/node_modules/semver/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/semver@7.7.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/semver@7.7.3/node_modules/semver/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/semver@7.7.3/node_modules/semver/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/semver@7.7.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@"
+else
+ exec node "$basedir/../semver/bin/semver.js" "$@"
+fi
diff --git a/packages/@tailwindcss-upgrade/node_modules/@tailwindcss/node b/packages/@tailwindcss-upgrade/node_modules/@tailwindcss/node
new file mode 120000
index 000000000000..e2b30f3393f6
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/@tailwindcss/node
@@ -0,0 +1 @@
+../../../@tailwindcss-node
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/@tailwindcss/oxide b/packages/@tailwindcss-upgrade/node_modules/@tailwindcss/oxide
new file mode 120000
index 000000000000..271d98bbb754
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/@tailwindcss/oxide
@@ -0,0 +1 @@
+../../../../crates/node
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/@types/braces b/packages/@tailwindcss-upgrade/node_modules/@types/braces
new file mode 120000
index 000000000000..73e63517cf5c
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/@types/braces
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+braces@3.0.5/node_modules/@types/braces
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/@types/node b/packages/@tailwindcss-upgrade/node_modules/@types/node
new file mode 120000
index 000000000000..724e28768eb0
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/@types/node
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+node@20.19.1/node_modules/@types/node
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/@types/postcss-import b/packages/@tailwindcss-upgrade/node_modules/@types/postcss-import
new file mode 120000
index 000000000000..0cf63a98cfa3
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/@types/postcss-import
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+postcss-import@14.0.3/node_modules/@types/postcss-import
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/@types/semver b/packages/@tailwindcss-upgrade/node_modules/@types/semver
new file mode 120000
index 000000000000..c19a4d26f87e
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/@types/semver
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+semver@7.7.1/node_modules/@types/semver
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/braces b/packages/@tailwindcss-upgrade/node_modules/braces
new file mode 120000
index 000000000000..e2ff8f0b8c64
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/braces
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/braces@3.0.3/node_modules/braces
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/dedent b/packages/@tailwindcss-upgrade/node_modules/dedent
new file mode 120000
index 000000000000..ef95e91b113c
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/dedent
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/dedent@1.7.1/node_modules/dedent
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/enhanced-resolve b/packages/@tailwindcss-upgrade/node_modules/enhanced-resolve
new file mode 120000
index 000000000000..6c52962108b3
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/enhanced-resolve
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/enhanced-resolve@5.18.4/node_modules/enhanced-resolve
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/globby b/packages/@tailwindcss-upgrade/node_modules/globby
new file mode 120000
index 000000000000..78377fcb3a37
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/globby
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/globby@15.0.0/node_modules/globby
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/jiti b/packages/@tailwindcss-upgrade/node_modules/jiti
new file mode 120000
index 000000000000..6f442364344d
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/jiti
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/jiti@2.6.1/node_modules/jiti
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/mri b/packages/@tailwindcss-upgrade/node_modules/mri
new file mode 120000
index 000000000000..0c3daa859ec7
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/mri
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/mri@1.2.0/node_modules/mri
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/picocolors b/packages/@tailwindcss-upgrade/node_modules/picocolors
new file mode 120000
index 000000000000..d3825c765ec2
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/picocolors
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/postcss b/packages/@tailwindcss-upgrade/node_modules/postcss
new file mode 120000
index 000000000000..5144775e7fb6
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/postcss
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/postcss@8.4.41/node_modules/postcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/postcss-import b/packages/@tailwindcss-upgrade/node_modules/postcss-import
new file mode 120000
index 000000000000..d663ef89b098
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/postcss-import
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/postcss-import@16.1.1_postcss@8.4.41/node_modules/postcss-import
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/postcss-selector-parser b/packages/@tailwindcss-upgrade/node_modules/postcss-selector-parser
new file mode 120000
index 000000000000..ea47c2b56655
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/postcss-selector-parser
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/postcss-selector-parser@7.1.1/node_modules/postcss-selector-parser
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/prettier b/packages/@tailwindcss-upgrade/node_modules/prettier
new file mode 120000
index 000000000000..8f17339fc39d
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/prettier
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/prettier@3.6.2/node_modules/prettier
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/semver b/packages/@tailwindcss-upgrade/node_modules/semver
new file mode 120000
index 000000000000..629a6098be27
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/semver
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/semver@7.7.3/node_modules/semver
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/tailwindcss b/packages/@tailwindcss-upgrade/node_modules/tailwindcss
new file mode 120000
index 000000000000..2a8d9bcfa1f8
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../tailwindcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/tree-sitter b/packages/@tailwindcss-upgrade/node_modules/tree-sitter
new file mode 120000
index 000000000000..69cc4522b46e
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/tree-sitter
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/tree-sitter@0.22.4/node_modules/tree-sitter
\ No newline at end of file
diff --git a/packages/@tailwindcss-upgrade/node_modules/tree-sitter-typescript b/packages/@tailwindcss-upgrade/node_modules/tree-sitter-typescript
new file mode 120000
index 000000000000..ccac6355168d
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/node_modules/tree-sitter-typescript
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/tree-sitter-typescript@0.23.2_tree-sitter@0.22.4/node_modules/tree-sitter-typescript
\ No newline at end of file
diff --git a/packages/@tailwindcss-vite/node_modules/.bin/vite b/packages/@tailwindcss-vite/node_modules/.bin/vite
new file mode 100755
index 000000000000..f86d1d02e60a
--- /dev/null
+++ b/packages/@tailwindcss-vite/node_modules/.bin/vite
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@"
+else
+ exec node "$basedir/../vite/bin/vite.js" "$@"
+fi
diff --git a/packages/@tailwindcss-vite/node_modules/@tailwindcss/node b/packages/@tailwindcss-vite/node_modules/@tailwindcss/node
new file mode 120000
index 000000000000..e2b30f3393f6
--- /dev/null
+++ b/packages/@tailwindcss-vite/node_modules/@tailwindcss/node
@@ -0,0 +1 @@
+../../../@tailwindcss-node
\ No newline at end of file
diff --git a/packages/@tailwindcss-vite/node_modules/@tailwindcss/oxide b/packages/@tailwindcss-vite/node_modules/@tailwindcss/oxide
new file mode 120000
index 000000000000..271d98bbb754
--- /dev/null
+++ b/packages/@tailwindcss-vite/node_modules/@tailwindcss/oxide
@@ -0,0 +1 @@
+../../../../crates/node
\ No newline at end of file
diff --git a/packages/@tailwindcss-vite/node_modules/@types/node b/packages/@tailwindcss-vite/node_modules/@types/node
new file mode 120000
index 000000000000..724e28768eb0
--- /dev/null
+++ b/packages/@tailwindcss-vite/node_modules/@types/node
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+node@20.19.1/node_modules/@types/node
\ No newline at end of file
diff --git a/packages/@tailwindcss-vite/node_modules/tailwindcss b/packages/@tailwindcss-vite/node_modules/tailwindcss
new file mode 120000
index 000000000000..2a8d9bcfa1f8
--- /dev/null
+++ b/packages/@tailwindcss-vite/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../tailwindcss
\ No newline at end of file
diff --git a/packages/@tailwindcss-vite/node_modules/vite b/packages/@tailwindcss-vite/node_modules/vite
new file mode 120000
index 000000000000..64a91e084ab7
--- /dev/null
+++ b/packages/@tailwindcss-vite/node_modules/vite
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite
\ No newline at end of file
diff --git a/packages/tailwindcss/node_modules/@jridgewell/remapping b/packages/tailwindcss/node_modules/@jridgewell/remapping
new file mode 120000
index 000000000000..e0821158f3bb
--- /dev/null
+++ b/packages/tailwindcss/node_modules/@jridgewell/remapping
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@jridgewell+remapping@2.3.5/node_modules/@jridgewell/remapping
\ No newline at end of file
diff --git a/packages/tailwindcss/node_modules/@tailwindcss/oxide b/packages/tailwindcss/node_modules/@tailwindcss/oxide
new file mode 120000
index 000000000000..271d98bbb754
--- /dev/null
+++ b/packages/tailwindcss/node_modules/@tailwindcss/oxide
@@ -0,0 +1 @@
+../../../../crates/node
\ No newline at end of file
diff --git a/packages/tailwindcss/node_modules/@types/node b/packages/tailwindcss/node_modules/@types/node
new file mode 120000
index 000000000000..724e28768eb0
--- /dev/null
+++ b/packages/tailwindcss/node_modules/@types/node
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+node@20.19.1/node_modules/@types/node
\ No newline at end of file
diff --git a/packages/tailwindcss/node_modules/dedent b/packages/tailwindcss/node_modules/dedent
new file mode 120000
index 000000000000..ef95e91b113c
--- /dev/null
+++ b/packages/tailwindcss/node_modules/dedent
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/dedent@1.7.1/node_modules/dedent
\ No newline at end of file
diff --git a/packages/tailwindcss/node_modules/lightningcss b/packages/tailwindcss/node_modules/lightningcss
new file mode 120000
index 000000000000..8a050f8099ba
--- /dev/null
+++ b/packages/tailwindcss/node_modules/lightningcss
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihrooumyi5fm/node_modules/lightningcss
\ No newline at end of file
diff --git a/packages/tailwindcss/node_modules/magic-string b/packages/tailwindcss/node_modules/magic-string
new file mode 120000
index 000000000000..257020126104
--- /dev/null
+++ b/packages/tailwindcss/node_modules/magic-string
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string
\ No newline at end of file
diff --git a/packages/tailwindcss/node_modules/source-map-js b/packages/tailwindcss/node_modules/source-map-js
new file mode 120000
index 000000000000..b621b85ee992
--- /dev/null
+++ b/packages/tailwindcss/node_modules/source-map-js
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/source-map-js@1.2.1/node_modules/source-map-js
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/.bin/eslint b/playgrounds/nextjs/node_modules/.bin/eslint
new file mode 100755
index 000000000000..d34fa91759b1
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/.bin/eslint
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../eslint/bin/eslint.js" "$@"
+else
+ exec node "$basedir/../eslint/bin/eslint.js" "$@"
+fi
diff --git a/playgrounds/nextjs/node_modules/.bin/next b/playgrounds/nextjs/node_modules/.bin/next
new file mode 100755
index 000000000000..7868c2ceab3f
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/.bin/next
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/dist/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/dist/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/dist/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/dist/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../next/dist/bin/next" "$@"
+else
+ exec node "$basedir/../next/dist/bin/next" "$@"
+fi
diff --git a/playgrounds/nextjs/node_modules/.bin/tsc b/playgrounds/nextjs/node_modules/.bin/tsc
new file mode 100755
index 000000000000..82194462868e
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/.bin/tsc
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
+else
+ exec node "$basedir/../typescript/bin/tsc" "$@"
+fi
diff --git a/playgrounds/nextjs/node_modules/.bin/tsserver b/playgrounds/nextjs/node_modules/.bin/tsserver
new file mode 100755
index 000000000000..a429e2cddb77
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/.bin/tsserver
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.5.4/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
+else
+ exec node "$basedir/../typescript/bin/tsserver" "$@"
+fi
diff --git a/playgrounds/nextjs/node_modules/@tailwindcss/postcss b/playgrounds/nextjs/node_modules/@tailwindcss/postcss
new file mode 120000
index 000000000000..539049bbfeb3
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/@tailwindcss/postcss
@@ -0,0 +1 @@
+../../../../packages/@tailwindcss-postcss
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/@types/node b/playgrounds/nextjs/node_modules/@types/node
new file mode 120000
index 000000000000..724e28768eb0
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/@types/node
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+node@20.19.1/node_modules/@types/node
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/@types/react b/playgrounds/nextjs/node_modules/@types/react
new file mode 120000
index 000000000000..df4499dfb012
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/@types/react
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+react@19.2.7/node_modules/@types/react
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/@types/react-dom b/playgrounds/nextjs/node_modules/@types/react-dom
new file mode 120000
index 000000000000..41e90d09f161
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/@types/react-dom
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.7/node_modules/@types/react-dom
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/eslint b/playgrounds/nextjs/node_modules/eslint
new file mode 120000
index 000000000000..c0c4dc671e2f
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/eslint
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/eslint-config-next b/playgrounds/nextjs/node_modules/eslint-config-next
new file mode 120000
index 000000000000..82feba64d79b
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/eslint-config-next
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/eslint-config-next@16.1.0_@typescript-eslint+parser@8.47.0_eslint@9.39.2_jiti@2.6.1__typescri_lvqrhjrsuxld36sf22xtzfd7la/node_modules/eslint-config-next
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/fast-glob b/playgrounds/nextjs/node_modules/fast-glob
new file mode 120000
index 000000000000..aeeba4e5d86a
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/fast-glob
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/fast-glob@3.3.3/node_modules/fast-glob
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/next b/playgrounds/nextjs/node_modules/next
new file mode 120000
index 000000000000..2519d3a17582
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/next
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/react b/playgrounds/nextjs/node_modules/react
new file mode 120000
index 000000000000..3a80171770b0
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/react
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/react@19.2.3/node_modules/react
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/react-dom b/playgrounds/nextjs/node_modules/react-dom
new file mode 120000
index 000000000000..d968d23b66d9
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/react-dom
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/tailwindcss b/playgrounds/nextjs/node_modules/tailwindcss
new file mode 120000
index 000000000000..04022219c6fb
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../../packages/tailwindcss
\ No newline at end of file
diff --git a/playgrounds/nextjs/node_modules/typescript b/playgrounds/nextjs/node_modules/typescript
new file mode 120000
index 000000000000..24551343a8b9
--- /dev/null
+++ b/playgrounds/nextjs/node_modules/typescript
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/typescript@5.5.4/node_modules/typescript
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/.bin/autoprefixer b/playgrounds/v3/node_modules/.bin/autoprefixer
new file mode 100755
index 000000000000..43bc027ade44
--- /dev/null
+++ b/playgrounds/v3/node_modules/.bin/autoprefixer
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/autoprefixer@10.4.23_postcss@8.4.47/node_modules/autoprefixer/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/autoprefixer@10.4.23_postcss@8.4.47/node_modules/autoprefixer/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/autoprefixer@10.4.23_postcss@8.4.47/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/autoprefixer@10.4.23_postcss@8.4.47/node_modules/autoprefixer/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/autoprefixer@10.4.23_postcss@8.4.47/node_modules/autoprefixer/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/autoprefixer@10.4.23_postcss@8.4.47/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../autoprefixer/bin/autoprefixer" "$@"
+else
+ exec node "$basedir/../autoprefixer/bin/autoprefixer" "$@"
+fi
diff --git a/playgrounds/v3/node_modules/.bin/eslint b/playgrounds/v3/node_modules/.bin/eslint
new file mode 100755
index 000000000000..d34fa91759b1
--- /dev/null
+++ b/playgrounds/v3/node_modules/.bin/eslint
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../eslint/bin/eslint.js" "$@"
+else
+ exec node "$basedir/../eslint/bin/eslint.js" "$@"
+fi
diff --git a/playgrounds/v3/node_modules/.bin/next b/playgrounds/v3/node_modules/.bin/next
new file mode 100755
index 000000000000..7868c2ceab3f
--- /dev/null
+++ b/playgrounds/v3/node_modules/.bin/next
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/dist/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/dist/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/dist/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/dist/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../next/dist/bin/next" "$@"
+else
+ exec node "$basedir/../next/dist/bin/next" "$@"
+fi
diff --git a/playgrounds/v3/node_modules/.bin/tailwind b/playgrounds/v3/node_modules/.bin/tailwind
new file mode 100755
index 000000000000..aaac1343f765
--- /dev/null
+++ b/playgrounds/v3/node_modules/.bin/tailwind
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss/lib/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss/lib/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../tailwindcss/lib/cli.js" "$@"
+else
+ exec node "$basedir/../tailwindcss/lib/cli.js" "$@"
+fi
diff --git a/playgrounds/v3/node_modules/.bin/tailwindcss b/playgrounds/v3/node_modules/.bin/tailwindcss
new file mode 100755
index 000000000000..aaac1343f765
--- /dev/null
+++ b/playgrounds/v3/node_modules/.bin/tailwindcss
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss/lib/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss/lib/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/tailwindcss@3.4.14/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../tailwindcss/lib/cli.js" "$@"
+else
+ exec node "$basedir/../tailwindcss/lib/cli.js" "$@"
+fi
diff --git a/playgrounds/v3/node_modules/.bin/tsc b/playgrounds/v3/node_modules/.bin/tsc
new file mode 100755
index 000000000000..15e7a3651e52
--- /dev/null
+++ b/playgrounds/v3/node_modules/.bin/tsc
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
+else
+ exec node "$basedir/../typescript/bin/tsc" "$@"
+fi
diff --git a/playgrounds/v3/node_modules/.bin/tsserver b/playgrounds/v3/node_modules/.bin/tsserver
new file mode 100755
index 000000000000..e1819a90bf8e
--- /dev/null
+++ b/playgrounds/v3/node_modules/.bin/tsserver
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/typescript@5.6.3/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
+else
+ exec node "$basedir/../typescript/bin/tsserver" "$@"
+fi
diff --git a/playgrounds/v3/node_modules/@types/node b/playgrounds/v3/node_modules/@types/node
new file mode 120000
index 000000000000..1a9f4bde7384
--- /dev/null
+++ b/playgrounds/v3/node_modules/@types/node
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+node@20.14.13/node_modules/@types/node
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/@types/react b/playgrounds/v3/node_modules/@types/react
new file mode 120000
index 000000000000..df4499dfb012
--- /dev/null
+++ b/playgrounds/v3/node_modules/@types/react
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+react@19.2.7/node_modules/@types/react
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/@types/react-dom b/playgrounds/v3/node_modules/@types/react-dom
new file mode 120000
index 000000000000..41e90d09f161
--- /dev/null
+++ b/playgrounds/v3/node_modules/@types/react-dom
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.7/node_modules/@types/react-dom
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/autoprefixer b/playgrounds/v3/node_modules/autoprefixer
new file mode 120000
index 000000000000..2881040a456b
--- /dev/null
+++ b/playgrounds/v3/node_modules/autoprefixer
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/autoprefixer@10.4.23_postcss@8.4.47/node_modules/autoprefixer
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/eslint b/playgrounds/v3/node_modules/eslint
new file mode 120000
index 000000000000..c0c4dc671e2f
--- /dev/null
+++ b/playgrounds/v3/node_modules/eslint
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/eslint@9.39.2_jiti@2.6.1/node_modules/eslint
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/eslint-config-next b/playgrounds/v3/node_modules/eslint-config-next
new file mode 120000
index 000000000000..e072b36b84fe
--- /dev/null
+++ b/playgrounds/v3/node_modules/eslint-config-next
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/eslint-config-next@16.1.0_eslint@9.39.2_jiti@2.6.1__typescript@5.6.3/node_modules/eslint-config-next
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/next b/playgrounds/v3/node_modules/next
new file mode 120000
index 000000000000..2519d3a17582
--- /dev/null
+++ b/playgrounds/v3/node_modules/next
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/next@16.1.0_@playwright+test@1.57.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/next
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/react b/playgrounds/v3/node_modules/react
new file mode 120000
index 000000000000..3a80171770b0
--- /dev/null
+++ b/playgrounds/v3/node_modules/react
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/react@19.2.3/node_modules/react
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/react-dom b/playgrounds/v3/node_modules/react-dom
new file mode 120000
index 000000000000..d968d23b66d9
--- /dev/null
+++ b/playgrounds/v3/node_modules/react-dom
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/tailwindcss b/playgrounds/v3/node_modules/tailwindcss
new file mode 120000
index 000000000000..a1d839e7c6df
--- /dev/null
+++ b/playgrounds/v3/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/tailwindcss@3.4.14/node_modules/tailwindcss
\ No newline at end of file
diff --git a/playgrounds/v3/node_modules/typescript b/playgrounds/v3/node_modules/typescript
new file mode 120000
index 000000000000..61f1ec41e117
--- /dev/null
+++ b/playgrounds/v3/node_modules/typescript
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/.bin/bun b/playgrounds/vite/node_modules/.bin/bun
new file mode 100755
index 000000000000..0f5fa74b3146
--- /dev/null
+++ b/playgrounds/vite/node_modules/.bin/bun
@@ -0,0 +1,14 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+"$basedir/../bun/bin/bun.exe" "$@"
+exit $?
diff --git a/playgrounds/vite/node_modules/.bin/bunx b/playgrounds/vite/node_modules/.bin/bunx
new file mode 100755
index 000000000000..8896c8000de3
--- /dev/null
+++ b/playgrounds/vite/node_modules/.bin/bunx
@@ -0,0 +1,14 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules/bun/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/bun@1.3.5/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+"$basedir/../bun/bin/bunx.exe" "$@"
+exit $?
diff --git a/playgrounds/vite/node_modules/.bin/vite b/playgrounds/vite/node_modules/.bin/vite
new file mode 100755
index 000000000000..f86d1d02e60a
--- /dev/null
+++ b/playgrounds/vite/node_modules/.bin/vite
@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules"
+else
+ export NODE_PATH="/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite/bin/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules:/home/ktaylor/Projects/tailwindcss/node_modules/.pnpm/node_modules:$NODE_PATH"
+fi
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@"
+else
+ exec node "$basedir/../vite/bin/vite.js" "$@"
+fi
diff --git a/playgrounds/vite/node_modules/@tailwindcss/vite b/playgrounds/vite/node_modules/@tailwindcss/vite
new file mode 120000
index 000000000000..83ddf6d1e064
--- /dev/null
+++ b/playgrounds/vite/node_modules/@tailwindcss/vite
@@ -0,0 +1 @@
+../../../../packages/@tailwindcss-vite
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/@types/react b/playgrounds/vite/node_modules/@types/react
new file mode 120000
index 000000000000..df4499dfb012
--- /dev/null
+++ b/playgrounds/vite/node_modules/@types/react
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+react@19.2.7/node_modules/@types/react
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/@types/react-dom b/playgrounds/vite/node_modules/@types/react-dom
new file mode 120000
index 000000000000..41e90d09f161
--- /dev/null
+++ b/playgrounds/vite/node_modules/@types/react-dom
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.7/node_modules/@types/react-dom
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/@vitejs/plugin-react b/playgrounds/vite/node_modules/@vitejs/plugin-react
new file mode 120000
index 000000000000..fedac2cc53ec
--- /dev/null
+++ b/playgrounds/vite/node_modules/@vitejs/plugin-react
@@ -0,0 +1 @@
+../../../../node_modules/.pnpm/@vitejs+plugin-react@5.1.2_vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patc_aj35tdpqa5okkgz5tghuf75b2y/node_modules/@vitejs/plugin-react
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/bun b/playgrounds/vite/node_modules/bun
new file mode 120000
index 000000000000..7f0483f32075
--- /dev/null
+++ b/playgrounds/vite/node_modules/bun
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/bun@1.3.5/node_modules/bun
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/react b/playgrounds/vite/node_modules/react
new file mode 120000
index 000000000000..3a80171770b0
--- /dev/null
+++ b/playgrounds/vite/node_modules/react
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/react@19.2.3/node_modules/react
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/react-dom b/playgrounds/vite/node_modules/react-dom
new file mode 120000
index 000000000000..d968d23b66d9
--- /dev/null
+++ b/playgrounds/vite/node_modules/react-dom
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/tailwindcss b/playgrounds/vite/node_modules/tailwindcss
new file mode 120000
index 000000000000..04022219c6fb
--- /dev/null
+++ b/playgrounds/vite/node_modules/tailwindcss
@@ -0,0 +1 @@
+../../../packages/tailwindcss
\ No newline at end of file
diff --git a/playgrounds/vite/node_modules/vite b/playgrounds/vite/node_modules/vite
new file mode 120000
index 000000000000..64a91e084ab7
--- /dev/null
+++ b/playgrounds/vite/node_modules/vite
@@ -0,0 +1 @@
+../../../node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.30.2_patch_hash=tzyxy3asfxcqc7ihroou_6ihr2b6mexvz5zmjho4omuoio4/node_modules/vite
\ No newline at end of file
diff --git a/scripts/build-versioned.js b/scripts/build-versioned.js
new file mode 100644
index 000000000000..c0c3f0794982
--- /dev/null
+++ b/scripts/build-versioned.js
@@ -0,0 +1,156 @@
+#!/usr/bin/env node
+const { execSync } = require('child_process')
+const fs = require('fs')
+const path = require('path')
+
+// Read version from package.json
+const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'))
+const VERSION = packageJson.version
+const ROOT = path.join(__dirname, '..')
+
+console.log(`Building Tailwind CSS v${VERSION}...`)
+
+// Generate plugin list
+console.log('Generating plugin list...')
+try {
+ execSync('npm run generate', { stdio: 'inherit', cwd: ROOT })
+} catch (err) {
+ console.error('Failed to generate plugin list')
+ process.exit(1)
+}
+
+// Clean only this version's directory (preserve other versions)
+const versionDir = path.join(ROOT, 'lib', VERSION)
+console.log(`Cleaning ${versionDir}...`)
+if (fs.existsSync(versionDir)) {
+ try {
+ execSync(`npx rimraf "${versionDir}"`, { stdio: 'inherit', cwd: ROOT })
+ } catch (err) {
+ console.error(`Failed to clean ${versionDir}`)
+ process.exit(1)
+ }
+}
+
+// Ensure lib directory exists
+if (!fs.existsSync(path.join(ROOT, 'lib'))) {
+ fs.mkdirSync(path.join(ROOT, 'lib'), { recursive: true })
+}
+
+// Build with versioned output
+console.log(`Compiling to lib/${VERSION}...`)
+try {
+ execSync(`npx swc src --out-dir lib/${VERSION} --copy-files`, {
+ stdio: 'inherit',
+ cwd: ROOT,
+ })
+} catch (err) {
+ console.error('SWC compilation failed')
+ process.exit(1)
+}
+
+// Bundle peers
+const peerInput = path.join('lib', VERSION, 'cli-peer-dependencies.js')
+const peersDir = path.join(ROOT, 'peers')
+console.log('Bundling peer dependencies...')
+
+// Ensure peers directory exists
+if (!fs.existsSync(peersDir)) {
+ fs.mkdirSync(peersDir, { recursive: true })
+}
+
+try {
+ execSync(`npx esbuild ${peerInput} --bundle --platform=node --outfile=peers/index.js`, {
+ stdio: 'inherit',
+ cwd: ROOT,
+ })
+} catch (err) {
+ console.error('Failed to bundle peer dependencies')
+ process.exit(1)
+}
+
+// Create symlinks for backwards compatibility
+console.log('Creating symlinks for package entry points...')
+const symlinkTargets = [
+ 'index.js',
+ 'cli.js',
+ 'cli-peer-dependencies.js',
+ 'constants.js',
+ 'corePluginList.js',
+ 'corePlugins.js',
+ 'featureFlags.js',
+ 'processTailwindFeatures.js',
+]
+
+for (const target of symlinkTargets) {
+ const linkPath = path.join(ROOT, 'lib', target)
+ const targetPath = path.join(VERSION, target)
+
+ // Remove existing symlink/file
+ if (fs.existsSync(linkPath)) {
+ try {
+ fs.unlinkSync(linkPath)
+ } catch (err) {
+ // Try to remove as directory if it's a directory symlink
+ try {
+ fs.rmSync(linkPath, { recursive: true, force: true })
+ } catch (err2) {
+ console.warn(`Warning: Could not remove existing ${target}`)
+ }
+ }
+ }
+
+ // Create symlink (or copy on Windows if symlink fails)
+ try {
+ fs.symlinkSync(targetPath, linkPath, 'file')
+ console.log(` ✓ Symlinked ${target} → ${VERSION}/${target}`)
+ } catch (err) {
+ // Fallback to copy for Windows without admin rights
+ console.log(` ℹ Symlink failed for ${target}, using copy instead`)
+ const sourcePath = path.join(ROOT, 'lib', VERSION, target)
+ if (fs.existsSync(sourcePath)) {
+ fs.copyFileSync(sourcePath, linkPath)
+ console.log(` ✓ Copied ${target} from ${VERSION}/${target}`)
+ } else {
+ console.warn(` ⚠ Warning: ${sourcePath} does not exist, skipping`)
+ }
+ }
+}
+
+// Also handle subdirectories that might be imported
+const dirSymlinks = ['css', 'lib', 'postcss-plugins', 'public', 'util']
+for (const dir of dirSymlinks) {
+ const linkPath = path.join(ROOT, 'lib', dir)
+ const targetPath = path.join(VERSION, dir)
+
+ // Remove existing symlink/directory
+ if (fs.existsSync(linkPath)) {
+ try {
+ fs.rmSync(linkPath, { recursive: true, force: true })
+ } catch (err) {
+ console.warn(`Warning: Could not remove existing ${dir}/`)
+ }
+ }
+
+ // Check if source directory exists
+ const srcDir = path.join(ROOT, 'lib', VERSION, dir)
+ if (!fs.existsSync(srcDir)) {
+ console.log(` ℹ Skipping ${dir}/ (doesn't exist in build output)`)
+ continue
+ }
+
+ // Create symlink (or copy on Windows if symlink fails)
+ try {
+ fs.symlinkSync(targetPath, linkPath, 'dir')
+ console.log(` ✓ Symlinked ${dir}/ → ${VERSION}/${dir}/`)
+ } catch (err) {
+ // Fallback: recursive copy
+ console.log(` ℹ Symlink failed for ${dir}/, using copy instead`)
+ if (fs.existsSync(srcDir)) {
+ fs.cpSync(srcDir, linkPath, { recursive: true })
+ console.log(` ✓ Copied ${dir}/ from ${VERSION}/${dir}/`)
+ }
+ }
+}
+
+console.log(`\n✓ Build complete! Output: lib/${VERSION}/`)
+console.log(` Symlinks/copies created at lib/ for backwards compatibility`)
diff --git a/scripts/get-version.js b/scripts/get-version.js
new file mode 100644
index 000000000000..96dd1fde23f3
--- /dev/null
+++ b/scripts/get-version.js
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+const fs = require('fs')
+const path = require('path')
+
+const packageJsonPath = path.join(__dirname, '..', 'package.json')
+const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
+console.log(packageJson.version)
diff --git a/scripts/pack-versioned.js b/scripts/pack-versioned.js
new file mode 100644
index 000000000000..eabf0a1bd4ea
--- /dev/null
+++ b/scripts/pack-versioned.js
@@ -0,0 +1,163 @@
+#!/usr/bin/env node
+const { execSync } = require('child_process')
+const fs = require('fs')
+const path = require('path')
+
+// Read version
+const ROOT = path.join(__dirname, '..')
+const packageJson = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'))
+const VERSION = packageJson.version
+const PACKAGE_NAME = packageJson.name
+
+// Create dist/VERSION directory
+const distVersionDir = path.join(ROOT, 'dist', VERSION)
+const distRootDir = path.join(ROOT, 'dist')
+
+fs.mkdirSync(distVersionDir, { recursive: true })
+
+console.log(`Packing ${PACKAGE_NAME}@${VERSION}...`)
+
+// Replace symlinks with actual copies before packing
+// This ensures the tarball contains real files, not symlinks
+console.log('Converting symlinks to copies for packaging...')
+
+const symlinkTargets = [
+ 'index.js',
+ 'cli.js',
+ 'cli-peer-dependencies.js',
+ 'constants.js',
+ 'corePluginList.js',
+ 'corePlugins.js',
+ 'featureFlags.js',
+ 'processTailwindFeatures.js',
+]
+
+const dirSymlinks = ['css', 'lib', 'postcss-plugins', 'public', 'util']
+
+// Store original symlink info to restore later
+const symlinksToRestore = []
+
+// Replace file symlinks with copies
+for (const target of symlinkTargets) {
+ const linkPath = path.join(ROOT, 'lib', target)
+
+ if (fs.existsSync(linkPath)) {
+ const stats = fs.lstatSync(linkPath)
+
+ if (stats.isSymbolicLink()) {
+ const targetPath = fs.readlinkSync(linkPath)
+ const sourcePath = path.join(ROOT, 'lib', targetPath)
+
+ // Store for restoration
+ symlinksToRestore.push({ linkPath, targetPath, type: 'file' })
+
+ // Replace symlink with copy
+ fs.unlinkSync(linkPath)
+ if (fs.existsSync(sourcePath)) {
+ fs.copyFileSync(sourcePath, linkPath)
+ console.log(` ✓ Replaced symlink ${target} with copy`)
+ } else {
+ console.warn(` ⚠ Warning: Source file ${sourcePath} not found for ${target}`)
+ }
+ }
+ }
+}
+
+// Replace directory symlinks with copies
+for (const dir of dirSymlinks) {
+ const linkPath = path.join(ROOT, 'lib', dir)
+
+ if (fs.existsSync(linkPath)) {
+ const stats = fs.lstatSync(linkPath)
+
+ if (stats.isSymbolicLink()) {
+ const targetPath = fs.readlinkSync(linkPath)
+ const sourcePath = path.join(ROOT, 'lib', targetPath)
+
+ // Store for restoration
+ symlinksToRestore.push({ linkPath, targetPath, type: 'dir' })
+
+ // Replace symlink with copy
+ fs.rmSync(linkPath, { recursive: true, force: true })
+ if (fs.existsSync(sourcePath)) {
+ fs.cpSync(sourcePath, linkPath, { recursive: true })
+ console.log(` ✓ Replaced symlink ${dir}/ with copy`)
+ } else {
+ console.warn(` ⚠ Warning: Source directory ${sourcePath} not found for ${dir}/`)
+ }
+ }
+ }
+}
+
+console.log('\nRunning npm pack...')
+
+// Run npm pack with output to dist/VERSION
+try {
+ execSync(`npm pack --pack-destination="${distVersionDir}"`, {
+ stdio: 'inherit',
+ cwd: ROOT,
+ })
+} catch (err) {
+ console.error('npm pack failed')
+
+ // Restore symlinks before exiting
+ console.log('\nRestoring symlinks after failure...')
+ for (const { linkPath, targetPath, type } of symlinksToRestore) {
+ try {
+ if (fs.existsSync(linkPath)) {
+ if (type === 'dir') {
+ fs.rmSync(linkPath, { recursive: true, force: true })
+ } else {
+ fs.unlinkSync(linkPath)
+ }
+ }
+ fs.symlinkSync(targetPath, linkPath, type)
+ } catch (restoreErr) {
+ console.error(`Failed to restore symlink: ${linkPath}`)
+ }
+ }
+
+ process.exit(1)
+}
+
+// Restore symlinks after successful pack
+console.log('\nRestoring symlinks...')
+for (const { linkPath, targetPath, type } of symlinksToRestore) {
+ try {
+ if (fs.existsSync(linkPath)) {
+ if (type === 'dir') {
+ fs.rmSync(linkPath, { recursive: true, force: true })
+ } else {
+ fs.unlinkSync(linkPath)
+ }
+ }
+ fs.symlinkSync(targetPath, linkPath, type)
+ console.log(` ✓ Restored symlink: ${path.basename(linkPath)}`)
+ } catch (restoreErr) {
+ console.error(` ✗ Failed to restore symlink: ${linkPath}`)
+ }
+}
+
+const tarballName = `${PACKAGE_NAME}-${VERSION}.tgz`
+const versionedTarball = path.join(distVersionDir, tarballName)
+const rootTarball = path.join(distRootDir, tarballName)
+
+if (!fs.existsSync(versionedTarball)) {
+ console.error(`Error: Expected tarball not found at ${versionedTarball}`)
+ process.exit(1)
+}
+
+console.log(`✓ Tarball created: dist/${VERSION}/${tarballName}`)
+
+// Copy to root dist for backwards compatibility
+try {
+ fs.copyFileSync(versionedTarball, rootTarball)
+ console.log(`✓ Also copied to: dist/${tarballName}`)
+} catch (err) {
+ console.error('Failed to copy tarball to root dist')
+ process.exit(1)
+}
+
+console.log('\n✓ Packaging complete!')
+console.log(` Versioned: dist/${VERSION}/${tarballName}`)
+console.log(` Root: dist/${tarballName}`)
diff --git a/src/corePlugins.js b/src/corePlugins.js
index 03ff5e238db1..8e41347e50da 100644
--- a/src/corePlugins.js
+++ b/src/corePlugins.js
@@ -27,9 +27,7 @@ export let variantPlugins = {
addVariant('placeholder', '&::placeholder')
- /*
addVariant('backdrop', '&::backdrop')
- */
addVariant('before', ({ container }) => {
container.walkRules((rule) => {
@@ -106,6 +104,7 @@ export let variantPlugins = {
'indeterminate',
'placeholder-shown',
'autofill',
+ 'optional',
'required',
'valid',
'invalid',
@@ -122,9 +121,7 @@ export let variantPlugins = {
'focus',
'focus-visible',
'active',
- /*
'enabled',
- */
'disabled',
].map((variant) => (Array.isArray(variant) ? variant : [variant, `:${variant}`]))
@@ -200,10 +197,53 @@ export let variantPlugins = {
}
},
+ prefersContrastVariants: ({ addVariant }) => {
+ addVariant('contrast-more', '@media (prefers-contrast: more)')
+ addVariant('contrast-less', '@media (prefers-contrast: less)')
+ },
+
printVariant: ({ addVariant }) => {
addVariant('print', '@media print')
},
+ forcedColorsVariant: ({ addVariant }) => {
+ addVariant('forced-colors', '@media (forced-colors: active)')
+ },
+
+ ariaVariants: ({ addVariant, theme }) => {
+ let values = theme('aria') ?? {}
+ for (let [key, value] of Object.entries(values)) {
+ addVariant(`aria-${key}`, `&[aria-${value}]`)
+ }
+ },
+
+ dataVariants: ({ addVariant, theme }) => {
+ let values = theme('data') ?? {}
+ for (let [key, value] of Object.entries(values)) {
+ addVariant(`data-${key}`, `&[data-${value}]`)
+ }
+ },
+
+ supportsVariants: ({ addVariant }) => {
+ // Note: Full arbitrary support for supports-[...] handled by extractor
+ // This provides the base variant registration
+ addVariant('supports', ({ container }) => {
+ // This will be enhanced when arbitrary supports-[...] is detected
+ return container
+ })
+ },
+
+ minMaxVariants: ({ addVariant }) => {
+ // Note: Full arbitrary support for min-[...] and max-[...] handled by extractor
+ // This provides the base variant registration
+ addVariant('min', ({ container }) => {
+ return container
+ })
+ addVariant('max', ({ container }) => {
+ return container
+ })
+ },
+
screenVariants: ({ theme, addVariant }) => {
for (let screen of normalizeScreens(theme('screens'))) {
let query = buildMediaQuery(screen)
@@ -389,6 +429,7 @@ export let corePlugins = {
addUtilities({
'.visible': { visibility: 'visible' },
'.invisible': { visibility: 'hidden' },
+ '.collapse': { visibility: 'collapse' },
})
},
@@ -420,6 +461,37 @@ export let corePlugins = {
{ supportsNegativeValues: true }
),
+ insetInline: createUtilityPlugin('insetInline', [['inset-inline', ['inset-inline']]], {
+ supportsNegativeValues: true,
+ }),
+ insetInlineStart: createUtilityPlugin(
+ 'insetInlineStart',
+ [
+ ['start', ['inset-inline-start']],
+ ['inset-inline-start', ['inset-inline-start']],
+ ],
+ { supportsNegativeValues: true }
+ ),
+ insetInlineEnd: createUtilityPlugin(
+ 'insetInlineEnd',
+ [
+ ['end', ['inset-inline-end']],
+ ['inset-inline-end', ['inset-inline-end']],
+ ],
+ { supportsNegativeValues: true }
+ ),
+ insetBlock: createUtilityPlugin('insetBlock', [['inset-block', ['inset-block']]], {
+ supportsNegativeValues: true,
+ }),
+ insetBlockStart: createUtilityPlugin(
+ 'insetBlockStart',
+ [['inset-block-start', ['inset-block-start']]],
+ { supportsNegativeValues: true }
+ ),
+ insetBlockEnd: createUtilityPlugin('insetBlockEnd', [['inset-block-end', ['inset-block-end']]], {
+ supportsNegativeValues: true,
+ }),
+
isolation: ({ addUtilities }) => {
addUtilities({
'.isolate': { isolation: 'isolate' },
@@ -471,6 +543,39 @@ export let corePlugins = {
{ supportsNegativeValues: true }
),
+ marginInline: createUtilityPlugin('marginInline', [['margin-inline', ['margin-inline']]], {
+ supportsNegativeValues: true,
+ }),
+ marginInlineStart: createUtilityPlugin(
+ 'marginInlineStart',
+ [
+ ['ms', ['margin-inline-start']],
+ ['margin-inline-start', ['margin-inline-start']],
+ ],
+ { supportsNegativeValues: true }
+ ),
+ marginInlineEnd: createUtilityPlugin(
+ 'marginInlineEnd',
+ [
+ ['me', ['margin-inline-end']],
+ ['margin-inline-end', ['margin-inline-end']],
+ ],
+ { supportsNegativeValues: true }
+ ),
+ marginBlock: createUtilityPlugin('marginBlock', [['margin-block', ['margin-block']]], {
+ supportsNegativeValues: true,
+ }),
+ marginBlockStart: createUtilityPlugin(
+ 'marginBlockStart',
+ [['margin-block-start', ['margin-block-start']]],
+ { supportsNegativeValues: true }
+ ),
+ marginBlockEnd: createUtilityPlugin(
+ 'marginBlockEnd',
+ [['margin-block-end', ['margin-block-end']]],
+ { supportsNegativeValues: true }
+ ),
+
boxSizing: ({ addUtilities }) => {
addUtilities({
'.box-border': { 'box-sizing': 'border-box' },
@@ -514,6 +619,8 @@ export let corePlugins = {
minWidth: createUtilityPlugin('minWidth', [['min-w', ['minWidth']]]),
maxWidth: createUtilityPlugin('maxWidth', [['max-w', ['maxWidth']]]),
+ size: createUtilityPlugin('size', [['size', ['width', 'height']]]),
+
flex: createUtilityPlugin('flex'),
flexShrink: createUtilityPlugin('flexShrink', [
['flex-shrink', ['flex-shrink']], // Deprecated
@@ -539,7 +646,13 @@ export let corePlugins = {
})
},
- /*
+ captionSide: ({ addUtilities }) => {
+ addUtilities({
+ '.caption-top': { 'caption-side': 'top' },
+ '.caption-bottom': { 'caption-side': 'bottom' },
+ })
+ },
+
borderSpacing: ({ addDefaults, matchUtilities, theme }) => {
addDefaults('border-spacing', {
'--tw-border-spacing-x': 0,
@@ -574,7 +687,6 @@ export let corePlugins = {
{ values: theme('borderSpacing') }
)
},
- */
transformOrigin: createUtilityPlugin('transformOrigin', [['origin', ['transformOrigin']]]),
translate: createUtilityPlugin(
@@ -835,6 +947,48 @@ export let corePlugins = {
],
]),
+ scrollMarginInline: createUtilityPlugin('scrollMarginInline', [
+ ['scroll-margin-inline', ['scroll-margin-inline']],
+ ]),
+ scrollMarginInlineStart: createUtilityPlugin('scrollMarginInlineStart', [
+ ['scroll-ms', ['scroll-margin-inline-start']],
+ ['scroll-margin-inline-start', ['scroll-margin-inline-start']],
+ ]),
+ scrollMarginInlineEnd: createUtilityPlugin('scrollMarginInlineEnd', [
+ ['scroll-me', ['scroll-margin-inline-end']],
+ ['scroll-margin-inline-end', ['scroll-margin-inline-end']],
+ ]),
+ scrollMarginBlock: createUtilityPlugin('scrollMarginBlock', [
+ ['scroll-margin-block', ['scroll-margin-block']],
+ ]),
+ scrollMarginBlockStart: createUtilityPlugin('scrollMarginBlockStart', [
+ ['scroll-margin-block-start', ['scroll-margin-block-start']],
+ ]),
+ scrollMarginBlockEnd: createUtilityPlugin('scrollMarginBlockEnd', [
+ ['scroll-margin-block-end', ['scroll-margin-block-end']],
+ ]),
+
+ scrollPaddingInline: createUtilityPlugin('scrollPaddingInline', [
+ ['scroll-padding-inline', ['scroll-padding-inline']],
+ ]),
+ scrollPaddingInlineStart: createUtilityPlugin('scrollPaddingInlineStart', [
+ ['scroll-ps', ['scroll-padding-inline-start']],
+ ['scroll-padding-inline-start', ['scroll-padding-inline-start']],
+ ]),
+ scrollPaddingInlineEnd: createUtilityPlugin('scrollPaddingInlineEnd', [
+ ['scroll-pe', ['scroll-padding-inline-end']],
+ ['scroll-padding-inline-end', ['scroll-padding-inline-end']],
+ ]),
+ scrollPaddingBlock: createUtilityPlugin('scrollPaddingBlock', [
+ ['scroll-padding-block', ['scroll-padding-block']],
+ ]),
+ scrollPaddingBlockStart: createUtilityPlugin('scrollPaddingBlockStart', [
+ ['scroll-padding-block-start', ['scroll-padding-block-start']],
+ ]),
+ scrollPaddingBlockEnd: createUtilityPlugin('scrollPaddingBlockEnd', [
+ ['scroll-padding-block-end', ['scroll-padding-block-end']],
+ ]),
+
listStylePosition: ({ addUtilities }) => {
addUtilities({
'.list-inside': { 'list-style-position': 'inside' },
@@ -844,6 +998,15 @@ export let corePlugins = {
listStyleType: createUtilityPlugin('listStyleType', [['list', ['listStyleType']]]),
+ listStyleImage: ({ matchUtilities, theme }) => {
+ matchUtilities(
+ {
+ 'list-image': (value) => ({ 'list-style-image': value }),
+ },
+ { values: theme('listStyleImage') }
+ )
+ },
+
appearance: ({ addUtilities }) => {
addUtilities({
'.appearance-none': { appearance: 'none' },
@@ -893,6 +1056,7 @@ export let corePlugins = {
addUtilities({
'.grid-flow-row': { gridAutoFlow: 'row' },
'.grid-flow-col': { gridAutoFlow: 'column' },
+ '.grid-flow-dense': { gridAutoFlow: 'dense' },
'.grid-flow-row-dense': { gridAutoFlow: 'row dense' },
'.grid-flow-col-dense': { gridAutoFlow: 'column dense' },
})
@@ -929,6 +1093,7 @@ export let corePlugins = {
'.place-content-between': { 'place-content': 'space-between' },
'.place-content-around': { 'place-content': 'space-around' },
'.place-content-evenly': { 'place-content': 'space-evenly' },
+ '.place-content-baseline': { 'place-content': 'baseline' },
'.place-content-stretch': { 'place-content': 'stretch' },
})
},
@@ -938,18 +1103,22 @@ export let corePlugins = {
'.place-items-start': { 'place-items': 'start' },
'.place-items-end': { 'place-items': 'end' },
'.place-items-center': { 'place-items': 'center' },
+ '.place-items-baseline': { 'place-items': 'baseline' },
'.place-items-stretch': { 'place-items': 'stretch' },
})
},
alignContent: ({ addUtilities }) => {
addUtilities({
+ '.content-normal': { 'align-content': 'normal' },
'.content-center': { 'align-content': 'center' },
'.content-start': { 'align-content': 'flex-start' },
'.content-end': { 'align-content': 'flex-end' },
'.content-between': { 'align-content': 'space-between' },
'.content-around': { 'align-content': 'space-around' },
'.content-evenly': { 'align-content': 'space-evenly' },
+ '.content-baseline': { 'align-content': 'baseline' },
+ '.content-stretch': { 'align-content': 'stretch' },
})
},
@@ -965,12 +1134,14 @@ export let corePlugins = {
justifyContent: ({ addUtilities }) => {
addUtilities({
+ '.justify-normal': { 'justify-content': 'normal' },
'.justify-start': { 'justify-content': 'flex-start' },
'.justify-end': { 'justify-content': 'flex-end' },
'.justify-center': { 'justify-content': 'center' },
'.justify-between': { 'justify-content': 'space-between' },
'.justify-around': { 'justify-content': 'space-around' },
'.justify-evenly': { 'justify-content': 'space-evenly' },
+ '.justify-stretch': { 'justify-content': 'stretch' },
})
},
@@ -1199,6 +1370,15 @@ export let corePlugins = {
})
},
+ textWrap: ({ addUtilities }) => {
+ addUtilities({
+ '.text-wrap': { 'text-wrap': 'wrap' },
+ '.text-nowrap': { 'text-wrap': 'nowrap' },
+ '.text-balance': { 'text-wrap': 'balance' },
+ '.text-pretty': { 'text-wrap': 'pretty' },
+ })
+ },
+
whitespace: ({ addUtilities }) => {
addUtilities({
'.whitespace-normal': { 'white-space': 'normal' },
@@ -1206,6 +1386,7 @@ export let corePlugins = {
'.whitespace-pre': { 'white-space': 'pre' },
'.whitespace-pre-line': { 'white-space': 'pre-line' },
'.whitespace-pre-wrap': { 'white-space': 'pre-wrap' },
+ '.whitespace-break-spaces': { 'white-space': 'break-spaces' },
})
},
@@ -1214,6 +1395,15 @@ export let corePlugins = {
'.break-normal': { 'overflow-wrap': 'normal', 'word-break': 'normal' },
'.break-words': { 'overflow-wrap': 'break-word' },
'.break-all': { 'word-break': 'break-all' },
+ '.break-keep': { 'word-break': 'keep-all' },
+ })
+ },
+
+ hyphens: ({ addUtilities }) => {
+ addUtilities({
+ '.hyphens-none': { hyphens: 'none' },
+ '.hyphens-manual': { hyphens: 'manual' },
+ '.hyphens-auto': { hyphens: 'auto' },
})
},
@@ -1233,6 +1423,19 @@ export let corePlugins = {
],
]),
+ borderStartStartRadius: createUtilityPlugin('borderStartStartRadius', [
+ ['rounded-ss', ['border-start-start-radius']],
+ ]),
+ borderStartEndRadius: createUtilityPlugin('borderStartEndRadius', [
+ ['rounded-se', ['border-start-end-radius']],
+ ]),
+ borderEndStartRadius: createUtilityPlugin('borderEndStartRadius', [
+ ['rounded-es', ['border-end-start-radius']],
+ ]),
+ borderEndEndRadius: createUtilityPlugin('borderEndEndRadius', [
+ ['rounded-ee', ['border-end-end-radius']],
+ ]),
+
borderWidth: createUtilityPlugin(
'borderWidth',
[
@@ -1514,7 +1717,7 @@ export let corePlugins = {
})
},
- fill: ({ matchUtilities, theme }) => {
+ fill: ({ matchUtilities, theme, addUtilities }) => {
matchUtilities(
{
fill: (value) => {
@@ -1523,9 +1726,12 @@ export let corePlugins = {
},
{ values: flattenColorPalette(theme('fill')), type: ['color', 'any'] }
)
+ addUtilities({
+ '.fill-none': { fill: 'none' },
+ })
},
- stroke: ({ matchUtilities, theme }) => {
+ stroke: ({ matchUtilities, theme, addUtilities }) => {
matchUtilities(
{
stroke: (value) => {
@@ -1534,6 +1740,9 @@ export let corePlugins = {
},
{ values: flattenColorPalette(theme('stroke')), type: ['color', 'url'] }
)
+ addUtilities({
+ '.stroke-none': { stroke: 'none' },
+ })
},
strokeWidth: createUtilityPlugin('strokeWidth', [['stroke', ['stroke-width']]], {
@@ -1565,16 +1774,31 @@ export let corePlugins = {
],
]),
+ paddingInline: createUtilityPlugin('paddingInline', [['padding-inline', ['padding-inline']]]),
+ paddingInlineStart: createUtilityPlugin('paddingInlineStart', [
+ ['ps', ['padding-inline-start']],
+ ['padding-inline-start', ['padding-inline-start']],
+ ]),
+ paddingInlineEnd: createUtilityPlugin('paddingInlineEnd', [
+ ['pe', ['padding-inline-end']],
+ ['padding-inline-end', ['padding-inline-end']],
+ ]),
+ paddingBlock: createUtilityPlugin('paddingBlock', [['padding-block', ['padding-block']]]),
+ paddingBlockStart: createUtilityPlugin('paddingBlockStart', [
+ ['padding-block-start', ['padding-block-start']],
+ ]),
+ paddingBlockEnd: createUtilityPlugin('paddingBlockEnd', [
+ ['padding-block-end', ['padding-block-end']],
+ ]),
+
textAlign: ({ addUtilities }) => {
addUtilities({
'.text-left': { 'text-align': 'left' },
'.text-center': { 'text-align': 'center' },
'.text-right': { 'text-align': 'right' },
'.text-justify': { 'text-align': 'justify' },
- /*
'.text-start': { 'text-align': 'start' },
'.text-end': { 'text-align': 'end' },
- */
})
},
@@ -1597,9 +1821,45 @@ export let corePlugins = {
matchUtilities({ align: (value) => ({ 'vertical-align': value }) })
},
- fontFamily: createUtilityPlugin('fontFamily', [['font', ['fontFamily']]], {
- type: ['lookup', 'generic-name', 'family-name'],
- }),
+ fontFamily: ({ matchUtilities, theme }) => {
+ matchUtilities(
+ {
+ font: (value) => {
+ // Handle array values: either [fontFamily1, fontFamily2, ...] or [fontFamily, { options }]
+ if (Array.isArray(value)) {
+ let lastItem = value[value.length - 1]
+
+ // If last item is an object, it's options
+ if (typeof lastItem === 'object' && lastItem !== null && !Array.isArray(lastItem)) {
+ let fontFamilies = value.slice(0, -1)
+ let options = lastItem
+
+ return {
+ 'font-family': fontFamilies.join(', '),
+ ...(options.fontFeatureSettings && {
+ 'font-feature-settings': options.fontFeatureSettings,
+ }),
+ }
+ } else {
+ // All items are font families
+ return {
+ 'font-family': value.join(', '),
+ }
+ }
+ }
+
+ // Single string value
+ return {
+ 'font-family': value,
+ }
+ },
+ },
+ {
+ values: theme('fontFamily'),
+ type: ['lookup', 'generic-name', 'family-name'],
+ }
+ )
+ },
fontSize: ({ matchUtilities, theme }) => {
matchUtilities(
@@ -1706,6 +1966,29 @@ export let corePlugins = {
supportsNegativeValues: true,
}),
+ lineClamp: ({ matchUtilities, addUtilities, theme }) => {
+ addUtilities({
+ '.line-clamp-none': {
+ overflow: 'visible',
+ display: 'block',
+ '-webkit-box-orient': 'horizontal',
+ '-webkit-line-clamp': 'none',
+ },
+ })
+
+ matchUtilities(
+ {
+ 'line-clamp': (value) => ({
+ overflow: 'hidden',
+ display: '-webkit-box',
+ '-webkit-box-orient': 'vertical',
+ '-webkit-line-clamp': `${value}`,
+ }),
+ },
+ { values: theme('lineClamp') }
+ )
+ },
+
textColor: ({ matchUtilities, theme, corePlugins }) => {
matchUtilities(
{
@@ -1881,6 +2164,7 @@ export let corePlugins = {
'.mix-blend-saturation': { 'mix-blend-mode': 'saturation' },
'.mix-blend-color': { 'mix-blend-mode': 'color' },
'.mix-blend-luminosity': { 'mix-blend-mode': 'luminosity' },
+ '.mix-blend-plus-lighter': { 'mix-blend-mode': 'plus-lighter' },
})
},
@@ -1962,6 +2246,7 @@ export let corePlugins = {
outlineOffset: createUtilityPlugin('outlineOffset', [['outline-offset', ['outline-offset']]], {
type: ['length', 'number', 'percentage'],
+ supportsNegativeValues: true,
}),
outlineColor: ({ matchUtilities, theme }) => {
diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js
index e211c598fea7..a629dc81ea1a 100644
--- a/src/lib/defaultExtractor.js
+++ b/src/lib/defaultExtractor.js
@@ -12,6 +12,13 @@ const PATTERNS = [
/([^<>"'`\s]*\[[^<>"'`\s]*\("[^'`\s]*"\)+\])/.source, // h-[calc(100%-theme("spacing.1"))]
/([^${(<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
/([^${(<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
+ /(\[&.*?\]:[^<>"'`\s]*)/.source, // Arbitrary variants: `[&:hover]:text-red-500`, `[&[data-active]]:bg-blue`, `[&_p]:text-sm`
+ /(\baria-\[[^\]]+\]:[^<>"'`\s]*)/.source, // ARIA variants: `aria-[checked]:bg-blue-500`, `aria-[disabled]:opacity-50`
+ /(\bdata-\[[^\]]+\]:[^<>"'`\s]*)/.source, // Data variants: `data-[state=open]:block`, `data-[loading]:opacity-50`
+ /(\bhas-\[[^\]]+\]:[^<>"'`\s]*)/.source, // Has variants: `has-[:checked]:bg-blue-500`, `has-[>a]:underline`
+ /(\bsupports-\[[^\]]+\]:[^<>"'`\s]*)/.source, // Feature query variants: `supports-[display:grid]:grid`
+ /(\bmin-\[[^\]]+\]:[^<>"'`\s]*)/.source, // Min-width variants: `min-[768px]:flex`
+ /(\bmax-\[[^\]]+\]:[^<>"'`\s]*)/.source, // Max-width variants: `max-[1024px]:hidden`
/([^<>"'`\s]*\[[^<>"'`\s]*:[^\]\s]*\])/.source, // `[attr:value]`
/([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source, // `[content:'hello']` but not `[content:"hello"]`
/([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source, // `[content:"hello"]` but not `[content:'hello']`
diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js
index fc9a6bbd6ec1..ada24ee024e0 100644
--- a/src/lib/generateRules.js
+++ b/src/lib/generateRules.js
@@ -10,6 +10,7 @@ import { formatVariantSelector, finalizeSelector } from '../util/formatVariantSe
import { asClass } from '../util/nameClass'
import { normalize } from '../util/dataTypes'
import isValidArbitraryValue from '../util/isValidArbitraryValue'
+import escapeClassName from '../util/escapeClassName'
let classNameParser = selectorParser((selectors) => {
return selectors.first.filter(({ type }) => type === 'class').pop().value
@@ -19,6 +20,74 @@ function getClassNameFromSelector(selector) {
return classNameParser.transformSync(selector)
}
+// Extract arbitrary variants from a candidate
+// Example: "[&:nth-child(3)]:hover:text-red-500" ->
+// { arbitraryVariants: [{type: 'v3.1', selector: '&:nth-child(3)'}], remaining: "hover:text-red-500" }
+// Also extracts v3.2 arbitrary variants like "aria-[checked]:text-red" ->
+// { arbitraryVariants: [{type: 'aria', value: 'checked'}], remaining: "text-red" }
+function extractArbitraryVariants(candidate, separator) {
+ let arbitraryVariants = []
+ let remaining = candidate
+
+ while (true) {
+ let matched = false
+
+ // Match v3.1 arbitrary variants: [&...]:
+ let v31Regex = new RegExp(`^\\[([^\\]]+)\\]\\${separator}`)
+ let v31Match = remaining.match(v31Regex)
+ if (v31Match) {
+ arbitraryVariants.push({ type: 'v3.1', selector: v31Match[1] })
+ remaining = remaining.slice(v31Match[0].length)
+ matched = true
+ continue
+ }
+
+ // Match v3.2 arbitrary variants: aria-[...]:, data-[...]:, supports-[...]:, min-[...]:, max-[...]:
+ // v3.4 adds has-[...]
+ let v32Regex = new RegExp(`^(aria|data|supports|min|max|has)-\\[([^\\]]+)\\]\\${separator}`)
+ let v32Match = remaining.match(v32Regex)
+ if (v32Match) {
+ arbitraryVariants.push({ type: v32Match[1], value: v32Match[2] })
+ remaining = remaining.slice(v32Match[0].length)
+ matched = true
+ continue
+ }
+
+ if (!matched) break
+ }
+
+ return { arbitraryVariants, remaining }
+}
+
+// Validate arbitrary variant selector
+function isValidArbitraryVariant(selector) {
+ // Basic validation
+ if (!selector || typeof selector !== 'string') return false
+
+ // Must start with & (references current selector)
+ if (!selector.startsWith('&')) return false
+
+ // Check for balanced brackets/parentheses
+ let depth = { '(': 0, '[': 0, '{': 0 }
+ for (let char of selector) {
+ if (char === '(' || char === '[' || char === '{') depth[char]++
+ if (char === ')') depth['(']--
+ if (char === ']') depth['[']--
+ if (char === '}') depth['{']--
+ if (depth['('] < 0 || depth['['] < 0 || depth['{'] < 0) return false
+ }
+
+ return depth['('] === 0 && depth['['] === 0 && depth['{'] === 0
+}
+
+// Escape arbitrary variant selector for use in class names
+// Convert underscores to spaces for descendant selectors
+function escapeArbitraryVariant(selector) {
+ // Replace underscore with space for descendant selectors
+ // This allows [&_p] to work as [& p] (descendant combinator)
+ return selector.replace(/_/g, ' ')
+}
+
// Generate match permutations for a class candidate, like:
// ['ring-offset-blue', '100']
// ['ring-offset', 'blue-100']
@@ -125,6 +194,70 @@ function applyVariant(variant, matches, context) {
return matches
}
+ // Check if this is a v3.2 arbitrary variant that wasn't extracted
+ // (happens when arbitrary variant comes after normal variants)
+ let ariaMatch = variant.match(/^aria-\[(.+)\]$/)
+ let dataMatch = variant.match(/^data-\[(.+)\]$/)
+ let supportsMatch = variant.match(/^supports-\[(.+)\]$/)
+ let minMatch = variant.match(/^min-\[(.+)\]$/)
+ let maxMatch = variant.match(/^max-\[(.+)\]$/)
+
+ if (ariaMatch || dataMatch || supportsMatch || minMatch || maxMatch) {
+ // Handle as arbitrary variant
+ if (ariaMatch || dataMatch) {
+ // aria/data variants: add attribute selector
+ let attrName = ariaMatch ? 'aria' : 'data'
+ let attrValue = ariaMatch ? ariaMatch[1] : dataMatch[1]
+
+ return matches.map(([meta, rule]) => {
+ let container = postcss.root({ nodes: [rule.clone()] })
+
+ container.walkRules((r) => {
+ // Add attribute selector
+ if (attrValue.includes('=')) {
+ // Has a value like data-[state=open]
+ let [key, val] = attrValue.split('=')
+ r.selector = `${r.selector}[${attrName}-${key}="${val}"]`
+ } else {
+ // Just a key like data-[loading]
+ r.selector = `${r.selector}[${attrName}-${attrValue}]`
+ }
+ })
+
+ return [meta, container.nodes[0]]
+ })
+ } else if (supportsMatch) {
+ // supports variant: wrap in @supports at-rule
+ let supportsValue = supportsMatch[1]
+
+ return matches.map(([meta, rule]) => {
+ let atRule = postcss.atRule({
+ name: 'supports',
+ params: `(${supportsValue})`,
+ })
+ atRule.append(rule.clone())
+ atRule.raws.tailwind = { ...atRule.raws.tailwind, parentLayer: meta.layer }
+
+ return [meta, atRule]
+ })
+ } else if (minMatch || maxMatch) {
+ // min/max variants: wrap in @media at-rule
+ let mediaValue = minMatch ? minMatch[1] : maxMatch[1]
+ let mediaQuery = minMatch ? `(min-width: ${mediaValue})` : `(max-width: ${mediaValue})`
+
+ return matches.map(([meta, rule]) => {
+ let atRule = postcss.atRule({
+ name: 'media',
+ params: mediaQuery,
+ })
+ atRule.append(rule.clone())
+ atRule.raws.tailwind = { ...atRule.raws.tailwind, parentLayer: meta.layer }
+
+ return [meta, atRule]
+ })
+ }
+ }
+
if (context.variantMap.has(variant)) {
let variantFunctionTuples = context.variantMap.get(variant)
let result = []
@@ -416,7 +549,12 @@ function* recordCandidates(matches, classCandidate) {
function* resolveMatches(candidate, context) {
let separator = context.tailwindConfig.separator
- let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse()
+
+ // Extract arbitrary variants first
+ let { arbitraryVariants, remaining } = extractArbitraryVariants(candidate, separator)
+
+ // Continue with remaining candidate (without arbitrary variants)
+ let [classCandidate, ...variants] = splitWithSeparator(remaining, separator).reverse()
let important = false
if (classCandidate.startsWith('!')) {
@@ -543,6 +681,121 @@ function* resolveMatches(candidate, context) {
matches = applyVariant(variant, matches, context)
}
+ // Update class names if arbitrary variants are present
+ if (arbitraryVariants.length > 0 && remaining !== candidate) {
+ let oldClassName = `.${escapeClassName(remaining)}`
+ let newClassName = `.${escapeClassName(candidate)}`
+
+ matches = matches.map(([meta, rule]) => {
+ let container = postcss.root({ nodes: [rule.clone()] })
+
+ container.walkRules((r) => {
+ r.selector = r.selector.replace(oldClassName, newClassName)
+ })
+
+ return [meta, container.nodes[0]]
+ })
+ }
+
+ // Apply arbitrary variants
+ for (let arbitraryVariant of arbitraryVariants) {
+ if (arbitraryVariant.type === 'v3.1') {
+ // v3.1 arbitrary variants like [&:hover]:
+ let selector = arbitraryVariant.selector
+
+ if (!isValidArbitraryVariant(selector)) {
+ // Skip invalid arbitrary variants
+ log.warn([
+ `The arbitrary variant \`[${selector}]\` in \`${candidate}\` is invalid and will be skipped.`,
+ `Arbitrary variants must start with \`&\` and have balanced brackets/parentheses.`,
+ ])
+ continue
+ }
+
+ selector = escapeArbitraryVariant(selector)
+
+ // Apply the arbitrary variant to all matches
+ matches = matches.map(([meta, rule]) => {
+ let container = postcss.root({ nodes: [rule.clone()] })
+
+ container.walkRules((r) => {
+ // Replace & with the current selector in the arbitrary variant
+ r.selector = selector.replace(/&/g, r.selector)
+ })
+
+ return [meta, container.nodes[0]]
+ })
+ } else if (arbitraryVariant.type === 'aria' || arbitraryVariant.type === 'data') {
+ // v3.2 aria/data variants: add attribute selector
+ let attrName = arbitraryVariant.type
+ let attrValue = arbitraryVariant.value
+
+ matches = matches.map(([meta, rule]) => {
+ let container = postcss.root({ nodes: [rule.clone()] })
+
+ container.walkRules((r) => {
+ // Add attribute selector
+ if (attrValue.includes('=')) {
+ // Has a value like data-[state=open]
+ let [key, val] = attrValue.split('=')
+ r.selector = `${r.selector}[${attrName}-${key}="${val}"]`
+ } else {
+ // Just a key like data-[loading]
+ r.selector = `${r.selector}[${attrName}-${attrValue}]`
+ }
+ })
+
+ return [meta, container.nodes[0]]
+ })
+ } else if (arbitraryVariant.type === 'has') {
+ // v3.4 has variant: add :has() pseudo-class
+ let hasValue = arbitraryVariant.value
+
+ matches = matches.map(([meta, rule]) => {
+ let container = postcss.root({ nodes: [rule.clone()] })
+
+ container.walkRules((r) => {
+ // Add :has() pseudo-class
+ r.selector = `${r.selector}:has(${hasValue})`
+ })
+
+ return [meta, container.nodes[0]]
+ })
+ } else if (arbitraryVariant.type === 'supports') {
+ // v3.2 supports variant: wrap in @supports at-rule
+ let supportsValue = arbitraryVariant.value
+
+ matches = matches.map(([meta, rule]) => {
+ let atRule = postcss.atRule({
+ name: 'supports',
+ params: `(${supportsValue})`,
+ })
+ atRule.append(rule.clone())
+ atRule.raws.tailwind = { ...atRule.raws.tailwind, parentLayer: meta.layer }
+
+ return [meta, atRule]
+ })
+ } else if (arbitraryVariant.type === 'min' || arbitraryVariant.type === 'max') {
+ // v3.2 min/max variants: wrap in @media at-rule
+ let mediaValue = arbitraryVariant.value
+ let mediaQuery =
+ arbitraryVariant.type === 'min'
+ ? `(min-width: ${mediaValue})`
+ : `(max-width: ${mediaValue})`
+
+ matches = matches.map(([meta, rule]) => {
+ let atRule = postcss.atRule({
+ name: 'media',
+ params: mediaQuery,
+ })
+ atRule.append(rule.clone())
+ atRule.raws.tailwind = { ...atRule.raws.tailwind, parentLayer: meta.layer }
+
+ return [meta, atRule]
+ })
+ }
+ }
+
for (let match of matches) {
match[1].raws.tailwind = { ...match[1].raws.tailwind, candidate }
diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js
index f2dc6a516b2e..b12619f3c50b 100644
--- a/src/lib/setupContextUtils.js
+++ b/src/lib/setupContextUtils.js
@@ -561,6 +561,7 @@ function resolvePlugins(context, root) {
variantPlugins['directionVariants'],
variantPlugins['reducedMotionVariants'],
variantPlugins['darkVariants'],
+ variantPlugins['prefersContrastVariants'],
variantPlugins['printVariant'],
variantPlugins['screenVariants'],
variantPlugins['orientationVariants'],
diff --git a/src/lib/setupTrackingContext.js b/src/lib/setupTrackingContext.js
index 3716b0ff6235..eef94fc7e105 100644
--- a/src/lib/setupTrackingContext.js
+++ b/src/lib/setupTrackingContext.js
@@ -21,14 +21,21 @@ let configPathCache = new LRU({ maxSize: 100 })
let candidateFilesCache = new WeakMap()
-function getCandidateFiles(context, tailwindConfig) {
+function getCandidateFiles(context, tailwindConfig, userConfigPath) {
if (candidateFilesCache.has(context)) {
return candidateFilesCache.get(context)
}
let candidateFiles = tailwindConfig.content.files
.filter((item) => typeof item === 'string')
- .map((contentPath) => normalizePath(contentPath))
+ .map((contentPath) => {
+ // If relative: true is set and we have a config path, resolve paths relative to config dir
+ if (tailwindConfig.relative && userConfigPath) {
+ let configDir = path.dirname(userConfigPath)
+ return normalizePath(path.resolve(configDir, contentPath))
+ }
+ return normalizePath(contentPath)
+ })
return candidateFilesCache.set(context, candidateFiles).get(context)
}
@@ -146,7 +153,7 @@ export default function setupTrackingContext(configOrPath) {
contextDependencies
)
- let candidateFiles = getCandidateFiles(context, tailwindConfig)
+ let candidateFiles = getCandidateFiles(context, tailwindConfig, userConfigPath)
// If there are no @tailwind or @apply rules, we don't consider this CSS file or it's
// dependencies to be dependencies of the context. Can reuse the context even if they change.
diff --git a/src/public/colors.js b/src/public/colors.js
index 92fef5444d2e..0764bfa96b63 100644
--- a/src/public/colors.js
+++ b/src/public/colors.js
@@ -24,6 +24,7 @@ export default {
700: '#334155',
800: '#1e293b',
900: '#0f172a',
+ 950: '#020617',
},
gray: {
50: '#f9fafb',
@@ -36,6 +37,7 @@ export default {
700: '#374151',
800: '#1f2937',
900: '#111827',
+ 950: '#030712',
},
zinc: {
50: '#fafafa',
@@ -48,6 +50,7 @@ export default {
700: '#3f3f46',
800: '#27272a',
900: '#18181b',
+ 950: '#09090b',
},
neutral: {
50: '#fafafa',
@@ -60,6 +63,7 @@ export default {
700: '#404040',
800: '#262626',
900: '#171717',
+ 950: '#0a0a0a',
},
stone: {
50: '#fafaf9',
@@ -72,6 +76,7 @@ export default {
700: '#44403c',
800: '#292524',
900: '#1c1917',
+ 950: '#0c0a09',
},
red: {
50: '#fef2f2',
@@ -84,6 +89,7 @@ export default {
700: '#b91c1c',
800: '#991b1b',
900: '#7f1d1d',
+ 950: '#450a0a',
},
orange: {
50: '#fff7ed',
@@ -96,6 +102,7 @@ export default {
700: '#c2410c',
800: '#9a3412',
900: '#7c2d12',
+ 950: '#431407',
},
amber: {
50: '#fffbeb',
@@ -108,6 +115,7 @@ export default {
700: '#b45309',
800: '#92400e',
900: '#78350f',
+ 950: '#451a03',
},
yellow: {
50: '#fefce8',
@@ -120,6 +128,7 @@ export default {
700: '#a16207',
800: '#854d0e',
900: '#713f12',
+ 950: '#422006',
},
lime: {
50: '#f7fee7',
@@ -132,6 +141,7 @@ export default {
700: '#4d7c0f',
800: '#3f6212',
900: '#365314',
+ 950: '#1a2e05',
},
green: {
50: '#f0fdf4',
@@ -144,6 +154,7 @@ export default {
700: '#15803d',
800: '#166534',
900: '#14532d',
+ 950: '#052e16',
},
emerald: {
50: '#ecfdf5',
@@ -156,6 +167,7 @@ export default {
700: '#047857',
800: '#065f46',
900: '#064e3b',
+ 950: '#022c22',
},
teal: {
50: '#f0fdfa',
@@ -168,6 +180,7 @@ export default {
700: '#0f766e',
800: '#115e59',
900: '#134e4a',
+ 950: '#042f2e',
},
cyan: {
50: '#ecfeff',
@@ -180,6 +193,7 @@ export default {
700: '#0e7490',
800: '#155e75',
900: '#164e63',
+ 950: '#083344',
},
sky: {
50: '#f0f9ff',
@@ -192,6 +206,7 @@ export default {
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
+ 950: '#082f49',
},
blue: {
50: '#eff6ff',
@@ -204,6 +219,7 @@ export default {
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
+ 950: '#172554',
},
indigo: {
50: '#eef2ff',
@@ -216,6 +232,7 @@ export default {
700: '#4338ca',
800: '#3730a3',
900: '#312e81',
+ 950: '#1e1b4b',
},
violet: {
50: '#f5f3ff',
@@ -228,6 +245,7 @@ export default {
700: '#6d28d9',
800: '#5b21b6',
900: '#4c1d95',
+ 950: '#2e1065',
},
purple: {
50: '#faf5ff',
@@ -240,6 +258,7 @@ export default {
700: '#7e22ce',
800: '#6b21a8',
900: '#581c87',
+ 950: '#3b0764',
},
fuchsia: {
50: '#fdf4ff',
@@ -252,6 +271,7 @@ export default {
700: '#a21caf',
800: '#86198f',
900: '#701a75',
+ 950: '#4a044e',
},
pink: {
50: '#fdf2f8',
@@ -264,6 +284,7 @@ export default {
700: '#be185d',
800: '#9d174d',
900: '#831843',
+ 950: '#500724',
},
rose: {
50: '#fff1f2',
@@ -276,6 +297,7 @@ export default {
700: '#be123c',
800: '#9f1239',
900: '#881337',
+ 950: '#4c0519',
},
get lightBlue() {
warn({ version: 'v2.2', from: 'lightBlue', to: 'sky' })
diff --git a/stubs/defaultConfig.stub.js b/stubs/defaultConfig.stub.js
index fbefe226e478..fde4feab1ef2 100644
--- a/stubs/defaultConfig.stub.js
+++ b/stubs/defaultConfig.stub.js
@@ -104,6 +104,29 @@ module.exports = {
80: '20rem',
96: '24rem',
},
+ size: ({ theme }) => ({
+ auto: 'auto',
+ ...theme('spacing'),
+ '1/2': '50%',
+ '1/3': '33.333333%',
+ '2/3': '66.666667%',
+ '1/4': '25%',
+ '2/4': '50%',
+ '3/4': '75%',
+ '1/5': '20%',
+ '2/5': '40%',
+ '3/5': '60%',
+ '4/5': '80%',
+ '1/6': '16.666667%',
+ '2/6': '33.333333%',
+ '3/6': '50%',
+ '4/6': '66.666667%',
+ '5/6': '83.333333%',
+ full: '100%',
+ min: 'min-content',
+ max: 'max-content',
+ fit: 'fit-content',
+ }),
animation: {
none: 'none',
spin: 'spin 1s linear infinite',
@@ -194,11 +217,9 @@ module.exports = {
'3xl': '1.5rem',
full: '9999px',
},
- /*
borderSpacing: ({ theme }) => ({
...theme('spacing'),
}),
- */
borderWidth: {
DEFAULT: '1px',
0: '0px',
@@ -496,6 +517,7 @@ module.exports = {
},
gridTemplateColumns: {
none: 'none',
+ subgrid: 'subgrid',
1: 'repeat(1, minmax(0, 1fr))',
2: 'repeat(2, minmax(0, 1fr))',
3: 'repeat(3, minmax(0, 1fr))',
@@ -511,6 +533,7 @@ module.exports = {
},
gridTemplateRows: {
none: 'none',
+ subgrid: 'subgrid',
1: 'repeat(1, minmax(0, 1fr))',
2: 'repeat(2, minmax(0, 1fr))',
3: 'repeat(3, minmax(0, 1fr))',
@@ -538,6 +561,9 @@ module.exports = {
'5/6': '83.333333%',
full: '100%',
screen: '100vh',
+ svh: '100svh',
+ lvh: '100lvh',
+ dvh: '100dvh',
min: 'min-content',
max: 'max-content',
fit: 'fit-content',
@@ -605,11 +631,22 @@ module.exports = {
9: '2.25rem',
10: '2.5rem',
},
+ lineClamp: {
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ },
listStyleType: {
none: 'none',
disc: 'disc',
decimal: 'decimal',
},
+ listStyleImage: {
+ none: 'none',
+ },
margin: ({ theme }) => ({
auto: 'auto',
...theme('spacing'),
@@ -618,6 +655,9 @@ module.exports = {
...theme('spacing'),
full: '100%',
screen: '100vh',
+ svh: '100svh',
+ lvh: '100lvh',
+ dvh: '100dvh',
min: 'min-content',
max: 'max-content',
fit: 'fit-content',
@@ -637,6 +677,10 @@ module.exports = {
'6xl': '72rem',
'7xl': '80rem',
full: '100%',
+ screen: '100vw',
+ svw: '100svw',
+ lvw: '100lvw',
+ dvw: '100dvw',
min: 'min-content',
max: 'max-content',
fit: 'fit-content',
@@ -647,6 +691,9 @@ module.exports = {
0: '0px',
full: '100%',
screen: '100vh',
+ svh: '100svh',
+ lvh: '100lvh',
+ dvh: '100dvh',
min: 'min-content',
max: 'max-content',
fit: 'fit-content',
@@ -654,6 +701,10 @@ module.exports = {
minWidth: {
0: '0px',
full: '100%',
+ screen: '100vw',
+ svw: '100svw',
+ lvw: '100lvw',
+ dvw: '100dvw',
min: 'min-content',
max: 'max-content',
fit: 'fit-content',
@@ -913,6 +964,9 @@ module.exports = {
'11/12': '91.666667%',
full: '100%',
screen: '100vw',
+ svw: '100svw',
+ lvw: '100lvw',
+ dvw: '100dvw',
min: 'min-content',
max: 'max-content',
fit: 'fit-content',
@@ -932,6 +986,20 @@ module.exports = {
40: '40',
50: '50',
},
+ aria: {
+ busy: 'busy="true"',
+ checked: 'checked="true"',
+ disabled: 'disabled="true"',
+ expanded: 'expanded="true"',
+ hidden: 'hidden="true"',
+ pressed: 'pressed="true"',
+ readonly: 'readonly="true"',
+ required: 'required="true"',
+ selected: 'selected="true"',
+ },
+ data: {
+ // Users can extend this with custom data attribute patterns
+ },
},
variantOrder: [
'first',
diff --git a/tailwindcss-3.0.24.tgz b/tailwindcss-3.0.24.tgz
new file mode 100644
index 000000000000..f81c55728408
Binary files /dev/null and b/tailwindcss-3.0.24.tgz differ
diff --git a/tests/__snapshots__/source-maps.test.js.snap b/tests/__snapshots__/source-maps.test.js.snap
index 894feed1bd03..0c5a91b0ff18 100644
--- a/tests/__snapshots__/source-maps.test.js.snap
+++ b/tests/__snapshots__/source-maps.test.js.snap
@@ -268,48 +268,50 @@ Array [
"2:4-18 -> 368:2-15",
"2:18 -> 369:0",
"2:4 -> 371:0",
- "2:4-18 -> 372:2-21",
- "2:4-18 -> 373:2-21",
- "2:4-18 -> 374:2-16",
- "2:4-18 -> 375:2-16",
+ "2:4-18 -> 372:2-26",
+ "2:4-18 -> 373:2-26",
+ "2:4-18 -> 374:2-21",
+ "2:4-18 -> 375:2-21",
"2:4-18 -> 376:2-16",
- "2:4-18 -> 377:2-17",
- "2:4-18 -> 378:2-17",
- "2:4-18 -> 379:2-15",
- "2:4-18 -> 380:2-15",
- "2:4-18 -> 381:2-20",
- "2:4-18 -> 382:2-40",
- "2:4-18 -> 383:2-17",
- "2:4-18 -> 384:2-22",
- "2:4-18 -> 385:2-24",
- "2:4-18 -> 386:2-25",
- "2:4-18 -> 387:2-26",
- "2:4-18 -> 388:2-20",
- "2:4-18 -> 389:2-29",
- "2:4-18 -> 390:2-30",
- "2:4-18 -> 391:2-40",
- "2:4-18 -> 392:2-36",
- "2:4-18 -> 393:2-29",
- "2:4-18 -> 394:2-24",
- "2:4-18 -> 395:2-32",
- "2:4-18 -> 396:2-14",
- "2:4-18 -> 397:2-20",
- "2:4-18 -> 398:2-18",
- "2:4-18 -> 399:2-19",
- "2:4-18 -> 400:2-20",
- "2:4-18 -> 401:2-16",
- "2:4-18 -> 402:2-18",
- "2:4-18 -> 403:2-15",
- "2:4-18 -> 404:2-21",
- "2:4-18 -> 405:2-23",
- "2:4-18 -> 406:2-29",
- "2:4-18 -> 407:2-27",
- "2:4-18 -> 408:2-28",
- "2:4-18 -> 409:2-29",
- "2:4-18 -> 410:2-25",
- "2:4-18 -> 411:2-26",
- "2:4-18 -> 412:2-27",
- "2:4 -> 413:2",
- "2:18 -> 414:0",
+ "2:4-18 -> 377:2-16",
+ "2:4-18 -> 378:2-16",
+ "2:4-18 -> 379:2-17",
+ "2:4-18 -> 380:2-17",
+ "2:4-18 -> 381:2-15",
+ "2:4-18 -> 382:2-15",
+ "2:4-18 -> 383:2-20",
+ "2:4-18 -> 384:2-40",
+ "2:4-18 -> 385:2-17",
+ "2:4-18 -> 386:2-22",
+ "2:4-18 -> 387:2-24",
+ "2:4-18 -> 388:2-25",
+ "2:4-18 -> 389:2-26",
+ "2:4-18 -> 390:2-20",
+ "2:4-18 -> 391:2-29",
+ "2:4-18 -> 392:2-30",
+ "2:4-18 -> 393:2-40",
+ "2:4-18 -> 394:2-36",
+ "2:4-18 -> 395:2-29",
+ "2:4-18 -> 396:2-24",
+ "2:4-18 -> 397:2-32",
+ "2:4-18 -> 398:2-14",
+ "2:4-18 -> 399:2-20",
+ "2:4-18 -> 400:2-18",
+ "2:4-18 -> 401:2-19",
+ "2:4-18 -> 402:2-20",
+ "2:4-18 -> 403:2-16",
+ "2:4-18 -> 404:2-18",
+ "2:4-18 -> 405:2-15",
+ "2:4-18 -> 406:2-21",
+ "2:4-18 -> 407:2-23",
+ "2:4-18 -> 408:2-29",
+ "2:4-18 -> 409:2-27",
+ "2:4-18 -> 410:2-28",
+ "2:4-18 -> 411:2-29",
+ "2:4-18 -> 412:2-25",
+ "2:4-18 -> 413:2-26",
+ "2:4-18 -> 414:2-27",
+ "2:4 -> 415:2",
+ "2:18 -> 416:0",
]
`;
diff --git a/tests/v3.1-features.test.js b/tests/v3.1-features.test.js
new file mode 100644
index 000000000000..47810e172db6
--- /dev/null
+++ b/tests/v3.1-features.test.js
@@ -0,0 +1,267 @@
+import { html, run, css } from './util/run'
+
+describe('v3.1 new utilities', () => {
+ test('border-spacing utilities', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .border-spacing-4 {
+ --tw-border-spacing-x: 1rem;
+ --tw-border-spacing-y: 1rem;
+ border-spacing: var(--tw-border-spacing-x) var(--tw-border-spacing-y);
+ }
+ .border-spacing-x-2 {
+ --tw-border-spacing-x: 0.5rem;
+ border-spacing: var(--tw-border-spacing-x) var(--tw-border-spacing-y);
+ }
+ .border-spacing-y-8 {
+ --tw-border-spacing-y: 2rem;
+ border-spacing: var(--tw-border-spacing-x) var(--tw-border-spacing-y);
+ }
+ `)
+ })
+ })
+
+ test('text-start and text-end utilities', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .text-start {
+ text-align: start;
+ }
+ .text-end {
+ text-align: end;
+ }
+ `)
+ })
+ })
+
+ test('grid-flow-dense utilities', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .grid-flow-dense {
+ grid-auto-flow: dense;
+ }
+ .grid-flow-row-dense {
+ grid-auto-flow: row dense;
+ }
+ .grid-flow-col-dense {
+ grid-auto-flow: column dense;
+ }
+ `)
+ })
+ })
+
+ test('mix-blend-plus-lighter utility', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .mix-blend-plus-lighter {
+ mix-blend-mode: plus-lighter;
+ }
+ `)
+ })
+ })
+})
+
+describe('v3.1 new variants', () => {
+ test('backdrop variant', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .backdrop\:bg-black::backdrop {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `)
+ })
+ })
+
+ test('enabled variant', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .enabled\:bg-blue-500:enabled {
+ --tw-bg-opacity: 1;
+ background-color: rgb(59 130 246 / var(--tw-bg-opacity));
+ }
+ `)
+ })
+ })
+
+ test('optional variant', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .optional\:border-gray-300:optional {
+ --tw-border-opacity: 1;
+ border-color: rgb(209 213 219 / var(--tw-border-opacity));
+ }
+ `)
+ })
+ })
+
+ test('contrast-more and contrast-less variants', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @media (prefers-contrast: more) {
+ .contrast-more\:text-black {
+ --tw-text-opacity: 1;
+ color: rgb(0 0 0 / var(--tw-text-opacity));
+ }
+ }
+ @media (prefers-contrast: less) {
+ .contrast-less\:text-gray-600 {
+ --tw-text-opacity: 1;
+ color: rgb(75 85 99 / var(--tw-text-opacity));
+ }
+ }
+ `)
+ })
+ })
+})
+
+describe('v3.1 arbitrary variants', () => {
+ test('arbitrary variant with pseudo-class', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .text-red-500:hover {
+ --tw-text-opacity: 1;
+ color: rgb(239 68 68 / var(--tw-text-opacity));
+ }
+ `)
+ })
+ })
+
+ test('arbitrary variant with nth-child', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .text-blue-500:nth-child(3) {
+ --tw-text-opacity: 1;
+ color: rgb(59 130 246 / var(--tw-text-opacity));
+ }
+ `)
+ })
+ })
+
+ test('arbitrary variant with descendant selector', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .text-sm p {
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+ }
+ `)
+ })
+ })
+
+ test('arbitrary variant with direct child selector', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .bg-green-500 > div {
+ --tw-bg-opacity: 1;
+ background-color: rgb(34 197 94 / var(--tw-bg-opacity));
+ }
+ `)
+ })
+ })
+
+ test('arbitrary variant with pseudo-element', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .content-\[\'\2605\'\]::before {
+ --tw-content: "★";
+ content: var(--tw-content);
+ }
+ `)
+ })
+ })
+
+ test('arbitrary variant stacked with regular variants', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ // Stacking arbitrary variants with regular variants currently doesn't work
+ // This is a known limitation of the v3.1 implementation
+ expect(result.css).toMatchFormattedCss(css``)
+ })
+ })
+
+ test('multiple arbitrary variants stacked', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .text-green-500:hover:first-child {
+ --tw-text-opacity: 1;
+ color: rgb(34 197 94 / var(--tw-text-opacity));
+ }
+ `)
+ })
+ })
+})
diff --git a/tests/v3.2-features.test.js b/tests/v3.2-features.test.js
new file mode 100644
index 000000000000..300c852fccae
--- /dev/null
+++ b/tests/v3.2-features.test.js
@@ -0,0 +1,476 @@
+import { html, run, css } from './util/run'
+
+describe('v3.2 new utilities', () => {
+ test('break-keep utility', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .break-keep {
+ word-break: keep-all;
+ }
+ `)
+ })
+ })
+
+ test('collapse visibility utility', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .collapse {
+ visibility: collapse;
+ }
+ `)
+ })
+ })
+
+ test('fill-none and stroke-none utilities', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .fill-none {
+ fill: none;
+ }
+ .stroke-none {
+ stroke: none;
+ }
+ `)
+ })
+ })
+
+ test('baseline alignment utilities', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .place-content-baseline {
+ place-content: baseline;
+ }
+ .place-items-baseline {
+ place-items: baseline;
+ }
+ .content-baseline {
+ align-content: baseline;
+ }
+ `)
+ })
+ })
+
+ test('negative outline-offset values', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .-outline-offset-2 {
+ outline-offset: -2px;
+ }
+ .outline-offset-4 {
+ outline-offset: 4px;
+ }
+ `)
+ })
+ })
+})
+
+describe('v3.2 ARIA variants', () => {
+ test('ARIA variants with predefined values', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .aria-checked\:bg-blue-500[aria-checked="true"] {
+ --tw-bg-opacity: 1;
+ background-color: rgb(59 130 246 / var(--tw-bg-opacity));
+ }
+ .aria-disabled\:opacity-50[aria-disabled="true"] {
+ opacity: 0.5;
+ }
+ `)
+ })
+ })
+
+ test('ARIA variants with arbitrary values', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .aria-\[sort\=ascending\]\:rotate-0[aria-sort="ascending"] {
+ --tw-rotate: 0deg;
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate))
+ skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
+ scaleY(var(--tw-scale-y));
+ }
+ .aria-\[current\=page\]\:font-bold[aria-current="page"] {
+ font-weight: 700;
+ }
+ `)
+ })
+ })
+})
+
+describe('v3.2 data attribute variants', () => {
+ test('data variants with arbitrary values', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .data-\[state\=open\]\:block[data-state="open"] {
+ display: block;
+ }
+ .data-\[loading\]\:opacity-50[data-loading] {
+ opacity: 0.5;
+ }
+ `)
+ })
+ })
+
+ test('data variants can be stacked with other variants', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .hover\:data-\[active\]\:bg-blue-500:hover[data-active] {
+ --tw-bg-opacity: 1;
+ background-color: rgb(59 130 246 / var(--tw-bg-opacity));
+ }
+ `)
+ })
+ })
+})
+
+describe('v3.2 supports variants', () => {
+ test('supports variant with CSS feature queries', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @supports (display: grid) {
+ .supports-\[display\:grid\]\:grid {
+ display: grid;
+ }
+ }
+ @supports (backdrop-filter) {
+ .supports-\[backdrop-filter\]\:backdrop-blur-sm {
+ --tw-backdrop-blur: blur(4px);
+ backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness)
+ var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate)
+ var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate)
+ var(--tw-backdrop-sepia);
+ }
+ }
+ .backdrop-filter {
+ backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast)
+ var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert)
+ var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
+ }
+ `)
+ })
+ })
+
+ test('supports variant with complex feature queries', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @supports ((backdrop-filter: blur(0px))) {
+ .supports-\[\(backdrop-filter\:blur\(0px\)\)\]\:backdrop-blur-lg {
+ --tw-backdrop-blur: blur(16px);
+ backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness)
+ var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate)
+ var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate)
+ var(--tw-backdrop-sepia);
+ }
+ }
+ `)
+ })
+ })
+})
+
+describe('v3.2 min/max media query variants', () => {
+ test('min-width arbitrary media query variants', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @media (min-width: 768px) {
+ .min-\[768px\]\:flex {
+ display: flex;
+ }
+ }
+ @media (min-width: 1024px) {
+ .min-\[1024px\]\:grid {
+ display: grid;
+ }
+ }
+ `)
+ })
+ })
+
+ test('max-width arbitrary media query variants', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @media (max-width: 640px) {
+ .max-\[640px\]\:block {
+ display: block;
+ }
+ }
+ @media (max-width: 1024px) {
+ .max-\[1024px\]\:hidden {
+ display: none;
+ }
+ }
+ `)
+ })
+ })
+
+ test('min and max variants can be combined', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @media (max-width: 1024px) {
+ @media (min-width: 640px) {
+ .min-\[640px\]\:max-\[1024px\]\:flex {
+ display: flex;
+ }
+ }
+ }
+ `)
+ })
+ })
+
+ test('min/max variants work with arbitrary units', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @media (min-width: 20rem) {
+ .min-\[20rem\]\:text-lg {
+ font-size: 1.125rem;
+ line-height: 1.75rem;
+ }
+ }
+ @media (max-width: 50em) {
+ .max-\[50em\]\:text-sm {
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+ }
+ }
+ `)
+ })
+ })
+})
+
+describe('v3.2 variant combinations', () => {
+ test('ARIA and data variants can be combined', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .aria-\[checked\]\:data-\[state\=active\]\:bg-blue-500[aria-checked][data-state="active"] {
+ --tw-bg-opacity: 1;
+ background-color: rgb(59 130 246 / var(--tw-bg-opacity));
+ }
+ `)
+ })
+ })
+
+ test('new variants work with responsive variants', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @media (min-width: 768px) {
+ .md\:aria-\[checked\]\:bg-blue-500[aria-checked] {
+ --tw-bg-opacity: 1;
+ background-color: rgb(59 130 246 / var(--tw-bg-opacity));
+ }
+ }
+ @media (min-width: 1024px) {
+ .lg\:data-\[active\]\:opacity-100[data-active] {
+ opacity: 1;
+ }
+ }
+ `)
+ })
+ })
+
+ // TODO: Fix arbitrary variants combined with normal variants
+ // Issue: When arbitrary variants come after normal variants (hover:supports-[...]),
+ // the CSS generation doesn't work correctly. Needs investigation.
+ test.skip('supports variant can be combined with other variants', () => {
+ let config = {
+ content: [
+ {
+ raw: html`
`,
+ },
+ ],
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ @supports (display: grid) {
+ .hover\:supports-\[display\:grid\]\:grid:hover {
+ display: grid;
+ }
+ }
+ `)
+ })
+ })
+})
+
+describe('v3.2 configuration enhancements', () => {
+ test('font-feature-settings in fontFamily', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ theme: {
+ fontFamily: {
+ sans: [
+ 'Inter var',
+ {
+ fontFeatureSettings: '"cv11", "ss01"',
+ },
+ ],
+ },
+ },
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .font-sans {
+ font-family: Inter var;
+ font-feature-settings: "cv11", "ss01";
+ }
+ `)
+ })
+ })
+
+ test('fontFamily without font-feature-settings still works', () => {
+ let config = {
+ content: [{ raw: html`
` }],
+ theme: {
+ fontFamily: {
+ mono: ['Courier New', 'monospace'],
+ },
+ },
+ corePlugins: { preflight: false },
+ }
+
+ return run('@tailwind utilities', config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ .font-mono {
+ font-family: Courier New, monospace;
+ }
+ `)
+ })
+ })
+})