| name | always-design-system |
| description | MANDATORY rules - use design system tokens, existing components, and INDX Swiss patterns |
| license | MIT |
| compatibility | Claude Code |
| metadata | {"author":"indx.sh","version":"4.1","project":"indx-web","priority":"critical"} |
| allowed-tools | ["Read","Write","Edit","Glob","Grep","Bash"] |
DESIGN SYSTEM - MANDATORY RULES
Every line of code MUST comply. NO EXCEPTIONS.
SOURCE OF TRUTH
Before implementing ANY feature, check the specs:
ls docs/specs/
Read the relevant spec BEFORE implementing.
RULE 0: COMPONENT SOURCE HIERARCHY
Before creating ANY component:
Step 1: Check Local
ls src/components/ui/
Step 2: Check Fabrk Boilerplate
ls ../fabrk-dev/src/components/ui/
Step 3: Decision
| Situation | Action |
|---|
| Exists in web | Use it |
| Exists in fabrk-dev only | Copy to web, then use |
| Doesn't exist in EITHER | ONLY THEN build custom |
fabrk-dev is READ-ONLY. Never modify. Only copy FROM it.
RULE 1: USE EXISTING COMPONENTS
We have 98 UI components. NEVER build custom UI.
Core Form Components
| Need | Component | Import |
|---|
| Button | Button | @/components/ui/button |
| Input | Input | @/components/ui/input |
| InputSearch | InputSearch | @/components/ui/input-search |
| InputPassword | InputPassword | @/components/ui/input-password |
| InputOTP | InputOTP | @/components/ui/input-otp |
| InputNumber | InputNumber | @/components/ui/input-number |
| InputGroup | InputGroup | @/components/ui/input-group |
| Textarea | Textarea | @/components/ui/textarea |
| Select | Select, SelectTrigger, SelectContent, SelectItem | @/components/ui/select |
| Checkbox | Checkbox | @/components/ui/checkbox |
| Switch | Switch | @/components/ui/switch |
| RadioGroup | RadioGroup, RadioGroupItem | @/components/ui/radio-group |
| Slider | Slider | @/components/ui/slider |
| Label | Label | @/components/ui/label |
| Form | Form, FormField, FormItem, FormLabel, FormMessage | @/components/ui/form |
| FormError | FormError | @/components/ui/form-error |
| TagInput | TagInput | @/components/ui/tag-input |
| FileUpload | FileUpload | @/components/ui/file-upload |
| DatePicker | DatePicker | @/components/ui/date-picker |
| Calendar | Calendar | @/components/ui/calendar |
Layout Components
| Need | Component | Import |
|---|
| Card | Card, CardHeader, CardContent, CardFooter | @/components/ui/card |
| Container | Container | @/components/ui/container |
| Tabs | Tabs, TabsList, TabsTrigger, TabsContent | @/components/ui/tabs |
| StyledTabs | StyledTabs | @/components/ui/styled-tabs |
| Accordion | Accordion, AccordionItem, AccordionTrigger, AccordionContent | @/components/ui/accordion |
| Sidebar | Sidebar, SidebarContent, SidebarGroup | @/components/ui/sidebar |
| ScrollArea | ScrollArea | @/components/ui/scroll-area |
| Separator | Separator | @/components/ui/separator |
| Resizable | ResizablePanelGroup, ResizablePanel, ResizableHandle | @/components/ui/resizable |
Feedback & Overlay
| Need | Component | Import |
|---|
| Dialog | Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle | @/components/ui/dialog |
| Sheet | Sheet, SheetTrigger, SheetContent, SheetHeader | @/components/ui/sheet |
| Alert | Alert, AlertTitle, AlertDescription | @/components/ui/alert |
| AlertDialog | AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogAction | @/components/ui/alert-dialog |
| Toast | toast() | @/components/ui/toast |
| Toaster | Toaster | @/components/ui/toaster |
| Tooltip | Tooltip, TooltipTrigger, TooltipContent | @/components/ui/tooltip |
| InfoTooltip | InfoTooltip | @/components/ui/info-tooltip |
| Popover | Popover, PopoverTrigger, PopoverContent | @/components/ui/popover |
Navigation
| Need | Component | Import |
|---|
| Breadcrumb | Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink | @/components/ui/breadcrumb |
| Pagination | Pagination | @/components/ui/pagination |
| ScrollToTop | ScrollToTop | @/components/ui/scroll-to-top |
Data Display
| Need | Component | Import |
|---|
| Table | Table, TableHeader, TableBody, TableRow, TableHead, TableCell | @/components/ui/table |
| TableSkeleton | TableSkeleton | @/components/ui/table-skeleton |
| DataTable | DataTable | @/components/ui/data-table |
| Badge | Badge | @/components/ui/badge |
| Avatar | Avatar, AvatarImage, AvatarFallback | @/components/ui/avatar |
| Progress | Progress | @/components/ui/progress |
| Skeleton | Skeleton | @/components/ui/skeleton |
| EmptyState | EmptyState | @/components/ui/empty-state |
| CodeBlock | CodeBlock | @/components/ui/code-block |
| KPICard | KPICard | @/components/ui/kpi-card |
| StatCard | StatCard | @/components/ui/stat-card |
| PricingCard | PricingCard | @/components/ui/pricing-card |
| BillingSummaryCard | BillingSummaryCard | @/components/ui/billing-summary-card |
| MemberCard | MemberCard | @/components/ui/member-card |
Menus
| Need | Component | Import |
|---|
| DropdownMenu | DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem | @/components/ui/dropdown-menu |
| ContextMenu | ContextMenu, ContextMenuTrigger, ContextMenuContent | @/components/ui/context-menu |
| Command | Command, CommandInput, CommandList, CommandItem | @/components/ui/command |
Charts
| Need | Component | Import |
|---|
| AreaChart | AreaChart | @/components/ui/area-chart |
| BarChart | BarChart | @/components/ui/bar-chart |
| LineChart | LineChart | @/components/ui/line-chart |
| PieChart | PieChart | @/components/ui/pie-chart |
| DonutChart | DonutChart | @/components/ui/donut-chart |
| FunnelChart | FunnelChart | @/components/ui/funnel-chart |
| Heatmap | Heatmap | @/components/ui/heatmap |
| Sparkline | Sparkline | @/components/ui/sparkline |
| Gauge | Gauge | @/components/ui/gauge |
Special Components
| Need | Component | Import |
|---|
| Loading | Loading | @/components/ui/loading |
| TerminalSpinner | TerminalSpinner | @/components/ui/terminal-spinner |
| Marquee | Marquee | @/components/ui/marquee |
| Typewriter | Typewriter | @/components/ui/typewriter |
| Icon | Icon | @/components/ui/icon |
| SimpleIcon | SimpleIcon | @/components/ui/simple-icon |
| CookieConsent | CookieConsent | @/components/ui/cookie-consent |
| KeyboardHelpModal | KeyboardHelpModal | @/components/ui/keyboard-help-modal |
| NotificationBadge | NotificationBadge | @/components/ui/notification-badge |
| NotificationCenter | NotificationCenter | @/components/ui/notification-center |
| NotificationList | NotificationList | @/components/ui/notification-list |
| OnboardingChecklist | OnboardingChecklist | @/components/ui/onboarding-checklist |
| ApiKeyManager | ApiKeyManager | @/components/ui/api-key-manager |
| AuditLog | AuditLog | @/components/ui/audit-log |
| WebhookLog | WebhookLog | @/components/ui/webhook-log |
| SignInForm | SignInForm | @/components/ui/sign-in-form |
Templates (USE FOR PAGES)
| Need | Template | Import |
|---|
| Form pages | FormPageTemplate | @/components/templates/form-page-template |
| Directory listings | DirectoryListingTemplate | @/components/templates/directory-listing-template |
| Directory detail | DirectoryDetailTemplate | @/components/templates/directory-detail-template |
| Directory table | DirectoryTableTemplate | @/components/templates/directory-table-template |
| Admin pages | AdminPageTemplate | @/components/templates/admin-page-template |
| Auth pages | AuthPageTemplate | @/components/templates/auth-page-template |
| Auth form field | AuthFormField | @/components/templates/auth-form-field |
| Settings pages | SettingsPageTemplate | @/components/templates/settings-page-template |
| User dashboard | UserDashboardTemplate | @/components/templates/user-dashboard-template |
| Marketing pages | MarketingPageTemplate | @/components/templates/marketing-page-template |
| Landing pages | CommunityLandingTemplate | @/components/templates/community-landing-template |
| Docs hub | DocsHubTemplate | @/components/templates/docs-hub-template |
| Docs article | DocsArticleTemplate | @/components/templates/docs-article-template |
| Learn course | LearnCourseTemplate | @/components/templates/learn-course-template |
| Legal pages | LegalPageTemplate | @/components/templates/legal-page-template |
| Error pages | ErrorPageTemplate | @/components/templates/error-page-template |
| Success pages | SuccessPageTemplate | @/components/templates/success-page-template |
| TE Directory | TEDirectoryTemplate | @/components/templates/te-directory-template |
RULE 2: USE HOOKS
See docs/specs/08-HOOKS.md for complete signatures.
Data Fetching Hooks
import {
useRulesData,
useMcpData,
useToolsData,
useSkillsData,
useJobsData,
useFeaturedItems,
useDirectoryStats,
useSidebarStats,
useRegistryData,
} from '@/hooks';
Form Hooks
import {
useRuleSubmitForm,
useRuleEditForm,
useMcpSubmitForm,
useMcpEditForm,
useToolSubmitForm,
useToolEditForm,
useSkillSubmitForm,
useSkillEditForm,
useJobPostForm,
useJobEditForm,
useInlineEdit,
} from '@/hooks';
UI State Hooks
import {
useToast,
useAuthModal,
usePalette,
useMediaQuery,
useDataTableState,
useColumnResize,
useKeyboardShortcuts,
useListKeyboardNav,
} from '@/hooks';
Action Hooks
import {
useBookmark,
useBulkBookmarks,
useCheckout,
useModeration,
useCsrfToken,
useAnalytics,
useNotifications,
usePusher,
useSearch,
useRecentSearches,
useAutocomplete,
} from '@/hooks';
Usage Examples
const { toast } = useToast();
toast({ title: 'SUCCESS', description: 'Saved.' });
toast({ title: 'ERROR', description: 'Failed.', variant: 'destructive' });
const csrfFetch = useCsrfToken();
await csrfFetch('/api/endpoint', {
method: 'POST',
body: JSON.stringify(data),
});
const { approve, reject } = useModeration();
await approve('rule', ruleId);
RULE 3: DESIGN TOKENS
Required Imports
import { mode } from '@/design-system';
import { cn } from '@/lib/utils';
Color Tokens
mode.color.bg.base
mode.color.bg.surface
mode.color.bg.surfaceRaised
mode.color.bg.elevated
mode.color.bg.muted
mode.color.bg.mutedSubtle
mode.color.bg.mutedLight
mode.color.bg.mutedMedium
mode.color.bg.secondary
mode.color.bg.accent
mode.color.bg.accentMuted
mode.color.bg.accentHover
mode.color.bg.primarySubtle
mode.color.bg.primaryLight
mode.color.bg.danger
mode.color.bg.dangerMuted
mode.color.bg.success
mode.color.bg.successMuted
mode.color.bg.successSubtle
mode.color.bg.warning
mode.color.bg.warningMuted
mode.color.bg.info
mode.color.bg.infoMuted
mode.color.text.primary
mode.color.text.secondary
mode.color.text.muted
mode.color.text.inverse
mode.color.text.disabled
mode.color.text.accent
mode.color.text.danger
mode.color.text.dangerOnColor
mode.color.text.success
mode.color.text.successOnColor
mode.color.text.warning
mode.color.text.warningOnColor
mode.color.text.info
mode.color.text.infoOnColor
mode.color.border.default
mode.color.border.divider
mode.color.border.focus
mode.color.border.active
mode.color.border.accent
mode.color.border.accentSubtle
mode.color.border.mutedSubtle
mode.color.border.danger
mode.color.border.success
mode.color.border.warning
mode.color.border.info
mode.color.icon.primary
mode.color.icon.secondary
mode.color.icon.muted
mode.color.icon.accent
mode.color.icon.danger
mode.color.icon.success
mode.color.icon.warning
mode.color.icon.info
mode.color.badge.success.border
mode.color.badge.success.bg
mode.color.badge.success.text
mode.color.badge.warning.border
mode.color.badge.warning.bg
mode.color.badge.warning.text
mode.color.badge.error.border
mode.color.badge.error.bg
mode.color.badge.error.text
mode.color.badge.info.border
mode.color.badge.info.bg
mode.color.badge.info.text
mode.color.badge.neutral.border
mode.color.badge.neutral.bg
mode.color.badge.neutral.text
mode.color.badge.accent.border
mode.color.badge.accent.bg
mode.color.badge.accent.text
mode.color.terminal.magenta
mode.color.terminal.magentaBright
mode.color.terminal.cyan
mode.color.terminal.cyanBright
mode.color.terminal.red
mode.color.terminal.orange
mode.color.terminal.green
mode.color.terminal.yellow
mode.color.terminal.blue
Typography Tokens
mode.typography.display.lg
mode.typography.display.md
mode.typography.display.sm
mode.typography.headline.lg
mode.typography.headline.md
mode.typography.headline.sm
mode.typography.title.lg
mode.typography.title.md
mode.typography.title.sm
mode.typography.body.lg
mode.typography.body.md
mode.typography.body.sm
mode.typography.label.lg
mode.typography.label.md
mode.typography.label.sm
mode.typography.code
mode.typography.caps
mode.typography.button
mode.typography.caption
mode.typography.input
mode.typography.sidebar.item
mode.typography.sidebar.header
mode.typography.heading.h1
mode.typography.heading.h2
mode.typography.heading.h3
mode.typography.heading.h4
mode.typography.heading.h5
mode.typography.heading.h6
State Tokens (ACTUAL from state-config.ts)
mode.state.hover.bg
mode.state.hover.text
mode.state.hover.card
mode.state.hover.cardSubtle
mode.state.hover.link
mode.state.hover.linkOpacity
mode.state.hover.listItem
mode.state.hover.opacity
mode.state.hover.border
mode.state.hover.borderWarning
mode.state.hover.textWarning
mode.state.hover.borderAccent
mode.state.hover.textAccent
mode.state.focus.ring
mode.state.focus.layer
mode.state.pressed.layer
mode.state.dragged.layer
mode.state.disabled.opacity
mode.state.disabled.cursor
mode.state.disabled.layer
mode.state.selected.layer
mode.state.selected.layerHover
mode.state.completed.opacity
mode.state.muted.opacity
mode.state.subtle.opacity
mode.state.secondary.opacity
Mode Configuration Tokens
mode.font
mode.radius
mode.shadow
mode.borderWidth
mode.buttonPrefix
mode.textTransform
mode.inputStyle
mode.labelFormat
mode.cardHeader
Font Role Tokens (Swiss Typography)
mode.fontRole.ui
mode.fontRole.data
mode.fontRole.body
mode.fontRole.headline
Icon Sizing
mode.icon['2xs']
mode.icon.xs
mode.icon.sm
mode.icon.md
mode.icon.lg
mode.icon.xl
Spacing Tokens
mode.spacing.button.sm
mode.spacing.button.md
mode.spacing.button.lg
mode.spacing.input
mode.spacing.card
mode.spacing.badge.sm
mode.spacing.badge.md
mode.spacing.sidebar.container
mode.spacing.sidebar.item
mode.spacing.sidebar.header
mode.spacing.sidebar.gap
Sizing Tokens
mode.sizing.panel
mode.sizing.panelSm
mode.sizing.sidebar
mode.sizing.auth
mode.sizing.dropdown
mode.sizing.select
mode.sizing.dropdownHeight
mode.sizing.textareaHeight
mode.sizing.touch
mode.sizing.buttonHeight.sm
mode.sizing.buttonHeight.md
mode.sizing.buttonHeight.lg
Line Height Tokens
mode.lineHeight.display
mode.lineHeight.compact
mode.lineHeight.tight
mode.lineHeight.snug
mode.lineHeight.normal
mode.lineHeight.relaxed
mode.lineHeight.loose
Z-Index Tokens
mode.zIndex.banner
mode.zIndex.modal
M3 Tokens (Material Design 3)
For advanced layouts, see src/design-system/mode/m3-config.ts:
mode.layout
mode.space
mode.shape
mode.elevation
mode.motion
mode.density
mode.iconSpec
mode.stateLayer
mode.accessibility
mode.canonicalLayout
mode.contentDensity
RULE 4: GRID SPACING SYSTEM (MANDATORY)
ALL spacing MUST use --grid-* CSS variables. NO hardcoded Tailwind spacing.
Based on IBM Carbon's 4px Mini-Unit system for Swiss-Industrial design.
Grid Spacing Scale
| Token | Value | Use Case |
|---|
--grid-1 | 4px | Micro: icon padding, tight gaps |
--grid-2 | 8px | Small: between related items |
--grid-3 | 12px | Medium-small: toolbar gaps |
--grid-4 | 16px | Standard: 1 line-height |
--grid-6 | 24px | Medium: section headers |
--grid-8 | 32px | Large: between sections |
--grid-12 | 48px | XL: page sections |
--grid-16 | 64px | XXL: major divisions |
Usage
<div className="pt-[var(--grid-4)] mb-[var(--grid-8)]">
<div className="gap-[var(--grid-2)] space-y-[var(--grid-4)]">
<header className="pb-[var(--grid-4)] mb-[var(--grid-8)]">
<section className="mt-[var(--grid-12)]">
// ❌ BANNED - Hardcoded Tailwind spacing
<div className="pt-4 mb-8"> // NEVER
<div className="gap-2 space-y-4"> // NEVER
<div className="p-3 mt-5"> // NEVER
<section className="mt-12"> // NEVER
Swiss Layout Hierarchy
Standard vertical spacing between page elements:
| Transition | Spacing | Token |
|---|
| Global Bar → Page Header | 16px | pt-[var(--grid-4)] |
| Page Header → Toolbar | 24px | pb-[var(--grid-6)] |
| Toolbar → Content | 16px | mt-[var(--grid-4)] |
| Section → Section | 32px | space-y-[var(--grid-8)] |
| Content → Footer | 48px | mt-[var(--grid-12)] |
| Major divisions | 64px | space-y-[var(--grid-16)] |
Horizontal Spacing
Use character widths (ch) for horizontal padding:
px-[1ch]
px-[2ch]
px-[3ch]
Heights
h-[var(--grid-4)]
h-[var(--grid-6)]
h-[var(--grid-8)]
Asymmetric Spacing Rule
Space ABOVE headings > Space BELOW (anchors heading to content):
<section className="mt-8 mb-8">
<section className="mt-[var(--grid-16)] mb-[var(--grid-6)]"> // Sections
<section className="mt-[var(--grid-12)] mb-[var(--grid-4)]"> // Subsections
BANNED Patterns
p-1, p-2, p-3, p-4, p-5, p-6, p-8, p-10, p-12
m-1, m-2, m-3, m-4, m-5, m-6, m-8, m-10, m-12
gap-1, gap-2, gap-3, gap-4, gap-5, gap-6, gap-8
space-y-1, space-y-2, space-y-4, space-y-8, space-y-12
pt-4, pb-4, mt-8, mb-8
See grid-spacing skill for complete reference.
RULE 5: BORDER RADIUS
<div className={cn('border', mode.radius)}>
<div className="border-b">
<div className="border-t border-b">
// Tables = NEVER radius
<th className="border">
<td className="border">
// BANNED - never hardcode radius
// rounded-sm, rounded-md, rounded-lg, rounded-xl, rounded-2xl
RULE 6: THEME SWITCHING
The app supports light and dark mode via data-theme-mode attribute.
import { useTheme } from 'next-themes';
const { theme, setTheme } = useTheme();
RULE 7: RESPONSIVE PATTERNS
Breakpoints
<div className="p-4 md:p-6 lg:p-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
Common Patterns
<div className="flex flex-col md:flex-row gap-4">
<div className="w-full max-w-2xl mx-auto">
// Hide on mobile
<div className="hidden sm:block">
// Show only on mobile
<div className="block sm:hidden">
RULE 8: ACCESSIBILITY
Focus States (REQUIRED)
<button className={cn(
mode.state.focus.ring,
)}>
<button className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
Screen Reader Text
<span className="sr-only">Description for screen readers</span>
<button aria-label="Close dialog">
<X className={mode.icon.md} />
</button>
RULE 9: FILE SIZE LIMITS
| File Type | Max Lines |
|---|
| Components | 150 |
| Pages | 200 |
| Hooks | 100 |
| API Routes | 150 |
If over limit: Split into smaller files.
RULE 10: ADDING NEW TOKENS
If a token doesn't exist, ADD IT to the design system first.
Step 1: Add to config.ts
color: {
bg: {
newToken: 'bg-[oklch(var(--your-css-var))]',
}
}
Step 2: Add CSS variable (if needed)
:root {
--your-variable: 65% 0.15 240;
}
[data-theme-mode="dark"] {
--your-variable: 35% 0.15 240;
}
Swiss Color Rules
- 90% grayscale (0 chroma) - structure, text
- 8% accent (0.15-0.22 chroma) - interactive
- 2% semantic (0.15-0.18 chroma) - status
RULE 11: COMPLETE EXAMPLES
Basic Component
'use client';
import * as React from 'react';
import { cn } from '@/lib/utils';
import { mode } from '@/design-system';
import { Card, CardHeader, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
interface ExampleProps {
title: string;
description?: string;
}
export function Example({ title, description }: ExampleProps) {
return (
<Card className={cn('border', mode.radius, mode.color.border.default)}>
<CardHeader className="p-4">
<h2 className={cn(
mode.typography.headline.sm,
mode.font,
mode.color.text.primary
)}>
{title}
</h2>
</CardHeader>
<CardContent className="p-4 space-y-4">
{description && (
<p className={cn(
mode.typography.body.md,
mode.font,
mode.color.text.muted
)}>
{description}
</p>
)}
<div className="flex gap-4">
<Input placeholder="Enter text" />
<Button>{mode.buttonPrefix}SUBMIT</Button>
</div>
</CardContent>
</Card>
);
}
Form with Validation
'use client';
import * as React from 'react';
import { useState } from 'react';
import { cn } from '@/lib/utils';
import { mode } from '@/design-system';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useToast } from '@/hooks';
export function ExampleForm() {
const { toast } = useToast();
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
toast({ title: 'SUCCESS', description: 'Form submitted.' });
} catch {
setError('Failed to submit');
toast({ title: 'ERROR', description: 'Submission failed.', variant: 'destructive' });
}
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label className={cn(mode.typography.label.md, mode.font)}>
EMAIL
</Label>
<Input type="email" required />
</div>
{error && (
<div className={cn(
'p-4 border',
mode.radius,
mode.color.border.danger,
mode.color.bg.dangerMuted
)}>
<p className={cn(mode.typography.body.sm, mode.color.text.danger)}>
{error}
</p>
</div>
)}
<Button type="submit" className={mode.state.focus.ring}>
{mode.buttonPrefix}SUBMIT
</Button>
</form>
);
}
BANNED PATTERNS
<button className="px-4 py-2 bg-blue-500 rounded">
<div className="border rounded-lg p-4 shadow">
// BANNED: Custom modal
<div className="fixed inset-0 bg-black/50 z-50">
// BANNED: Custom input
<input className="border rounded px-2 py-1" />
// BANNED: Hardcoded colors
className="bg-gray-100"
className="text-blue-500"
className="border-slate-200"
// BANNED: Hardcoded typography
className="text-sm"
className="text-xl"
className="font-bold"
// BANNED: ALL hardcoded Tailwind spacing (use --grid-* variables)
className="p-4" // Use p-[var(--grid-4)]
className="gap-2" // Use gap-[var(--grid-2)]
className="mt-8" // Use mt-[var(--grid-8)]
className="space-y-4" // Use space-y-[var(--grid-4)]
className="mb-12" // Use mb-[var(--grid-12)]
className="pt-6" // Use pt-[var(--grid-6)]
// BANNED: Hardcoded radius
className="rounded-lg"
className="rounded-xl"
// BANNED: Inline styles
style={{ color: '#333', backgroundColor: '#f5f5f5' }}
CHECKLIST
Before submitting code: