feat: 운영 안정성과 세션 음성 경험 개선

This commit is contained in:
Yun Chan 2026-07-31 00:13:08 +09:00
parent facc4ad2d9
commit c788343467
95 changed files with 8431 additions and 1785 deletions

View file

@ -83,6 +83,7 @@
background:var(--bg-surface-2);
}
.lh-tabs button{
position:relative;
flex:1 1 0;
min-width:0;
padding:9px 12px;
@ -94,8 +95,27 @@
font-weight:700;
cursor:pointer;
}
/* D6( 구분 강화): 비활성 탭이 배경과 같아 "여러 개 중 하나" 읽혔다.
비활성 사이에만 세로 구분선을 넣는다. 활성 탭은 자체 배경/테두리로
이미 구분되므로 활성 탭에 붙는 구분선은 숨겨 이중 경계선을 막는다. */
.lh-tabs button + button::before{
content:"";
position:absolute;
left:-4px;
top:22%;
bottom:22%;
width:1px;
background:var(--border-strong);
opacity:.55;
pointer-events:none;
}
.lh-tabs button.is-active::before,
.lh-tabs button.is-active + button::before{
opacity:0;
}
.lh-tabs button:hover{
color:var(--text-strong);
background:color-mix(in srgb,var(--text-strong) 5%,transparent);
}
.lh-tabs button:focus-visible{
outline:2px solid var(--focus-ring);
@ -190,11 +210,25 @@
justify-content:space-between;
gap:var(--sp-4);
}
/* 페르소나 제목이 페이지 h1(.lh-title)보다 커서 위계가 역전돼 있었다(2026-07-27).
크기는 h1 아래로 낮추고 강조는 weight 로만 준다. */
.lh-session-focus__head h2{
margin:8px 0 0;
color:var(--text-strong);
font-size:clamp(24px,2.3vw,34px);
line-height:1.12;
font-size:clamp(19px,1.7vw,24px);
font-weight:820;
line-height:1.18;
letter-spacing:0;
word-break:keep-all;
}
/* D3: 제목에서 떼어낸 주호소 조각. 크기를 낮춰 제목 한 줄에 가운뎃점이 1개만 남게 한다. */
.lh-title-tail{
display:block;
margin-top:4px;
color:var(--text-body);
font-size:.64em;
font-weight:740;
line-height:1.34;
letter-spacing:0;
word-break:keep-all;
}
@ -278,6 +312,9 @@
.lh-recap__avatar{
min-width:0;
display:grid;
/* L3: 암시적 auto 트랙이면 자식(고정 196px) max-content 트랙이 부풀어
컨테이너( 320px 에서 148px) 밖으로 나간다. 트랙을 명시해 컨테이너에 묶는다. */
grid-template-columns:minmax(0,1fr);
place-items:center;
min-height:156px;
border:1px solid var(--border-subtle);
@ -285,8 +322,24 @@
background:var(--bg-surface);
overflow:hidden;
}
/* L3(2026-07-27): ClientAvatar size prop 인라인 style(width/height:196px) 박는다.
실측 /learn 320px 에서 컨테이너 148px, 360px 에서 188px 이라
자식 figure(196px) 오른쪽으로 각각 48px / 8px 잘려 나갔다
(.lh-recap__avatar overflow:hidden 걸림).
자식 폭을 컨테이너에 맞춰 줄인다. */
.lh-recap__avatar .vg-avatar{
margin:0;
/* min-width:auto(기본) 이면 인라인 width 196px 그리드 트랙의 자동 최소값이
트랙 자체가 196px 부풀고 컨테이너(148px) 밖으로 삐져나온다. 0 으로 풀어야
아래 max-width 실제로 걸린다. */
min-width:0;
max-width:100%;
}
/* 폭만 줄이면 인라인 height(고정 196px) 때문에 원형 마스크가 타원이 되므로
높이를 폭에서 다시 계산한다. 인라인 스타일이라 !important 없이는 이긴다. */
.lh-recap__avatar .vg-avatar__stage{
height:auto !important;
aspect-ratio:1;
}
.lh-recap__body{
min-width:0;
@ -796,16 +849,27 @@
text-overflow:ellipsis;
white-space:nowrap;
}
/* D3: "코드 · 단계 · 날짜"에서 날짜를 오른쪽 컬럼으로 떼어 가운뎃점을 1개로 줄인다. */
.lh-compact-list__body small{
min-width:0;
display:flex;
align-items:baseline;
justify-content:space-between;
gap:10px;
color:var(--text-muted);
font-family:var(--font-num);
font-size:11.5px;
line-height:1.25;
}
.lh-compact-list__body small > span{
min-width:0;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
.lh-compact-list__body small > span:last-child{
flex:none;
}
.lh-compact-list__action,
.lh-compact-list__status{
min-height:28px;
@ -861,11 +925,29 @@
.lh-feedback-mini__row:hover{
color:var(--accent-deep);
}
/* D3: "코드 · 단계 · 점수"에서 점수를 오른쪽 컬럼으로 분리 */
.lh-feedback-mini__row b{
display:flex;
align-items:baseline;
justify-content:space-between;
gap:10px;
color:var(--text-strong);
font-size:13.5px;
line-height:1.35;
}
.lh-feedback-mini__row b > span:first-child{
min-width:0;
color:var(--text-strong);
font-size:inherit;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
.lh-feedback-mini__row b > span:last-child{
flex:none;
color:var(--text-body);
font-size:inherit;
}
.lh-feedback-mini__row span{
color:var(--text-body);
font-size:12.5px;
@ -990,14 +1072,49 @@
-webkit-line-clamp:2;
-webkit-box-orient:vertical;
}
/* D3: 이름줄에서 떼어낸 주호소. 이름과 다른 층으로 읽히게 색·굵기를 낮춘다. */
.lh-persona__concern{
min-width:0;
color:var(--text-body);
font-size:12.5px;
font-weight:700;
line-height:1.35;
word-break:keep-all;
overflow:hidden;
display:-webkit-box;
-webkit-line-clamp:2;
-webkit-box-orient:vertical;
}
.lh-persona__meta{
min-width:0;
display:flex;
align-items:center;
gap:6px;
color:var(--text-muted);
font-size:12px;
line-height:1.45;
}
.lh-persona__meta > span{
min-width:0;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
/* D3: "· 사용 불가"를 이어 붙이면 가운뎃점이 늘어나므로 별도 칩으로 뺀다. */
.lh-persona__flag{
flex:none;
display:inline-flex;
align-items:center;
min-height:20px;
padding:0 6px;
border:1px solid var(--border-subtle);
border-radius:var(--radius-sm);
background:var(--bg-surface);
color:var(--warn-text);
font-size:11px;
font-weight:800;
white-space:nowrap;
}
.lh-persona__summary{
min-width:0;
color:var(--text-body);
@ -1044,14 +1161,23 @@
align-content:start;
padding:var(--sp-5);
}
/* L1(2026-07-27): 이전 `grid-template-columns:minmax(0,1fr) minmax(220px,auto)`
우측 액션 열이 max-content(=.lh-actions__note max-width 280px)까지 먼저 자라고
좌측 신원 열은 최소 0 이라 남은 폭을 전부 빼앗겼다.
실측( 1181px): 프리뷰 히어로 423px 열이 "127px 280px" 잡혀 제목 열이 47px,
1280px 에서도 146px 밖에 26~28px 제목이 글자 단위로 쪼개져 흘러내렸다.
액션을 "줄바꿈되는 항목"으로 바꾼다. 신원 열이 340px 받는 폭에서는
액션이 통째로 아랫줄로 내려가고 제목 열은 히어로 폭을 쓴다. */
.lh-preview__hero{
min-width:0;
display:grid;
grid-template-columns:minmax(0,1fr) minmax(220px,auto);
display:flex;
flex-wrap:wrap;
gap:var(--sp-4);
align-items:start;
align-items:flex-start;
}
.lh-preview__identity{
/* 340px 미만이면 같은 줄에 액션을 두지 않는다(=제목 열 최소 260px 확보) */
flex:1 1 340px;
min-width:0;
display:grid;
grid-template-columns:auto minmax(0,1fr);
@ -1090,7 +1216,10 @@
line-height:1.2;
letter-spacing:0;
word-break:keep-all;
overflow-wrap:anywhere;
/* L1: `anywhere` min-content "한 글자" 만들어 부모 flex/grid 제목 열을
0 까지 줄여도 되는 것처럼 계산한다. `break-word` 줄바꿈 결과는 같지만
min-content "가장 긴 단어"라서 열이 통째로 붕괴하는 구조적으로 막는다. */
overflow-wrap:break-word;
}
.lh-preview__copy p{
margin:7px 0 0;
@ -1100,6 +1229,11 @@
word-break:keep-all;
}
.lh-actions{
/* L1: 히어로가 좁으면 늘어나지도 억지로 버티지도 말고 아랫줄로 내려간다.
아랫줄로 내려갔을 때도 margin-left:auto 카드 오른쪽에 붙여
줄일 (=넓은 ) 같은 "액션은 오른쪽" 규칙을 유지한다. */
flex:0 1 auto;
margin-left:auto;
min-width:0;
display:grid;
justify-items:end;
@ -1209,6 +1343,9 @@
display:grid;
gap:10px;
background:transparent;
/* L2: 카드가 깨지는 기준은 뷰포트가 아니라 "카드 폭"이라 컨테이너 질의를 쓴다.
같은 1181px 뷰포트에서도 목록 위치에 따라 카드 폭이 391px~794px 갈린다. */
container:lh-session-list / inline-size;
}
.lh-session-list li{
min-width:0;
@ -1221,6 +1358,26 @@
border-radius:var(--radius);
background:var(--bg-surface);
}
/* L2(2026-07-27): 3열을 끝까지 붙들면 중앙 본문이 뭉개졌다.
실측( 1181px, /learn/practice): 카드 391px 에서 열이
"140px 67.27px 131.73px" 잡혀 본문이 67px, 제목 b("서연") 24px,
"라포 단계 · 0턴 / 날짜" 4줄로 접혔다( 1280px 에서도 본문 166px).
140 + 본문 180 + 액션 132 + 24 + 패딩 26 500px 3열의 손익분기라
여유를 600px 아래에서는 액션을 아랫줄로 내리고 본문에 최소 180px 준다. */
@container lh-session-list (max-width:600px){
.lh-session-list li{
grid-template-columns:140px minmax(180px,1fr);
}
.lh-session-actions{
grid-column:1 / -1;
}
}
/* 2열(140+180+갭12+패딩26=358px)조차 못 넣는 폭에서는 완전 세로 스택 */
@container lh-session-list (max-width:380px){
.lh-session-list li{
grid-template-columns:minmax(0,1fr);
}
}
.lh-session-card:hover{
border-color:var(--border-strong);
background:color-mix(in srgb,var(--bg-surface) 78%,var(--bg-surface-2));
@ -1302,6 +1459,13 @@
font-size:12px;
line-height:1.45;
}
/* D3: "단계 · 턴 · 날짜"를 한 줄에 붙이면 가운뎃점이 2개다. 날짜를 컬럼으로 분리. */
.lh-session-card__body p{
display:flex;
flex-wrap:wrap;
align-items:baseline;
gap:2px 14px;
}
.lh-session-card__progress{
width:100%;
height:5px;
@ -1433,13 +1597,25 @@
line-height:1.35;
}
.lh-persona-progress__title em,
.lh-persona-progress__meta,
.lh-persona-progress__latest{
min-width:0;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
/* D3: "N회 · N회 진행 · N회 리뷰 · 평균 N턴" 가운뎃점이 3개였다.
줄로 확정 분리해 줄마다 가운뎃점이 1개만 남게 한다. */
.lh-persona-progress__meta{
min-width:0;
display:grid;
gap:2px;
}
.lh-persona-progress__meta > span{
min-width:0;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
.lh-persona-progress__title em{
font-style:normal;
font-weight:720;
@ -1585,10 +1761,11 @@
.lh-history-filter{
justify-content:flex-start;
}
.lh-preview__hero{
grid-template-columns:1fr;
}
/* L1: 히어로가 flex-wrap 바뀌어 grid-template-columns 이상 쓰이지 않는다.
구간은 폭과 무관하게 항상 액션을 아랫줄에 두던 기존 동작을 유지한다. */
.lh-actions{
flex-basis:100%;
margin-left:0;
justify-items:start;
}
.lh-actions__note{
@ -2205,8 +2382,11 @@
position: relative;
z-index: 1;
}
/* 위계 복구(2026-07-27): 이전 clamp(30px,3vw,38px) h1(clamp(29px,2.7vw,36px))보다
커서 페르소나 이름이 페이지 제목을 눌렀다. h1 아래 단계로 내린다. */
.vg-shell--learner-dashboard .lh-session-focus__head h2 {
font-size: clamp(30px, 3vw, 38px);
font-size: clamp(21px, 1.95vw, 28px);
font-weight: 820;
}
.vg-shell--learner-dashboard .lh-recap {
grid-template-columns: 224px minmax(0, 1fr);