Files
fanuzu/design/design-tokens.md
T

246 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 디자인 토큰 — Fancake
> 위치: `design/design-tokens.md` · 계약: 디자인 kit CONTRACT §6
> 색·타이포·간격·반경·사이징은 **토큰으로만** 참조한다(브리프에 raw hex/px 하드코딩 금지).
> `web-*`(Shadcn)은 고객 web + 관리자 admin 공용, `color-*`(MD3)은 네이티브 app surface용.
## 컬러 시드 선정 근거
- 입력 시드: `#FF85D9`
- 근거: 발주사가 인수 자산으로 제공한 데모(`고객사 준비 데모/FANUZU_landing_page.tsx`)의 로고 SVG에
실제로 쓰인 브랜드 핑크다. 새 색을 발명하는 대신 이미 존재하는 브랜드 자산에서 시드를 가져와
로고·앱아이콘·UI가 하나의 브랜드로 읽히게 했다.
- 가독성 보정(라이트 한정): `#ff85d9` → **`#ac5992`**. 흰 배경에 얹을 때만 필요한 보정이다.
**2026-08-02 전 surface를 코스믹 다크로 통일하면서 화면에서는 원 시드 `#FF85D9` 를 그대로 쓴다** —
검정 배경 위 대비가 **9.61:1** 로 보정 없이 AA를 넘긴다. `#ac5992` 는 라이트 대체 경로용으로만 남긴다.
색을 깎을 필요가 없어진 덕에 인수 데모의 네온 채도가 살아났다.
- 세컨더리 민트 `#C1FFED` 도 같은 데모 로고(아이싱)에서 왔다. 성장·회복 지표(행성 성장률·방어 회복량)
한 곳에만 쓰고 그 외에는 쓰지 않는다.
## 로고 결정
- 발주사 인수 자산 `고객사 준비 데모/LOGO/*.png` 4종은 모두 **회색 배경 위 네온 글로우 목업**이다.
알파 채널이 없어 헤더에 회색 사각형이 박히고, 글로우·발광은 계약 §5.1 이 금지한 신호다.
또한 워드마크가 **FANUZU(팬우주)** 인데 견적서·별첨의 서비스명은 **Fancake** 다.
- 그래서 시안에는 **Fancake 플랫 워드마크를 제안본으로 만들어** 썼다(첫 `a` 의 카운터를 고리 행성으로 치환,
단색 플럼, 알파 PNG). 인수 원본은 `sources/logo-발주사원본-fanuzu.png` 로 보존했다.
- **서비스명은 `Fancake` 로 확정됐다 (CD-01).** 데모 최신 소스 3종이 전부 Fancake 표기이고
견적서·별첨의 서비스명과도 일치한다. **FANUZU(팬우주)는 인수 원본에만 남은 옛 표기이므로 신규 산출물에 쓰지 않는다.**
인수 자산의 FANUZU 워드마크는 이력 보존용으로만 둔다.
- **남은 확인 항목은 로고 원본 하나뿐**: 이 제안 워드마크를 쓸지, 발주사가 별도 로고 원본(벡터·알파)을
제공할지 (확인요청항목 **Q6**).
## 컬러 운용 규율 (60-30-10)
- 60 배경/서피스 · 30 중립 텍스트·보더 · **10 악센트**. 악센트는 **행동·선택·포커스에만** 쓴다.
- 브랜드색으로 배경을 도배하지 않는다. 위계는 색이 아니라 타입 스케일과 여백으로 만든다.
- 순흑(`#000`)은 **텍스트가 아니라 캔버스**다. 배경은 `color-cosmic-void`(#000), 글자는 `color-on-cosmic`.
- 네온(시안·에메랄드·마젠타·바이올렛)은 **의미가 있을 때만** 쓴다 — 진행·성공·경고·프리미엄.
네 색을 한 화면에 다 풀지 않는다. 화면당 네온 악센트는 하나를 주로 하고 나머지는 보조로만.
## 서피스 전략 — 왜 두 벌인가
| surface | 기본 서피스 | 근거 |
|---|---|---|
| app (네이티브) | **코스믹 보이드**(`color-cosmic-void` + 네뷸라 + 별밭) | 행성·갤럭시 맵·이클립스가 우주 배경을 전제로 한 연출이다. 인수 데모 프로토타입의 `body{background:#000}` 을 그대로 쓴다(결정 D-19). |
| web (마케팅·사전예약) | 코스믹 보이드 (네뷸라 약하게) | 2026-08-02 변경. 랜딩에서 앱으로 넘어갈 때 브랜드가 끊기지 않게 같은 캔버스를 쓴다. |
| admin (운영 콘솔) | 코스믹 서피스 (네뷸라 제외·별밭만) | 2026-08-02 변경. 색면이 표·수치와 경쟁하지 않도록 배경 광원을 걷어내고 별밭만 남긴다. |
> 세 surface 모두 다크로 통일한 이유는 `아트디렉션-예외.md` 에 적었다. 요약하면 PRD-13 「Non-Verbal
> Cinematic UI」가 계약 요건이고, 발주사 인수 데모가 검정 캔버스·네온·글래스를 이미 확정했기 때문이다.
## 타이포 — 디스플레이 페어링
- 본문·UI: **Pretendard Variable** (한글 가독성) 고정.
- 디스플레이(제목): **Gmarket Sans** — 타입 디렉션 `geometric`.
- 근거: 팬덤 서비스의 제목은 또렷하고 젊은 기하학적 인상이 맞고, 국내 사용자에게 익숙한 리테일·커머스
톤(배달의민족·올리브영 계열)과 붙는다. 제목과 본문이 모두 Pretendard이면 모든 화면이 똑같아진다.
- 숫자(POP·FPI·달성률·표)는 `type-mono-num` 으로 tabular 고정 — 실시간으로 값이 바뀌는 화면에서
자릿수가 흔들리지 않아야 한다.
## 사용 규칙
- 앱 터치 타깃 `touch-min-app` 48 이상, 웹 클릭 타깃 `touch-min-web` 36 이상.
- 여백은 `space-*` 스케일에서만 고른다(임의값 금지). 섹션은 크게, 요소는 작게.
- 깊이는 `elev-border`(헤어라인)가 1순위. 떠 있는 요소만 `elev-1~3`.
- 오버레이 순서는 `z-*` 토큰을 따른다.
# ℹ primary 가독성 보정: #ff85d9 → #ac5992 (흰/검정 라벨이 둘 다 AA 미달인 중간톤 → 흰 글자 대비 4.5+ 확보)
# ℹ 타입 디렉션: geometric — 디스플레이='Gmarket Sans' / 본문=Pretendard (예: 배달의민족 · 쿠팡 · 올리브영). 다른 디렉션: neutral, editorial, technical, warm
<!-- TOKENS --> <!-- seed=#ff85d9 → primary=#ac5992(가독성 보정) · 타입 디렉션=geometric (gen_tokens.py 생성) -->
```yaml
colors:
# --- app (MD3) ---
color-primary: "#ac5992"
color-on-primary: "#ffffff"
color-primary-container: "#f0e1eb"
color-on-primary-container: "#924c7c"
color-surface: "#f8f5fa"
color-surface-container: "#ebe7ed"
color-on-surface: "#1a1c1e"
color-on-surface-variant: "#4b4753"
color-outline: "#7a7481"
color-error: "#c53030"
color-on-error: "#ffffff"
# --- web (Shadcn) · 고객 web + 관리자 admin 공용 · 중립은 브랜드 미세 틴트 ---
web-background: "#ffffff"
web-foreground: "#1a1c1e"
web-primary: "#ac5992"
web-primary-foreground: "#ffffff"
web-muted: "#f1eef4"
web-muted-foreground: "#4b4753"
web-border: "#ded7df"
# --- 코스믹 다크 서피스 (전 surface 기본 · 결정 D-19 · 인수 데모 시각 언어 복원 2026-08-02) ---
# 데모(FANUZU_prototype.tsx STYLES · FANUZU_HUD Proto.html)의 순수 검정 캔버스를 그대로 쓴다.
color-cosmic-void: "#000000"
color-cosmic-surface: "#05070F"
color-cosmic-surface-container: "#0D1220"
color-cosmic-surface-raised: "#141A2B"
color-on-cosmic: "#F4F0F7"
color-on-cosmic-variant: "#B4AEC0"
# 네온 악센트 — 검정 위에서만 쓴다(전부 검정 대비 5:1 이상, 대비 보정 없이 원색 유지)
color-cosmic-accent: "#FF85D9"
color-on-cosmic-accent: "#05070F"
color-neon-cyan: "#00F2FF"
color-on-neon-cyan: "#05070F"
color-neon-emerald: "#34D399"
color-on-neon-emerald: "#05070F"
color-neon-magenta: "#FF007A"
color-on-neon-magenta: "#05070F"
color-neon-violet: "#A855F7"
color-on-neon-violet: "#05070F"
color-cosmic-mint: "#C1FFED"
color-on-cosmic-mint: "#05070F"
color-cosmic-outline: "#2A3348"
cosmic_fx:
# 인수 데모의 시각 언어를 토큰으로 고정한 그룹.
# 킷 art-direction.md §0 은 글로우·그라데이션·글래스를 금지 신호로 두지만,
# 이 프로젝트는 PRD-13 「Non-Verbal Cinematic UI」가 계약 요건이고 발주사 인수 데모가
# 그 표현을 이미 확정했으므로 프로젝트 예외로 허용한다(근거: design/아트디렉션-예외.md).
glass-fill: "rgba(255,255,255,.05)"
glass-fill-strong: "rgba(255,255,255,.08)"
glass-stroke: "rgba(255,255,255,.10)"
glass-blur: "16px"
glow-sm: "0 0 12px"
glow-md: "0 0 24px"
glow-lg: "0 0 48px"
glow-accent: "0 0 24px rgba(255,133,217,.45)"
glow-cyan: "0 0 24px rgba(0,242,255,.40)"
glow-emerald: "0 0 24px rgba(52,211,153,.40)"
glow-magenta: "0 0 28px rgba(255,0,122,.45)"
grad-action: "linear-gradient(135deg,#34D399 0%,#4F46E5 100%)"
grad-brand: "linear-gradient(135deg,#FF85D9 0%,#A855F7 100%)"
grad-eclipse: "linear-gradient(135deg,#FF007A 0%,#7C1D3F 100%)"
grad-veil: "linear-gradient(180deg,rgba(0,0,0,0) 0%,rgba(0,0,0,.85) 100%)"
nebula: "radial-gradient(720px 460px at 10% -6%, rgba(168,85,247,.34), transparent 70%), radial-gradient(600px 400px at 94% 8%, rgba(0,242,255,.24), transparent 70%), radial-gradient(760px 520px at 74% 52%, rgba(255,0,122,.20), transparent 72%), radial-gradient(640px 460px at 16% 62%, rgba(88,60,180,.24), transparent 72%), radial-gradient(820px 560px at 82% 96%, rgba(255,133,217,.20), transparent 72%), radial-gradient(600px 440px at 8% 98%, rgba(52,211,153,.14), transparent 70%)"
starfield: "radial-gradient(1.6px 1.6px at 33.1% 16.5%,rgba(255,255,255,0.44),transparent), radial-gradient(1px 1px at 53.4% 37.1%,rgba(255,133,217,0.52),transparent), radial-gradient(1px 1px at 10.3% 42.1%,rgba(255,255,255,0.7),transparent), radial-gradient(1px 1px at 7.7% 56.3%,rgba(168,85,247,0.75),transparent), radial-gradient(1.2px 1.2px at 93.0% 57.4%,rgba(255,255,255,0.94),transparent), radial-gradient(1px 1px at 6.5% 84.4%,rgba(0,242,255,0.48),transparent), radial-gradient(1.8px 1.8px at 13.3% 31.6%,rgba(168,85,247,0.5),transparent), radial-gradient(1px 1px at 57.8% 63.3%,rgba(255,255,255,0.7),transparent), radial-gradient(1px 1px at 8.0% 7.7%,rgba(0,242,255,0.77),transparent), radial-gradient(1.4px 1.4px at 43.0% 32.2%,rgba(0,242,255,0.6),transparent), radial-gradient(1.8px 1.8px at 25.8% 19.3%,rgba(255,255,255,0.45),transparent), radial-gradient(1px 1px at 30.8% 49.5%,rgba(168,85,247,0.65),transparent), radial-gradient(1.4px 1.4px at 60.5% 9.0%,rgba(0,242,255,0.49),transparent), radial-gradient(1.2px 1.2px at 34.8% 91.6%,rgba(255,255,255,0.93),transparent), radial-gradient(1.8px 1.8px at 9.5% 55.6%,rgba(52,211,153,0.57),transparent), radial-gradient(1.4px 1.4px at 68.7% 59.1%,rgba(52,211,153,0.65),transparent), radial-gradient(1.2px 1.2px at 82.6% 92.7%,rgba(168,85,247,0.77),transparent), radial-gradient(1.6px 1.6px at 7.8% 69.3%,rgba(255,133,217,0.95),transparent), radial-gradient(1.2px 1.2px at 80.9% 29.3%,rgba(168,85,247,0.59),transparent), radial-gradient(1.4px 1.4px at 92.3% 36.1%,rgba(255,255,255,0.67),transparent), radial-gradient(1.6px 1.6px at 22.9% 29.6%,rgba(255,255,255,0.62),transparent), radial-gradient(1px 1px at 90.0% 49.7%,rgba(0,242,255,0.62),transparent), radial-gradient(1.2px 1.2px at 28.7% 15.1%,rgba(52,211,153,0.7),transparent), radial-gradient(1.6px 1.6px at 69.8% 96.7%,rgba(0,242,255,0.93),transparent), radial-gradient(1px 1px at 16.5% 18.9%,rgba(168,85,247,0.53),transparent), radial-gradient(1px 1px at 48.6% 58.6%,rgba(255,255,255,0.4),transparent), radial-gradient(1.4px 1.4px at 42.2% 37.4%,rgba(255,255,255,0.92),transparent), radial-gradient(1.4px 1.4px at 68.3% 51.5%,rgba(168,85,247,0.77),transparent), radial-gradient(1.8px 1.8px at 7.2% 88.4%,rgba(52,211,153,0.77),transparent), radial-gradient(1.2px 1.2px at 55.7% 40.2%,rgba(255,255,255,0.66),transparent), radial-gradient(1px 1px at 40.4% 20.3%,rgba(0,242,255,0.49),transparent), radial-gradient(1px 1px at 34.6% 7.0%,rgba(255,133,217,0.48),transparent), radial-gradient(1px 1px at 11.7% 36.9%,rgba(255,255,255,0.88),transparent), radial-gradient(1px 1px at 61.0% 16.3%,rgba(255,255,255,0.73),transparent), radial-gradient(1.2px 1.2px at 47.5% 13.1%,rgba(0,242,255,0.66),transparent), radial-gradient(1.6px 1.6px at 31.9% 15.8%,rgba(255,255,255,0.81),transparent), radial-gradient(1.4px 1.4px at 47.9% 68.4%,rgba(255,255,255,0.51),transparent), radial-gradient(1.6px 1.6px at 93.4% 36.7%,rgba(255,133,217,0.9),transparent), radial-gradient(1.6px 1.6px at 74.8% 30.6%,rgba(52,211,153,0.45),transparent), radial-gradient(1px 1px at 83.2% 51.8%,rgba(255,255,255,0.82),transparent), radial-gradient(1px 1px at 53.1% 76.8%,rgba(168,85,247,0.52),transparent), radial-gradient(1.8px 1.8px at 79.9% 96.6%,rgba(255,255,255,0.84),transparent), radial-gradient(1px 1px at 80.6% 73.0%,rgba(255,255,255,0.68),transparent), radial-gradient(1px 1px at 36.1% 4.8%,rgba(52,211,153,0.55),transparent), radial-gradient(1px 1px at 26.9% 68.5%,rgba(0,242,255,0.84),transparent), radial-gradient(1px 1px at 71.4% 35.6%,rgba(255,255,255,0.52),transparent)"
orbit-stroke: "rgba(255,255,255,.10)"
brand:
brand-kakao: "#FEE500"
brand-kakao-label: "#000000"
brand-naver: "#03C75A"
brand-naver-label: "#FFFFFF"
brand-apple: "#000000"
brand-apple-label: "#FFFFFF"
brand-apple-onlight: "#FFFFFF"
brand-google-fill: "#FFFFFF"
brand-google-stroke: "#747775"
brand-google-label: "#1F1F1F"
font:
font-display: "'Gmarket Sans', Pretendard Variable, sans-serif"
font-body: "Pretendard Variable, system-ui, sans-serif"
font-mono: "JetBrains Mono, IBM Plex Mono, ui-monospace, monospace"
font-direction: "geometric"
font-source: "Gmarket Sans = webfontworld/jsdelivr · 본문 Pretendard = jsdelivr"
type:
type-display-l: {family: font-display, size: 44, weight: 700, tracking: -0.01em, leading: 1.06}
type-display-m: {family: font-display, size: 32, weight: 700, tracking: -0.01em, leading: 1.11}
type-title-l: {family: font-display, size: 24, weight: 700, tracking: -0.01em, leading: 1.2}
type-title-m: {family: font-body, size: 18, weight: 600, leading: 1.3}
type-body-l: {family: font-body, size: 18, weight: 400, leading: 1.6}
type-body-m: {family: font-body, size: 16, weight: 400, leading: 1.6}
type-body-s: {family: font-body, size: 14, weight: 400, leading: 1.55}
type-label-l: {family: font-body, size: 14, weight: 500, leading: 1.2}
type-eyebrow: {family: font-body, size: 12, weight: 600, tracking: 0.06em, transform: uppercase}
type-caption: {family: font-body, size: 12, weight: 500, leading: 1.4}
type-mono-num: {family: font-mono, feature: 'tnum', note: '가격·지표·표는 tabular'}
sizing:
touch-min-app: 48
touch-min-web: 36
body-min-app: 16
body-min-web: 14
space:
space-0: 0
space-1: 4
space-2: 8
space-3: 12
space-4: 16
space-5: 24
space-6: 32
space-7: 48
space-8: 64
space-9: 96
space-card: 24
space-section-desktop: 96
space-section-mobile: 56
container-max: 1200
gutter-desktop: 32
gutter-mobile: 16
measure-ch: 70
radius:
corner-xs: 8
corner-sm: 10
corner-md: 14
corner-lg: 18
corner-full: 9999
elevation:
elev-border: "0 0 0 1px rgba(16,18,29,.08)"
elev-1: "0 1px 2px rgba(16,18,29,.06), 0 1px 1px rgba(16,18,29,.04)"
elev-2: "0 4px 12px rgba(16,18,29,.08), 0 2px 4px rgba(16,18,29,.06)"
elev-3: "0 12px 32px rgba(16,18,29,.14)"
motion:
motion-fast: "120ms"
motion-base: "180ms"
motion-slow: "260ms"
motion-ease: "cubic-bezier(.2,.8,.2,1)"
motion-ease-in-out: "cubic-bezier(.4,0,.2,1)"
z:
z-base: 0
z-sticky: 1100
z-dropdown: 1200
z-popover: 1300
z-overlay: 1400
z-modal: 1500
z-toast: 1700
contrast_checks:
- [color-on-primary, color-primary]
- [color-on-primary-container, color-primary-container]
- [color-on-surface, color-surface]
- [color-on-error, color-error]
- [web-foreground, web-background]
- [color-on-cosmic, color-cosmic-surface]
- [color-on-cosmic-variant, color-cosmic-surface]
- [color-on-cosmic, color-cosmic-surface-container]
- [color-on-cosmic-accent, color-cosmic-accent]
- [color-on-cosmic-mint, color-cosmic-mint]
- [color-on-cosmic, color-cosmic-void]
- [color-on-cosmic-variant, color-cosmic-void]
- [color-cosmic-accent, color-cosmic-void]
- [color-neon-cyan, color-cosmic-void]
- [color-neon-emerald, color-cosmic-void]
- [color-neon-magenta, color-cosmic-void]
- [color-neon-violet, color-cosmic-void]
- [color-on-neon-cyan, color-neon-cyan]
- [color-on-neon-emerald, color-neon-emerald]
- [color-on-neon-magenta, color-neon-magenta]
- [color-on-neon-violet, color-neon-violet]
- [color-on-cosmic, color-cosmic-surface-raised]
# 앱 테마 조립이 새로 만드는 조합 (app/lib/core/theme/app_theme.dart navigationBarTheme).
# 토큰 자체의 쌍이 아니라 '위젯 테마가 실제로 겹치는' 쌍이라 여기 없으면 회귀 게이트가 없다.
- [color-cosmic-accent, color-cosmic-surface] # 선택된 탭 라벨
- [color-cosmic-accent, color-cosmic-surface-raised] # 인디케이터 위 선택 라벨
- [color-on-cosmic-variant, color-cosmic-surface-raised] # 인디케이터 위 비선택 라벨
```
---
## 정정 이력
| 일자 | 내용 |
|---|---|
| 2026-08-08 | **서비스명 확인 질문 삭제 — CD-01 로 이미 확정된 사항이었음.** 「① 서비스명 표기가 Fancake 인지 팬우주(FANUZU) 인지」를 확인 필요 항목으로 남겨 두었으나, 변경 대장 **CD-01(서비스명 Fancake 확정)** 으로 닫힌 건이라 질문을 지우고 확정 문구로 교체했다. **디자인 결정 변경은 없고**, 이미 확정된 것을 미확정처럼 적어 둔 표기를 바로잡은 것이다. 로고 원본 제공 여부(**Q6**)는 실제 미확정이라 그대로 남겼다 |