diff --git a/.atp/work-session/20260630-175023/implementation/ownership.md b/.atp/work-session/20260630-175023/implementation/ownership.md
new file mode 100644
index 0000000..c02e4fa
--- /dev/null
+++ b/.atp/work-session/20260630-175023/implementation/ownership.md
@@ -0,0 +1,27 @@
+---
+phase: implementation
+agent: implementation-advisor
+agent_version: 1
+generated_at: 2026-06-30T17:50:23+09:00
+---
+
+# 파일 소유권 맵
+
+| 파일 | 담당 | 변경 유형 | 관련 fix | 의존 |
+|---|---|---|---|---|
+| src/main/webapp/WEB-INF/views/index.jsp | advisor 직접 | modify | #1 #3 #4 #13 | - |
+| src/main/webapp/css/bibimbap.css | advisor 직접 | modify | #2 #6 #7 #11 #12 | - |
+| src/main/webapp/WEB-INF/views/recruit-list.jsp | advisor 직접 | modify | #5 #8 #9 #10 | - |
+| src/main/webapp/WEB-INF/views/fragments/recruit-empty.jspf | (변경 없음) | none | #9 (이미 충족) | - |
+
+## planned_workers vs actual
+- planned_workers(code-writer): 3 (파일당 1)
+- actual_workers: 0 (advisor 직접)
+- 전환 근거: 편집 파일 3개 < 8 임계, 총 변경 추정 < 50줄, 전부 소규모 CSS/속성 조정으로
+ 병렬화 이득 없음 + JSP UTF-8 보존 사고 이력으로 advisor 직접 정밀 편집이 더 안전.
+- recruit-empty.jspf 는 이미 .btn-primary(골드) + .btn-ghost(보조) 구조라 #9 충족 → 무편집(인코딩 보존).
+
+## 충돌 방지 불변식
+- 각 파일은 단일 편집 주체(advisor)만 접근 → 충돌 없음.
+- 토큰 계열 분리: index.jsp/recruit-list.jsp 로컬 토큰(--accent/--text/--border 등),
+ bibimbap.css 는 --color-* 만. #2 .btn-ghost 는 bibimbap.css 소속 → var(--color-text) 정확.
diff --git a/.atp/work-session/20260630-175023/report.md b/.atp/work-session/20260630-175023/report.md
new file mode 100644
index 0000000..0efc5a6
--- /dev/null
+++ b/.atp/work-session/20260630-175023/report.md
@@ -0,0 +1,79 @@
+---
+schema_version: 2
+sid: 20260630-175023
+started_at: 2026-06-30T17:50:23
+user_request: |
+ /frontend-design 두 시각 버그 수정 (이전 작업서 미해결):
+ - Image #2 (메인 게임 허브): 게임 카드 썸네일 "비율" 문제
+ - Image #3 (팀원 모집 빈 상태): "가시성" 떨어지는 케이스
+Invocations: []
+Summary: ''
+Decisions: []
+user_signals:
+ positive: []
+ negative:
+ - quote: "이전 작업에서 안고쳐졌어"
+ structural: false
+ note: "직전 리디자인 세션이 두 케이스 미해결. 발원 단계 재검 필요(§2.6)."
+regression: ''
+graph_refresh: ''
+open_items: []
+verified_by_me: []
+needs_user_verification: []
+---
+
+# Advisor Invocation Decision Log
+# 각 advisor 호출/스킵 판단 즉시 1줄 append
+
+- advisor: requirements/design/implementation
+ decision: skip
+ rationale: '2건 모두 국소 CSS 수정(토큰 오용·종횡비 1값). 이슈2 원인 확정, 이슈1 결정축 단일. orchestrator 직접+plan게이트(§1 마이크로 예외, §5.0).'
+ checked_at: 2026-06-30T17:52
+- advisor: verification
+ decision: call(self)
+ rationale: 'CSS 변경 → 런타임 스모크 의무(직전 교훈). 다크모드 대비·카드 비율 육안 확인.'
+ checked_at: 2026-06-30T17:52
+
+- advisor: implementation
+ decision: call
+ rationale: '결정 후 범위=전체13건+카드4:3, 4개 파일(index.jsp/bibimbap.css/recruit-list.jsp/recruit-empty.jspf). 다중파일+일부 마크업변경(#4#9#10) → 파일소유권 분할 필요. 종합 산출 concrete_change 확정적.'
+ checked_at: 2026-06-30T18:00
+
+---
+
+## Summary
+사용자 지적 2건(이미지#2 비율 / 이미지#3 가시성, 직전 세션 미해결)을 다축 멀티에이전트 평가로 13건 결함으로 확장 → 카드 종횡비 4:3 + 전체 13건 적용. 런타임 스모크 라이트/다크 양 화면 PASS.
+
+## Invocations
+- cavecrew-investigator: 두 화면 JSP/CSS 위치 file:line 확정
+- Workflow(ui-multiaxis-eval, 6 agents): 관찰1 → 다축평가4(레이아웃비율·카드종횡비·대비가시성·타이포간격) → 종합1 → 13 fixes + 1 open_decision
+- implementation-advisor: 13건+4:3 구현(3파일, recruit-empty.jspf 무편집)
+- (self) verification: 정적 L1 + 런타임 L2 스모크
+
+## Decisions
+- 카드 종횡비 **4:3** (사용자 선택; 16:9/4:5유지 대안 제시)
+- 적용 범위 **전체 13건** (사용자 선택)
+- #4 픽셀 margin 대신 `.search-stack` 컬럼 wrapper (advisor 조정 — 버튼 텍스트 가변 대응 결정적)
+- #8 공용 클래스 대신 로컬 시각스펙 일치 (index/bibimbap 토큰계열 분리 제약 + font-mono 토큰 부재)
+
+## verified_by_me
+- L1 정적: index.jsp div 18/18·recruit 6/6 균형, scriptlet 균형, U+FFFD 0, stray taglib 0(§293 적신호 없음)
+- L2 런타임 스모크(PASS): bibimbap-app(mvn spring-boot:run) 재기동 → GET / + /recruit = 200 → 브라우저 육안 라이트+다크 양 화면.
+ - 이미지#2(비율): 검색바 풀폭 정렬(#1), 카드 4:3(#13 object-position) — 해소 확인
+ - 이미지#3(가시성): 필터 초기화 흰글자+보더 명확(#2, zoom 확정) — 해소 확인
+ - 부수: #6 정렬칩 보더·#7 정렬라벨·#8 eyebrow 통일·#9 빈상태 CTA 강등·#10 히어로폭·#11 패널패딩·푸터 비잘림 육안 확인
+
+## needs_user_verification
+- 로그인 상태 1회 스모크: 본 검증은 로그아웃 상태만. (a) 메인 '신규 게임 개시' 버튼 노출 시 #4 search-stack 우측끝선 정렬, (b) 모집글 ≥1건 시 #9 히어로 골드 CTA 유지.
+- 실게임 가로 썸네일 업로드 시 4:3 cover 크롭 인상 최종 확인(더미는 폴백 로고만 노출).
+
+## regression
+- 발원 단계: 직전 리디자인 세션(cf1e7ce 등)이 두 케이스 미해결. 본 세션이 다축 재검으로 표면화+수정. 토큰 오용(.btn-ghost on-accent) = 골드버튼 토큰을 고스트에 재사용한 설계 결함 → --color-text 로 정정.
+
+## graph_refresh
+partial-stale — 내 변경(src view/css)은 include/import/route 위상 0델타 = src fresh. partial 사유는 직전 세션들의 docs/changes 노드 2건 신규(pre-existing) + 직전 graphify 미반영(index.md "재생성 요청 중"이나 source_commit 360078a 고정). 내 세션 구조 무영향 → src 재생성 불요. docs 노드 backlog 는 open_items 로 이월(다음 구조변경 시 일괄 /graphify full).
+
+## open_items
+- [pre-existing] docs/graph 재생성 backlog: 직전 세션 docs/changes 노드 미반영 + source_commit stale(360078a→cf1e7ce). 다음 구조변경 작업 시 /graphify full + index.md frontmatter/Scopes 표 갱신. (본 세션 산출 아님)
+- [untracked, 타세션] .atp/work-session/{20260630-103443,105459,143405,160000,170024}/ + graphify-out/ : 직전 세션들 미커밋 잔여. 본 작업 단위 외 — 미관여.
+- [stale-log] 07:35Z JasperException(/error JSTL) = 내 재기동(09:19Z) 이전 옛 라인, errer.jsp 현재 clean, /error 현재 200. 회귀 아님.
diff --git a/src/main/webapp/WEB-INF/views/index.jsp b/src/main/webapp/WEB-INF/views/index.jsp
index a7deb98..4f6ef4c 100644
--- a/src/main/webapp/WEB-INF/views/index.jsp
+++ b/src/main/webapp/WEB-INF/views/index.jsp
@@ -171,6 +171,7 @@
}
.home-action-button {
flex-shrink: 0;
+ align-self: flex-start;
min-height: 3rem;
padding: 0 0.875rem 0 0.625rem;
border: 1px solid rgba(232, 165, 75, 0.32);
@@ -222,8 +223,15 @@
/* 검색 */
.search-section {
- width: min(100%, 48rem);
- margin: 0 auto 1.25rem;
+ width: 100%;
+ margin: 0 0 1.25rem;
+ }
+ /* 검색 폼 + 상세검색 패널을 한 컬럼으로 묶어 우측 끝선 정렬(#4) */
+ .search-stack {
+ flex: 1;
+ min-width: 0;
+ display: flex;
+ flex-direction: column;
}
.search-form {
flex: 1;
@@ -506,10 +514,10 @@
transform: scale(0.98);
}
- /* 카드 그리드: 모바일 2열 → 태블릿 3열 → 데스크톱 4~5열 */
+ /* 카드 그리드: 콘텐츠 적응형(소량 카드 좌측 쏠림/우측 거대공백 완화) */
.card-grid {
display: grid;
- grid-template-columns: repeat(2, minmax(0, 1fr));
+ grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
gap: 0.625rem;
justify-content: center;
}
@@ -520,20 +528,9 @@
}
@media (min-width: 640px) {
.card-grid {
- grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1rem;
}
}
- @media (min-width: 900px) {
- .card-grid {
- grid-template-columns: repeat(4, minmax(0, 1fr));
- }
- }
- @media (min-width: 1200px) {
- .card-grid {
- grid-template-columns: repeat(5, minmax(0, 1fr));
- }
- }
a.card {
display: flex;
@@ -560,11 +557,11 @@
outline: 2px solid var(--accent);
outline-offset: 2px;
}
- /* 가로:세로 = 4:5 (포스터/썸네일에 흔한 비율, 3:5보다 덜 길쭉해 모바일 그리드에 균형 있음) */
+ /* 가로:세로 = 4:3 (가로형 썸네일 — 카드 높이 축소로 그리드 균형·스캔성 개선) */
.card__media {
position: relative;
width: 100%;
- aspect-ratio: 4 / 5;
+ aspect-ratio: 4 / 3;
background: var(--card-media-2);
}
.card__index {
@@ -591,6 +588,7 @@
height: 100%;
display: block;
object-fit: cover;
+ object-position: center;
}
/* 이미지 없음: 로고만 중앙 */
.card__media-empty {
@@ -605,7 +603,7 @@
.card__logo-fallback {
width: min(52%, 7.5rem);
height: auto;
- max-height: 42%;
+ max-height: 50%;
object-fit: contain;
opacity: 0.88;
filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.12));
@@ -768,7 +766,11 @@
직접 만든 인디 게임을 올리고, 함께 즐기세요
유니티 개발자들이 만든 웹게임을 플레이하고 리뷰를 남길 수 있어요.
+<%
+ boolean advOpen = !searchKeyword.isBlank() || !searchCreator.isBlank() || !"latest".equals(searchSort) || !selectedTagSlugs.isEmpty();
+%>
+
+ <% if (loggedIn) { %>
+
+
+
+
+ 신규 게임 개시
+
+ <% } %>
+
<%-- 정렬 칩 --%>
diff --git a/src/main/webapp/WEB-INF/views/recruit-list.jsp b/src/main/webapp/WEB-INF/views/recruit-list.jsp
index 5ec0dc3..fddfee5 100644
--- a/src/main/webapp/WEB-INF/views/recruit-list.jsp
+++ b/src/main/webapp/WEB-INF/views/recruit-list.jsp
@@ -60,11 +60,17 @@
gap: 1rem;
margin-bottom: 1rem;
}
+ .recruit-hero__titles {
+ max-width: 40rem;
+ }
.recruit-hero__eyebrow {
margin: 0 0 0.35rem;
color: var(--accent);
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
font-size: 0.75rem;
- font-weight: 900;
+ font-weight: 600;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
}
.recruit-hero h1 {
margin: 0;
@@ -92,6 +98,13 @@
text-decoration: none;
white-space: nowrap;
}
+ /* 빈 상태(목록 0건)일 때 히어로 CTA 를 보조 스타일로 강등 — 화면당 골드 채움 CTA 1개(#9) */
+ .recruit-write--ghost {
+ background: transparent;
+ border: 1px solid var(--border);
+ color: var(--text);
+ font-weight: 700;
+ }
.recruit-toolbar {
margin-bottom: 1.25rem;
display: grid;
@@ -100,6 +113,7 @@
.recruit-search {
display: flex;
gap: 0.5rem;
+ max-width: 48rem;
}
.recruit-search input {
width: 100%;
@@ -248,12 +262,12 @@