소개 페이지를 스킬 전체 경로로 다시 만들고, 배운 것을 스킬에 반영

방향을 글래스로 바꿀 때 2단계 재결정을 하고도 전체 경로로 올리지 않았다.
레퍼런스 없이 재질만 갈아끼운 결과가 스위스 미니멀 뼈대에 유리를 바른
페이지였고, design.md 는 초판 결정을 그대로 담고 있었다. 0단계부터 다시 돌았다.

1단계 — 레퍼런스 3개를 computed style 까지 실측
  R1 zed.dev      컨테이너 1120px 과 전체폭이 교대 · radius 2px 621회
  R2 lusion.co    3D 는 액자 안, 텍스트는 액자 밖 · 배경 흰색 · h1 36px
  R3 Codrops      DOM 이 구조를 소유하고 WebGL 은 uniform 만 만진다

2단계 — 프리셋 swiss-minimal → dark-instrument, 컨셉 "검사대 위의 물체"
        유리는 액자에만 남긴다(헤더 · 검사대 · 명령창)

4단계 — 히어로 재구성. 캔버스를 배경에서 빼 액자 안으로, 텍스트는 밖으로
        판독기가 통과한 게이트를 표시한다(값이 바뀔 때만 DOM 을 쓴다)
        파이프라인을 2열로 열어 625px → 1113px

5단계에서 실제로 걸린 것
  게이트 3  radius 4종 → 2종 (3px / 14px, pill 제거)
  게이트 1  base.css 토큰 밖 rgb() 7곳 → 토큰
  게이트 7  헤더 English 2.59:1 → ink 로 상향
  카운트    히어로 h1 4줄 → 2줄
  셰이더    판이 정면이라 프레넬이 구조적으로 0. 법선을 굽히고 UV 로 테두리
  셰이더    gl_FragCoord 를 렌더 타겟 크기로 나눠 UV 가 1 을 넘고 있었다
  수치      페이지가 실은 "타입 단계 5단계"가 실측 9종이었다. lang 속성이
            스케일을 재정의해 링크 하나가 16px 로 새고 있었다
  측정      대비 스크립트가 반투명 배경을 불투명으로 계산했다. 알파 합성으로 교정

스킬 반영
  three.md    §0-A 배치 원리(3D 는 액자 안) · 프레넬 0 함정 · gl_FragCoord 함정
  preflight.md 대비 측정 시 알파 합성. 검사 도구가 틀리면 통과도 의미가 없다

최종: 하드 게이트 12/12, 대비 실패 0, 320px 오버플로 0, 테스트 22개 통과
This commit is contained in:
Yun Chan 2026-08-20 13:33:28 +09:00
parent eb3ca69b5d
commit 9648d1d82a
15 changed files with 576 additions and 306 deletions

View file

