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 {