Delete Tailwind's half and build the Workbench without it

Plan step 39 (parts 1-3, folded into one commit: PHP tests read the
deleted files directly, so they cannot land apart from it). Tailwind
leaves the whole stack:

- Delete resources/css/tailwind.css, tokens/theme.css and
  tokens/utilities.css. Neither token file declared an --md-sys-*
  custom property of its own (both only referenced tokens declared
  elsewhere), so nothing loses a value; the md-* interaction and text
  classes already mirror utilities.css's declarations exactly
  (foundation/interaction.css, text.css).
- npm uninstall tailwindcss @tailwindcss/vite; vite.config.js drops the
  plugin and its import; composer.json drops the tailwindcss keyword
  (no lock change — keywords are outside Composer's content hash).
- The Workbench now builds one CSS entry, workbench/resources/css/app.css
  (all.css, showcase.css and the scheme; package.css is folded in and
  removed) instead of two, used by ErrorPage::assets() and every
  browser-test probe page's raw @vite() call; the showcase's own pages
  still take their CSS from the bundle route.
- TokensTest and StylesheetsTest: the two facts theme.css and
  utilities.css carried (every scheme role becomes a colour, resolved
  on the element; md-type-* matches the type-* utilities) are asserted
  directly against the scheme and text.css now that there is no second
  copy to cross-check; StylesheetsTest gained a full-tree scan (every
  .css file under resources/css/ is reached from all.css or
  showcase.css, no exclusions left for Tailwind); the Workbench-entry
  test and every "moved out of tailwind.css" assertion updated for the
  single entry and its removal.
- DesignGuard.php's comments and the development skill's setup section
  no longer name the deleted files or a second Tailwind entry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-15 06:49:03 +02:00
co-authored by Claude Sonnet 5
parent cfc57a9867
commit f21943746e
24 changed files with 109 additions and 1310 deletions
+15 -20
View File
@@ -37,14 +37,15 @@ function typeStyles(): array
}
/**
* The body of every `@utility type-…` block, keyed by utility name. The utilities live in
* tokens/utilities.css, apart from the tokens, so the foundation imports no Tailwind directive.
* The body of every `.md-type-…` class in text.css, keyed by class name without the `md-` prefix
* (`type-display-lg`, `type-emphasized-display-lg`, …). Plain CSS now (plan step 39 deleted the
* Tailwind utilities they used to be); text.css is theirs alone.
*
* @return array<string, string>
*/
function typeUtilities(): array
{
preg_match_all('/@utility (type-[\w-]+) \{\n(.*?)\n\}/s', File::get(packageCss('tokens/utilities.css')), $matches, PREG_SET_ORDER);
preg_match_all('/\.md-(type-[\w-]+) \{\n(.*?)\n {4}\}/s', File::get(packageCss('text.css')), $matches, PREG_SET_ORDER);
return array_combine(array_column($matches, 1), array_column($matches, 2));
}
@@ -84,26 +85,20 @@ it('ships M3\'s medium and high contrast levels beside the standard one', functi
}
});
it('turns every role into a Tailwind colour', function () {
$roles = array_keys(json_decode(File::get(packageCss('tokens/scheme.json')), true)['light']);
$theme = File::get(packageCss('tokens/theme.css'));
foreach ($roles as $role) {
expect($theme)->toContain("--color-{$role}: var(--md-sys-color-{$role});");
// Tailwind's theme.css used to turn every scheme role into a `--color-*` Tailwind colour, in an
// inline theme block so it resolved on the element and a nested data-theme still repainted it
// rather than reading a value computed once on :root. Both went with Tailwind (plan step 39): the
// first fact is already the scheme test above (every role a `--md-sys-color-*` custom property,
// light and dark); the second no longer has anything to hold, because no file replaces theme.css's
// alias — every package rule reads `--md-sys-color-*` directly at its point of use, so there is no
// second custom property that could be computed once on :root and go stale under a nested
// data-theme in the first place.
it('never aliases a colour role to a second custom property resolved once on :root', function () {
foreach (File::allFiles(packageCss()) as $file) {
expect($file->getContents())->not->toMatch('/--color-[\w-]+:\s*var\(--md-sys-color-/', $file->getRelativePathname());
}
});
it('resolves colour utilities on the element, so a nested data-theme repaints them', function () {
$theme = File::get(packageCss('tokens/theme.css'));
preg_match_all('/@theme inline \{(.*?)\}/s', $theme, $inline);
expect(implode("\n", $inline[1]))
->toContain('--color-primary: var(--md-sys-color-primary);')
->toContain('--color-body: var(--md-sys-color-on-surface-variant);')
->not->toMatch('/--[\w-]+:\s*#/');
});
it('leaves the choice of theme and of contrast to the head script, never to a media query', function () {
foreach (File::allFiles(packageCss()) as $file) {
expect($file->getContents())