<!-- SuperFID app-v3 dir-tc — 개발 핸드오프 · 디자인 시스템. 갱신 2026-07-11. -->
<!-- SSOT = design-system.css (모든 토큰·컴포넌트). 정책·유스케이스 = SPEC.md · superfid-wiki. -->
# SuperFID 작업자 앱 v3 (dir-tc) — 디자인 시스템 & 개발 핸드오프

현장 작업자용 RFID 재고관리 앱. 웹/앱 개발자가 `design-system.css` + 각 `*.html`을 기준으로 구현한다.
이 문서는 토큰·컴포넌트 계약을 서술하며, **값이 어긋나면 언제나 `design-system.css`가 정본이다** (이 문서가 아님).

- **SSOT**: `design-system.css` — 모든 색·폰트·굵기·자간·간격·컴포넌트 클래스가 여기 산다.
- **정책 SSOT**: `SPEC.md`, `superfid-wiki` (유스케이스·스코프·입력수단 규칙).
- **로컬 미리보기**: `cd ~/dev/superfid-mockups/app-v3/dir-tc && python3 -m http.server 4173` → `localhost:4173`

---

## 1. 원칙 (토큰 강제)

1. **토큰 하드코딩 0.** 화면 HTML/`<style>`은 색·폰트·`font-size`·`font-weight`·`letter-spacing`를 **절대 직접 쓰지 않는다.** 전부 `design-system.css`의 클래스·변수를 통해서만 온다. 새 값이 필요하면 화면이 아니라 CSS 토큰에 추가한다.
2. **per-screen `<style>` = 레이아웃 배치 전용.** 허용: `padding`/`margin`/`display`/`flex`/`grid`/`gap`/`height`/`overflow`, 그리고 특정 화면에서만 쓰는 컨테이너(`.home`, `.confirm-body`, `.chips` 등)의 배치. 금지: 색·타이포·굵기·자간·radius 재정의.
   - 예: `work-home.html`은 `.home{padding…}` `.titlerow{display:flex…}`만 정의하고, 시각 토큰은 하나도 건드리지 않는다.
3. **기준 뷰포트 360×800.** `html,body{width:360px;height:800px}`. 모든 화면은 `.phone`(360×800, `flex-column`, `overflow:hidden`) 안에 산다. 스크롤 화면은 가운데 목록만 `overflow-y:auto`, 상단/하단은 고정.
4. **폰트**: 본문 `Pretendard Variable`(→ `Pretendard` → `sans-serif`). 숫자 등폭은 `JetBrains Mono`를 `.mono` 클래스로만. 매 화면이 두 웹폰트를 `<link>`로 로드한다.

> 자기완결성(self-containment)은 의도적으로 폐기됨 (Tony 지시 2026-07-11): 모든 파일이 한 폴더를 공유하므로 각 화면은 `design-system.css` 한 장을 `<link>`로 공유한다. 토큰을 화면에 인라인 복제하지 않는다.

---

## 2. 컬러

### 2.1 뉴트럴 사다리 (R≈G≈B, 쿨 트루-뉴트럴)
| 토큰 | 값 | 용도 |
|---|---|---|
| `--surface` | `#FFFFFF` | 캔버스 + 카드 (순백) |
| `--gray-50` | `#F7F8FA` | `--fill-2` (부드러운 인셋 카드 배경) |
| `--gray-100` | `#F5F6F9` | `--tile` / `--fill` (칩·타일·입력 배경) |
| `--gray-200` | `#E6E8EE` | `--line` (헤어라인 보더) |
| `--gray-300` | `#D5D7DF` | 강한 보더 · 비활성 CTA 배경 |
| `--gray-400` | `#AAADB8` | 뮤트 아이콘 |
| `--ink` | `#15161C` | 본문 잉크 |
| `--ink-sub` | `#565A66` | 보조 텍스트 |
| `--ink-mute` | `#737782` | 뮤트 텍스트 (a11y 대비 하한) |

별칭: `--line=gray-200`, `--tile=gray-100`, `--fill=gray-100`, `--fill-2=gray-50`.

