소개 페이지 — 스킬을 스스로 적용해 만든 첫 사례

designpaca 파이프라인 0~6단계를 실제로 돌려 만들었다. 근거는 research/site-brief.md,
결정 기록은 apps/site/design.md 에 있다.

한 문장 컨셉
- 이 페이지는 designpaca 를 거쳐 만들어졌고, 절차와 형태 수치를 한국어 기준으로 전부 공개한다

번호 없이 순서 표현 (C-07 회피)
- 파이프라인 6단계를 번호로 매기면 검출률 3위 슬롭 지문에 걸린다
- 시각: 스파인 위 위치가 순서를 만든다 / 내용: 같은 브리프가 단계마다 변한다
- 의미: <ol role="list"> — 화면에 번호 0개, 보조기술에는 "6개 중 n번째"

멀티링구얼
- / = 한국어, /en/ = 영어. 번역이 아니라 각 판을 따로 썼다
- 언어별 레이아웃이 자기 폰트만 로드한다 (판당 2개)
- 조판 섹션은 한국어판에서 주장이고 영어판에서 사례다

실측
- JS 314B (gzip, 예산 50KB) / CSS 3.0KB / HTML 4.4~4.8KB
- radius 2종 · backdrop-filter 0개 · 타입 5단계 · 강조색 1개
- 슬롭 지문 grep 9패턴 0건, 정적 하드 게이트 8개 전부 통과

감사에서 걸려 고친 것
- eyebrow 6개 → 상한 ceil(7/3)=3 위반 → 3개로
- clip-path 리빌 → 게이트 #8 위반 → transform 으로 교정
- 구분선 대비 1.30:1 → 입력 테두리용 별칭 분리 (WCAG 1.4.11)
- 본문 컬럼 960px → --measure 로. layout.md 예시 코드도 같이 수정
This commit is contained in:
Yun Chan 2026-08-20 11:00:38 +09:00
parent 8808c672dc
commit 6103700d38
18 changed files with 1497 additions and 20 deletions

View file

