From 14c4b82155e6e6eb8a6a26c283db8742364e43cd Mon Sep 17 00:00:00 2001 From: Haewon Kam Date: Fri, 18 Sep 2026 16:56:52 +0900 Subject: [PATCH] =?UTF-8?q?refactor(design):=20=EC=9A=94=EC=B2=AD=EB=AC=B8?= =?UTF-8?q?=EA=B3=BC=20=EC=84=A4=EB=AA=85=EB=AC=B8=EC=9D=84=20=ED=85=8D?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=97=AD=ED=95=A0=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B0=80=EB=A5=B8=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "한 장씩 봐 주세요" 같은 요청문이 읽고 넘어가는 설명문과 같은 무게로 놓여 있어 지나치기 쉬웠다. 역할별 토큰과 클래스를 두고 화면에 적용한다. .ui-ask 요청문. 사람이 무엇을 해야 하는지 말하는 문장 (17px·600·인디고) .ui-ask-block 문단으로 서는 요청문. 왼쪽 규칙선으로 설명과 구분한다 .ui-body 설명 본문 (16px·slate-600) .ui-note 보조·출처 (14px·slate-400) 크기는 기존 화면을 세어 맞췄다. text-base 167회·text-sm 58회가 지배적이라 body 를 16px, note 를 14px 로 두면 치환해도 크기가 변하지 않고 역할과 색만 정리된다. 한글 줄바꿈: word-break keep-all 로 어절을 지키고, 긴 URL·영문 토큰만 overflow-wrap anywhere 로 자른다. text-wrap 으로 마지막 줄에 한 어절만 남는 것을 줄이고, 62ch 로 줄 길이를 묶는다. 제목에도 keep-all 과 balance 를 건다. 다크 섹션은 .on-dark 로 값을 뒤집고, 그 안의 흰 카드는 .on-light 로 되돌린다. 이걸 두지 않으면 흰 글씨가 흰 배경에 얹혀 보이지 않는다(디자인 시스템 기록된 실수). 사진 확인 화면의 썸네일 줄이 누를 수 있는 것으로 안 읽혀 같이 고친다. 72px 카드, 호버 반응, 순번 배지, 현재 위치 표시, 안 정한 것 아래 띠, 범례, 이전·다음 이동을 둔다. 상태가 안 보이는 것이 크기보다 큰 문제였다. Co-Authored-By: Claude Opus 5 (1M context) --- src/components/discovery/AbmrLoop.tsx | 6 +- src/components/discovery/AeoGeoV2Panel.tsx | 20 +-- src/components/discovery/AiAnswerMock.tsx | 2 +- .../discovery/ClinicInputsPanel.tsx | 26 ++-- src/components/discovery/DiscoveryCta.tsx | 4 +- .../discovery/DiscoveryLeadModal.tsx | 12 +- src/components/discovery/ImageReviewPanel.tsx | 138 +++++++++++++----- src/components/discovery/SampleReport.tsx | 4 +- src/components/discovery/WhyNow.tsx | 2 +- src/components/report/ui/SectionWrapper.tsx | 2 +- src/index.css | 89 ++++++++++- src/pages/ClinicProfilePage.tsx | 14 +- src/pages/DataValidationPage.tsx | 12 +- src/pages/DistributionPage.tsx | 2 +- src/pages/ImageReviewPage.tsx | 9 +- src/pages/PerformancePage.tsx | 18 +-- src/pages/PricingPage.tsx | 4 +- src/pages/SupportersBuildPage.tsx | 6 +- 18 files changed, 264 insertions(+), 106 deletions(-) diff --git a/src/components/discovery/AbmrLoop.tsx b/src/components/discovery/AbmrLoop.tsx index 48e7602..cc17c31 100644 --- a/src/components/discovery/AbmrLoop.tsx +++ b/src/components/discovery/AbmrLoop.tsx @@ -41,7 +41,7 @@ export default function AbmrLoop({ axes }: AbmrLoopProps) { whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.6, delay: 0.1 }} - className="relative overflow-hidden bg-[#0A1128] rounded-2xl px-8 py-7 flex flex-col items-center text-left" + className="on-dark relative overflow-hidden bg-[#0A1128] rounded-2xl px-8 py-7 flex flex-col items-center text-left" > {/* Background glow */}
@@ -65,7 +65,7 @@ export default function AbmrLoop({ axes }: AbmrLoopProps) { {/* Center orb */} -
+
ABMR @@ -77,7 +77,7 @@ export default function AbmrLoop({ axes }: AbmrLoopProps) { {/* Nodes */} {NODES.map((node) => (
-
+
{node.letter}
{node.label} diff --git a/src/components/discovery/AeoGeoV2Panel.tsx b/src/components/discovery/AeoGeoV2Panel.tsx index b5d34da..f8d3a18 100644 --- a/src/components/discovery/AeoGeoV2Panel.tsx +++ b/src/components/discovery/AeoGeoV2Panel.tsx @@ -16,14 +16,14 @@ function ItemRow({ it }: { it: ItemScoreV2; key?: string }) { return (
- {it.item.id} + {it.item.id}

{it.item.name}

-

{it.item.weight}점 · {METHOD_LABEL[it.item.method]}

+

{it.item.weight}점 · {METHOD_LABEL[it.item.method]}

-

{it.item.question}

- {it.evidence &&

{it.evidence}

} -

+

{it.item.question}

+ {it.evidence &&

{it.evidence}

} +

{BASIS_LABEL[it.basis]} {it.signals.length > 0 && ` · ${it.signals.map((s) => `${s.criterionId}=${s.level === 'unverified' ? '미검증' : s.level}`).join(' · ')}`}

@@ -51,7 +51,7 @@ function AxisCard({ ax }: { ax: AxisScoreV2 }) {
-

검증 {ax.verifiedCount}/{ax.items.length} · {ax.earned} / {ax.possible}점

+

검증 {ax.verifiedCount}/{ax.items.length} · {ax.earned} / {ax.possible}점

{ax.cappedBy.length > 0 && (

게이트 상한 {Math.min(...ax.cappedBy.map((g) => g.gate.cap))} (원점수 {ax.rawScore})

)} @@ -60,7 +60,7 @@ function AxisCard({ ax }: { ax: AxisScoreV2 }) {
-

{ax.axis.description}

+

{ax.axis.description}

{ax.items.map((it) => )}
@@ -81,8 +81,8 @@ export function AeoGeoV2Panel({ rubric, score }: { rubric: RubricV2; score: Over

{ax.axis.code} · {ax.axis.name}

-

{ax.axis.question}

-

+

{ax.axis.question}

+

등급 {ax.grade} · 검증 {ax.verifiedCount}/{ax.items.length} {ax.cappedBy.length > 0 && ` · 게이트 상한 적용 (원점수 ${ax.rawScore})`}

@@ -95,7 +95,7 @@ export function AeoGeoV2Panel({ rubric, score }: { rubric: RubricV2; score: Over

게이트 (점수가 아니라 상한)

    {score.gates.map((g) => ( -
  • +
  • {g.gate.id} {g.gate.name} · {g.passed ? '통과' : `실패 (${g.failedBy.join(', ')}) → 상한 ${g.gate.cap}`} {g.gate.reason}
  • diff --git a/src/components/discovery/AiAnswerMock.tsx b/src/components/discovery/AiAnswerMock.tsx index 9be38ab..a61406d 100644 --- a/src/components/discovery/AiAnswerMock.tsx +++ b/src/components/discovery/AiAnswerMock.tsx @@ -38,7 +38,7 @@ export default function AiAnswerMock({ clinicName, criteriaCount }: AiAnswerMock - + 강남에서 안전하게 가슴성형 상담받을 수 있는 병원 추천해줘
diff --git a/src/components/discovery/ClinicInputsPanel.tsx b/src/components/discovery/ClinicInputsPanel.tsx index b3b276c..cc7ad26 100644 --- a/src/components/discovery/ClinicInputsPanel.tsx +++ b/src/components/discovery/ClinicInputsPanel.tsx @@ -97,8 +97,12 @@ export function ClinicInputsPanel({ clinicId }: { clinicId: string }) {
SUPPORTERS BUILD · 병원 확인 항목

서포터즈 사이트 미리보기와 병원이 확인해 주실 것

-

- 병원 홈페이지 공개 자료만으로 만든 초안입니다. 아래 항목은 자료에 없어 병원만 답할 수 있는 값이며, 입력 전까지는 사이트에 "확인 대기"로 표시됩니다. 의학 검토와 게시 승인은 병원이 확정합니다. +

+ 병원 홈페이지 공개 자료만으로 만든 초안입니다.{' '} + 입력 전까지는 사이트에 "확인 대기"로 표시되고, 의학 검토와 게시 승인은 병원이 확정합니다. +

+

+ 아래 항목은 공개 자료에 없어 병원만 답할 수 있는 값입니다. 채워 주세요.

{/* 빌드 상태 */} @@ -108,9 +112,9 @@ export function ClinicInputsPanel({ clinicId }: { clinicId: string }) { {build && (
-

상태

-

{STATUS_LABEL[build.status] ?? build.status}{build.phase ? 단계 {build.phase} : null}

-

갱신 {build.updated_at.slice(0, 16).replace('T', ' ')} · 글 {posts.length}편{typeof build.report?.totalCostUsd === 'number' ? ` · 생성 비용 $${build.report.totalCostUsd}` : ''}

+

상태

+

{STATUS_LABEL[build.status] ?? build.status}{build.phase ? 단계 {build.phase} : null}

+

갱신 {build.updated_at.slice(0, 16).replace('T', ' ')} · 글 {posts.length}편{typeof build.report?.totalCostUsd === 'number' ? ` · 생성 비용 $${build.report.totalCostUsd}` : ''}

{build.preview_url && ( 미리보기 열기 (noindex) @@ -135,7 +139,7 @@ export function ClinicInputsPanel({ clinicId }: { clinicId: string }) {

{f.title}

{cur ? `입력됨 ${String(current(f.key)?.created_at ?? '').slice(0, 10)}` : '확인 대기'}
-

{f.hint}

+

{f.hint}

{f.inputs.map((inp) => { const value = draft[inp.name] ?? (cur ? String(Array.isArray(cur[inp.name]) ? (cur[inp.name] as string[]).join(', ') : cur[inp.name] ?? '') : ''); @@ -175,7 +179,7 @@ export function ClinicInputsPanel({ clinicId }: { clinicId: string }) { {build?.report?.channels && (

발견한 채널

-

홈페이지·웹검색·레지스트리에서 찾아 병원 것인지 확인한 채널입니다. "확인 필요"는 병원이 맞는지 알려 주셔야 사이트에 연결합니다.

+

홈페이지·웹검색·레지스트리에서 찾아 병원 것인지 확인한 채널입니다. "확인 필요"는 병원이 맞는지 알려 주셔야 사이트에 연결합니다.