StackUp 프론트엔드 시각·행동 규약. Tailwind CSS v4 기반 단일 출처(SSOT). 구현 —
frontend/src/app/styles/(tokens.css,global.css,index.css) 데모 페이지 —frontend/src/App.tsx(npm run dev→http://localhost:5173) 컴포넌트 —frontend/src/shared/ui/(도메인 비종속),frontend/src/features/*/ui/(도메인 종속)
- 신뢰감 우선 — 면접 도구이므로 가벼운 톤 지양. 진중·차분한 시각 언어.
- 집중 환경 보호 — 면접 화면은 노이즈 최소화. 핵심 UI만 노출, 부가 정보는 hover/click 으로 점진적 공개.
- 상태 가시성 — 분석 진행, 세션 상태, SSE 이벤트 등 비동기 상태는 항상 명시적으로 표현.
- 컬러는 SEED 토큰 위임 — 컬러·radius·shadow 는 당근 SEED Design(
@seed-design/css, Apache-2.0)을 참조한다. 브랜드는 SEEDblue팔레트로 리테마했고, 라이트/다크는 SEED 토큰이 전환한다. Domain(직군·면접유형) 컬러만 자체 값 유지. 상세 §2. - 접근성 (WCAG 2.1 AA) — 키보드 only 조작, 명도 대비 4.5:1 이상, focus ring 명확.
- 모바일 웹뷰 대응 — 데스크탑 우선이지만 mobile breakpoint(
< lg)에서도 깨지지 않게. - 라이트/다크 동시 지원 — 색은 반드시 시맨틱 토큰으로 쓴다. 고정 hex·
sage-*를 표면/본문 의미로 쓰면 다크에서 반전되지 않아 깨진다(§2.1).
모든 토큰은 frontend/src/app/styles/tokens.css 의 @theme 블록에만 정의. 컴포넌트는 토큰만 참조하고 하드코딩 금지 (bg-[#626e5c] ✗ → bg-primary ✓).
| 토큰 | Hex | Tailwind | 용도 |
|---|---|---|---|
--color-white |
#ffffff |
bg-white, text-white |
순백 |
--color-black |
#000000 |
bg-black |
순흑 |
--color-background |
#eceef3 |
bg-background (= bg-bg) |
앱 기본 배경 (쿨 라이트) |
토큰 이름은
sage-*로 유지하되 값은 브랜드 블루(#4662D2)에 맞춘 쿨 블루그레이 모노크롬 이다(저채도 — 중립/본문용). 브랜드 강조색은 별도primary(아래 §2.3, 스케일과 분리).
| 토큰 | Hex | 권장 용도 |
|---|---|---|
sage-50 |
#eef1f6 |
가장 밝은 컴포넌트 배경 (= surface) |
sage-100 |
#dbe2ec |
분리선 / 보더 (= border) |
sage-200 |
#c6cedd |
비활성 텍스트 / 보조 배경 (= border-strong, fg-disabled) |
sage-300 |
#9fafc9 |
비활성 보조 / placeholder |
sage-400 |
#6e7f9f |
흐린 텍스트 (= fg-subtle) |
sage-500 |
#4a5a7e |
본문 보조 텍스트 (= fg-muted), 활성 / 포커스 |
sage-600 |
#38486a |
강조 보더 / 표면 |
sage-700 |
#2b3a59 |
강조 컴포넌트 |
sage-800 |
#1e2a44 |
주요 헤딩 · 푸터 네이비 (= fg-strong) |
sage-900 |
#161f33 |
본문 (대안) |
sage-950 |
#101627 |
가장 어두운 텍스트 (= fg, 기본) |
Tailwind 사용: bg-sage-{n}, text-sage-{n}, border-sage-{n}.
sage-* 직접 참조보다 의미 별칭 사용을 권장 (다크 모드 도입 시 자동 대응).
| 토큰 | 매핑 | Tailwind |
|---|---|---|
--color-bg |
background |
bg-bg |
--color-surface |
sage-50 |
bg-surface |
--color-surface-raised |
white |
bg-surface-raised |
--color-border |
sage-100 |
border-border |
--color-border-strong |
sage-200 |
border-border-strong |
--color-fg |
sage-950 |
text-fg |
--color-fg-strong |
sage-800 |
text-fg-strong |
--color-fg-muted |
sage-500 |
text-fg-muted |
--color-fg-subtle |
sage-400 |
text-fg-subtle |
--color-fg-disabled |
sage-200 |
text-fg-disabled |
--color-fg-faint |
SEED fg-neutral-subtle (장식·대형 텍스트 전용, 3.42:1) |
text-fg-faint |
--color-fg-on-primary |
white |
text-fg-on-primary |
--color-primary |
#4662d2 (브랜드 블루, 스케일과 분리) |
bg-primary, text-primary |
--color-primary-hover |
#3b54bd |
bg-primary-hover |
--color-primary-pressed |
#31479f |
bg-primary-pressed |
--color-primary-50 |
#eff2fd (연한 파랑 표면) |
bg-primary-50 |
--color-primary-100 |
#dee4fa |
bg-primary-100 |
--color-primary-200 |
#c3cdf5 (틴트 위 보더) |
border-primary-200 |
상태 시각화. Sage 톤과 조화되는 muted jewel tones.
| 카테고리 | -50 (연한 배경) | -500 (기본) | -700 (강조) | 단축 |
|---|---|---|---|---|
| Success | #e8efe1 |
#5b7c47 |
#3f5731 |
bg-success, text-success |
| Warning | #f4e8d4 |
#b88840 |
#8a6529 |
bg-warning, text-warning |
| Danger | #f4e0d8 |
#a8503c |
#803a2a |
bg-danger, text-danger |
| Info | #dde4ea |
#4d6878 |
#36475a |
bg-info, text-info |
조합 규칙:
- 솔리드 뱃지:
bg-success text-white - 연한 뱃지:
bg-success-50 text-success-700 - 인라인 텍스트 강조:
text-success-700
StackUp 도메인 한정 컬러. features/*/ui 의 도메인 뱃지에서만 사용 (shared/ui 에서 직접 참조 금지).
| 직군 | Hex | Tailwind |
|---|---|---|
| Frontend | #5e8a98 (teal) |
bg-job-frontend |
| Backend | #7d6c93 (plum) |
bg-job-backend |
| Infra | #b06c70 (rose) |
bg-job-infra |
| DBA | #b89c5e (gold) |
bg-job-dba |
| 모드 | Hex | Tailwind |
|---|---|---|
| Personality | #6f9978 (mint) |
bg-type-personality |
| Technical | #6c8294 (slate) |
bg-type-technical |
| Integrated | #8a7896 (violet) |
bg-type-integrated |
| 토큰 | 폰트 | 용도 | Tailwind |
|---|---|---|---|
--font-heading / --font-display |
Fira Sans Extra Condensed | H1~H3 (Uppercase, 임팩트) | font-heading, font-display |
--font-subheading |
Geist | H4~H6, Caption (모던) | font-subheading |
--font-sans / --font-body |
Inter | 본문, 버튼 (가독성) | font-sans, font-body |
--font-mono |
Geist Mono | 코드 / 숫자 모노 | font-mono |
폰트 로딩은 frontend/index.html 의 <link> (Google Fonts).
각 토큰은 font-size + line-height + letter-spacing + font-weight 페어. 반응형은 *-mobile 변형.
| Tailwind | Size / LH | Weight | 폰트 카테고리 | 용도 |
|---|---|---|---|---|
text-display (text-display-mobile) |
100/1.0 (48/1.05) | 700 | Heading | 랜딩 / 페이지 타이틀 |
text-h2 (text-h2-mobile) |
56/1.05 (42/1.1) | 700 | Heading | 섹션 제목 |
text-h3 |
38/1.1 | 700 | Heading | 카드 / 블록 제목 |
text-h4 |
32/1.2 | 700 | Subheading | 큰 서브 헤딩 |
text-h5 |
24/1.3 | 700 | Subheading | 중간 서브 헤딩 |
text-h6 |
20/1.4 | 700 | Subheading | 작은 서브 헤딩 |
text-rich |
20/1.5 | 500 | Subheading | 큰 본문 / 강조 |
text-body |
16/1.2 | 500 | Sans | 기본 본문 |
text-button |
14/1.2 | 600 | Sans | 버튼 / 작은 본문 |
text-caption |
12/1.4 | 400 | Subheading | 캡션 / 메타 |
반응형 헤딩 사용법:
<h1 className="text-display-mobile lg:text-display">
계층 가이드: 한 페이지에
text-display1개,text-h2/text-h3는 섹션 단위. 카드 안 헤더는text-h5/text-h6우선.
Tailwind v4 기본 --spacing: 0.25rem (= 4px) 사용. p-4 = 16px.
| 토큰 | 값 |
|---|---|
space-1 |
4px |
space-2 |
8px |
space-3 |
12px |
space-4 |
16px |
space-5 |
20px |
space-6 |
24px |
space-8 |
32px |
space-10 |
40px |
space-12 |
48px |
space-16 |
64px |
권장 — 위 10개 값 우선. 임의 값(p-[13px])은 디자인 의도가 분명할 때만.
| 토큰 | 값 | Tailwind | 용도 |
|---|---|---|---|
--radius-sm |
4px | rounded-sm |
뱃지 |
--radius-md |
8px | rounded-md |
버튼, 인풋 |
--radius-lg |
12px | rounded-lg |
카드 |
--radius-xl |
16px | rounded-xl |
모달 |
--radius-2xl |
24px | rounded-2xl |
큰 모달 / Hero |
--radius-pill |
9999px | rounded-pill |
칩, 아바타, 토글 |
| 토큰 | Tailwind | 값 |
|---|---|---|
--shadow-sm |
shadow-sm |
0 1px 2px rgba(31,39,27,.06) |
--shadow-md |
shadow-md |
0 4px 6px -1px rgba(31,39,27,.10), 0 2px 4px -2px rgba(31,39,27,.06) |
--shadow-lg |
shadow-lg |
0 10px 15px -3px rgba(31,39,27,.10), 0 4px 6px -4px rgba(31,39,27,.05) |
--shadow-focus-ring |
shadow-focus-ring |
0 0 0 3px rgba(98,110,92,.45) |
| 토큰 | 값 | Tailwind | 용도 |
|---|---|---|---|
--duration-fast |
120ms | duration-fast |
hover, focus |
--duration-normal |
200ms | duration-normal |
기본 transition |
--duration-slow |
320ms | duration-slow |
모달 enter / exit |
--ease-standard |
cubic-bezier(0.4,0,0.2,1) |
ease-standard |
기본 |
--ease-decelerate |
cubic-bezier(0,0,0.2,1) |
ease-decelerate |
enter |
--ease-accelerate |
cubic-bezier(0.4,0,1,1) |
ease-accelerate |
exit |
prefers-reduced-motion: reduce사용자에게는 모든 transition / animation 0.01ms 강제 (global.css에서 처리).
레이어 충돌 방지용 정수 스케일. Tailwind 자동 utility 미생성 (--z-* 는 namespace 가 아님) → CSS var 직접 사용.
| 토큰 | 값 | 용도 |
|---|---|---|
--z-base |
0 | 기본 |
--z-raised |
10 | 카드 hover, 떠오름 |
--z-dropdown |
1000 | Select, Menu |
--z-sticky |
1100 | Sticky TopNav |
--z-modal-backdrop |
1200 | 모달 dim |
--z-modal |
1300 | 모달 본체 |
--z-popover |
1400 | Popover |
--z-tooltip |
1500 | Tooltip |
--z-toast |
1600 | Toast (가장 위) |
<div className="z-[var(--z-modal)]">...</div>
// or
<div style={{ zIndex: 'var(--z-modal)' }}>...</div>| 토큰 | 값 | Tailwind | 용도 |
|---|---|---|---|
--container-readable |
65ch | max-w-readable |
본문 / 프로즈 카드 |
--container-content |
1280px | max-w-content |
TopNav 안쪽 메인 영역 |
--container-app |
1440px | max-w-app |
앱 전체 최대 폭 |
Breakpoints — Tailwind v4 default 사용:
sm: 640px,md: 768px,lg: 1024px,xl: 1280px,2xl: 1536px.
- 라이브러리 — Lucide Icons (
lucide-react도입 예정, 트리쉐이킹 지원). - 크기 —
16 / 20 / 24 px(line-height 와 정렬). - 색상 —
currentColor(텍스트 색 상속). Tailwind:text-fg,text-fg-muted적용. - 의미 있는 아이콘은
aria-label필수, 장식용은aria-hidden="true".
위치: frontend/src/shared/ui/{Name}/ (도메인 비종속) 또는 frontend/src/features/*/ui/ (도메인 종속). 각 컴포넌트는 index.ts 로 public API.
랜딩(/)이 쓰던 조판을 프리미티브로 뽑아 모든 화면이 같은 것을 쓴다. 화면마다 제목
크기·라벨 스타일이 갈리던 문제를 여기로 모았다.
Eyebrow— 섹션 위 모노 라벨.font-mono text-caption tracking-tight, tone:subtle | brand.Heading— level:display | page | section | sub. 뷰포트 비례clamp()+ 음수 자간 +word-break: keep-all.Panel— 헤어라인 표면. paddingnone|sm|md|lg· toneraised|sunken·interactive.PageHeader— 라벨 → 제목 → 설명 → 하단 헤어라인.actions(우측),above(뒤로가기) 슬롯. level:page | section | sub.ColorModeToggle— 라이트/다크 전환.SiteNav·WorkspaceSidebar·로그인 헤더가 공유.
조판 4규칙 (직접 클래스를 쓸 때도 동일):
| 항목 | 규약 | 하지 말 것 |
|---|---|---|
| 헤딩 폰트 | font-sans(Pretendard) |
font-heading(Bricolage)를 한글 제목에 — 자소 높이가 튀어 조판이 흔들린다 |
| 헤딩 크기 | clamp() + 자간 -0.02 ~ -0.055em |
고정 text-h4 스케일 — 랜딩의 반응형 리듬과 어긋난다 |
| 섹션 라벨 | 조밀한 모노(Eyebrow) |
uppercase tracking-[0.22em] — 자간을 벌리면 한글 라벨이 무너진다 |
| 깊이 | 보더 한 줄 + 배경 단계 | 목록 카드마다 shadow-* — elevation 은 모달·미리보기 목업 등 실제로 떠 있는 것에만 |
한글 제목·본문에는 word-break: keep-all 을 건다(어절 중간 줄바꿈 방지).
헤더가 연달아 나오면 두 단계를 내린다. 랜딩은 섹션 제목 사이에 큰 콘텐츠가 끼지만
앱 화면은 PageHeader(page) 바로 아래 섹션 헤더가 붙는다. 이때 섹션을 section(최대 30px)
으로 두면 두 헤더가 비슷한 무게로 겹쳐 위계가 납작해진다 → 워크스페이스 섹션은 sub(18px).
모노 라벨이 섹션의 제목 역할을 하면 <Eyebrow as="h2">. 큰 제목 없이 라벨만으로 섹션을
여는 자리(피드백 리포트의 '강점', 히스토리의 '지난 면접')를 <p> 로 두면 문서 개요에서
사라져 스크린리더로 섹션 간 이동이 불가능해진다. 조판은 <p> 와 완전히 동일하게 계산된다.
Button— variant:primary | secondary | ghost | danger· size:sm | md | lg· state:loading | disabled. 라벨은font-semibold, 라운드는 크기를 따른다(sm·mdrounded-lg/ lgrounded-xl). 그림자 없음.IconButton— 아이콘 전용,aria-label필수.Link— 인라인 / 블록, 외부 링크는 자동target="_blank" rel="noopener".Input,Textarea,Select,Combobox(검색·자동완성).Checkbox,Radio,Switch.FileUploader— Drag & Drop, 진행률, 파일 검증 메시지.
Badge— 상태 매핑 (§4 참조).Tag/Chip— 기술 스택 등 다중 라벨.Avatar— GitHub avatar.Progress— 선형 / 원형.Skeleton— 로딩 placeholder (4-state §5).EmptyState— 빈 목록 안내, 아이콘 + 설명 + CTA (4-state §5).Card—header / body / footerslot.
Toast— 4종 (success / info / warning / error), 우상단 stack, 4초 자동 dismiss,z-toast.Modal✅ —shared/ui/Modal.title+children+ 옵션footer슬롯, Esc·백드롭 클릭으로 닫힘,z-modal, body 스크롤 잠금 + 포커스 복원. (전체 focus trap 은 추후)Drawer— 우측 슬라이드, 세션 설정 등.Popover,Tooltip— 키보드 접근 가능.ConfirmDialog— 파괴적 액션(삭제, 회원 탈퇴) 전용.Alert— 페이지 inline 경고.
TopNav— 로고, 글로벌 액션, Avatar 드롭다운, 64px height, sticky,z-sticky.SideNav— Workspace 좌측 메뉴, 240px width.Tabs—Underline | Pills.Breadcrumb,Pagination.
JobCategoryBadge— 직군별 컬러 (§2.5).InterviewModeBadge— 면접 모드별 컬러 (§2.5).SessionStatusBadge— 상태 매핑 (§4).AnalysisStateIndicator—QUEUED / PROCESSING / COMPLETED / FAILED4단계 progress.
shared vs features 구분 — 도메인 의존이 있으면
features, 디자인 토큰만 참조하면shared.
| 도메인 상태 | 시각 컬러 | 토큰 | 컴포넌트 예 |
|---|---|---|---|
READY / PENDING / QUEUED |
neutral | text-fg-muted (sage-500) |
회색 Badge |
IN_PROGRESS / PROCESSING / ANALYZING |
warning | bg-warning-50 text-warning-700 |
노란 Badge + spinner |
COMPLETED / ANALYZED / ACTIVE |
success | bg-success-50 text-success-700 |
초록 Badge |
INTERRUPTED |
warning | bg-warning-50 text-warning-700 |
노란 Badge (느낌표 아이콘) |
FAILED |
danger | bg-danger-50 text-danger-700 |
빨간 Badge + 재시도 |
CANCELLED / ARCHIVED |
disabled | text-fg-disabled |
회색 strikethrough |
구현 컨벤션 — frontend/src/shared/ui/StatusBadge 단일 컴포넌트가 모든 매핑을 캡슐화. 새 상태 추가 시 이 컴포넌트만 수정.
서버 데이터의 4가지 상태별 UI 분기. frontend/src/shared/lib/AsyncBoundary 로 일원화.
| 상태 | UI | 컴포넌트 |
|---|---|---|
| Loading (Pending) | shape-mimicking placeholder | Skeleton |
| Empty | 아이콘 + 설명 + CTA | EmptyState |
| Error (Rejected) | 메시지 + 재시도 버튼 | Alert (또는 rejectedFallback) |
| Success | 정상 컨텐츠 | (각 페이지 자체) |
<AsyncBoundary
pendingFallback={<ResumeListSkeleton />}
rejectedFallback={({ error, reset }) => (
<ErrorState error={error} onRetry={reset} />
)}
>
<ResumeList />
</AsyncBoundary>상세: frontend/src/shared/CLAUDE.md, docs/ui-patterns.md.
┌────────────────────────────────────────────────────┐
│ TopNav (height: 64px, sticky, z-sticky) │
├──────────┬─────────────────────────────────────────┤
│ │ │
│ SideNav │ Main Content │
│ (240px) │ - max-w-content (1280px) │
│ │ - px-6 lg:px-12, py-12 │
│ │ │
└──────────┴─────────────────────────────────────────┘
화면 제목 블록은 항상 PageHeader (§3 Editorial). 컨테이너는 max-w-content px-6 lg:px-12.
페이지 배경은 랜딩과 같은 두 단계를 번갈아 쓴다 — bg-surface-raised(기본 콘텐츠 화면)
· bg-surface(워크스페이스 본문처럼 사이드바/카드와 대비가 필요한 면).
특수 페이지:
- Login — SideNav 없음.
SiteNav대신 같은 형태의 얇은 헤더(CTA 가 자기 자신을 가리키지 않게) +SiteFooter. - Interview — focus mode (TopNav 숨김), 배경 사진 + 스크림 위에 반투명 헤더·질문 카드. 이 화면의 고정 다크 요소(면접관 아바타, 웹캠 셀프뷰)만
sage-*를 쓴다. - Feedback Report — TopNav 만, 인쇄 친화 (
@media print).
<html data-theme="light|dark">토글.prefers-color-scheme자동 감지 + 사용자 명시 선택 우선.- 토큰만 갱신 (컴포넌트 코드 수정 X) —
[data-theme='dark'] { --color-bg: ...; ... }. - 면접 진행 중 다크 모드 강제 옵션 검토 (눈 피로 감소).
다크 토큰 정의는 Phase 2 진입 시 frontend/src/app/styles/tokens.css 에 추가.
| CSS Variable | Tailwind Utility |
|---|---|
--color-sage-{50..950} |
bg-sage-{n}, text-sage-{n}, border-sage-{n} |
--color-primary / --color-fg / --color-bg |
bg-primary / text-fg / bg-bg |
--color-success / --color-success-50 / --color-success-700 |
bg-success / bg-success-50 / text-success-700 |
--color-job-frontend |
bg-job-frontend, text-job-frontend |
--font-heading / --font-sans / --font-mono |
font-heading / font-sans / font-mono |
--text-display (+ paired LH / letter / weight) |
text-display |
--radius-md / --radius-pill |
rounded-md / rounded-pill |
--shadow-md / --shadow-focus-ring |
shadow-md / shadow-focus-ring |
--duration-normal / --ease-standard |
duration-normal / ease-standard |
--container-content / --container-readable |
max-w-content / max-w-readable |
--z-modal / --z-toast |
z-[var(--z-modal)] (namespace 미생성) |
원칙 — 컴포넌트는 utility class 만 사용. bg-[#626e5c] 같은 직접 hex 사용 금지.
- 키보드만으로 모든 액션 가능 (
tab,enter,esc, 화살표). - focus-visible 명확 (
outline: 2px solid var(--color-primary)—global.cssdefault). - semantic HTML (
<button>대신<div onClick>금지,<a>vs<button>구분). -
aria-label/aria-describedby명시 (의미 전달 필요 시). - 명도 대비 — 텍스트 4.5:1, 큰 텍스트 (≥ 18.66px or ≥ 14px bold) 3:1.
- form 은
<label htmlFor>또는aria-label필수. - 동적 콘텐츠는
aria-live="polite"영역. -
prefers-reduced-motion대응 (전역 —global.css). - 모달 / Drawer 는 focus trap +
esc닫기.
- Figma 디자인 확정 → 토큰만 사용하는지 검증 (하드코딩 X).
- 디렉토리 생성 —
frontend/src/shared/ui/{Name}/{Name}.tsx,{Name}.test.tsx,{Name}.stories.tsx(옵션),index.ts.
- Props minimal — variant 는 union string (
"primary" | "secondary"). - 본 문서 §3 인벤토리 등록.
- PR 시 스크린샷 첨부 (light, 향후 dark 도입 시 양쪽).
| 작업 | 위치 |
|---|---|
| 토큰 추가 / 변경 | frontend/src/app/styles/tokens.css + 본 문서 §2 |
| 글로벌 스타일 (reset, base) | frontend/src/app/styles/global.css |
| 신규 공통 컴포넌트 | frontend/src/shared/ui/{Name}/ |
| 도메인 컴포넌트 | frontend/src/features/{domain}/ui/ |
| 데모 페이지 확인 | npm run dev (frontend) → http://localhost:5173 |
| 폰트 추가 | frontend/index.html <link> + tokens.css --font-* |
-
2026-08 — 랜딩 조판을 전 화면에 확장: 랜딩만 새 언어(모노 라벨 ·
clamp()헤딩 · 헤어라인 표면)를 쓰고 나머지 화면은 이전 언어(font-heading+uppercase tracking-[0.22em]+rounded-2xl+shadow)에 남아 있어, 같은 서비스가 두 벌의 디자인을 갖고 있었다. 랜딩 조판을Eyebrow/Heading/Panel/PageHeader프리미티브로 추출하고(§3 Editorial) 로그인·워크스페이스·면접 설정/진행·피드백·연습·404·디자인시스템 화면 전부에 적용. 겸사로 고정sage-*를 표면/장식 의미로 쓰던 자리(워크스페이스 배너, 면접 스테이지의 로딩 점·이퀄라이저·모드 토글)를 시맨틱 토큰으로 교체 — 다크에서 반전되지 않아 배경에 묻히던 것들이다.ColorModeToggle을shared/ui로 올려 SiteNav 를 쓰지 않는 화면에서도 모드 전환이 사라지지 않게 했다. -
2026-08 — 접근성 감사(WCAG AA) 후 컬러 재매핑: axe-core 로 전 페이지를 라이트·다크 양쪽 스캔한 결과 페이지당 최대 29건의
color-contrast위반이 있었다. 원인은 SEED 시맨틱을 1:1로 매핑한 것 — SEED 의fg-neutral-subtle(gray-700)·fg-placeholder(gray-600)는 흰 배경 대비가 3.42:1·2.10:1 이라 12px 캡션에 쓰면 AA 미달이었다. 텍스트 사다리를 한 단계씩 어둡게 재매핑하고(fg-muted→gray-800 6.62:1,fg-subtle→color-mix5.36:1), Status 의-700을fg-*-contrast로 교체했다(weak 틴트 위 3.383.84:1 → 8.059.61:1). 장식용 대형 텍스트를 위해fg-faint(3.42:1, AA-large 전용) 추가. 결과: 전 페이지 양 모드 위반 0건. -
2026-08 — SEED Design 토큰 채택 + 다크모드: 컬러·radius·shadow 를 당근 SEED(
@seed-design/css+@seed-design/tailwind4-theme)로 위임. 우리 alias 이름(--color-fg,--color-primary…)은 유지하고 값만var(--seed-color-*)로 교체해 컴포넌트 수정 없이 전환. 브랜드는 SEEDblue팔레트로 리테마(seed-overrides.css— carrot 대신 blue 참조).--color-primary(배경)와--color-primary-fg(텍스트)를 분리 — 다크에서 요구가 정반대라 한 토큰으로 불가능. 다크모드는<html data-seed-color-mode>로 전환(shared/lib/color-mode). 타이포그래피는 자체 스케일 유지. -
2026-06 — 블루 리테마: 브랜드 블루(#4662D2)에 맞춰
sage-*스케일 값을 쿨 블루그레이 모노크롬으로 교체(토큰명 유지),primary를 스케일에서 분리해 로고 블루로 지정. 배경/그림자/포커스링도 쿨톤·네이비로 재조정. 위젯 하드코딩 hex 일괄 치환. Status / Domain 컬러는 유지. -
2026-05 — Tailwind CSS v4 기반 sage 모노크로매틱 시스템으로 전면 개편. 이전
Pretendard + 블루 브랜드스펙은 본 문서로 흡수. -
2026-05 — Status / Domain 컬러를 muted jewel tone 으로 재정의 (Sage 톤과 조화).
-
2026-05 — Z-index, Container max-width, 4-State UI 패턴 등 누락 토큰 / 규약 보강.