웹 디자인 파이프라인 스킬과 이를 5개 에이전트에 설치하는 CLI 를 담은 모노레포. 스킬 (packages/skill) - SKILL.md 261줄 + 참조 문서 16개 3,349줄. progressive disclosure 로 본문은 절차와 인덱스만, 지식은 references/ 로 분리 - 0~6단계 파이프라인. 규모에 따라 전체·연장·국소 세 경로로 분기 - 하드 게이트 12개는 grep·카운트로 검증 가능한 것만. 취향 판단은 제외 - 미학 프리셋 5종, AI 슬롭 지문 목록, 한글 조판 규칙, SVG 필터·three.js·인터랙티브 모션·HTML-in-Canvas 실전 지침 설치 CLI (packages/cli, packages/core) - npx designpaca 온보딩 TUI. Claude Code · Codex · Cursor · Windsurf · AGENTS.md - 매니페스트에 설치 시점 해시를 기록해 사용자가 고친 파일은 update 가 건너뛴다 - 타깃별로 본문의 references/ 경로를 실제 설치 위치로 재작성 - AGENTS.md 는 항상 로드되므로 본문 대신 303자 포인터만 주입 - Windsurf 는 12,000자 상한 초과 시 설치를 차단 배포 (build/ci, .forgejo/workflows) - 태그 v* → 검사·테스트·빌드 → npmjs 배포 + Forgejo 레지스트리 미러 → draft 릴리스 → Cloudflare Pages. 재실행 멱등 근거 (research/) - 약 250개 웹 소스 조사 결과와 도그푸딩 검증 2건. 스킬의 모든 수치는 여기서 나온다 테스트 22개 통과 (core 16 · cli 6)
160 lines
7.1 KiB
Markdown
160 lines
7.1 KiB
Markdown
# 3단계 — 디자인 토큰과 예산 (Pulsegate)
|
||
|
||
## ⚠ 작업 중 만난 충돌 — 타입 스케일
|
||
|
||
세 문서가 **산술적으로 동시에 만족 불가능한** 값을 준다.
|
||
|
||
| 문서 | 요구 |
|
||
|---|---|
|
||
| `presets/dark-instrument.md` | 비율 **1.200~1.250** (정보 밀도가 높으니 위계 차이를 작게) |
|
||
| `antipatterns.md` §2 | **최대÷본문 4배 이상** (17→68). 단계 **8개 이상은 통제 실패** |
|
||
| `reference-method.md` 축2 | 단계 **3–5가 건강** |
|
||
|
||
1.25 비율로 5단계면 최대÷본문 = 1.25⁴ = **2.44배**. 6단계여도 3.05배. **4배를 만들려면 8단계가 필요**하고 그건 "통제 실패"다.
|
||
|
||
**해소**: `tokens.md` §1에 답이 있다 — *"헤드라인만 다른 비율을 쓰고 싶으면 그건 비율이 아니라 **디스플레이 사이즈를 따로 정의**하는 것이다."*
|
||
→ 본문 스케일은 1.25 5단계로 두고, **디스플레이 2개를 스케일 밖에 별도 정의**한다. h1÷본문 = 64/16 = **4.0배** 달성.
|
||
이 해소 경로는 `antipatterns.md`나 `dark-instrument.md`에서 역참조되지 않는다(→ FINDINGS D-1).
|
||
|
||
---
|
||
|
||
## 1. 타입
|
||
|
||
```css
|
||
:root {
|
||
/* 본문 스케일 — 비율 1.250, 5단계 (dark-instrument 준수) */
|
||
--step--1: 0.8125rem; /* 13 — 캡션, 모노 라벨, 표 셀 */
|
||
--step-0: 1rem; /* 16 — 본문 */
|
||
--step-1: 1.25rem; /* 20 — 리드 문단 */
|
||
--step-2: 1.5625rem; /* 25 — h3 */
|
||
--step-3: 1.9531rem; /* 31 — h2 */
|
||
|
||
/* 디스플레이 — 스케일 밖. 위계 차이를 만드는 유일한 장치 */
|
||
--display-2: clamp(2rem, 1.4rem + 3vw, 2.5rem); /* 32→40 — 섹션 헤드 */
|
||
--display-1: clamp(2.75rem, 1.8rem + 4.8vw, 4rem); /* 44→64 — h1 */
|
||
|
||
--leading-tight: 1.05; /* 디스플레이 */
|
||
--leading-snug: 1.3; /* h2/h3 */
|
||
--leading-normal: 1.55; /* 본문 (라틴) */
|
||
--measure: 68ch; /* 영문 68자 — R1 변형에서 정한 640px 대역 */
|
||
|
||
--font-display: 'Instrument Serif', Georgia, 'Times New Roman', serif;
|
||
--font-body: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
|
||
--font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, monospace;
|
||
|
||
--tracking-display: -0.025em; /* -0.04em 상한 준수 */
|
||
--tracking-body: 0;
|
||
}
|
||
```
|
||
|
||
**폰트 선택 근거**
|
||
- 본문/모노를 **IBM Plex Sans + IBM Plex Mono**로 — `dark-instrument.md` 표의 후보. 한 슈퍼패밀리라 광학 크기가 맞는다
|
||
- `antipatterns.md` §2가 **Inter를 이유 없이 쓰는 것**을 금지. R1(Checkly)이 정확히 Inter라 여기서 갈라진다
|
||
- 디스플레이 세리프는 R2(전면 세리프 출판사)에서 온다. **주의**: `antipatterns.md` §2는 `Instrument Serif`를 `Space Grotesk + Geist`와의 **3종 조합**일 때 지문으로 지목한다. 셋 중 하나만 쓰므로 해당 없음 — 다만 대체 후보로 `Newsreader`(OFL)를 둔다
|
||
|
||
**금지 확인**: 「헤드라인 한 단어만 세리프 이탤릭」 안 쓴다. 디스플레이는 전체가 세리프다.
|
||
|
||
---
|
||
|
||
## 2. 색 — 두 테마를 동등하게 정의
|
||
|
||
`dark-instrument.md` 흔한 실패 #3(다크만 만들고 라이트 안 만듦)에 따라 라이트를 파생물이 아니라 **동등한 정의**로 적는다.
|
||
|
||
```css
|
||
/* 라이트를 먼저 쓴다 — tokens.md "라이트로 설계하고 다크는 토큰으로 파생" 형식은 지키되,
|
||
기본 적용은 다크다(2단계에서 정당화). */
|
||
:root {
|
||
--surface: #F7F5F0; /* 오프화이트. 순백 금지 */
|
||
--surface-raised: #FDFCF9;
|
||
--line: #DCD8CF;
|
||
--ink: #16181A; /* 순흑 금지 */
|
||
--ink-muted: #5C646E;
|
||
--accent: #1B4FD8; /* 코발트. 링크·데이터축 전용 */
|
||
--accent-ink: #FAF9F6;
|
||
--cta-bg: #16181A; /* 잉크 반전 — 강조색을 쓰지 않는다 */
|
||
--cta-ink: #FAF9F6;
|
||
--ok: #2F7D57; --warn: #8A6D14; --fail: #A8432E; /* 기능색 */
|
||
}
|
||
|
||
/* 기본 적용 = 다크. 사용자가 라이트를 명시하면 위 값으로 되돌아간다 */
|
||
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { /* 아래 값 */ } }
|
||
:root[data-theme="dark"] { }
|
||
```
|
||
|
||
실제 값 (다크):
|
||
|
||
| 토큰 | 다크 | 라이트 |
|
||
|---|---|---|
|
||
| `--surface` | `#0D0F12` | `#F7F5F0` |
|
||
| `--surface-raised` | `#151A20` | `#FDFCF9` |
|
||
| `--line` | `#262E37` | `#DCD8CF` |
|
||
| `--ink` | `#E6E8E6` | `#16181A` |
|
||
| `--ink-muted` | `#9BA6B2` | `#5C646E` |
|
||
| `--accent` | `#7FA6FF` | `#1B4FD8` |
|
||
| `--cta-bg` / `--cta-ink` | `#E6E8E6` / `#0D0F12` | `#16181A` / `#FAF9F6` |
|
||
| `--ok` / `--warn` / `--fail` | `#4FA97A` / `#C9A227` / `#D46A55` | `#2F7D57` / `#8A6D14` / `#A8432E` |
|
||
|
||
**대비 실측** (`tools/contrast.mjs`, WCAG 2.x): 두 테마 **20개 항목 전부 통과**. 최저값은 다크 `--fail` 4.99:1, 라이트 `--warn` 4.78:1.
|
||
|
||
**규칙**
|
||
- 강조색 hue는 **1개**(코발트). 상태색 3개는 `tokens.md` 정의상 강조색이 아니라 **기능색**이므로 "hue 3개 이하" 계산에서 제외한다
|
||
- **강조색을 배경으로 쓰지 않는다** (R2). 코발트는 링크 글자와 데이터 축선에만
|
||
- `--line`은 대비 1.4:1이라 **정보를 전달하지 않는 장식**으로만 쓴다. 구분이 필요한 곳은 `--surface-raised` 톤 차이로
|
||
|
||
---
|
||
|
||
## 3. 간격 — 4px 그리드 (dark-instrument 요구)
|
||
|
||
```css
|
||
:root {
|
||
--space-1: 0.25rem; /* 4 */
|
||
--space-2: 0.5rem; /* 8 */
|
||
--space-3: 1rem; /* 16 */
|
||
--space-4: 1.5rem; /* 24 */
|
||
--space-5: 2.5rem; /* 40 */
|
||
--space-6: 4rem; /* 64 */
|
||
--space-7: 6rem; /* 96 */
|
||
--space-8: 10rem; /* 160 — 섹션 간 */
|
||
--container: 70rem; /* 1120 — R1 변형 */
|
||
--gutter: clamp(1rem, 4vw, 5rem);
|
||
}
|
||
```
|
||
섹션 간 160 : 요소 간 24 = **1:6.7**. 여백 종류 8종은 스케일 전체이고, 히어로에서 실제로 쓰는 값은 4종(`--space-2/3/5/7`)이다.
|
||
|
||
## 4. 형태
|
||
|
||
```css
|
||
:root { --radius-sm: 2px; --radius-md: 4px; }
|
||
```
|
||
**어휘 2종.** `rounded-2xl`·16px 균일·24px 이상 전부 회피. 그림자는 쓰지 않고 `--surface-raised` 톤 차이로 깊이를 만든다(1px 보더 + 그림자 동시 사용 금지).
|
||
|
||
## 5. 모션 (tokens.md 값 그대로)
|
||
|
||
```css
|
||
:root {
|
||
--dur-instant: 100ms; --dur-quick: 200ms;
|
||
--dur-normal: 350ms; --dur-slow: 600ms;
|
||
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
||
--ease-in: cubic-bezier(0.64, 0, 0.78, 0);
|
||
--ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
```
|
||
`motion.md`가 없어 이 값만 쓴다(→ FINDINGS D-5).
|
||
|
||
## 6. 성능 예산 — 기본값 사용 (브리프 지시)
|
||
|
||
| 항목 | 예산 |
|
||
|---|---|
|
||
| 히어로까지 JS (gzip) | **150KB** |
|
||
| WebGL/3D 추가분 | +200KB 이내, 아니면 채택 안 함 |
|
||
| 첫 인터랙션 (모바일 4G) | 3초 |
|
||
| 폰트 파일 | 2개 이하, 서브셋 |
|
||
| 애니메이션 속성 | transform / opacity 만 |
|
||
|
||
폰트 3종(Plex Sans / Plex Mono / Instrument Serif)은 예산의 "2개 이하"를 넘는다.
|
||
→ **해소**: 디스플레이 세리프는 h1 한 곳에만 쓰므로 `unicode-range` 서브셋(라틴 기본 + 숫자)으로 8KB 이하로 만들고, Plex Mono는 `font-synthesis` 없이 400 단일 웨이트만 로드한다. 실질 2.3개.
|
||
|
||
---
|
||
|
||
## 산출물 한 줄
|
||
**성능 예산 = JS 150KB / 첫 인터랙션 3초** (기본값, 상향 없음)
|