### 2.2 블루 = 유일한 포인트 색
`--brand:#2E44FF` — **화면에 등장하는 유일한 채도 있는 브랜드 색.** 오직 CTA / 활성 / 포커스 / 선택 상태에만 쓴다. 보조: `--brand-2:#7C8CFF`, `--tint:#E7ECFF`, `--tint-2:#DCE3FF`.

브랜드 블루가 나타나는 곳 (이 목록 외에는 쓰지 않는다):
- 주 CTA: `.btn.primary`, `.putbtn`, `.req-btns .btn.approve`, `.rdr-row .rbtn` (배경)
- 활성 탭/토글: `.dtab.on`(배경 `--tint`·글자 `--brand`), `.segmented button.on`(글자 `--brand`), `.chip.count`
- 선택 표식: `.loc-row .ck`(체크), `.loc-row.sel .box`, `.rrow-check`
- 포커스 링: `.fbox.focus`(보더 `--brand` + `0 0 0 3px --tint`), OTP `.d.cursor`
- 브랜드 강조: `.brandmark`, `.info-card .ic`, `.hl-brand`, `.icon-brand`, `.ic-brand`
- 스캔 진행 도트: `.scan-chip .d`

### 2.3 이벤트 3색 (증가 / 감소 / 맞춤)
한 패밀리, 동일 채도. 각 이벤트는 **circle(면·연함) / fill(중간) / ink(진함)** 3단계.

| 이벤트 | ink | fill | circle | 의미 |
|---|---|---|---|---|
| in (증가) | `--c-in:#12A08C` | `--c-in-fill:#86D6C6` | `--c-in-circle:#DBF2EE` | 입고·반품 = 터콰이즈 |
| out (감소) | `--c-out:#E03E4C` | `--c-out-fill:#F29AA0` | `--c-out-circle:#FCE1E2` | 출고·판매 = 크림슨 |
| set (맞춤) | `--c-set:#5C6980` | `--c-set-fill:#B4BBCB` | `--c-set-circle:#E5E8F1` | 조정·조사 = 쿨 슬레이트 |

`--c-*-tint`는 각 `-circle`의 별칭. 메달리온/아바타는 `.event-in/out/set` 클래스가 `--med-fill`·`--med-ink`(또는 `--icon-fill`·`--icon-ink`)를 이 값으로 오버라이드해 SVG를 물들인다 — **아이콘 색을 SVG 속성에 하드코딩하지 않는다.**

### 2.4 시맨틱 상태색
- `--amber:#A2770D` + `--amber-tint:#FCEEC6` — 확인 필요·경고 (`.list-row.warn`, `.row-flag`, `.queue-banner .qb-dot`, `.done .stat .sv.warn`)
- `--green:#38B36B` — 연결/온라인 도트 (`.chip .dot`, 리더기 상태)
- `--red:#DC4C4C` — 파괴적 액션 (`.logout`, `.pbtn.danger`)

### 2.5 금지
- **브랜드 글로우 box-shadow 금지** (2026-07-11 전량 제거). 그림자는 중립 회색(`rgba(16,24,40,…)`)만 — dock·sheet·segmented on·pick-change.
- **유저 아바타 사진 금지.** `.row-av`는 이니셜 글자 또는 듀오톤 SVG. 사람 사진 없음.
- **상품 사진 썸네일 금지.** 목록은 텍스트 + 이니셜 서클만.
- 뉴트럴 사다리 밖 채도 배경 금지 (블루/이벤트 3색/시맨틱만 채도 허용).

---

## 3. 타이포그래피

### 3.1 폰트 사이즈 토큰 (정수 px, 6단계 + 디스플레이)
| 토큰 | 값 | 대표 용도 |
|---|---|---|
| `--fs-cap` | `12px` | 캡션·칩·메타·탭 라벨·섹션 라벨·힌트 |
| `--fs-sm` | `13px` | 보조 메타·hero-kicker·서브텍스트 |
| `--fs-base` | `15px` | 본문 기본·리스트 이름·세그먼트 |
| `--fs-md` | `17px` | 강조 본문·타일 제목·입력값·주 CTA 글자 |
| `--fs-lg` | `20px` | 앱바 타이틀·hero-title·시트 h2·스텝퍼 값 |
| `--fs-page` | `28px` | 페이지 제목(`.page-title`/`.phead h1`/`.auth-title`)·`.dl-row.big` |
| `--fs-display` | `40px` | 카운터 대형 숫자(`.counter-num`) |

