Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions docs/design-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
1. **신뢰감 우선** — 면접 도구이므로 가벼운 톤 지양. 진중·차분한 시각 언어.
2. **집중 환경 보호** — 면접 화면은 노이즈 최소화. 핵심 UI만 노출, 부가 정보는 hover/click 으로 점진적 공개.
3. **상태 가시성** — 분석 진행, 세션 상태, SSE 이벤트 등 비동기 상태는 항상 명시적으로 표현.
4. **모노크로매틱 + 의미 컬러** — Sage 단일 베이스로 톤 일관성을 유지하고, Status / Domain 만 muted jewel tone 으로 식별성 부여.
4. **모노크로매틱 + 의미 컬러** — 로고 블루(#3E63D8) 기반 **쿨 블루그레이** 단일 베이스(토큰명은 `sage-*` 유지)로 톤 일관성을 유지하고, 브랜드 강조는 로고 블루 `primary`, Status / Domain 만 muted jewel tone 으로 식별성 부여.
5. **접근성 (WCAG 2.1 AA)** — 키보드 only 조작, 명도 대비 4.5:1 이상, focus ring 명확.
6. **모바일 웹뷰 대응** — 데스크탑 우선이지만 mobile breakpoint(`< lg`)에서도 깨지지 않게.

Expand All @@ -28,23 +28,25 @@
|---|---|---|---|
| `--color-white` | `#ffffff` | `bg-white`, `text-white` | 순백 |
| `--color-black` | `#000000` | `bg-black` | 순흑 |
| `--color-background` | `#e9e8e7` | `bg-background` (= `bg-bg`) | 앱 기본 배경 |
| `--color-background` | `#eceef3` | `bg-background` (= `bg-bg`) | 앱 기본 배경 (쿨 라이트) |

### 2.2 컬러 — Sage Scale (메인 테마, 11 단계)

> 토큰 이름은 `sage-*` 로 유지하되 **값은 로고(#3E63D8)에 맞춘 쿨 블루그레이 모노크롬** 이다(저채도 — 중립/본문용). 브랜드 강조색은 별도 `primary` (아래 §2.3, 스케일과 분리).

| 토큰 | Hex | 권장 용도 |
|---|---|---|
| `sage-50` | `#e8e7e1` | 가장 밝은 컴포넌트 배경 (= `surface`) |
| `sage-100` | `#d4cfcb` | 분리선 / 보더 (= `border`) |
| `sage-200` | `#c9ccc8` | 비활성 텍스트 / 보조 배경 (= `border-strong`, `fg-disabled`) |
| `sage-300` | `#b4bdaf` | 비활성 보조 / placeholder |
| `sage-400` | `#a0a89d` | 보조 텍스트 (= `fg-subtle`) |
| `sage-500` | `#626e5c` | **Primary**, 활성 / 포커스, 본문 보조 텍스트 (= `fg-muted`) |
| `sage-600` | `#3e4739` | Primary hover |
| `sage-700` | `#2b3625` | Primary pressed / 강조 컴포넌트 |
| `sage-800` | `#1f271b` | 주요 헤딩 (= `fg-strong`) |
| `sage-900` | `#181e15` | 본문 (대안) |
| `sage-950` | `#141a11` | 가장 어두운 텍스트 (= `fg`, 기본) |
| `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}`.

Expand All @@ -65,9 +67,9 @@ Tailwind 사용: `bg-sage-{n}`, `text-sage-{n}`, `border-sage-{n}`.
| `--color-fg-subtle` | `sage-400` | `text-fg-subtle` |
| `--color-fg-disabled` | `sage-200` | `text-fg-disabled` |
| `--color-fg-on-primary` | `white` | `text-fg-on-primary` |
| `--color-primary` | `sage-500` | `bg-primary`, `text-primary` |
| `--color-primary-hover` | `sage-600` | `bg-primary-hover` |
| `--color-primary-pressed` | `sage-700` | `bg-primary-pressed` |
| `--color-primary` | `#3e63d8` (로고 블루, 스케일과 분리) | `bg-primary`, `text-primary` |
| `--color-primary-hover` | `#3050be` | `bg-primary-hover` |
| `--color-primary-pressed` | `#274099` | `bg-primary-pressed` |

### 2.4 컬러 — Status

Expand Down Expand Up @@ -410,6 +412,7 @@ Tailwind v4 기본 `--spacing: 0.25rem` (= 4px) 사용. `p-4` = `16px`.

## 12. 변경 이력

- **2026-06** — **블루 리테마**: 로고(#3E63D8)에 맞춰 `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 패턴 등 누락 토큰 / 규약 보강.
46 changes: 25 additions & 21 deletions frontend/src/app/styles/tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,25 @@
* ========================================================= */
--color-white: #ffffff;
--color-black: #000000;
--color-background: #e9e8e7;
--color-background: #eceef3;

/* =========================================================
* 2. Color — Sage / Neutral Scale (Main Theme)
* bg-sage-500, text-sage-800, border-sage-200 ...
* NOTE: 토큰 이름은 'sage' 로 유지하되 값은 로고(#3E63D8)에 맞춘
* 쿨 블루그레이 모노크롬 램프다(저채도 — 본문/중립용). 브랜드 강조색은 §3 primary.
* ========================================================= */
--color-sage-50: #e8e7e1;
--color-sage-100: #d4cfcb;
--color-sage-200: #c9ccc8;
--color-sage-300: #b4bdaf;
--color-sage-400: #a0a89d;
--color-sage-500: #626e5c;
--color-sage-600: #3e4739;
--color-sage-700: #2b3625;
--color-sage-800: #1f271b;
--color-sage-900: #181e15;
--color-sage-950: #141a11;
--color-sage-50: #eef1f6;
--color-sage-100: #dbe2ec;
--color-sage-200: #c6cedd;
--color-sage-300: #9fafc9;
--color-sage-400: #6e7f9f;
--color-sage-500: #4a5a7e;
--color-sage-600: #38486a;
--color-sage-700: #2b3a59;
--color-sage-800: #1e2a44;
--color-sage-900: #161f33;
--color-sage-950: #101627;

/* =========================================================
* 3. Color — Semantic Aliases
Expand All @@ -47,9 +49,11 @@
--color-fg-disabled: var(--color-sage-200);
--color-fg-on-primary: var(--color-white);

--color-primary: var(--color-sage-500);
--color-primary-hover: var(--color-sage-600);
--color-primary-pressed: var(--color-sage-700);
/* 브랜드 강조색 — 로고 블루(#3E63D8). 중립 스케일과 분리(고채도라 본문엔 미사용,
* 버튼·링크·강조에만). bg-primary / text-primary / border-primary 가 이 값을 쓴다. */
--color-primary: #3e63d8;
--color-primary-hover: #3050be;
--color-primary-pressed: #274099;

/* =========================================================
* 4. Color — Status (Success / Warning / Danger / Info)
Expand Down Expand Up @@ -201,14 +205,14 @@
* 9. Shadow / Elevation (sage-tint)
* shadow-sm, shadow-md, shadow-lg, shadow-focus-ring
* ========================================================= */
--shadow-sm: 0 1px 2px rgba(31, 39, 27, 0.06);
--shadow-sm: 0 1px 2px rgba(16, 22, 39, 0.06);
--shadow-md:
0 4px 6px -1px rgba(31, 39, 27, 0.10),
0 2px 4px -2px rgba(31, 39, 27, 0.06);
0 4px 6px -1px rgba(16, 22, 39, 0.10),
0 2px 4px -2px rgba(16, 22, 39, 0.06);
--shadow-lg:
0 10px 15px -3px rgba(31, 39, 27, 0.10),
0 4px 6px -4px rgba(31, 39, 27, 0.05);
--shadow-focus-ring: 0 0 0 3px rgba(98, 110, 92, 0.45);
0 10px 15px -3px rgba(16, 22, 39, 0.10),
0 4px 6px -4px rgba(16, 22, 39, 0.05);
--shadow-focus-ring: 0 0 0 3px rgba(62, 99, 216, 0.45);

/* =========================================================
* 10. Motion
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/DesignSystem/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ export function luminance(hex: string): number {
}

export function readableFg(hex: string): string {
return luminance(hex) > 0.45 ? '#1f271b' : '#ffffff'
return luminance(hex) > 0.45 ? '#1e2a44' : '#ffffff'
}
46 changes: 23 additions & 23 deletions frontend/src/pages/DesignSystem/sections/Colors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,33 @@ import { Code, Section, Sub, Swatch, TableHead } from '../primitives'
import { readableFg } from '../lib'

const SAGE_SCALE = [
{ token: 'sage-50', hex: '#e8e7e1' },
{ token: 'sage-100', hex: '#d4cfcb' },
{ token: 'sage-200', hex: '#c9ccc8' },
{ token: 'sage-300', hex: '#b4bdaf' },
{ token: 'sage-400', hex: '#a0a89d' },
{ token: 'sage-500', hex: '#626e5c' },
{ token: 'sage-600', hex: '#3e4739' },
{ token: 'sage-700', hex: '#2b3625' },
{ token: 'sage-800', hex: '#1f271b' },
{ token: 'sage-900', hex: '#181e15' },
{ token: 'sage-950', hex: '#141a11' },
{ token: 'sage-50', hex: '#eef1f6' },
{ token: 'sage-100', hex: '#dbe2ec' },
{ token: 'sage-200', hex: '#c6cedd' },
{ token: 'sage-300', hex: '#9fafc9' },
{ token: 'sage-400', hex: '#6e7f9f' },
{ token: 'sage-500', hex: '#4a5a7e' },
{ token: 'sage-600', hex: '#38486a' },
{ token: 'sage-700', hex: '#2b3a59' },
{ token: 'sage-800', hex: '#1e2a44' },
{ token: 'sage-900', hex: '#161f33' },
{ token: 'sage-950', hex: '#101627' },
]

const SEMANTIC_ROWS = [
{ token: 'bg', alias: 'background', hex: '#e9e8e7', usage: '앱 기본 배경' },
{ token: 'surface', alias: 'sage-50', hex: '#e8e7e1', usage: '컴포넌트 배경' },
{ token: 'bg', alias: 'background', hex: '#eceef3', usage: '앱 기본 배경' },
{ token: 'surface', alias: 'sage-50', hex: '#eef1f6', usage: '컴포넌트 배경' },
{ token: 'surface-raised', alias: 'white', hex: '#ffffff', usage: '카드 · 모달' },
{ token: 'border', alias: 'sage-100', hex: '#d4cfcb', usage: '기본 보더' },
{ token: 'border-strong', alias: 'sage-200', hex: '#c9ccc8', usage: '강조 보더' },
{ token: 'fg', alias: 'sage-950', hex: '#141a11', usage: '기본 텍스트' },
{ token: 'fg-strong', alias: 'sage-800', hex: '#1f271b', usage: '헤딩' },
{ token: 'fg-muted', alias: 'sage-400', hex: '#a0a89d', usage: '보조 텍스트' },
{ token: 'fg-subtle', alias: 'sage-300', hex: '#b4bdaf', usage: '흐린 텍스트' },
{ token: 'fg-disabled', alias: 'sage-200', hex: '#c9ccc8', usage: '비활성' },
{ token: 'primary', alias: 'sage-500', hex: '#626e5c', usage: 'Primary 액션' },
{ token: 'primary-hover', alias: 'sage-600', hex: '#3e4739', usage: 'hover' },
{ token: 'primary-pressed', alias: 'sage-700', hex: '#2b3625', usage: 'active' },
{ token: 'border', alias: 'sage-100', hex: '#dbe2ec', usage: '기본 보더' },
{ token: 'border-strong', alias: 'sage-200', hex: '#c6cedd', usage: '강조 보더' },
{ token: 'fg', alias: 'sage-950', hex: '#101627', usage: '기본 텍스트' },
{ token: 'fg-strong', alias: 'sage-800', hex: '#1e2a44', usage: '헤딩' },
{ token: 'fg-muted', alias: 'sage-500', hex: '#4a5a7e', usage: '보조 텍스트' },
{ token: 'fg-subtle', alias: 'sage-400', hex: '#6e7f9f', usage: '흐린 텍스트' },
{ token: 'fg-disabled', alias: 'sage-200', hex: '#c6cedd', usage: '비활성' },
{ token: 'primary', alias: '브랜드 블루(로고)', hex: '#3e63d8', usage: 'Primary 액션·링크·강조' },
{ token: 'primary-hover', alias: '', hex: '#3050be', usage: 'hover' },
{ token: 'primary-pressed', alias: '', hex: '#274099', usage: 'active' },
]

const STATUS_COLORS = [
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/DesignSystem/sections/ZIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function ZIndexSection() {
className="flex items-center gap-3 px-3 py-1.5 rounded-sm"
style={{
backgroundColor: `rgba(98,110,92,${intensity})`,
color: intensity > 0.5 ? '#ffffff' : '#1f271b',
color: intensity > 0.5 ? '#ffffff' : '#1e2a44',
}}
>
<span className="font-mono text-[11px] w-10 text-right shrink-0">
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/widgets/home-cta/ui/HomeCta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function HomeCta() {

<Link
to={getStartedTo}
className="mt-10 inline-flex items-center gap-2 pl-5 pr-2 py-2.5 rounded-pill bg-[#e6dfd4] text-sage-900 text-button hover:bg-white transition-colors duration-fast"
className="mt-10 inline-flex items-center gap-2 pl-5 pr-2 py-2.5 rounded-pill bg-[#dbe2ec] text-sage-900 text-button hover:bg-white transition-colors duration-fast"
>
Get Started
<span
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/widgets/home-hero/ui/HomeHero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function HomeHero() {
className="relative overflow-hidden"
style={{
background:
'radial-gradient(120% 80% at 50% 0%, #f1ece4 0%, #e9e8e7 60%, #e9e8e7 100%)',
'radial-gradient(120% 80% at 50% 0%, #f3f5fa 0%, #eceef3 60%, #eceef3 100%)',
}}
>
<div
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/widgets/home-quote/ui/HomeQuote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ export function HomeQuote() {
className="absolute inset-0"
style={{
background:
'radial-gradient(120% 80% at 20% 30%, #2b3625 0%, #1f271b 60%, #141a11 100%)',
'radial-gradient(120% 80% at 20% 30%, #2b3a59 0%, #1e2a44 60%, #101627 100%)',
}}
/>
<div
aria-hidden
className="absolute inset-0 opacity-[0.35] mix-blend-screen"
style={{
background:
'radial-gradient(40% 35% at 70% 25%, #c9ccc8 0%, transparent 60%),' +
'radial-gradient(50% 40% at 30% 80%, #626e5c 0%, transparent 65%)',
'radial-gradient(40% 35% at 70% 25%, #c6cedd 0%, transparent 60%),' +
'radial-gradient(50% 40% at 30% 80%, #4a5a7e 0%, transparent 65%)',
}}
/>
<div className="relative h-full flex items-end p-8 lg:p-10">
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/widgets/home-services/ui/HomeServices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function CardInner({ card }: { card: ServiceCard }) {
}}
/>

<span className="absolute top-4 left-4 px-3 py-1 rounded-pill bg-[#e6dfd4] text-sage-900 text-caption font-medium">
<span className="absolute top-4 left-4 px-3 py-1 rounded-pill bg-[#dbe2ec] text-sage-900 text-caption font-medium">
{card.tag}
</span>

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/widgets/site-footer/ui/SiteFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function SiteFooter() {
</h2>
<Link
to={getStartedTo}
className="inline-flex self-start lg:self-end items-center gap-2 pl-5 pr-2 py-2.5 rounded-pill bg-[#e6dfd4] text-sage-900 text-button hover:bg-white transition-colors duration-fast"
className="inline-flex self-start lg:self-end items-center gap-2 pl-5 pr-2 py-2.5 rounded-pill bg-[#dbe2ec] text-sage-900 text-button hover:bg-white transition-colors duration-fast"
>
Get Started
<span
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/widgets/site-nav/ui/SiteNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function SiteNav() {
onClick={logout}
disabled={loggingOut}
aria-busy={loggingOut}
className="inline-flex items-center gap-2 pl-5 pr-5 py-2 rounded-pill bg-[#e6dfd4] text-sage-900 text-button hover:bg-[#dcd4c6] transition-colors duration-fast disabled:opacity-60 disabled:cursor-not-allowed"
className="inline-flex items-center gap-2 pl-5 pr-5 py-2 rounded-pill bg-[#dbe2ec] text-sage-900 text-button hover:bg-[#c6cedd] transition-colors duration-fast disabled:opacity-60 disabled:cursor-not-allowed"
>
{loggingOut ? '로그아웃 중…' : 'Logout'}
</button>
Expand All @@ -87,7 +87,7 @@ export function SiteNav() {
</Link>
<Link
to="/login"
className="inline-flex items-center gap-2 pl-5 pr-2 py-2 rounded-pill bg-[#e6dfd4] text-sage-900 text-button hover:bg-[#dcd4c6] transition-colors duration-fast"
className="inline-flex items-center gap-2 pl-5 pr-2 py-2 rounded-pill bg-[#dbe2ec] text-sage-900 text-button hover:bg-[#c6cedd] transition-colors duration-fast"
>
Get Started
<span
Expand Down