버튼 행이 입자 밴드를 파고들었다. 1280x720 에서 34px, 무리 라벨과는 7px.
1440x900 에서만 여유가 있어(45px) 안 보이던 문제다.
원인은 두 값이 서로 다른 기준으로 움직인 것:
카피 상단 여백 19vh 화면 비율
카피 높이 351px 고정
밴드 시작 0.63×높이 화면 비율
카피만 px 고정이라 화면이 짧아지면 밴드가 카피를 덮는다.
0.19H + 351 > 0.63H → H < 798px 이면 전부 겹친다.
1280x720, 1366x768 같은 흔한 노트북 높이가 여기 들어간다.
pt-[19vh] 는 위치만 잡을 뿐 경계를 강제하지 못한다. 그래서:
- 카피 영역 높이를 밴드 시작선에 묶었다. 뷰포트와 무관하게 구조적으로 못 겹친다.
- BAND_TOP 을 export 해 캔버스와 카피가 같은 값을 쓴다. 라벨 좌표가 이미 쓰던 방식이다.
- 높이·밴드를 한 식에서 뽑는다. 따로 두면 어긋난다 — 밴드를 63vh 로 두고 높이만
키웠더니 짧은 화면에서 변수가 실제 밴드보다 위를 가리켰다.
- min-h 바닥 780px. 밴드 위 공간에 헤더(104)+카피(351)+여유(24)=479px 가 들어가려면
높이 760px 이 하한이라, 정렬만으로는 짧은 화면을 못 구한다. 살짝 스크롤될 뿐이다.
- pt-[104px] 를 md 이상에서도 유지. 빼면 가운데 정렬이 카피를 fixed 헤더 밑으로 민다.
검증(실측, 음수 = 밴드 밖):
1280x620 +20 → -30, 헤더 여유 +12, 라벨 75px
1280x720 +34 → -30, 헤더 여유 +12, 라벨 75px
1440x900 -45 → -68, 헤더 여유 +50, 라벨 122px
375x812 -57, 헤더 여유 +6
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
디자인 시스템이 색·활자만 소유하고 간격은 각 섹션 파일에 흩어져 있어,
같은 관계에 값이 여러 개 생겼다. 스크롤할 때 섹션마다 호흡이 달라지던 원인.
eyebrow → title 12/20px → 16px
title → description 16/20/32px → 20px (display 티어 32px)
머리 → 본문 48~96px 5종 → 56px / 80px(md)
컨트롤 → 본문 56/64px → 48px
리드 → CTA 56/48px → 48px
- SectionHeading 이 리듬을 소유하고 HEADING_GAP·CONTROL_GAP·CTA_GAP·
DISPLAY_LEAD_GAP 를 노출. 섹션 파일에서 mb-24 같은 값을 직접 쓰지 않는다.
- negotiation-demo·final-cta 가 Section/SectionHeading 을 우회해 머리를 직접
조판하고 있었다 — 아이브로우 간격이 이 둘만 20px 이던 원인. 프리미티브로 환원.
- SectionHeading 이 eyebrow 없이도 빈 span 을 렌더해 유령 여백이 생기던 버그 수정.
- descriptionClassName 의 text-[17px] 중복 선언 제거. lead 변형이 이미 갖고 있는
모바일 축소 단계(text-[16px] sm:text-[17px])를 지우고 있었다.
- reinforcement: text-balance 가 쉼표를 넘어 끊던 헤드라인을 <br /> 로 명시.
reinforcement 만 gap="none" 인데, 머리가 그리드 셀 안이라 마진이 상쇄되지 않아
items-center 정렬을 밀기 때문. 간격은 그리드 래퍼가 진다.
검증: tsc --noEmit 통과, 프로덕션 빌드 통과. DOM 실측으로 375/868/1440px
전 구간에서 머리→본문·eyebrow→title·컨트롤→본문 값 일치 확인.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
답답함의 원인은 가로 비율이 아니라 세로 간격이었다. 헤드라인 80px 에 대해
헤드라인↔서브 28px, 서브↔CTA 40px 는 너무 촘촘했다.
- 간격 확대: mt-7 → mt-11(44px), mt-10 → mt-14(56px).
- 헤드라인 80 → 74px. 글자 실폭이 뷰포트의 40% (레퍼런스 statworx 는 48%).
- 측정 주의사항을 주석에 남김: h1 은 블록이라 getBoundingClientRect 로 재면
컨테이너 폭(848px)이 나온다. Range 로 텍스트 노드를 재야 실제 글자 폭이다.
이걸 헷갈려 한 번 과교정(66px, 36%)했다가 되돌렸다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
히어로에 헤드라인·서브·CTA 2개·군집 밴드·순환 링이 다 들어가 세로 예산이 포화라
위를 벌리면 아래가 터지는 상태였다. 링을 옮겨 자리를 만든다.
- 순환 링을 강화학습 섹션으로. "협상할수록 좋아진다"를 말하는 자리라
루프가 의미상 속하는 곳이기도 하다. 텍스트 좌 / 링 우 2단 배치.
- OrbitRing 에 자체 시계 모드 추가 — progressRef·phase 를 안 주면 스스로 돈다.
덕분에 히어로 캔버스와 무관한 섹션에서도 단독으로 쓸 수 있다.
- 히어로 상단 여백 14vh → 19vh, 밴드를 하단 전체(0.63/0.30)로 확장.
- 군집 라벨 y 계산 버그 수정. 밴드 지역 좌표(0.5)를 화면 좌표로 착각해
밴드를 옮길 때마다 라벨이 엉뚱한 곳으로 갔다. 이제 행 수·행간에서
격자 상단을 실제로 계산해 투영한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 글리프 크기를 화면 폭에서 파생. 격자 간격은 dx × width 로 폭에 비례하는데
글리프가 CSS px 고정이라 375px 에서 셀(7.7px)보다 커져(22px) 서로 겹쳐 덩어리가 됐다.
- 좁은 화면(<640px)에서는 밴드를 링 뒤로 내리고 군집 라벨을 접는다.
모바일은 CTA 가 세로로 쌓여 세로 예산이 부족하고, 375px 에서 3군집을 나란히 두면
군집당 100px 남짓이라 어차피 판독이 안 된다. 의미는 순환 링이 담는다.
- 히어로 상단 여백을 vh 대신 모바일 고정값으로. 헤더는 고정 높이라
pt-[7vh](모바일 57px)로는 헤더(약 70px)를 피할 수 없어 헤드라인이 겹쳤다.
- 데스크톱 상단 여백 복원(14vh)과 밴드 재배치(0.575/0.155), 링 290px.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 군집 좌표를 투영 후 위치에서 역산하도록 변경.
sx = 0.5 + (x−0.5)·k 라 깊이마다 당겨지는 양이 다르고, 가장 깊은 협력사가
중앙으로 제일 많이 끌려와 구도가 왼쪽으로 쏠렸다. 이제 화면 19/50/81% 에
대칭으로 놓인다 — 라벨도 같은 값을 써서 어긋나지 않는다.
- 순환 링을 원근 타원에서 정원으로 교체(orbit-ring). 점선 궤도만 회전하고
마디·라벨은 고정이다. 눕힌 타원은 깊이는 생기지만 "닫힌 루프"의 완결감이 없다.
- 학습 단계 입자 궤도 제거. 화면을 가로지르는 큰 선이 순환 링과 의미가 겹치고
시선을 뺏었다. 순환은 링이 맡고 입자는 안쪽으로 흡수만 한다.
- Playfair Display self-host(latin 서브셋 39KB). 구글 폰트 CDN 제거 —
서드파티 요청이 LCP 를 흔들고 방문자 IP 가 외부로 나간다.
- 히어로 CTA "협상 시연 보기" → "직접 협상해 보기".
데모는 실제로 동작한다(앵커 이하 낙찰 · 카드 소모 역제안 · 소진 시 개찰 확인).
수동태 문구는 인터랙티브 기능을 영상처럼 보이게 해 전환을 깎는다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
레퍼런스(statworx·jitter·infinith) 실측값으로 디자인 시스템을 다시 잡고,
스크롤 재생형 콘솔을 사용자가 직접 협상하는 데모로 교체했다.
디자인 토큰
- 타이포: 굵기·크기·자간을 함께 조정(섹션 제목 44→64px/600→800/자간 -0.042em).
한글 행간은 1.07 — 라틴 기준 0.95 를 쓰면 네모틀이 꽉 차 줄이 닿는다.
- 모서리: 12가지로 흩어져 있던 값을 card 8px / control 4px / full 셋으로 수렴.
20~32px 짜리 뭉툭한 카드가 제네릭 SaaS 의 가장 강한 신호였다.
- 다크 무대 토큰 신설(stage/on-stage/counter) + 배경 그라데이션.
- primary-on-stage(#7C8CFF) 추가 — #0101F3 은 무대 배경 대비 2.0:1 로
WCAG 최소(4.5:1)의 절반도 안 돼 다크 위에서 읽히지 않았다.
- 영문 디스플레이 서체 Playfair Display self-host(latin 서브셋 39KB).
히어로
- 배경 캔버스가 실제 파이프라인을 그린다: 수집→분류→대조→산정→협상→학습.
분류 단계는 거래 품목(시트)·사용자·협력사로 갈라지고 라벨이 붙는다.
- z 좌표 + 원근 투영. 군집마다 z 평면을 하나씩 줘 격자는 온전한 채 깊이만 생긴다.
- 순환 링(정원, 점선 궤도 회전). 진행도는 ref 로 공유해 60fps 리렌더를 피한다.
- 카피에 진입 애니메이션을 걸지 않는다 — LCP 요소라 opacity:0 으로 시작하면
하이드레이션 전까지 첫 화면이 빈다.
협상 데모 (신규)
- 역할 선택(공급사/구매 담당자) → 품목·단가 제시 → 턴 협상 → 낙찰/개찰 → 상담 신청.
- 판정 규칙은 실제 엔진과 동일: 앵커링가 이하 낙찰, 협상 카드 3장, 소진 시 개찰.
- 로직은 lib/negotiation-sim.ts 순수 함수로 분리 — 나중에 agent 서비스 연동 시
컴포넌트를 건드리지 않는다.
카피 감사
- "봇" 21곳 → "에이전트"(로봇 아이콘 3개 포함). 대리인은 조달 실무의 정당한 역할이다.
- "악역은 봇이", "단가를 깎는 악역" 제거 — 협력사를 적으로 규정하는 프레임은
같은 페이지 FAQ(공급사 만족도 82%)와 모순이고, 동반성장 평가를 받는
대기업 구매팀 결재 라인에 올릴 수 없다.
- 번역투 최상급(초정밀·압도적·완벽히·최적의)과 데모 대화문 전면 재작성.
버그 수정
- 헤더가 흰 배경 위에 흰 글자 버튼을 그리던 문제. onStage 를 스크롤 수치로 계산해
하이드레이션 전 스크롤 복원 시 초기값이 굳었다 → IntersectionObserver 로 교체.
- 버튼 transition-all → transition-colors (variant 교체 시 배경 플리커).
- 폼 입력 14px → 16px. iOS 사파리는 16px 미만 입력에 포커스하면 화면을 확대해
모바일 폼 이탈을 만든다.
정리
- 대체된 히어로 3종·기존 협상 콘솔 삭제(약 760줄).
- 라벨 아이콘·알약 배지·blur(120px) 글로우 블롭 제거.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 채팅 링크로 바로 진입하면 세션이 협상생성(1)에 머물러 오프닝 메시지가 seed 되지 않던 문제:
chat init/messages 에서 participate 와 동일하게 협상중(2)으로 전이(마감 견적·마감시간 초과는 제외)
- 부가정보 저장이 1301 로 실패하던 문제: '협상완료' 요약은 chat_end=false 라 세션이 아직 협상중이므로,
마지막 말풍선이 summaryRSP/CM 이면 협상중 세션도 저장 허용
- 채팅 언마운트 시 messages 캐시도 제거 — staleTime:Infinity 라 빈 목록이 남아 재진입해도 빈 화면이던 문제
- 채팅 스크롤을 컨테이너 기준 scrollTo 로 변경(rAF 후 실행) — 요약·폼이 뒤늦게 레이아웃되면 중간에 멈추던 문제
- 모바일 채팅 상단 여백 제거(pt-[64px] 는 우측 협상절차 카드가 있는 lg 이상만)
- 노치 대응: viewport-fit=cover + safe-t/b/x 유틸 신설, 헤더·하단 액션 덱·드로어·랜딩 헤더에 적용, h-screen→100dvh