### 3.2 웨이트 (3역할만)
`--fw-base:400`(본문·메타) / `--fw-med:500`(라벨·이름·칩·활성) / `--fw-bold:700`(제목·수치·주 버튼).

### 3.3 자간
- `--ls-none:0` — **한글/CJK는 항상 0, 음수 금지.**
- `--ls-num:-.02em` — **숫자에만.** `.mono`(JetBrains Mono + tabular) 및 대형 숫자에 적용.
- `.num` = `tabular-nums lining-nums`(자간 무조정). `.code-wide` = `.18em`. `.brandmark` = `.05em`.

---

## 4. 헤더 4패턴

시트(bottom sheet)는 자기 헤더 없이 **뒤 화면을 그대로 베이스로 깔고** 위에 뜬다.

### ① 위치 스코프형 (작업 홈 · 재고 홈)
`.titlesel` 버튼 안에 `.hero-kicker`(fs-sm·mute·말줄임)=**상위 위치** + `.hero-title`(fs-lg·bold)=**현재 노드**+`˅` 쉐브런. 노드명은 `.ht`로 감싸 min-width:0+말줄임. **리더기 칩(`리더기 H103`)은 작업 홈에서만** — 재고 홈엔 없다.

### ② 단순형 (목록·상세·탭 루트)
`.phead h1`(fs-page·bold) 또는 `.page-title`. 서브페이지는 `.phead.back`(`.pback` + 제목). `stock.html`은 `.phead` 안에 `.titlesel`을 넣어 스코프 전환을 겸한다.

### ③ 작업 중 (동사 실행 화면)
`.appbar` = `.back` + `.appbar-title`(동사, fs-lg·bold·말줄임) + `.loc-chip`(우측). `.loc-chip` = 핀 SVG + `.lt`(위치·구역, max-width 56%·말줄임) — 작업이 어느 위치에 쌓이는지 항상 보인다. 리더기 상태는 여기 아니라 본문의 `.scan-chip`(`● H103 · 스캔 중`).

### ④ 결과 / 인증 (무헤더 · auth-head)
결과 화면(`work-done`·`login-pending`)은 헤더 없이 중앙 히어로. 인증은 `.auth-head`: `.auth-back`(2단계부터) + `.brandmark`(SUPERFID) + `.auth-title` + `.auth-sub`.

### 시트 베이스
`.sheet`/`.scrim`이 뜨는 순간에도 **뒤 원 화면이 그대로 베이스**로 남는다. 시트 2단계는 `.sheet-head`(‹ 뒤로 + h2 + 우측 서브)로 드릴인. 풀스크린 전환 아님 (§7).

---

## 5. 컴포넌트 인벤토리

클래스명 기준, 전부 `design-system.css` 정의. 각 항목 = 용도 + 핵심 수치.

### 칩 / 토글
- **`.chip`** — 상태/필터 칩. h32·r999·`--fill`·fs-cap·med. 하위: `.dot`(7×7 green), `b`(강조), `.chip.count`(h22·tint/brand 카운트), `.chip.ghost`(사유 선택 등).
- **`.segmented`** — 모드/범위 토글. 트랙 `--fill`·r14·p4. 버튼 h46(`.signal` 변형 44), 활성 `.on` = `--surface`+`--brand` 글자+중립 그림자.

