diff --git a/docs/design-system.md b/docs/design-system.md index cbafd6c9..2b3fd549 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -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`)에서도 깨지지 않게. @@ -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}`. @@ -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 @@ -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 패턴 등 누락 토큰 / 규약 보강. diff --git a/frontend/src/app/styles/tokens.css b/frontend/src/app/styles/tokens.css index c76544c4..447633ee 100644 --- a/frontend/src/app/styles/tokens.css +++ b/frontend/src/app/styles/tokens.css @@ -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 @@ -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) @@ -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 diff --git a/frontend/src/pages/DesignSystem/lib.ts b/frontend/src/pages/DesignSystem/lib.ts index 868c8698..8d120da5 100644 --- a/frontend/src/pages/DesignSystem/lib.ts +++ b/frontend/src/pages/DesignSystem/lib.ts @@ -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' } diff --git a/frontend/src/pages/DesignSystem/sections/Colors.tsx b/frontend/src/pages/DesignSystem/sections/Colors.tsx index d9399766..43ac7be4 100644 --- a/frontend/src/pages/DesignSystem/sections/Colors.tsx +++ b/frontend/src/pages/DesignSystem/sections/Colors.tsx @@ -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 = [ diff --git a/frontend/src/pages/DesignSystem/sections/ZIndex.tsx b/frontend/src/pages/DesignSystem/sections/ZIndex.tsx index 5b2218fc..410fe355 100644 --- a/frontend/src/pages/DesignSystem/sections/ZIndex.tsx +++ b/frontend/src/pages/DesignSystem/sections/ZIndex.tsx @@ -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', }} > diff --git a/frontend/src/widgets/home-cta/ui/HomeCta.tsx b/frontend/src/widgets/home-cta/ui/HomeCta.tsx index 226afca2..6f033a0f 100644 --- a/frontend/src/widgets/home-cta/ui/HomeCta.tsx +++ b/frontend/src/widgets/home-cta/ui/HomeCta.tsx @@ -37,7 +37,7 @@ export function HomeCta() { Get Started
diff --git a/frontend/src/widgets/home-services/ui/HomeServices.tsx b/frontend/src/widgets/home-services/ui/HomeServices.tsx index e64274e6..33e0afea 100644 --- a/frontend/src/widgets/home-services/ui/HomeServices.tsx +++ b/frontend/src/widgets/home-services/ui/HomeServices.tsx @@ -57,7 +57,7 @@ function CardInner({ card }: { card: ServiceCard }) { }} /> - + {card.tag} diff --git a/frontend/src/widgets/site-footer/ui/SiteFooter.tsx b/frontend/src/widgets/site-footer/ui/SiteFooter.tsx index 8e534aa7..39aa1507 100644 --- a/frontend/src/widgets/site-footer/ui/SiteFooter.tsx +++ b/frontend/src/widgets/site-footer/ui/SiteFooter.tsx @@ -51,7 +51,7 @@ export function SiteFooter() { Get Started {loggingOut ? '로그아웃 중…' : 'Logout'} @@ -87,7 +87,7 @@ export function SiteNav() { Get Started