feat(skill): absorb external design skills, restore interview gate, add review route
- Restore the step-0 interview as a mechanical gate the skill explicitly depends on; add harness.md (per-harness question tools, limits, fallbacks) and brief-interview.md (slots, question cards, rounds). - Add 10 reference docs absorbed from external design skills (accessibility, interaction-feel, elevation, color, icons, product-copy, component-systems, critique, change-review, print-email) and extend existing references. - Add a review-only route and two hard-gate clauses (truncated content reachability, three-flashes limit). - design-gate: split tap targets into WCAG 2.5.8 and 44px contract layers, run axe-core when available, and fix false positives found on a real site (decorative alt="", stacked wordmark line count, url-only pages). - lint-skill: fail if the interview gate section or its links disappear. - Ship agents/openai.yaml and THIRD_PARTY_NOTICES.md.
This commit is contained in:
parent
79e79c120b
commit
6805fb2be7
37 changed files with 5688 additions and 128 deletions
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
이 순위는 기본 탐색 순서일 뿐이다. 자산 용도·품질·권리·진실성 판단보다 앞서지 않는다.
|
||||
|
||||
사용자가 이미 자산을 제공했거나 사용 가능한 사진이 없다고 명시했거나, `design.md`·저장소에서 확인할 수 있으면 다시 묻지 않는다. 기존 정보로 확인할 수 없고 자산 유무가 결정에 필요할 때만 **0단계에서 묻는다**: "쓸 수 있는 사진이 있나요?"
|
||||
사용자가 이미 자산을 제공했거나 사용 가능한 사진이 없다고 명시했거나, `design.md`·저장소 파일로 확인할 수 있으면 다시 묻지 않는다. 그 밖의 경우에는 **0단계 브리프 슬롯(기존 브랜드 자산)** 으로 반드시 묻는다: "쓸 수 있는 사진이 있나요?" — 자산 유무가 이번 화면 구성을 얼마나 바꿀지를 스스로 판단해 질문을 생략하지 않는다. 슬롯 확인·질문 카드는 [brief-interview.md](brief-interview.md)를 따른다.
|
||||
없다는 답만으로 생성 경로를 자동 선택하지 않는다. 슬롯별 자산 용도·품질·권리·진실성을 비교해 경로를 고르고, 생성물을 쓰면 **생성물이라는 사실을 `design.md` 에 적는다.**
|
||||
나중에 실제 사진으로 바꿀 가능성이 있으면 레이아웃을 다시 짜지 않도록 비율을 미리 고정해 둔다. 구도·크롭·타이포 검토는 [art-direction.md](art-direction.md)를 따른다.
|
||||
|
||||
|
|
@ -135,6 +135,34 @@ await sharp(src).resize({ width: w }).webp({ quality: 82 }).toFile(out);
|
|||
| 본문 폭 이미지 | 1100px |
|
||||
| 카드·썸네일 | 640px |
|
||||
|
||||
## 3-b. 화면별로 다른 크기를 보낸다 — srcset·sizes·picture
|
||||
|
||||
**프로젝트 계약 — 히어로처럼 화면 전체에 걸리는 이미지는 `srcset`으로 화면별 실제 크기를 보낸다.** §3에서 만든 여러 해상도 파일을 하나의 `<img>`에 폭 서술자(`w`)로 나열하고, `sizes`로 뷰포트별 실제 표시 폭을 알려준다. 브라우저가 다운로드 시점에 화면 폭·픽셀 밀도에 맞는 파일을 고른다.
|
||||
|
||||
```html
|
||||
<img
|
||||
srcset="hero-640.webp 640w, hero-1100.webp 1100w, hero-1600.webp 1600w"
|
||||
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 90vw, 1600px"
|
||||
src="hero-1100.webp"
|
||||
width="1600" height="900" alt="..." />
|
||||
```
|
||||
|
||||
`sizes`는 CSS 레이아웃이 실제로 이미지에 주는 폭과 일치해야 한다. 전체폭 배경은 `100vw`에 가깝고, 그리드 안의 카드 이미지는 그리드 열 폭을 반영한다 — 대충 적으면 브라우저가 필요 이상으로 큰 파일을 내려받는다 [SKILL-IMPECCABLE].
|
||||
|
||||
**모바일과 데스크톱에서 피사체 자체가 다르게 잘려야 하면(art direction) `<picture>`로 분기한다.** `srcset`은 같은 그림의 해상도만 바꾼다. §2의 이미지 바이블에서 모바일 히어로를 별도 원본으로 정했다면 `<source>`로 명시적으로 분기한다. 각 `<source>`에도 `sizes`를 함께 준다 — 없으면 브라우저가 `100vw`로 가정해 필요 이상으로 큰 파일을 고를 수 있다.
|
||||
|
||||
```html
|
||||
<picture>
|
||||
<source media="(max-width: 640px)" srcset="hero-mobile-750.webp 750w, hero-mobile-1080.webp 1080w" sizes="100vw">
|
||||
<source media="(min-width: 641px)" srcset="hero-1100.webp 1100w, hero-1600.webp 1600w" sizes="(max-width: 1024px) 90vw, 1600px">
|
||||
<img src="hero-1100.webp" width="1600" height="900" alt="..." />
|
||||
</picture>
|
||||
```
|
||||
|
||||
`<picture>`는 항상 대체용 `<img>`로 닫는다 — 어떤 `<source>`도 조건에 맞지 않을 때의 폴백이자, `alt`·`width`·`height`가 실제로 적용되는 자리다 [SKILL-IMPECCABLE].
|
||||
|
||||
---
|
||||
|
||||
## 4. `<img>` 에 `width`/`height` 를 적었다면 `height: auto` 를 반드시 줘라
|
||||
|
||||
CLS 를 막으려고 속성을 적는 것은 맞다. 그런데 CSS 에서 높이를 정하지 않으면
|
||||
|
|
@ -159,6 +187,36 @@ img { max-width: 100%; height: auto; } /* 이 한 줄이 없으면 */
|
|||
|
||||
## 5. `alt` 는 장식이 아니면 반드시 쓴다
|
||||
|
||||
**하드 게이트 — 이미지의 용도를 다섯 가지로 나누고 각각 다르게 쓴다.** 장식과 비장식을 한 덩어리로 다루면 정보성·기능성·텍스트 이미지가 각각 요구하는 다른 문장을 놓친다 [SKILL-BETTER-A11Y].
|
||||
|
||||
| 분류 | 무엇인가 | `alt`에 적는 것 | 예시 |
|
||||
|---|---|---|---|
|
||||
| 장식 | 배경 텍스처·그레인처럼 정보가 없는 순수 시각 장식 | `alt=""` + `aria-hidden="true"` | 헤더 뒤 그라디언트 패턴 |
|
||||
| 정보성 | 내용을 전달하는 사진·일러스트 | 무엇이 보이는지 서술 | `alt="작업대 위에 놓인 마른 꽃 다발과 가위"` |
|
||||
| 기능성 | 클릭·이동 같은 동작을 일으키는 이미지(아이콘 버튼, 링크가 된 로고) | 이미지 묘사가 아니라 **행동**을 서술 | `alt="장바구니로 이동"` |
|
||||
| 텍스트 이미지 | 이미지 안에 글자가 박혀 있다(로고, 스캔한 포스터) | 이미지 속 **텍스트를 그대로** 옮긴다 | `alt="2026 가을 컬렉션"` |
|
||||
| 복합 이미지 | 차트·인포그래픽·스크린샷처럼 요약이 필요하다 | 짧은 요약을 `alt`에 쓰고, 상세 값은 본문 표·목록으로 따로 둔다 | `alt="최근 3개월 방문자 추이, 9월에 40% 증가"` + 본문 수치 표 |
|
||||
|
||||
- 내용을 나르는 이미지 → **무엇이 보이는지** 적는다. "이미지", "사진" 은 alt 가 아니다
|
||||
- 순수 장식(배경 텍스처·그레인) → `alt=""` + `aria-hidden="true"`
|
||||
- 캡션이 이미 설명하고 있으면 alt 는 짧게. 같은 문장을 두 번 읽히지 않는다
|
||||
|
||||
**하드 게이트 — `alt` 속성 자체를 빼먹는 것은 빈 `alt=""` 보다 나쁘다.** 스크린리더는 `alt` 속성이 없는 `<img>`를 만나면 파일 경로나 파일명을 대신 읽는다. 빈 `alt=""`는 "건너뛰어도 된다"는 의도된 신호지만, 속성 누락에는 그 의도가 없어 스크린리더가 의미 없는 문자열을 그대로 읽는다 — 아무것도 전달하지 않는 것보다 나쁘다 [SKILL-BETTER-A11Y].
|
||||
|
||||
---
|
||||
|
||||
## 6. 이미지 1px 중립 외곽선 — 관찰 후보
|
||||
|
||||
밝은 배경 위의 흰 계열 사진, 어두운 배경 위의 검정 계열 사진은 경계가 배경에 녹아 사라진다. 색조 없는 중립 1px 외곽선을 후보로 검토한다.
|
||||
|
||||
```css
|
||||
img {
|
||||
outline: 1px solid oklch(0 0 0 / 0.1);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
img { outline-color: oklch(1 0 0 / 0.1); }
|
||||
}
|
||||
```
|
||||
|
||||
`border` 대신 `outline`을 쓰는 이유는 레이아웃 폭에 영향을 주지 않기 때문이다 — 이미지 표시 크기가 그대로 유지된다. slate·zinc 계열처럼 색조가 있는 중성색은 피한다. 사진 표면 위에서 "때"처럼 보이기 쉽다. 이 값은 시작값이며, 사진이 이미 카드 테두리·그림자 같은 뚜렷한 경계를 갖고 있으면 불필요하다 [SKILL-BETTER-UI].
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue