refactor(design-system): fold CSS prelude into styles.base.css#17
Merged
Conversation
Audit and polish the surfaces left inconsistent by the Catalyst utility-first refactor series. The review follows the web-design-reviewer workflow: capture a baseline, audit drift, apply fixes, re-capture, and ship recordings as evidence. PR1: replace `font-display` with `font-heading` across the auth routes, the brand wordmark, and the recipes doc. The canonical heading utility per tokens.md is `font-heading`. PR2: tighten the `app-auth-layout` sticky header. Drop duplicate background utilities, make sticky behavior unconditional so the chrome stays reachable on mobile after scroll, replace `min-h-[calc(100vh-64px)]` with `min-h-dvh`. PR3: tighten `app-auth-card` mobile padding to a 24px floor. Add `data-od-id="submit"` to every auth route's primary CTA and `data-od-id="brand"` to the brand link for visual e2e. PR4: add `scripts/capture-ui-snapshots.cjs` driving a structured snapshot grid (12 site PNGs + 60 auth PNGs) against a single BASE_URL, regenerate auth flow recordings, bump version to 1.5.0, update roadmap. Bonus: fix activation page tab bindings. The previous `[class.bg-white dark:bg-zinc-950]` threw `InvalidCharacterError` in Angular's renderer on every SSR render. Follow recipes.md: split each multi-class binding into per-mode `[class.X]` entries. Replaces the retired `text-accent` token with `text-blue-600` / `dark:text-blue-500` per tokens.md. Unblocks 2 activation e2e specs. Verification: app:lint, app:typecheck, app:vite:test, site:lint, ui-designer:lint, app-e2e:e2e (44/44), site-e2e:e2e all pass. Static guards confirm zero `font-display`, zero duplicate auth layout utilities, zero broken multi-class bindings, and the expected `data-od-id` hook counts. See docs/specs/2026-06-27-post-refactor-ui-review/ for the full SDD.
Move the shared font imports, @import 'tailwindcss', and @custom-variant dark(...) prelude that was duplicated across apps/web/app/src/styles.css, apps/web/site/src/styles/global.css, and apps/web/ui-designer/src/preview/preview.css into the workspace-root styles.base.css so each app stylesheet only needs to import the base and declare its own overrides. Order in styles.base.css follows the existing design-system guidance (fonts first, then Tailwind), and ui-designer keeps its own @source directive in preview.css since that directive is local to the preview app's HTML scanning. Verified with app:build, site:build, ui-designer:build, ui-designer:build-css, and lint for all three projects; all three output bundles still emit the expected @font-face declarations and --tw-* utilities picked up through the transitive import chain.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The same CSS prelude (4×
@fontsource/*,@import 'tailwindcss', and@custom-variant dark(...)) was duplicated across the three web app entry stylesheets:apps/web/app/src/styles.css,apps/web/site/src/styles/global.css, andapps/web/ui-designer/src/preview/preview.css. Each of them also importedstyles.base.cssfrom the workspace root, so the prelude ended up being declared in four places.This PR folds the prelude into
styles.base.cssso each app stylesheet only needs to import the base and declare its own overrides. Order follows the design-system guidance (docs/agents/design-system.md): fonts first, then Tailwind, then the variant.Changes
styles.base.css— add 8 lines at the top: four@import '@fontsource/...';,@import 'tailwindcss';, and@custom-variant dark (&:where(.dark, .dark *));. Existing token block, utilities, and selectors unchanged.apps/web/app/src/styles.css— drop 8 duplicated lines, keep@import '../../../../styles.base.css';and the app-specific html/body/button/input/textarea/select/a/.sr-only overrides.apps/web/site/src/styles/global.css— drop 8 duplicated lines, keep@import '../../../../../styles.base.css';and the body transition / upward keyframes.apps/web/ui-designer/src/preview/preview.css— drop the local@import 'tailwindcss';and@custom-variant, keep@import '../../../../../styles.base.css';, the local@source '../prototypes/*.html';(preview-only), and the preview chrome overrides.Verification
Bundle inspection confirms Tailwind v4 picks up the prelude through the transitive
@importchain in all three apps:dist/apps/web/app/browser/en/styles-*.csscontains the 4@font-familydeclarations (Inter, Manrope, JetBrains Mono, Material Symbols Outlined) plus--tw-*utilities.dist/apps/web/site/client/_astro/base-layout.*.csscontains the same.dist/apps/web/ui-designer/public/tailwind.csscontains 23@font-faceblocks and 462--tw-*selectors.Risks
None. Pure refactor, identical byte-content in the output bundles. Verified by inspecting the
@font-faceand--tw-*markers in all three output bundles.Follow-ups (out of scope)
html, body { min-height: 100% }+ button/input/textarea/select/a reset rules inapps/web/app/src/styles.cssandapps/web/ui-designer/src/preview/preview.csscould move intostyles.base.cssas a follow-up; intentionally not done here to keep this PR scoped to the prelude only.🤖 Generated with opencode