diff --git a/docs/90_current_state.md b/docs/90_current_state.md index b2bb5fe..85b0ab0 100644 --- a/docs/90_current_state.md +++ b/docs/90_current_state.md @@ -14,6 +14,10 @@ Last Updated: 2026-03-16 - atmosphere는 `scene + sound`가 함께 묶인 선택 단위로 동작하며, 선택한 atmosphere가 `/app` 배경과 `/space` start payload에 같이 반영된다 - custom duration server contract 전까지는 입력한 분 값을 가장 가까운 기본 리듬(`25/5`, `50/10`, `90/20`)으로 매핑한다 - weekly review entry는 main CTA를 먹지 않도록 no-session shell의 quiet secondary dock 위치로 이동했다 +- `/app` Atmosphere Entry Shell visual premium polish: + - no-session shell을 `decision rail + selected atmosphere stage + curated atmosphere library` 구조로 다시 짰다 + - 좌측은 입력과 시작 결정을 담당하고, 우측은 선택한 atmosphere의 immersive preview를 크게 보여준다 + - review entry는 start stage 아래 quiet dock로 내려 main CTA와 경쟁하지 않게 정리했다 - current session direct start 차단: - silent abandon을 막기 위해 server `startSession()`은 current session 존재 시 direct start를 거절한다 diff --git a/docs/screens/app/current/19_app_atmosphere_entry_spec.md b/docs/screens/app/current/19_app_atmosphere_entry_spec.md index ceb62c6..2333405 100644 --- a/docs/screens/app/current/19_app_atmosphere_entry_spec.md +++ b/docs/screens/app/current/19_app_atmosphere_entry_spec.md @@ -7,6 +7,7 @@ Last Updated: 2026-03-16 현재 상태: - `Slice 1` no-session shell 구현 완료 +- `Slice 1-2` visual premium polish 구현 완료 - `Custom Duration Contract`와 `Weekly Review Dock Reposition`은 다음 slice로 남아 있음 핵심 정책 변경: @@ -151,6 +152,8 @@ Last Updated: 2026-03-16 - goal input - duration input - start CTA +- editorial copy block +- selected atmosphere large preview stage ### Layer 3. Atmosphere Grid @@ -161,6 +164,21 @@ Last Updated: 2026-03-16 핵심은 **review / archive / history가 main stage를 먹지 않고, atmosphere grid도 secondary decoration이 아니라 실제 선택 surface로 작동해야 한다**는 점이다. +### 현재 visual shell 원칙 + +- left: decision rail + - 큰 제목 + - goal / duration input + - selected atmosphere summary + - primary CTA + - quiet review dock +- right: selected atmosphere stage + - immersive preview + - sound / scene / best-for meta +- bottom: curated atmosphere library + - 4열 grid + - selected state가 즉시 읽혀야 함 + --- ## 6. 화면 구성 diff --git a/docs/session_brief.md b/docs/session_brief.md index 86b442c..ab3e7ac 100644 --- a/docs/session_brief.md +++ b/docs/session_brief.md @@ -32,6 +32,10 @@ Last Updated: 2026-03-16 - 선택한 atmosphere는 `/app` 배경 preview와 `/space` start payload의 `scene/sound`에 같이 반영된다. - duration은 우선 가장 가까운 기본 리듬으로 매핑하는 임시 계약을 사용한다. - weekly review entry는 right-side quiet dock 위치로 옮겨 main CTA보다 낮은 위계를 유지한다. +- `/app` Atmosphere Entry Shell visual premium polish를 반영했다. + - utility card 묶음 대신 `decision rail + selected atmosphere stage + curated library` 구조로 재구성했다. + - 좌측은 입력과 결심, 우측은 immersive preview, 하단은 12개 atmosphere library로 위계를 고정했다. + - review entry는 start stage 아래의 quiet dock로 낮춰 main CTA와 경쟁하지 않게 정리했다. - `/app`은 이제 session gate를 보여주지 않는다. - current session이 있으면 상태와 상관없이 즉시 `/space`로 이동한다. - 따라서 paused resume gate와 takeover sheet는 current UX가 아니다. diff --git a/docs/work.md b/docs/work.md index 1ba9419..f87bf58 100644 --- a/docs/work.md +++ b/docs/work.md @@ -38,7 +38,7 @@ - goal + duration + selected atmosphere가 start surface 안에서 명확히 읽힌다 - 12개 dummy atmosphere가 4열 그리드로 배치된다 - 진행 상태: - - 구현 완료, browser QA 대기 + - 구현 완료, visual premium polish 반영, browser QA 대기 - 검증: - `/app` no-session browser QA - 커밋 힌트: diff --git a/src/widgets/focus-dashboard/ui/AppAtmosphereEntryShell.tsx b/src/widgets/focus-dashboard/ui/AppAtmosphereEntryShell.tsx index 447f24d..38f017c 100644 --- a/src/widgets/focus-dashboard/ui/AppAtmosphereEntryShell.tsx +++ b/src/widgets/focus-dashboard/ui/AppAtmosphereEntryShell.tsx @@ -5,12 +5,14 @@ import { getSceneCardPhotoUrl } from '@/entities/scene'; import { cn } from '@/shared/lib/cn'; import type { AtmosphereOption } from '../model/atmosphereEntry'; -const shellCardClass = - 'rounded-[2rem] border border-white/12 bg-[#0f1115]/26 shadow-[0_24px_60px_rgba(3,7,18,0.32)] backdrop-blur-xl'; -const inputShellClass = - 'w-full rounded-[1.5rem] border border-white/14 bg-white/[0.06] px-5 py-4 text-white outline-none transition focus:border-white/24 focus:bg-white/[0.09]'; +const stageShellClass = + 'relative overflow-hidden rounded-[2.35rem] border border-white/12 bg-[linear-gradient(160deg,rgba(9,13,20,0.54)_0%,rgba(9,13,20,0.2)_52%,rgba(9,13,20,0.48)_100%)] shadow-[0_26px_90px_rgba(3,7,18,0.34)] backdrop-blur-[26px]'; +const fieldShellClass = + 'w-full rounded-[1.45rem] border border-white/12 bg-[linear-gradient(180deg,rgba(255,255,255,0.09)_0%,rgba(255,255,255,0.05)_100%)] px-5 py-4 text-white outline-none transition focus:border-white/24 focus:bg-white/[0.1]'; +const reviewDockClass = + 'group relative overflow-hidden rounded-[1.65rem] border border-white/12 bg-[linear-gradient(145deg,rgba(255,255,255,0.09)_0%,rgba(255,255,255,0.04)_100%)] px-5 py-4 backdrop-blur-xl transition hover:border-white/18 hover:bg-white/[0.1]'; const primaryButtonClass = - 'inline-flex items-center justify-center rounded-full border border-white/16 bg-white/[0.14] px-6 py-3 text-sm font-medium text-white transition hover:bg-white/[0.18] active:scale-[0.99] disabled:cursor-not-allowed disabled:opacity-48'; + 'inline-flex min-h-[3.65rem] items-center justify-center rounded-full border border-white/14 bg-white/[0.16] px-6 text-[15px] font-medium tracking-[-0.01em] text-white shadow-[0_10px_22px_rgba(5,10,20,0.24)] transition hover:bg-white/[0.2] active:scale-[0.99] disabled:cursor-not-allowed disabled:opacity-50'; interface AppAtmosphereEntryShellProps { canStart: boolean; @@ -64,167 +66,246 @@ export const AppAtmosphereEntryShell = ({ onStartSession, }: AppAtmosphereEntryShellProps) => { return ( -
- 목표는 한 줄이면 충분해요. 얼마나 붙잡을지와 어떤 분위기로 들어갈지만 정하면 바로 - 집중 화면으로 이어집니다. -
-+ Focus Entry +
++ 목표는 한 줄이면 충분합니다. 걸릴 시간을 적고, 오늘의 atmosphere 하나만 고르면 + 바로 공간 안으로 들어갈 수 있어요. +
++ 선택한 Atmosphere +
++ {selectedAtmosphere.name} +
+
+ {selectedAtmosphere.soundLabel}
+
+ {selectedAtmosphere.caption}
+
{durationHelper}
+- Selected Atmosphere -
-{selectedAtmosphere.name}
-- {selectedAtmosphere.soundLabel} · {selectedAtmosphere.caption} -
++ 빠른 선택 +
+{sessionLookupError}
- ) : null} ++ 현재 선택 +
++ {selectedAtmosphere.description} +
+{sessionLookupError}
+ ) : null} +