Audit and refactor CSS to comply with Game Loopers design system and BEM methodology
**css-bem-auditor**
Audit, normalize, and refactor CSS across the Game Loopers application to comply with the project's **BEM (Block–Element–Modifier)** methodology and design system, ensuring maintainability, consistency, and scalability.
This skill identifies non-compliant selectors, design token violations, naming collisions, overly-specific rules, and architectural inconsistencies, then proposes or applies BEM-aligned fixes specific to Game Loopers.
**Critical**: This project uses **strict BEM with NO utility-first CSS** (no Tailwind, no inline utilities). All styles must use component-scoped CSS with BEM naming.
---
This skill operates on:
It does **not** redesign UI or change visual intent unless explicitly requested.
---
Game Loopers has a comprehensive design system defined in `DESIGN_SYSTEM.md` (co-located in this directory). All CSS must comply with:
**Semantic Colors**:
```css
--primary /* Black in light mode */
--primary-foreground /* White text on primary */
--secondary /* Light gray */
--secondary-foreground
--destructive /* Red for errors/delete */
--destructive-foreground
--accent /* Highlights, hover states */
--accent-foreground
--background /* Page background */
--foreground /* Primary text */
--card /* Card backgrounds */
--card-foreground
--muted /* Low emphasis backgrounds */
--muted-foreground /* Secondary text */
--border /* Default borders */
--input /* Input borders */
--ring /* Focus ring color */
```
**Status Colors**:
```css
--color-success /* Green - confirmations */
--color-success-foreground
--color-warning /* Yellow - cautions */
--color-warning-foreground
--color-error /* Red - failures */
--color-error-foreground
--color-info /* Blue - notifications */
--color-info-foreground
```
```css
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
--text-5xl: 3rem; /* 48px */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
--leading-tight: 1.25;
--leading-snug: 1.375;
--leading-normal: 1.5;
--leading-relaxed: 1.625;
```
```css
--spacing-xs: 0.25rem; /* 4px */
--spacing-sm: 0.5rem; /* 8px */
--spacing-md: 1rem; /* 16px */
--spacing-lg: 1.5rem; /* 24px */
--spacing-xl: 2rem; /* 32px */
--spacing-2xl: 3rem; /* 48px */
--spacing-3xl: 4rem; /* 64px */
--spacing-4xl: 6rem; /* 96px */
--gap-xs: 0.25rem;
--gap-sm: 0.5rem;
--gap-md: 1rem;
--gap-lg: 1.5rem;
--gap-xl: 2rem;
--gap-2xl: 3rem;
```
```css
--radius-sm: 0.125rem; /* 2px */
--radius-md: 0.375rem; /* 6px */
--radius-lg: 0.5rem; /* 8px */
--radius-xl: 0.75rem; /* 12px */
--radius-2xl: 1rem; /* 16px */
--radius-full: 9999px; /* Fully rounded */
```
```css
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
```
---
```css
.block {}
.block__element {}
.block--modifier {}
.block__element--modifier {}
```
**Block Naming**:
**Element Naming**:
**Modifier Naming**:
**Core Components**:
**Browse Components** (global.css):
**Product Components**:
**Document Components**:
**Interactive Components**:
❌ **Strictly Forbidden**:
```css
/* NO Tailwind-style utilities */
.flex { display: flex; }
.text-center { text-align: center; }
.mt-4 { margin-top: 1rem; }
/* NO chained selectors (breaks BEM) */
.card .title { }
.button .icon { }
/* NO tag-qualified classes */
div.card { }
a.button { }
/* NO ID selectors */
#header { }
/* NO deep nesting beyond 2 levels */
.card__header__title__icon { } /* Too deep */
/* NO generic state classes without block context */
.is-active { } /* Use .button--active instead */
.has-error { } /* Use .input--error instead */
/* NO hardcoded colors/sizes (use design tokens) */
.card {
color: #333; /* ❌ Use var(--foreground) */
padding: 24px; /* ❌ Use var(--spacing-lg) */
border-radius: 8px; /* ❌ Use var(--radius-lg) */
}
```
✅ **Correct Usage**:
```css
/* Flat class selectors with design tokens */
.card {
background-color: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: var(--spacing-3xl);
}
/* Explicit block ownership */
.card__title {
font-size: var(--text-xl);
font-weight: var(--font-weight-semibold);
color: var(--card-foreground);
}
/* Boolean and value modifiers */
.button--primary { }
.button--lg { }
.card--elevated { }
/* Pseudo-states on BEM classes */
.button:hover { }
.button:focus-visible { }
.button:disabled { }
/* Global page utilities (limited exceptions) */
.page { }
.page__container { }
/* Third-party libraries (unmodifiable) */
.tiptap { }
.astro-* { }
```
---
Each selector is categorized as:
**Naming Violations**:
**Design Token Violations**:
**Structural Violations**:
For each violation:
1. **Propose canonical BEM block name** (check existing blocks first)
2. **Replace hardcoded values with design tokens**
3. **Flatten selector structure** (convert nested to explicit elements)
4. **Normalize modifiers** (ensure `--` separator)
5. **Update markup** (Astro/TSX files) to match new class names
Ensure all CSS uses design tokens:
```css
/* BEFORE (violations) */
.card {
color: #333;
background: #fff;
padding: 24px;
margin-bottom: 32px;
border-radius: 8px;
font-size: 18px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
/* AFTER (compliant) */
.card {
color: var(--foreground);
background: var(--card);
padding: var(--spacing-lg);
margin-bottom: var(--spacing-xl);
border-radius: var(--radius-lg);
font-size: var(--text-lg);
box-shadow: var(--shadow-md);
}
```
---
**BEFORE (Violation)**:
```html
<!-- Astro component using Tailwind-style classes -->
<div class="flex gap-4 p-6 rounded-lg bg-white">
<h2 class="text-xl font-bold">Title</h2>
<p class="text-gray-600">Description</p>
</div>
<style>
.flex { display: flex; }
.gap-4 { gap: 1rem; }
.p-6 { padding: 1.5rem; }
.rounded-lg { border-radius: 0.5rem; }
.bg-white { background: white; }
.text-xl { font-size: 1.25rem; }
.font-bold { font-weight: bold; }
.text-gray-600 { color: #666; }
</style>
```
**AFTER (BEM Compliant)**:
```html
<div class="product-card">
<h2 class="product-card__title">Title</h2>
<p class="product-card__description">Description</p>
</div>
<style>
.product-card {
display: flex;
gap: var(--gap-md);
padding: var(--spacing-lg);
border-radius: var(--radius-lg);
background: var(--card);
}
.product-card__title {
font-size: var(--text-xl);
font-weight: var(--font-weight-bold);
color: var(--card-foreground);
}
.product-card__description {
color: var(--muted-foreground);
}
</style>
```
**BEFORE (Violation)**:
```css
.card .header .title {
font-size: 20px;
}
.card.active {
border-color: blue;
}
.card .footer button {
padding: 12px 24px;
}
```
**AFTER (BEM Compliant)**:
```css
.card__title {
font-size: var(--text-xl);
}
.card--active {
border-color: var(--primary);
}
.card__footer-button {
padding: var(--spacing-sm) var(--spacing-lg);
}
```
```html
<div class="card card--active">
<div class="card__header">
<h2 class="card__title">Title</h2>
</div>
<div class="card__footer">
<button class="card__footer-button">Action</button>
</div>
</div>
```
**BEFORE (Violations)**:
```css
.product-card {
background: #ffffff;
color: #333333;
border: 1px solid #e0e0e0;
padding: 16px 24px;
margin-bottom: 32px;
border-radius: 8px;
font-size: 16px;
line-height: 1.5;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.product-card__title {
color: #000000;
font-size: 24px;
font-weight: 600;
margin-bottom: 8px;
}
.product-card__description {
color: #666666;
font-size: 14px;
line-height: 1.6;
}
.product-card:hover {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
```
**AFTER (Design Token Compliant)**:
```css
.product-card {
background: var(--card);
color: var(--card-foreground);
border: 1px solid var(--border);
padding: var(--spacing-md) var(--spacing-lg);
margin-bottom: var(--spacing-xl);
border-radius: var(--radius-lg);
font-size: var(--text-base);
line-height: var(--leading-normal);
box-shadow: var(--shadow-sm);
}
.product-card__title {
color: var(--foreground);
font-size: var(--text-2xl);
font-weight: var(--font-weight-semibold);
margin-bottom: var(--spacing-sm);
}
.product-card__description {
color: var(--muted-foreground);
font-size: var(--text-sm);
line-height: var(--leading-relaxed);
}
.product-card:hover {
box-shadow: var(--shadow-md);
}
```
---
```css
/* Base button block */
.button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--spacing-sm) var(--spacing-lg);
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: var(--font-weight-medium);
transition: background-color 150ms;
}
/* Variant modifiers */
.button--primary {
background-color: var(--primary);
color: var(--primary-foreground);
}
.button--secondary {
background-color: var(--secondary);
color: var(--secondary-foreground);
}
.button--destructive {
background-color: var(--destructive);
color: var(--destructive-foreground);
}
/* Size modifiers */
.button--sm {
padding: var(--spacing-xs) var(--spacing-md);
font-size: var(--text-sm);
}
.button--lg {
padding: var(--spacing-md) var(--spacing-xl);
font-size: var(--text-lg);
}
/* Elements */
.button__icon {
margin-right: var(--spacing-xs);
}
.button__text { }
/* States */
.button:hover {
opacity: 0.9;
}
.button:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
.button:disabled {
opacity: 0.5;
pointer-events: none;
}
```
```css
.modal-overlay {
position: fixed;
inset: 0;
background: rgb(0 0 0 / 0.5);
display: flex;
align-items: center;
justify-content: center;
padding: var(--spacing-lg);
z-index: 50;
}
.modal-content {
background: var(--card);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-xl);
max-width: 32rem;
width: 100%;
max-height: 90vh;
overflow-y: auto;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-lg);
border-bottom: 1px solid var(--border);
}
.modal-title {
font-size: var(--text-xl);
font-weight: var(--font-weight-semibold);
color: var(--foreground);
}
.modal-close {
padding: var(--spacing-xs);
color: var(--muted-foreground);
}
.modal-close:hover {
color: var(--foreground);
}
.modal-body {
padding: var(--spacing-lg);
}
```
---
All CSS must support accessibility standards:
```css
/* All interactive elements MUST have visible focus indicators */
.button:focus-visible,
.browse-tags__tag:focus-visible,
.navigation__link:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
```
**All semantic color tokens meet WCAG 2.1 Level AA standards.**
```css
/* Hidden but accessible to screen readers */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
/* Decorative elements should be hidden from screen readers via aria-hidden="true" */
/* No CSS-only hiding for interactive elements */
```
---
CSS files must follow this structure:
```
src/
├── styles/
│ └── global.css # Global styles, shared .browse-* classes
├── components/
│ ├── Button.astro # <style> block in component
│ ├── Card.astro # <style> block in component
│ ├── products/
│ │ ├── ProductFilesForm.tsx # SolidJS component
│ │ ├── product-files-form.css # Co-located CSS
│ │ ├── ProductRoyaltyBreakdown.tsx
│ │ └── product-royalty-breakdown.css
```
**Rules**:
---
Generates:
Generates:
Generates:
---
---
✅ **Pass Conditions**:
---
This skill enforces Game Loopers' strict BEM architecture and design system compliance. It ensures:
1. **Consistent BEM naming** across all components
2. **Design token usage** for theming and maintainability
3. **No utility-first CSS** (Tailwind prohibition)
4. **Accessibility compliance** (WCAG 2.1 Level AA)
5. **Scalable architecture** for long-term maintenance
This is critical for a product-market fit focused MVP where consistency and maintainability enable rapid iteration.
Leave a review
No reviews yet. Be the first to review this skill!