# task-303.1: 렌더러 종합 피드백 7건 개선 (풀미팅 + 구현)

## 개요
제이회장님의 실제 테스트 후 종합 피드백 7건을 적용한다.
**반드시 풀 미팅(팀원 전원) 진행 후 구현.** 시행착오 없이 한 번에 완성할 것.

## 참고 이미지
테스트 결과 이미지 위치:
- NavyGold: `/home/jay/projects/ThreadAuto/output/cardnews_20260306_121953_*.png` (6장)
- PurplePink: `/home/jay/projects/ThreadAuto/output/cardnews_20260306_121954_*.png` (6장)
- BlackRed: `/home/jay/projects/ThreadAuto/output/cardnews_20260306_121955_*.png` (6장)

특히 문제가 보이는 슬라이드:
- PurplePink detail (03번): TIP 블록 겹침, 제목 "커리/어를" 줄바꿈, ㄴ과 서울대보험쌤 겹침
- BlackRed cover (00번): "어떻/게" 줄바꿈
- NavyGold card_list (01번): 동그라미-제목 align, 들여쓰기

## 피드백 항목 (7건)

### FB-1. 제목 줄바꿈 로직 개선 (커버 + 블록 제목 공통)
- **문제**: wrap_text()가 단순 폭 기반이라 "어떻/게", "커리/어를" 같이 글자 중간에서 잘림
- **요구**: 한글 단어 단위로 줄바꿈. 최소한 2글자짜리가 혼자 다음 줄로 떨어지지 않게.
- **적용 대상**:
  - 커버 타이틀 (fit_font_size + wrap_text)
  - card_list 블록 제목 (72pt Bold)
  - detail 블록 제목 (72pt Bold)
- **구현 방향**:
  - wrap_text()에 한글 단어 경계 인식 추가: 조사/어미 포함 최소 단위 유지
  - 공백 기준 단어 분리 → 단어가 max_width를 초과하면 그때만 글자 단위 분리
  - 커버 타이틀은 `\n` 줄바꿈이 콘텐츠에 포함되어 있을 수 있으니 이것도 존중

### FB-2. TIP 블록 겹침 방지
- **문제**: detail 슬라이드에서 인포박스 3개 + TIP 블록이 캔버스를 초과하면 TIP이 겹쳐 보임
- **요구**: 여백 부족 시 대응 로직
- **구현 방향** (우선순위):
  1. TIP 블록 렌더 전 safe_bottom 체크 → 남은 높이 부족하면 **TIP 생략**
  2. 남은 높이가 TIP 최소높이보다 작으면 생략, 충분하면 렌더링
  3. TIP 텍스트가 길면 1줄로 축약 + "..." 처리

### FB-3. 좌하단 "서울대보험쌤" 글자와 ㄴ(L-브라켓) 장식 겹침 해결
- **문제**: `_draw_corner_decoration()` ㄴ모양과 `_draw_watermark()` 텍스트가 좌하단에서 겹침
- **구현 방향**:
  - 워터마크는 우하단 고정 (현재 상태 유지)
  - ㄴ 코너 장식(좌하단)의 위치를 워터마크와 겹치지 않게 조정
  - 또는: 좌하단 ㄴ 장식을 워터마크 위쪽으로 이동

### FB-4. 동그라미 숫자 첫줄 높이 align
- **문제**: 동그라미 ①②③이 제목 텍스트 블록의 세로중앙에 배치되어 있어서, 제목이 2줄 이상일 때 첫 줄과 높이가 안 맞음
- **요구**: 동그라미 숫자를 **제목 첫 줄의 세로 중심**에 align
- **구현**: `_draw_circle_badge()`의 cy 좌표를 제목 첫 줄 기준으로 계산
  - `cy = title_first_line_y + title_line_height // 2`
  - 현재처럼 전체 제목 높이 중간이 아님

### FB-5. 큰제목 아래 subtitle 들여쓰기
- **문제**: subtitle이 margin부터 시작하여 큰제목과 왼쪽 align이 안 맞음
- **요구**: subtitle 시작 x좌표를 큰제목 텍스트 시작점과 동일하게 맞추기
- **구현**: 동그라미 뱃지가 있으면 `subtitle_x = badge_cx + badge_r + 간격` (제목과 같은 x)
  - 동그라미가 없는 슬라이드(cover 등)는 기존 유지

### FB-6. 박스 내 description 들여쓰기
- **문제**: 카드 내부에서 title과 description이 같은 왼쪽 정렬이라 시각적 위계 구분 약함
- **요구**: description을 title보다 오른쪽으로 들여쓰기 (블록 제목 글자크기 절반 수준, 약 24~36px)
- **적용 대상**: card_list 카드 내부, detail 인포박스 내부
- **구현**: description 렌더링 시 `desc_x = title_x + indent_offset` (indent_offset ≈ 24~36px)
  - wrap_text의 max_width도 indent만큼 줄여서 오른쪽 잘림 방지

### FB-7. 캔버스 오버플로우 강화
- **FB-3(task-300.1)에서 safe_bottom 추가했지만 여전히 부족한 케이스 존재**
- **강화 포인트**:
  - card_list: 아이템이 safe_bottom을 넘으면 마지막 아이템 렌더링 중단
  - detail: 인포박스 + TIP 합산 높이를 사전 계산, 초과 시 인포박스 개수 제한
  - 모든 슬라이드: 최종 crop 전 경계 침범 여부 로그 출력 (디버그용)

## 파일 범위
- `renderer/cardnews.py` — 메인 수정
- `renderer/engine.py` — wrap_text() 줄바꿈 로직 개선
- `renderer/themes.py` — 필요시 상수 조정

## 진행 방법
1. **풀 미팅** (불칸/이리스/아테나/아르고스 전원)
   - 7건 각각 구현 방안 토론, 특히 FB-1(줄바꿈 로직)은 한글 특성 고려 필요
   - 미팅 기록: `memory/meetings/2026-03-06-renderer-feedback-v4.md`
2. **구현**: 미팅 합의대로 코딩
3. **테스트**:
   - 5개 테마 전부 파이프라인 테스트
   - 긴 제목 엣지케이스 테스트 (20자 이상 제목)
   - 인포박스 3개 + 긴 TIP 텍스트 엣지케이스
   - 오버플로우 엣지케이스 (아이템 4개 이상)
4. **샘플 이미지**: `output/feedback_v4/` 하위 저장
5. **보고서**: `memory/reports/task-303.1.md`

## 테스트용 콘텐츠
기존 테스트 콘텐츠 경로: `/tmp/test_pipeline_v3.json`
이 콘텐츠로 렌더링하면 위 7건 피드백 대부분을 재현할 수 있음.

## 완료 기준
- [ ] 한글 단어 단위 줄바꿈 동작 (글자 중간에서 안 잘림)
- [ ] TIP 블록 겹침 없음 (여백 부족 시 생략)
- [ ] 서울대보험쌤 글자와 ㄴ 장식 겹침 없음
- [ ] 동그라미 숫자가 제목 첫 줄과 높이 align
- [ ] subtitle이 큰제목 텍스트와 왼쪽 align
- [ ] description이 title보다 들여쓰기됨
- [ ] 캔버스 오버플로우 없음 (모든 엣지케이스)
- [ ] 5개 테마 정상 렌더링
- [ ] 기존 테스트 PASS

## task-timer
- task_id: task-303.1
- 완료 시: `python3 /home/jay/workspace/memory/task-timer.py end task-303.1`