@ -35,8 +35,12 @@ export interface Content {
install: string;
installNote: string;
links: { label: string; href: string }[];
proofAlt: string;
proofCaption: string;
stage: {
alt: string;
caption: string;
gate: string;
pass: string;
};
};
pipeline: {
eyebrow: string;
@ -174,9 +178,12 @@ export const ko: Content = {
{ label: "저장소", href: "https://git.chanpaca.net/yunchan/designpaca" },
{ label: "npm", href: "https://www.npmjs.com/package/designpaca" },
],
proofAlt:
"designpaca 로 만든 커피 구독 랜딩. 헤드라인은 취향은 형용사가 아니라 좌표입니다 이고, 옆에 원두 3종의 수치표가 있다.",
proofCaption: "이 스킬로 만든 페이지. 브리프 한 줄에서 시작했다.",
stage: {
alt: "유리판 여섯 장이 깊이 방향으로 나란히 서 있다. 스크롤하면 카메라가 판을 하나씩 통과하고, 통과한 판은 뒤로 물러난다.",
caption: "판 하나가 단계 하나다. 통과 조건을 채우지 못하면 다음 판으로 가지 않는다.",
gate: "게이트",
pass: "통과",
},
},
pipeline: {
eyebrow: "여섯 단계",
@ -241,12 +248,12 @@ export const ko: Content = {
"문장을 다듬는 것으로 해결되는 것은 문장뿐이다. radius 어휘 수, 반투명 패널 개수, 타입 단계 수는 그대로 남는다. 그래서 이 페이지 자신의 형태 수치를 공개한다. 결과가 나쁘게 나와도 그대로 싣는다.",
items: [
{ label: "히어로까지 JS", value: "0.6%", note: "예산 50KB 중 실제로 쓴 비율", feature: true },
{ label: "하드 게이트", value: "12/12", note: "8개는 정적 검사, 4개는 320px 실렌더", feature: true },
{ label: "three.js 추가분", value: "185KB", note: "재료 섹션이 가까워질 때만 받는다. 초기 번들에는 없다" },
{ label: "하드 게이트", value: "12/12", note: "정적 검사와 320px · 1440px 실렌더 양쪽", feature: true },
{ label: "three.js 추가분", value: "184KB", note: "검사대가 화면에 들어올 때만 받는다. 초기 번들에는 없다" },
{ label: "슬롭 지문", value: "0건", note: "9개 패턴 grep" },
{ label: "radius 어휘", value: "2종", note: "10px, 20px. 셸은 파생값" },
{ label: "반투명 패널", value: "5개", note: "29개까지 늘렸다가 걷어냈다. 유리는 정말 떠 있어야 하는 것에만 남겼다" },
{ label: "타입 단계", value: "5단계", note: "디스플레이는 스케일 밖" },
{ label: "radius 어휘", value: "2종", note: "3px 과 14px. 알약 모양을 없앴다" },
{ label: "반투명 패널", value: "2개", note: "29개까지 늘렸다가 걷어냈다. 유리는 무언가를 담는 액자에만 남겼다" },
{ label: "타입 단계", value: "6단계", note: "토큰에 정의된 수. 디스플레이는 스케일 밖이고, 최대 글자는 본문의 5.6배" },
{ label: "폰트 패밀리", value: "2개", note: "언어판마다 자기 것만 받는다" },
{ label: "강조색", value: "1개", note: "라이트와 다크는 같은 색의 대응값" },
{ label: "첫 인터랙션", value: "미측정", note: "배포 후 Lighthouse 로 잰다" },
@ -301,8 +308,28 @@ export const ko: Content = {
caught: "본문 컬럼이 960px. 우리가 정한 한 줄 길이는 561px",
fixed: "그리드의 본문 폭을 토큰에 묶었다. 스킬 문서의 예시 코드도 같이 고쳤다.",
},
{
caught: "방향을 바꾸면서 이 스킬의 1단계를 건너뛰었다",
fixed:
"재질을 유리로 바꾸라는 요청은 2단계 방향 재결정이고, 그때는 전체 경로로 올려 레퍼런스부터 다시 봐야 한다. 그러지 않고 구현으로 바로 들어갔다. 결과는 이전 방향의 뼈대에 유리를 바른 페이지였고 design.md 는 옛 결정을 그대로 담고 있었다. 0단계부터 다시 돌았다.",
},
{
caught: "유리판이 정면으로 서 있어 프레넬이 구조적으로 0이었다",
fixed:
"평면이 카메라를 정면으로 보면 법선과 시선의 내적이 1이라 가장자리 반사가 계산되지 않는다. 유리로 읽히게 하는 유일한 신호가 죽어 있었고, 그래서 판 여섯 장이 흐린 사각형으로 보였다. 법선을 미세하게 굽히고 테두리 광을 UV 경계에서 따로 만들었다.",
},
{
caught: "페이지의 본체인 파이프라인이 화면의 43%만 쓰고 있었다",
fixed:
"1440px 중 625px. 아홉 섹션에서 가장 좁으면서 높이는 1637px 로 가장 길었다. 단계 설명과 산출물을 두 열로 열어 1113px 로 넓혔다.",
},
{
caught: "대비를 재는 스크립트가 반투명 배경을 불투명으로 계산했다",
fixed:
"\"English 1.15:1\" 이라는 틀린 값이 나왔다. 알파를 아래에서 위로 합성하도록 고치자 실패 0건이었다. 검사 도구가 틀리면 통과도 실패도 의미가 없다.",
},
],
note: "아홉 건 모두 만들면서 걸린 것이고, 걸린 뒤에 고쳤다. 사람이 잡은 것이 둘이다. 카드가 전형적이라는 말과, 폰트를 제대로 다루지 못한다는 말.",
note: "열세 건 모두 만들면서 걸린 것이고, 걸린 뒤에 고쳤다. 사람이 잡은 것이 셋이다. 카드가 전형적이라는 말, 폰트를 제대로 다루지 못한다는 말, 그리고 우리 스킬을 진짜로 쓴 게 맞냐는 말.",
},
typography: {
eyebrow: "한글 조판",
@ -373,9 +400,12 @@ export const en: Content = {
{ label: "Repository", href: "https://git.chanpaca.net/yunchan/designpaca" },
{ label: "npm", href: "https://www.npmjs.com/package/designpaca" },
],
proofAlt:
"A coffee roastery subscription landing page built with designpaca. The hero carries a table of acidity and body figures for three beans.",
proofCaption: "Built with this skill, starting from one line of brief.",
stage: {
alt: "Six glass panes stand in a row along the depth axis. Scrolling moves the camera through them one at a time, and each pane recedes once passed.",
caption: "One pane is one stage. Fail its condition and you do not reach the next.",
gate: "GATE",
pass: "PASS",
},
},
pipeline: {
eyebrow: "Six stages",
@ -440,12 +470,12 @@ export const en: Content = {
"Polishing sentences fixes sentences. The radius vocabulary, the translucent panels, the number of type steps all stay. So here are this page's own form metrics. If a number comes back badly, it ships as it is.",
items: [
{ label: "JS to first paint", value: "0.6%", note: "of the 50KB budget actually spent", feature: true },
{ label: "hard gates", value: "12/12", note: "8 checked statically, 4 on a real 320px render", feature: true },
{ label: "three.js payload", value: "185KB", note: "fetched only as the materials section approaches. Never in the initial bundle" },
{ label: "hard gates", value: "12/12", note: "static checks plus real renders at 320px and 1440px", feature: true },
{ label: "three.js payload", value: "184KB", note: "fetched only when the inspection frame enters view. Never in the initial bundle" },
{ label: "slop fingerprints", value: "0", note: "9 patterns grepped" },
{ label: "radius vocabulary", value: "2", note: "10px and 20px. The shell is derived" },
{ label: "translucent panels", value: "5", note: "grew to 29 before being pulled back. Glass stayed only where something has to float" },
{ label: "type scale steps", value: "5", note: "the display size sits outside the scale" },
{ label: "radius vocabulary", value: "2", note: "3px and 14px. The pill shape is gone" },
{ label: "translucent panels", value: "2", note: "grew to 29 before being pulled back. Glass stayed only on frames that hold something" },
{ label: "type scale steps", value: "6", note: "as defined in tokens. Display sits outside the scale, and the largest type is 6x the body" },
{ label: "font families", value: "2", note: "each language loads only its own" },
{ label: "accent colours", value: "1", note: "light and dark are the same colour" },
{ label: "time to interactive", value: "not yet", note: "measured with Lighthouse after deploy" },
@ -501,8 +531,28 @@ export const en: Content = {
fixed:
"Bound the grid's main column to the token. The skill's own example code was wrong too, so that got fixed as well.",
},
{
caught: "We skipped this skill's own stage 1 when the direction changed",
fixed:
"Switching the material to glass is a stage-2 decision, and that means going back to references first. We jumped straight to implementation instead. The result was glass painted onto the previous direction's skeleton, while design.md still described the old decisions. We re-ran the whole path from stage 0.",
},
{
caught: "The glass panes faced the camera head-on, so Fresnel was structurally zero",
fixed:
"When a flat plane faces the camera, the dot product of normal and view is 1, so no edge reflection is computed. The one signal that makes a surface read as glass was dead, which is why six panes looked like blurry rectangles. We bend the normal slightly and derive the rim light from the UV edge instead.",
},
{
caught: "The pipeline, the spine of this page, used only 43% of the viewport",
fixed:
"625px out of 1440. Narrowest of the nine sections while being the tallest at 1637px. Opening each stage into two columns brought it to 1113px.",
},
{
caught: "The contrast script treated translucent backgrounds as opaque",
fixed:
"It reported \"English 1.15:1\", which was wrong. Compositing alpha bottom-up gave zero failures. A checker that is wrong makes both its passes and its failures meaningless.",
},
],
note: "All nine were caught while building this page, and fixed after being caught. Two came from a person rather than a checker: the cards look generic, and the typography is not handled well.",
note: "All thirteen were caught while building this page, and fixed after being caught. Three came from a person rather than a checker: the cards look generic, the typography is not handled well, and did we actually use our own skill.",
},
typography: {
eyebrow: "Your language is probably not Latin",