wing-ops/docs/DESIGN-SYSTEM.md

566 lines
25 KiB
Markdown

# WING-OPS 디자인 시스템
## 개요
WING-OPS UI 디자인 시스템의 비주얼 레퍼런스 카탈로그.
시맨틱 토큰 기반 다크/라이트 테마 전환을 지원한다.
---
## 버전 히스토리
### v1.1 — 시맨틱 토큰 & 테마 시스템 (2026-03-28~)
> 브랜치: `feature/predict-develop`, `feature/design-system-font`
v1.0의 축약형 토큰 시스템을 시맨틱 네이밍으로 전면 전환하고, 다크/라이트 테마 전환 기능을 도입한 구조적 리팩토링.
#### 변경된 점
| 항목 | v1.0 | v1.1 |
|------|------|------|
| 토큰 네이밍 | 축약형 (`--bg0`, `--t1`, `--cyan`) | 시맨틱 (`--bg-base`, `--fg-default`, `--color-accent`) |
| 폰트 | Outfit + Noto Sans KR + JetBrains Mono (3종) | PretendardGOV 단일 폰트 (4웨이트) |
| 테마 | 다크 모드 전용 (하드코딩) | 다크/라이트 전환 지원 (`data-theme` 속성) |
| 프리미티브 팔레트 | 7그룹 11단계 (Navy/Cyan/Blue/Red/Green/Orange/Yellow, 00~100) | 6그룹 10단계 (Gray/Blue/Green/Yellow/Red/Purple, 100~1000) |
| 텍스트 대비 | `--t2: #b0b8cc`, `--t3: #8690a6` | `--fg-sub: #c0c8dc`, `--fg-disabled: #9ba3b8` (대비 향상) |
| 버튼 스타일 | `.prd-btn.pri` 그라데이션 (cyan→blue) | 아웃라인/고스트 스타일 |
| Tailwind 컬러 키 | 하드코딩 hex (`bg.0`, `text.1`, `primary.cyan`) | CSS 변수 참조 (`bg.base`, `fg.DEFAULT`, `color.accent`) |
| 폰트 유틸리티 | 하드코딩 (`font-family: 'JetBrains Mono'`) | CSS 변수 경유 (`font-family: var(--font-mono)`) |
#### 토큰 마이그레이션 매핑
| v1.0 | v1.1 | 설명 |
|------|------|------|
| `--bg0` | `--bg-base` | 페이지 배경 |
| `--bg1` | `--bg-surface` | 사이드바, 패널 |
| `--bg2` | `--bg-elevated` | 테이블 헤더, 상위 요소 |
| `--bg3` | `--bg-card` | 카드 배경 |
| `--bgH` | `--bg-surface-hover` | 호버 상태 |
| `--bd` | `--stroke-default` | 기본 구분선 |
| `--bdL` | `--stroke-light` | 연한 구분선 |
| `--t1` | `--fg-default` | 기본 텍스트 |
| `--t2` | `--fg-sub` | 보조 텍스트 |
| `--t3` | `--fg-disabled` | 비활성 텍스트 |
| `--cyan` | `--color-accent` | 주요 강조 |
| `--blue` | `--color-info` | 정보, 링크 |
| `--red` | `--color-danger` | 위험, 삭제 |
| `--orange` | `--color-warning` | 주의 |
| `--yellow` | `--color-caution` | 경고 |
| `--green` | `--color-success` | 성공, 정상 |
| `--purple` | `--color-tertiary` | 3차 강조 |
| `--boom` | `--color-boom` | 오일붐 전용 |
| `--fK` | `--font-korean` | 한국어 폰트 스택 |
| `--fM` | `--font-mono` | 모노 폰트 스택 |
| `--rS` | `--radius-sm` | 소형 border radius |
| `--rM` | `--radius-md` | 중형 border radius |
#### 추가된 기능
- **다크/라이트 테마 전환**: `themeStore.ts` (Zustand) + `data-theme` DOM 속성 + FOUC 방지 인라인 스크립트
- **시맨틱 오버레이 토큰**: `--hover-overlay`, `--dropdown-bg` (테마별 불투명도 차별화)
- **Navy 액센트 토큰**: `--color-navy`, `--color-navy-hover`, `--color-accent-muted`
- **정적 컬러 토큰**: `--static-black`, `--static-white` (테마 무관 고정값)
- **타이포그래피 스케일 (17개 토큰)**: Display 3종, Heading 3종, Title 6종, Body 2종, Label 2종, Caption 1종
- **Letter-spacing 토큰 5종**: `--letter-spacing-display` (0.06em) ~ `--letter-spacing-label` (0.04em)
- **Font weight 토큰 4종**: thin(300) / regular(400) / medium(500) / bold(700)
- **Line height 토큰 4종**: tight(1.3) / snug(1.4) / normal(1.5) / relaxed(1.6)
- **Tailwind tracking 유틸리티**: `tracking-display`, `tracking-heading`, `tracking-body`, `tracking-navigation`, `tracking-label`
- **라이트 테마 컴포넌트 오버라이드**: CCTV 팝업, 날짜피커, 타임라인, 콤보박스, 좌표 표시 등
- **폰트 렌더링 최적화**: `-webkit-font-smoothing: antialiased`, `text-rendering: optimizeLegibility`
#### 업데이트된 부분
- 92개+ 컴포넌트 파일의 토큰 마이그레이션 (축약형 → 시맨틱)
- Stitch MCP 프로젝트 참조 제거 (독립 토큰 시스템으로 전환)
- DESIGN-SYSTEM.md 문서 전면 재작성
---
### v1.0 — 초기 디자인 시스템 (2026-03-24~25)
> 브랜치: `feature/stitch-mcp` | 도구: Google Stitch MCP
WING-OPS 전용 디자인 시스템의 첫 구축. CSS 변수 기반 토큰 시스템, `.wing-*` 컴포넌트 클래스, 라이브 카탈로그 뷰어를 도입.
#### 컬러 시스템
- **프리미티브 팔레트**: 7개 그룹 (Navy/Cyan/Blue/Red/Green/Orange/Yellow), 각 11단계 스케일 (00~100)
- **시맨틱 컬러**: 축약형 CSS 변수 — Background(`--bg0`~`--bgH`), Text(`--t1`~`--t3`), Border(`--bd`, `--bdL`)
- **액센트 컬러**: `--cyan`(#06b6d4), `--blue`(#3b82f6), `--red`, `--green`, `--orange`, `--yellow`, `--purple`
- **특수 컬러**: `--boom`(#f59e0b) — 오일붐 전용 Amber
#### 타이포그래피
- **3종 폰트 패밀리**: Outfit (영문 본문), Noto Sans KR (한국어), JetBrains Mono (좌표/수치)
- **10개 `.wing-*` 타이포 클래스**: `.wing-title`(15px) ~ `.wing-badge`(9px)
#### 컴포넌트 클래스
| 카테고리 | 클래스 |
|----------|--------|
| 레이아웃 셸 | `.wing-panel`, `.wing-panel-scroll`, `.wing-header-bar`, `.wing-sidebar` |
| 컨테이너 | `.wing-card`, `.wing-card-sm`, `.wing-section` |
| 버튼 | `.wing-btn`, `.wing-btn-primary` (cyan→blue 그라데이션), `-secondary`, `-outline`, `-pdf`, `-danger` |
| 입력 | `.wing-input` (cyan 포커스 링) |
| 테이블 | `.wing-table`, `.wing-th`, `.wing-td`, `.wing-tr-hover` |
| 탭 | `.wing-tab-bar`, `.wing-tab` (cyan 틴트 + 보더 활성) |
| 모달 | `.wing-overlay` (블러 백드롭), `.wing-modal`, `.wing-modal-header` |
| 유틸리티 | `.wing-divider`, `.wing-kv-row`, `.wing-kv-label`, `.wing-kv-value` |
| 뱃지/아이콘 | `.wing-badge`, `.wing-icon-badge`, `.wing-icon-badge-sm` |
#### 특수 컴포넌트
| 영역 | 클래스 접두사 | 설명 |
|------|--------------|------|
| 예측 패널 | `.prd-*` | 폼 입력, 버튼, 맵 버튼 |
| 콤보박스 | `.combo-*` | 커스텀 드롭다운 (검색 + 리스트) |
| 타임라인 | `.tlb`, `.tlt`, `.tlr`, `.tlth` | 지도 하단 재생 컨트롤 |
| 레이어 트리 | `.lyr-*` | 3단계 접이식 레이어 (색상 스와치 + 투명도) |
| 오일붐 | `.boom-*` | 오일붐 드로잉 인디케이터 |
| 역추적 | `.bt-*` | 역추적 리플레이 마커 + 속도 버튼 |
| HNS | `.hns-scn-card` | HNS 시나리오 선택 카드 |
| 모델 칩 | `.prd-mc` | 모델 선택 칩 (활성 `✓` 인디케이터) |
#### 레이아웃
- **데스크톱 전용** (≥ 1280px), Tablet/Mobile 미지원
- **7단계 z-index 레이어**: Base(0) ~ Tooltip(60)
- **Spacing**: Tailwind 기본 스케일 사용 (`gap-1`~`gap-8`)
#### Border Radius
- `rounded-sm`: **6px** (커스텀 오버라이드)
- `rounded-md`: **10px** (커스텀 오버라이드)
- 나머지 Tailwind 기본값 유지
#### 애니메이션
`fadeIn`, `fadeSlideDown`, `pulse-dot`, `pulse-border`, `comboIn`, `lyrPopIn`, `bt-collision-pulse`
#### 디자인 카탈로그
`/design` 라우트에 라이브 카탈로그 뷰어 배포:
- **Foundations 탭**: Color Palette, Typography, Radius, Layout, Overview
- **Components 탭**: Button, TextField, Overview (Button Catalog, Card, Icon Badge 섹션)
- **다크/라이트 모드 토글** 내장
- **테마 엔진**: `designTheme.ts` — 타입 안전한 `DesignTheme` 인터페이스
#### SVG 아이콘 에셋
23개 커스텀 아이콘 (`wing-` 접두사): `wing-anchor`, `wing-cargo`, `wing-chart-bar`, `wing-color-palette`, `wing-documentation`, `wing-elevation`, `wing-foundations`, `wing-layout-grid`, `wing-notification`, `wing-pdf-file`, `wing-settings`, `wing-typography`, `wing-wave-graph`
#### Stitch MCP 연동
Google Stitch 프로젝트 7개 스크린 참조:
- Design Tokens, Component Catalog (Buttons/Badges), Form Components
- Table & List Patterns, Modal Catalog, Operational Shell (Layout)
- Container & Navigation
---
## 테마 (Theme)
### 테마 전환 메커니즘
다크(기본)/라이트 2벌 테마를 CSS 변수 오버라이드 방식으로 지원한다.
```
[플래시 방지] index.html 인라인 스크립트
↓ localStorage → <html data-theme="dark|light">
[상태 관리] themeStore.ts (Zustand)
↓ toggleTheme() / setTheme()
[CSS 적용] base.css :root (dark) / [data-theme="light"] (light)
↓ CSS 변수 오버라이드
[UI 반영] 모든 컴포넌트가 var(--*) 참조 → 즉시 전환
```
#### 1단계 — FOUC 방지 (`index.html`)
```html
<script>
document.documentElement.setAttribute(
'data-theme',
localStorage.getItem('wing-theme') || 'dark'
);
</script>
```
HTML 파싱 즉시 `data-theme` 속성을 설정하여 테마 깜빡임을 방지한다.
#### 2단계 — Zustand 스토어 (`themeStore.ts`)
```ts
type ThemeMode = 'dark' | 'light';
interface ThemeState {
theme: ThemeMode;
toggleTheme: () => void; // dark ↔ light 토글
setTheme: (mode: ThemeMode) => void; // 직접 지정
}
```
- 초기값: `localStorage.getItem('wing-theme') || 'dark'`
- `toggleTheme()`: localStorage 갱신 → DOM 속성 변경 → Zustand 상태 갱신
#### 3단계 — CSS 변수 오버라이드 (`base.css`)
- `:root` — 다크 테마 (기본값)
- `[data-theme="light"]` — 라이트 테마 오버라이드
시맨틱 토큰(`--bg-*`, `--fg-*`, `--stroke-*`)만 테마별 오버라이드하고, 프리미티브 토큰(`--gray-*`, `--blue-*` 등)과 액센트 컬러(`--color-*`)는 테마 간 동일 값을 유지한다.
#### UI 진입점
TopBar 퀵메뉴에서 `toggleTheme()` 호출로 전환.
---
## Foundations
### 색상 (Color Palette)
#### 토큰 아키텍처
```
Primitive Tokens (정적) Semantic Tokens (테마 반응형)
────────────────────── ────────────────────────────
--gray-100 ~ --gray-1000 --bg-base, --bg-surface, ...
--blue-100 ~ --blue-1000 --fg-default, --fg-sub, ...
--red-100 ~ --red-1000 --stroke-default, --stroke-light
--green-100 ~ --green-1000 --hover-overlay, --dropdown-bg
--yellow-100 ~ --yellow-1000
--purple-100 ~ --purple-1000
Accent Tokens (테마 불변)
─────────────────────────
--color-accent, --color-info, ...
```
#### Semantic Colors — Background
| CSS 변수 | Tailwind 클래스 | Dark | Light | 용도 |
|----------|----------------|------|-------|------|
| `--bg-base` | `bg-bg-base` | `#0a0e1a` | `#f8fafc` | 페이지 배경 |
| `--bg-surface` | `bg-bg-surface` | `#0f1524` | `#ffffff` | 사이드바, 패널 |
| `--bg-elevated` | `bg-bg-elevated` | `#121929` | `#f1f5f9` | 테이블 헤더, 상위 요소 |
| `--bg-card` | `bg-bg-card` | `#1a2236` | `#ffffff` | 카드 배경 |
| `--bg-surface-hover` | `bg-bg-surface-hover` | `#1e2844` | `#e2e8f0` | 호버 상태 |
#### Semantic Colors — Foreground (Text)
| CSS 변수 | Tailwind 클래스 | Dark | Light | 용도 |
|----------|----------------|------|-------|------|
| `--fg-default` | `text-fg` | `#edf0f7` | `#0f172a` | 기본 텍스트, 아이콘 |
| `--fg-sub` | `text-fg-sub` | `#c0c8dc` | `#475569` | 보조 텍스트 |
| `--fg-disabled` | `text-fg-disabled` | `#9ba3b8` | `#94a3b8` | 비활성, 플레이스홀더 |
#### Semantic Colors — Border (Stroke)
| CSS 변수 | Tailwind 클래스 | Dark | Light | 용도 |
|----------|----------------|------|-------|------|
| `--stroke-default` | `border-stroke` | `#1e2a42` | `#cbd5e1` | 기본 구분선 |
| `--stroke-light` | `border-stroke-light` | `#2a3a5c` | `#e2e8f0` | 연한 구분선 |
#### Semantic Colors — Overlay
| CSS 변수 | Dark | Light | 용도 |
|----------|------|-------|------|
| `--hover-overlay` | `rgba(255,255,255,0.06)` | `rgba(0,0,0,0.04)` | 호버 오버레이 |
| `--dropdown-bg` | `rgba(18,25,41,0.97)` | `rgba(255,255,255,0.97)` | 드롭다운 배경 |
#### Accent Colors (테마 불변)
| CSS 변수 | Tailwind 클래스 | Hex | 용도 |
|----------|----------------|-----|------|
| `--color-accent` | `text-color-accent` | `#06b6d4` | 주요 강조 (Cyan) |
| `--color-accent-muted` | `bg-color-accent-muted` | `#0e7490` / `#0891b2`(light) | 차분한 강조 (버튼 배경 등) |
| `--color-info` | `text-color-info` | `#3b82f6` | 정보, 링크 (Blue) |
| `--color-tertiary` | `text-color-tertiary` | `#a855f7` | 3차 강조 (Purple) |
| `--color-danger` | `text-color-danger` | `#ef4444` | 위험, 삭제 (Red) |
| `--color-warning` | `text-color-warning` | `#f97316` | 주의 (Orange) |
| `--color-caution` | `text-color-caution` | `#eab308` | 경고 (Yellow) |
| `--color-success` | `text-color-success` | `#22c55e` | 성공, 정상 (Green) |
| `--color-boom` | `text-color-boom` | `#f59e0b` | 오일붐 전용 (Amber) |
| `--color-boom-hover` | — | `#fbbf24` | 오일붐 호버 |
| `--color-navy` | `bg-color-navy` | `#1e40af` / `#1d4ed8`(light) | Navy 버튼 배경 |
| `--color-navy-hover` | `bg-color-navy-hover` | `#1d4ed8` / `#2563eb`(light) | Navy 호버 |
#### Static Colors
| CSS 변수 | Hex | 용도 |
|----------|-----|------|
| `--static-black` | `#131415` | 테마 무관 고정 검정 |
| `--static-white` | `#ffffff` | 테마 무관 고정 흰색 |
#### Primitive Colors
UI 전반에서 직접 참조하거나 시맨틱 토큰의 원천으로 사용하는 기본 팔레트. 100~1000 (10단계).
**Gray**
| 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
| `#f1f5f9` | `#e2e8f0` | `#cbd5e1` | `#94a3b8` | `#64748b` | `#475569` | `#334155` | `#1e293b` | `#0f172a` | `#020617` |
**Blue**
| 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
| `#dbeafe` | `#bfdbfe` | `#93c5fd` | `#60a5fa` | `#3b82f6` | `#2563eb` | `#1d4ed8` | `#1e40af` | `#1e3a8a` | `#172554` |
**Green**
| 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
| `#dcfce7` | `#bbf7d0` | `#86efac` | `#4ade80` | `#22c55e` | `#16a34a` | `#15803d` | `#166534` | `#14532d` | `#052e16` |
**Yellow**
| 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
| `#fef9c3` | `#fef08a` | `#fde047` | `#facc15` | `#eab308` | `#ca8a04` | `#a16207` | `#854d0e` | `#713f12` | `#422006` |
**Red**
| 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
| `#fee2e2` | `#fecaca` | `#fca5a5` | `#f87171` | `#ef4444` | `#dc2626` | `#b91c1c` | `#991b1b` | `#7f1d1d` | `#450a0a` |
**Purple**
| 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
| `#f3e8ff` | `#e9d5ff` | `#d8b4fe` | `#c084fc` | `#a855f7` | `#9333ea` | `#7e22ce` | `#6b21a8` | `#581c87` | `#3b0764` |
---
### 타이포그래피 (Typography)
#### Font Family
| CSS 변수 | Tailwind 클래스 | 용도 |
|----------|----------------|------|
| `--font-korean` | `font-korean` | 기본 UI 텍스트, 한국어/영문 콘텐츠 |
| `--font-mono` | `font-mono` | 좌표, 수치, 데이터 값 |
| — | `font-sans` | body 기본 (PretendardGOV) |
> 모든 폰트 패밀리가 `PretendardGOV` 우선 스택으로 통일.
> `@font-face`: Regular(400), Medium(500), SemiBold(600), Bold(700) — `/fonts/PretendardGOV-*.otf`
#### Typography Categories
5가지 용도 카테고리로 타이포그래피를 구성합니다.
| 카테고리 | 토큰 | 설명 |
|----------|------|------|
| **Display** | Display 1, Display 2, Display 3 | 배너, 마케팅 등 최대 크기 텍스트 |
| **Heading** | Heading 1, Heading 2, Heading 3 | 페이지/모듈 단위 제목, 계층 설정 |
| **Body** | Body 1, Body 2, Caption | 본문/콘텐츠 텍스트 |
| **Navigation** | Title 1~6 | 사이트 내 이정표 역할 (패널 제목, 탭 버튼, 메뉴 항목 등) |
| **Label** | Label 1, Label 2 | 컴포넌트 label, placeholder, 버튼 텍스트 |
> Navigation 카테고리의 토큰은 CSS 변수명 `--font-size-title-*` / Tailwind `text-title-*`을 유지합니다.
#### Font Size Tokens
CSS 변수와 Tailwind 유틸리티가 1:1 매핑된 타이포그래피 스케일. `text-*` 클래스 사용 시 font-size, line-height, letter-spacing이 함께 적용됩니다.
**Display** — 배너, 마케팅, 랜딩 영역
| CSS 변수 | Tailwind | px | Weight | Line-H | Spacing |
|----------|---------|-----|--------|--------|---------|
| `--font-size-display-1` | `text-display-1` | 60px | 700 | 1.3 | 0.06em |
| `--font-size-display-2` | `text-display-2` | 40px | 700 | 1.3 | 0.06em |
| `--font-size-display-3` | `text-display-3` | 36px | 500 | 1.4 | 0.06em |
**Heading** — 페이지/모듈 제목
| CSS 변수 | Tailwind | px | Weight | Line-H | Spacing |
|----------|---------|-----|--------|--------|---------|
| `--font-size-heading-1` | `text-heading-1` | 32px | 700 | 1.4 | 0.02em |
| `--font-size-heading-2` | `text-heading-2` | 24px | 700 | 1.4 | 0.02em |
| `--font-size-heading-3` | `text-heading-3` | 22px | 500 | 1.4 | 0.02em |
**Body** — 본문/콘텐츠
| CSS 변수 | Tailwind | px | Weight | Line-H | Spacing |
|----------|---------|-----|--------|--------|---------|
| `--font-size-body-1` | `text-body-1` | 14px | 400 | 1.6 | 0em |
| `--font-size-body-2` | `text-body-2` | 13px | 400 | 1.6 | 0em |
| `--font-size-caption` | `text-caption` | 11px | 400 | 1.5 | 0em |
**Navigation** — 패널 제목, 탭 버튼, 메뉴 항목, 소형 네비게이션
| CSS 변수 | Tailwind | px | Weight | Line-H | Spacing |
|----------|---------|-----|--------|--------|---------|
| `--font-size-title-1` | `text-title-1` | 18px | 700 | 1.5 | 0.02em |
| `--font-size-title-2` | `text-title-2` | 16px | 500 | 1.5 | 0.02em |
| `--font-size-title-3` | `text-title-3` | 14px | 500 | 1.5 | 0.02em |
| `--font-size-title-4` | `text-title-4` | 13px | 500 | 1.5 | 0.02em |
| `--font-size-title-5` | `text-title-5` | 12px | 500 | 1.5 | 0.02em |
| `--font-size-title-6` | `text-title-6` | 11px | 500 | 1.5 | 0.02em |
**Label** — 레이블, 플레이스홀더, 버튼
| CSS 변수 | Tailwind | px | Weight | Line-H | Spacing |
|----------|---------|-----|--------|--------|---------|
| `--font-size-label-1` | `text-label-1` | 12px | 500 | 1.5 | 0.04em |
| `--font-size-label-2` | `text-label-2` | 11px | 500 | 1.5 | 0.04em |
#### Font Weight Tokens
| CSS 변수 | 값 | 용도 |
|----------|-----|------|
| `--font-weight-thin` | 300 | 얇은 텍스트 |
| `--font-weight-regular` | 400 | 본문 기본 |
| `--font-weight-medium` | 500 | 중간 강조 |
| `--font-weight-bold` | 700 | 제목, 강조 |
#### Line Height Tokens
| CSS 변수 | 값 | 용도 |
|----------|-----|------|
| `--line-height-tight` | 1.3 | Display |
| `--line-height-snug` | 1.4 | Heading |
| `--line-height-normal` | 1.5 | Navigation, Label, Caption |
| `--line-height-relaxed` | 1.6 | Body |
#### Letter Spacing Tokens
카테고리별 자간 토큰. `text-*` 클래스에 자동 포함되며, `tracking-*` 클래스로 개별 사용도 가능합니다.
| CSS 변수 | Tailwind | 값 | 카테고리 |
|----------|---------|-----|----------|
| `--letter-spacing-display` | `tracking-display` | 0.06em | Display |
| `--letter-spacing-heading` | `tracking-heading` | 0.02em | Heading |
| `--letter-spacing-body` | `tracking-body` | 0em | Body |
| `--letter-spacing-navigation` | `tracking-navigation` | 0.02em | Navigation |
| `--letter-spacing-label` | `tracking-label` | 0.04em | Label |
#### Typography Tokens (`.wing-*` 클래스)
| 클래스 | Size | Font | Weight | 용도 | 샘플 |
|--------|------|------|--------|------|------|
| `.wing-title` | 15px | font-korean | Bold (700) | 패널 제목 | 확산 예측 시뮬레이션 |
| `.wing-section-header` | 13px | font-korean | Bold (700) | 섹션 헤더 | 기본 정보 입력 |
| `.wing-label` | 11px | font-korean | Semibold (600) | 필드 레이블 | 유출량 (kL) |
| `.wing-btn` | 11px | font-korean | Semibold (600) | 버튼 텍스트 | 시뮬레이션 실행 |
| `.wing-value` | 11px | font-mono | Semibold (600) | 수치 / 데이터 값 | 35.1284° N, 129.0598° E |
| `.wing-input` | 11px | font-korean | Normal (400) | 입력 필드 | 서해 대산항 인근 해역 |
| `.wing-section-desc` | 10px | font-korean | Normal (400) | 섹션 설명 | 예측 결과는 기상 조건에 따라... |
| `.wing-subtitle` | 10px | font-korean | Normal (400) | 보조 설명 | 최근 업데이트: 2026-03-24 09:00 KST |
| `.wing-meta` | 9px | font-korean | Normal (400) | 메타 정보 | v2.1 \| 해양환경공단 |
| `.wing-badge` | 9px | font-korean | Bold (700) | 뱃지 / 태그 | 진행중 |
---
### Border Radius
#### Radius Tokens
| Tailwind 클래스 | 값 | 비고 |
|-----------------|-----|------|
| `rounded-sm` | 6px | **Custom** (Tailwind 기본값 오버라이드) |
| `rounded` | 4px (0.25rem) | Tailwind 기본 |
| `rounded-md` | 10px | **Custom** (Tailwind 기본값 오버라이드) |
| `rounded-lg` | 8px (0.5rem) | Tailwind 기본 |
| `rounded-xl` | 12px (0.75rem) | Tailwind 기본 |
| `rounded-2xl` | 16px (1rem) | Tailwind 기본 |
| `rounded-full` | 9999px | Tailwind 기본 |
#### 컴포넌트 매핑
| Radius | 값 | 적용 컴포넌트 |
|--------|-----|-------------|
| `rounded-sm` | 6px | `.wing-btn`, `.wing-input`, `.wing-card-sm` |
| `rounded` | 4px | `.wing-badge` |
| `rounded-md` | 10px | `.wing-card`, `.wing-section`, `.wing-tab` |
| `rounded-lg` | 8px | `.wing-tab-bar` |
| `rounded-xl` | 12px | `.wing-modal` |
---
### 레이아웃 (Layout)
#### Breakpoints
| Name | Prefix | Min Width | 사용 | 비고 |
|------|--------|-----------|------|------|
| sm | `sm:` | 640px | - | |
| md | `md:` | 768px | - | |
| lg | `lg:` | 1024px | - | |
| xl | `xl:` | 1280px | **사용 중** | TopBar 탭 레이블/아이콘 토글 |
| 2xl | `2xl:` | 1536px | - | |
> Desktop(≥ 1280px)만 지원. Tablet/Mobile 미지원.
| Device | Width | Columns | Gutter | Margin |
|--------|-------|---------|--------|--------|
| Desktop | ≥ 1280px | flex 기반 가변 | gap-2 ~ gap-6 | px-5 ~ px-8 |
| Tablet | 768px ~ 1279px | - | - | - |
| Mobile | < 768px | - | - | - |
#### Spacing Scale
| Scale | rem | px | 용도 |
|-------|-----|----|------|
| 0.5 | 0.125rem | 2px | 미세 간격 |
| 1 | 0.25rem | 4px | 최소 간격 (gap-1) |
| 1.5 | 0.375rem | 6px | 컴팩트 간격 (gap-1.5) |
| 2 | 0.5rem | 8px | 기본 간격 (gap-2, p-2) |
| 2.5 | 0.625rem | 10px | 중간 간격 |
| 3 | 0.75rem | 12px | 표준 간격 (gap-3, p-3) |
| 4 | 1rem | 16px | 넓은 간격 (p-4, gap-4) |
| 5 | 1.25rem | 20px | 패널 패딩 (px-5, py-5) |
| 6 | 1.5rem | 24px | 섹션 간격 (gap-6, p-6) |
| 8 | 2rem | 32px | 간격 (px-8, gap-8) |
| 16 | 4rem | 64px | 최대 간격 |
#### Z-Index Layers
| Layer | z-index | Color | 설명 |
|-------|---------|-------|------|
| Tooltip | 60 | `#a855f7` | 툴팁, 드롭다운 메뉴 |
| Popup | 50 | `#f97316` | 팝업, 지도 오버레이 |
| Modal | 40 | `#ef4444` | 모달 다이얼로그, 백드롭 |
| TopBar | 30 | `#3b82f6` | 상단 네비게이션 |
| Sidebar | 20 | `#06b6d4` | 사이드바, 패널 |
| Content | 10 | `#22c55e` | 메인 콘텐츠 영역 |
| Base | 0 | `#8690a6` | 기본 레이어, 배경 |
#### App Shell Classes
| 클래스 | 역할 | Tailwind 스타일 |
|--------|------|----------------|
| `.wing-panel` | 콘텐츠 패널 | `flex flex-col h-full overflow-hidden` |
| `.wing-panel-scroll` | 패널 스크롤 영역 | `flex-1 overflow-y-auto` |
| `.wing-header-bar` | 패널 헤더 | `flex items-center justify-between shrink-0 px-5 border-b` |
| `.wing-sidebar` | 사이드바 | `flex flex-col border-r border-border` |
---
## CSS 레이어 아키텍처
```
index.css
├── @import base.css → @layer base (CSS 변수, reset, body, @font-face)
├── @import components.css → @layer components (MapLibre, scrollbar, prd-*, combo-*)
├── @import wing.css → @layer components (wing-* 디자인 시스템 클래스)
├── @tailwind base
├── @tailwind components
└── @tailwind utilities
```
---
## Tailwind 시맨틱 토큰 매핑 요약
| 카테고리 | CSS 변수 | Tailwind 클래스 예시 |
|---------|----------|---------------------|
| Background | `--bg-base` ~ `--bg-surface-hover` | `bg-bg-base`, `bg-bg-surface`, ... |
| Foreground | `--fg-default`, `--fg-sub`, `--fg-disabled` | `text-fg`, `text-fg-sub`, `text-fg-disabled` |
| Border | `--stroke-default`, `--stroke-light` | `border-stroke`, `border-stroke-light` |
| Accent | `--color-accent` ~ `--color-success` | `text-color-accent`, `bg-color-info`, ... |
| Font Size | `--font-size-display-1` ~ `--font-size-caption` | `text-display-1`, `text-body-1`, ... |
| Font Family | `--font-korean`, `--font-mono` | `font-korean`, `font-mono`, `font-sans` |