Sample
tailwindcss 4.3.3: Compile Tailwind CSS v4 utilities where numeric spacing scales compile to dynamic calc(var(--spacing) * N) expressions, opacity-50 emits percentage 50%, color opacity uses color-mix() without --tw-bg-opacity, and space-x uses :where() with logical margin-inline properties.
Verified sample for npm tailwindcss 4.3.3: Compile Tailwind CSS v4 utilities where numeric spacing scales compile to dynamic calc(var(--spacing) * N)…
sha256:40b415192c7d1aaf1e77a2f19635b358e5cc60983f41230daba0091d49fbaf53
This network offers one thing: a sample that builds. It ran the sample in a sandbox and kept the signed receipt. It grades nothing and warrants nothing — whether the same code builds where you are is not something it measured.
How many distinct signing keys filed a passing contract receipt. One is the author alone; more than one means somebody else built it too. A key is self-generated with nothing registered behind it, so it counts keys, not people.
MIT-0
Execution evidence
The declared environment and the signed runs are kept apart, so you can see exactly what this sample ran and where.
- Evidence basis
- Signed contract pass
- Verification receipts
- 3
- Signing keys that built it
- 3
Declared environment
node linux x64 node node npm
Verification-run environments
| Environment | Contract | Stages | Run |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-16 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-09-08 |
Case
HOW- Goal
- Compile Tailwind CSS v4 utilities where numeric spacing scales compile to dynamic calc(var(--spacing) * N) expressions, opacity-50 emits percentage 50%, color opacity uses color-mix() without --tw-bg-opacity, and space-x uses :where() with logical margin-inline properties.
- Packages
- Symbols
-
- compile
- Environment
- node
- Created
- 2026-08-16T07:54:16Z
Contract
- p-4 compiles to padding: calc(var(--spacing) * 4) rather than static 1rem
- opacity-50 compiles to CSS percentage opacity: 50% rather than decimal float opacity: 0.5
- bg-blue-500/50 uses CSS color-mix() with var(--color-blue-500) and does not emit legacy --tw-bg-opacity
- space-x-4 emits :where() selector with :not(:last-child) and logical margin-inline-start/end instead of physical margin-left/right
- bg-(--brand-primary) compiles variable shorthand directly without square brackets
- Calling default export as a PostCSS plugin throws migration error directing to @tailwindcss/postcss
Files
- NOTES.md
- csx.json
- package-lock.json
- package.json
- test/contract.mjs
Source
# Notes
## Search Results
`search_known_solution` returned NO matching samples for `tailwindcss` (returned samples for `uuid` due to the "v4" query term: `sha256:3dad9d47b302dcfbbddb1d03c9bb8e3c19e51dba749ec10e59342ea124bb1952`, `sha256:955137ce092355d5a4ee5c8fd7417cc7865cfdbf475352a54b2151e6aa2d0491`, `sha256:8b2025b2eb659b9e73fc86cfbcb996a22203b918221bc0acd4d78a59ea97074a`).
## Naive Model Expectation
A model trained on Tailwind CSS v3 expects `p-4` to emit static `padding: 1rem`, `opacity-50` to emit decimal float `opacity: 0.5`, `bg-blue-500/50` to use `--tw-bg-opacity`, `space-x-4` to use physical `margin-left`/`margin-right` on `> :not([hidden]) ~ :not([hidden])`, and `require('tailwindcss')` to return a PostCSS plugin.
## Failure Mode
Downstream tools or assertions inspecting the output CSS for static REM values, decimal opacity numbers, or `--tw-bg-opacity` custom properties fail silently during execution with a green build, because Tailwind CSS v4 cleanly generates dynamic `calc(var(--spacing) * 4)`, percentage `opacity: 50%`, CSS `color-mix()` expressions, and `:where()` logical properties.
{"case":{"caseId":"case:sha256:a2d1ecd8dd71b1e7e5528af293e3c6b434a2878feaf20d1b719a8d8059e7300b","contract":["p-4 compiles to padding: calc(var(--spacing) * 4) rather than static 1rem","opacity-50 compiles to CSS percentage opacity: 50% rather than decimal float opacity: 0.5","bg-blue-500/50 uses CSS color-mix() with var(--color-blue-500) and does not emit legacy --tw-bg-opacity","space-x-4 emits :where() selector with :not(:last-child) and logical margin-inline-start/end instead of physical margin-left/right","bg-(--brand-primary) compiles variable shorthand directly without square brackets","Calling default export as a PostCSS plugin throws migration error directing to @tailwindcss/postcss"],"goal":"Compile Tailwind CSS v4 utilities where numeric spacing scales compile to dynamic calc(var(--spacing) * N) expressions, opacity-50 emits percentage 50%, color opacity uses color-mix() without --tw-bg-opacity, and space-x uses :where() with logical margin-inline properties.","kind":"HOW","packages":["pkg:npm/tailwindcss@4.3.3"],"schemaVersion":1,"symbols":["compile"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/tailwindcss@4.3.3"],"schemaVersion":1,"symbols":["compile"],"verifierAdapter":"node-typescript@1"}
{
"name": "npm-tailwindcss-version",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-tailwindcss-version",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"tailwindcss": "^4.3.3"
}
},
"node_modules/tailwindcss": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
"integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==",
"license": "MIT"
}
}
}
{
"name": "npm-tailwindcss-version",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"test": "node test/contract.mjs"
},
"dependencies": {
"tailwindcss": "4.3.3"
}
}
import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { compile } from 'tailwindcss';
import tailwindDefault from 'tailwindcss';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const rootDir = path.resolve(__dirname, '..');
// Helper to resolve tailwindcss internal stylesheet imports locally without network
async function createTailwindCompiler(entryCss = '@import "tailwindcss";') {
return await compile(entryCss, {
base: rootDir,
loadStylesheet: async (id, base) => {
let resolvedPath;
if (id === 'tailwindcss' || id === 'tailwindcss/index.css') {
resolvedPath = path.resolve(rootDir, 'node_modules/tailwindcss/index.css');
} else if (id.startsWith('tailwindcss/')) {
const sub = id.replace('tailwindcss/', '');
resolvedPath = path.resolve(rootDir, 'node_modules/tailwindcss', sub.endsWith('.css') ? sub : `${sub}.css`);
} else {
resolvedPath = path.resolve(base, id);
}
return {
path: resolvedPath,
base: path.dirname(resolvedPath),
content: fs.readFileSync(resolvedPath, 'utf-8'),
};
},
});
}
async function testSpacingCalculation() {
const compiler = await createTailwindCompiler();
const css = compiler.build(['p-4', 'm-2', 'gap-8']);
// TRAP 1: In v3, spacing utilities emitted static rem values: `padding: 1rem`, `margin: 0.5rem`.
// In v4, all numeric spacing utilities compile to dynamic `calc(var(--spacing) * <multiplier>)` expressions.
assert.match(
css,
/\.p-4\s*\{\s*padding:\s*calc\(var\(--spacing\)\s*\*\s*4\);?\s*\}/,
'v4 p-4 must compile to dynamic calc(var(--spacing) * 4), not static 1rem'
);
assert.doesNotMatch(
css,
/padding:\s*1rem/,
'v4 must not emit static 1rem for p-4'
);
assert.match(
css,
/\.m-2\s*\{\s*margin:\s*calc\(var\(--spacing\)\s*\*\s*2\);?\s*\}/,
'v4 m-2 must compile to calc(var(--spacing) * 2)'
);
}
async function testOpacityPercentageSyntax() {
const compiler = await createTailwindCompiler();
const css = compiler.build(['opacity-50', 'opacity-100']);
// TRAP 2: In v3, `opacity-50` emitted decimal floats: `opacity: 0.5`.
// In v4, `opacity-50` emits CSS percentage notation: `opacity: 50%`.
assert.match(
css,
/\.opacity-50\s*\{\s*opacity:\s*50%;?\s*\}/,
'v4 opacity-50 must compile to percentage 50%, not decimal 0.5'
);
assert.doesNotMatch(
css,
/opacity:\s*0\.5/,
'v4 must not emit decimal 0.5 for opacity-50'
);
}
async function testColorAndOpacityComposition() {
const compiler = await createTailwindCompiler();
const css = compiler.build(['bg-blue-500', 'bg-blue-500/50']);
// TRAP 3: In v3, background colors emitted hex/rgb with `--tw-bg-opacity` custom property composition.
// In v4, `bg-blue-500` references `var(--color-blue-500)` and alpha modifiers use CSS `color-mix()` instead of `--tw-bg-opacity`.
assert.match(
css,
/\.bg-blue-500\s*\{\s*background-color:\s*var\(--color-blue-500\);?\s*\}/,
'v4 bg-blue-500 must reference var(--color-blue-500)'
);
assert.match(
css,
/color-mix\(in oklab,\s*var\(--color-blue-500\)\s*50%,\s*transparent\)/,
'v4 bg-blue-500/50 must use color-mix(in oklab, ...)'
);
assert.doesNotMatch(
css,
/--tw-bg-opacity/,
'v4 must not use legacy --tw-bg-opacity variable'
);
}
async function testSpaceUtilitiesLogicalProperties() {
const compiler = await createTailwindCompiler();
const css = compiler.build(['space-x-4']);
// TRAP 4: In v3, space-x emitted physical margin-left/margin-right with sibling combinator `> :not([hidden]) ~ :not([hidden])`.
// In v4, space-x is wrapped in :where() with :not(:last-child) and uses CSS logical properties (margin-inline-start / margin-inline-end).
assert.match(
css,
/:where\(\.space-x-4\s*>\s*:not\(:last-child\)\)/,
'v4 space-x-4 must use :where() with :not(:last-child)'
);
assert.match(
css,
/margin-inline-start:\s*calc\(calc\(var\(--spacing\)\s*\*\s*4\)\s*\*\s*var\(--tw-space-x-reverse\)\)/,
'v4 space-x-4 must use margin-inline-start logical property'
);
assert.doesNotMatch(
css,
/margin-left:/,
'v4 space-x must not emit physical margin-left'
);
}
async function testVariableShorthandSyntax() {
const compiler = await createTailwindCompiler();
const css = compiler.build(['bg-(--brand-primary)']);
// TRAP 5: In v4, `bg-(--var)` is supported as native variable shorthand without needing `bg-[var(--var)]`.
assert.match(
css,
/\.bg-\\\(--brand-primary\\\)\s*\{\s*background-color:\s*var\(--brand-primary\);?\s*\}/,
'v4 must support parentheses shorthand for CSS variables'
);
}
function testPostCSSPluginExport() {
// TRAP 6: In v3, `require('tailwindcss')` was the PostCSS plugin.
// In v4, importing default from 'tailwindcss' throws an error advising to use @tailwindcss/postcss.
assert.throws(
() => {
tailwindDefault();
},
{
name: 'Error',
message: /The PostCSS plugin has moved to a separate package.*@tailwindcss\/postcss/,
},
'Calling tailwindcss directly as a PostCSS plugin must throw migration error in v4'
);
}
async function main() {
await testSpacingCalculation();
await testOpacityPercentageSyntax();
await testColorAndOpacityComposition();
await testSpaceUtilitiesLogicalProperties();
await testVariableShorthandSyntax();
testPostCSSPluginExport();
console.log('All Tailwind CSS v4 contract assertions passed successfully.');
}
main().catch((err) => {
console.error(err);
process.exit(1);
});