From d5c71832f5bef3135090285965d17f59de530472 Mon Sep 17 00:00:00 2001 From: Hermes BUILD <48018975+nujovich@users.noreply.github.com> Date: Thu, 13 Aug 2026 06:54:13 +0200 Subject: [PATCH 1/5] chore(mint): scaffold BUILD-PLAN for modern CSS feature adoption scan --- BUILD-PLAN-issue-13.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 BUILD-PLAN-issue-13.md diff --git a/BUILD-PLAN-issue-13.md b/BUILD-PLAN-issue-13.md new file mode 100644 index 0000000..08b1ceb --- /dev/null +++ b/BUILD-PLAN-issue-13.md @@ -0,0 +1,12 @@ +# BUILD-PLAN-issue-13.md — Modern CSS feature adoption scan + +**Card:** https://github.com/nujovich/mint-radar/issues/13 + +**Decision:** PLAN already defined 4 concrete code milestones (planned). Decision not required. + +## Milestones + +- [ ] Milestone 1 — Extend audit prompt in lib/prompts.mjs with STEP 14: modern CSS feature scan (detect @property, @layer, @container, @supports, nesting, color-mix, @scope, :has()), report presence/absence with adoption suggestions +- [ ] Milestone 2 — Add modernFeatures field to AuditReport type in lib/types.ts (Record) +- [ ] Milestone 3 — Wire modern features results in playground UI as "Modern CSS Adoption" section +- [ ] Milestone 4 — Add test fixture with modern and legacy CSS and tests in lib/**tests**/ From 398f4dc04308025a208c373650500e2e0531f8fb Mon Sep 17 00:00:00 2001 From: Hermes BUILD <48018975+nujovich@users.noreply.github.com> Date: Thu, 13 Aug 2026 07:00:09 +0200 Subject: [PATCH 2/5] feat(mint): add modern CSS feature adoption scan to audit prompt --- lib/__tests__/prompts.test.mjs | 4 +++- lib/prompts.mjs | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/lib/__tests__/prompts.test.mjs b/lib/__tests__/prompts.test.mjs index 0edee3b..15e3753 100644 --- a/lib/__tests__/prompts.test.mjs +++ b/lib/__tests__/prompts.test.mjs @@ -153,7 +153,7 @@ describe('buildAuditPrompt', () => { expect(content).toContain('') }) - it('includes all thirteen analysis steps', () => { + it('includes all fourteen analysis steps', () => { const content = buildAuditPrompt(css).content expect(content).toContain('STEP 1') expect(content).toContain('STEP 2') @@ -168,6 +168,7 @@ describe('buildAuditPrompt', () => { expect(content).toContain('STEP 11') expect(content).toContain('STEP 12') expect(content).toContain('STEP 13') + expect(content).toContain('STEP 14') }) it('covers all required JSON output fields in the example', () => { @@ -181,6 +182,7 @@ describe('buildAuditPrompt', () => { expect(content).toContain('"lineHeights"') expect(content).toContain('"motion"') expect(content).toContain('"propertyTypeIssues"') + expect(content).toContain('"modernFeatures"') }) it('includes all allowed semantic color names', () => { diff --git a/lib/prompts.mjs b/lib/prompts.mjs index e90d3ee..d13152b 100644 --- a/lib/prompts.mjs +++ b/lib/prompts.mjs @@ -242,7 +242,26 @@ Scan every var() usage of a registered property for a fallback whose type contra 13c. FOREIGN CONTEXT USAGE A registered property assigned to a CSS property its declared syntax cannot satisfy — a property used in \`color\`, or a property used in \`width\`. Report only when the mismatch is unambiguous from this stylesheet alone; skip any var() whose value may come from another stylesheet or from JavaScript. Record these with "rule": "property-type-mismatch" and "severity": "suggestion". -Only report up to 8 propertyTypeIssues total. Prioritize invalid-initial-value, then fallback-type-mismatch, then property-type-mismatch. If the CSS contains no @property registrations, record an empty array. +Only report up to 8 propertyTypeIssues total. Prioritize invalid-initial-value, then fallback-type-mismatch, then property-type-mismatch. If the CSS contains no @property registrations, record an empty array. + +STEP 14 — MODERN CSS FEATURE SCAN +Scan the CSS source for usage of modern CSS features. For each feature id below, detect whether the feature is present (used) or absent, and record it in the "modernFeatures" object with: +- "used": true when the feature appears anywhere in the CSS source, false when it does not +- "suggestion": include ONLY when "used" is false — a one-sentence adoption recommendation where the feature would apply (omit this field entirely when "used" is true) + +Feature ids and what to detect: +- "property": @property at-rules registering typed custom properties +- "layer": @layer cascade layers (statement or block form) +- "container": @container queries or container-type / container-name declarations +- "supports": @supports feature-query blocks +- "nesting": native CSS nesting (a style rule nested inside another rule, with or without the & selector) +- "color-mix": color-mix() function usage +- "scope": @scope at-rules for scoped styles +- "has": the :has() relational pseudo-class + +Record all eight feature ids every time, even when used is false. Suggestions are informational only and never contribute to the chaos score. + + Return ONLY a valid JSON object matching the structure in the example below. No markdown fences, no backticks, no text before or after the JSON. @@ -316,7 +335,17 @@ Return ONLY a valid JSON object matching the structure in the example below. No { "selector": "@property --spacing-unit", "property": "initial-value", "rule": "invalid-initial-value", "severity": "warning", "reason": "Registered as \`\` but \`initial-value: red\` is a \`\` — the browser rejects this registration entirely", "propertyName": "--spacing-unit", "declaredSyntax": "" }, { "selector": ".button", "property": "background-color", "rule": "fallback-type-mismatch", "severity": "warning", "reason": "\`--my-color\` is registered as \`\` but falls back to \`14px\` — the fallback can never apply", "propertyName": "--my-color", "declaredSyntax": "" }, { "selector": ".card", "property": "color", "rule": "property-type-mismatch", "severity": "suggestion", "reason": "\`--spacing-unit\` is registered as \`\` but is used as a color value", "propertyName": "--spacing-unit", "declaredSyntax": "" } - ] + ], + "modernFeatures": { + "property": { "used": true }, + "layer": { "used": false, "suggestion": "No @layer rules found — consider organizing the cascade into reset, base, components, and utilities layers" }, + "container": { "used": false, "suggestion": "No container queries found — consider @container for component-responsive behavior instead of media queries" }, + "supports": { "used": true }, + "nesting": { "used": false, "suggestion": "No CSS nesting found — consider native nesting to reduce selector repetition and improve readability" }, + "color-mix": { "used": false, "suggestion": "No color-mix() usage found — consider it for runtime color derivation instead of precomputed color shades" }, + "scope": { "used": false, "suggestion": "No @scope rules found — consider scoping component styles with @scope to avoid selector leakage" }, + "has": { "used": true } + } } ` From fe548385dd9325f4bc0999b025535fe75e6deaf1 Mon Sep 17 00:00:00 2001 From: Hermes BUILD <48018975+nujovich@users.noreply.github.com> Date: Fri, 14 Aug 2026 06:51:47 +0200 Subject: [PATCH 3/5] feat(mint): add modernFeatures field to audit report type --- lib/types.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/types.ts b/lib/types.ts index 7171834..df93672 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -169,6 +169,22 @@ export interface PropertyTypeIssue { declaredSyntax: string // the @property syntax descriptor, e.g. '' } +export interface ModernFeatureStatus { + used: boolean + suggestion?: string +} + +export interface ModernFeatures { + property: ModernFeatureStatus // @property at-rules registering typed custom properties + layer: ModernFeatureStatus // @layer cascade layers (statement or block form) + container: ModernFeatureStatus // @container queries / container-type / container-name + supports: ModernFeatureStatus // @supports feature-query blocks + nesting: ModernFeatureStatus // native CSS nesting + 'color-mix': ModernFeatureStatus // color-mix() function usage + scope: ModernFeatureStatus // @scope at-rules for scoped styles + has: ModernFeatureStatus // :has() relational pseudo-class +} + export interface AuditReport { brand: string chaosScore: number @@ -183,6 +199,7 @@ export interface AuditReport { adoptionSuggestions?: AdoptionSuggestion[] overflowSafetyIssues?: OverflowSafetyIssue[] propertyTypeIssues?: PropertyTypeIssue[] + modernFeatures?: ModernFeatures } export interface ColorDecision { From 5dfeb54a2468f89f86352d81c0ed6fcdaec7ba64 Mon Sep 17 00:00:00 2001 From: Hermes BUILD <48018975+nujovich@users.noreply.github.com> Date: Sat, 15 Aug 2026 06:52:48 +0200 Subject: [PATCH 4/5] feat(mint): wire modern features results into playground UI --- components/AuditView.tsx | 88 +++++++++++++++++++++++++++- lib/__tests__/audit-summary.test.mjs | 88 +++++++++++++++++++++++++++- lib/audit-summary.mjs | 30 ++++++++++ 3 files changed, 204 insertions(+), 2 deletions(-) diff --git a/components/AuditView.tsx b/components/AuditView.tsx index 2086793..8ab2b76 100644 --- a/components/AuditView.tsx +++ b/components/AuditView.tsx @@ -2,7 +2,10 @@ import { useState } from 'react' import type { AuditReport, ColorDecision, UserDecisions } from '@/lib/types' -import { collectLintGroups } from '@/lib/audit-summary.mjs' +import { + collectLintGroups, + collectModernFeatures, +} from '@/lib/audit-summary.mjs' interface Props { audit: AuditReport @@ -53,6 +56,8 @@ export default function AuditView({ audit, onResolve }: Props) { const motionDurations = audit.motion?.durations?.suggestedScale ?? {} const motionEasings = audit.motion?.easings?.suggestedScale ?? {} const lintGroups = collectLintGroups(audit) + const modernFeatures = collectModernFeatures(audit) + const adoptedFeatureCount = modernFeatures.filter((f) => f.used).length const chaosColor = audit.chaosScore <= 3 @@ -882,6 +887,87 @@ export default function AuditView({ audit, onResolve }: Props) { )} + {/* Modern CSS adoption */} + {modernFeatures.length > 0 && ( +
+ + Modern CSS Adoption — {adoptedFeatureCount} of{' '} + {modernFeatures.length} adopted + + +
+ {modernFeatures.map((feature) => ( +
+ +
+
+ + {feature.label} + + + {feature.used ? 'adopted' : 'not adopted'} + +
+ {!feature.used && feature.suggestion && ( +
+ {feature.suggestion} +
+ )} +
+
+ ))} +
+
+ )} + {/* CTA */}