### 카운터
- **`.counter`** — 대형 카운트 블록: `.scan-chip`(`.d` 브랜드 도트 + mono 리더기명) → `.counter-num`(40px·bold·tabular) → `.counter-sub`(fs-sm·mute).
- **`.counter.compact`** — 카운트를 28px로 축소. **`.counter-sub.lg`**(fs-base·ink-sub·위 간격)/**`.dim`**(6px 간격) — 보조 라인 위계.

### 리스트 로우
- **`.list-row`** — 기본 행(p 10px 0 + 상단 헤어라인). `.row-av`(40×40 이니셜/듀오톤) + `.row-body`(flex:1·min-width:0) + `.row-name`(fs-base·med·**2줄 클램프**) + `.row-meta`(fs-sm·mute·**말줄임**) + `.row-qty`(**flex:0 0 auto·nowrap** — 수량은 온전히) + `.row-status`/`.row-flag`(amber) + `.mchip`(수동 뱃지) + `.row-x`(48×48 삭제 히트영역). `.warn` 변형 = amber 아바타.
- **`.loc-row`** — 위치/구역 행: 46×46 `.pin`(중립) + `.lb`(`.ln` fs-md / `.lh` fs-sm, 말줄임) + `.ck`(브랜드 체크). `.list-row.setting` = `.row-label`+`.row-value`.

### 카드류
- **`.pick-card`** — 선택된 SKU 카드: `.row-av` + `.pick-body`(`.pick-nm` bold·2줄 클램프 / `.pick-mt` 말줄임) + **`.pick-change`**(38×38 원형 아이콘 버튼, swap 글리프 = 상품 바꾸기).
- **`.adjust-card`** — 조정/요약 카드(`--fill-2`·r18·p18): `.ac-head`+`.ac-set`(현재 재고 + `.stepper`).
- **`.dl-row`** — 정의 리스트 행(조사 확정 요약): 좌 `.k`(fs-base·ink-sub) / 우 `.v`(fs-md·bold·nowrap) + 헤어라인. **`.dl-row.big`** = 대표 수치(fs-page).
- **`.req-card`** — 승인 카드(`--fill-2`): `.req-info`(이름 말줄임·역할 2줄 클램프·메타 말줄임) + `.req-btns` — **`.reject` = 흰 배경+`--line` 보더**, `.approve` = 브랜드(flex 1.25).
- **`.acct-card`** — 계정 카드: `.ai` 세로 스택(`.an` bold / `.am` mute, 둘 다 말줄임). 아바타 없음.
- **`.info-card`** — 안내 카드: 44×44 `.ic`(tint/brand) + `.tt`/`.ts`(block 스택).
- **`.queue-banner`** — 업로드 대기 배너(`--fill-2`·r18): `.qb-dot`(amber) + `.qb-t`(말줄임) + `›`. 조건부 노출.

### 액션 / 내비
- **`.action-tile`**(`.action-grid` 2열) — 6동사 타일: `--tile`·r20·min-h 114. 44×44 `.medallion`(이벤트색) + `.tile-title`(fs-md) + `.tile-desc`(fs-cap).
- **`.dock`+`.dtab`** — 플로팅 탭바: h66·r28·중립 그림자. 활성 `.on` = `--tint` 필 + `--brand`.
- **`.btn`** — h56·r999·fs-md·bold. `.ghost`=flex:1·`--fill` / `.primary`=flex:1.8·`--brand`(글로우 없음) / **`.block`=width:100%·flex:0 0 auto** (세로 스택에서 가로용 flex 비율이 높이를 뭉개지 않도록 고정) / `.disabled`=`--gray-200`+mute·클릭 불가.
- **`.fbtns`**(flex·gap10) / **`.footer`+`.saved`**(자동 저장 안심 텍스트) / **`.stepper`**(48×48 ± + `.val` tabular).

### 시트 / 오버레이
- **`.sheet`**(r24 상단·큰 중립 그림자·z4) + **`.sheet-handle`**(40×5) + **`.sheet-head`**(‹ `.sheet-back` + h2 + 우측 `.sheet-sub`) — 2단계 드릴인 그릇. **`.scrim`**(rgba(22,23,26,.42)·z3). `.mg` = 시트 위 제스처 바.

### 검색 / 입력
- **`.search`** — h50·r14·`--fill`: 돋보기 + input/`.q`(min-width:0·말줄임) + `.scan-btn`(34×34 바코드).
- **`.field`/`.fbox`/`.fval`** — 인증 입력: h56·r14, `.focus`=흰 배경+브랜드 보더+3px tint 링, `.fval` 말줄임(이메일 장문 대응). OTP `.d` 6칸 + `.cursor`.
- **`.cam-frame`** — 폰 카메라 뷰파인더(직접 추가 2단계·조정 바코드 세기). 색·구조=CSS SSOT(#111114 배경+스캔 라인), 높이만 화면 로컬(200/170).

### 기타
- **`.medallion`** — 원형 아이콘 담개(이벤트색은 `.event-*`가 변수로). **`.gesture`**(홈 인디케이터, 스캔 화면은 `.solid`). **`.statusbar`**(34px). **`.done .stat .s`** — 완료 지표 칸: `flex:1 1 auto`·내용 기반 확장, `.sv` nowrap(**천단위 수치 대응**).

---

## 6. 긴 텍스트 정책 (말줄임 / 클램프)

한국어 상품명·위치명·이메일·역할이 아무리 길어도 360px에서 깨지지 않도록 클래스별 전략 고정 (crew audit 2026-07-11 하드닝).

| 전략 | 적용 클래스 |
|---|---|
| **2줄 클램프** | `.row-name`, `.pick-nm`, `.ac-nm`, `.req-role` |
| **1줄 말줄임** | `.row-meta`, `.hero-kicker`, `.hero-title .ht`, `.appbar-title`, `.loc-chip .lt`, `.loc-row .ln`·`.lh`, `.pick-mt`, `.ac-mt`, `.req-nm`·`.req-meta`, `.acct-card .an`·`.am`, `.rdr-row .rn`·`.rm`, `.stock-location`, `.search .q`, `.queue-banner .qb-t`, `.signal-label .h`, `.row-label`, `.fval` |
| **말줄임 금지 · 칸 확장** | `.row-qty`, `.row-value`, `.signal-label .l`, `.done .stat .sv`, `.dl-row .v` |

- **숫자는 절대 말줄임하지 않는다.** 수량/값은 `flex:0 0 auto`+nowrap로 온전히 — 대신 이름 칸(flex:1·min-width:0)이 줄어든다.
- **flex min-width:0 체인 함정**: flex 자식 기본값은 `min-width:auto`라 말줄임이 안 먹고 부모를 밀어낸다. 말줄임 대상의 **모든 flex 조상**(`.row-body`·`.pick-body`·`.loc-row .lb`·`.acct-card .ai`·`.titlesel` 등)에 `min-width:0` 필수. 텍스트가 안 잘리면 조상 누락부터 의심.
- flex 컨테이너 안 **bare 텍스트 노드는 ellipsis가 안 먹는다** — 반드시 span으로 감싼다(`.ht`, `.lt`가 그 예).

---

## 7. 시트 2단계 드릴인 문법

컨텍스트 선택은 **풀스크린 전환이 아니라 한 bottom sheet 안 2단계 드릴인**. 뒤 작업 화면(카운터·저장통)은 `.scrim` 뒤에 살아있다.

- **위치 → 구역**: 1단계 위치 선택 → 같은 시트가 기본 구역을 포함한 구역 리스트로 전환(`.sheet-head` ‹ 뒤로). 작업은 구역을 명시적으로 선택하고, 재고는 상위 위치 합산도 선택할 수 있다. 재고 2단계는 행에 구역별 수량 표시(소계 겸함).
- **직접 추가 → 카메라**: 검색/수량 시트 → 스캔 아이콘 → 같은 시트 2단계(뷰파인더). 대기(미인식·담기 비활성)/인식(결과 카드) 2상태.
- **금지**: 이 흐름을 새 페이지로 밀어내지 말 것 — 누적 중인 작업이 뒤에 유지돼야 하므로 오버레이여야 한다.

---

## 8. 아이콘

- **라인 SVG only.** stroke 1.8~2.2(24px 기준), round cap/join. 이모지 금지.
- 24px 기준(dock·액션), 인라인 소형 14~16px, 히어로는 44px 담개 안.
- **듀오톤 색은 CSS로만**: `.mf/.mi/.mis`·`.if/.ii/.iis/.iw` 헬퍼로 fill/stroke — SVG 속성 색 하드코딩 금지.
- **상품 바꾸기 = swap 글리프**(좌우 교차 화살표), 38×38 원형 버튼.
