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

방향을 글래스로 바꿀 때 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

@ -18,17 +18,22 @@ const FONT_CSS = {
const alt = lang === "ko" ? "/en/" : "/";
// 파비콘: 페이지의 스파인 모티프를 그대로 쓴 단순 기하 마크
// 파비콘: 페이지의 스파인 모티프를 그대로 쓴 단순 기하 마크.
// data: URI 안의 SVG 는 상위 문서의 커스텀 프로퍼티를 읽지 못한다.
// 하드 게이트 #1 의 유일한 예외이고, 값은 tokens.css 와 손으로 맞춘다.
// MARK_BG = --accent-inverse · MARK_FG = --surface-inverse
const MARK_BG = "#0E6B63";
const MARK_FG = "#F4F2EC";
const FAVICON =
"data:image/svg+xml," +
encodeURIComponent(
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" rx="6" fill="#0E6B63"/>
<path d="M11 7v18" stroke="#FAF9F6" stroke-width="2" stroke-linecap="round"/>
<circle cx="11" cy="10" r="3" fill="#FAF9F6"/>
<circle cx="11" cy="16" r="3" fill="#FAF9F6"/>
<circle cx="11" cy="22" r="3" fill="#FAF9F6"/>
<path d="M18 10h7M18 16h5M18 22h7" stroke="#FAF9F6" stroke-width="2" stroke-linecap="round" opacity=".55"/>
<rect width="32" height="32" rx="3" fill="${MARK_BG}"/>
<path d="M11 7v18" stroke="${MARK_FG}" stroke-width="2" stroke-linecap="round"/>
<circle cx="11" cy="10" r="3" fill="${MARK_FG}"/>
<circle cx="11" cy="16" r="3" fill="${MARK_FG}"/>
<circle cx="11" cy="22" r="3" fill="${MARK_FG}"/>
<path d="M18 10h7M18 16h5M18 22h7" stroke="${MARK_FG}" stroke-width="2" stroke-linecap="round" opacity=".55"/>
</svg>`,
);
---
@ -144,7 +149,12 @@ const FAVICON =
/* 상단에 붙은 풀블리드 바 대신 떠 있는 헤더 */
/* 상단에 붙은 바가 아니라 떠 있는 유리 알약 */
/* 언어 전환 링크에는 lang 속성이 붙는다(스크린리더가 "English" 를
영어로 읽어야 하므로 옳다). 그런데 [lang] 셀렉터가 타입 스케일을
통째로 재정의해서 이 링크만 16px 이 됐다 — 스케일 밖 단계가 하나 생긴다.
크기는 헤더에서 확정하고 링크는 상속만 받는다. */
.site-header {
font-size: var(--step-0);
position: fixed;
top: var(--space-3);
left: 0;
@ -160,7 +170,7 @@ const FAVICON =
justify-content: space-between;
gap: var(--space-4);
padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
border-radius: 999px;
border-radius: var(--radius-frame);
}
.wordmark {
display: inline-flex;
@ -176,11 +186,13 @@ const FAVICON =
align-items: center;
min-height: 36px;
padding-inline: var(--space-3);
border-radius: 999px;
border-radius: var(--radius-sm);
font-size: inherit;
background: var(--glass-tint-2);
border: 1px solid var(--glass-edge);
font-size: var(--step-0);
color: var(--ink-muted);
/* muted 로 두면 유리 위에서 2.59:1 이다. 언어 전환은 내비게이션이지
보조 정보가 아니므로 ink 로 올린다(하드 게이트 #7) */
color: var(--ink);
text-decoration: none;
transition: color var(--dur-instant) var(--ease-out),
background var(--dur-instant) var(--ease-out);