@ -0,0 +1,157 @@
/* ============================================================
designpaca 소개 페이지 기반 스타일
토큰은 tokens.css 에만 있다. 파일에 값을 만들지 않는다.
============================================================ */
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
-webkit-text-size-adjust: 100%;
scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
}
body {
margin: 0;
background: var(--surface);
color: var(--ink);
font-family: var(--font-sans);
font-size: var(--step-0);
line-height: var(--leading-normal);
letter-spacing: var(--tracking-body);
font-synthesis-weight: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
/* 한글은 단어 중간에서 끊지 않는다 */
[lang="ko"] body,
[lang="ko"] p,
[lang="ko"] li,
[lang="ko"] h1,
[lang="ko"] h2,
[lang="ko"] h3 {
word-break: keep-all;
overflow-wrap: break-word;
}
/* ---- 그리드 ------------------------------------------------
main 폭은 3단계에서 정한 --measure . 고정값을 쓰지 않는다.
----------------------------------------------------------- */
.page {
display: grid;
grid-template-columns:
[full-start] minmax(var(--space-4), 1fr)
[wide-start] minmax(0, var(--space-8))
[main-start] minmax(0, var(--measure)) [main-end]
minmax(0, var(--space-8)) [wide-end]
minmax(var(--space-4), 1fr) [full-end];
}
.page > * { grid-column: main; }
.page > .wide { grid-column: wide; }
.page > .full { grid-column: full; }
/* 섹션 안에서도 같은 그리드를 쓴다 — 정렬선이 페이지 전체에서 하나여야 한다 */
.section {
display: grid;
grid-template-columns: subgrid;
grid-column: full;
padding-block: var(--space-7);
}
.section > * { grid-column: main; }
.section > .wide { grid-column: wide; }
/* ---- 타이포 ------------------------------------------------ */
h1, h2, h3 {
margin: 0;
line-height: var(--leading-tight);
letter-spacing: var(--tracking-display);
font-weight: 600;
text-wrap: balance;
}
h1 { font-size: var(--display); font-weight: 620; }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-1); }
p { margin: 0 0 var(--space-3); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }
.lead {
font-size: var(--step-1);
color: var(--ink-muted);
}
/* eyebrow 는 새 크기를 만들지 않는다 — 본문 크기 + 자간 + muted */
.eyebrow {
font-size: var(--step-0);
letter-spacing: var(--tracking-label);
color: var(--ink-muted);
font-weight: 500;
margin: 0 0 var(--space-3);
}
code, kbd, samp, pre {
font-family: var(--font-mono);
font-size: var(--mono-size);
}
a {
color: inherit;
text-underline-offset: 0.2em;
text-decoration-thickness: from-font;
transition: color var(--dur-instant) var(--ease-out);
}
a:hover { color: var(--accent); }
/* 포커스는 어떤 이펙트보다 우선한다 */
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: var(--radius-sm);
}
hr {
border: 0;
border-top: 1px solid var(--line);
margin-block: var(--space-6);
}
/* ---- 표 ---------------------------------------------------- */
table {
border-collapse: collapse;
width: 100%;
font-variant-numeric: tabular-nums;
}
th, td {
text-align: left;
padding: var(--space-2) var(--space-3) var(--space-2) 0;
border-bottom: 1px solid var(--line);
vertical-align: baseline;
}
th {
font-weight: 500;
color: var(--ink-muted);
font-size: var(--step-0);
letter-spacing: var(--tracking-label);
}
/* 좁은 화면에서 표가 페이지를 밀지 않게 — 하드 게이트 #5 */
.table-scroll { overflow-x: auto; }
/* ---- 유틸 -------------------------------------------------- */
.visually-hidden {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.muted { color: var(--ink-muted); }
.mono { font-family: var(--font-mono); font-size: var(--mono-size); }

View file

@ -0,0 +1,125 @@
/* ============================================================
designpaca 소개 페이지 디자인 토큰
프리셋: swiss-minimal / 비율 1.25 / 강조색 1개 / radius 2종
============================================================ */
:root {
/* ---- 폰트 패밀리 ---------------------------------------- */
--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
--mono-size: 0.9375em; /* 부모 대비. 새 스케일 단계를 만들지 않는다 */
/* ---- 색: 라이트 (기본) ----------------------------------- */
--surface: #FAF9F6; /* 웜 오프화이트. 순백 아님 (A-07) */
--surface-raised: #F2F0EA;
--surface-inverse: #14161A; /* 다크 밴드. 순흑 아님 */
--ink: #16181C; /* 대비 16.88:1 */
--ink-muted: #5A5F66; /* 대비 6.11:1 */
--ink-inverse: #E9E7E2; /* 밴드 위 14.66:1 */
--ink-muted-inverse: #9AA0A6; /* 밴드 위 6.86:1 */
--line: #DFDCD4; /* 1.30:1 — 장식 구분선 전용 */
--line-inverse: #2A2E34; /* 1.33:1 — 장식 구분선 전용 */
--line-strong: var(--ink-muted); /* 입력·컨트롤 테두리. WCAG 1.4.11 (3:1) */
--accent: #0E6B63; /* 딥 틸. 대비 6.04:1 */
--accent-ink: #FFFFFF; /* 강조 위 글자. 6.36:1 */
--accent-inverse: #3FA89D; /* 밴드 위 강조. 6.30:1 */
/* ---- 형태: radius 2종 (게이트 #3) ------------------------ */
--radius-sm: 3px; /* 버튼·입력·배지 */
--radius-md: 6px; /* 카드·코드 블록 */
/* ---- 간격 ------------------------------------------------ */
--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: 8rem; /* 128 — 다크 밴드 상하. 본문 간격의 8배 */
/* ---- 모션 ------------------------------------------------ */
--dur-instant: 100ms; /* 호버·포커스 */
--dur-quick: 200ms; /* 작은 등장·퇴장 */
--dur-normal: 320ms; /* 패널·전환. 2단계 상한 */
--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);
/* bounce·elastic 없음 (E-02) */
}
/* ---- 색: 다크 테마 — 라이트와 동등하게 정의 ------------------ */
@media (prefers-color-scheme: dark) {
:root {
--surface: #14161A;
--surface-raised: #1C1F24;
--surface-inverse: #FAF9F6; /* 다크에서는 밴드가 밝아진다 */
--ink: #E9E7E2;
--ink-muted: #9AA0A6;
--ink-inverse: #16181C;
--ink-muted-inverse: #5A5F66;
--line: #2A2E34;
--line-inverse: #DFDCD4;
--line-strong: var(--ink-muted);
--accent: #3FA89D; /* 6.30:1 */
--accent-ink: #0B1A18; /* 6.21:1 */
--accent-inverse: #0E6B63;
}
}
/* ---- 타입: 한국어판 --------------------------------------- */
[lang="ko"] {
--font-sans: "Pretendard Variable", Pretendard, system-ui, sans-serif;
--step-0: 1.0625rem; /* 17 — 본문 · eyebrow · 코드 */
--step-1: 1.328rem; /* 21.3 — 리드 */
--step-2: 1.660rem; /* 26.6 — h3 */
--step-3: 2.076rem; /* 33.2 — h2 */
--step-4: 2.595rem; /* 41.5 — h1 */
--display: clamp(2.595rem, 1.6rem + 4.2vw, 4.25rem); /* → 68 */
--leading-tight: 1.15;
--leading-normal: 1.7; /* 한글은 넉넉하게 */
--measure: 33em; /* ≈ 561px. 한글 글자폭 ≈ 1em */
--tracking-display: -0.01em; /* 한글은 음수 자간을 크게 주지 않는다 */
--tracking-body: 0; /* 한글 본문 음수 자간 금지 */
--tracking-label: 0.08em;
word-break: keep-all;
overflow-wrap: break-word;
}
/* ---- 타입: 영어판 ------------------------------------------ */
[lang="en"] {
--font-sans: "Switzer", system-ui, -apple-system, sans-serif;
--step-0: 1rem; /* 16 */
--step-1: 1.25rem; /* 20 */
--step-2: 1.5625rem; /* 25 */
--step-3: 1.953rem; /* 31.3 */
--step-4: 2.441rem; /* 39 */
--display: clamp(2.441rem, 1.5rem + 4vw, 4rem); /* → 64 */
--leading-tight: 1.1;
--leading-normal: 1.55;
--measure: 65ch; /* ≈ 640px */
--tracking-display: -0.025em;
--tracking-body: 0;
--tracking-label: 0.08em;
}
/* ---- 다크 밴드: 게이트 #4가 요구하는 "규칙으로 정의된 반전" ---- */
/* 사용처는 히어로와 설치 섹션 두 곳뿐이다. 그 외 사용 금지. */
.band-inverse {
--surface: var(--surface-inverse);
--ink: var(--ink-inverse);
--ink-muted: var(--ink-muted-inverse);
--line: var(--line-inverse);
--accent: var(--accent-inverse);
background: var(--surface);
color: var(--ink);
padding-block: var(--space-8);
}