Keep five responsibilities separate
An external token export, a runtime custom property, a Tailwind theme mapping, a generated utility, and a consuming component form a connected chain. They aren't interchangeable sources of truth. When a button looks wrong, changing the last declaration visible in DevTools may hide the mismatch while leaving the ownership error intact.
| Responsibility | Owned artifact | Acceptance question | |
|---|---|---|---|
| Upstream system | Semantic intent and mode-specific values | Versioned token source or export | Is the intended role current, approved, and present in every required mode? |
| Application loading | Import order, selector strategy, and runtime availability | Served external custom properties | Did the intended source version and selector-scoped values reach the inspected artifact? |
| Tailwind mapping | Namespace aliases and utility vocabulary | @theme declarations and generated rules | Does each mapping produce its expected declaration and utility? |
| Consumer | Use of shared roles and bounded exceptions | Classes, component CSS, and computed styles | Does each named surface resolve the expected value without an undeclared override? |
| Acceptance owner | Evidence review and disposition | Completed acceptance record | Does the evidence support accept, revise, or block? |
Do not promote an alias into the source
A Tailwind name can give the application a stable vocabulary without owning the design decision. When the external source changes, regenerate or update the mapping. Don't copy the same raw value into several @theme declarations and treat those copies as authoritative.
Use only the Tailwind v4 mechanics the handoff needs
Tailwind v4 uses CSS-first configuration. Theme-variable namespaces connect declarations to utility families. A color variable in the appropriate namespace can supply background, text, border, and related color utilities. Tailwind also exposes theme variables as CSS custom properties, depending on how they are declared and emitted.
When a Tailwind theme variable points to an external custom property, Tailwind documents the inline option for resolving that reference in the generated utility. The generated rule then refers directly to the external property. That property remains a runtime dependency, so it must be present in served CSS wherever the utility can apply.
@import "tailwindcss";
:root {
--source-action-background: oklch(0.62 0.17 252);
}
@theme inline {
--color-action: var(--source-action-background);
}<button class="bg-action">Save changes</button>For this fixture, expect a generated declaration equivalent to .bg-action { background-color: var(--source-action-background); }. The raw color stays in one external property. The Tailwind mapping supplies the vocabulary, while the generated rule preserves the runtime dependency.
Static controls emission, not authority
Use @theme static when the project contract requires every declared theme variable in generated CSS, including variables without detected utility usage. Static emission doesn't make Tailwind the owner of an upstream design decision.
@theme static {
--radius-control: 0.5rem;
}Separate contracts, expectations, observations, and decisions
The phrase "Tailwind supports this" can mean four different things. Keep the official framework contract, your project expectation, an environment-specific observation, and the acceptance decision in separate fields. A failure in one toolchain isn't a universal framework rule, and a clean build doesn't prove that the application served the intended CSS.
| Official contract | Project expectation | Environment observation | Acceptance decision | |
|---|---|---|---|---|
| CSS imports | Tailwind v4 advertises built-in import support | The application should load the selected upstream token CSS | Clearly Design reports a missing served import in particular Nuxt and Next.js setups | Inspect this project's served output and revise loading if required properties are absent |
| Inline mapping | @theme inline can place an external-variable reference in a generated utility | bg-action should reference --source-action-background | Record the generated declaration and the runtime property's selector-scoped presence | Block if the rule or its runtime dependency is absent |
| Runtime values | Theme variables and referenced custom properties participate in runtime CSS resolution | The action role should resolve to the recorded mode value | Record the computed background color on every named consumer in both modes | Accept only when observations match expectations |
| Static emission | @theme static requests generation of all declared theme variables | A named non-class consumer may require an otherwise unused variable | Record whether the required variable exists in the inspected artifact | Revise if the contract requires the variable and the artifact omits it |
Treat the Clearly Design report as diagnostic evidence tied to a specific approach, date, and environment: its build appeared healthy while the served output lacked the expected token CSS. Tailwind's official release material separately documents built-in import support. Neither fact determines what your framework served. Inspect the exact artifact used by your application.
Choose the narrowest layer that owns the decision
| Put it here when | Do not put it here when | Evidence to record | |
|---|---|---|---|
| Upstream source | The value expresses portable design intent or a shared semantic role | It exists only to satisfy one framework or local component | Source version, semantic role, modes, and decision owner |
| Global runtime CSS | A custom property is referenced at runtime by an inline-generated utility, non-Tailwind CSS, inline styles, or another consumer | A verified build step has materialized the value and the served output contains no runtime reference to the external property | Load path, required selector scope, import order, runtime dependency name, and served-artifact presence |
| @theme mapping | A Tailwind namespace should expose the role through a stable utility vocabulary | The behavior is contextual and has no stable utility meaning | External identifier, namespace, expected generated declaration, expected utility, and mapping owner |
| Project custom CSS | A documented project behavior does not fit ordinary theme or utility constraints | A standard theme variable or utility already expresses it clearly | Selector scope, consumers, reason, protected surfaces, and owner |
| Component or layout | A named consumer owns independent behavior or a bounded exception | Several unrelated consumers should change together | Component contract, states, scope, owner, and exit condition |
Let the required change scope determine placement. If an action background must change across buttons, selected navigation, and other action surfaces together, keep the meaning semantic. If only one promotional card may differ, record a card-level exception instead of redefining the global action role.
Copy the source-to-consumer worksheet
Create one record for every disputed or release-critical mapping. The record below includes the fields needed to trace both build output and runtime resolution. Its identifiers, values, consumers, and owners are illustrative project fixtures.
record_id: action-background-001
source_version: demo-kit@2026-09-09
semantic_role: action background
mode_values:
light:
upstream_identifier: --source-action-background
expected_value: oklch(0.62 0.17 252)
dark:
upstream_identifier: --source-action-background
expected_value: oklch(0.74 0.13 252)
tailwind_namespace: --color-*
theme_mapping: --color-action -> var(--source-action-background)
mapping_directive: "@theme inline"
mapping_owner: frontend platform
runtime_dependency: --source-action-background
runtime_scope_expectation:
light: ':root and [data-theme="light"]'
dark: '[data-theme="dark"]'
expected_utility: bg-action
expected_generated_declaration: 'background-color: var(--source-action-background)'
utility_evidence:
expected_present: true
observed_present: pending inspection
named_consumers:
- primary save button
- selected navigation item
consumer_observations:
light:
expected: recorded light value
observed: pending
dark:
expected: recorded dark value
observed: pending
evidence_status: pending inspection
protected_surfaces:
destructive_button:
light: { expected: recorded baseline, observed: pending }
dark: { expected: recorded baseline, observed: pending }
informational_badge:
light: { expected: recorded baseline, observed: pending }
dark: { expected: recorded baseline, observed: pending }
declared_exceptions: []
correction_owner: design systems engineer
final_disposition: pendingUse expected, observed, contradicted, unresolved, or accepted for evidence status. "The build passed" isn't a mapping status. It doesn't identify the source version, prove the generated rule exists, establish that the runtime dependency loaded, or show what a consumer computed.
Map light and dark values behind one stable utility
The consuming application owns its mode selectors. In this bounded fixture, a data attribute changes the value behind one stable external identifier. Tailwind maps that identifier once, so components keep using bg-action in either mode.
:root,
[data-theme="light"] {
--source-action-background: oklch(0.62 0.17 252);
}
[data-theme="dark"] {
--source-action-background: oklch(0.74 0.13 252);
}
@theme inline {
--color-action: var(--source-action-background);
}<button class="bg-action">Save changes</button>First, inspect the generated bg-action rule. It should contain the recorded reference to --source-action-background. Next, activate the explicit light selector and record the button's computed background-color. Repeat under the explicit dark selector. Compare both observations with the worksheet instead of deciding that the colors merely look plausible.
The selector does not define theme policy
This fixture covers only explicit selector resolution. The application still owns operating-system preference, default selection, persistence, initialization flash prevention, nested theme behavior, selector precedence, import order, and overrides.
Token specimen · real values
Ambient Sage
Live renderAmbient Sage's actual tokens — the same values its exports use.
The public Ambient Sage page establishes a real upstream artifact with semantic light and dark roles and a Tailwind CSS v4 export. It doesn't establish your application's selector strategy, file order, aliases, consumers, overrides, or observed results. Record those in the consuming project's worksheet.
Inspect a real semantic kit before mapping it
Use Ambient Sage to examine a published token system, then record the exact roles and runtime dependencies your Tailwind application will consume.
Classify responsive variation before implementing it
Responsive values don't have one universal home. The unresolved Tailwind discussion about responsive design tokens captures the tension: repeated breakpoint classes burden consumers, while a global responsive property can hide context and change more surfaces than intended. Before choosing syntax, classify the decision by meaning, scope, consumers, and owner.
| Placement signal | Required scope record | Failure condition | |
|---|---|---|---|
| Semantic intent | The meaning should change coherently for every legitimate consumer under the same condition | Condition, all consumers, source owner, and protected roles | One consumer needs independent behavior, showing that the global meaning is too broad |
| Layout policy | A page region or layout system owns the adaptation | Container or viewport condition, affected regions, layout owner, and exceptions | The rule leaks into a component used outside that layout |
| Breakpoint utility | Consumers may choose the variation independently and should show it at each use | Breakpoint, named consumers, permitted combinations, and code owner | Required consumers repeat inconsistent variants or omit a required state |
| Component contract | One component owns responsive behavior across supported placements | Component, variants, conditions, states, and component owner | Detached instances or local overrides contradict the shared contract |
A responsive spacing role applied identically to every page section may belong upstream or in layout policy. A card that changes composition inside a narrow container may own that behavior. A one-off marketing arrangement may be clearest as explicit breakpoint utilities. Recording the scope makes the decision reviewable; the category name alone doesn't settle the architecture.
Run a reproducible acceptance record
Freeze expectations before inspecting anything. Use content that exposes ordinary and edge behavior: a primary save button, the same action with a long label, a selected navigation item, a destructive action, and an informational badge. Inspect both explicit modes in the same immutable built artifact.
- 1
Freeze the source and mapping
Record the exact upstream version, mode values, external identifiers, runtime selector scopes, @theme declarations, expected generated rules, expected utilities, consumers, owners, and exceptions.
- 2
Inspect the built and served artifact
Confirm that the intended source version, required runtime properties, expected generated declarations, and required static variables are present in the asset the application actually serves.
- 3
Record utility evidence
For each required utility, record whether the expected declaration is present and whether it references the expected runtime dependency.
- 4
Inspect representative consumers
In each mode, record the computed value for the primary save button and selected navigation item. Compare each observation with its recorded expectation.
- 5
Inspect protected surfaces
Record expected and observed values for the destructive button and informational badge in both modes. Treat an unexplained difference as a failure.
- 6
Route every mismatch
Send a wrong source value upstream, a missing runtime property to application loading, a missing generated rule to the Tailwind mapping, and a local conflict to the component or exception owner.
- 7
Choose the disposition
Accept only when all required evidence matches. Revise a bounded mismatch with a known correction owner. Block when a required artifact, mode, observation, exception, or owner remains unresolved.
acceptance_id: tailwind-token-handoff-001
execution_context:
tailwind_version: record exact installed v4 version
application_build: record immutable build identifier
source_version: record exact upstream artifact version
built_artifact:
location: record inspected served CSS asset
runtime_dependency: --source-action-background
runtime_dependency_presence:
light_scope: { expected: present, observed: pending }
dark_scope: { expected: present, observed: pending }
utility_evidence:
bg-action:
expected_present: true
observed_present: pending
expected_declaration: 'background-color: var(--source-action-background)'
observed_declaration: pending
mode_matrix:
light:
selector: '[data-theme="light"]'
primary_save_button:
expected: recorded light action value
observed: pending computed background-color
selected_navigation_item:
expected: recorded light action value
observed: pending computed background-color
dark:
selector: '[data-theme="dark"]'
primary_save_button:
expected: recorded dark action value
observed: pending computed background-color
selected_navigation_item:
expected: recorded dark action value
observed: pending computed background-color
protected_surfaces:
destructive_button:
light: { expected: recorded light baseline, observed: pending }
dark: { expected: recorded dark baseline, observed: pending }
informational_badge:
light: { expected: recorded light baseline, observed: pending }
dark: { expected: recorded dark baseline, observed: pending }
representative_content:
- Save changes
- A deliberately long primary-action label
declared_exceptions:
- record selector, reason, scope, owner, and removal condition
unresolved_behavior:
- record responsive classification or selector-precedence questions
correction_owners:
upstream_value: design system owner
application_loading: frontend platform owner
tailwind_mapping: frontend platform owner
component_override: component owner
failure_conditions:
- wrong or unknown source version
- runtime dependency absent from a required selector scope
- expected utility or generated declaration absent
- generated declaration references the wrong dependency
- either mode resolves to the wrong recorded value
- a protected surface differs from its expected baseline without an approved exception
- an exception or unresolved mismatch has no owner
disposition: block until every required observation is recordedLet the record determine the final decision. Accept when the exact source version reaches the served artifact, every runtime dependency exists in its required scope, the expected utilities and declarations are present, both modes produce the recorded consumer values, and protected surfaces match their baselines. Revise a mismatch when its layer and owner are known. Block when the evidence or responsibility remains unclear.
Sources
- Tailwind CSS v4.0 - Tailwind CSS: Tailwind CSS v4 introduced CSS-first configuration, built-in import support, and native CSS-variable exposure for design tokens.
- Theme variables - Core concepts - Tailwind CSS: Tailwind documents theme-variable namespaces, utility generation, runtime variables, inline reference behavior, and static emission.
- Adding custom styles - Core concepts - Tailwind CSS: Tailwind documents custom CSS as a project-specific surface when ordinary theme variables and utilities do not fit a requirement.
- Wiring design tokens through Tailwind v4 (Nuxt and Next): This implementation account reports an import failure in particular Nuxt and Next.js setups and demonstrates inspecting served CSS instead of relying on build completion.
- How to make design tokens responsive in Tailwind 4?: The discussion records an unresolved question about repeating responsive variation at consumers versus representing it through a shared token mechanism.
- Ambient Sage Design Kit: The public Ambient Sage kit provides semantic light and dark roles and a Tailwind CSS v4 export as an upstream implementation artifact.