diff --git a/src/shared/ui/Card/index.ts b/src/shared/ui/Card/index.ts
new file mode 100644
index 0000000..b5c2138
--- /dev/null
+++ b/src/shared/ui/Card/index.ts
@@ -0,0 +1,2 @@
+export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from './ui/Card'
+export type { CardBackground } from './ui/Card'
diff --git a/src/shared/ui/Card/ui/Card.test.tsx b/src/shared/ui/Card/ui/Card.test.tsx
new file mode 100644
index 0000000..1d49f3d
--- /dev/null
+++ b/src/shared/ui/Card/ui/Card.test.tsx
@@ -0,0 +1,79 @@
+import { describe, it, expect } from 'vitest'
+import { render, screen } from '@testing-library/react'
+import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from './Card'
+
+describe('Card', () => {
+ describe('rendering', () => {
+ it('renders children', () => {
+ render(Content)
+ expect(screen.getByText('Content')).toBeInTheDocument()
+ })
+ it('has brutal-border and brutal-shadow classes', () => {
+ const { container } = render(Content)
+ expect(container.firstChild).toHaveClass('brutal-border', 'brutal-shadow')
+ })
+ })
+ describe('background variants', () => {
+ it('defaults to ochre background', () => {
+ const { container } = render(Content)
+ expect(container.firstChild).toHaveClass('bg-ochre-clay')
+ })
+ it('applies slate background', () => {
+ const { container } = render(Content)
+ expect(container.firstChild).toHaveClass('bg-slate-indigo')
+ })
+ it('applies white background', () => {
+ const { container } = render(Content)
+ expect(container.firstChild).toHaveClass('bg-white')
+ })
+ })
+ describe('padding', () => {
+ it('has default padding', () => {
+ const { container } = render(Content)
+ expect(container.firstChild).toHaveClass('p-6')
+ })
+ it('removes padding when noPadding is true', () => {
+ const { container } = render(Content)
+ expect(container.firstChild).not.toHaveClass('p-6')
+ })
+ })
+ describe('className passthrough', () => {
+ it('merges custom className', () => {
+ const { container } = render(Content)
+ expect(container.firstChild).toHaveClass('group')
+ })
+ })
+})
+describe('CardHeader', () => {
+ it('renders children with bottom margin', () => {
+ render(Header)
+ expect(screen.getByText('Header')).toHaveClass('mb-4')
+ })
+})
+describe('CardTitle', () => {
+ it('renders children as h3', () => {
+ render(Title)
+ expect(screen.getByRole('heading', { level: 3 })).toHaveTextContent('Title')
+ })
+})
+describe('CardDescription', () => {
+ it('renders children as paragraph with opacity', () => {
+ render(Desc)
+ const el = screen.getByText('Desc')
+ expect(el.tagName).toBe('P')
+ expect(el).toHaveClass('opacity-80')
+ })
+})
+describe('CardContent', () => {
+ it('renders children in a div', () => {
+ render(Body)
+ expect(screen.getByText('Body')).toBeInTheDocument()
+ })
+})
+describe('CardFooter', () => {
+ it('renders children with top border', () => {
+ render(Footer)
+ const el = screen.getByText('Footer')
+ expect(el).toHaveClass('brutal-border-top', 'mt-6', 'pt-6')
+ })
+})
diff --git a/src/shared/ui/Card/ui/Card.tsx b/src/shared/ui/Card/ui/Card.tsx
new file mode 100644
index 0000000..cadf0d1
--- /dev/null
+++ b/src/shared/ui/Card/ui/Card.tsx
@@ -0,0 +1,88 @@
+import type { ReactNode } from 'react'
+import { cn } from '$shared/lib'
+
+export type CardBackground = 'ochre' | 'slate' | 'white'
+
+interface CardProps {
+ /**
+ * Card content
+ */
+ children: ReactNode
+ /**
+ * Additional CSS classes
+ */
+ className?: string
+ /**
+ * Background color preset
+ * @default 'ochre'
+ */
+ background?: CardBackground
+ /**
+ * Remove default padding
+ * @default false
+ */
+ noPadding?: boolean
+}
+
+const BG: Record = {
+ ochre: 'bg-ochre-clay',
+ slate: 'bg-slate-indigo text-ochre-clay',
+ white: 'bg-white',
+}
+
+/**
+ * Brutalist card container with background and padding variants.
+ */
+export function Card({ children, className, background = 'ochre', noPadding = false }: CardProps) {
+ return (
+
+ {children}
+
+ )
+}
+
+interface SlotProps {
+ /**
+ * Slot content
+ */
+ children: ReactNode
+ /**
+ * Additional CSS classes
+ */
+ className?: string
+}
+
+/**
+ * Card header wrapper — adds bottom margin.
+ */
+export function CardHeader({ children, className }: SlotProps) {
+ return {children}
+}
+
+/**
+ * Card title — renders as h3.
+ */
+export function CardTitle({ children, className }: SlotProps) {
+ return {children}
+}
+
+/**
+ * Card description — muted paragraph below the title.
+ */
+export function CardDescription({ children, className }: SlotProps) {
+ return {children}
+}
+
+/**
+ * Card body content area.
+ */
+export function CardContent({ children, className }: SlotProps) {
+ return {children}
+}
+
+/**
+ * Card footer — separated by a brutal border-top.
+ */
+export function CardFooter({ children, className }: SlotProps) {
+ return {children}
+}