From 9c9ab2de7e61ceb42ee699daf4b8e03be6e27bed Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Thu, 20 Aug 2026 14:15:30 +0900 Subject: [PATCH] =?UTF-8?q?=EB=94=94=EC=9E=90=EC=9D=B8=20SSOT=20=EB=A5=BC?= =?UTF-8?q?=20=EC=84=B8=EC=9A=B0=EA=B3=A0=203D=20=EB=A5=BC=20=EB=B0=B0?= =?UTF-8?q?=EA=B2=BD=20=EC=9E=AC=EC=A7=88=EB=A1=9C=20=EB=90=98=EB=8F=8C?= =?UTF-8?q?=EB=A6=B0=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 지적받은 것: 모바일 마진·패딩, 폰트 웨이트, 버튼 스타일 불일치, SSOT, 스크롤바, 모바일 메뉴, 그리고 3D 를 왜 상자에 넣었는지. 3D 의 역할을 잘못 잡았다 lusion.co 의 "3D 는 액자 안"은 3D 자체가 상품일 때의 규칙이다. 우리는 절차를 파는데 액자에 넣을 상품이 없어 "저 상자는 뭐냐"가 됐고, 의미를 게이트 판독기가 자막으로 설명하고 있었다. 이 씬의 역할은 재질이다. 배경으로 되돌리고 값을 전부 낮췄다 — 테두리 광 0.85->0.42, 알파 0.72->0.34, UV 경계 0.05->0.17, 이동 60% ResizeObserver 로 캔버스를 따라가게 했다. window.resize 만 듣는 동안 히어로 높이 변화를 놓쳐 배경이 화면의 3분의 2만 덮었다 SSOT 웨이트 6종(400/500/560/600/620/660) -> 3종. 셋은 토큰에 없던 값이었다 .btn + btn-solid/btn-quiet. 두 버튼이 높이 36 vs 44, 패딩 16 vs 8, 테두리 1px vs 0, 웨이트 400 vs 500 이었다 --header-h. 간격을 clamp 로 바꾸자 관계가 끊겨 h1 이 헤더 뒤로 들어갔다 --space-5~8 과 --gutter 를 clamp 로. 고정이면 모바일 여백이 화면의 26% scrollbar-color 지정 모바일 좌우 여백 24 -> 32px, 섹션 상하 112 -> 56px 헤더에 섹션 앵커 4개. 900px 미만은 details 기반 메뉴(JS 0바이트) 패럴랙스는 섹션마다 다른 말을 한다 히어로 글자 상승 / 배경 하강 — 반대 방향이라야 시차가 보인다 파이프라인 단계명 고정, 산출물만 지연 — 인과 재료 타일이 서로 다른 깊이 — 표면은 한 겹이 아니다 프리플라이트 뒤 항목일수록 늦게 — 로그는 흐른다 수치 없음. 의도적 정지 — 계기판의 바늘은 떨지 않는다 스킬 three.md §0-A 를 역할별로 갈랐다. "액자 안"만 적어둔 것이 잘못된 일반화였고 내가 거기 그대로 걸렸다. 재질일 때의 값 교정을 실측으로 남김 tokens.md 웨이트·컨트롤·헤더 높이·반응형 간격 — 토큰이 아예 없던 네 축 motion.md 섹션별 패럴랙스 배정표. 움직이지 않는 것도 결정이다 390px 실렌더: 가로 스크롤 0, 대비 실패 0, 웨이트 3종, radius 2종. 테스트 22개 통과 --- apps/site/design.md | 59 +++++ apps/site/src/components/CopyCommand.astro | 26 +-- apps/site/src/components/Hero.astro | 244 ++++++++------------- apps/site/src/components/Install.astro | 6 +- apps/site/src/components/Materials.astro | 4 +- apps/site/src/components/Metrics.astro | 17 +- apps/site/src/components/Pipeline.astro | 6 +- apps/site/src/components/Preflight.astro | 6 +- apps/site/src/components/Rules.astro | 4 +- apps/site/src/components/Showcase.astro | 6 +- apps/site/src/i18n/content.ts | 19 ++ apps/site/src/layouts/Base.astro | 105 +++++++-- apps/site/src/lib/hero-scene.ts | 40 ++-- apps/site/src/styles/base.css | 106 ++++++++- apps/site/src/styles/tokens.css | 43 +++- packages/skill/references/motion.md | 52 +++++ packages/skill/references/three.md | 32 ++- packages/skill/references/tokens.md | 62 ++++++ 18 files changed, 606 insertions(+), 231 deletions(-) diff --git a/apps/site/design.md b/apps/site/design.md index 80316f1..f13727c 100644 --- a/apps/site/design.md +++ b/apps/site/design.md @@ -168,6 +168,65 @@ WebGL 게이트: `prefers-reduced-motion` 이면 **아예 시작하지 않는다 - **언어 자동 리다이렉트 / 국기 아이콘** — 사용자를 놀라게 하고, 언어는 국가가 아니다 - **두 판을 번역으로 만들기** — 각 언어판을 따로 썼다 +## 3D 의 역할 — 주인공이 아니라 재질 + +**한 번 액자 안에 넣었다가 되돌렸다.** R2(lusion.co)의 "3D 는 액자 안"은 **3D 자체가 상품일 때**의 +규칙이다. 그 스튜디오는 3D 를 팔기 때문에 액자가 쇼케이스 프레임으로 정당하다. +우리는 절차를 파는데 액자 안에 넣을 상품이 없어서, 보는 사람이 "저 상자는 뭐냐"고 묻게 됐다. +게다가 의미를 `게이트 01 / 06` 판독기가 **자막으로 설명하고 있었다** — 그림이 스스로 말하지 +못해서 자막을 단 것이다. + +이 씬의 역할은 **재질**이다. 공간을 만드는 표면이지 볼거리가 아니다. 그래서 규칙이 반대다: + +| | 주인공(액자) | 재질(배경) — 현행 | +|---|---|---| +| 테두리 광 | 0.85 | **0.42** | +| 알파 | 0.72 | **0.34** | +| UV 경계 | `smoothstep(0, 0.05)` | **`smoothstep(0, 0.17)` + 제곱** | +| 카메라 이동 | 전 구간 | **60%** | +| 텍스트 | 액자 밖 | 위에 앉되 **스크림으로 자리를 눌러줌** | + +`ResizeObserver` 로 캔버스를 따라가게 했다. `window.resize` 만 듣던 동안 히어로 높이 변화를 +놓쳐 배경이 화면의 3분의 2만 덮고 아래가 검게 비었다. + +## 모션 문법 — 섹션마다 다른 말 + +같은 패럴랙스를 전부에 걸면 벽지다. 각 섹션의 주장을 움직임으로 옮겼다. + +| 섹션 | 주장 | 움직임 | +|---|---|---| +| 히어로 | 결정하지 않으면 기본값이 나온다 | 글자 ↑ / 배경 ↓ — **반대 방향**이라야 시차가 보인다 | +| 파이프라인 | 단계를 밟으면 결과가 나온다 | 단계명 **고정**, 산출물만 지연 | +| 사례 | 같은 스킬에서 다른 결과 | 두 판이 다른 속도 | +| 재료 | 표면은 한 겹이 아니다 | 타일이 서로 다른 깊이 | +| 프리플라이트 | 시간순 기록 | 뒤 항목일수록 늦게 | +| **수치** | 공개한 값은 검증 가능하다 | **없음 — 의도적 정지** | + +마지막 줄이 결정이다. 숫자가 스크롤에 흔들리면 그 값도 흔들려 보인다. + +## 디자인 SSOT + +토큰이 없어서 깨져 있던 세 축을 채웠다. + +- **웨이트 3종** — `400 / 500 / 600`. 이전에는 코드 곳곳에 `500·560·600·620·660` 이 흩어져 + **6종**이었고 셋은 토큰에 없는 값이었다. R1 모바일 실측은 `400` 이 832회, 나머지 12회다 +- **컨트롤 치수** — `--control-h: 44px` · `--control-h-sm: 36px` · `--control-pad-x`. + 버튼처럼 생긴 것은 전부 `.btn` + `.btn-solid` / `.btn-quiet` 를 쓴다. + 이전에는 두 버튼이 높이 36 vs 44, 패딩 16 vs 8, 테두리 1px vs 0, 웨이트 400 vs 500 이었다 +- **`--header-h`** — 떠 있는 헤더의 높이. 간격 토큰을 `clamp()` 로 바꾸는 순간 관계가 끊겨 + h1 이 헤더 뒤로 들어갔다. **값이 아니라 관계를 토큰으로 둔다** +- **반응형 간격** — `--space-5~8` 과 `--gutter` 를 `clamp()` 로. 고정이면 모바일에서 + 섹션 상하 112px 이 그대로 들어가 화면의 26% 를 여백이 먹는다 +- **스크롤바** — `scrollbar-color` 지정. 기본값이면 어두운 페이지 옆에 OS 색 밝은 막대가 선다 + +## 모바일 + +- 좌우 여백 24px → **32px** (R1 모바일 실측값) +- 섹션 상하 112px → **56px** +- 헤더에 섹션 앵커 4개 추가. 900px 미만에서는 `
` 기반 메뉴로 접힌다 — + JS 0바이트이고 열림 상태·Esc·포커스 순서·`aria-expanded` 를 브라우저가 맞게 한다 +- 390px 실렌더: 가로 스크롤 0, 대비 실패 0, 웨이트 3종, radius 2종 + ## 히어로 3D 의 형태 결정 - 판 **15 × 6** (액자 비율 2.5:1 과 일치). 첫 판이 화면을 완전히 덮어 이미 첫 게이트 안에 들어와 있다 diff --git a/apps/site/src/components/CopyCommand.astro b/apps/site/src/components/CopyCommand.astro index 4f9521b..07dbc32 100644 --- a/apps/site/src/components/CopyCommand.astro +++ b/apps/site/src/components/CopyCommand.astro @@ -12,7 +12,7 @@ const { command, copyLabel, copiedLabel, note } = Astro.props;
{command} -