From f456b8997a99392b782f3808dd947d8356fc207d Mon Sep 17 00:00:00 2001
From: Yun Chan
Date: Mon, 29 Jun 2026 00:01:40 +0900
Subject: [PATCH] =?UTF-8?q?=EC=84=B8=EC=85=98=20=EC=A7=84=ED=96=89=20?=
=?UTF-8?q?=ED=8C=A8=EB=84=90=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EB=B3=B4?=
=?UTF-8?q?=EA=B0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/web/src/pages/Session.tsx | 101 +++++++++--
apps/web/src/pages/session/session.css | 234 +++++++++++++++++++++++--
2 files changed, 307 insertions(+), 28 deletions(-)
diff --git a/apps/web/src/pages/Session.tsx b/apps/web/src/pages/Session.tsx
index 162d807..3479bf4 100644
--- a/apps/web/src/pages/Session.tsx
+++ b/apps/web/src/pages/Session.tsx
@@ -2041,6 +2041,26 @@ export default function Session() {
))}
+
+
+
+ 세션 진행
+
+
+
+ {elapsedLabel}
+ 회기 시간
+
+
+ {remainingLabel}
+ 권장 30분 기준
+
+
+ {turnCount}턴
+ 저장된 발화
+
+
+
{/* ── CENTER ── */}
@@ -2076,8 +2096,14 @@ export default function Session() {
/>
+
+
{clientName}
+
{stageClientLine}
+
+
- 지금: {stageStateText[avatarState]} · {avatarExpressionLabel}
+ 지금: {stageStateText[avatarState]}
+ {avatarExpressionLabel}
@@ -2270,6 +2296,38 @@ export default function Session() {
)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 음성 입력
+ {voiceInputStatus}
+
+
+ 응답 상태
+ {responseStatus}
+
+
+ 화면 모드
+
+ {feedbackMode === "ambient"
+ ? "상태 신호"
+ : feedbackMode === "coached"
+ ? "코칭"
+ : "몰입"}
+
+
+
+
최근 흐름
@@ -2397,19 +2455,34 @@ export default function Session() {
-
-
-
-
-
- 안전 점검 · {safety ?? "현재 감지된 위기 신호 없음"}
- {crisisResource ? (
-
- {crisisResource.title}
- {crisisResource.number}
-
- ) : null}
-
+
+
+
+
+
+ 안전 점검
+ {safetyStatusText}
+
+
+
+ 위기 신호
+ {safety ?? "감지 없음"}
+
+
+ 대응 상태
+ {safety ? "즉시 확인" : "모니터링"}
+
+
+ 긴급 자원
+ {crisisResource ? crisisResource.title : "대기"}
+
+
+ {crisisResource ? (
+
+ {crisisResource.title}
+ {crisisResource.number}
+
+ ) : null}
diff --git a/apps/web/src/pages/session/session.css b/apps/web/src/pages/session/session.css
index 108489d..e94fc78 100644
--- a/apps/web/src/pages/session/session.css
+++ b/apps/web/src/pages/session/session.css
@@ -544,6 +544,41 @@
color: var(--clay-deep);
}
+.sx-session-progress {
+ order: 3;
+ padding: 14px;
+ overflow: hidden;
+}
+.sx-session-progress__head {
+ margin-bottom: 12px;
+}
+.sx-session-progress__grid {
+ display: grid;
+ gap: 8px;
+}
+.sx-session-progress__grid span {
+ min-width: 0;
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) auto;
+ align-items: baseline;
+ gap: 10px;
+ padding: 8px 0;
+ border-top: 1px solid var(--paper-2);
+}
+.sx-session-progress__grid span:first-child {
+ border-top: none;
+}
+.sx-session-progress__grid b {
+ color: var(--text-strong);
+ font: 800 14px/1.2 var(--font-num);
+ font-variant-numeric: tabular-nums;
+}
+.sx-session-progress__grid small {
+ color: var(--text-muted);
+ font: 600 11.5px/1.2 var(--font-sans);
+ text-align: right;
+}
+
/* ── CENTER: 어두운 STAGE ── */
.sx-stage {
position: relative;
@@ -556,7 +591,7 @@
padding: 14px 16px;
display: grid;
grid-template-columns: minmax(136px, 184px) minmax(0, 1fr);
- grid-template-rows: auto minmax(0, 1fr);
+ grid-template-rows: auto minmax(0, 1fr) auto;
align-items: center;
column-gap: 18px;
row-gap: 8px;
@@ -630,7 +665,7 @@
.sx-orb-wrap {
position: relative;
grid-column: 1;
- grid-row: 1 / span 2;
+ grid-row: 1 / span 3;
margin: 0;
display: flex;
align-items: center;
@@ -680,7 +715,7 @@
.sx-stage__now {
grid-column: 2;
- grid-row: 2;
+ grid-row: 3;
font-size: 15px;
font-weight: 650;
color: var(--text-strong);
@@ -690,6 +725,40 @@
line-height: 1.45;
min-width: 0;
}
+.sx-stage__now small {
+ color: var(--text-muted);
+ font: 650 12px/1.2 var(--font-sans);
+}
+.sx-stage__client {
+ grid-column: 2;
+ grid-row: 2;
+ align-self: center;
+ min-width: 0;
+ display: grid;
+ gap: 8px;
+ position: relative;
+ z-index: 2;
+}
+.sx-stage__client-kicker {
+ width: fit-content;
+ max-width: 100%;
+ color: var(--clay-deep);
+ font-size: 15px;
+ font-weight: 850;
+ line-height: 1.1;
+}
+.sx-stage__client p {
+ max-width: 42ch;
+ margin: 0;
+ color: rgba(237, 247, 244, 0.9);
+ font-size: 16px;
+ font-weight: 650;
+ line-height: 1.58;
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-line-clamp: 4;
+ -webkit-box-orient: vertical;
+}
.sx-page--active .sx-stage .vg-avatar {
width: clamp(176px, 15vw, 238px) !important;
}
@@ -718,15 +787,16 @@
}
.sx-page--active .sx-stage {
- grid-template-columns: minmax(0, 1fr);
+ grid-template-columns: minmax(220px, 0.9fr) minmax(260px, 1fr);
grid-template-rows: auto minmax(0, 1fr) auto;
- justify-items: center;
+ justify-items: stretch;
align-items: center;
- padding: 18px 24px 16px;
+ padding: 20px 28px 18px;
+ column-gap: clamp(20px, 3vw, 46px);
}
.sx-page--active .sx-stage__top {
- grid-column: 1;
+ grid-column: 1 / -1;
grid-row: 1;
position: relative;
z-index: 2;
@@ -739,14 +809,20 @@
margin: 0;
}
+ .sx-page--active .sx-stage__client {
+ grid-column: 2;
+ grid-row: 2;
+ justify-self: start;
+ }
+
.sx-page--active .sx-stage__now {
- grid-column: 1;
+ grid-column: 1 / -1;
grid-row: 3;
position: relative;
right: auto;
bottom: auto;
place-self: center;
- width: min(100%, 520px);
+ width: min(100%, 600px);
max-width: calc(100% - 48px);
padding: 7px 10px;
border: 1px solid rgba(169, 215, 204, 0.15);
@@ -758,6 +834,10 @@
overflow: hidden;
text-overflow: ellipsis;
z-index: 2;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
}
.sx-page--active .sx-stage .vg-avatar {
@@ -1077,6 +1157,7 @@
}
.sx-turn-error {
margin-top: 10px;
+ display: flex;
}
/* 보내기 = 1차 액션. 입력창(틴트) 대비 또렷한 진한 accent + 미세 elevation.
비활성(입력 없음)은 표면 톤으로 낮춰 활성 상태와 위계를 분명히. */
@@ -1167,6 +1248,61 @@
.sx-feedback-ambient .sx-signal__one-when {
margin-left: 0;
}
+.sx-signal__wave {
+ height: 26px;
+ margin-top: 11px;
+ display: grid;
+ grid-template-columns: repeat(8, minmax(0, 1fr));
+ align-items: center;
+ gap: 4px;
+ color: var(--accent-bright);
+}
+.sx-signal__wave i {
+ display: block;
+ height: 7px;
+ border-radius: 999px;
+ background: currentColor;
+ opacity: 0.55;
+}
+.sx-signal__wave i:nth-child(2),
+.sx-signal__wave i:nth-child(7) {
+ height: 12px;
+}
+.sx-signal__wave i:nth-child(3),
+.sx-signal__wave i:nth-child(6) {
+ height: 18px;
+ opacity: 0.8;
+}
+.sx-signal__wave i:nth-child(4),
+.sx-signal__wave i:nth-child(5) {
+ height: 24px;
+ opacity: 0.95;
+}
+.sx-signal__rows {
+ display: grid;
+ gap: 0;
+ margin-top: 10px;
+}
+.sx-signal__rows span {
+ min-width: 0;
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) auto;
+ align-items: baseline;
+ gap: 10px;
+ padding: 8px 0;
+ border-top: 1px solid var(--paper-2);
+}
+.sx-signal__rows b {
+ color: var(--text-body);
+ font-size: 12.5px;
+ font-weight: 650;
+}
+.sx-signal__rows small {
+ color: var(--accent-deep);
+ font-size: 12px;
+ font-weight: 750;
+ text-align: right;
+}
/* 최근 흐름 시퀀스 (클릭 가능) */
.sx-signal__seq {
display: flex;
@@ -1215,8 +1351,7 @@
/* ambient(상태 신호) 모드에서도 본문 안내를 남겨 패널이 비어 보이지 않게 한다.
minimal 톤 유지를 위해 여백만 살짝 좁힌다. */
.sx-feedback-ambient .sx-signal__defer {
- margin-top: 10px;
- padding-top: 10px;
+ display: none;
}
.sx-coach-card {
display: grid;
@@ -1542,9 +1677,9 @@
/* ── RIGHT: 안전 점검 콜아웃 (warn, 빨강 아님) ── */
.sx-safety {
- display: flex;
+ display: grid;
gap: 10px;
- padding: 12px;
+ padding: 14px;
background: var(--warn-tint);
border: 1px solid color-mix(in srgb, var(--warn-solid) 24%, transparent);
border-radius: var(--radius);
@@ -1567,6 +1702,52 @@
.sx-safety--ok .sx-safety__text {
color: #9ed6ca;
}
+.sx-safety__head {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ min-width: 0;
+}
+.sx-safety__head .vg-kicker {
+ flex: 1;
+ min-width: 0;
+}
+.sx-safety__badge {
+ flex: none;
+ padding: 3px 8px;
+ border-radius: 999px;
+ background: rgba(237, 247, 244, 0.08);
+ color: currentColor;
+ font-size: 11px;
+ font-weight: 750;
+}
+.sx-safety__rows {
+ display: grid;
+ gap: 0;
+}
+.sx-safety__rows span {
+ min-width: 0;
+ display: grid;
+ grid-template-columns: minmax(0, 0.75fr) minmax(0, 1.25fr);
+ gap: 8px;
+ padding: 7px 0;
+ border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent);
+}
+.sx-safety__rows b {
+ color: currentColor;
+ font-size: 12px;
+ font-weight: 700;
+}
+.sx-safety__rows small {
+ min-width: 0;
+ color: var(--text-body);
+ font-size: 12px;
+ font-weight: 650;
+ text-align: right;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
.sx-safety__ico {
flex: none;
width: 17px;
@@ -2780,6 +2961,17 @@
font-size: 13px;
line-height: 1.35;
}
+ .sx-page--active .sx-stage__client {
+ gap: 5px;
+ }
+ .sx-page--active .sx-stage__client-kicker {
+ font-size: 13px;
+ }
+ .sx-page--active .sx-stage__client p {
+ font-size: 13px;
+ line-height: 1.45;
+ -webkit-line-clamp: 3;
+ }
.sx-page--active .sx-transcript__head {
margin-bottom: 8px;
}
@@ -2897,6 +3089,11 @@
grid-template-columns: minmax(88px, 104px) minmax(0, 1fr);
column-gap: 10px;
}
+ .sx-page--active .sx-stage__client p {
+ font-size: 12.5px;
+ line-height: 1.4;
+ -webkit-line-clamp: 2;
+ }
.sx-page--active .sx-orb {
inset: -5px;
}
@@ -3059,6 +3256,13 @@
padding: 0;
font-size: 0;
}
+ .sx-sessionbar .sx-sessionbar__back {
+ width: 34px;
+ min-width: 34px;
+ padding: 0;
+ overflow: hidden;
+ font-size: 0;
+ }
.sx-page--prestart .sx-head {
gap: var(--sp-3);
}
@@ -3197,9 +3401,11 @@
.sx-sessionbar {
grid-template-columns: auto minmax(0, 1fr) auto;
}
- .sx-sessionbar__back {
+ .sx-sessionbar .sx-sessionbar__back {
width: 34px;
+ min-width: 34px;
padding: 0;
+ overflow: hidden;
font-size: 0;
}
.sx-sessionbar__meta b {