토큰
모든 화면이 이 표 하나에서 나옵니다. 값을 바꾸면 전체가 바뀝니다.
직접 확인 — 토큰은 진짜로 작동합니다
아래 슬라이더는 문서 최상위의 CSS 토큰 값을 바꿉니다. 이 페이지의 모든 요소(상단 내비게이션·버튼·링크·표 포함)가 즉시 따라 바뀝니다 — 화면과 토큰이 한 몸이라는 증거입니다.
색 (oklch)
기본 상태는 흑백. 파랑(--primary)은 hover·포커스·강조 전용입니다.
| 토큰 | 값 | 용도 | |
|---|---|---|---|
--foreground | oklch(0.145 0 0) | 본문 텍스트 · 기본 버튼 배경 | |
--primary | oklch(0.55 0.18 250) | 블루 — hover·포커스·강조 전용 | |
--primary-muted | oklch(0.92 0.04 250) | 블루 배경 (hover·selection) | |
--muted | oklch(0.97 0 0) | 옅은 회색 배경 | |
--muted-foreground | oklch(0.556 0 0) | 보조 텍스트 | |
--border | oklch(0.922 0 0) | 모든 테두리 | |
--ok | oklch(0.62 0.17 150) | 성공 | |
--err | oklch(0.58 0.21 25) | 오류 | |
--canvas | oklch(0.98 0 0) | 카드 밖 페이지 배경 |
타이포그래피
Geist + Pretendard. 워드마크는 The(500) + Noun(750) + 마침표.
형태 · 모션
--radius | 0.5rem | 카드 |
--radius-btn | 6px | 버튼 |
--radius-input | 7px | 입력 |
--radius-pill | 999px | 칩 |
--ts | all 0.4s cubic-bezier(0.16,1,0.3,1) | |
| 등장 | tn-fadeUp — translateY 14px→0 · 0.55s | |
| 그림자 | 카드 0 1px 3px 5% · 버튼 hover 0 4px 12px primary 25% | |
간격
간격은 아래 7단계만 사용합니다. 임의 값(0.65rem, 13px 등)을 만들지 않습니다.
| 단계 | 값 | 용도 | |
|---|---|---|---|
| xs | 0.35rem | 아이콘–레이블 사이 · 칩 내부 | |
| sm | 0.5rem | 버튼 나열 · 인접 요소 | |
| md | 0.7rem | 레이블–입력 사이 · 리스트 행 간 | |
| lg | 0.9rem | 카드 내부 블록 간 | |
| xl | 1.2rem | 카드 패딩 (표준 1.2~1.5rem) | |
| 2xl | 2rem | 섹션 제목 위 여백 | |
| 3xl | 3.5rem | 섹션 사이 · 히어로 아래 |
그리드 gap은 1rem 하나로 통일한다. 관련 있는 것끼리는 좁게, 관련 없는 것끼리는 넓게 — 위계는 간격으로 만든다.
px와 rem을 섞어 새 값을 만들지 않는다. 여백 대신 구분선(Divider)을 남발하지 않는다 — 간격으로 충분하면 선은 없앤다.
레이아웃
모든 페이지는 같은 컨테이너 폭과 같은 브레이크포인트를 씁니다.
| 페이지 최대폭 | 1060px | 중앙 정렬 + 좌우 1.5rem |
| 앱 셸 사이드바 | 228px | 고정폭 · 860px 이하에서 숨김 |
| 미니앱 프레임 | 340px | 채팅 안 미니앱 폭 |
.grid2 / .grid3 | 1fr 균등분할 · gap 1rem | |
760px | 이하에서 모든 그리드 1열로 | |
860px | 이하에서 사이드바 숨김 | |
가로 스크롤은 페이지가 아니라 컨테이너가 가진다 — 넓은 표·코드·다이어그램은 overflow-x:auto 박스 안에 넣는다.
한 화면의 콘텐츠 열은 최대 3열까지. 4열 이상이 필요하면 화면을 나누는 것부터 검토한다.
다크 모드
색은 반드시 토큰으로만 씁니다. 토큰을 지키면 다크 모드는 공짜로 얻습니다 — :root[data-theme="dark"]가 값만 바꿉니다.
| 토큰 | 라이트 | 다크 | 비고 |
|---|---|---|---|
--background | oklch(1 0 0) | oklch(0.17 0 0) | |
--foreground | oklch(0.145 0 0) | oklch(0.93 0 0) | 텍스트 · 기본 버튼 배경 |
--card | oklch(1 0 0) | oklch(0.205 0 0) | |
--primary | oklch(0.55 0.18 250) | oklch(0.64 0.15 250) | 다크에선 더 밝고 덜 진하게 |
--border | oklch(0.922 0 0) | oklch(0.30 0 0) | |
--on-foreground | #fff | oklch(0.17 0 0) | ⚠️ 검정 배경 위 글자는 항상 이 토큰 |
var(--foreground) 배경 위 텍스트는 var(--on-foreground). 새 색이 필요하면 토큰을 추가하고 다크 값도 같이 정의한다.
color:var(--on-foreground), background:#000 같은 하드코딩 금지 — 다크 모드에서 즉시 깨진다. 컴포넌트 안에서 라이트/다크를 if로 분기하지 않는다.
접근성
사람과 에이전트 모두가 조작할 수 있어야 합니다. 최소 기준 5가지.
| 항목 | 기준 |
|---|---|
| 포커스 | 입력·선택 요소는 포커스 시 border-color:var(--primary). 포커스 표시를 없애지 않는다 (outline:none 단독 금지) |
| 대비 | 본문 텍스트 4.5:1 이상. 보조 텍스트(--muted-foreground)는 캡션·설명에만 — 본문 대체 금지 |
| 클릭 영역 | 버튼·아이콘 버튼 최소 32×32px. 텍스트 링크만으로 중요한 행동을 처리하지 않는다 |
| 레이블 | 아이콘만 있는 버튼은 aria-label 필수. 입력은 항상 보이는 레이블 — placeholder를 레이블 대용으로 쓰지 않는다 |
| 다이얼로그 | 네이티브 alert/confirm/prompt 금지 → Alert Dialog. ESC로 닫히고 포커스가 원래 자리로 돌아온다 |
보이스 & 톤
화면의 모든 문장은 격식 있는 한국어로, 필요한 정보만 씁니다.
| 자리 | 규칙 | 예 |
|---|---|---|
| 버튼 | 명사형 동작, 2~4자 | 전송 · 저장 · 예약 확정 |
| 제목 | 명사구, 마침표 없음 | 화면 패턴 · 상담 기록 |
| 본문·안내 | 합니다체, 한 문장에 한 정보 | 업로드가 완료되었습니다. |
| 에러 | 원인 + 다음 행동, 사과·감탄 금지 | 파일이 10GB를 넘습니다. 나눠서 올려 주세요. |
| 빈 상태 | 이유 한 줄 + 행동 1개 | 아직 에이전트가 없습니다. 첫 에이전트를 만들어 보세요. |
숫자·날짜·코드성 값은 mono 서체. 사용자를 부를 때는 "고객님"이 아니라 문장 구조로 생략한다.
이모지·느낌표·"~해 보세요!" 류의 들뜬 어투 금지. 영어 남용 금지 — 고유명사(Flow Editor 등) 외에는 한국어로.
워드마크
브랜드 표기는 한 가지뿐입니다.
- 텍스트 표기는 항상 TheNoun. — 마침표까지가 이름
- 마침표는
var(--primary), 본문 색으로 쓰지 않는다 - 띄어쓰기·소문자 변형 금지 (The Noun, thenoun ×) — 도메인만 예외
- 마스코트는 좌측, 워드마크는 우측 — 순서를 바꾸지 않는다